Pixel-Composer/scripts/pack_best_fit/pack_best_fit.gml

60 lines
1.8 KiB
Text
Raw Normal View History

2023-03-19 09:17:39 +01:00
function sprite_pack_best_fit(rectangles) {
2024-04-30 10:49:12 +02:00
var area = new Rectangle(0, 0, 0, 0);
if(array_length(rectangles) <= 1) return [ area, rectangles ];
2023-03-19 09:17:39 +01:00
2024-04-30 10:49:12 +02:00
array_sort(rectangles, function(rect1, rect2) { return rect2.w * rect2.h - rect1.w * rect1.h; });
var grW = rectangles[0].w;
var grH = rectangles[0].h;
2023-03-19 09:17:39 +01:00
var _or, _nr;
2024-04-30 10:49:12 +02:00
for (var i = 1; i < array_length(rectangles); i++) {
2023-03-19 09:17:39 +01:00
_nr = rectangles[i];
2024-04-30 10:49:12 +02:00
grW = gcd(_nr.w, grW);
grH = gcd(_nr.h, grH);
2023-03-19 09:17:39 +01:00
}
for (var i = 0; i < array_length(rectangles); i++) {
var rect = rectangles[i];
var bestSpace = noone;
2024-04-30 10:49:12 +02:00
var bestArea = new Rectangle(0, 0, 0, 0);
2024-03-14 14:35:19 +01:00
for (var xx = area.x; xx <= area.x + area.w; xx += grW)
for (var yy = area.y; yy <= area.y + area.h; yy += grH) {
var space = new Rectangle(xx, yy, rect.w, rect.h);
if (space.x + space.w > area.x + area.w || space.y + space.h > area.y + area.h)
continue;
2023-03-19 09:17:39 +01:00
2024-03-14 14:35:19 +01:00
var overlaps = false;
for (var j = 0; j < i; j++) {
var otherRect = rectangles[j];
if (rectangleOverlap(space, otherRect)) {
overlaps = true;
break;
2023-03-19 09:17:39 +01:00
}
2024-03-14 14:35:19 +01:00
}
2023-03-19 09:17:39 +01:00
2024-03-14 14:35:19 +01:00
if (!overlaps && (bestSpace == noone || space.w * space.h < bestSpace.w * bestSpace.h)) {
bestSpace = space;
bestArea = new Rectangle(area.x, area.y, area.w, area.h);
2023-03-19 09:17:39 +01:00
}
}
if (bestSpace == noone) {
area.w = max(area.w, rect.w);
area.h += rect.h;
rectangles[i].x = area.x;
rectangles[i].y = area.y + area.h - rect.h;
} else {
rectangles[i].x = bestSpace.x;
rectangles[i].y = bestSpace.y;
area = bestArea;
}
}
return [ area, rectangles ];
}