I BROKE THE OFFSETS FUCK

.
This commit is contained in:
Yoshman29
2026-01-18 21:43:47 +01:00
parent 246014af60
commit 0c8b766b19
17 changed files with 96 additions and 531 deletions
-92
View File
@@ -1,92 +0,0 @@
package funkin.backend;
import flixel.graphics.frames.FlxFrame;
import flixel.math.FlxAngle;
import flixel.math.FlxMatrix;
import openfl.display.BlendMode;
import openfl.geom.ColorTransform;
class FlxAnimate extends flxanimate.FlxAnimate {
static var rMatrix = new FlxMatrix();
override function drawLimb(limb:FlxFrame, _rMatrix:FlxMatrix, ?colorTransform:ColorTransform, ?blendMode:BlendMode)
{
if (alpha == 0 || colorTransform != null && (colorTransform.alphaMultiplier == 0 || colorTransform.alphaOffset == -255) || limb == null || limb.type == EMPTY)
return;
if (blendMode == null)
blendMode = BlendMode.NORMAL;
for (camera in cameras)
{
rMatrix.identity();
limb.prepareMatrix(rMatrix, FlxFrameAngle.ANGLE_0, _checkFlipX() != camera.flipX, _checkFlipY() != camera.flipY);
rMatrix.concat(_rMatrix);
if (!camera.visible || !camera.exists || !limbOnScreen(limb, _rMatrix, camera))
return;
getScreenPosition(_point, camera).subtractPoint(offset);
rMatrix.translate(-origin.x, -origin.y);
if (limb != _pivot) {
if (frameOffsetAngle != null && frameOffsetAngle != angle)
{
var angleOff = (frameOffsetAngle - angle) * FlxAngle.TO_RAD;
var cos = Math.cos(angleOff);
var sin = Math.sin(angleOff);
// cos doesn't need to be negated
rMatrix.rotateWithTrig(cos, -sin);
rMatrix.translate(-frameOffset.x, -frameOffset.y);
rMatrix.rotateWithTrig(cos, sin);
}
else
{
rMatrix.translate(-frameOffset.x, -frameOffset.y);
}
rMatrix.scale(scale.x, scale.y);
if (!matrixExposed && bakedRotationAngle <= 0)
{
updateTrig();
if (angle != 0)
rMatrix.rotateWithTrig(_cosAngle, _sinAngle);
}
}
else
rMatrix.a = rMatrix.d = 0.7 / camera.zoom;
if (matrixExposed)
{
rMatrix.concat(transformMatrix);
}
else
{
rMatrix.concat(@:privateAccess flxanimate.FlxAnimate._skewMatrix);
}
_point.addPoint(origin);
if (isPixelPerfectRender(camera))
{
_point.floor();
}
rMatrix.translate(_point.x, _point.y);
camera.drawPixels(limb, null, rMatrix, colorTransform, blendMode, antialiasing, shaderEnabled ? shader : null);
#if FLX_DEBUG
FlxBasic.visibleCount++;
#end
}
// doesn't work, needs to be remade
// #if FLX_DEBUG
// if (FlxG.debugger.drawDebug)
// drawDebug();
// #end
}
override function limbOnScreen(limb:FlxFrame, m:FlxMatrix, ?Camera:FlxCamera)
{
// TODO: ACTUAL OPTIMIZATION
return true;
}
}
+27 -109
View File
@@ -1,5 +1,7 @@
package funkin.backend;
import animate.FlxAnimate;
import animate.FlxAnimateController.FlxAnimateAnimation;
import flixel.addons.effects.FlxSkewedSprite;
import flixel.animation.FlxAnimation;
import flixel.math.FlxMatrix;
@@ -43,7 +45,7 @@ enum abstract XMLAnimType(Int)
}
}
class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements IOffsetCompatible implements IXMLEvents
class FunkinSprite extends FlxAnimate implements IBeatReceiver implements IOffsetCompatible implements IXMLEvents
{
public var extra:Map<String, Dynamic> = [];
@@ -66,10 +68,6 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
public var beatOffset:Int = 0;
public var skipNegativeBeats:Bool = false;
public var animateAtlas:FlxAnimate;
@:noCompletion public var atlasPlayingAnim:String;
@:noCompletion public var atlasPath:String;
var _rect2:FlxRect;
public function new(?X:Float = 0, ?Y:Float = 0, ?SimpleGraphic:FlxGraphicAsset)
@@ -85,6 +83,7 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
}
moves = false;
applyStageMatrix = true;
}
/**
@@ -100,8 +99,6 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
@:privateAccess {
spr.setPosition(source.x, source.y);
spr.frames = source.frames;
if (casted != null && casted.animateAtlas != null && casted.atlasPath != null)
spr.loadSprite(casted.atlasPath);
spr.animation.copyFrom(source.animation);
spr.visible = source.visible;
spr.alpha = source.alpha;
@@ -111,8 +108,6 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
if (casted != null) {
spr.skew.set(casted.skew.x, casted.skew.y);
spr.transformMatrix = casted.transformMatrix;
spr.matrixExposed = casted.matrixExposed;
spr.animOffsets = casted.animOffsets.copy();
spr.zoomFactor = casted.zoomFactor;
}
@@ -123,8 +118,6 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
public override function update(elapsed:Float)
{
super.update(elapsed);
if (animateAtlas != null)
animateAtlas.update(elapsed);
// hate how it looks like but hey at least its optimized and fast - Nex
if (!debugMode && isAnimFinished()) {
@@ -142,15 +135,7 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
public function loadSprite(path:String, Unique:Bool = false, Key:String = null)
{
var noExt = Path.withoutExtension(path);
if (Assets.exists('$noExt/Animation.json'))
{
atlasPath = noExt;
animateAtlas = new FlxAnimate(x, y, noExt);
}
else
{
frames = Paths.getFrames(path, true);
}
frames = Paths.getFrames(path, true);
return this;
}
@@ -182,48 +167,9 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
// ANIMATE ATLAS DRAWING
#if REGION
public override function draw()
{
if (animateAtlas != null)
{
copyAtlasValues();
animateAtlas.draw();
}
else
{
super.draw();
}
}
public function copyAtlasValues()
{
@:privateAccess {
animateAtlas.cameras = cameras; // investigate if we can use _cameras
animateAtlas.scrollFactor = scrollFactor;
animateAtlas.scale = scale;
animateAtlas.offset = offset;
animateAtlas.frameOffset = frameOffset;
animateAtlas.x = x;
animateAtlas.y = y;
animateAtlas.angle = angle;
animateAtlas.alpha = alpha;
animateAtlas.visible = visible;
animateAtlas.flipX = flipX;
animateAtlas.flipY = flipY;
animateAtlas.shader = shader;
animateAtlas.shaderEnabled = shaderEnabled;
animateAtlas.antialiasing = antialiasing;
animateAtlas.skew = skew;
animateAtlas.transformMatrix = transformMatrix;
animateAtlas.matrixExposed = matrixExposed;
animateAtlas.colorTransform = colorTransform;
}
}
public override function destroy()
{
animateAtlas = FlxDestroyUtil.destroy(animateAtlas);
if (animOffsets != null) {
for (key in animOffsets.keys()) {
final point = animOffsets[key];
@@ -340,13 +286,7 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
Force = anim != null && anim.forced;
}
if (animateAtlas != null)
{
@:privateAccess
animateAtlas.anim.play(AnimName, Force, Reversed, Frame);
atlasPlayingAnim = AnimName;
}
else animation.play(AnimName, Force, Reversed, Frame);
animation.play(AnimName, Force, Reversed, Frame);
var daOffset = getAnimOffset(AnimName);
frameOffset.set(daOffset.x, daOffset.y);
@@ -370,18 +310,11 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
});
}
public inline function removeAnim(name:String)
{
if (animateAtlas != null)
@:privateAccess animateAtlas.anim.animsMap.remove(name);
else
animation.remove(name);
public inline function removeAnim(name:String) {
animation.remove(name);
}
public function getAnim(name:String):OneOfTwo<FlxAnimation, FlxSymbolAnimation>
{
if(animateAtlas != null)
return animateAtlas.anim.getByName(name);
public function getAnim(name:String):OneOfTwo<FlxAnimation, FlxAnimateAnimation> {
return animation.getByName(name);
}
@@ -392,40 +325,26 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
return FlxPoint.weak(0, 0);
}
public inline function hasAnim(AnimName:String):Bool @:privateAccess
return animateAtlas != null ? (animateAtlas.anim.animsMap.exists(AnimName)
|| animateAtlas.anim.symbolDictionary.exists(AnimName)) : animation.exists(AnimName);
public inline function hasAnim(AnimName:String):Bool
return animation.exists(AnimName);
public inline function getAnimName() {
return (animateAtlas != null) ? atlasPlayingAnim : animation.name;
}
public inline function getAnimName()
return animation.name;
public inline function isAnimReversed():Bool {
return animateAtlas != null ? animateAtlas.anim.reversed : animation.curAnim != null ? animation.curAnim.reversed : false;
}
public inline function isAnimReversed():Bool
return animation.curAnim?.reversed ?? false;
public inline function getNameList():Array<String> {
if (animateAtlas != null)
return [for (name in @:privateAccess animateAtlas.anim.animsMap.keys()) name];
else
return animation.getNameList();
}
public inline function getNameList():Array<String>
return animation.getNameList();
public inline function stopAnim()
{
if (animateAtlas != null)
animateAtlas.anim.pause();
else
animation.stop();
}
animation.stop();
public inline function isAnimFinished() {
return animateAtlas != null ? animateAtlas.anim.finished : (animation.curAnim != null ? animation.curAnim.finished : true);
}
public inline function isAnimFinished()
return animation.curAnim?.finished ?? true;
public inline function isAnimAtEnd() {
return animateAtlas != null ? animateAtlas.anim.isAtEnd : (animation.curAnim != null ? animation.curAnim.isAtEnd : false);
}
public inline function isAnimAtEnd()
return animation.curAnim?.isAtEnd ?? false;
override function updateAnimation(elapsed:Float) {
if (animEnabled)
@@ -447,10 +366,9 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
return beatInterval = v;
}
@:noCompletion private inline function get_globalCurFrame() {
return animateAtlas != null ? (animateAtlas.anim.curFrame) : (animation.curAnim != null ? animation.curAnim.curFrame : 0);
}
@:noCompletion private inline function set_globalCurFrame(val:Int) {
return animateAtlas != null ? (animateAtlas.anim.curFrame = val) : (animation.curAnim != null ? animation.curAnim.curFrame = val : val);
}
@:noCompletion private inline function get_globalCurFrame()
return animation.curAnim?.curFrame ?? 0;
@:noCompletion private inline function set_globalCurFrame(val:Int)
return animation.curAnim?.curFrame ?? 0;
}
+2 -6
View File
@@ -114,12 +114,8 @@ class MusicBeatTransition extends MusicBeatSubstate {
}
if (transitionSprite != null) {
if (transitionSprite.animateAtlas == null) {
transitionSprite.setGraphicSize(transitionCamera.width, transitionCamera.height);
transitionSprite.updateHitbox();
} else {
transitionSprite.screenCenter();
}
transitionSprite.setGraphicSize(transitionCamera.width, transitionCamera.height);
transitionSprite.updateHitbox();
}
}
+6
View File
@@ -8,6 +8,7 @@ import funkin.backend.scripting.Script;
import haxe.io.Path;
import lime.utils.AssetLibrary;
import openfl.utils.Assets as OpenFlAssets;
import animate.FlxAnimateFrames;
using StringTools;
@@ -174,6 +175,9 @@ class Paths
inline static public function getSparrowAtlas(key:String, ?library:String, ?ext:String)
return FlxAtlasFrames.fromSparrow(image(key, library, ext), file('images/$key.xml', library));
inline static public function getAnimateAtlasAlt(key:String)
return FlxAnimateFrames.fromAnimate(key);
inline static public function getSparrowAtlasAlt(key:String, ?ext:String)
return FlxAtlasFrames.fromSparrow('$key.${ext != null ? ext : Flags.IMAGE_EXT}', '$key.xml');
@@ -263,6 +267,8 @@ class Paths
cur++;
}
return finalFrames;
} else if (Assets.exists('$noExt/Animation.json')) {
return Paths.getAnimateAtlasAlt(noExt);
} else if (Assets.exists('$noExt.xml')) {
return Paths.getSparrowAtlasAlt(noExt, ext);
} else if (Assets.exists('$noExt.txt')) {
+1 -1
View File
@@ -91,7 +91,7 @@ class Script extends FlxBasic implements IFlxDestroyable {
"FunkinShader" => funkin.backend.shaders.FunkinShader,
"CustomShader" => funkin.backend.shaders.CustomShader,
"FunkinText" => funkin.backend.FunkinText,
"FlxAnimate" => funkin.backend.FlxAnimate,
"FlxAnimate" => animate.FlxAnimate,
"FunkinSprite" => funkin.backend.FunkinSprite,
"Alphabet" => funkin.menus.ui.Alphabet,
"Flags" => funkin.backend.system.Flags,
@@ -23,7 +23,7 @@ class Macros {
#if VIDEO_CUTSCENES "hxvlc.flixel", "hxvlc.openfl", #end
#if NAPE_ENABLED "nape", "flixel.addons.nape", #end
// BASE HAXE
"DateTools", "EReg", "Lambda", "StringBuf", "haxe.crypto", "haxe.display", "haxe.exceptions", "haxe.extern", "scripting"
"DateTools", "EReg", "Lambda", "StringBuf", "haxe.crypto", "haxe.display", "haxe.exceptions", "haxe.extern", "scripting", "animate"
])
Compiler.include(inc);
+1 -4
View File
@@ -1265,10 +1265,7 @@ final class CoolUtil
}
public static function getAnimsListFromSprite(spr:FunkinSprite):Array<String> {
if (spr.animateAtlas != null) {
return [for (symbol => timeline in spr.animateAtlas.anim.symbolDictionary) symbol];
} else
return getAnimsListFromFrames(spr.frames);
return getAnimsListFromFrames(spr.frames);
}
// TODO: check this for bugs
+8 -136
View File
@@ -34,151 +34,23 @@ final class MatrixUtil {
//if(_height == -1) _height = sprite.height;
if(camera == null) camera = sprite.camera;
if(points is FlxBasePoint) points = [points];
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;
var nc:FakeCamera = FakeCamera.instance;
nc.zoom = camera.zoom;
nc.scroll.set(camera.scroll.x, camera.scroll.y);
nc.pixelPerfectRender = camera.pixelPerfectRender;
var points:Array<FlxPoint> = cast points;
if(isAnimateAtlas) {
var cnc = FakeCallCamera.instance;
var sprite = funkinSprite;
var oldOnDraw = cnc.onDraw;
// TODO: fix rotation
// TODO: fix skew
var boundsTopLeft = new FlxPoint(Math.POSITIVE_INFINITY, Math.POSITIVE_INFINITY);
var boundsTopRight = new FlxPoint(Math.NEGATIVE_INFINITY, Math.POSITIVE_INFINITY);
var boundsBottomLeft = new FlxPoint(Math.POSITIVE_INFINITY, Math.NEGATIVE_INFINITY);
var boundsBottomRight = new FlxPoint(Math.NEGATIVE_INFINITY, Math.NEGATIVE_INFINITY);
cnc.onDraw = function(?frame:FlxFrame, ?pixels:BitmapData, matrix:FlxMatrix, ?transform:ColorTransform, ?blend:BlendMode, ?smoothing:Bool = false, ?shader:FlxShader) {
// cnc is already perfect rn
// so we need to manually process the limb
var points = [
// corners
FlxPoint.get(0, 0),
FlxPoint.get(1, 0),
FlxPoint.get(0, 1),
FlxPoint.get(1, 1)
];
rawTransformPoints(points, matrix, frame.sourceSize.x, frame.sourceSize.y);
// sort the points, incase like they were transformed with a scale -1 matrix
var topLeft:FlxPoint = points[0];
var topRight:FlxPoint = points[1];
var bottomLeft:FlxPoint = points[2];
var bottomRight:FlxPoint = points[3];
if (points[0].y > points[1].y) {
topLeft = points[1];
topRight = points[0];
}
if (points[2].y > points[3].y) {
bottomLeft = points[3];
bottomRight = points[2];
}
if (topLeft.x > topRight.x) {
var temp = topLeft;
topLeft = topRight;
topRight = temp;
}
if (bottomLeft.x > bottomRight.x) {
var temp = bottomLeft;
bottomLeft = bottomRight;
bottomRight = temp;
}
// points should now contain the corners of the limb
// trace("Corners of limb: " + points);
// set the max bounds of each corner of the limb
if(topLeft.x < boundsTopLeft.x) boundsTopLeft.x = topLeft.x;
if(topLeft.y < boundsTopLeft.y) boundsTopLeft.y = topLeft.y;
if(topRight.x > boundsTopRight.x) boundsTopRight.x = topRight.x;
if(topRight.y < boundsTopRight.y) boundsTopRight.y = topRight.y;
if(bottomLeft.x < boundsBottomLeft.x) boundsBottomLeft.x = bottomLeft.x;
if(bottomLeft.y > boundsBottomLeft.y) boundsBottomLeft.y = bottomLeft.y;
if(bottomRight.x > boundsBottomRight.x) boundsBottomRight.x = bottomRight.x;
if(bottomRight.y > boundsBottomRight.y) boundsBottomRight.y = bottomRight.y;
// recycle the points
for(point in points) point.put();
}
var cameras = sprite._cameras;
var oldVisible = cnc.visible;
cnc.visible = true;
sprite._cameras = [cnc];
sprite.draw();
sprite._cameras = cameras;
cnc.visible = oldVisible;
cnc.onDraw = oldOnDraw;
// fake transform
//trace("");
//trace("topLeft: " + boundsTopLeft);
//trace("topRight: " + boundsTopRight);
//trace("bottomLeft: " + boundsBottomLeft);
//trace("bottomRight: " + boundsBottomRight);
//trace("Before transform");
//trace(points);
for(point in points) {
//var x = matrix.__transformX(point.x * _width, point.y * _height);
//var y = matrix.__transformY(point.x * _width, point.y * _height);
// apply using boundsTopLeft, boundsTopRight, boundsBottomLeft, boundsBottomRight
// matrix doesnt work for this
var x = FlxMath.lerp(
FlxMath.lerp(boundsTopLeft.x, boundsTopRight.x, point.x),
FlxMath.lerp(boundsBottomLeft.x, boundsBottomRight.x, point.x),
point.y
);
var y = FlxMath.lerp(
FlxMath.lerp(boundsTopLeft.y, boundsTopRight.y, point.x),
FlxMath.lerp(boundsBottomLeft.y, boundsBottomRight.y, point.x),
point.y
);
//trace("(" + point.x + ", " + point.y + ") -> (" + x + ", " + y + ")");
// reset to ingame coords
x += camera.scroll.x;
y += camera.scroll.y;
if(isFunkinSprite) {
var ratio = 1 - FlxMath.lerp(1 / camera.zoom, 1, funkinSprite.zoomFactor);
x += camera.width / 2 * ratio;
y += camera.height / 2 * ratio;
}
point.set(x, y);
}
//trace("After transform");
//trace(points);
if(sprite is IPrePostDraw) {
var postDraw = cast(sprite, IPrePostDraw);
postDraw.preDraw();
sprite.drawComplex(nc);
postDraw.postDraw();
} else {
if(sprite is IPrePostDraw) {
var postDraw = cast(sprite, IPrePostDraw);
postDraw.preDraw();
sprite.drawComplex(nc);
postDraw.postDraw();
} else {
sprite.drawComplex(nc);
}
transformPoints(sprite, points, sprite._matrix, camera, _width, _height);
sprite.drawComplex(nc);
}
transformPoints(sprite, points, sprite._matrix, camera, _width, _height);
return points;
}
+8 -2
View File
@@ -14,6 +14,7 @@ import funkin.backend.scripting.ScriptPack;
import flixel.util.typeLimit.OneOfTwo;
import funkin.backend.system.interfaces.IOffsetCompatible;
import haxe.xml.Access;
import animate.FlxAnimateFrames;
using StringTools;
@@ -127,6 +128,10 @@ final class XMLUtil {
spr.spriteAnimType = XMLAnimType.fromString(node.att.type, spr.spriteAnimType);
}
if (node.has.applyStageMatrix) {
spr.applyStageMatrix = node.att.applyStageMatrix == "true";
}
if(node.has.x) {
var x:Null<Float> = Std.parseFloat(node.att.x);
if (x.isNotNull()) spr.x = x;
@@ -299,11 +304,12 @@ final class XMLUtil {
if (animData.name != null) {
if (animData.fps <= 0 #if web || animData.fps == null #end) animData.fps = 24;
if (sprite is FunkinSprite && cast(sprite, FunkinSprite).animateAtlas != null) {
var animateAnim = cast(sprite, FunkinSprite).animateAtlas.anim;
if (sprite.frames is FlxAnimateFrames) {
if(animData.anim == null)
return MISSING_PROPERTY;
var animateAnim = cast(sprite, FunkinSprite).anim;
if (animData.indices != null && animData.indices.length > 0)
animateAnim.addBySymbolIndices(animData.name, animData.anim, animData.indices, animData.fps, animData.loop);
else