diff --git a/source/funkin/backend/FunkinSprite.hx b/source/funkin/backend/FunkinSprite.hx index 5a7d01997..dea05a8d6 100644 --- a/source/funkin/backend/FunkinSprite.hx +++ b/source/funkin/backend/FunkinSprite.hx @@ -56,10 +56,12 @@ class FunkinSprite extends FlxAnimate implements IBeatReceiver implements IOffse public var beatAnims:Array = []; public var name:String; public var zoomFactor:Float = 1; + public var angleFactor:Float = 1; public var debugMode:Bool = false; public var animDatas:Map = []; public var animEnabled:Bool = true; public var zoomFactorEnabled:Bool = true; + public var angleFactorEnabled:Bool = true; //Backwards compatibility public var animateAtlas(get, never):FunkinSprite; @@ -118,6 +120,7 @@ class FunkinSprite extends FlxAnimate implements IBeatReceiver implements IOffse spr.skew.set(casted.skew.x, casted.skew.y); spr.animOffsets = casted.animOffsets.copy(); spr.zoomFactor = casted.zoomFactor; + spr.angleFactor = casted.angleFactor; } } return spr; @@ -239,6 +242,13 @@ class FunkinSprite extends FlxAnimate implements IBeatReceiver implements IOffse return camera.containsRect(bounds); } + private inline function __shouldDoAngleFactor() + return angleFactorEnabled && angleFactor != 1; + + private inline function __prepareAngleFactor(camera:FlxCamera):Float { + return FlxMath.lerp(-camera.angle, 0, angleFactor); + } + // OFFSETTING #if REGION public var animOffsets:Map = new Map(); @@ -365,17 +375,25 @@ class FunkinSprite extends FlxAnimate implements IBeatReceiver implements IOffse return val; } - override function prepareDrawMatrix(matrix:FlxMatrix, camera:FlxCamera):Void { + override function prepareDrawMatrix(matrix:FlxMatrix, camera:FlxCamera):Void { super.prepareDrawMatrix(matrix, camera); - if (__shouldDoZoomFactor()) { + if (__shouldDoZoomFactor() || __shouldDoAngleFactor()) { __prepareZoomFactor(_rect2, camera); - matrix.setTo( - matrix.a * _rect2.width, matrix.b * _rect2.height, - matrix.c * _rect2.width, matrix.d * _rect2.height, - (matrix.tx - _rect2.x) * _rect2.width + _rect2.x, - (matrix.ty - _rect2.y) * _rect2.height + _rect2.y, - ); + + if (__shouldDoZoomFactor()) { + matrix.setTo( + matrix.a * _rect2.width, matrix.b * _rect2.height, + matrix.c * _rect2.width, matrix.d * _rect2.height, + (matrix.tx - _rect2.x) * _rect2.width + _rect2.x, + (matrix.ty - _rect2.y) * _rect2.height + _rect2.y + ); + } + if (__shouldDoAngleFactor()) { + matrix.translate(-_rect2.x, -_rect2.y); + matrix.rotate(FlxAngle.asRadians(__prepareAngleFactor(camera))); + matrix.translate(_rect2.x, _rect2.y); + } } } @@ -385,4 +403,4 @@ class FunkinSprite extends FlxAnimate implements IBeatReceiver implements IOffse override function checkFlipY() { return super.checkFlipY() != camera.flipY; } -} +} \ No newline at end of file diff --git a/source/funkin/backend/FunkinText.hx b/source/funkin/backend/FunkinText.hx index 5bde26cb4..1a41e1bc2 100644 --- a/source/funkin/backend/FunkinText.hx +++ b/source/funkin/backend/FunkinText.hx @@ -9,90 +9,141 @@ import funkin.backend.system.Flags; class FunkinText extends FlxText { - public var zoomFactor:Float = 1; - public var zoomFactorEnabled:Bool = true; - - public function new(X:Float = 0, Y:Float = 0, FieldWidth:Float = 0, ?Text:String, ?Size:Int, Border:Bool = true) - { - if (Size == null) - Size = Flags.DEFAULT_FONT_SIZE; - - super(X, Y, FieldWidth, Text, Size); - - setFormat(Paths.font(Flags.DEFAULT_FONT), Size, FlxColor.WHITE); - - if (Border) - { - borderStyle = OUTLINE; - borderSize = 1; - borderColor = 0xFF000000; - } - } - - private inline function __shouldDoZoomFactor():Bool - { - return zoomFactorEnabled && zoomFactor != 1; - } - - private inline function __getZoomScaleX(camera:FlxCamera):Float - { - return (camera.scaleX > 0 ? Math.max : Math.min)(0, FlxMath.lerp(1 / camera.scaleX, 1, zoomFactor)); - } - - private inline function __getZoomScaleY(camera:FlxCamera):Float - { - return (camera.scaleY > 0 ? Math.max : Math.min)(0, FlxMath.lerp(1 / camera.scaleY, 1, zoomFactor)); - } - - private inline function __getZoomAnchorX(camera:FlxCamera):Float - { - if (Flags.USE_LEGACY_ZOOM_FACTOR) - return camera.width * 0.5; - - return camera.width * 0.5 + camera.scroll.x * scrollFactor.x; - } - - private inline function __getZoomAnchorY(camera:FlxCamera):Float - { - if (Flags.USE_LEGACY_ZOOM_FACTOR) - return camera.height * 0.5; - - return camera.height * 0.5 + camera.scroll.y * scrollFactor.y; - } - - override public function draw():Void - { - if (!__shouldDoZoomFactor()) - { - super.draw(); - return; - } - - var camera:FlxCamera = this.camera; - - if (camera == null) - camera = FlxG.camera; - - var oldX:Float = x; - var oldY:Float = y; - var oldScaleX:Float = scale.x; - var oldScaleY:Float = scale.y; - - var zoomScaleX:Float = __getZoomScaleX(camera); - var zoomScaleY:Float = __getZoomScaleY(camera); - - var anchorX:Float = __getZoomAnchorX(camera); - var anchorY:Float = __getZoomAnchorY(camera); - - x = (x - anchorX) * zoomScaleX + anchorX; - y = (y - anchorY) * zoomScaleY + anchorY; - - scale.set(scale.x * zoomScaleX, scale.y * zoomScaleY); - - super.draw(); - - x = oldX; - y = oldY; - scale.set(oldScaleX, oldScaleY); - } + public var zoomFactor:Float = 1; + public var zoomFactorEnabled:Bool = true; + public var angleFactor:Float = 1; + public var angleFactorEnabled:Bool = true; + + public function new(X:Float = 0, Y:Float = 0, FieldWidth:Float = 0, ?Text:String, ?Size:Int, Border:Bool = true) + { + if (Size == null) + Size = Flags.DEFAULT_FONT_SIZE; + + super(X, Y, FieldWidth, Text, Size); + + setFormat(Paths.font(Flags.DEFAULT_FONT), Size, FlxColor.WHITE); + + if (Border) + { + borderStyle = OUTLINE; + borderSize = 1; + borderColor = 0xFF000000; + } + } + + private inline function __shouldDoZoomFactor():Bool + { + return zoomFactorEnabled && zoomFactor != 1; + } + + private inline function __getZoomScaleX(camera:FlxCamera):Float + { + return (camera.scaleX > 0 ? Math.max : Math.min)(0, FlxMath.lerp(1 / camera.scaleX, 1, zoomFactor)); + } + + private inline function __getZoomScaleY(camera:FlxCamera):Float + { + return (camera.scaleY > 0 ? Math.max : Math.min)(0, FlxMath.lerp(1 / camera.scaleY, 1, zoomFactor)); + } + + private inline function __getZoomAnchorX(camera:FlxCamera):Float + { + if (Flags.USE_LEGACY_ZOOM_FACTOR) + return camera.width * 0.5 - origin.x; + + return camera.width * 0.5 + camera.scroll.x * scrollFactor.x - origin.x; + } + + private inline function __getZoomAnchorY(camera:FlxCamera):Float + { + if (Flags.USE_LEGACY_ZOOM_FACTOR) + return camera.height * 0.5 - origin.y; + + return camera.height * 0.5 + camera.scroll.y * scrollFactor.y - origin.y; + } + + private inline function __getAngleAnchorX(camera:FlxCamera):Float + { + if (Flags.USE_LEGACY_ZOOM_FACTOR) + return camera.width * 0.5 - origin.x; + + return camera.width * 0.5 + camera.scroll.x * scrollFactor.x - origin.x; + } + + private inline function __getAngleAnchorY(camera:FlxCamera):Float + { + if (Flags.USE_LEGACY_ZOOM_FACTOR) + return camera.height * 0.5 - origin.y; + + return camera.height * 0.5 + camera.scroll.y * scrollFactor.y - origin.y; + } + + private inline function __shouldDoAngleFactor():Bool + { + return angleFactorEnabled && angleFactor != 1; + } + + private inline function __prepareAngleFactor(camera:FlxCamera):Float + { + return FlxMath.lerp(-camera.angle, 0, angleFactor); + } + + override public function draw():Void + { + if (!__shouldDoZoomFactor() && !__shouldDoAngleFactor()) + { + super.draw(); + return; + } + + var camera:FlxCamera = this.camera; + + if (camera == null) + camera = FlxG.camera; + + var oldX:Float = x; + var oldY:Float = y; + var oldScaleX:Float = scale.x; + var oldScaleY:Float = scale.y; + var oldAngle:Float = angle; + + if (__shouldDoZoomFactor()) + { + var zoomScaleX:Float = __getZoomScaleX(camera); + var zoomScaleY:Float = __getZoomScaleY(camera); + + var anchorX:Float = __getZoomAnchorX(camera); + var anchorY:Float = __getZoomAnchorY(camera); + + x = (x - anchorX) * zoomScaleX + anchorX; + y = (y - anchorY) * zoomScaleY + anchorY; + + scale.set(scale.x * zoomScaleX, scale.y * zoomScaleY); + } + + if (__shouldDoAngleFactor()) + { + var anchorX:Float = __getAngleAnchorX(camera); + var anchorY:Float = __getAngleAnchorY(camera); + var prepAngle:Float = __prepareAngleFactor(camera); + + var rad:Float = prepAngle * (Math.PI / 180); + var cos:Float = Math.cos(rad); + var sin:Float = Math.sin(rad); + + var dx:Float = x - anchorX; + var dy:Float = y - anchorY; + + x = dx * cos - dy * sin + anchorX; + y = dx * sin + dy * cos + anchorY; + angle += prepAngle; + } + + super.draw(); + + x = oldX; + y = oldY; + scale.set(oldScaleX, oldScaleY); + angle = oldAngle; + } } \ No newline at end of file