Funkin/source/animate/FlxSymbol.hx

418 lines
9.4 KiB
Haxe
Raw Normal View History

2021-04-14 11:31:52 -04:00
package animate;
2021-04-15 23:13:52 -04:00
import flixel.FlxCamera;
2021-04-14 11:31:52 -04:00
import flixel.FlxSprite;
2021-04-15 23:13:52 -04:00
import flixel.graphics.frames.FlxFrame.FlxFrameAngle;
2021-04-14 11:31:52 -04:00
import flixel.math.FlxAngle;
2021-06-18 14:18:56 -04:00
import flixel.math.FlxMath;
2021-04-15 23:13:52 -04:00
import flixel.math.FlxMatrix;
import flixel.math.FlxPoint;
2021-06-22 15:41:15 -04:00
import lime.system.System;
2021-04-15 23:13:52 -04:00
import openfl.geom.Matrix;
2021-04-14 11:31:52 -04:00
class FlxSymbol extends FlxSprite
{
public var coolParse:Parsed;
public var oldMatrix:Array<Float> = [];
// Loop types shit
public static inline var LOOP:String = 'LP';
public static inline var PLAY_ONCE:String = 'PO';
public static inline var SINGLE_FRAME:String = 'SF';
2021-08-21 13:19:56 -04:00
/**
* This gets set in some nest animation bullshit in animation render code
*/
public var firstFrame:Int = 0;
public var daLoopType:String = 'LP'; // LP by default, is set below!!!
2021-04-14 11:31:52 -04:00
public function new(x:Float, y:Float, coolParsed:Parsed)
{
super(x, y);
2021-06-22 15:41:15 -04:00
// trace(System.deviceModel);
// trace(System.deviceVendor);
// trace(System.platformLabel);
// trace(System.platformName);
2021-04-14 11:31:52 -04:00
this.coolParse = coolParsed;
var hasSymbolDictionary:Bool = Reflect.hasField(coolParse, "SD");
if (hasSymbolDictionary)
symbolAtlasShit = parseSymbolDictionary(coolParse);
}
var symbolAtlasShit:Map<String, String> = new Map();
2021-04-15 11:57:59 -04:00
public static var nestedShit:Map<Int, Array<FlxSymbol>> = new Map();
2021-04-14 11:31:52 -04:00
var symbolMap:Map<String, Animation> = new Map();
2021-04-14 21:52:43 -04:00
public var daFrame:Int = 0;
2021-04-15 23:13:52 -04:00
public var transformMatrix:Matrix = new Matrix();
2021-06-15 17:43:46 -04:00
function renderFrame(TL:Timeline, coolParsed:Parsed, ?traceShit:Bool = false)
2021-04-14 11:31:52 -04:00
{
for (layer in TL.L)
{
2021-06-15 21:15:06 -04:00
if (FlxG.keys.justPressed.TWO)
trace(layer.LN);
2021-04-14 21:52:43 -04:00
// layer.FR.reverse();
2021-04-14 11:31:52 -04:00
// for (frame in layer.FR)
// {
2021-08-21 13:19:56 -04:00
var keyFrames:Array<Int> = [];
var keyFrameMap:Map<Int, Frame> = new Map();
// probably dumb to generate this every single frame for every layer?
// prob want to generate it first when loading
for (frm in layer.FR)
{
keyFrameMap[frm.I] = frm;
keyFrames.push(frm.I);
for (thing in 0...frm.DU - 1)
keyFrames.push(frm.I);
}
if (FlxG.keys.justPressed.THREE)
{
trace(layer.LN);
trace(keyFrames);
}
var newFrameNum:Int = daFrame;
2021-08-21 19:53:08 -04:00
// need to account for movie clip / Graphic bullshit?
switch (daLoopType)
2021-04-14 11:31:52 -04:00
{
case LOOP:
var tempFrame = layer.FR[newFrameNum + firstFrame % layer.FR.length];
2021-08-20 11:01:37 -04:00
// trace(tempFrame);
2021-06-18 14:18:56 -04:00
// newFrameNum += firstFrame;
// newFrameNum = newFrameNum % (tempFrame.I + tempFrame.DU);
// newFrameNum = FlxMath.wrap(newFrameNum, tempFrame.I, tempFrame.I + tempFrame.DU);
2021-08-21 13:19:56 -04:00
trace(newFrameNum % keyFrames.length);
trace(newFrameNum);
trace(keyFrames);
newFrameNum = keyFrames[newFrameNum % keyFrames.length]; // temp, fix later for good looping
case PLAY_ONCE:
2021-08-21 13:19:56 -04:00
trace(newFrameNum);
trace(keyFrames.length - 1);
trace(keyFrameMap.get(newFrameNum + firstFrame));
trace(keyFrameMap.get(keyFrames[keyFrames.length - 1]));
trace(layer.LN);
trace(keyFrames);
newFrameNum = Std.int(Math.min(newFrameNum + firstFrame, keyFrames.length - 1));
case SINGLE_FRAME:
2021-08-21 13:19:56 -04:00
trace(layer);
trace(firstFrame);
trace(newFrameNum);
trace(layer.LN);
trace(keyFrames);
newFrameNum = keyFrames[firstFrame];
}
2021-06-18 14:18:56 -04:00
// trace(daLoopType);
// trace(newFrameNum);
// trace(layer.FR.length);
2021-06-18 14:18:56 -04:00
// trace(newFrameNum % layer.FR.length);
2021-08-21 13:19:56 -04:00
// var swagFrame:Frame = layer.FR[newFrameNum % layer.FR.length]; // has modulo just in case????
// doesnt actually use position in the array?3
var swagFrame:Frame = keyFrameMap.get(newFrameNum);
// get frame by going through
// if (newFrameNum >= frame.I && newFrameNum < frame.I + frame.DU)
// {
2021-08-21 13:19:56 -04:00
trace(daLoopType);
for (element in swagFrame.E)
{
if (Reflect.hasField(element, 'ASI'))
2021-04-14 11:31:52 -04:00
{
var m3d = element.ASI.M3D;
var dumbassMatrix:Matrix = new Matrix(m3d[0], m3d[1], m3d[4], m3d[5], m3d[12], m3d[13]);
2021-04-14 11:31:52 -04:00
var spr:FlxSymbol = new FlxSymbol(0, 0, coolParsed);
matrixExposed = true;
spr.frames = frames;
spr.frame = spr.frames.getByName(element.ASI.N);
2021-04-15 23:13:52 -04:00
// dumbassMatrix.translate(origin.x, origin.y);
2021-04-14 11:31:52 -04:00
dumbassMatrix.concat(_matrix);
spr.matrixExposed = true;
spr.transformMatrix.concat(dumbassMatrix);
// spr._matrix.concat(spr.transformMatrix);
2021-04-14 11:31:52 -04:00
spr.origin.set();
// Prob dont need these offset thingies???
// spr.origin.x += origin.x;
// spr.origin.y += origin.y;
2021-04-14 11:31:52 -04:00
spr.antialiasing = true;
// if (layer.LN != 'head')
spr.draw();
2021-04-14 11:31:52 -04:00
if (FlxG.keys.justPressed.ONE)
{
trace("ASI - " + layer.LN + ": " + element.ASI.N);
}
}
else
{
var nestedSymbol = symbolMap.get(element.SI.SN);
var nestedShit:FlxSymbol = new FlxSymbol(0, 0, coolParse);
nestedShit.frames = frames;
2021-04-14 11:31:52 -04:00
var swagMatrix:FlxMatrix = new FlxMatrix(element.SI.M3D[0], element.SI.M3D[1], element.SI.M3D[4], element.SI.M3D[5], element.SI.M3D[12],
element.SI.M3D[13]);
2021-06-15 21:15:06 -04:00
swagMatrix.concat(_matrix);
2021-06-15 21:15:06 -04:00
nestedShit._matrix.concat(swagMatrix);
nestedShit.origin.set(element.SI.TRP.x, element.SI.TRP.y);
// nestedShit.angle += ((180 / Math.PI) * Math.atan2(swagMatrix.b, swagMatrix.a));
// nestedShit.angle += angle;
2021-04-14 11:31:52 -04:00
if (symbolAtlasShit.exists(nestedSymbol.SN))
{
// nestedShit.frames.getByName(symbolAtlasShit.get(nestedSymbol.SN));
// nestedShit.draw();
}
// scale.y = Math.sqrt(_matrix.c * _matrix.c + _matrix.d * _matrix.d);
// scale.x = Math.sqrt(_matrix.a * _matrix.a + _matrix.b * _matrix.b);
// nestedShit.oldMatrix = element.SI.M3D;
if (FlxG.keys.justPressed.ONE)
{
trace("SI - " + layer.LN + ": " + element.SI.SN + " - LOOP TYPE: " + element.SI.LP);
2021-04-14 21:52:43 -04:00
}
nestedShit.firstFrame = element.SI.FF;
// nestedShit.daFrame += nestedShit.firstFrame;
nestedShit.daLoopType = element.SI.LP;
nestedShit.daFrame = daFrame;
2021-06-22 15:41:15 -04:00
nestedShit.scrollFactor.set(1, 1);
nestedShit.renderFrame(nestedSymbol.TL, coolParsed);
// renderFrame(nestedSymbol.TL, coolParsed);
2021-04-14 11:31:52 -04:00
}
}
// }
// }
2021-04-14 11:31:52 -04:00
}
2021-04-15 11:57:59 -04:00
}
2021-04-14 21:52:43 -04:00
function changeFrame(frameChange:Int = 0):Void
{
daFrame += frameChange;
}
2021-04-14 11:31:52 -04:00
function parseSymbolDictionary(coolParsed:Parsed):Map<String, String>
{
var awesomeMap:Map<String, String> = new Map();
for (symbol in coolParsed.SD.S)
{
symbolMap.set(symbol.SN, symbol);
var symbolName = symbol.SN;
2021-06-18 14:18:56 -04:00
// one time reverse?
symbol.TL.L.reverse();
2021-04-14 11:31:52 -04:00
for (layer in symbol.TL.L)
{
for (frame in layer.FR)
{
for (element in frame.E)
{
if (Reflect.hasField(element, 'ASI'))
{
awesomeMap.set(symbolName, element.ASI.N);
}
}
}
}
}
return awesomeMap;
}
2021-04-15 23:13:52 -04:00
2021-08-21 13:19:56 -04:00
function getFrame() {}
2021-04-15 23:13:52 -04:00
override function drawComplex(camera:FlxCamera):Void
{
_frame.prepareMatrix(_matrix, FlxFrameAngle.ANGLE_0, checkFlipX(), checkFlipY());
_matrix.translate(-origin.x, -origin.y);
_matrix.scale(scale.x, scale.y);
if (matrixExposed)
{
_matrix.concat(transformMatrix);
}
else
{
if (bakedRotationAngle <= 0)
{
updateTrig();
if (angle != 0)
_matrix.rotateWithTrig(_cosAngle, _sinAngle);
}
// updateSkewMatrix();
_matrix.concat(_skewMatrix);
}
_point.addPoint(origin);
if (isPixelPerfectRender(camera))
_point.floor();
_matrix.translate(_point.x, _point.y);
camera.drawPixels(_frame, framePixels, _matrix, colorTransform, blend, antialiasing);
}
var _skewMatrix:Matrix = new Matrix();
// public var transformMatrix(default, null):Matrix = new Matrix();
/**
* Bool flag showing whether transformMatrix is used for rendering or not.
* False by default, which means that transformMatrix isn't used for rendering
*/
public var matrixExposed:Bool = false;
public var skew(default, null):FlxPoint = FlxPoint.get();
function updateSkewMatrix():Void
{
_skewMatrix.identity();
if (skew.x != 0 || skew.y != 0)
{
_skewMatrix.b = Math.tan(skew.y * FlxAngle.TO_RAD);
_skewMatrix.c = Math.tan(skew.x * FlxAngle.TO_RAD);
}
}
2021-04-14 11:31:52 -04:00
}
// TYPEDEFS FOR ANIMATION.JSON PARSING
typedef Parsed =
{
var MD:Metadata;
var AN:Animation;
var SD:SymbolDictionary; // Doesn't always have symbol dictionary!!
}
typedef Metadata =
{
/** Framerate */
var FRT:Int;
}
/** Basically treated like one big symbol*/
typedef Animation =
{
/** symbolName */
var SN:String;
var TL:Timeline;
/** IDK what STI stands for, Symbole Type Instance?
Anyways, it is NOT used in SYMBOLS, only the main AN animation
*/
var STI:Dynamic;
}
/** DISCLAIMER, MAY NOT ACTUALLY BE CALLED
SYMBOL TYPE ISNTANCE, IM JUST MAKING ASSUMPTION!! */
typedef SymbolTypeInstance =
{
// var TL:Timeline;
// var SN:String;
}
typedef SymbolDictionary =
{
var S:Array<Animation>;
}
typedef Timeline =
{
/** Layers */
var L:Array<Layer>;
}
// Singular layer, not to be confused with LAYERS
typedef Layer =
{
var LN:String;
/** Frames */
var FR:Array<Frame>;
}
typedef Frame =
{
2021-06-18 14:18:56 -04:00
/** Frame index*/
2021-04-14 11:31:52 -04:00
var I:Int;
/** Duration, in frames*/
var DU:Int;
/** Elements*/
var E:Array<Element>;
}
typedef Element =
{
var SI:SymbolInstance;
var ASI:AtlasSymbolInstance;
}
/**
Symbol instance, for SYMBOLS and refers to SYMBOLS
*/
typedef SymbolInstance =
{
var SN:String;
/** SymbolType (Graphic, Movieclip, Button)*/
var ST:String;
/** First frame*/
var FF:Int;
/** Loop type (Loop, play once, single frame)*/
var LP:String;
2021-04-14 11:31:52 -04:00
var TRP:TransformationPoint;
var M3D:Array<Float>;
}
typedef AtlasSymbolInstance =
{
var N:String;
var M3D:Array<Float>;
}
typedef TransformationPoint =
{
var x:Float;
var y:Float;
}