diff --git a/app/assets/tpl/editEntityDefs.html b/app/assets/tpl/editEntityDefs.html
index b21d42435..2239b3e62 100644
--- a/app/assets/tpl/editEntityDefs.html
+++ b/app/assets/tpl/editEntityDefs.html
@@ -89,6 +89,18 @@
Project entities
Keep aspect ratio
+
+ Flippable:
+
+
+
+
diff --git a/app/assets/tpl/entityInstanceEditor.html b/app/assets/tpl/entityInstanceEditor.html
index 8d73f2c88..a4ce00fec 100644
--- a/app/assets/tpl/entityInstanceEditor.html
+++ b/app/assets/tpl/entityInstanceEditor.html
@@ -27,6 +27,22 @@
+
+ Flips
+ How this Entity instance is oriented on the X and Y axes.
+
+
+
+
+
+
+
References to this entity
This is a list of all other Entities having a Reference field pointing to this Entity.
@@ -42,4 +58,4 @@
-
\ No newline at end of file
+
diff --git a/src/electron.renderer/data/def/EntityDef.hx b/src/electron.renderer/data/def/EntityDef.hx
index 6cd591693..e146f5ec3 100644
--- a/src/electron.renderer/data/def/EntityDef.hx
+++ b/src/electron.renderer/data/def/EntityDef.hx
@@ -31,6 +31,8 @@ class EntityDef {
public var resizableX : Bool;
public var resizableY : Bool;
+ public var flippableX : Bool;
+ public var flippableY : Bool;
public var keepAspectRatio : Bool;
public var pivotX(default,set) : Float;
public var pivotY(default,set) : Float;
@@ -60,6 +62,7 @@ class EntityDef {
identifier = "Entity"+uid;
setPivot(0.5,1);
resizableX = resizableY = false;
+ flippableX = flippableY = false;
keepAspectRatio = false;
hollow = false;
tags = new Tags();
@@ -143,6 +146,8 @@ class EntityDef {
o.height = JsonTools.readInt( json.height, 16 );
o.resizableX = JsonTools.readBool( json.resizableX, false );
o.resizableY = JsonTools.readBool( json.resizableY, false );
+ o.flippableX = JsonTools.readBool( json.flippableX, false );
+ o.flippableY = JsonTools.readBool( json.flippableY, false );
o.keepAspectRatio = JsonTools.readBool( json.keepAspectRatio, false );
o.doc = JsonTools.unescapeString( json.doc );
@@ -196,6 +201,8 @@ class EntityDef {
height: height,
resizableX: resizableX,
resizableY: resizableY,
+ flippableX: flippableX,
+ flippableY: flippableY,
keepAspectRatio: keepAspectRatio,
tileOpacity: JsonTools.writeFloat(tileOpacity),
fillOpacity: JsonTools.writeFloat(fillOpacity),
@@ -313,4 +320,4 @@ class EntityDef {
for(fd in fieldDefs)
fd.tidy(p);
}
-}
\ No newline at end of file
+}
diff --git a/src/electron.renderer/data/inst/EntityInstance.hx b/src/electron.renderer/data/inst/EntityInstance.hx
index a36dbef75..d45003f1a 100644
--- a/src/electron.renderer/data/inst/EntityInstance.hx
+++ b/src/electron.renderer/data/inst/EntityInstance.hx
@@ -15,6 +15,7 @@ class EntityInstance {
public var worldY(get,never) : Int;
public var customWidth : Null;
public var customHeight: Null;
+ public var flips : Int;
public var width(get,never) : Int;
inline function get_width() return customWidth!=null ? customWidth : def.width;
@@ -30,11 +31,12 @@ class EntityInstance {
public var bottom(get,never) : Int; inline function get_bottom() return top + height;
- public function new(p:Project, li:LayerInstance, entityDefUid:Int, iid:String) {
+ public function new(p:Project, li:LayerInstance, entityDefUid:Int, iid:String, flips:Int = 0) {
_project = p;
_li = li;
defUid = entityDefUid;
this.iid = iid;
+ this.flips = flips;
}
@:keep public function toString() {
@@ -68,6 +70,7 @@ class EntityInstance {
height: height,
defUid: defUid,
px: [x,y],
+ f: flips,
fieldInstances: {
var all = [];
for(fd in def.fieldDefs)
@@ -88,6 +91,7 @@ class EntityInstance {
layer: _li.def.identifier,
x : x,
y : y,
+ f: flips,
width: width,
height: height,
color: getSmartColor(false),
@@ -109,6 +113,8 @@ class EntityInstance {
ei.x = JsonTools.readInt( json.px[0], 0 );
ei.y = JsonTools.readInt( json.px[1], 0 );
+ ei.flips = JsonTools.readInt( json.f, 0 );
+
ei.customWidth = JsonTools.readNullableInt( json.width );
if( ei.customWidth==ei.def.width )
ei.customWidth = null;
@@ -363,4 +369,4 @@ class EntityInstance {
}
-}
\ No newline at end of file
+}
diff --git a/src/electron.renderer/display/EntityRender.hx b/src/electron.renderer/display/EntityRender.hx
index abf7fa3a8..027e4de9f 100644
--- a/src/electron.renderer/display/EntityRender.hx
+++ b/src/electron.renderer/display/EntityRender.hx
@@ -95,6 +95,8 @@ class EntityRender extends dn.Process {
if( ed==null )
ed = ei.def;
+ var flipX = (ei!=null && M.hasBit(ei.flips,0));
+ var flipY = (ei!=null && M.hasBit(ei.flips,1));
var w = ei!=null ? ei.width : ed.width;
var h = ei!=null ? ei.height : ed.height;
@@ -129,6 +131,8 @@ class EntityRender extends dn.Process {
// Texture
var td = Editor.ME.project.defs.getTilesetDef(rect.tilesetUid);
var t = td.getTileRect(rect);
+ t.xFlip = flipX;
+ t.yFlip = flipY;
var alpha = ed.tileOpacity;
switch mode {
case Stretch:
@@ -152,7 +156,11 @@ class EntityRender extends dn.Process {
bmp.setScale(s);
case Repeat:
+ // Invert flips to prevent broken rendering.
+ t.xFlip = false;
+ t.yFlip = false;
var tt = new dn.heaps.TiledTexture(t, w,h, wrapper);
+
tt.alpha = alpha;
tt.x = -w*ed.pivotX + (ld==null ? 0 : ld.pxOffsetX);
tt.y = -h*ed.pivotY + (ld==null ? 0 : ld.pxOffsetY);
@@ -171,6 +179,8 @@ class EntityRender extends dn.Process {
t.height*ed.pivotY - fh*ed.pivotY,
fw,fh
);
+ bmp.tile.xFlip = t.xFlip;
+ bmp.tile.yFlip = t.yFlip;
bmp.tile.setCenterRatio(ed.pivotX, ed.pivotY);
bmp.setScale(s);
@@ -185,6 +195,8 @@ class EntityRender extends dn.Process {
t.height*ed.pivotY - fh*ed.pivotY,
fw, fh
);
+ bmp.tile.xFlip = t.xFlip;
+ bmp.tile.yFlip = t.yFlip;
bmp.tile.setCenterRatio(ed.pivotX, ed.pivotY);
bmp.alpha = alpha;
@@ -209,7 +221,6 @@ class EntityRender extends dn.Process {
sg.height = h;
sg.x = -w*ed.pivotX + (ld==null ? 0 : ld.pxOffsetX);
sg.y = -h*ed.pivotY + (ld==null ? 0 : ld.pxOffsetY);
-
}
}
}
@@ -401,4 +412,4 @@ class EntityRender extends dn.Process {
}
}
-}
\ No newline at end of file
+}
diff --git a/src/electron.renderer/tool/lt/EntityTool.hx b/src/electron.renderer/tool/lt/EntityTool.hx
index cf6099800..20d9a49c8 100644
--- a/src/electron.renderer/tool/lt/EntityTool.hx
+++ b/src/electron.renderer/tool/lt/EntityTool.hx
@@ -4,6 +4,9 @@ class EntityTool extends tool.LayerTool {
public var curEntityDef(get,never) : Null;
static var PREV_CHAINABLE_EI: Null;
+ public var flipX = false;
+ public var flipY = false;
+
public function new() {
super();
@@ -41,7 +44,14 @@ class EntityTool extends tool.LayerTool {
inline function get_curEntityDef() return project.defs.getEntityDef( getSelectedValue() );
override function selectValue(v:Int) {
+ var lastEntityDef = curEntityDef;
super.selectValue(v);
+
+ // Clear flip values ONLY if we have changed entity defs.
+ if ( lastEntityDef!=curEntityDef ) {
+ flipX = false;
+ flipY = false;
+ }
}
override function canEdit():Bool {
@@ -113,7 +123,9 @@ class EntityTool extends tool.LayerTool {
// editor.cursor.overrideNativeCursor("grab");
case _:
- editor.cursor.set( Entity(curLayerInstance, curEntityDef, getPlacementX(m), getPlacementY(m), false) );
+ // Create dummy EntityInstance so that we can draw it with transforms for flips.
+ var dummyEi = new data.inst.EntityInstance(project, null, curEntityDef.uid, "", M.makeBitsFromBools(flipX, flipY));
+ editor.cursor.set( Entity(curLayerInstance, curEntityDef, dummyEi, getPlacementX(m), getPlacementY(m), false) );
}
ev.cancel = true;
updateChainRefPreview(m);
@@ -192,6 +204,7 @@ class EntityTool extends tool.LayerTool {
// Finalize entity
ei.x = getPlacementX(m);
ei.y = getPlacementY(m);
+ ei.flips = M.makeBitsFromBools(flipX, flipY);
onEditAnything();
stopUsing(m);
if( ei.def.isResizable() ) {
@@ -405,4 +418,21 @@ class EntityTool extends tool.LayerTool {
if( PREV_CHAINABLE_EI!=null && PREV_CHAINABLE_EI._li!=null && !PREV_CHAINABLE_EI._li.containsEntity(PREV_CHAINABLE_EI) )
cancelRefChaining();
}
-}
\ No newline at end of file
+
+ override function onKeyPress(keyId:Int) {
+ super.onKeyPress(keyId);
+
+ if ( !Editor.ME.hasInputFocus() )
+ switch keyId {
+ case K.X if ( curEntityDef!=null && curEntityDef.flippableX && !App.ME.hasAnyToggleKeyDown() ):
+ flipX = !flipX;
+ N.quick("X-flip: "+L.onOff(flipX));
+ customCursor(new hxd.Event(EMove), lastMouse);
+
+ case K.Y if ( curEntityDef!=null && curEntityDef.flippableY && !App.ME.hasAnyToggleKeyDown() ):
+ flipY = !flipY;
+ N.quick("Y-flip: "+L.onOff(flipY));
+ customCursor(new hxd.Event(EMove), lastMouse);
+ }
+ }
+}
diff --git a/src/electron.renderer/ui/EntityInstanceEditor.hx b/src/electron.renderer/ui/EntityInstanceEditor.hx
index 2bda16449..ecb5a65fd 100644
--- a/src/electron.renderer/ui/EntityInstanceEditor.hx
+++ b/src/electron.renderer/ui/EntityInstanceEditor.hx
@@ -262,6 +262,33 @@ class EntityInstanceEditor extends dn.Process {
if( UNIT_GRID )
i.setUnit(ei._li.def.gridSize);
+ // Flip block
+ var jFlips = jPropsForm.find(".flips");
+
+ // X
+ var i = new form.input.BoolInput(
+ jFlips.find("[name=x]"),
+ ()->(M.hasBit(ei.flips,0)),
+ (v)->{
+ ei.flips = M.makeBitsFromBools(!M.hasBit(ei.flips, 0), M.hasBit(ei.flips, 1));
+ }
+ );
+ i.setEnabled( ei.def.flippableX );
+ i.linkEvent( EntityInstanceChanged(ei) );
+ i.onChange = ()->onEntityFieldChanged();
+
+ // Y
+ var i = new form.input.BoolInput(
+ jFlips.find("[name=y]"),
+ ()->(M.hasBit(ei.flips,1)),
+ (v)->{
+ ei.flips = M.makeBitsFromBools(M.hasBit(ei.flips, 0), !M.hasBit(ei.flips, 1));
+ }
+ );
+ i.setEnabled( ei.def.flippableY );
+ i.linkEvent( EntityInstanceChanged(ei) );
+ i.onChange = ()->onEntityFieldChanged();
+
// References to this
var refs = project.getEntityInstancesReferingTo(ei);
@@ -321,4 +348,4 @@ class EntityInstanceEditor extends dn.Process {
if( !isOccupied && jWindow.hasClass("faded") )
jWindow.removeClass("faded");
}
-}
\ No newline at end of file
+}
diff --git a/src/electron.renderer/ui/modal/panel/EditEntityDefs.hx b/src/electron.renderer/ui/modal/panel/EditEntityDefs.hx
index b6755ca4a..7646a46b5 100644
--- a/src/electron.renderer/ui/modal/panel/EditEntityDefs.hx
+++ b/src/electron.renderer/ui/modal/panel/EditEntityDefs.hx
@@ -210,6 +210,12 @@ class EditEntityDefs extends ui.modal.Panel {
i.onChange = editor.ge.emit.bind(EntityDefChanged);
i.setEnabled( curEntity.resizableX && curEntity.resizableY );
+ // Flippable
+ var i = Input.linkToHtmlInput( curEntity.flippableX, jEntityForm.find("input#flippableX") );
+ i.onChange = editor.ge.emit.bind(EntityDefChanged);
+ var i = Input.linkToHtmlInput( curEntity.flippableY, jEntityForm.find("input#flippableY") );
+ i.onChange = editor.ge.emit.bind(EntityDefChanged);
+
var i = Input.linkToHtmlInput( curEntity.height, jEntityForm.find("input[name='height']") );
i.setBounds(1,2048);
i.onChange = editor.ge.emit.bind(EntityDefChanged);