diff --git a/project.xml b/project.xml index 072ab1ab..09502ba7 100644 --- a/project.xml +++ b/project.xml @@ -108,7 +108,7 @@
- +
diff --git a/source/funkin/backend/system/FakeCamera.hx b/source/funkin/backend/system/FakeCamera.hx index 5170c246..83d66eee 100644 --- a/source/funkin/backend/system/FakeCamera.hx +++ b/source/funkin/backend/system/FakeCamera.hx @@ -35,4 +35,15 @@ class FakeCamera extends FlxCamera { // override function set_zoom(Zoom:Float):Float return zoom = (Zoom == 0) ? FlxCamera.defaultZoom : Zoom; public override function setScale(X:Float, Y:Float):Void {} +} + +class FakeCallCamera extends FakeCamera { + public static final instance = new FakeCallCamera(); + + public dynamic function onDraw(?frame:FlxFrame, ?pixels:BitmapData, matrix:FlxMatrix, ?transform:ColorTransform, ?blend:BlendMode, ?smoothing:Bool = false, ?shader:FlxShader, smooth:Bool = false, ?shader:FlxShader) { + } + + override function drawPixels(?frame:FlxFrame, ?pixels:BitmapData, matrix:FlxMatrix, ?transform:ColorTransform, ?blend:BlendMode, ?smoothing:Bool = false, ?shader:FlxShader) { + onDraw(frame, pixels, matrix, transform, blend, smoothing, shader); + } } \ No newline at end of file diff --git a/source/funkin/backend/utils/MatrixUtil.hx b/source/funkin/backend/utils/MatrixUtil.hx index 41cd5f1f..97e2d7a9 100644 --- a/source/funkin/backend/utils/MatrixUtil.hx +++ b/source/funkin/backend/utils/MatrixUtil.hx @@ -1,14 +1,30 @@ package funkin.backend.utils; +import flixel.graphics.frames.FlxFrame; import flixel.FlxCamera; import flixel.math.FlxPoint; import flixel.util.typeLimit.OneOfTwo; +import funkin.backend.system.FakeCamera; +import funkin.backend.system.FakeCamera.FakeCallCamera; +import flixel.graphics.FlxGraphic; +import flixel.graphics.frames.FlxFrame; +import flixel.graphics.tile.FlxDrawTrianglesItem; +import flixel.math.FlxMatrix; +import flixel.math.FlxPoint; +import flixel.system.FlxAssets.FlxShader; +import openfl.display.BitmapData; +import openfl.display.BlendMode; +import openfl.geom.ColorTransform; +import openfl.geom.Point; +import openfl.geom.Rectangle; interface IPrePostDraw { public function preDraw():Void; public function postDraw():Void; } +@:access(flixel.FlxCamera) +@:access(flixel.FlxSprite) final class MatrixUtil { public static function getMatrixPosition(sprite:FlxSprite, points:OneOfTwo>, ?camera:FlxCamera, _width:Float = 1, _height:Float = 1):Array { @@ -16,34 +32,70 @@ final class MatrixUtil { //if(_height == -1) _height = sprite.height; if(camera == null) camera = sprite.camera; if(points is FlxBasePoint) points = [points]; - var nc = funkin.backend.system.FakeCamera.instance; + var isFunkinSprite = sprite is FunkinSprite; + var funkinSprite:FunkinSprite = null; + if(isFunkinSprite) funkinSprite = cast sprite; + var isAnimateAtlas = isFunkinSprite && funkinSprite.animateAtlas != null; + + var nc:FakeCamera = isAnimateAtlas ? FakeCallCamera.instance : FakeCamera.instance; nc.zoom = camera.zoom; nc.scroll.set(camera.scroll.x, camera.scroll.y); nc.pixelPerfectRender = camera.pixelPerfectRender; - if(sprite is IPrePostDraw) { - var postDraw = cast(sprite, IPrePostDraw); - postDraw.preDraw(); - @:privateAccess sprite.drawComplex(nc); - postDraw.postDraw(); + + if(isAnimateAtlas) { + var nc = FakeCallCamera.instance; + var sprite = funkinSprite; + var oldOnDraw = nc.onDraw; + nc.onDraw = function(?frame:FlxFrame, ?pixels:BitmapData, matrix:FlxMatrix, ?transform:ColorTransform, ?blend:BlendMode, ?smoothing:Bool = false, ?shader:FlxShader, smooth:Bool = false, ?shader:FlxShader) { + // pixels is null + + } + var cameras = sprite.animateAtlas._cameras; + sprite.animateAtlas._cameras = [nc]; + if(sprite is IPrePostDraw) { + var postDraw = cast(sprite, IPrePostDraw); + postDraw.preDraw(); + @:privateAccess sprite.draw(); + postDraw.postDraw(); + } else { + @:privateAccess sprite.draw(); + } + sprite.animateAtlas._cameras = cameras; + nc.onDraw = oldOnDraw; } else { - @:privateAccess sprite.drawComplex(nc); + if(sprite is IPrePostDraw) { + var postDraw = cast(sprite, IPrePostDraw); + postDraw.preDraw(); + @:privateAccess sprite.drawComplex(nc); + postDraw.postDraw(); + } else { + @:privateAccess sprite.drawComplex(nc); + } } - var isFunkinSprite = sprite is FunkinSprite; - var points:Array = cast points; - @:privateAccess for(point in points) { - var x = sprite._matrix.__transformX(point.x * _width, point.y * _height); - var y = sprite._matrix.__transformY(point.x * _width, point.y * _height); + transformPoints(sprite, points, sprite._matrix, camera, _width, _height); + return points; + } + + /** + * Warning: modifies the points in the array + **/ + public static function transformPoints(sprite:FlxSprite, points:Array, matrix:FlxMatrix, ?camera:FlxCamera, _width:Float = 1, _height:Float = 1):Array { + var isFunkinSprite = sprite is FunkinSprite; + var funkinSprite:FunkinSprite = null; + if(isFunkinSprite) funkinSprite = cast sprite; + + for(point in points) { + var x = matrix.__transformX(point.x * _width, point.y * _height); + var y = matrix.__transformY(point.x * _width, point.y * _height); // reset to ingame coords x += camera.scroll.x; y += camera.scroll.y; if(isFunkinSprite) { - var sprite:FunkinSprite = cast sprite; - - var ratio = 1 - FlxMath.lerp(1 / camera.zoom, 1, sprite.zoomFactor); + var ratio = 1 - FlxMath.lerp(1 / camera.zoom, 1, funkinSprite.zoomFactor); x += camera.width / 2 * ratio; y += camera.height / 2 * ratio; } diff --git a/source/funkin/editors/character/CharacterAnimsWindow.hx b/source/funkin/editors/character/CharacterAnimsWindow.hx index 48980179..a3e67ea8 100644 --- a/source/funkin/editors/character/CharacterAnimsWindow.hx +++ b/source/funkin/editors/character/CharacterAnimsWindow.hx @@ -1,5 +1,6 @@ package funkin.editors.character; +import flixel.util.typeLimit.OneOfTwo; import funkin.backend.utils.XMLUtil.AnimData; import flixel.animation.FlxAnimation; import flixel.graphics.FlxGraphic; @@ -14,7 +15,7 @@ class CharacterAnimsWindow extends UIButtonList { public var displayWindowSprite:FlxSprite; public var displayWindowGraphic:FlxGraphic; - public var displayAnimsFramesList:Map = []; + public var displayAnimsFramesList:Map}> = []; public var animButtons:Map = []; public var animsList:Array = []; @@ -28,7 +29,7 @@ class CharacterAnimsWindow extends UIButtonList { buttonCameras.pixelPerfectRender = true; - if (Assets.exists(Paths.image('characters/${character.sprite}'))) + if (Assets.exists(Paths.image('characters/${character.sprite}')) && character.animateAtlas == null) displayWindowGraphic = FlxG.bitmap.add(Assets.getBitmapData(Paths.image('characters/${character.sprite}'), true, false)); displayWindowSprite = new FlxSprite(); @@ -53,16 +54,33 @@ class CharacterAnimsWindow extends UIButtonList { character.ghosts = ghosts; } - public function buildAnimDisplay(name:String, anim:FlxAnimation) { - if (anim.frames.length <= 0) return; + public function buildAnimDisplay(name:String, anim:AnimData) @:privateAccess { + if (character.animateAtlas == null) { + var anim:FlxAnimation = character.animation._animations[anim.name]; + if (anim == null || anim.frames.length <= 0) return; - var frameIndex:Int = anim.frames.getDefault([0])[0]; - var frame:FlxFrame = displayWindowSprite.frames.frames[frameIndex]; + var frameIndex:Int = anim.frames.getDefault([0])[0]; + var frame:FlxFrame = displayWindowSprite.frames.frames[frameIndex]; + + var frameRect:Rectangle = new Rectangle(frame.offset.x, frame.offset.y, frame.sourceSize.x, frame.sourceSize.y); + var animBounds:Rectangle = displayWindowGraphic != null ? displayWindowGraphic.bitmap.bounds(frameRect) : frameRect; + + displayAnimsFramesList.set(name, {frame: anim.frames.getDefault([0])[0], scale: 104/animBounds.height, animBounds: animBounds}); + } else { + var ogFrame:Int = character.animateAtlas.anim.curFrame; + var oldTick:Float = character.animateAtlas.anim._tick; + var oldPlaying:Bool = character.animateAtlas.anim.isPlaying; - var frameRect:Rectangle = new Rectangle(frame.offset.x, frame.offset.y, frame.sourceSize.x, frame.sourceSize.y); - var animBounds:Rectangle = displayWindowGraphic != null ? displayWindowGraphic.bitmap.bounds(frameRect) : frameRect; + character.animateAtlas.anim.play(anim.name, true, false, 0); + character.animateAtlas.anim.stop(); - displayAnimsFramesList.set(name, {frame: anim.frames.getDefault([0])[0], scale: 104/animBounds.height, animBounds: animBounds}); + var animBounds:Rectangle = MatrixUtil.getBounds(character).copyToFlash(); + displayAnimsFramesList.set(name, {frame: anim.anim, scale: 104/animBounds.height, animBounds: animBounds}); + + character.animateAtlas.anim.play(atlasPlayingAnim, true, false, ogFrame); + character.animateAtlas.anim._tick = oldTick; + character.animateAtlas.anim.isPlaying = oldPlaying; + } } public function removeAnimDisplay(name:String) diff --git a/source/funkin/editors/character/CharacterEditor.hx b/source/funkin/editors/character/CharacterEditor.hx index a0d38458..569b69c5 100644 --- a/source/funkin/editors/character/CharacterEditor.hx +++ b/source/funkin/editors/character/CharacterEditor.hx @@ -409,6 +409,7 @@ class CharacterEditor extends UIState { if(character.animateAtlas == null) { StageEditor.calcSpriteBounds(character); var bounds:FlxRect = cast character.extra.get(StageEditor.exID("bounds")); + trace(bounds); if (bounds.containsPoint(point)) { cameraHoverDummy.cursor = #if (mac) DRAG_OPEN; #else CLICK; #end if (FlxG.mouse.justPressed) diff --git a/source/funkin/editors/character/CharacterGhost.hx b/source/funkin/editors/character/CharacterGhost.hx index 906f3f13..d1aabfee 100644 --- a/source/funkin/editors/character/CharacterGhost.hx +++ b/source/funkin/editors/character/CharacterGhost.hx @@ -4,6 +4,13 @@ import openfl.geom.ColorTransform; import flixel.animation.FlxAnimation; import funkin.game.Character; +typedef AtlasState = { + var oldAnim:String; + var oldFrame:Int; + var oldTick:Float; + var oldPlaying:Bool; +}; + class CharacterGhost extends Character { public var ghosts:Array = []; public override function draw() @:privateAccess { @@ -67,4 +74,14 @@ class CharacterGhost extends Character { offset.set(globalOffset.x * (isPlayer != playerOffsets ? 1 : -1), -globalOffset.y); } + + var atlasState:AtlasState = null; + public function storeAtlasState():AtlasState { + return atlasState = { + oldAnim: atlasPlayingAnim, + oldFrame: animateAtlas.anim.curFrame, + oldTick: animateAtlas.anim._tick, + oldPlaying: animateAtlas.anim.isPlaying, + }; + } } \ No newline at end of file diff --git a/source/funkin/editors/stage/StageEditor.hx b/source/funkin/editors/stage/StageEditor.hx index b596eb7a..042711fa 100644 --- a/source/funkin/editors/stage/StageEditor.hx +++ b/source/funkin/editors/stage/StageEditor.hx @@ -1001,9 +1001,18 @@ class StageEditor extends UIState { } } - public static function calcSpriteBounds(sprite:FlxSprite) { + public static function calcSpriteBounds(sprite:FunkinSprite) { var oldWidth = sprite.width; var oldHeight = sprite.height; + + /* + if (sprite.animateAtlas != null) { + var rect:FlxRect = MatrixUtil.getBounds(sprite); + oldWidth = rect.width; + oldHeight = rect.height; + } + */ + var oldOffset = sprite.offset.clone(FlxPoint.weak()); var oldOrigin = sprite.origin.clone(FlxPoint.weak()); sprite.updateHitbox(); diff --git a/source/funkin/game/Stage.hx b/source/funkin/game/Stage.hx index 1a48d065..ab653653 100644 --- a/source/funkin/game/Stage.hx +++ b/source/funkin/game/Stage.hx @@ -409,7 +409,8 @@ class StageCharPos extends FlxObject { oldInfo = getOldInfo(char); char.setPosition(x + (id * charSpacingX), y + (id * charSpacingY)); char.scrollFactor.set(scrollFactor.x, scrollFactor.y); - char.scale.x *= scale.x; char.scale.y *= scale.y; + if (!char.debugMode) + char.scale.x *= scale.x; char.scale.y *= scale.y; char.cameraOffset += FlxPoint.weak(camxoffset, camyoffset); char.skew.x += skewX; char.skew.y += skewY; char.alpha *= alpha;