diff --git a/scripts/api/entity/zone.lua b/scripts/api/entity/zone.lua index 5291213b1a..3fc9f2231f 100644 --- a/scripts/api/entity/zone.lua +++ b/scripts/api/entity/zone.lua @@ -19,15 +19,30 @@ end local Entity = getLuaEntityFunctionTable() --- Sets the corners of this Zone n-gon to x_1, y_1, x_2, y_2, ... x_n, y_n. --- Positive x coordinates are right/"east" of the origin, and positive y coordinates are down/"south" of the origin in space. +--- This also moves the Zone's Transform coordinates to the new centroid via setPosition(). --- Example: zone:setPoints(2000,0, 0,3000, -2000,0) -- defines a triangular zone function Entity:setPoints(...) if self.components.zone then local coords = {...} local points = {} - for n=1,#coords,2 do - table.insert(points, {coords[n], coords[n+1]}) + local sum_x, sum_y, count = 0, 0, 0 + for n = 1, #coords, 2 do + local x, y = coords[n], coords[n+1] + table.insert(points, {x, y}) + sum_x = sum_x + x + sum_y = sum_y + y + count = count + 1 + end + if count > 0 then + local center_x = sum_x / count + local center_y = sum_y / count + self:setPosition(center_x, center_y) + local relative_points = {} + for _, pt in ipairs(points) do + table.insert(relative_points, {pt[1] - center_x, pt[2] - center_y}) + end + self.components.zone.points = relative_points end - self.components.zone.points = points end return self end diff --git a/scripts/api/gm.lua b/scripts/api/gm.lua index ceaa9017e8..45e22e3122 100644 --- a/scripts/api/gm.lua +++ b/scripts/api/gm.lua @@ -586,12 +586,17 @@ function __exportZone(entity) extras = extras .. ":setLocalSkybox('" .. z.skybox .. "')" end end - -- Outline points: z.points is {{x1,y1},{x2,y2},...}; setPoints takes a flat coord list + -- Outline points: z.points is {{x1,y1},{x2,y2},...} (relative to center); setPoints takes absolute coords if z.points and #z.points > 0 then local coords = {} + local tx, ty = 0, 0 + if entity.components.transform and entity.components.transform.position then + tx = entity.components.transform.position[1] or 0 + ty = entity.components.transform.position[2] or 0 + end for _, pt in ipairs(z.points) do - coords[#coords+1] = string.format("%.0f", pt[1]) - coords[#coords+1] = string.format("%.0f", pt[2]) + coords[#coords+1] = string.format("%.0f", pt[1] + tx) + coords[#coords+1] = string.format("%.0f", pt[2] + ty) end extras = extras .. ":setPoints(" .. table.concat(coords, ", ") .. ")" end diff --git a/src/components/zone.cpp b/src/components/zone.cpp index 2430d2a019..ee6cbbb500 100644 --- a/src/components/zone.cpp +++ b/src/components/zone.cpp @@ -5,19 +5,23 @@ void Zone::updateTriangles() { - if (outline.empty()) { - radius = 1; - triangles.clear(); - return; - } + // Re-initalize the zone radius cache and shape. + radius = 1.0f; + triangles.clear(); + + // If there aren't any points, clear the shape. + if (outline.empty()) return; + // Place the label at the center of the outline. label_offset = centerOfMass(outline); - radius = 1; - for(auto p : outline) { + + // Populate the shape and recalculate radius from outline points. + for (auto p : outline) + { p -= label_offset; radius = std::max(radius, glm::length(p)); } - - triangles.clear(); + + // Re-triangulate the shape. Triangulate::process(outline, triangles); -} \ No newline at end of file +}