Merge branch 'notehold-styles' into rewrite/master
This commit is contained in:
+1
-1
Submodule assets updated: 26b7f54a06...51f7f0df72
@@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
<!-- TODO: Include NoteSplash and NoteStyle changes made to accomodate week 6 note splash/hold stuff -->
|
||||
|
||||
## [1.1.0]
|
||||
### Added
|
||||
- Added several new `assets`:
|
||||
|
||||
@@ -290,4 +290,33 @@ typedef NoteStyleData_HoldNoteCover =
|
||||
@:optional
|
||||
@:default(true)
|
||||
var enabled:Bool;
|
||||
|
||||
@:optional
|
||||
var left:NoteStyleData_HoldNoteCoverDirectionData;
|
||||
|
||||
@:optional
|
||||
var down:NoteStyleData_HoldNoteCoverDirectionData;
|
||||
|
||||
@:optional
|
||||
var up:NoteStyleData_HoldNoteCoverDirectionData;
|
||||
|
||||
@:optional
|
||||
var right:NoteStyleData_HoldNoteCoverDirectionData;
|
||||
};
|
||||
|
||||
typedef NoteStyleData_HoldNoteCoverDirectionData =
|
||||
{
|
||||
/**
|
||||
* Optionally specify an asset path to use for this specific animation.
|
||||
* @:default The assetPath of the main holdNoteCover asset
|
||||
*/
|
||||
@:optional
|
||||
var assetPath:String;
|
||||
|
||||
@:optional
|
||||
var start:UnnamedAnimationData;
|
||||
@:optional
|
||||
var hold:UnnamedAnimationData;
|
||||
@:optional
|
||||
var end:UnnamedAnimationData;
|
||||
}
|
||||
|
||||
@@ -4,66 +4,37 @@ import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
||||
import flixel.graphics.frames.FlxFramesCollection;
|
||||
import funkin.util.assets.FlxAnimationUtil;
|
||||
import flixel.FlxSprite;
|
||||
import funkin.play.notes.notestyle.NoteStyle;
|
||||
|
||||
class NoteHoldCover extends FlxTypedSpriteGroup<FlxSprite>
|
||||
{
|
||||
static final FRAMERATE_DEFAULT:Int = 24;
|
||||
|
||||
static var glowFrames:FlxFramesCollection;
|
||||
|
||||
public var holdNote:SustainTrail;
|
||||
|
||||
var glow:FlxSprite;
|
||||
public var glow:FlxSprite;
|
||||
|
||||
var sparks:FlxSprite;
|
||||
|
||||
public function new()
|
||||
public function new(noteStyle:NoteStyle)
|
||||
{
|
||||
super(0, 0);
|
||||
|
||||
setup();
|
||||
}
|
||||
|
||||
public static function preloadFrames():Void
|
||||
{
|
||||
glowFrames = null;
|
||||
for (direction in Strumline.DIRECTIONS)
|
||||
{
|
||||
var directionName = direction.colorName.toTitleCase();
|
||||
|
||||
var atlas:FlxFramesCollection = Paths.getSparrowAtlas('holdCover${directionName}');
|
||||
atlas.parent.persist = true;
|
||||
|
||||
if (glowFrames != null)
|
||||
{
|
||||
glowFrames = FlxAnimationUtil.combineFramesCollections(glowFrames, atlas);
|
||||
}
|
||||
else
|
||||
{
|
||||
glowFrames = atlas;
|
||||
}
|
||||
}
|
||||
setupHoldNoteCover(noteStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add ALL the animations to this sprite. We will recycle and reuse the FlxSprite multiple times.
|
||||
*/
|
||||
function setup():Void
|
||||
function setupHoldNoteCover(noteStyle:NoteStyle):Void
|
||||
{
|
||||
glow = new FlxSprite();
|
||||
add(glow);
|
||||
if (glowFrames == null) preloadFrames();
|
||||
glow.frames = glowFrames;
|
||||
|
||||
for (direction in Strumline.DIRECTIONS)
|
||||
{
|
||||
var directionName = direction.colorName.toTitleCase();
|
||||
// TODO: null check here like how NoteSplash does
|
||||
noteStyle.buildHoldCoverSprite(this);
|
||||
|
||||
glow.animation.addByPrefix('holdCoverStart$directionName', 'holdCoverStart${directionName}0', FRAMERATE_DEFAULT, false, false, false);
|
||||
glow.animation.addByPrefix('holdCover$directionName', 'holdCover${directionName}0', FRAMERATE_DEFAULT, true, false, false);
|
||||
glow.animation.addByPrefix('holdCoverEnd$directionName', 'holdCoverEnd${directionName}0', FRAMERATE_DEFAULT, false, false, false);
|
||||
}
|
||||
|
||||
glow.animation.finishCallback = this.onAnimationFinished;
|
||||
glow.animation.onFinish.add(this.onAnimationFinished);
|
||||
|
||||
if (glow.animation.getAnimationList().length < 3 * 4)
|
||||
{
|
||||
|
||||
@@ -12,19 +12,13 @@ class NoteSplash extends FlxSprite
|
||||
|
||||
static var frameCollection:FlxFramesCollection;
|
||||
|
||||
public static function preloadFrames():Void
|
||||
{
|
||||
frameCollection = Paths.getSparrowAtlas('noteSplashes');
|
||||
frameCollection.parent.persist = true;
|
||||
}
|
||||
|
||||
public function new(noteStyle:NoteStyle)
|
||||
{
|
||||
super(0, 0);
|
||||
|
||||
setupSplashGraphic(noteStyle);
|
||||
|
||||
this.animation.finishCallback = this.onAnimationFinished;
|
||||
this.animation.onFinish.add(this.onAnimationFinished);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,6 +49,7 @@ class NoteSplash extends FlxSprite
|
||||
}
|
||||
|
||||
// splashUP0, splashUP1, splashRIGHT0, etc.
|
||||
// the animations are processed via `NoteStyle.fetchSplashAnimationData()` in this format
|
||||
this.playAnimation('splash${direction.nameUpper}${variant}');
|
||||
|
||||
if (animation.curAnim == null) return;
|
||||
|
||||
@@ -779,10 +779,10 @@ class Strumline extends FlxSpriteGroup
|
||||
splash.x = this.x;
|
||||
splash.x += getXPos(direction);
|
||||
splash.x += INITIAL_OFFSET;
|
||||
splash.x += noteStyle.getSplashOffsets()[0] * splash.scale.x;
|
||||
|
||||
splash.y = this.y;
|
||||
splash.y -= INITIAL_OFFSET;
|
||||
splash.y += 0;
|
||||
splash.x += noteStyle.getSplashOffsets()[0] * splash.scale.x;
|
||||
splash.y += noteStyle.getSplashOffsets()[1] * splash.scale.y;
|
||||
}
|
||||
}
|
||||
@@ -806,12 +806,14 @@ class Strumline extends FlxSpriteGroup
|
||||
cover.x += getXPos(holdNote.noteDirection);
|
||||
cover.x += STRUMLINE_SIZE / 2;
|
||||
cover.x -= cover.width / 2;
|
||||
cover.x += -12; // Manual tweaking because fuck.
|
||||
cover.x += noteStyle.getHoldCoverOffsets()[0] * cover.scale.x;
|
||||
cover.x += -12; // hardcoded adjustment, because we are evil.
|
||||
|
||||
cover.y = this.y;
|
||||
cover.y += INITIAL_OFFSET;
|
||||
cover.y += STRUMLINE_SIZE / 2;
|
||||
cover.y += -96; // Manual tweaking because fuck.
|
||||
cover.y += noteStyle.getHoldCoverOffsets()[1] * cover.scale.y;
|
||||
cover.y += -96; // hardcoded adjustment, because we are evil.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -916,7 +918,7 @@ class Strumline extends FlxSpriteGroup
|
||||
if (noteHoldCovers.length < noteHoldCovers.maxSize)
|
||||
{
|
||||
// Create a new note hold cover.
|
||||
result = new NoteHoldCover();
|
||||
result = new NoteHoldCover(noteStyle);
|
||||
this.noteHoldCovers.add(result);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -2,6 +2,7 @@ package funkin.play.notes.notestyle;
|
||||
|
||||
import funkin.play.Countdown;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.graphics.frames.FlxFramesCollection;
|
||||
import funkin.data.animation.AnimationData;
|
||||
import funkin.data.IRegistryEntry;
|
||||
import funkin.graphics.FunkinSprite;
|
||||
@@ -99,6 +100,15 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||
target.updateHitbox();
|
||||
}
|
||||
|
||||
function getNoteAssetLibrary():Null<String>
|
||||
{
|
||||
// library:path
|
||||
var parts = getNoteAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||
if (parts.length == 0) return null;
|
||||
if (parts.length == 1) return null;
|
||||
return parts[0];
|
||||
}
|
||||
|
||||
var noteFrames:Null<FlxAtlasFrames> = null;
|
||||
|
||||
function buildNoteFrames(force:Bool = false):Null<FlxAtlasFrames>
|
||||
@@ -123,7 +133,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||
|
||||
if (noteFrames != null && !force) return noteFrames;
|
||||
|
||||
noteFrames = Paths.getSparrowAtlas(noteAssetPath, getNoteAssetLibrary());
|
||||
noteFrames = Paths.getSparrowAtlas(noteAssetPath, getAssetLibrary(getNoteAssetPath(true)));
|
||||
|
||||
if (noteFrames == null)
|
||||
{
|
||||
@@ -149,15 +159,6 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||
return parts[1];
|
||||
}
|
||||
|
||||
function getNoteAssetLibrary():Null<String>
|
||||
{
|
||||
// library:path
|
||||
var parts = getNoteAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||
if (parts.length == 0) return null;
|
||||
if (parts.length == 1) return null;
|
||||
return parts[0];
|
||||
}
|
||||
|
||||
function buildNoteAnimations(target:NoteSprite):Void
|
||||
{
|
||||
var leftData:Null<AnimationData> = fetchNoteAnimationData(LEFT);
|
||||
@@ -232,7 +233,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||
// TODO: Add support for multi-Sparrow.
|
||||
// Will be less annoying after this is merged: https://github.com/HaxeFlixel/flixel/pull/2772
|
||||
|
||||
var atlas:FlxAtlasFrames = Paths.getSparrowAtlas(getStrumlineAssetPath() ?? '', getStrumlineAssetLibrary());
|
||||
var atlas:FlxAtlasFrames = Paths.getSparrowAtlas(getStrumlineAssetPath() ?? '', getAssetLibrary(getStrumlineAssetPath(true)));
|
||||
|
||||
if (atlas == null)
|
||||
{
|
||||
@@ -258,14 +259,6 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||
return parts[1];
|
||||
}
|
||||
|
||||
function getStrumlineAssetLibrary():Null<String>
|
||||
{
|
||||
// library:path
|
||||
var parts = getStrumlineAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||
if (parts.length <= 1) return null;
|
||||
return parts[0];
|
||||
}
|
||||
|
||||
public function applyStrumlineAnimations(target:StrumlineNote, dir:NoteDirection):Void
|
||||
{
|
||||
FlxAnimationUtil.addAtlasAnimations(target, getStrumlineAnimationData(dir));
|
||||
@@ -921,7 +914,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||
|
||||
if (splashFrames != null && !force) return splashFrames;
|
||||
|
||||
splashFrames = Paths.getSparrowAtlas(splashAssetPath, getSplashAssetLibrary());
|
||||
splashFrames = Paths.getSparrowAtlas(splashAssetPath, getAssetLibrary(getSplashAssetPath(true)));
|
||||
splashFrames.parent.persist = true;
|
||||
if (splashFrames == null)
|
||||
{
|
||||
@@ -945,14 +938,6 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||
return parts[1];
|
||||
}
|
||||
|
||||
function getSplashAssetLibrary():Null<String>
|
||||
{
|
||||
var parts = getSplashAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||
if (parts.length == 0) return null;
|
||||
if (parts.length == 1) return null;
|
||||
return parts[0];
|
||||
}
|
||||
|
||||
function buildSplashAnimations(target:NoteSplash):Void
|
||||
{
|
||||
final addSplashAnim:NoteDirection->Void = function(dir:NoteDirection) {
|
||||
@@ -1007,8 +992,189 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||
return _data?.assets?.noteSplash?.data?.framerateVariance ?? fallback?.getSplashFramerateVariance() ?? 2;
|
||||
}
|
||||
|
||||
public function buildHoldCoverSprite(target:NoteHoldCover):Void
|
||||
{
|
||||
// NoteHoldCover has "glow" and "sparks". Right now it only implements "glow"
|
||||
// but "sparks" I believe is meant to be used for the ending of the hold note
|
||||
var glowAtlas:Null<FlxFramesCollection> = buildHoldCoverFrames(false);
|
||||
if (glowAtlas == null)
|
||||
{
|
||||
throw 'Could not load spritesheet for note style: $id';
|
||||
}
|
||||
target.glow.frames = glowAtlas;
|
||||
|
||||
target.antialiasing = !(_data.assets.holdNoteCover?.isPixel ?? false);
|
||||
target.glow.antialiasing = !(_data.assets.holdNoteCover?.isPixel ?? false);
|
||||
target.scale.set(_data.assets.holdNoteCover?.scale ?? 1.0, _data.assets.holdNoteCover?.scale ?? 1.0);
|
||||
target.updateHitbox();
|
||||
target.glow.updateHitbox();
|
||||
|
||||
buildHoldCoverAnimations(target);
|
||||
}
|
||||
|
||||
// we use FlxFramesCollection here so we can combine em into one atlas later
|
||||
var holdCoverFrames:Null<FlxFramesCollection> = null;
|
||||
|
||||
function buildHoldCoverFrames(force:Bool = false):Null<FlxFramesCollection>
|
||||
{
|
||||
if (holdCoverFrames != null && !force) return holdCoverFrames;
|
||||
for (direction in Strumline.DIRECTIONS)
|
||||
{
|
||||
// We make a FlxFramesCollection here so we can combine em into one atlas later
|
||||
var atlas:Null<FlxFramesCollection> = buildHoldCoverFrameForDirection(direction);
|
||||
if (holdCoverFrames == null) holdCoverFrames = atlas;
|
||||
else if (atlas != null) holdCoverFrames = FlxAnimationUtil.combineFramesCollections(holdCoverFrames, atlas);
|
||||
}
|
||||
return holdCoverFrames;
|
||||
}
|
||||
|
||||
function buildHoldCoverFrameForDirection(direction:NoteDirection):Null<FlxFramesCollection>
|
||||
{
|
||||
var directionData = switch (direction)
|
||||
{
|
||||
case LEFT: _data.assets?.holdNoteCover?.data?.left;
|
||||
case DOWN: _data.assets?.holdNoteCover?.data?.down;
|
||||
case UP: _data.assets?.holdNoteCover?.data?.up;
|
||||
case RIGHT: _data.assets?.holdNoteCover?.data?.right;
|
||||
};
|
||||
|
||||
if (directionData == null) return null;
|
||||
|
||||
var holdCoverAssetPath:Null<String> = getHoldCoverDirectionAssetPath(direction) ?? fallback?.getHoldCoverDirectionAssetPath(direction);
|
||||
if (holdCoverAssetPath == null)
|
||||
{
|
||||
FlxG.log.warn('Hold Note Cover asset path not found: ${id}');
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!FunkinSprite.isTextureCached(Paths.image(holdCoverAssetPath)))
|
||||
{
|
||||
FlxG.log.warn('Hold Note Cover texture not cached: ${holdCoverAssetPath}');
|
||||
}
|
||||
|
||||
var atlas:FlxFramesCollection = Paths.getSparrowAtlas(holdCoverAssetPath, getAssetLibrary(getHoldCoverDirectionAssetPath(direction, true)));
|
||||
if (atlas == null) return null;
|
||||
|
||||
atlas.parent.persist = true;
|
||||
|
||||
return atlas;
|
||||
}
|
||||
|
||||
function buildHoldCoverAnimations(target:NoteHoldCover):Void
|
||||
{
|
||||
for (direction in Strumline.DIRECTIONS)
|
||||
{
|
||||
var animData:Null<Array<AnimationData>> = fetchHoldCoverAnimationData(direction);
|
||||
if (animData != null)
|
||||
{
|
||||
// this entry is the base animation that plays ("holdCover$noteColor" animation), which we want to loop
|
||||
animData[1].looped = true;
|
||||
FlxAnimationUtil.addAtlasAnimations(target.glow, animData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fetchHoldCoverAnimationData(dir:NoteDirection):Null<Array<AnimationData>>
|
||||
{
|
||||
var noteColor:String = dir.colorName.toTitleCase();
|
||||
var result:Array<Null<AnimationData>> = switch (dir)
|
||||
{
|
||||
case LEFT: [
|
||||
_data.assets?.holdNoteCover?.data?.left?.start?.toNamed('holdCoverStart$noteColor'),
|
||||
_data.assets?.holdNoteCover?.data?.left?.hold?.toNamed('holdCover$noteColor'),
|
||||
_data.assets?.holdNoteCover?.data?.left?.end?.toNamed('holdCoverEnd$noteColor'),
|
||||
];
|
||||
case DOWN: [
|
||||
_data.assets?.holdNoteCover?.data?.down?.start?.toNamed('holdCoverStart$noteColor'),
|
||||
_data.assets?.holdNoteCover?.data?.down?.hold?.toNamed('holdCover$noteColor'),
|
||||
_data.assets?.holdNoteCover?.data?.down?.end?.toNamed('holdCoverEnd$noteColor'),
|
||||
];
|
||||
case UP: [
|
||||
_data.assets?.holdNoteCover?.data?.up?.start?.toNamed('holdCoverStart$noteColor'),
|
||||
_data.assets?.holdNoteCover?.data?.up?.hold?.toNamed('holdCover$noteColor'),
|
||||
_data.assets?.holdNoteCover?.data?.up?.end?.toNamed('holdCoverEnd$noteColor'),
|
||||
];
|
||||
case RIGHT: [
|
||||
_data.assets?.holdNoteCover?.data?.right?.start?.toNamed('holdCoverStart$noteColor'),
|
||||
_data.assets?.holdNoteCover?.data?.right?.hold?.toNamed('holdCover$noteColor'),
|
||||
_data.assets?.holdNoteCover?.data?.right?.end?.toNamed('holdCoverEnd$noteColor'),
|
||||
];
|
||||
default: [];
|
||||
};
|
||||
|
||||
// New variable so we can change the type.
|
||||
var filteredResult:Array<AnimationData> = thx.Arrays.filterNull(result);
|
||||
|
||||
if (filteredResult.length == 0) return fallback?.fetchHoldCoverAnimationData(dir) ?? [];
|
||||
|
||||
return filteredResult;
|
||||
}
|
||||
|
||||
// fallbacks:
|
||||
// assetPath for a direction -> root assetpath -> fallback assetpath for direction -> fallback root assetpath
|
||||
// `direction` here is required, however it only is used for fallback purposes
|
||||
function getHoldCoverRootAssetPath(direction:NoteDirection, raw:Bool = false):Null<String>
|
||||
{
|
||||
if (raw)
|
||||
{
|
||||
var rawPath:Null<String> = _data?.assets?.holdNoteCover?.assetPath;
|
||||
// remember, if we need a fallback for our *root* asset path,
|
||||
// we fallback and look for the *direction* asset path first
|
||||
if (rawPath == null) return fallback?.getHoldCoverDirectionAssetPath(direction, true);
|
||||
return rawPath;
|
||||
}
|
||||
|
||||
var parts:Array<String> = getHoldCoverRootAssetPath(direction, true)?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||
if (parts.length == 0) return null;
|
||||
if (parts.length == 1) return getHoldCoverRootAssetPath(direction, true);
|
||||
return parts[1];
|
||||
}
|
||||
|
||||
function getHoldCoverDirectionAssetPath(direction:NoteDirection, raw:Bool = false):Null<String>
|
||||
{
|
||||
if (raw)
|
||||
{
|
||||
var rawPath:Null<String> = switch (direction)
|
||||
{
|
||||
case LEFT: _data?.assets?.holdNoteCover?.data?.left?.assetPath;
|
||||
case DOWN: _data?.assets?.holdNoteCover?.data?.down?.assetPath;
|
||||
case UP: _data?.assets?.holdNoteCover?.data?.up?.assetPath;
|
||||
case RIGHT: _data?.assets?.holdNoteCover?.data?.right?.assetPath;
|
||||
};
|
||||
|
||||
// we don't want to fallback directly just yet, we want to check our root assetpath first
|
||||
if (rawPath == null) return getHoldCoverRootAssetPath(direction, true);
|
||||
return rawPath;
|
||||
}
|
||||
|
||||
var parts:Array<String> = getHoldCoverDirectionAssetPath(direction, true)?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||
if (parts.length == 0) return null;
|
||||
if (parts.length == 1) return getHoldCoverDirectionAssetPath(direction, true);
|
||||
return parts[1];
|
||||
}
|
||||
|
||||
public function getHoldCoverOffsets():Array<Float>
|
||||
{
|
||||
return _data?.assets?.holdNoteCover?.offsets ?? fallback?.getHoldCoverOffsets() ?? [0.0, 0.0];
|
||||
}
|
||||
|
||||
public function destroy():Void {}
|
||||
|
||||
/**
|
||||
* Returns a string of the library name for the given asset id
|
||||
* `default:assets/images/awesome.png` returns `default`
|
||||
* If you pass a asset path with no library name (no `:` aka LIBRARY_SEPARATOR) it will return null
|
||||
* @param id The asset id to get the library name from
|
||||
* @return Null<String> The library name, or null if no library name is present
|
||||
*/
|
||||
function getAssetLibrary(?id:String):Null<String>
|
||||
{
|
||||
var parts:Array<String> = id?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||
if (parts.length <= 1) return null;
|
||||
|
||||
return parts[0];
|
||||
}
|
||||
|
||||
public function toString():String
|
||||
{
|
||||
return 'NoteStyle($id)';
|
||||
|
||||
@@ -9,7 +9,7 @@ class FlxAnimationUtil
|
||||
/**
|
||||
* Properly adds an animation to a sprite based on the provided animation data.
|
||||
*/
|
||||
public static function addAtlasAnimation(target:FlxSprite, anim:AnimationData)
|
||||
public static function addAtlasAnimation(target:FlxSprite, anim:AnimationData):Void
|
||||
{
|
||||
var frameRate = anim.frameRate == null ? 24 : anim.frameRate;
|
||||
var looped = anim.looped == null ? false : anim.looped;
|
||||
@@ -33,7 +33,7 @@ class FlxAnimationUtil
|
||||
/**
|
||||
* Properly adds multiple animations to a sprite based on the provided animation data.
|
||||
*/
|
||||
public static function addAtlasAnimations(target:FlxSprite, animations:Array<AnimationData>)
|
||||
public static function addAtlasAnimations(target:FlxSprite, animations:Array<AnimationData>):Void
|
||||
{
|
||||
for (anim in animations)
|
||||
{
|
||||
@@ -41,6 +41,12 @@ class FlxAnimationUtil
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine two FlxFramesCollection objects into one.
|
||||
* @param a The first FlxFramesCollection
|
||||
* @param b The second FlxFramesCollection
|
||||
* @return FlxFramesCollection The combined FlxFramesCollection
|
||||
*/
|
||||
public static function combineFramesCollections(a:FlxFramesCollection, b:FlxFramesCollection):FlxFramesCollection
|
||||
{
|
||||
var result:FlxFramesCollection = new FlxFramesCollection(null, ATLAS, null);
|
||||
|
||||
Reference in New Issue
Block a user