diff --git a/app/assets/tpl/editEntityDefs.html b/app/assets/tpl/editEntityDefs.html index 76a5ec15d..0e201cb75 100644 --- a/app/assets/tpl/editEntityDefs.html +++ b/app/assets/tpl/editEntityDefs.html @@ -102,6 +102,23 @@

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/GenericLevelElementGroup.hx b/src/electron.renderer/GenericLevelElementGroup.hx index f5bb1fc4d..841dd2150 100644 --- a/src/electron.renderer/GenericLevelElementGroup.hx +++ b/src/electron.renderer/GenericLevelElementGroup.hx @@ -216,8 +216,8 @@ class GenericLevelElementGroup { case Entity(li, ei): selectRender.beginFill(c, alpha); selectRender.drawRect( - li.pxParallaxX + ( ei.x - ei.width * ei.def.pivotX ) * li.def.getScale(), - li.pxParallaxY + ( ei.y - ei.height * ei.def.pivotY ) * li.def.getScale(), + li.pxParallaxX + ( ei.x - ei.width * ei.getAdjustedPivotX() ) * li.def.getScale(), + li.pxParallaxY + ( ei.y - ei.height * ei.getAdjustedPivotY() ) * li.def.getScale(), ei.width * li.def.getScale(), ei.height * li.def.getScale() ); @@ -863,4 +863,4 @@ class GenericLevelElementGroup { renderSelection(); } } -} \ 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 87f1275e8..92eb66403 100644 --- a/src/electron.renderer/data/def/EntityDef.hx +++ b/src/electron.renderer/data/def/EntityDef.hx @@ -32,6 +32,9 @@ class EntityDef { public var resizableX : Bool; public var resizableY : Bool; + public var flippableX : Bool; + public var flippableY : Bool; + public var flipAroundPivot : Bool; public var minWidth : Null; public var maxWidth : Null; public var minHeight : Null; @@ -66,6 +69,8 @@ class EntityDef { identifier = "Entity"+uid; setPivot(0.5,1); resizableX = resizableY = false; + flippableX = flippableY = false; + flipAroundPivot = false; keepAspectRatio = false; hollow = false; tags = new Tags(); @@ -97,6 +102,14 @@ class EntityDef { return null; } + public inline function getFlippedPivotX() { + return flipAroundPivot ? ((width - 1) / width) - pivotX : pivotX; + } + + public inline function getFlippedPivotY() { + return flipAroundPivot ? ((height - 1) / height) - pivotY : pivotY; + } + function set_identifier(id:String) { return identifier = Project.isValidIdentifier(id) ? Project.cleanupIdentifier(id, _project.identifierStyle) : identifier; } @@ -149,6 +162,9 @@ 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.flipAroundPivot = JsonTools.readBool( json.flipAroundPivot, false ); o.minWidth = JsonTools.readNullableInt( json.minWidth ); o.maxWidth = JsonTools.readNullableInt( json.maxWidth ); o.minHeight = JsonTools.readNullableInt( json.minHeight ); @@ -207,6 +223,9 @@ class EntityDef { height: height, resizableX: resizableX, resizableY: resizableY, + flippableX: flippableX, + flippableY: flippableY, + flipAroundPivot: flipAroundPivot, minWidth: minWidth, maxWidth: maxWidth, minHeight: minHeight, @@ -329,4 +348,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 bb747edaf..d24d48b2a 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; @@ -24,25 +25,26 @@ class EntityInstance { public var fieldInstances : Map = new Map(); - public var left(get,never) : Int; inline function get_left() return M.round( x - width*def.pivotX ); + public var left(get,never) : Int; inline function get_left() return M.round( x - width*getAdjustedPivotX() ); public var right(get,never) : Int; inline function get_right() return left + width; - public var top(get,never) : Int; inline function get_top() return M.round( y - height*def.pivotY ); + public var top(get,never) : Int; inline function get_top() return M.round( y - height*getAdjustedPivotY() ); 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() { return 'EntityInst "${def.identifier}" @$x,$y'; } - inline function get_centerX() return M.round( x + (0.5-def.pivotX)*width ); - inline function get_centerY() return M.round( y + (0.5-def.pivotY)*height ); + inline function get_centerX() return M.round( x + (0.5-getAdjustedPivotX())*width ); + inline function get_centerY() return M.round( y + (0.5-getAdjustedPivotY())*height ); inline function get_worldX() return Std.int( x + _li.level.worldX ); inline function get_worldY() return Std.int( y + _li.level.worldY ); @@ -70,6 +72,7 @@ class EntityInstance { height: height, defUid: defUid, px: [x,y], + f: flips, fieldInstances: { var all = []; for(fd in def.fieldDefs) @@ -90,6 +93,7 @@ class EntityInstance { layer: _li.def.identifier, x : x, y : y, + f: flips, width: width, height: height, color: getSmartColor(false), @@ -111,6 +115,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; @@ -127,12 +133,20 @@ class EntityInstance { return ei; } + public inline function getAdjustedPivotX() { + return (def.flipAroundPivot && M.hasBit(flips, 0)) ? ((width - 1) / width) - def.pivotX : def.pivotX; + } + + public inline function getAdjustedPivotY() { + return (def.flipAroundPivot && M.hasBit(flips, 1)) ? ((height - 1) / height) - def.pivotY : def.pivotY; + } + public inline function getCx(ld:data.def.LayerDef) { - return Std.int( ( x + (def.pivotX==1 ? -1 : 0) ) / ld.gridSize ); + return Std.int( ( x + (getAdjustedPivotX()==1 ? -1 : 0) ) / ld.gridSize ); } public inline function getCy(ld:data.def.LayerDef) { - return Std.int( ( y + (def.pivotY==1 ? -1 : 0) ) / ld.gridSize ); + return Std.int( ( y + (getAdjustedPivotY()==1 ? -1 : 0) ) / ld.gridSize ); } public inline function getPointOriginX(ld:data.def.LayerDef) { @@ -365,4 +379,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 540a1d4a0..01b62e4a6 100644 --- a/src/electron.renderer/display/EntityRender.hx +++ b/src/electron.renderer/display/EntityRender.hx @@ -112,15 +112,21 @@ class EntityRender extends dn.Process { ed = ei.def; + var w = ei!=null ? ei.width : ed.width; var h = ei!=null ? ei.height : ed.height; var color = ei!=null ? ei.getSmartColor(false) : ed.color; + var flipX = (ei!=null && M.hasBit(ei.flips,0)); + var flipY = (ei!=null && M.hasBit(ei.flips,1)); + var pivotX = ei!=null ? ei.getAdjustedPivotX() : ed.pivotX; + var pivotY = ei!=null ? ei.getAdjustedPivotY() : ed.pivotY; + var wrapper = new h2d.Object(); var g = new h2d.Graphics(wrapper); - g.x = Std.int( -w*ed.pivotX + (ld!=null ? ld.pxOffsetX : 0) ); - g.y = Std.int( -h*ed.pivotY + (ld!=null ? ld.pxOffsetY : 0) ); + g.x = Std.int( -w*pivotX + (ld!=null ? ld.pxOffsetX : 0)); + g.y = Std.int( -h*pivotY + (ld!=null ? ld.pxOffsetY : 0)); var zoomScale = 1 / Editor.ME.camera.adjustedZoom; @@ -145,13 +151,15 @@ 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: var bmp = new h2d.Bitmap(t, wrapper); if( ld!=null ) bmp.setPosition(ld.pxOffsetX, ld.pxOffsetY); - bmp.tile.setCenterRatio(ed.pivotX, ed.pivotY); + bmp.tile.setCenterRatio(pivotX, pivotY); bmp.alpha = alpha; bmp.scaleX = w / bmp.tile.width; @@ -161,17 +169,21 @@ class EntityRender extends dn.Process { var bmp = new h2d.Bitmap(t, wrapper); if( ld!=null ) bmp.setPosition(ld.pxOffsetX, ld.pxOffsetY); - bmp.tile.setCenterRatio(ed.pivotX, ed.pivotY); + bmp.tile.setCenterRatio(pivotX, pivotY); bmp.alpha = alpha; var s = M.fmin(w / bmp.tile.width, h / bmp.tile.height); bmp.setScale(s); case Repeat: - var tt = new dn.heaps.TiledTexture(w,h, t, wrapper); + // Invert flips to prevent broken rendering. + t.xFlip = false; + t.yFlip = false; + var tt = new dn.heaps.TiledTexture(w, h, t, wrapper); + tt.alpha = alpha; - tt.x = -w*ed.pivotX + (ld==null ? 0 : ld.pxOffsetX); - tt.y = -h*ed.pivotY + (ld==null ? 0 : ld.pxOffsetY); + tt.x = -w*pivotX + (ld==null ? 0 : ld.pxOffsetX); + tt.y = -h*pivotY + (ld==null ? 0 : ld.pxOffsetY); case Cover: var bmp = new h2d.Bitmap(wrapper); @@ -183,11 +195,13 @@ class EntityRender extends dn.Process { final fw = M.fmin(w, t.width*s) / s; final fh = M.fmin(h, t.height*s) / s; bmp.tile = t.sub( - t.width*ed.pivotX - fw*ed.pivotX, - t.height*ed.pivotY - fh*ed.pivotY, + t.width*pivotX - fw*pivotX, + t.height*pivotY - fh*pivotY, fw,fh ); - bmp.tile.setCenterRatio(ed.pivotX, ed.pivotY); + bmp.tile.xFlip = t.xFlip; + bmp.tile.yFlip = t.yFlip; + bmp.tile.setCenterRatio(pivotX, pivotY); bmp.setScale(s); case FullSizeCropped: @@ -197,11 +211,13 @@ class EntityRender extends dn.Process { final fw = M.fmin(w, t.width); final fh = M.fmin(h, t.height); bmp.tile = t.sub( - t.width*ed.pivotX - fw*ed.pivotX, - t.height*ed.pivotY - fh*ed.pivotY, + t.width*pivotX - fw*pivotX, + t.height*pivotY - fh*pivotY, fw, fh ); - bmp.tile.setCenterRatio(ed.pivotX, ed.pivotY); + bmp.tile.xFlip = t.xFlip; + bmp.tile.yFlip = t.yFlip; + bmp.tile.setCenterRatio(pivotX, pivotY); bmp.alpha = alpha; case FullSizeUncropped: @@ -209,7 +225,7 @@ class EntityRender extends dn.Process { if( ld!=null ) bmp.setPosition(ld.pxOffsetX, ld.pxOffsetY); - bmp.tile.setCenterRatio(ed.pivotX, ed.pivotY); + bmp.tile.setCenterRatio(pivotX, pivotY); bmp.alpha = alpha; case NineSlice: @@ -223,9 +239,8 @@ class EntityRender extends dn.Process { sg.tileCenter = true; sg.width = w; sg.height = h; - sg.x = -w*ed.pivotX + (ld==null ? 0 : ld.pxOffsetX); - sg.y = -h*ed.pivotY + (ld==null ? 0 : ld.pxOffsetY); - + sg.x = -w*pivotX + (ld==null ? 0 : ld.pxOffsetX); + sg.y = -h*pivotY + (ld==null ? 0 : ld.pxOffsetY); } } } @@ -266,11 +281,18 @@ class EntityRender extends dn.Process { } // Pivot + + // Adjust pivot rendering position based on our flip statuses. + var pivotX = ((ed.flipAroundPivot && flipX) ? ((w - 1) / w) - ed.pivotX : ed.pivotX); + var pivotY = ((ed.flipAroundPivot && flipY) ? ((h - 1) / h) - ed.pivotY : ed.pivotY); + g.lineStyle(0); + // Draw pivot background. g.beginFill(0x0, 0.4); - g.drawRect(w*ed.pivotX-1, h*ed.pivotY-1, 3,3); + g.drawRect(w*pivotX-1, h*pivotY-1, 3,3); + // Draw pivot foreground. g.beginFill(color, 1); - g.drawRect(w*ed.pivotX, h*ed.pivotY, 1,1); + g.drawRect(w*pivotX, h*pivotY, 1,1); return { wrapper: wrapper, @@ -366,13 +388,15 @@ class EntityRender extends dn.Process { fieldGraphics.alpha = fullVis ? 1 : ei._li.def.inactiveOpacity; } + var pivX = M.hasBit(ei.flips, 0) ? ed.getFlippedPivotX() : ed.pivotX; + var pivY = M.hasBit(ei.flips, 1) ? ed.getFlippedPivotY() : ed.pivotY; // Identifier if( identifier!=null ) { identifier.visible = fullVis || !ei._li.def.hideFieldsWhenInactive; identifier.setScale(zoomScale); - identifier.x = Std.int( -ei.width*ed.pivotX - identifier.textWidth*0.5*identifier.scaleX + ei.width*0.5 ); - identifier.y = Std.int( -identifier.textHeight*identifier.scaleY - ei.height*ed.pivotY ); + identifier.x = Std.int( -ei.width*pivX - identifier.textWidth*0.5*identifier.scaleX + ei.width*0.5 ); + identifier.y = Std.int( -identifier.textHeight*identifier.scaleY - ei.height*pivY ); } // Update field wrappers @@ -380,8 +404,8 @@ class EntityRender extends dn.Process { above.visible = showFields && above.numChildren>0; if( above.visible ) { above.setScale(zoomScale); - above.x = M.round( -ei.width*ed.pivotX - above.outerWidth*0.5*above.scaleX + ei.width*0.5 ); - above.y = Std.int( -above.outerHeight*above.scaleY - ei.height*ed.pivotY ); + above.x = M.round( -ei.width*pivX - above.outerWidth*0.5*above.scaleX + ei.width*0.5 ); + above.y = Std.int( -above.outerHeight*above.scaleY - ei.height*pivY ); if( identifier!=null ) above.y -= identifier.textHeight*identifier.scaleY; above.alpha = 1; @@ -390,16 +414,16 @@ class EntityRender extends dn.Process { center.visible = showFields && center.numChildren>0; if( center.visible ) { center.setScale(zoomScale); - center.x = Std.int( -ei.width*ed.pivotX - center.outerWidth*0.5*center.scaleX + ei.width*0.5 ); - center.y = Std.int( -ei.height*ed.pivotY - center.outerHeight*0.5*center.scaleY + ei.height*0.5); + center.x = Std.int( -ei.width*pivX - center.outerWidth*0.5*center.scaleX + ei.width*0.5 ); + center.y = Std.int( -ei.height*pivY - center.outerHeight*0.5*center.scaleY + ei.height*0.5); center.alpha = 1; } beneath.visible = showFields && beneath.numChildren>0; if( beneath.visible ) { beneath.setScale(zoomScale); - beneath.x = Std.int( -ei.width*ed.pivotX - beneath.outerWidth*0.5*beneath.scaleX + ei.width*0.5 ); - beneath.y = Std.int( ei.height*(1-ed.pivotY) ); + beneath.x = Std.int( -ei.width*pivX - beneath.outerWidth*0.5*beneath.scaleX + ei.width*0.5 ); + beneath.y = Std.int( ei.height*(1-pivY) ); beneath.alpha = 1; } } diff --git a/src/electron.renderer/display/LevelRender.hx b/src/electron.renderer/display/LevelRender.hx index 589b0a084..8fca0734e 100644 --- a/src/electron.renderer/display/LevelRender.hx +++ b/src/electron.renderer/display/LevelRender.hx @@ -401,8 +401,8 @@ class LevelRender extends dn.Process { public inline function bleepEntity(ei:data.inst.EntityInstance, ?overrideColor:Int, spd=1.0) : Bleep { return bleepLayerRectPx( ei._li, - Std.int( (ei.x-ei.width*ei.def.pivotX) * ei._li.def.getScale() ), - Std.int( (ei.y-ei.height*ei.def.pivotY) * ei._li.def.getScale() ), + Std.int( (ei.x-ei.width*ei.getAdjustedPivotX()) * ei._li.def.getScale() ), + Std.int( (ei.y-ei.height*ei.getAdjustedPivotY()) * ei._li.def.getScale() ), ei.width, ei.height, overrideColor!=null ? overrideColor : ei.getSmartColor(true), diff --git a/src/electron.renderer/tool/ResizeTool.hx b/src/electron.renderer/tool/ResizeTool.hx index 337c1c0d0..bfdc874c9 100644 --- a/src/electron.renderer/tool/ResizeTool.hx +++ b/src/electron.renderer/tool/ResizeTool.hx @@ -272,14 +272,14 @@ class ResizeTool extends Tool { if( ei.customHeight==ei.def.height ) ei.customHeight = null; switch draggedHandle { - case Left, TopLeft, BottomLeft: if( ei.def.pivotX==0 ) ei.x -= ( ei.width - oldW ); - case Right, TopRight, BottomRight: if( ei.def.pivotX==1 ) ei.x += ( ei.width - oldW ); + case Left, TopLeft, BottomLeft: if( ei.getAdjustedPivotX()==0 ) ei.x -= ( ei.width - oldW ); + case Right, TopRight, BottomRight: if( ei.getAdjustedPivotX()==1 ) ei.x += ( ei.width - oldW ); case _: } switch draggedHandle { - case Top, TopLeft, TopRight: if( ei.def.pivotY==0 ) ei.y -= ( ei.height - oldH ); - case Bottom, BottomLeft, BottomRight: if( ei.def.pivotY==1 ) ei.y += ( ei.height - oldH ); + case Top, TopLeft, TopRight: if( ei.getAdjustedPivotY()==0 ) ei.y -= ( ei.height - oldH ); + case Bottom, BottomLeft, BottomRight: if( ei.getAdjustedPivotY()==1 ) ei.y += ( ei.height - oldH ); case _: } @@ -314,4 +314,4 @@ class ResizeTool extends Tool { invalidated = false; } } -} \ 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..34be439e8 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 { @@ -66,14 +76,16 @@ class EntityTool extends tool.LayerTool { } function getPlacementX(m:Coords) { + var pivot = flipX ? curEntityDef.getFlippedPivotX() : curEntityDef.pivotX; return snapToGrid() - ? M.round( ( m.cx + curEntityDef.pivotX ) * curLayerInstance.def.gridSize ) + ? M.round( ( m.cx * curLayerInstance.def.gridSize ) + pivot * curEntityDef.width ) : m.levelX; } function getPlacementY(m:Coords) { + var pivot = flipY ? curEntityDef.getFlippedPivotY() : curEntityDef.pivotY; return snapToGrid() - ? M.round( ( m.cy + curEntityDef.pivotY ) * curLayerInstance.def.gridSize) + ? M.round( ( m.cy * curLayerInstance.def.gridSize ) + pivot * curEntityDef.height ) : m.levelY; } @@ -113,7 +125,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 +206,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 +420,25 @@ 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); + // Simulate mouse movement to recenter entity render. + editor.cursor.onMouseMove(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); + // Simulate mouse movement to recenter entity render. + editor.cursor.onMouseMove(lastMouse); + } + } +} diff --git a/src/electron.renderer/ui/Cursor.hx b/src/electron.renderer/ui/Cursor.hx index 31b2080b7..b55cdc151 100644 --- a/src/electron.renderer/ui/Cursor.hx +++ b/src/electron.renderer/ui/Cursor.hx @@ -203,14 +203,14 @@ class Cursor { final ry = ei.height*0.5; g.lineStyle(1, 0xffcc00, 1); g.drawEllipse( - (0.5-def.pivotX)*ei.width, (0.5-def.pivotY)*ei.height, + (0.5-ei.getAdjustedPivotX())*ei.width, (0.5-ei.getAdjustedPivotY())*ei.height, rx+pad, ry+pad, 0, rx<=16 && ry<=16 ? 24 : 0 ); case Rectangle, Tile: g.lineStyle(1, 0xffcc00, 1); - renderBeveledRect(g, -def.pivotX*ei.width-pad, -def.pivotY*ei.height-pad, ei.width+pad*2, ei.height+pad*2); + renderBeveledRect(g, -ei.getAdjustedPivotX()*ei.width-pad, -ei.getAdjustedPivotY()*ei.height-pad, ei.width+pad*2, ei.height+pad*2); } } @@ -363,4 +363,4 @@ class Cursor { render(); } } -} \ No newline at end of file +} diff --git a/src/electron.renderer/ui/EntityInstanceEditor.hx b/src/electron.renderer/ui/EntityInstanceEditor.hx index b119c68bb..9005df4d8 100644 --- a/src/electron.renderer/ui/EntityInstanceEditor.hx +++ b/src/electron.renderer/ui/EntityInstanceEditor.hx @@ -268,6 +268,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); @@ -327,4 +354,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 8af6835ea..2245d2e9f 100644 --- a/src/electron.renderer/ui/modal/panel/EditEntityDefs.hx +++ b/src/electron.renderer/ui/modal/panel/EditEntityDefs.hx @@ -227,6 +227,15 @@ class EditEntityDefs extends ui.modal.Panel { i.linkEvent(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.flipAroundPivot, jEntityForm.find("input#flipAroundPivot") ); + 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);