diff --git a/art/flashFiles/Alphabet_Bold.fla b/art/flashFiles/Alphabet_Bold.fla
index a4bb2f4b..7a2559f9 100644
Binary files a/art/flashFiles/Alphabet_Bold.fla and b/art/flashFiles/Alphabet_Bold.fla differ
diff --git a/assets/data/alphabet.xml b/assets/data/alphabet.xml
index 281b7f18..a265c95a 100644
--- a/assets/data/alphabet.xml
+++ b/assets/data/alphabet.xml
@@ -28,6 +28,7 @@
+
diff --git a/assets/images/menus/alphabet-bold.png b/assets/images/menus/alphabet-bold.png
index ecc22cae..73e7110d 100644
Binary files a/assets/images/menus/alphabet-bold.png and b/assets/images/menus/alphabet-bold.png differ
diff --git a/assets/images/menus/alphabet-bold.xml b/assets/images/menus/alphabet-bold.xml
index 481bc3a4..742b3b86 100644
--- a/assets/images/menus/alphabet-bold.xml
+++ b/assets/images/menus/alphabet-bold.xml
@@ -2,108 +2,112 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/buildnumber.txt b/buildnumber.txt
index 1f3f6d91..721b63db 100644
--- a/buildnumber.txt
+++ b/buildnumber.txt
@@ -1 +1 @@
-2582
\ No newline at end of file
+2596
\ No newline at end of file
diff --git a/source/animateatlas/displayobject/SpriteAnimationLibrary.hx b/source/animateatlas/displayobject/SpriteAnimationLibrary.hx
index 2f835ab4..6eab5ae2 100644
--- a/source/animateatlas/displayobject/SpriteAnimationLibrary.hx
+++ b/source/animateatlas/displayobject/SpriteAnimationLibrary.hx
@@ -100,7 +100,6 @@ class SpriteAnimationLibrary {
}
// # region Pooling
- // todo migrate this to lime pool
@:access(animateatlas)
@:allow(AtlasFrameMaker)
diff --git a/source/animateatlas/displayobject/SpriteSymbol.hx b/source/animateatlas/displayobject/SpriteSymbol.hx
index 42ea0273..a433fdc6 100644
--- a/source/animateatlas/displayobject/SpriteSymbol.hx
+++ b/source/animateatlas/displayobject/SpriteSymbol.hx
@@ -307,7 +307,7 @@ class SpriteSymbol extends Sprite {
sMatrix.setTo(data.m00, data.m01, data.m10, data.m11, data.m30, data.m31);
if (sMatrix.a != transform.matrix.a || sMatrix.b != transform.matrix.b || sMatrix.c != transform.matrix.c || sMatrix.d != transform.matrix.d
|| sMatrix.tx != transform.matrix.tx || sMatrix.ty != transform.matrix.ty)
- transform.matrix = sMatrix.clone(); // todo stop the cloning :(
+ transform.matrix = sMatrix.clone();
}
private function setColor(data:ColorData):Void {
diff --git a/source/animateatlas/tilecontainer/TileAnimationLibrary.hx b/source/animateatlas/tilecontainer/TileAnimationLibrary.hx
index 008f0e36..62490962 100644
--- a/source/animateatlas/tilecontainer/TileAnimationLibrary.hx
+++ b/source/animateatlas/tilecontainer/TileAnimationLibrary.hx
@@ -102,7 +102,6 @@ class TileAnimationLibrary {
}
// # region Pooling
- // todo migrate this to lime pool
@:access(animateatlas)
private function getSymbol(name:String):TileContainerSymbol {
diff --git a/source/flxanimate/frames/FlxAnimateFrames.hx b/source/flxanimate/frames/FlxAnimateFrames.hx
new file mode 100644
index 00000000..b61a3282
--- /dev/null
+++ b/source/flxanimate/frames/FlxAnimateFrames.hx
@@ -0,0 +1,619 @@
+package flxanimate.frames;
+import flixel.graphics.frames.FlxFramesCollection;
+import flxanimate.data.AnimationData.OneOfTwo;
+import openfl.geom.Rectangle;
+import flxanimate.data.SpriteMapData.Meta;
+import haxe.io.Bytes;
+import flxanimate.zip.Zip;
+import haxe.io.BytesInput;
+import flixel.math.FlxMatrix;
+import flixel.FlxG;
+import flixel.graphics.FlxGraphic;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.graphics.frames.FlxFrame.FlxFrameAngle;
+import flixel.math.FlxPoint;
+import flixel.math.FlxRect;
+import flxanimate.data.SpriteMapData.AnimateAtlas;
+import flxanimate.data.SpriteMapData.AnimateSpriteData;
+import openfl.Assets;
+import openfl.display.BitmapData;
+import flixel.system.FlxAssets.FlxGraphicAsset;
+#if haxe4
+import haxe.xml.Access;
+#else
+import haxe.xml.Fast as Access;
+#end
+import flixel.graphics.frames.FlxFrame;
+
+class FlxAnimateFrames extends FlxAtlasFrames
+{
+ public function new()
+ {
+ super(null);
+ parents = [];
+ }
+ static var data:AnimateAtlas = null;
+ static var zip:Null>;
+
+ public var parents:Array;
+ /**
+ * Parses the spritemaps into small sprites to use in the animation.
+ *
+ * @param Path Where the Sprites are, normally you use it once when calling FlxAnimate already
+ * @return new sliced limbs for you to use ;)
+ */
+ public static function fromTextureAtlas(Path:String):FlxAtlasFrames
+ {
+ var frames:FlxAnimateFrames = new FlxAnimateFrames();
+
+ if (zip != null || haxe.io.Path.extension(Path) == "zip")
+ {
+ #if html5
+ FlxG.log.error("Zip Stuff isn't supported on Html5 since it can't transform bytes into an image");
+ return null;
+ #end
+ var imagemap:Map = new Map();
+ var jsonMap:Map = new Map();
+ var thing = (zip != null) ? zip : Zip.unzip(Zip.readZip(Assets.getBytes(Path)));
+ for (list in thing)
+ {
+ if (haxe.io.Path.extension(list.fileName) == "json")
+ {
+ jsonMap.set(list.fileName,haxe.Json.parse(StringTools.replace(list.data.toString(), String.fromCharCode(0xFEFF), "")));
+ }
+ else if (haxe.io.Path.extension(list.fileName) == "png")
+ {
+ var name = list.fileName.split("/");
+ imagemap.set(name[name.length - 1], list.data);
+ }
+ }
+ // Assuming the json has the same stuff as the image stuff
+ for (curJson in jsonMap)
+ {
+ var curImage = BitmapData.fromBytes(imagemap[curJson.meta.image]);
+ if (curImage != null)
+ {
+ for (sprites in curJson.ATLAS.SPRITES)
+ {
+ frames.pushFrame(textureAtlasHelper(curImage, sprites.SPRITE, curJson.meta));
+ }
+ }
+ else
+ FlxG.log.error('the Image called "${curJson.meta.image}" isnt in this zip file!');
+ }
+ zip == null;
+ }
+ else
+ {
+ if (Assets.exists('$Path/spritemap.json'))
+ {
+ var curJson:AnimateAtlas = haxe.Json.parse(StringTools.replace(Assets.getText('$Path/spritemap.json'), String.fromCharCode(0xFEFF), ""));
+ var graphic = FlxG.bitmap.add('$Path/${curJson.meta.image}');
+ if (graphic != null)
+ {
+ var spritemapFrames = new FlxAnimateFrames();
+ spritemapFrames.parent = graphic;
+ for (curSprite in curJson.ATLAS.SPRITES)
+ spritemapFrames.pushFrame(textureAtlasHelper(graphic.bitmap,curSprite.SPRITE, curJson.meta));
+ graphic.addFrameCollection(spritemapFrames);
+ frames.concat(spritemapFrames);
+ }
+ else
+ FlxG.log.error('the image called "${curJson.meta.image}" does not exist in Path $Path, maybe you changed the image Path somewhere else?');
+ }
+ var i = 1;
+ while (Assets.exists('$Path/spritemap$i.json'))
+ {
+ var curJson:AnimateAtlas = haxe.Json.parse(StringTools.replace(Assets.getText('$Path/spritemap$i.json'), String.fromCharCode(0xFEFF), ""));
+ var graphic = FlxG.bitmap.add('$Path/${curJson.meta.image}');
+ if (graphic != null)
+ {
+ var spritemapFrames = new FlxAnimateFrames();
+ spritemapFrames.parent = graphic;
+ for (curSprite in curJson.ATLAS.SPRITES)
+ spritemapFrames.pushFrame(textureAtlasHelper(graphic.bitmap,curSprite.SPRITE, curJson.meta));
+ graphic.addFrameCollection(spritemapFrames);
+ frames.concat(spritemapFrames);
+ }
+ else
+ FlxG.log.error('the image called "${curJson.meta.image}" does not exist in Path $Path, maybe you changed the image Path somewhere else?');
+ i++;
+ }
+ }
+ if (frames.frames == [])
+ {
+ FlxG.log.error("the Frames parsing couldn't parse any of the frames, it's completely empty! \n Maybe you misspelled the Path?");
+ return null;
+ }
+ return frames;
+ }
+ public function concat(frames:FlxFramesCollection)
+ {
+ if (parents.indexOf(frames.parent) == -1)
+ parents.push(frames.parent);
+ for (frame in frames.frames)
+ {
+ this.frames.push(frame);
+ framesHash.set(frame.name, frame);
+ }
+ }
+ /**
+ * Sparrow spritesheet format parser with support of both of the versions and making the image completely optional to you.
+ * @param Path The direction of the Xml you want to parse.
+ * @param Image (Optional) the image of the Xml.
+ * @return A new instance of `FlxAtlasFrames`
+ */
+ public static function fromSparrow(Path:FlxSparrow, ?Image:FlxGraphicAsset):FlxAtlasFrames
+ {
+ if ((Path is String) && !Assets.exists(Path))
+ return null;
+
+ var data:Access = new Access((Path is String) ? Xml.parse(Assets.getText(Path)).firstElement() : Path.firstElement());
+ if (Image == null)
+ {
+ if ((Path is String))
+ {
+ var splitDir = Path.split("/");
+ splitDir.pop();
+ splitDir.push(data.att.imagePath);
+ Image = splitDir.join("/");
+ }
+ else
+ return null;
+ }
+ var graphic:FlxGraphic = FlxG.bitmap.add(Image);
+ if (graphic == null)
+ return null;
+
+ // No need to parse data again
+ var frames:FlxAtlasFrames = FlxAtlasFrames.findFrame(graphic);
+ if (frames != null)
+ return frames;
+
+ frames = new FlxAtlasFrames(graphic);
+
+ for (texture in data.nodes.SubTexture)
+ {
+ var version2 = texture.has.width;
+ var name = texture.att.name;
+ var trimmed = texture.has.frameX;
+ var width = (version2) ? texture.att.width : texture.att.w;
+ var height = (version2) ? texture.att.height : texture.att.h;
+ var rotated = (texture.has.rotated && texture.att.rotated == "true");
+ var flipX = (texture.has.flipX && texture.att.flipX == "true");
+ var flipY = (texture.has.flipY && texture.att.flipY == "true");
+
+ var rect = FlxRect.get(Std.parseFloat(texture.att.x), Std.parseFloat(texture.att.y), Std.parseFloat(width),
+ Std.parseFloat(height));
+
+ var size = (trimmed) ? new FlxRect(Std.parseInt(texture.att.frameX), Std.parseInt(texture.att.frameY), Std.parseInt(texture.att.frameWidth),
+ Std.parseInt(texture.att.frameHeight)) : new FlxRect(0, 0, rect.width, rect.height);
+
+ var angle = rotated ? FlxFrameAngle.ANGLE_NEG_90 : FlxFrameAngle.ANGLE_0;
+
+ var offset = FlxPoint.get(-size.left, -size.top);
+ var ImageSize = FlxPoint.get(size.width, size.height);
+
+ if (rotated && !trimmed)
+ ImageSize.set(size.height, size.width);
+
+ frames.addAtlasFrame(rect, ImageSize, offset, name, angle, flipX, flipY);
+ }
+
+ return frames;
+ }
+ /**
+ *
+ * @param Path the Json in specific, can be the path of it or the actual json
+ * @param Image the image which the file is referencing **WARNING:** if you set the path as a json, it's obligatory to set the image!
+ * @return A new instance of `FlxAtlasFrames`
+ */
+ public static function fromJson(Path:FlxJson, ?Image:FlxGraphicAsset):FlxAtlasFrames
+ {
+ if ((Path is String) && !Assets.exists(Path))
+ return null;
+ var data:JsonNormal = (Path is String) ? haxe.Json.parse(Assets.getText(Path)) : Path;
+ if (Image == null)
+ {
+ if ((Path is String))
+ {
+ var splitDir = Path.split("/");
+ splitDir.pop();
+ splitDir.push(data.meta.image);
+ Image = splitDir.join("/");
+ }
+ else
+ {
+ FlxG.log.error("The Path isn't a String but a Json, you need to set an image if you use Jsons!");
+ return null;
+ }
+ }
+
+ var graphic:FlxGraphic = FlxG.bitmap.add(Image);
+ if (graphic == null)
+ return null;
+
+ // No need to parse data again
+ var frames:FlxAtlasFrames = FlxAtlasFrames.findFrame(graphic);
+ if (frames != null)
+ return frames;
+
+ frames = new FlxAtlasFrames(graphic);
+
+ // JSON-Array
+ if ((data.frames is Array))
+ {
+ for (frame in Lambda.array(data.frames))
+ {
+ texturePackerHelper(frame.filename, frame, frames);
+ }
+ }
+ // JSON-Hash
+ else
+ {
+ for (frameName in Reflect.fields(data.frames))
+ {
+ texturePackerHelper(frameName, Reflect.field(data.frames, frameName), frames);
+ }
+ }
+
+ return frames;
+ }
+ /**
+ * Edge Animate
+ * @param Path the Path of the .eas
+ * @param Image (Optional) the Image
+ * @return Cute little Frames to use ;)
+ */
+ public static function fromEdgeAnimate(Path:String, ?Image:FlxGraphicAsset):FlxAtlasFrames
+ {
+ return fromJson((StringTools.startsWith(Path, "{")) ? haxe.Json.parse(Path) : Path, Image);
+ }
+ /**
+ * Starling spritesheet format parser which uses a preference list from Mac computer shit
+ * @param Path the dir of the preference list
+ * @param Image (Optional) the Image
+ * @return Some recently cooked Frames for you ;)
+ */
+ public static function fromStarling(Path:FlxPropertyList, ?Image:FlxGraphicAsset):FlxAtlasFrames
+ {
+ if ((Path is String) && !Assets.exists(Path))
+ return null;
+ var data:Plist = (Path is String) ? PropertyList.parse(Assets.getText(Path)) : Path;
+ if (Image == null)
+ {
+ if ((Path is String))
+ {
+ var splitDir = Path.split("/");
+ splitDir.pop();
+ splitDir.push(data.metadata.textureFileName);
+ Image = splitDir.join("/");
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+
+ var graphic:FlxGraphic = FlxG.bitmap.add(Image, false);
+ if (graphic == null)
+ return null;
+
+ // No need to parse data again
+ var frames:FlxAtlasFrames = FlxAtlasFrames.findFrame(graphic);
+ if (frames != null)
+ return frames;
+
+ frames = new FlxAtlasFrames(graphic);
+
+ for (frameName in Reflect.fields(data.frames))
+ {
+ starlingHelper(frameName, Reflect.field(data.frames, frameName), frames);
+ }
+
+ return frames;
+ }
+ /**
+ * Cocos2D spritesheet format parser, which basically has 2 versions,
+ * One is basically Starling (2v) and the other one which is a more fucky and weird (3v)
+ * @param Path the Path of the plist
+ * @param Image (Optional) the image
+ * @return Recently made Frames for your dispose ;)
+ */
+ public static function fromCocos2D(Path:String, ?Image:FlxGraphicAsset):FlxAtlasFrames
+ {
+ if (!Assets.exists(Path))
+ return null;
+ var data:Plist = PropertyList.parse(Assets.getText(Path));
+ if (data.metadata.format == 2)
+ {
+ return fromStarling(Path, Image);
+ }
+ else
+ {
+ if (Image == null)
+ {
+ if ((Path is String))
+ {
+ var splitDir = Path.split("/");
+ splitDir.pop();
+ splitDir.push(data.metadata.target.name);
+ Image = splitDir.join("/");
+ }
+ else
+ {
+ return null;
+ }
+ }
+ var graphic:FlxGraphic = FlxG.bitmap.add(Image);
+ if (graphic == null)
+ return null;
+
+ // No need to parse data again
+ var frames:FlxAtlasFrames = FlxAtlasFrames.findFrame(graphic);
+ if (frames != null)
+ return frames;
+
+ frames = new FlxAtlasFrames(graphic);
+
+ for (frameName in Reflect.fields(data.frames))
+ {
+ cocosHelper(frameName, Reflect.field(data.frames, frameName), frames);
+ }
+
+ return frames;
+ }
+ }
+ /**
+ * EaselJS spritesheet format parser, pretty weird stuff.
+ * @param Path The Path of the jsFile
+ * @param Image (optional) the Path of the image
+ * @return New frames made for you to use ;)
+ */
+ public static function fromEaselJS(Path:String, ?Image:FlxGraphicAsset):FlxAtlasFrames
+ {
+ var hugeFrames:FlxAtlasFrames = new FlxAtlasFrames(null);
+ var separatedJS = Assets.getText(Path).split("\n");
+ var lines:Array = [];
+ for (line in separatedJS)
+ {
+ if (StringTools.contains(line, "new createjs.SpriteSheet({"))
+ lines.push(line);
+ }
+ var names:Array = [];
+ var jsons:Array = [];
+ for (line in lines)
+ {
+ names.push(StringTools.replace(line.split(".")[0], "_", " "));
+ var curJson = StringTools.replace(StringTools.replace(line.split("(")[1], ")", ""), ";", "");
+ var parsedJson = haxe.Json.parse(~/({|,\s*)(\S+)(\s*:)/g.replace(curJson, '$1\"$2"$3'));
+ jsons.push(parsedJson);
+ }
+ var prevName = "";
+ var imagePath = Path.split("/");
+ imagePath.pop();
+ for (i in 0...names.length)
+ {
+ var times = 0;
+ var name = names[i];
+ var json = jsons[i];
+ var bitmap = FlxG.bitmap.add((Image == null) ? '${imagePath.join("/")}/${json.images[0]}' : Image);
+ var frames = new FlxAtlasFrames(bitmap);
+ for (frame in json.frames)
+ {
+ var frameRect:FlxRect = new FlxRect(frame[0], frame[1], frame[2], frame[3]);
+ var sourceSize:FlxPoint = new FlxPoint(frameRect.width, frameRect.height);
+ var offset = new FlxPoint(-frame[5], -frame[6]);
+ frames.addAtlasFrame(frameRect, sourceSize, offset, name + Std.string(times));
+ times++;
+ }
+ for (frame in frames.frames)
+ {
+ hugeFrames.pushFrame(frame);
+ }
+ }
+ return hugeFrames;
+ }
+
+ static function cocosHelper(FrameName:String, FrameData:Dynamic, Frames:FlxAtlasFrames)
+ {
+ var rotated:Bool = FrameData.textureRotated;
+ var name:String = FrameName;
+ var sourceSize:FlxPoint = FlxPoint.get(Std.parseFloat(FrameData.spriteSourceSize[0]), Std.parseFloat(FrameData.spriteSourceSize[1]));
+ var offset:FlxPoint = FlxPoint.get(-Std.parseFloat(FrameData.spriteOffset[0]), -Std.parseFloat(FrameData.spriteOffset[1]));
+ var angle:FlxFrameAngle = FlxFrameAngle.ANGLE_0;
+ var frameRect:FlxRect = null;
+
+ var frame = FrameData.textureRect;
+ if (rotated)
+ {
+ frameRect = FlxRect.get(Std.parseFloat(frame[0]), Std.parseFloat(frame[1]), Std.parseFloat(frame[3]), Std.parseFloat(frame[2]));
+ angle = FlxFrameAngle.ANGLE_NEG_90;
+ }
+ else
+ {
+ frameRect = FlxRect.get(Std.parseFloat(frame[0]), Std.parseFloat(frame[1]), Std.parseFloat(frame[2]), Std.parseFloat(frame[3]));
+ }
+
+ Frames.addAtlasFrame(frameRect, sourceSize, offset, name, angle);
+ }
+
+ static function starlingHelper(FrameName:String, FrameData:Dynamic, Frames:FlxAtlasFrames):Void
+ {
+ var rotated:Bool = FrameData.rotated;
+ var name:String = FrameName;
+ var sourceSize:FlxPoint = FlxPoint.get(Std.parseFloat(FrameData.sourceSize[0]), Std.parseFloat(FrameData.sourceSize[1]));
+ var offset:FlxPoint = FlxPoint.get(-Std.parseFloat(FrameData.offset[0]), -Std.parseFloat(FrameData.offset[1]));
+ var angle:FlxFrameAngle = FlxFrameAngle.ANGLE_0;
+ var frameRect:FlxRect = null;
+
+ var frame = FrameData.frame;
+ if (rotated)
+ {
+ frameRect = FlxRect.get(Std.parseFloat(frame[0]), Std.parseFloat(frame[1]), Std.parseFloat(frame[3]), Std.parseFloat(frame[2]));
+ angle = FlxFrameAngle.ANGLE_NEG_90;
+ }
+ else
+ {
+ frameRect = FlxRect.get(Std.parseFloat(frame[0]), Std.parseFloat(frame[1]), Std.parseFloat(frame[2]), Std.parseFloat(frame[3]));
+ }
+
+ Frames.addAtlasFrame(frameRect, sourceSize, offset, name, angle);
+ }
+
+ static function textureAtlasHelper(SpriteMap:BitmapData, limb:AnimateSpriteData, curMeta:Meta)
+ {
+ var width = (limb.rotated) ? limb.h : limb.w;
+ var height = (limb.rotated) ? limb.w : limb.h;
+ var sprite = new BitmapData(width, height, true, 0);
+ var matrix = new FlxMatrix(1,0,0,1,-limb.x,-limb.y);
+ if (limb.rotated)
+ {
+ matrix.rotateByNegative90();
+ matrix.translate(0, height);
+ }
+ sprite.draw(SpriteMap, matrix);
+
+ @:privateAccess
+ var curFrame = new FlxFrame(FlxG.bitmap.add(sprite));
+ curFrame.name = limb.name;
+ curFrame.sourceSize.set(width, height);
+ curFrame.frame = new FlxRect(0,0, width, height);
+ return curFrame;
+ }
+
+ static function texturePackerHelper(FrameName:String, FrameData:Dynamic, Frames:FlxAtlasFrames):Void
+ {
+ var rotated:Bool = FrameData.rotated;
+ var name:String = FrameName;
+ var sourceSize:FlxPoint = FlxPoint.get(FrameData.sourceSize.w, FrameData.sourceSize.h);
+ var offset:FlxPoint = FlxPoint.get(FrameData.spriteSourceSize.x, FrameData.spriteSourceSize.y);
+ var angle:FlxFrameAngle = FlxFrameAngle.ANGLE_0;
+ var frameRect:FlxRect = null;
+
+ if (rotated)
+ {
+ frameRect = FlxRect.get(FrameData.frame.x, FrameData.frame.y, FrameData.frame.h, FrameData.frame.w);
+ angle = FlxFrameAngle.ANGLE_NEG_90;
+ }
+ else
+ {
+ frameRect = FlxRect.get(FrameData.frame.x, FrameData.frame.y, FrameData.frame.w, FrameData.frame.h);
+ }
+
+ Frames.addAtlasFrame(frameRect, sourceSize, offset, name, angle);
+ }
+ static function max(a:Int, b:Int):Int
+ return a < b ? b : a;
+}
+// code made by noonat 11 years ago, not mine lol
+class PropertyList
+{
+ static var _dateRegex:EReg = ~/(\d{4}-\d{2}-\d{2})(?:T(\d{2}:\d{2}:\d{2})Z)?/;
+
+ /**
+ * Parse an Apple property list XML file into a dynamic object. If
+ * the property list is empty, an empty object will be returned.
+ * @param text Text contents of the property list file.
+ */
+ static public function parse(text:String):Dynamic
+ {
+ var fast = new Access(Xml.parse(text).firstElement());
+ return fast.hasNode.dict ? parseDict(fast.node.dict) : {};
+ }
+
+ static function parseDate(text:String):Date
+ {
+ if (!_dateRegex.match(text))
+ {
+ throw 'Invalid date "' + text + '" (only yyyy-mm-dd and yyyy-mm-ddThh:mm:ssZ supported)';
+ }
+ text = _dateRegex.matched(1);
+ if (_dateRegex.matched(2) != null)
+ {
+ text += ' ' + _dateRegex.matched(2);
+ }
+ return Date.fromString(text);
+ }
+
+ static function parseDict(node:Access):Dynamic
+ {
+ var key:String = null;
+ var result:Dynamic = {};
+ for (childNode in node.elements)
+ {
+ if (childNode.name == 'key')
+ {
+ key = childNode.innerData;
+ } else if (key != null)
+ {
+ Reflect.setField(result, key, parseValue(childNode));
+ }
+ }
+ return result;
+ }
+
+ static function parseValue(node:Access):Dynamic
+ {
+ var value:Dynamic = null;
+ switch (node.name)
+ {
+ case 'array':
+ value = new Array();
+ for (childNode in node.elements)
+ {
+ value.push(parseValue(childNode));
+ }
+
+ case 'dict':
+ value = parseDict(node);
+
+ case 'date':
+ value = parseDate(node.innerData);
+
+ case 'string':
+ var thing:Dynamic = node.innerData;
+ if (thing.charAt(0) == "{")
+ {
+ thing = StringTools.replace(thing, "{", "");
+ thing = StringTools.replace(thing, "}", "");
+ thing = thing.split(",");
+ }
+ value = thing;
+ case 'data':
+ value = node.innerData;
+
+ case 'true':
+ value = true;
+
+ case 'false':
+ value = false;
+
+ case 'real':
+ value = Std.parseFloat(node.innerData);
+
+ case 'integer':
+ value = Std.parseInt(node.innerData);
+ }
+ return value;
+ }
+}
+typedef JSJson =
+{
+ var images:Array;
+ var frames:Array>;
+}
+typedef FlxSparrow = OneOfTwo;
+typedef FlxJson = OneOfTwo;
+typedef FlxPropertyList = OneOfTwo;
+typedef JsonNormal =
+{
+ frames:Dynamic,
+ meta:Meta
+}
+typedef Plist =
+{
+ frames:Dynamic,
+ metadata:Dynamic
+}
\ No newline at end of file
diff --git a/source/funkin/chart/BaseGameParser.hx b/source/funkin/chart/BaseGameParser.hx
index c111822b..85abbdd0 100644
--- a/source/funkin/chart/BaseGameParser.hx
+++ b/source/funkin/chart/BaseGameParser.hx
@@ -87,8 +87,13 @@ class BaseGameParser {
}
if (section.changeBPM && section.bpm != curBPM) {
- // TODO: BPM CHANGE EVENT
curCrochet = ((60 / (curBPM = section.bpm)) * 1000);
+
+ result.events.push({
+ time: curTime,
+ type: BPM_CHANGE,
+ params: [section.bpm]
+ });
}
curTime += curCrochet * beatsPerMesure;
diff --git a/source/funkin/game/Note.hx b/source/funkin/game/Note.hx
index 514fb674..2fee02a3 100644
--- a/source/funkin/game/Note.hx
+++ b/source/funkin/game/Note.hx
@@ -94,7 +94,6 @@ class Note extends FlxSprite
{
super();
- // TODO: Sustain note
this.prevNote = strumLine.notes.members.last();
this.noteTypeID = noteData.type.getDefault(0);
this.isSustainNote = sustain;
diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx
index d26e9df3..5a702456 100644
--- a/source/funkin/game/PlayState.hx
+++ b/source/funkin/game/PlayState.hx
@@ -561,7 +561,6 @@ class PlayState extends MusicBeatState
generateSong(SONG);
- trace(SONG.noteTypes);
for(noteType in SONG.noteTypes) {
var scriptPath = Paths.script('data/notes/${noteType}');
if (Assets.exists(scriptPath) && !scripts.contains(scriptPath)) {
diff --git a/source/funkin/options/OptionsMenu.hx b/source/funkin/options/OptionsMenu.hx
index 8736b4c9..6f743065 100644
--- a/source/funkin/options/OptionsMenu.hx
+++ b/source/funkin/options/OptionsMenu.hx
@@ -18,17 +18,17 @@ class OptionsMenu extends TreeMenu {
substate: funkin.options.keybinds.KeybindsOptions
},
{
- name: 'Gameplay',
+ name: 'Gameplay >',
desc: 'Change Gameplay options such as Downscroll, Scroll Speed, Naughtyness...',
state: GameplayOptions
},
{
- name: 'Appearance',
+ name: 'Appearance >',
desc: 'Change Appearance options such as Flashing menus...',
state: AppearanceOptions
},
{
- name: 'Miscellaneous',
+ name: 'Miscellaneous >',
desc: 'Use this menu to reset save data or engine settings.',
state: MiscOptions
}
@@ -112,7 +112,7 @@ class OptionsMenu extends TreeMenu {
}
options.push(new Checkbox(name, desc, node.att.id, FlxG.save.data));
case "menu":
- options.push(new TextOption(name, desc, function() {
+ options.push(new TextOption(name + " >", desc, function() {
optionsTree.add(new OptionsScreen(name, desc, parseOptionsFromXML(node)));
}));
}
diff --git a/source/funkin/system/Conductor.hx b/source/funkin/system/Conductor.hx
index d15591ae..6cb1fe60 100644
--- a/source/funkin/system/Conductor.hx
+++ b/source/funkin/system/Conductor.hx
@@ -15,7 +15,7 @@ import flixel.util.FlxSignal.FlxTypedSignal;
typedef BPMChangeEvent =
{
- var stepTime:Int;
+ var stepTime:Float;
var songTime:Float;
var bpm:Float;
}
@@ -115,37 +115,35 @@ class Conductor
public static function setupSong(SONG:ChartData) {
reset();
- // mapBPMChanges(SONG); // TODO!!!
+ mapBPMChanges(SONG);
changeBPM(SONG.meta.bpm, cast SONG.meta.beatsPerMesure.getDefault(4), cast SONG.meta.stepsPerBeat.getDefault(4));
}
/**
* Maps BPM changes from a song.
* @param song Song to map BPM changes from.
*/
- public static function mapBPMChanges(song:SwagSong)
+ public static function mapBPMChanges(song:ChartData)
{
bpmChangeMap = [];
- var curBPM:Float = song.bpm;
- var totalSteps:Int = 0;
- var totalPos:Float = 0;
- for (i=>notes in song.notes)
- {
- if (notes == null) continue;
- if (notes.changeBPM && notes.bpm != curBPM)
- {
- curBPM = notes.bpm;
- var event:BPMChangeEvent = {
- stepTime: totalSteps,
- songTime: totalPos,
- bpm: curBPM
- };
- bpmChangeMap.push(event);
- }
+ if (song.events == null) return;
- var deltaSteps:Int = notes.lengthInSteps;
- totalSteps += deltaSteps;
- totalPos += ((60 / curBPM) * 1000 / 4) * deltaSteps;
+ var curBPM:Float = song.meta.bpm;
+ var songTime:Float = 0;
+ var stepTime:Float = 0;
+
+ for(e in song.events) if (e.type == BPM_CHANGE && e.params != null && e.params[0] is Float) {
+ if (e.params[0] == curBPM) continue;
+ var steps = (e.time - songTime) / ((60 / curBPM) * 1000 / 4);
+ stepTime += steps;
+ songTime = e.time;
+ curBPM = e.params[0];
+
+ bpmChangeMap.push({
+ stepTime: stepTime,
+ songTime: songTime,
+ bpm: curBPM
+ });
}
}
diff --git a/source/funkin/system/FlxAnimate.hx b/source/funkin/system/FlxAnimate.hx
index b126187e..2e472945 100644
--- a/source/funkin/system/FlxAnimate.hx
+++ b/source/funkin/system/FlxAnimate.hx
@@ -1,5 +1,6 @@
package funkin.system;
+import flixel.graphics.frames.FlxFramesCollection;
import openfl.geom.ColorTransform;
import flixel.math.FlxMatrix;
import flixel.math.FlxAngle;
@@ -8,6 +9,21 @@ import flixel.graphics.frames.FlxFrame;
import flixel.math.FlxPoint;
class FlxAnimate extends flxanimate.FlxAnimate {
+ public static var loadedPaths:Array = [];
+ public override function loadAtlas(Path:String) {
+ super.loadAtlas(Path);
+ loadedPaths.push(Path);
+ }
+
+ public static function init() {
+ FlxG.signals.preStateSwitch.add(onSwitch);
+ }
+
+ private static function onSwitch() {
+ for(p in loadedPaths) {
+ Assets.cache.clear(p);
+ }
+ }
override function drawLimb(limb:FlxFrame, _matrix:FlxMatrix, ?colorTransform:ColorTransform)
{
if (alpha == 0 || colorTransform != null && (colorTransform.alphaMultiplier == 0 || colorTransform.alphaOffset == -255) || limb == null || limb.type == EMPTY)
diff --git a/source/funkin/system/FunkinSprite.hx b/source/funkin/system/FunkinSprite.hx
index 90339e0e..aada8ed8 100644
--- a/source/funkin/system/FunkinSprite.hx
+++ b/source/funkin/system/FunkinSprite.hx
@@ -152,8 +152,8 @@ class FunkinSprite extends FlxSprite implements IBeatReceiver implements IOffset
}
public override function destroy() {
- super.destroy();
- animateAtlas = FlxDestroyUtil.destroy(animateAtlas);
+ animateAtlas = FlxDestroyUtil.destroy(animateAtlas);
+ super.destroy();
}
#end
diff --git a/source/funkin/system/Main.hx b/source/funkin/system/Main.hx
index d1e105f8..7e87d42b 100644
--- a/source/funkin/system/Main.hx
+++ b/source/funkin/system/Main.hx
@@ -158,6 +158,7 @@ class Main extends Sprite
#if GLOBAL_SCRIPT
funkin.scripting.GlobalScript.init();
#end
+ funkin.system.FlxAnimate.init();
#if sys
if (startedFromSource = Sys.args().contains("-livereload")) {
diff --git a/source/lime/system/System.hx b/source/lime/system/System.hx
index 6d3fe425..549adf70 100644
--- a/source/lime/system/System.hx
+++ b/source/lime/system/System.hx
@@ -424,8 +424,6 @@ class System
#if sys
private static function __parseArguments(attributes:WindowAttributes):Void
{
- // TODO: Handle default arguments, like --window-fps=60
-
var arguments = Sys.args();
var stripQuotes = ~/^['"](.*)['"]$/;
var equals, argValue, parameters = null;
diff --git a/source/openfl/display3D/Context3D.hx b/source/openfl/display3D/Context3D.hx
index d81ac241..0da9190c 100644
--- a/source/openfl/display3D/Context3D.hx
+++ b/source/openfl/display3D/Context3D.hx
@@ -271,7 +271,7 @@ import lime.math.Vector2;
@:noCompletion private var __enableErrorChecking:Bool;
@:noCompletion private var __fragmentConstants:Float32Array;
@:noCompletion private var __frontBufferTexture:RectangleTexture;
- @:noCompletion private var __positionScale:Float32Array; // TODO: Better approach?
+ @:noCompletion private var __positionScale:Float32Array;
@:noCompletion private var __present:Bool;
@:noCompletion private var __programs:Map;
@:noCompletion private var __quadIndexBuffer:IndexBuffer3D;
@@ -1000,8 +1000,6 @@ import lime.math.Vector2;
**/
public function dispose(recreate:Bool = true):Void
{
- // TODO: Dispose all related buffers
-
gl = null;
__dispose();
}
@@ -1073,9 +1071,6 @@ import lime.math.Vector2;
__flushGLFramebuffer();
__flushGLViewport();
-
- // TODO: Read less pixels if srcRect is smaller
-
//! EDITED BY NE_EO TO REDUCE GARBAGE MEMORY
var buffer = UInt8Buff.get(backBufferWidth * backBufferHeight * 4); // new UInt8Array(backBufferWidth * backBufferHeight * 4);
var data = buffer.buffer;
@@ -1177,14 +1172,12 @@ import lime.math.Vector2;
#if !openfl_disable_display_render
if (__state.renderToTexture == null)
{
- // TODO: Make sure state is correct for this?
if (__stage.context3D == this && !__stage.__renderer.__cleared)
{
__stage.__renderer.__clear();
}
else if (!__cleared)
{
- // TODO: Throw error if error reporting is enabled?
clear(0, 0, 0, 0, 1, 0, Context3DClearMask.COLOR);
}
}
@@ -1230,7 +1223,7 @@ import lime.math.Vector2;
if (!__cleared)
{
// Make sure texture is initialized
- // TODO: Throw error if error reporting is enabled?
+ // BASE-TODO: Throw error if error reporting is enabled?
clear(0, 0, 0, 0, 1, 0, Context3DClearMask.COLOR);
}
@@ -1291,7 +1284,7 @@ import lime.math.Vector2;
__state.blendSourceAlphaFactor = sourceAlphaFactor;
__state.blendDestinationAlphaFactor = destinationAlphaFactor;
- // TODO: Better way to handle this?
+ // BASE-TODO: Better way to handle this?
__setGLBlendEquation(gl.FUNC_ADD);
}
@@ -1370,7 +1363,7 @@ import lime.math.Vector2;
public function setProgram(program:Program3D):Void
{
__state.program = program;
- __state.shader = null; // TODO: Merge this logic
+ __state.shader = null; // BASE-TODO: Merge this logic
if (program != null)
{
@@ -1414,11 +1407,11 @@ import lime.math.Vector2;
if (__state.program != null && __state.program.__format == GLSL)
{
- // TODO
+ // BASE-TODO
}
else
{
- // TODO: Cleanup?
+ // BASE-TODO: Cleanup?
if (numRegisters == -1)
{
@@ -1472,7 +1465,7 @@ import lime.math.Vector2;
{
__flushGLProgram();
- // TODO: Cache value, prevent need to copy
+ // BASE-TODO: Cache value, prevent need to copy
var data = new Float32Array(16);
for (i in 0...16)
{
@@ -1937,7 +1930,7 @@ import lime.math.Vector2;
@:noCompletion private function __bindGLTexture2D(texture:GLTexture):Void
{
- // TODO: Need to consider activeTexture ID
+ // BASE-TODO: Need to consider activeTexture ID
// if (#if openfl_disable_context_cache true #else __contextState.__currentGLTexture2D != texture #end) {
@@ -1949,7 +1942,7 @@ import lime.math.Vector2;
@:noCompletion private function __bindGLTextureCubeMap(texture:GLTexture):Void
{
- // TODO: Need to consider activeTexture ID
+ // BASE-TODO: Need to consider activeTexture ID
// if (#if openfl_disable_context_cache true #else __contextState.__currentGLTextureCubeMap != texture #end) {
@@ -1988,14 +1981,14 @@ import lime.math.Vector2;
#if !openfl_disable_display_render
if (__state.renderToTexture == null)
{
- // TODO: Make sure state is correct for this?
+ // BASE-TODO: Make sure state is correct for this?
if (__stage.context3D == this && !__stage.__renderer.__cleared)
{
__stage.__renderer.__clear();
}
else if (!__cleared)
{
- // TODO: Throw error if error reporting is enabled?
+ // BASE-TODO: Throw error if error reporting is enabled?
clear(0, 0, 0, 0, 1, 0, Context3DClearMask.COLOR);
}
}
@@ -2191,7 +2184,7 @@ import lime.math.Vector2;
if (#if openfl_disable_context_cache true #else __contextState.shader != shader #end)
{
- // TODO: Merge this logic
+ // BASE-TODO: Merge this logic
if (__contextState.shader != null)
{
@@ -2319,7 +2312,7 @@ import lime.math.Vector2;
{
// if (#if openfl_disable_context_cache true #else texture != __contextState.textures[i] #end) {
- // TODO: Cleaner approach?
+ // BASE-TODO: Cleaner approach?
if (texture.__textureTarget == gl.TEXTURE_2D)
{
__bindGLTexture2D(texture.__getTexture());
@@ -2330,7 +2323,7 @@ import lime.math.Vector2;
}
#if (desktop && !html5)
- // TODO: Cache?
+ // BASE-TODO: Cache?
gl.enable(gl.TEXTURE_2D);
#end
@@ -2364,7 +2357,7 @@ import lime.math.Vector2;
gl.uniform1i(__state.program.__agalAlphaSamplerEnabled[sampler].location, 1);
#if (desktop && !html5)
- // TODO: Cache?
+ // BASE-TODO: Cache?
gl.enable(gl.TEXTURE_2D);
#end
}
@@ -2384,7 +2377,7 @@ import lime.math.Vector2;
@:noCompletion private function __flushGLViewport():Void
{
- // TODO: Cache
+ // BASE-TODO: Cache
if (__state.renderToTexture == null)
{
@@ -2403,7 +2396,7 @@ import lime.math.Vector2;
{
var width = 0, height = 0;
- // TODO: Avoid use of Std.is
+ // BASE-TODO: Avoid use of Std.is
if ((__state.renderToTexture is Texture))
{
var texture2D:Texture = cast __state.renderToTexture;
@@ -2467,7 +2460,7 @@ import lime.math.Vector2;
case GREATER: gl.GREATER;
case GREATER_EQUAL: gl.GEQUAL;
case LESS: gl.LESS;
- case LESS_EQUAL: gl.LEQUAL; // TODO : wrong value
+ case LESS_EQUAL: gl.LEQUAL; // BASE-TODO : wrong value
case NEVER: gl.NEVER;
case NOT_EQUAL: gl.NOTEQUAL;
default: gl.EQUAL;
@@ -2662,7 +2655,7 @@ import lime.math.Vector2;
{
if (__glMemoryCurrentAvailable != -1)
{
- // TODO: Return amount used by this application only
+ // BASE-TODO: Return amount used by this application only
var current = gl.getParameter(__glMemoryCurrentAvailable);
var total = gl.getParameter(__glMemoryTotalAvailable);