2022-03-08 03:13:53 -05:00
package funkin . animate ;
2021-09-01 15:34:20 -04:00
import haxe . format . JsonParser ;
import openfl . Assets ;
2021-09-11 09:37:04 -04:00
import openfl . geom . Matrix3D ;
import openfl . geom . Matrix ;
2022-04-18 15:00:12 -04:00
#if sys
2021-09-01 15:34:20 -04:00
import sys . io . File ;
2022-04-18 15:00:12 -04:00
#end
2021-09-01 15:34:20 -04:00
2021-09-02 16:56:46 -04:00
/ * *
* Generally designed / written in a way that can be easily taken out of FNF and used elsewhere
* I don ' t t h i n k i t e v e n h a s t i e s t o O p e n F L ? C o u l d p r o b a b l y j u s t u s e i t f o r A N Y h a x e
* project if n e e d e d , D O E S N E E D A L O T O F C L E A N U P T H O U G H !
* /
2021-09-01 15:34:20 -04:00
class ParseAnimate
{
// make list of frames needed to render (with ASI)
// make GIANT list of all the frames ever and have them in order?
public static var symbolMap: Map < String , Symbol > = new Map ( ) ;
public static var actualSprites: Map < String , Sprite > = new Map ( ) ;
2021-09-11 11:54:38 -04:00
private var _atlas: Map < String , Sprite > ;
private var _symbolData: Map < String , Symbol > ;
private var _defaultSymbolName: String ;
public function n e w ( data : AnimJson , atlas : Spritemap )
{
// bitmap data could prob be instead
// this code is mostly nabbed from https://github.com/miltoncandelero/OpenFLAnimateAtlas/blob/master/Source/animateatlas/displayobject/SpriteAnimationLibrary.hx
parseAnimationData ( data ) ;
parseAtlasData ( atlas ) ;
}
private function parseAnimationData ( data : AnimJson ) : Void
{
_symbolData = new Map ( ) ;
var symbols = data . SD . S ;
for ( symbol in symbols )
_symbolData [ symbol . SN ] = preprocessSymbolData ( symbol ) ;
var defaultSymbol: Symbol = preprocessSymbolData ( data . AN ) ;
_defaultSymbolName = defaultSymbol . SN ;
_symbolData . set ( _defaultSymbolName , defaultSymbol ) ;
}
// at little redundant, does exactly the same thing as genSpritemap()
private function parseAtlasData ( atlas : Spritemap ) : Void
{
_atlas = new Map < String , Sprite > ( ) ;
if ( atlas . ATLAS != null && atlas . ATLAS . SPRITES != null )
{
for ( s in atlas . ATLAS . SPRITES )
_atlas . set ( s . SPRITE . name , s . SPRITE ) ;
}
}
2021-09-02 16:56:46 -04:00
/ * *
* Not used , was used for t e s t i n g s t u f f t h o u g h !
* /
2021-09-01 15:34:20 -04:00
public static function init ( )
{
// Main.gids
var folder: String = ' t i g h t e s t B a r s ' ;
// var spritemap:Spritemap =
// var spritemap:Spritemap = genSpritemap('test/$folder/spritemap1.json');
actualSprites = genSpritemap ( ' t e s t / $ folder / s p r i t e m a p 1 . j s o n ' ) ;
var animation: AnimJson = cast CoolUtil . coolJSON ( Assets . getText ( ' s r c / $ folder / A n i m a t i o n . j s o n ' ) ) ;
generateSymbolmap ( animation . SD . S ) ;
trace ( " \n \n A N I M A T I O N S H I T \n " ) ;
var timelineLength: Int = 0 ;
for ( lyr in animation . AN . TL . L )
timelineLength = Std . int ( Math . max ( lyr . FR . length , timelineLength ) ) ;
var content: String = animation . AN . TL . L [ 0 ] . LN ;
content += " T O T A L F R A M E S N E E D E D : " + timelineLength + " \n " ;
for ( frm in 0 ... timelineLength )
{
trace ( ' F R A M E N U M B E R ' + frm ) ;
try
{
parseTimeline ( animation . AN . TL , 1 , frm ) ;
content += ' G o o d w r i t e o n f r a m e : ' + frm + " \n " ;
}
c atch ( e )
{
content += " B A D W R I T E : " + frm + " \n " ;
content += " \t " + e + " \n " ;
trace ( e ) ;
}
// File.saveContent("output.txt", content);
}
parseTimeline ( animation . AN . TL , 1 , 0 ) ;
trace ( actualSprites ) ;
}
/ * *
* a MAP of SPRITES , not to be confused with Spritemap ... lol
* /
public static function genSpritemap ( json : String ) : Map < String , Sprite >
{
var sprShitty: Spritemap = cast CoolUtil . coolJSON ( json ) ;
var sprMap: Map < String , Sprite > = new Map ( ) ;
for ( spr in sprShitty . ATLAS . SPRITES )
sprMap . set ( spr . SPRITE . name , spr . SPRITE ) ;
return sprMap ;
}
2021-09-11 11:54:38 -04:00
// should change dis to all private?
2021-09-01 15:34:20 -04:00
public static function generateSymbolmap ( symbols : Array < Symbol > )
{
for ( symbol in symbols )
{
// trace(symbol.SN + "has: " + symbol.TL.L.length + " LAYERS");
symbolMap . set ( symbol . SN , symbol ) ;
// parseTimeline(symbol.TL);
}
}
2021-09-11 11:54:38 -04:00
public static function preprocessSymbolData ( anim : Symbol ) : Symbol
{
var timelineData: Timeline = anim . TL ;
var layerData: Array < Layer > = timelineData . L ;
if ( ! timelineData . sortedForRender )
{
timelineData . sortedForRender = true ;
layerData . reverse ( ) ;
}
for ( layerStuff in layerData )
{
var frames: Array < Frame > = layerStuff . FR ;
for ( frame in frames )
{
var elements: Array < Element > = frame . E ;
for ( e in 0 ... elements . length )
{
var element: Element = elements [ e ] ;
if ( element . ASI != null )
{
element = elements [ e ] = {
SI : {
SN : " A T L A S _ S Y M B O L _ S P R I T E " ,
LP : " L P " ,
TRP : { x : 0 , y : 0 } ,
M3D : [ 1 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 1 ] ,
FF : 0 ,
ST : " G " ,
ASI : element . ASI
}
}
}
}
}
}
return anim ;
}
2021-09-01 15:34:20 -04:00
public static var curLoopType: String ;
/ * *
* Stuff for d e b u g p a r s i n g
* /
public static var depthTypeBeat: String = " " ;
2021-09-06 15:30:19 -04:00
/ * *
* Array of bullshit that will eventually be RENDERED by whoever wanna use it !
* /
2021-09-01 23:39:37 -04:00
public static var frameList: Array < Array < VALIDFRAME > > = [ ] ;
2021-09-01 15:34:20 -04:00
// for loop stuf
2021-09-01 23:39:37 -04:00
/ * *
* Similar to frameList , keeps track of shit according to framess ?
* That amount of arrays within arrays is fuckin dumb
* but innermost array is basically just x and y value , cuz im dum
* /
public static var matrixHelp: Array < Array < Array < Float > > > = [ ] ;
2021-09-11 09:37:04 -04:00
public static var trpHelpIDK: Array < Array < Array < Float > > > = [ ] ;
2021-09-01 15:34:20 -04:00
2021-09-01 20:37:37 -04:00
public static var loopedFrameShit: Int = 0 ;
2021-09-11 09:37:04 -04:00
public static var funnyMatrix: Matrix = new Matrix ( ) ;
public static var matrixFlipper: Array < Matrix > = [ ] ;
2021-09-06 15:30:19 -04:00
// clean up all the crazy ass arrays
2021-09-01 15:34:20 -04:00
public static function resetFrameList ( )
{
2021-09-11 09:37:04 -04:00
// funnyMatrix.identity();
2021-09-01 15:34:20 -04:00
frameList = [ ] ;
2021-09-01 20:04:07 -04:00
frameList . push ( [ ] ) ;
2021-09-01 23:39:37 -04:00
matrixHelp = [ ] ;
matrixHelp . push ( [ ] ) ;
2021-09-11 09:37:04 -04:00
trpHelpIDK = [ ] ;
trpHelpIDK . push ( [ ] ) ;
2021-09-01 15:34:20 -04:00
}
2021-09-11 09:37:04 -04:00
public static var isFlipped: Bool = false ;
2021-09-01 15:34:20 -04:00
public static function parseTimeline ( TL : Timeline , tabbed : Int = 0 , ? frameInput : Int )
{
var strTab: String = " " ;
for ( i in 0 ... tabbed )
strTab += ' \t ' ;
for ( layer in TL . L )
{
var frameArray: Array < Int > = [ ] ;
var frameMap: Map < Int , Frame > = new Map ( ) ;
for ( frms in layer . FR )
{
for ( i in 0 ... frms . DU )
frameArray . push ( frms . I ) ;
frameMap . set ( frms . I , frms ) ;
}
if ( frameInput == null )
frameInput = 0 ;
2021-09-01 20:37:37 -04:00
var oldFrm: Int = frameInput ;
2021-09-01 23:39:37 -04:00
/ *
if ( curLoopType == " S F " )
{
trace ( layer . LN ) ;
2021-09-01 20:37:37 -04:00
2021-09-01 23:39:37 -04:00
trace ( frameArray ) ;
trace ( frameInput ) ;
trace ( curLoopType ) ;
} * /
2021-09-01 20:37:37 -04:00
2021-09-01 15:34:20 -04:00
if ( curLoopType == " L P " )
frameInput = frameArray [ frameInput % frameArray . length ] ;
2021-09-01 20:37:37 -04:00
e lse if ( curLoopType == " S F " )
{
frameInput = frameArray [ loopedFrameShit ] ;
// see what happens when something has more than 2 layer?
2021-09-02 19:00:01 -04:00
// single frame stuff isn't fully implemented
2021-09-01 20:37:37 -04:00
}
2021-09-01 15:34:20 -04:00
e lse
frameInput = frameArray [ frameInput ] ;
2021-09-01 20:37:37 -04:00
// trace(frameMap.get(frameInput));
2021-09-01 15:34:20 -04:00
var frame: Frame = frameMap . get ( frameInput ) ;
2021-09-06 14:50:04 -04:00
// get somethin sorted per element list, which would essentially be per symbol things properly sorted
// seperate data types if symbol or atlassymbolinstance? would probably be maybe slightly less memory intensive? i dunno
// goes thru each layer, and then each element
// after it gets thru each element it adds to the layer frame stuff.
// make somethin that works recursively, maybe thats the symbol dictionary type shit?
2021-09-01 15:34:20 -04:00
for ( element in frame . E )
{
if ( Reflect . hasField ( element , " A S I " ) )
{
2021-09-01 23:39:37 -04:00
matrixHelp [ matrixHelp . length - 1 ] . push ( element . ASI . M3D ) ;
2021-09-11 09:37:04 -04:00
var m3D = element . ASI . M3D ;
var lilMatrix: Matrix = new Matrix ( m3D [ 0 ] , m3D [ 1 ] , m3D [ 4 ] , m3D [ 5 ] , m3D [ 12 ] , m3D [ 13 ] ) ;
matrixFlipper . push ( lilMatrix ) ;
// matrixFlipper.reverse();
// funnyMatrix.identity();
// for (m in matrixFlipper)
// funnyMatrix.concat(m);
if ( isFlipped )
{
trace ( " M O R E F L I P P E D S H I T " ) ;
trace ( " M O R E F L I P P E D S H I T " ) ;
trace ( " M O R E F L I P P E D S H I T " ) ;
trace ( funnyMatrix ) ;
trace ( matrixFlipper ) ;
}
// trace(funnyMatrix);
funnyMatrix . concat ( lilMatrix ) ;
// trace(funnyMatrix);
2021-09-01 23:39:37 -04:00
frameList [ frameList . length - 1 ] . push ( {
frameName : element . ASI . N ,
depthString : depthTypeBeat ,
2021-09-06 15:30:19 -04:00
matrixArray : matrixHelp [ matrixHelp . length - 1 ] ,
2021-09-11 09:37:04 -04:00
trpArray : trpHelpIDK [ trpHelpIDK . length - 1 ] ,
fullMatrix : funnyMatrix . clone ( )
2021-09-01 23:39:37 -04:00
} ) ;
2021-09-01 15:34:20 -04:00
2021-09-01 20:04:07 -04:00
// flips the matrix once?? I cant remember exactly why it needs to be flipped
2021-09-01 23:39:37 -04:00
// matrixHelp[matrixHelp.length - 1].reverse();
2021-09-01 20:04:07 -04:00
2021-09-11 09:37:04 -04:00
// trpHelpIDK = [];
// push the matrix array after each symbol?
funnyMatrix . identity ( ) ;
matrixFlipper = [ ] ;
2021-09-01 20:04:07 -04:00
2021-09-01 15:34:20 -04:00
depthTypeBeat = " " ;
curLoopType = " " ;
2021-09-01 20:37:37 -04:00
loopedFrameShit = 0 ;
2021-09-11 09:37:04 -04:00
isFlipped = false ;
2021-09-01 15:34:20 -04:00
}
e lse
{
2021-09-11 09:37:04 -04:00
var m3D = element . SI . M3D ;
var lilMatrix: Matrix = new Matrix ( m3D [ 0 ] , m3D [ 1 ] , m3D [ 4 ] , m3D [ 5 ] , m3D [ 12 ] , m3D [ 13 ] ) ;
if ( lilMatrix . a == - 1 )
{
isFlipped = true ;
trace ( ' I S T H E N E G A T I V E O N E ' ) ;
}
if ( isFlipped )
trace ( lilMatrix ) ;
funnyMatrix . concat ( lilMatrix ) ;
matrixFlipper . push ( lilMatrix ) ;
// trace(funnyMatrix);
2021-09-01 23:39:37 -04:00
matrixHelp [ matrixHelp . length - 1 ] . push ( element . SI . M3D ) ;
2021-09-11 09:37:04 -04:00
trpHelpIDK [ trpHelpIDK . length - 1 ] . push ( [ element . SI . TRP . x , element . SI . TRP . y ] ) ; // trpHelpIDK.push();
2021-09-01 15:34:20 -04:00
depthTypeBeat += " - > " + element . SI . SN ;
curLoopType = element . SI . LP ;
2021-09-01 20:37:37 -04:00
var inputFrame: Int = element . SI . FF ;
2021-09-02 19:00:01 -04:00
// JANKY FIX, MAY NOT ACCOUNT FOR ALL SCENARIOS OF SINGLE FRAME ANIMATIONS!!
2021-09-01 20:37:37 -04:00
if ( curLoopType == " S F " )
{
2021-09-01 23:39:37 -04:00
// trace("LOOP SHIT: " + inputFrame);
2021-09-01 20:37:37 -04:00
loopedFrameShit = inputFrame ;
}
2021-09-06 14:50:04 -04:00
// condense the animation code, so it automatically already fills up animation shit per symbol
2021-09-01 20:37:37 -04:00
parseTimeline ( symbolMap . get ( element . SI . SN ) . TL , tabbed + 1 , inputFrame ) ;
2021-09-01 15:34:20 -04:00
}
2021-09-11 09:37:04 -04:00
// idk if this should go per layer or per element / object?
matrixHelp . push ( [ ] ) ;
trpHelpIDK . push ( [ ] ) ;
2021-09-01 15:34:20 -04:00
}
2021-09-01 20:04:07 -04:00
2021-09-06 14:50:04 -04:00
if ( tabbed == 0 )
{
frameList [ frameList . length - 1 ] . reverse ( ) ;
frameList . push ( [ ] ) ; // new layer essentially
}
2021-09-01 15:34:20 -04:00
}
2021-09-01 20:04:07 -04:00
frameList . reverse ( ) ;
2021-09-01 15:34:20 -04:00
}
}
2021-09-01 23:39:37 -04:00
typedef VALIDFRAME =
{
frameName : String ,
depthString : String ,
2021-09-06 15:30:19 -04:00
matrixArray : Array < Array < Float >> ,
2021-09-11 09:37:04 -04:00
trpArray : Array < Array < Float >> ,
fullMatrix : Matrix
2021-09-01 23:39:37 -04:00
}
2021-09-01 15:34:20 -04:00
typedef AnimJson =
{
AN : Animation ,
SD : SymbolDictionary ,
MD : MetaData
}
typedef Animation =
{
N : String ,
SN : String ,
TL : Timeline
}
typedef SymbolDictionary =
{
S : Array < Symbol >
}
typedef Symbol =
{
/**Symbol name*/
SN : String ,
TL : Timeline
}
typedef Timeline =
{
2021-09-11 11:54:38 -04:00
? sortedForRender : Bool ,
2021-09-01 15:34:20 -04:00
L : Array < Layer >
}
typedef Layer =
{
LN : String ,
FR : Array < Frame >
}
typedef Frame =
{
E : Array < Element > ,
I : Int ,
DU : Int
2021-09-11 11:54:38 -04:00
// maybe need to implement names if it has frame labels?
2021-09-01 15:34:20 -04:00
}
typedef Element =
{
SI : SymbolInstance ,
2021-09-11 11:54:38 -04:00
? ASI : AlsoSymbolInstance
2021-09-01 15:34:20 -04:00
// lmfao idk what ASI stands for lmfaoo, i dont think its "also"
}
typedef SymbolInstance =
{
SN : String ,
2021-09-11 11:54:38 -04:00
ASI : AlsoSymbolInstance ,
2021-09-01 15:34:20 -04:00
2021-09-01 23:39:37 -04:00
/**Symbol type, prob either G (graphic), or movie clip?*/ ST : String ,
2021-09-01 15:34:20 -04:00
2021-09-01 23:39:37 -04:00
/**First frame*/ FF : Int ,
2021-09-01 15:34:20 -04:00
2021-09-01 23:39:37 -04:00
/**Loop type, loop ping pong, etc.*/ LP : String ,
2021-09-01 15:34:20 -04:00
2021-09-01 23:39:37 -04:00
/**3D matrix*/ M3D : Array < Float > ,
2021-09-01 15:34:20 -04:00
TRP :
{
x : Float , y : Float
}
}
typedef AlsoSymbolInstance =
{
N : String ,
M3D : Array < Float >
}
typedef MetaData =
{
/ * *
* Framerate
* /
FRT : Int
}
// SPRITEMAP BULLSHIT
typedef Spritemap =
{
ATLAS :
{
SPRITES : Array < SpriteBullshit >
} ,
meta : Meta
}
typedef SpriteBullshit =
{
SPRITE : Sprite
}
typedef Sprite =
{
name : String ,
x : Int ,
y : Int ,
w : Int ,
h : Int ,
rotated : Bool
}
typedef Meta =
{
app : String ,
verstion : String ,
image : String ,
format : String ,
size :
{
w : Int , h : Float
} ,
resolution : Float
}