diff --git a/editor/extensions/src/apply-wheelsprung-fixes.ts b/editor/extensions/src/apply-wheelsprung-fixes.ts
index 8e9c6c7c..4706c432 100644
--- a/editor/extensions/src/apply-wheelsprung-fixes.ts
+++ b/editor/extensions/src/apply-wheelsprung-fixes.ts
@@ -1,6 +1,9 @@
///
import { ensureWindingOrder } from "./ensure-winding-order";
+import { polylineToPolygon } from "./outline-polyline";
+import { newPolygon } from "./new-polygon";
+
export function applyWheelsprungFixes(mapOrLayer) {
tiled.log("Running applyWheelsprungFixes:" + mapOrLayer);
@@ -23,6 +26,16 @@ export function applyWheelsprungFixes(mapOrLayer) {
);
object.polygon = ensureWindingOrder(object.polygon);
}
+
+ if (object.shape == MapObject.Polyline && object.selected) {
+ var polygon = polylineToPolygon(object.polygon, 4.0);
+ var newObject = newPolygon(object);
+ tiled.log("New object:" + newObject);
+ tiled.log("new polygon:" + polygon);
+ newObject.polygon = polygon;
+ mapOrLayer.addObject(newObject);
+ };
+
if(object.shape == MapObject.Ellipse && object.className == "DynamicObject") {
if(object.width != object.height) {
tiled.log("Ellipses not supported for Dynamic Objects. Making circular:" + object);
diff --git a/editor/extensions/src/new-polygon.ts b/editor/extensions/src/new-polygon.ts
new file mode 100644
index 00000000..f0b496f6
--- /dev/null
+++ b/editor/extensions/src/new-polygon.ts
@@ -0,0 +1,9 @@
+export function newPolygon(oldObj) {
+ var object = new MapObject();
+ object.x = oldObj.x;
+ object.y = oldObj.y;
+ object.width = oldObj.width;
+ object.height = oldObj.height;
+ object.shape = MapObject.Polygon;
+ return object;
+}
diff --git a/editor/extensions/src/outline-polyline.ts b/editor/extensions/src/outline-polyline.ts
new file mode 100644
index 00000000..8acc47e1
--- /dev/null
+++ b/editor/extensions/src/outline-polyline.ts
@@ -0,0 +1,138 @@
+function getOffsets(a, b, thickness) {
+ var
+ dx = b.x - a.x,
+ dy = b.y - a.y,
+ len = Math.sqrt(dx * dx + dy * dy),
+ scale = thickness / (2 * len)
+ ;
+ return {
+ x: -scale * dy,
+ y: scale * dx
+ };
+}
+
+function getIntersection(a1, b1, a2, b2) {
+
+ // directional constants
+ var
+ k1 = (b1.y - a1.y) / (b1.x - a1.x),
+ k2 = (b2.y - a2.y) / (b2.x - a2.x);
+
+
+
+ // if the directional constants are equal, the lines are parallel
+ if (Math.abs(k1 - k2)<0.00001) {
+ return;
+ }
+
+ // y offset constants for both lines
+ var m1 = a1.y - k1 * a1.x;
+ var m2 = a2.y - k2 * a2.x;
+
+ // compute x
+ var x = (m1 - m2) / (k2 - k1);
+
+ // use y = k * x + m to get y coordinate
+ var y = k1 * x + m1;
+
+ return { x:x, y:y };
+}
+
+function isArray(obj){
+ return (Object.prototype.toString.call(obj)==='[object Array]');
+}
+
+function me(points, thickness) {
+
+
+ //Convert points into json notation
+ var arr = [];
+ for (var i=0; i [pt.x, pt.y]);
+ tiled.log("Running me:" + points);
+ var vertices = me(points, thickness);
+ return vertices.map((pt) => Qt.point(pt[0], pt[1]));
+}
\ No newline at end of file
diff --git a/editor/extensions/wheelsprung/index.js b/editor/extensions/wheelsprung/index.js
index 429e740d..74bdc1cf 100644
--- a/editor/extensions/wheelsprung/index.js
+++ b/editor/extensions/wheelsprung/index.js
@@ -19,6 +19,103 @@
return vertices;
}
+ // src/outline-polyline.ts
+ function getOffsets(a, b, thickness) {
+ var dx = b.x - a.x, dy = b.y - a.y, len = Math.sqrt(dx * dx + dy * dy), scale = thickness / (2 * len);
+ return {
+ x: -scale * dy,
+ y: scale * dx
+ };
+ }
+ function getIntersection(a1, b1, a2, b2) {
+ var k1 = (b1.y - a1.y) / (b1.x - a1.x), k2 = (b2.y - a2.y) / (b2.x - a2.x);
+ if (Math.abs(k1 - k2) < 1e-5) {
+ return;
+ }
+ var m1 = a1.y - k1 * a1.x;
+ var m2 = a2.y - k2 * a2.x;
+ var x = (m1 - m2) / (k2 - k1);
+ var y = k1 * x + m1;
+ return { x, y };
+ }
+ function isArray(obj) {
+ return Object.prototype.toString.call(obj) === "[object Array]";
+ }
+ function me(points, thickness) {
+ var arr = [];
+ for (var i2 = 0; i2 < points.length; i2++) {
+ var pt = points[i2];
+ arr.push({
+ x: pt[0],
+ y: pt[1]
+ });
+ }
+ points = arr;
+ if (!isArray(thickness)) {
+ var t2 = thickness;
+ thickness = [];
+ for (var i2 = 0; i2 < points.length; i2++) {
+ thickness.push(t2);
+ }
+ }
+ var off, off2, poly = [], isFirst, isLast, prevA, prevB, interA, interB, p0a, p1a, p0b, p1b;
+ for (var i2 = 0, il = points.length - 1; i2 < il; i2++) {
+ isFirst = !i2;
+ isLast = i2 === points.length - 2;
+ off = getOffsets(points[i2], points[i2 + 1], thickness[i2]);
+ off2 = getOffsets(points[i2], points[i2 + 1], thickness[i2 + 1]);
+ p0a = { x: points[i2].x + off.x, y: points[i2].y + off.y };
+ p1a = { x: points[i2 + 1].x + off2.x, y: points[i2 + 1].y + off2.y };
+ p0b = { x: points[i2].x - off.x, y: points[i2].y - off.y };
+ p1b = { x: points[i2 + 1].x - off2.x, y: points[i2 + 1].y - off2.y };
+ if (!isFirst) {
+ interA = getIntersection(prevA[0], prevA[1], p0a, p1a);
+ if (interA) {
+ poly.unshift(interA);
+ }
+ interB = getIntersection(prevB[0], prevB[1], p0b, p1b);
+ if (interB) {
+ poly.push(interB);
+ }
+ }
+ if (isFirst) {
+ poly.unshift(p0a);
+ poly.push(p0b);
+ }
+ if (isLast) {
+ poly.unshift(p1a);
+ poly.push(p1b);
+ }
+ if (!isLast) {
+ prevA = [p0a, p1a];
+ prevB = [p0b, p1b];
+ }
+ }
+ for (var i2 = 0; i2 < poly.length; i2++) {
+ var pt = poly[i2];
+ poly[i2] = [pt.x, pt.y];
+ }
+ poly.push(poly[0]);
+ return poly;
+ }
+ function polylineToPolygon(polygon, thickness) {
+ var points = polygon.map((pt) => [pt.x, pt.y]);
+ tiled.log("Running me:" + points);
+ var vertices = me(points, thickness);
+ return vertices.map((pt) => Qt.point(pt[0], pt[1]));
+ }
+
+ // src/new-polygon.ts
+ function newPolygon(oldObj) {
+ var object = new MapObject();
+ object.x = oldObj.x;
+ object.y = oldObj.y;
+ object.width = oldObj.width;
+ object.height = oldObj.height;
+ object.shape = MapObject.Polygon;
+ return object;
+ }
+
// src/apply-wheelsprung-fixes.ts
function applyWheelsprungFixes(mapOrLayer) {
tiled.log("Running applyWheelsprungFixes:" + mapOrLayer);
@@ -42,6 +139,15 @@
);
object.polygon = ensureWindingOrder(object.polygon);
}
+ if (object.shape == MapObject.Polyline && object.selected) {
+ var polygon = polylineToPolygon(object.polygon, 4);
+ var newObject = newPolygon(object);
+ tiled.log("New object:" + newObject);
+ tiled.log("new polygon:" + polygon);
+ newObject.polygon = polygon;
+ mapOrLayer.addObject(newObject);
+ }
+ ;
if (object.shape == MapObject.Ellipse && object.className == "DynamicObject") {
if (object.width != object.height) {
tiled.log("Ellipses not supported for Dynamic Objects. Making circular:" + object);
diff --git a/src/level_meta/level_data.nim b/src/level_meta/level_data.nim
index a3f38786..fec219f3 100644
--- a/src/level_meta/level_data.nim
+++ b/src/level_meta/level_data.nim
@@ -48,7 +48,7 @@ let officialLevels*: OrderedTable[Path, LevelMeta] = @[
newLevelMeta(name= "Novel Navigations", path="levels/novel_navigations.flatty", theme= Bookshelf, hash="83D025E12A1140BC3B86831F20FF4622"),
newLevelMeta(name= "Shelf Swinger", path="levels/shelf_swinger.flatty", theme= Bookshelf, hash="E91EE82424E715F5C6F9A439F1096F1B"),
newLevelMeta(name= "Under Covers", path="levels/under_covers.flatty", theme= Bookshelf, hash="07C4F9B28FA27A1EDB706A9432544979"),
- newLevelMeta(name= "Rollercoaster", path="levels/rollercoaster.flatty", theme= Bookshelf, hash="92330B17118385D29D0549DB1A823312"),
+ newLevelMeta(name= "Rollercoaster", path="levels/rollercoaster.flatty", theme= Bookshelf, hash="EB073CA2B150DF7EF20C31E8ECB01F86"),
newLevelMeta(name= "Hooked", path="levels/hooked.flatty", theme= Bookshelf, hash="C83A58916A6F97F1AA0A2952E12BFABA"),
newLevelMeta(name= "Dominoes", path="levels/dominoes.flatty", theme= Bookshelf, hash="19A67112C03DA92C9D51FB268956F93C"),
newLevelMeta(name= "Backflip", path="levels/backflip.flatty", theme= Bookshelf, hash="513A5202C29C322690EE9B33068D6789"),
@@ -64,11 +64,11 @@ let officialLevels*: OrderedTable[Path, LevelMeta] = @[
newLevelMeta(name= "Treasure Tunnel", path="levels/treasure_tunnel.flatty", theme= Plants, hash="6E5F2C44C7ED48F25ED86E834C68149B"),
newLevelMeta(name= "Half-Pipe Jungle", path="levels/halfpipe.flatty", theme= Plants, hash="31609EFBA4AB9DEFD10A4BF90CB5300D"),
newLevelMeta(name= "Rickety Bridge", path="levels/rickety_bridge.flatty", theme= Plants, hash="0CF980DB09C2EE873C16836319B51CBD"),
- newLevelMeta(name = "Rolling Raiders", path="levels/boulder.flatty", theme= Plants, hash="0541EF41C104AE11FFCE43B3B3077A85"),
+ newLevelMeta(name = "Rolling Raiders", path="levels/boulder.flatty", theme= Plants, hash="7A93A4DD90103EF4363EB503BFAF0642"),
newLevelMeta(name= "Zig Zag Down", path="levels/zig_zag_down.flatty", theme= Desk, hash="633154C6A64C4C0EB4FCC1FE1F0490B0"),
newLevelMeta(name = "Time Traveler", path="levels/time_traveler.flatty", theme= Desk, hash="18193FB4744661DA83906690CE211469"),
- newLevelMeta(name = "Tight Squeeze", path="levels/tight_squeeze.flatty", theme= Desk, hash="0541EF41C104AE11FFCE43B3B3077A85"),
+ newLevelMeta(name = "Tight Squeeze", path="levels/tight_squeeze.flatty", theme= Desk, hash="7A93A4DD90103EF4363EB503BFAF0642"),
newLevelMeta(name= "Ballistic Bowler", path="levels/ballistic_bowler.flatty", theme= Desk, hash="E7ED841B154ADD2B5694AD6613CCE5D1"),
newLevelMeta(name= "Ramp of Pages", path="levels/leg_up.flatty", theme= Desk, hash="6F48907EB90D6985CB66486C4A11FFEC"),
newLevelMeta(name= "Ballancing Act", path="levels/ballancing_act.flatty", theme= Desk, hash="15B0EC58F7BB8A9912DB470DE0CCA81F"),
diff --git a/support/levels b/support/levels
index 79b320f2..2d0238a4 160000
--- a/support/levels
+++ b/support/levels
@@ -1 +1 @@
-Subproject commit 79b320f2083502ea35b8e91d0ce0cf915f6648d2
+Subproject commit 2d0238a400060d3994de3daa9cca7dfd0aecac62