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);