From c1732b46ada1942f6e6f08232d26b344cb0d9568 Mon Sep 17 00:00:00 2001 From: lunarcleint <88809950+lunarcleint@users.noreply.github.com> Date: Sun, 9 Jun 2024 01:41:25 -0700 Subject: [PATCH] drawTriangles for 9splice (mostly working) --- assets/images/editors/ui/context-bg-debug.png | Bin 0 -> 922 bytes assets/images/editors/ui/context-bg-debug.xml | 15 + source/funkin/editors/UIDebugState.hx | 5 +- source/funkin/editors/ui/UISliceSprite.hx | 323 ++++++++++++------ 4 files changed, 231 insertions(+), 112 deletions(-) create mode 100644 assets/images/editors/ui/context-bg-debug.png create mode 100644 assets/images/editors/ui/context-bg-debug.xml diff --git a/assets/images/editors/ui/context-bg-debug.png b/assets/images/editors/ui/context-bg-debug.png new file mode 100644 index 0000000000000000000000000000000000000000..aa83123fa58eef0c5ba18b4d4f0e744da10f0f96 GIT binary patch literal 922 zcmV;L17-Y)P)Px&R7pfZRCt{2o6T|?MG(jTJ=3$hT3L2%bo0T%Aza`N$%z|}lS?Wu!Ic-`3P*|y zRlESH*vY|FRM`+?Nzv}kN9Q1iG9au;A#1a%`BkY(AHAjjw0gRGW;OKrH(&jL8&Du! zR^?$9@^MByVxu(x;MXs(6cM%jgAG9xmc9Mx)9)8g6b08*lR(vZ$R}r{g1>3UH(!)j z!w2`W-TTgY@;0Ed76^9n;raY78^;JE?y8tD{SZUG2cS&NKa4vv|cR0(nX{K)V6?FHaHi>Tn)JSo= zP0R-XfBD@USHG`ra$Y|DaRYMJ$JgIJS!px+s94@bZ4=1>Z3}3d_5jK<}pwDZ8I5>J}U2BCS$Cai45ScJKHwRK96vcHCjPMq9ED1!C zA^?cX0bRR+9-FdK1S~wYoiQLt5pZ1vVm3v))(S?-O%VW!TMl=PR0SeQ4rp6I+eGgN z^f6BW@*X=v9jk(|Wqa$Vz?T0*Bt^h`Y>C~mkaZKQmx0d!)GH1BFF*Y+L7V2;>uP%o!jqTD+I19XO)5pJvuM6;P&ybQE)yuhL;%|eXprk9Gd7^pfGDRB2$IhUu2nX zThGSPOsK_Qux{KLasCMr!QXQCqiYl7Hoe9uFe_A2ohdD1tBd(bxnsbp|80RW3VF`B zY?@QiWEB9E&Y$?HeN_y&*G^#8CI@vo}FzW{FB9xp2Ud>$l>4vPD>@#JiPa{;d7 z)qz>T7!6|-lp^_~s!y9T{QK}U01O)UBK$UciGmL~)8lNIjk0WUeEwowEd2rr)N06( wT7Kqrj={A7g*UaEOvIg6uxC=z-%g3X1&@6_Hv(F~S^xk507*qoM6N<$f-j+=%K!iX literal 0 HcmV?d00001 diff --git a/assets/images/editors/ui/context-bg-debug.xml b/assets/images/editors/ui/context-bg-debug.xml new file mode 100644 index 00000000..6eb3c21a --- /dev/null +++ b/assets/images/editors/ui/context-bg-debug.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/funkin/editors/UIDebugState.hx b/source/funkin/editors/UIDebugState.hx index 3a0bf57f..6b621e92 100644 --- a/source/funkin/editors/UIDebugState.hx +++ b/source/funkin/editors/UIDebugState.hx @@ -101,11 +101,8 @@ class UIDebugState extends UIState { }, 130, 48)); add(new UITextBox(10, 220, "")); - var spliceSprite:UISliceSprite = new UISliceSprite(650, 350, 30, 30, "editors/ui/context-bg"); + var spliceSprite:UISliceSprite = new UISliceSprite(650, 300, 200, 200, "editors/ui/context-bg-debug"); add(spliceSprite); - FlxTween.num(0, 1, 2, {type: PINGPONG}, function (v:Float) { - spliceSprite.bWidth = Std.int(lerp(12, 200, v)); spliceSprite.bHeight = Std.int(lerp(12, 200, v)); - }); } public override function update(elapsed:Float) { diff --git a/source/funkin/editors/ui/UISliceSprite.hx b/source/funkin/editors/ui/UISliceSprite.hx index 256c574d..63bea2b2 100644 --- a/source/funkin/editors/ui/UISliceSprite.hx +++ b/source/funkin/editors/ui/UISliceSprite.hx @@ -1,10 +1,13 @@ package funkin.editors.ui; +import flixel.math.FlxRect; import flixel.graphics.frames.FlxFrame; +import flixel.graphics.tile.FlxGraphicsShader; +import flixel.graphics.tile.FlxDrawTrianglesItem.DrawData; class UISliceSprite extends UISprite { - public var bWidth:Int = 120; - public var bHeight:Int = 20; + public var bWidth(default, set):Int = 120; + public var bHeight(default, set):Int = 20; public var framesOffset(default, set):Int = 0; public var incorporeal:Bool = false; @@ -14,7 +17,9 @@ class UISliceSprite extends UISprite { frames = Paths.getFrames(path); resize(w, h); + calculateFrames(); + __genMesh(); } public override function updateButton() { @@ -56,14 +61,15 @@ class UISliceSprite extends UISprite { override function set_frames(val) { super.set_frames(val); - calculateFrames(); + __framesDirty = true; + __meshDirty = true; return val; } function set_framesOffset(value:Int) { if(value != framesOffset) { framesOffset = value; - calculateFrames(); + __framesDirty = true; } return value; } @@ -84,125 +90,226 @@ class UISliceSprite extends UISprite { rightWidth = Std.int(Math.max(topright.frame.width, Math.max(middleright.frame.width, bottomright.frame.width))); topHeight = Std.int(Math.max(topleft.frame.height, Math.max(top.frame.height, topright.frame.height))); bottomHeight = Std.int(Math.max(topleft.frame.height, Math.max(top.frame.height, topright.frame.height))); + + __genUVs(); } public override function draw() @:privateAccess { - var lastPixelPerfect:Bool = cameras[0] != null ? cameras[0].pixelPerfectRender : false; - if (cameras[0] != null) cameras[0].pixelPerfectRender = false; - - var x:Float = this.x; - var y:Float = this.y; + checkEmptyFrame(); - if (visible && !(bWidth == 0 || bHeight == 0)) { - var oldAlpha = alpha; - // TOP - if (drawTop) { - // TOP LEFT - if(topAlpha != null) alpha = topAlpha; - frame = topleft; - setPosition(x, y); - __setSize( - topleft.frame.width * Math.min(bWidth/(topleft.frame.width*2), 1), - topleft.frame.height * Math.min(bHeight/(topleft.frame.height*2), 1) + if (alpha == 0 || _frame.type == FlxFrameType.EMPTY) + return; + + if (__framesDirty) calculateFrames(); + if (__meshDirty) __genMesh(); + + for (camera in cameras) + { + if (!camera.visible || !camera.exists || !isOnScreen(camera)) + continue; + + getScreenPosition(_point, camera).subtractPoint(offset); + + #if !flash + camera.drawTriangles(graphic, vertices, indices, uvtData, colors, _point, blend, false, antialiasing, colorTransform, shader); + #else + camera.drawTriangles(graphic, vertices, indices, uvtData, colors, _point, blend, false, antialiasing); + #end + + #if FLX_DEBUG + FlxBasic.visibleCount++; + #end + } + + super.drawMembers(); + __lastDrawCameras = cameras.copy(); + } + + var vertices:DrawData = new DrawData(); + var indices:DrawData = new DrawData(); + var uvtData:DrawData = new DrawData(); + var colors:DrawData = new DrawData(); + + var __framesDirty:Bool = false; + var __meshDirty:Bool = false; + + public function set_bWidth(value:Int):Int { + if(value != bWidth) { + bWidth = value; + __meshDirty = true; + } + return value; + } + + public function set_bHeight(value:Int):Int { + if(value != bHeight) { + bHeight = value; + __meshDirty = true; + } + return value; + } + + private inline function __genMesh() { + indices.length = 0; + vertices.length = 0; + + // TOP PART + if (drawTop) { + // TOP LEFT + var topLeftWidth:Float = topleft.frame.width * Math.min(bWidth / (topleft.frame.width * 2), 1); + var topLeftHeight:Float = topleft.frame.height * Math.min(bHeight / (topleft.frame.height * 2), 1); + __genSliceTri( + 0, 0, + topLeftWidth, topLeftHeight + ); + + // TOP MIDDLE + if (bWidth > topleft.frame.width + topright.frame.width) { + var topWidth:Float = bWidth - topleft.frame.width - topright.frame.width; + var topHeight:Float = top.frame.height * Math.min(bHeight / (top.frame.height * 2), 1); + __genSliceTri( + topLeftWidth, 0, + topWidth, topHeight ); - super.drawSuper(); - - // TOP - if (bWidth > topleft.frame.width + topright.frame.width) { - frame = top; - setPosition(x + topleft.frame.width, y); - __setSize(bWidth - topleft.frame.width - topright.frame.width, top.frame.height * Math.min(bHeight/(top.frame.height*2), 1)); - super.drawSuper(); - } - - // TOP RIGHT - setPosition(x + bWidth - (topright.frame.width * Math.min(bWidth/(topright.frame.width*2), 1)), y); - frame = topright; - __setSize( - topright.frame.width * Math.min(bWidth/(topright.frame.width*2), 1), - topright.frame.height * Math.min(bHeight/(topright.frame.height*2), 1) - ); - super.drawSuper(); } + // TOP RIGHT + var topRightWidth:Float = topright.frame.width * Math.min(bWidth/(topright.frame.width*2), 1); + var topRightHeight:Float = topright.frame.height * Math.min(bHeight/(topright.frame.height*2), 1); + __genSliceTri( + bWidth - (topright.frame.width * Math.min(bWidth/(topright.frame.width*2), 1)), 0, + topRightWidth, topRightHeight + ); + } + + if (drawMiddle && bHeight > top.frame.height + bottom.frame.height) { + var middleHeight:Float = bHeight - (topleft.frame.height * Math.min(bHeight/(topleft.frame.height*2), 1)) - + bottomleft.frame.height * Math.min(bHeight/(bottomleft.frame.height*2), 1); + + // MIDDLE LEFT + var middleLeftWidth:Float = middleleft.frame.width * Math.min(bWidth/(middleleft.frame.width*2), 1); + __genSliceTri( + 0, top.frame.height, + middleLeftWidth, middleHeight + ); + // MIDDLE - if (drawMiddle && bHeight > top.frame.height + bottom.frame.height) { - if(middleAlpha != null) alpha = middleAlpha; - var middleHeight:Float = bHeight - (topleft.frame.height * Math.min(bHeight/(topleft.frame.height*2), 1)) - - bottomleft.frame.height * Math.min(bHeight/(bottomleft.frame.height*2), 1); - - // MIDDLE LEFT - frame = middleleft; - setPosition(x, y + top.frame.height); - __setSize(middleleft.frame.width * Math.min(bWidth/(middleleft.frame.width*2), 1), middleHeight); - super.drawSuper(); - - if (bWidth > (middleleft.frame.width * Math.min(bWidth/(middleleft.frame.width*2), 1)) + middleright.frame.width) { - // MIDDLE - frame = middle; - setPosition(x + topleft.frame.width, y + top.frame.height); - __setSize(bWidth - middleleft.frame.width - middleright.frame.width, middleHeight); - super.drawSuper(); - } - - // MIDDLE RIGHT - frame = middleright; - setPosition(x + bWidth - (topright.frame.width * Math.min(bWidth/(topright.frame.width*2), 1)), y + top.frame.height); - __setSize(middleright.frame.width * Math.min(bWidth/(middleright.frame.width*2), 1), middleHeight); - super.drawSuper(); + if (bWidth > (middleleft.frame.width * Math.min(bWidth/(middleleft.frame.width*2), 1)) + middleright.frame.width) { + var middleWidth:Float = bWidth - middleleft.frame.width - middleright.frame.width; + __genSliceTri( + topleft.frame.width, top.frame.height, + middleWidth, middleHeight + ); } - // BOTTOM - if (drawBottom) { - if(bottomAlpha != null) alpha = bottomAlpha; - // BOTTOM LEFT - frame = bottomleft; - setPosition(x, y + bHeight - (bottomleft.frame.height * Math.min(bHeight/(bottomleft.frame.height*2), 1))); - __setSize( - bottomleft.frame.width * Math.min(bWidth/(bottomleft.frame.width*2), 1), - bottomleft.frame.height * Math.min(bHeight/(bottomleft.frame.height*2), 1) - ); - super.drawSuper(); - - if (bWidth > bottomleft.frame.width + bottomright.frame.width) { - // BOTTOM - frame = bottom; - setPosition(x + bottomleft.frame.width, y + bHeight - (bottom.frame.height * Math.min(bHeight/(bottom.frame.height*2), 1))); - __setSize(bWidth - bottomleft.frame.width - bottomright.frame.width, bottom.frame.height * Math.min(bHeight/(bottom.frame.height*2), 1)); - super.drawSuper(); - } - - // BOTTOM RIGHT - frame = bottomright; - setPosition( - x + bWidth - (bottomright.frame.width * Math.min(bWidth/(bottomright.frame.width*2), 1)), - y + bHeight - (bottomright.frame.height * Math.min(bHeight/(bottomright.frame.height*2), 1)) - ); - __setSize( - bottomright.frame.width * Math.min(bWidth/(bottomright.frame.width*2), 1), - bottomright.frame.height * Math.min(bHeight/(bottomright.frame.height*2), 1) - ); - super.drawSuper(); - - } - alpha = oldAlpha; + // MIDDLE RIGHT + var middleRightWidth:Float = middleright.frame.width * Math.min(bWidth/(middleright.frame.width*2), 1); + __genSliceTri( + bWidth - (topright.frame.width * Math.min(bWidth/(topright.frame.width*2), 1)), top.frame.height, + middleRightWidth, middleHeight + ); } - if (cameras[0] != null) cameras[0].pixelPerfectRender = lastPixelPerfect; - setPosition(x, y); - super.drawMembers(); + // BOTTOM + if (drawBottom) { + // BOTTOM LEFT + var bottomLeftWidth:Float = bottomleft.frame.width * Math.min(bWidth/(bottomleft.frame.width*2), 1); + var bottomLeftHeight:Float = bottomleft.frame.height * Math.min(bHeight/(bottomleft.frame.height*2), 1); + __genSliceTri( + 0, bHeight - (bottomleft.frame.height * Math.min(bHeight/(bottomleft.frame.height*2), 1)), + bottomLeftWidth, bottomLeftHeight + ); + + // BOTTOM MIDDLE + if (bWidth > bottomleft.frame.width + bottomright.frame.width) { + var bottomMiddleWidth:Float = bWidth - bottomleft.frame.width - bottomright.frame.width; + var bottomMiddleHeight:Float = bottom.frame.height * Math.min(bHeight/(bottom.frame.height*2), 1); + __genSliceTri( + bottomleft.frame.width, bHeight - (bottom.frame.height * Math.min(bHeight/(bottom.frame.height*2), 1)), + bottomMiddleWidth, bottomMiddleHeight + ); + } + + // BOTTOM RIGHT + var bottomRightWidth:Float = bottomright.frame.width * Math.min(bWidth/(bottomright.frame.width*2), 1); + var bottomRightHeight:Float = bottomright.frame.height * Math.min(bHeight/(bottomright.frame.height*2), 1); + __genSliceTri( + bWidth - (bottomright.frame.width * Math.min(bWidth/(bottomright.frame.width*2), 1)), + bHeight - (bottomright.frame.height * Math.min(bHeight/(bottomright.frame.height*2), 1)), + bottomRightWidth, bottomRightHeight + ); + } + + __meshDirty = false; } - private function __setSize(Width:Float, Height:Float) { - var newScaleX:Float = Width / frameWidth; - var newScaleY:Float = Height / frameHeight; - scale.set(newScaleX, newScaleY); + private inline function __genUVs() { + uvtData.length = 0; - if (Width <= 0) - scale.x = newScaleY; - else if (Height <= 0) - scale.y = newScaleX; + __genSliceUV(topleft); + __genSliceUV(top); + __genSliceUV(topright); + __genSliceUV(middleleft); + __genSliceUV(middle); + __genSliceUV(middleright); + __genSliceUV(bottomleft); + __genSliceUV(bottom); + __genSliceUV(bottomright); - updateHitbox(); + __framesDirty = false; + } + + private inline function __genSliceTri(x:Float, y:Float, width:Float, height:Float) { + var indicesOffset:Int = Std.int(vertices.length / 2); + + indices.push(indicesOffset); + indices.push(indicesOffset + 1); + indices.push(indicesOffset + 2); + indices.push(indicesOffset); + indices.push(indicesOffset + 2); + indices.push(indicesOffset + 3); + + vertices.push(x); + vertices.push(y); + vertices.push(x + width); + vertices.push(y); + vertices.push(x + width); + vertices.push(y + height); + vertices.push(x); + vertices.push(y + height); + } + + private inline function __genSliceUV(frame:FlxFrame) { + uvtData.push(frame.uv.x); + uvtData.push(frame.uv.y); + uvtData.push(frame.uv.width); + uvtData.push(frame.uv.y); + uvtData.push(frame.uv.width); + uvtData.push(frame.uv.height); + uvtData.push(frame.uv.x); + uvtData.push(frame.uv.height); + } + + @:access(flixel.FlxCamera) + override function getBoundingBox(camera:FlxCamera):FlxRect { + getScreenPosition(_point, camera); + + _rect.set(_point.x, _point.y, bWidth, bHeight); + _rect = camera.transformRect(_rect); + + // if (isPixelPerfectRender(camera)) + // _rect.floor(); + + return _rect; + } + + override public function destroy():Void + { + vertices = null; + indices = null; + uvtData = null; + colors = null; + + super.destroy(); } } \ No newline at end of file