mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2024-11-15 11:22:55 +00:00
Custom coutndown, judgements, and combo count now use the note style file instead of hardcoded paths.
This commit is contained in:
parent
d07564cdc2
commit
41bd0246ac
2
assets
2
assets
|
@ -1 +1 @@
|
||||||
Subproject commit 3a9e0510841533f96228609dcd50f2515443bb90
|
Subproject commit c4bd5281880ac2a1e26016c1219824d2f4247536
|
|
@ -263,7 +263,7 @@ abstract class BaseRegistry<T:(IRegistryEntry<J> & Constructible<EntryConstructo
|
||||||
* @param version The entry's version (use `fetchEntryVersion(id)`).
|
* @param version The entry's version (use `fetchEntryVersion(id)`).
|
||||||
* @return The created entry.
|
* @return The created entry.
|
||||||
*/
|
*/
|
||||||
public function parseEntryDataWithMigration(id:String, version:thx.semver.Version):Null<J>
|
public function parseEntryDataWithMigration(id:String, version:Null<thx.semver.Version>):Null<J>
|
||||||
{
|
{
|
||||||
if (version == null)
|
if (version == null)
|
||||||
{
|
{
|
||||||
|
|
31
source/funkin/data/notestyle/CHANGELOG.md
Normal file
31
source/funkin/data/notestyle/CHANGELOG.md
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# Note Style Data Schema Changelog
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
## [1.1.0]
|
||||||
|
### Added
|
||||||
|
- Added several new `assets`:
|
||||||
|
- `countdownThree`
|
||||||
|
- `countdownTwo`
|
||||||
|
- `countdownOne`
|
||||||
|
- `countdownGo`
|
||||||
|
- `judgementSick`
|
||||||
|
- `judgementGood`
|
||||||
|
- `judgementBad`
|
||||||
|
- `judgementShit`
|
||||||
|
- `comboNumber0`
|
||||||
|
- `comboNumber1`
|
||||||
|
- `comboNumber2`
|
||||||
|
- `comboNumber3`
|
||||||
|
- `comboNumber4`
|
||||||
|
- `comboNumber5`
|
||||||
|
- `comboNumber6`
|
||||||
|
- `comboNumber7`
|
||||||
|
- `comboNumber8`
|
||||||
|
- `comboNumber9`
|
||||||
|
|
||||||
|
## [1.0.0]
|
||||||
|
Initial version.
|
|
@ -74,6 +74,84 @@ typedef NoteStyleAssetsData =
|
||||||
*/
|
*/
|
||||||
@:optional
|
@:optional
|
||||||
var holdNoteCover:NoteStyleAssetData<NoteStyleData_HoldNoteCover>;
|
var holdNoteCover:NoteStyleAssetData<NoteStyleData_HoldNoteCover>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The THREE sound (and an optional pre-READY graphic).
|
||||||
|
*/
|
||||||
|
@:optional
|
||||||
|
var countdownThree:NoteStyleAssetData<NoteStyleData_Countdown>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The TWO sound and READY graphic.
|
||||||
|
*/
|
||||||
|
@:optional
|
||||||
|
var countdownTwo:NoteStyleAssetData<NoteStyleData_Countdown>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ONE sound and SET graphic.
|
||||||
|
*/
|
||||||
|
@:optional
|
||||||
|
var countdownOne:NoteStyleAssetData<NoteStyleData_Countdown>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GO sound and GO! graphic.
|
||||||
|
*/
|
||||||
|
@:optional
|
||||||
|
var countdownGo:NoteStyleAssetData<NoteStyleData_Countdown>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SICK! judgement.
|
||||||
|
*/
|
||||||
|
@:optional
|
||||||
|
var judgementSick:NoteStyleAssetData<NoteStyleData_Judgement>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GOOD! judgement.
|
||||||
|
*/
|
||||||
|
@:optional
|
||||||
|
var judgementGood:NoteStyleAssetData<NoteStyleData_Judgement>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The BAD! judgement.
|
||||||
|
*/
|
||||||
|
@:optional
|
||||||
|
var judgementBad:NoteStyleAssetData<NoteStyleData_Judgement>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SHIT! judgement.
|
||||||
|
*/
|
||||||
|
@:optional
|
||||||
|
var judgementShit:NoteStyleAssetData<NoteStyleData_Judgement>;
|
||||||
|
|
||||||
|
@:optional
|
||||||
|
var comboNumber0:NoteStyleAssetData<NoteStyleData_ComboNum>;
|
||||||
|
|
||||||
|
@:optional
|
||||||
|
var comboNumber1:NoteStyleAssetData<NoteStyleData_ComboNum>;
|
||||||
|
|
||||||
|
@:optional
|
||||||
|
var comboNumber2:NoteStyleAssetData<NoteStyleData_ComboNum>;
|
||||||
|
|
||||||
|
@:optional
|
||||||
|
var comboNumber3:NoteStyleAssetData<NoteStyleData_ComboNum>;
|
||||||
|
|
||||||
|
@:optional
|
||||||
|
var comboNumber4:NoteStyleAssetData<NoteStyleData_ComboNum>;
|
||||||
|
|
||||||
|
@:optional
|
||||||
|
var comboNumber5:NoteStyleAssetData<NoteStyleData_ComboNum>;
|
||||||
|
|
||||||
|
@:optional
|
||||||
|
var comboNumber6:NoteStyleAssetData<NoteStyleData_ComboNum>;
|
||||||
|
|
||||||
|
@:optional
|
||||||
|
var comboNumber7:NoteStyleAssetData<NoteStyleData_ComboNum>;
|
||||||
|
|
||||||
|
@:optional
|
||||||
|
var comboNumber8:NoteStyleAssetData<NoteStyleData_ComboNum>;
|
||||||
|
|
||||||
|
@:optional
|
||||||
|
var comboNumber9:NoteStyleAssetData<NoteStyleData_ComboNum>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -120,7 +198,8 @@ typedef NoteStyleAssetData<T> =
|
||||||
/**
|
/**
|
||||||
* The structure of this data depends on the asset.
|
* The structure of this data depends on the asset.
|
||||||
*/
|
*/
|
||||||
var data:T;
|
@:optional
|
||||||
|
var data:Null<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef NoteStyleData_Note =
|
typedef NoteStyleData_Note =
|
||||||
|
@ -131,7 +210,14 @@ typedef NoteStyleData_Note =
|
||||||
var right:UnnamedAnimationData;
|
var right:UnnamedAnimationData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef NoteStyleData_Countdown =
|
||||||
|
{
|
||||||
|
var audioPath:String;
|
||||||
|
}
|
||||||
|
|
||||||
typedef NoteStyleData_HoldNote = {}
|
typedef NoteStyleData_HoldNote = {}
|
||||||
|
typedef NoteStyleData_Judgement = {}
|
||||||
|
typedef NoteStyleData_ComboNum = {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data on animations for each direction of the strumline.
|
* Data on animations for each direction of the strumline.
|
||||||
|
|
|
@ -11,9 +11,9 @@ class NoteStyleRegistry extends BaseRegistry<NoteStyle, NoteStyleData>
|
||||||
* Handle breaking changes by incrementing this value
|
* Handle breaking changes by incrementing this value
|
||||||
* and adding migration to the `migrateNoteStyleData()` function.
|
* and adding migration to the `migrateNoteStyleData()` function.
|
||||||
*/
|
*/
|
||||||
public static final NOTE_STYLE_DATA_VERSION:thx.semver.Version = "1.0.0";
|
public static final NOTE_STYLE_DATA_VERSION:thx.semver.Version = "1.1.0";
|
||||||
|
|
||||||
public static final NOTE_STYLE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x";
|
public static final NOTE_STYLE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.1.x";
|
||||||
|
|
||||||
public static var instance(get, never):NoteStyleRegistry;
|
public static var instance(get, never):NoteStyleRegistry;
|
||||||
static var _instance:Null<NoteStyleRegistry> = null;
|
static var _instance:Null<NoteStyleRegistry> = null;
|
||||||
|
|
|
@ -40,8 +40,6 @@ class Countdown
|
||||||
|
|
||||||
static var fallbackNoteStyle:Null<NoteStyle>;
|
static var fallbackNoteStyle:Null<NoteStyle>;
|
||||||
|
|
||||||
static var isPixel:Bool = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The currently running countdown. This will be null if there is no countdown running.
|
* The currently running countdown. This will be null if there is no countdown running.
|
||||||
*/
|
*/
|
||||||
|
@ -204,18 +202,22 @@ class Countdown
|
||||||
*/
|
*/
|
||||||
public static function reset()
|
public static function reset()
|
||||||
{
|
{
|
||||||
noteStyle = NoteStyleRegistry.instance.fetchDefault();
|
noteStyle = null;
|
||||||
isPixel = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static function fetchNoteStyle():Void
|
/**
|
||||||
|
* Retrieve the note style data (if we haven't already)
|
||||||
|
* @param noteStyleId The id of the note style to fetch. Defaults to the one used by the current PlayState.
|
||||||
|
* @param force Fetch the note style from the registry even if we've already fetched it.
|
||||||
|
*/
|
||||||
|
static function fetchNoteStyle(?noteStyleId:String, force:Bool = false):Void
|
||||||
{
|
{
|
||||||
var fetchedNoteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(PlayState.instance.currentChart.noteStyle);
|
if (noteStyle != null && !force) return;
|
||||||
if (fetchedNoteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault();
|
|
||||||
else
|
if (noteStyleId == null) noteStyleId = PlayState.instance?.currentChart?.noteStyle;
|
||||||
noteStyle = fetchedNoteStyle;
|
|
||||||
fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID());
|
noteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyleId);
|
||||||
isPixel = false;
|
if (noteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -223,40 +225,13 @@ class Countdown
|
||||||
*/
|
*/
|
||||||
public static function showCountdownGraphic(index:CountdownStep):Void
|
public static function showCountdownGraphic(index:CountdownStep):Void
|
||||||
{
|
{
|
||||||
var indexString:String = null;
|
fetchNoteStyle();
|
||||||
switch (index)
|
|
||||||
{
|
|
||||||
case TWO:
|
|
||||||
indexString = 'ready';
|
|
||||||
case ONE:
|
|
||||||
indexString = 'set';
|
|
||||||
case GO:
|
|
||||||
indexString = 'go';
|
|
||||||
default:
|
|
||||||
// null
|
|
||||||
}
|
|
||||||
if (indexString == null) return;
|
|
||||||
|
|
||||||
var spritePath:String = null;
|
var countdownSprite = noteStyle.buildCountdownSprite(index);
|
||||||
spritePath = resolveGraphicPath(indexString);
|
if (countdownSprite == null) return;
|
||||||
|
|
||||||
if (spritePath == null) return;
|
|
||||||
|
|
||||||
var countdownSprite:FunkinSprite = FunkinSprite.create(spritePath);
|
|
||||||
countdownSprite.scrollFactor.set(0, 0);
|
|
||||||
|
|
||||||
if (isGraphicPixel) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE));
|
|
||||||
else
|
|
||||||
countdownSprite.setGraphicSize(Std.int(countdownSprite.width * 0.7));
|
|
||||||
|
|
||||||
var fadeEase = FlxEase.cubeInOut;
|
var fadeEase = FlxEase.cubeInOut;
|
||||||
if (isGraphicPixel) fadeEase = EaseUtil.stepped(8);
|
if (noteStyle.isCountdownSpritePixel(index)) fadeEase = EaseUtil.stepped(8);
|
||||||
|
|
||||||
countdownSprite.antialiasing = !isPixel;
|
|
||||||
|
|
||||||
countdownSprite.cameras = [PlayState.instance.camHUD];
|
|
||||||
|
|
||||||
countdownSprite.updateHitbox();
|
|
||||||
|
|
||||||
// Fade sprite in, then out, then destroy it.
|
// Fade sprite in, then out, then destroy it.
|
||||||
FlxTween.tween(countdownSprite, {alpha: 0}, Conductor.instance.beatLengthMs / 1000,
|
FlxTween.tween(countdownSprite, {alpha: 0}, Conductor.instance.beatLengthMs / 1000,
|
||||||
|
@ -267,69 +242,25 @@ class Countdown
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
countdownSprite.cameras = [PlayState.instance.camHUD];
|
||||||
PlayState.instance.add(countdownSprite);
|
PlayState.instance.add(countdownSprite);
|
||||||
countdownSprite.screenCenter();
|
countdownSprite.screenCenter();
|
||||||
}
|
|
||||||
|
|
||||||
static function resolveGraphicPath(index:String):Null<String>
|
var offsets = noteStyle.getCountdownSpriteOffsets(index);
|
||||||
{
|
countdownSprite.x += offsets[0];
|
||||||
fetchNoteStyle();
|
countdownSprite.y += offsets[1];
|
||||||
var basePath:String = 'ui/countdown/';
|
|
||||||
var spritePath:String = basePath + noteStyle.id + '/$index';
|
|
||||||
|
|
||||||
while (!Assets.exists(Paths.image(spritePath)) && fallbackNoteStyle != null)
|
|
||||||
{
|
|
||||||
noteStyle = fallbackNoteStyle;
|
|
||||||
fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID());
|
|
||||||
spritePath = basePath + noteStyle.id + '/$index';
|
|
||||||
}
|
|
||||||
if (noteStyle.isHoldNotePixel()) isPixel = true;
|
|
||||||
|
|
||||||
// If ABSOLUTELY nothing is found, revert it to default notestyle skin
|
|
||||||
if (!Assets.exists(Paths.image(spritePath)))
|
|
||||||
{
|
|
||||||
if (!isPixel) spritePath = basePath + Constants.DEFAULT_NOTE_STYLE + '/$index';
|
|
||||||
else
|
|
||||||
spritePath = basePath + Constants.DEFAULT_PIXEL_NOTE_STYLE + '/$index';
|
|
||||||
}
|
|
||||||
|
|
||||||
trace('Resolved sprite path: ' + Paths.image(spritePath));
|
|
||||||
return spritePath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the sound file to use for this step of the countdown.
|
* Retrieves the sound file to use for this step of the countdown.
|
||||||
*/
|
*/
|
||||||
public static function playCountdownSound(step:CountdownStep):Void
|
public static function playCountdownSound(step:CountdownStep):FunkinSound
|
||||||
{
|
{
|
||||||
return FunkinSound.playOnce(Paths.sound(resolveSoundPath(step)), Constants.COUNTDOWN_VOLUME);
|
|
||||||
}
|
|
||||||
|
|
||||||
static function resolveSoundPath(step:CountdownStep):Null<String>
|
|
||||||
{
|
|
||||||
if (step == CountdownStep.BEFORE || step == CountdownStep.AFTER) return null;
|
|
||||||
fetchNoteStyle();
|
fetchNoteStyle();
|
||||||
var basePath:String = 'gameplay/countdown/';
|
var path = noteStyle.getCountdownSoundPath(step);
|
||||||
var soundPath:String = basePath + noteStyle.id + '/intro$step';
|
if (path == null) return null;
|
||||||
|
|
||||||
while (!Assets.exists(Paths.sound(soundPath)) && fallbackNoteStyle != null)
|
return FunkinSound.playOnce(path, Constants.COUNTDOWN_VOLUME);
|
||||||
{
|
|
||||||
noteStyle = fallbackNoteStyle;
|
|
||||||
fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID());
|
|
||||||
soundPath = basePath + noteStyle.id + '/intro$step';
|
|
||||||
}
|
|
||||||
if (noteStyle.isHoldNotePixel()) isPixel = true;
|
|
||||||
|
|
||||||
// If ABSOLUTELY nothing is found, revert it to default notestyle sound
|
|
||||||
if (!Assets.exists(Paths.sound(soundPath)))
|
|
||||||
{
|
|
||||||
if (!isPixel) soundPath = basePath + Constants.DEFAULT_NOTE_STYLE + '/intro$step';
|
|
||||||
else
|
|
||||||
soundPath = basePath + Constants.DEFAULT_PIXEL_NOTE_STYLE + '/intro$step';
|
|
||||||
}
|
|
||||||
|
|
||||||
trace('Resolved sound path: ' + soundPath);
|
|
||||||
return soundPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function decrement(step:CountdownStep):CountdownStep
|
public static function decrement(step:CountdownStep):CountdownStep
|
||||||
|
|
|
@ -694,12 +694,7 @@ class PlayState extends MusicBeatSubState
|
||||||
initMinimalMode();
|
initMinimalMode();
|
||||||
}
|
}
|
||||||
initStrumlines();
|
initStrumlines();
|
||||||
|
initPopups();
|
||||||
// Initialize the judgements and combo meter.
|
|
||||||
comboPopUps = new PopUpStuff();
|
|
||||||
comboPopUps.zIndex = 900;
|
|
||||||
add(comboPopUps);
|
|
||||||
comboPopUps.cameras = [camHUD];
|
|
||||||
|
|
||||||
#if discord_rpc
|
#if discord_rpc
|
||||||
// Initialize Discord Rich Presence.
|
// Initialize Discord Rich Presence.
|
||||||
|
@ -1727,6 +1722,21 @@ class PlayState extends MusicBeatSubState
|
||||||
opponentStrumline.fadeInArrows();
|
opponentStrumline.fadeInArrows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the judgement and combo popups.
|
||||||
|
*/
|
||||||
|
function initPopups():Void
|
||||||
|
{
|
||||||
|
var noteStyleId:String = currentChart.noteStyle;
|
||||||
|
var noteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyleId);
|
||||||
|
if (noteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault();
|
||||||
|
// Initialize the judgements and combo meter.
|
||||||
|
comboPopUps = new PopUpStuff(noteStyle);
|
||||||
|
comboPopUps.zIndex = 900;
|
||||||
|
add(comboPopUps);
|
||||||
|
comboPopUps.cameras = [camHUD];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the Discord Rich Presence.
|
* Initializes the Discord Rich Presence.
|
||||||
*/
|
*/
|
||||||
|
@ -3005,7 +3015,6 @@ class PlayState extends MusicBeatSubState
|
||||||
GameOverSubState.reset();
|
GameOverSubState.reset();
|
||||||
PauseSubState.reset();
|
PauseSubState.reset();
|
||||||
Countdown.reset();
|
Countdown.reset();
|
||||||
PopUpStuff.reset();
|
|
||||||
|
|
||||||
// Clear the static reference to this state.
|
// Clear the static reference to this state.
|
||||||
instance = null;
|
instance = null;
|
||||||
|
|
|
@ -12,103 +12,47 @@ import openfl.utils.Assets;
|
||||||
import funkin.data.notestyle.NoteStyleRegistry;
|
import funkin.data.notestyle.NoteStyleRegistry;
|
||||||
import funkin.play.notes.notestyle.NoteStyle;
|
import funkin.play.notes.notestyle.NoteStyle;
|
||||||
|
|
||||||
|
@:nullSafety
|
||||||
class PopUpStuff extends FlxTypedGroup<FunkinSprite>
|
class PopUpStuff extends FlxTypedGroup<FunkinSprite>
|
||||||
{
|
{
|
||||||
public var offsets:Array<Int> = [0, 0];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Which alternate graphic on popup to use.
|
* The current note style to use. This determines which graphics to display.
|
||||||
* This is set via the current notestyle.
|
* For example, Week 6 uses the `pixel` note style, and mods can create their own.
|
||||||
* For example, in Week 6 it is `pixel`.
|
|
||||||
*/
|
*/
|
||||||
static var noteStyle:NoteStyle;
|
var noteStyle:NoteStyle;
|
||||||
|
|
||||||
static var fallbackNoteStyle:Null<NoteStyle>;
|
override public function new(noteStyle:NoteStyle)
|
||||||
|
|
||||||
static var isPixel:Bool = false;
|
|
||||||
|
|
||||||
override public function new()
|
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
this.noteStyle = noteStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function fetchNoteStyle():Void
|
public function displayRating(daRating:Null<String>)
|
||||||
{
|
{
|
||||||
var fetchedNoteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(PlayState.instance.currentChart.noteStyle);
|
|
||||||
if (fetchedNoteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault();
|
|
||||||
else
|
|
||||||
noteStyle = fetchedNoteStyle;
|
|
||||||
fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID());
|
|
||||||
isPixel = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function resolveGraphicPath(index:String):Null<String>
|
|
||||||
{
|
|
||||||
fetchNoteStyle();
|
|
||||||
var basePath:String = 'ui/popup/';
|
|
||||||
var spritePath:String = basePath + noteStyle.id + '/$index';
|
|
||||||
|
|
||||||
while (!Assets.exists(Paths.image(spritePath)) && fallbackNoteStyle != null)
|
|
||||||
{
|
|
||||||
noteStyle = fallbackNoteStyle;
|
|
||||||
fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID());
|
|
||||||
spritePath = basePath + noteStyle.id + '/$index';
|
|
||||||
}
|
|
||||||
if (noteStyle.isHoldNotePixel()) isPixel = true;
|
|
||||||
|
|
||||||
// If nothing is found, revert it to default notestyle skin
|
|
||||||
if (!Assets.exists(Paths.image(spritePath)))
|
|
||||||
{
|
|
||||||
if (!isPixel) spritePath = basePath + Constants.DEFAULT_NOTE_STYLE + '/$index';
|
|
||||||
else
|
|
||||||
spritePath = basePath + Constants.DEFAULT_PIXEL_NOTE_STYLE + '/$index';
|
|
||||||
}
|
|
||||||
|
|
||||||
return spritePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function displayRating(daRating:String)
|
|
||||||
{
|
|
||||||
var perfStart:Float = TimerUtil.start();
|
|
||||||
|
|
||||||
if (daRating == null) daRating = "good";
|
if (daRating == null) daRating = "good";
|
||||||
|
|
||||||
var ratingPath:String = resolveGraphicPath(daRating);
|
var rating:Null<FunkinSprite> = noteStyle.buildJudgementSprite(daRating);
|
||||||
|
if (rating == null) return;
|
||||||
// if (PlayState.instance.currentStageId.startsWith('school')) ratingPath = "weeb/pixelUI/" + ratingPath + "-pixel";
|
|
||||||
|
|
||||||
var rating:FunkinSprite = FunkinSprite.create(0, 0, ratingPath);
|
|
||||||
rating.scrollFactor.set(0.2, 0.2);
|
|
||||||
|
|
||||||
rating.zIndex = 1000;
|
rating.zIndex = 1000;
|
||||||
rating.x = (FlxG.width * 0.474) + offsets[0];
|
|
||||||
// rating.x -= FlxG.camera.scroll.x * 0.2;
|
rating.x = (FlxG.width * 0.474);
|
||||||
rating.y = (FlxG.camera.height * 0.45 - 60) + offsets[1];
|
rating.x -= rating.width / 2;
|
||||||
|
rating.y = (FlxG.camera.height * 0.45 - 60);
|
||||||
|
rating.y -= rating.height / 2;
|
||||||
|
|
||||||
|
var offsets = noteStyle.getJudgementSpriteOffsets(daRating);
|
||||||
|
rating.x += offsets[0];
|
||||||
|
rating.y += offsets[1];
|
||||||
|
|
||||||
rating.acceleration.y = 550;
|
rating.acceleration.y = 550;
|
||||||
rating.velocity.y -= FlxG.random.int(140, 175);
|
rating.velocity.y -= FlxG.random.int(140, 175);
|
||||||
rating.velocity.x -= FlxG.random.int(0, 10);
|
rating.velocity.x -= FlxG.random.int(0, 10);
|
||||||
|
|
||||||
add(rating);
|
add(rating);
|
||||||
|
|
||||||
var fadeEase = null;
|
var fadeEase = noteStyle.isJudgementSpritePixel(daRating) ? EaseUtil.stepped(2) : null;
|
||||||
|
|
||||||
if (isPixel)
|
|
||||||
{
|
|
||||||
rating.setGraphicSize(Std.int(rating.width * Constants.PIXEL_ART_SCALE * 0.7));
|
|
||||||
rating.antialiasing = false;
|
|
||||||
rating.pixelPerfectRender = true;
|
|
||||||
rating.pixelPerfectPosition = true;
|
|
||||||
fadeEase = EaseUtil.stepped(2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rating.setGraphicSize(Std.int(rating.width * 0.65));
|
|
||||||
rating.antialiasing = true;
|
|
||||||
}
|
|
||||||
rating.updateHitbox();
|
|
||||||
|
|
||||||
rating.x -= rating.width / 2;
|
|
||||||
rating.y -= rating.height / 2;
|
|
||||||
|
|
||||||
FlxTween.tween(rating, {alpha: 0}, 0.2,
|
FlxTween.tween(rating, {alpha: 0}, 0.2,
|
||||||
{
|
{
|
||||||
|
@ -119,55 +63,10 @@ class PopUpStuff extends FlxTypedGroup<FunkinSprite>
|
||||||
startDelay: Conductor.instance.beatLengthMs * 0.001,
|
startDelay: Conductor.instance.beatLengthMs * 0.001,
|
||||||
ease: fadeEase
|
ease: fadeEase
|
||||||
});
|
});
|
||||||
|
|
||||||
trace('displayRating took: ${TimerUtil.seconds(perfStart)}');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function displayCombo(?combo:Int = 0):Int
|
public function displayCombo(combo:Int = 0):Void
|
||||||
{
|
{
|
||||||
var perfStart:Float = TimerUtil.start();
|
|
||||||
|
|
||||||
if (combo == null) combo = 0;
|
|
||||||
|
|
||||||
var comboPath:String = resolveGraphicPath('combo');
|
|
||||||
var comboSpr:FunkinSprite = FunkinSprite.create(comboPath);
|
|
||||||
comboSpr.y = (FlxG.camera.height * 0.44) + offsets[1];
|
|
||||||
comboSpr.x = (FlxG.width * 0.507) + offsets[0];
|
|
||||||
// comboSpr.x -= FlxG.camera.scroll.x * 0.2;
|
|
||||||
|
|
||||||
comboSpr.acceleration.y = 600;
|
|
||||||
comboSpr.velocity.y -= 150;
|
|
||||||
comboSpr.velocity.x += FlxG.random.int(1, 10);
|
|
||||||
|
|
||||||
// add(comboSpr);
|
|
||||||
|
|
||||||
var fadeEase = null;
|
|
||||||
|
|
||||||
if (graphicSuffix.toLowerCase().contains('pixel'))
|
|
||||||
{
|
|
||||||
comboSpr.setGraphicSize(Std.int(comboSpr.width * Constants.PIXEL_ART_SCALE * 1));
|
|
||||||
comboSpr.antialiasing = false;
|
|
||||||
comboSpr.pixelPerfectRender = true;
|
|
||||||
comboSpr.pixelPerfectPosition = true;
|
|
||||||
fadeEase = EaseUtil.stepped(2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
comboSpr.setGraphicSize(Std.int(comboSpr.width * 0.7));
|
|
||||||
comboSpr.antialiasing = true;
|
|
||||||
}
|
|
||||||
comboSpr.updateHitbox();
|
|
||||||
|
|
||||||
FlxTween.tween(comboSpr, {alpha: 0}, 0.2,
|
|
||||||
{
|
|
||||||
onComplete: function(tween:FlxTween) {
|
|
||||||
remove(comboSpr, true);
|
|
||||||
comboSpr.destroy();
|
|
||||||
},
|
|
||||||
startDelay: Conductor.instance.beatLengthMs * 0.001,
|
|
||||||
ease: fadeEase
|
|
||||||
});
|
|
||||||
|
|
||||||
var seperatedScore:Array<Int> = [];
|
var seperatedScore:Array<Int> = [];
|
||||||
var tempCombo:Int = combo;
|
var tempCombo:Int = combo;
|
||||||
|
|
||||||
|
@ -182,31 +81,27 @@ class PopUpStuff extends FlxTypedGroup<FunkinSprite>
|
||||||
// seperatedScore.reverse();
|
// seperatedScore.reverse();
|
||||||
|
|
||||||
var daLoop:Int = 1;
|
var daLoop:Int = 1;
|
||||||
for (i in seperatedScore)
|
for (digit in seperatedScore)
|
||||||
{
|
{
|
||||||
var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, resolveGraphicPath('num' + Std.int(i)));
|
var numScore:Null<FunkinSprite> = noteStyle.buildComboNumSprite(digit);
|
||||||
|
if (numScore == null) continue;
|
||||||
|
|
||||||
if (graphicSuffix.toLowerCase().contains('pixel'))
|
numScore.x = (FlxG.width * 0.507) - (36 * daLoop) - 65;
|
||||||
{
|
trace('numScore($daLoop) = ${numScore.x}');
|
||||||
numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 1));
|
numScore.y = (FlxG.camera.height * 0.44);
|
||||||
numScore.antialiasing = false;
|
|
||||||
numScore.pixelPerfectRender = true;
|
var offsets = noteStyle.getComboNumSpriteOffsets(digit);
|
||||||
numScore.pixelPerfectPosition = true;
|
numScore.x += offsets[0];
|
||||||
}
|
numScore.y += offsets[1];
|
||||||
else
|
|
||||||
{
|
|
||||||
numScore.setGraphicSize(Std.int(numScore.width * 0.45));
|
|
||||||
numScore.antialiasing = true;
|
|
||||||
}
|
|
||||||
numScore.updateHitbox();
|
|
||||||
|
|
||||||
numScore.x = comboSpr.x - (36 * daLoop) - 65; //- 90;
|
|
||||||
numScore.acceleration.y = FlxG.random.int(250, 300);
|
numScore.acceleration.y = FlxG.random.int(250, 300);
|
||||||
numScore.velocity.y -= FlxG.random.int(130, 150);
|
numScore.velocity.y -= FlxG.random.int(130, 150);
|
||||||
numScore.velocity.x = FlxG.random.float(-5, 5);
|
numScore.velocity.x = FlxG.random.float(-5, 5);
|
||||||
|
|
||||||
add(numScore);
|
add(numScore);
|
||||||
|
|
||||||
|
var fadeEase = noteStyle.isComboNumSpritePixel(digit) ? EaseUtil.stepped(2) : null;
|
||||||
|
|
||||||
FlxTween.tween(numScore, {alpha: 0}, 0.2,
|
FlxTween.tween(numScore, {alpha: 0}, 0.2,
|
||||||
{
|
{
|
||||||
onComplete: function(tween:FlxTween) {
|
onComplete: function(tween:FlxTween) {
|
||||||
|
@ -219,18 +114,5 @@ class PopUpStuff extends FlxTypedGroup<FunkinSprite>
|
||||||
|
|
||||||
daLoop++;
|
daLoop++;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace('displayCombo took: ${TimerUtil.seconds(perfStart)}');
|
|
||||||
|
|
||||||
return combo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the popup configuration to the default.
|
|
||||||
*/
|
|
||||||
public static function reset()
|
|
||||||
{
|
|
||||||
noteStyle = NoteStyleRegistry.instance.fetchDefault();
|
|
||||||
isPixel = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,13 @@ class StrumlineNote extends FlxSprite
|
||||||
|
|
||||||
function setup(noteStyle:NoteStyle):Void
|
function setup(noteStyle:NoteStyle):Void
|
||||||
{
|
{
|
||||||
|
if (noteStyle == null)
|
||||||
|
{
|
||||||
|
// If you get an exception on this line, check the debug console.
|
||||||
|
// You probably have a parsing error in your note style's JSON file.
|
||||||
|
throw "FATAL ERROR: Attempted to initialize PlayState with an invalid NoteStyle.";
|
||||||
|
}
|
||||||
|
|
||||||
noteStyle.applyStrumlineFrames(this);
|
noteStyle.applyStrumlineFrames(this);
|
||||||
noteStyle.applyStrumlineAnimations(this, this.direction);
|
noteStyle.applyStrumlineAnimations(this, this.direction);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package funkin.play.notes.notestyle;
|
package funkin.play.notes.notestyle;
|
||||||
|
|
||||||
|
import funkin.play.Countdown;
|
||||||
import flixel.graphics.frames.FlxAtlasFrames;
|
import flixel.graphics.frames.FlxAtlasFrames;
|
||||||
import flixel.graphics.frames.FlxFramesCollection;
|
import flixel.graphics.frames.FlxFramesCollection;
|
||||||
import funkin.data.animation.AnimationData;
|
import funkin.data.animation.AnimationData;
|
||||||
|
@ -16,6 +17,7 @@ using funkin.data.animation.AnimationData.AnimationDataUtil;
|
||||||
* Holds the data for what assets to use for a note style,
|
* Holds the data for what assets to use for a note style,
|
||||||
* and provides convenience methods for building sprites based on them.
|
* and provides convenience methods for building sprites based on them.
|
||||||
*/
|
*/
|
||||||
|
@:nullSafety
|
||||||
class NoteStyle implements IRegistryEntry<NoteStyleData>
|
class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -42,12 +44,8 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
this.id = id;
|
this.id = id;
|
||||||
_data = _fetchData(id);
|
_data = _fetchData(id);
|
||||||
|
|
||||||
if (_data == null)
|
var fallbackID = _data.fallback;
|
||||||
{
|
if (fallbackID != null) this.fallback = NoteStyleRegistry.instance.fetchEntry(fallbackID);
|
||||||
throw 'Could not parse note style data for id: $id';
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fallback = NoteStyleRegistry.instance.fetchEntry(getFallbackID());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,7 +78,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
public function buildNoteSprite(target:NoteSprite):Void
|
public function buildNoteSprite(target:NoteSprite):Void
|
||||||
{
|
{
|
||||||
// Apply the note sprite frames.
|
// Apply the note sprite frames.
|
||||||
var atlas:FlxAtlasFrames = buildNoteFrames(false);
|
var atlas:Null<FlxAtlasFrames> = buildNoteFrames(false);
|
||||||
|
|
||||||
if (atlas == null)
|
if (atlas == null)
|
||||||
{
|
{
|
||||||
|
@ -89,7 +87,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
|
|
||||||
target.frames = atlas;
|
target.frames = atlas;
|
||||||
|
|
||||||
target.antialiasing = !_data.assets.note.isPixel;
|
target.antialiasing = !(_data.assets?.note?.isPixel ?? false);
|
||||||
|
|
||||||
// Apply the animations.
|
// Apply the animations.
|
||||||
buildNoteAnimations(target);
|
buildNoteAnimations(target);
|
||||||
|
@ -99,21 +97,30 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
target.updateHitbox();
|
target.updateHitbox();
|
||||||
}
|
}
|
||||||
|
|
||||||
var noteFrames:FlxAtlasFrames = null;
|
var noteFrames:Null<FlxAtlasFrames> = null;
|
||||||
|
|
||||||
function buildNoteFrames(force:Bool = false):FlxAtlasFrames
|
function buildNoteFrames(force:Bool = false):Null<FlxAtlasFrames>
|
||||||
{
|
{
|
||||||
if (!FunkinSprite.isTextureCached(Paths.image(getNoteAssetPath())))
|
var noteAssetPath = getNoteAssetPath();
|
||||||
|
if (noteAssetPath == null) return null;
|
||||||
|
|
||||||
|
if (!FunkinSprite.isTextureCached(Paths.image(noteAssetPath)))
|
||||||
{
|
{
|
||||||
FlxG.log.warn('Note texture is not cached: ${getNoteAssetPath()}');
|
FlxG.log.warn('Note texture is not cached: ${noteAssetPath}');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Purge the note frames if the cached atlas is invalid.
|
// Purge the note frames if the cached atlas is invalid.
|
||||||
if (noteFrames?.parent?.isDestroyed ?? false) noteFrames = null;
|
@:nullSafety(Off)
|
||||||
|
{
|
||||||
|
if (noteFrames?.parent?.isDestroyed ?? false) noteFrames = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (noteFrames != null && !force) return noteFrames;
|
if (noteFrames != null && !force) return noteFrames;
|
||||||
|
|
||||||
noteFrames = Paths.getSparrowAtlas(getNoteAssetPath(), getNoteAssetLibrary());
|
var noteAssetPath = getNoteAssetPath();
|
||||||
|
if (noteAssetPath == null) return null;
|
||||||
|
|
||||||
|
noteFrames = Paths.getSparrowAtlas(noteAssetPath, getNoteAssetLibrary());
|
||||||
|
|
||||||
if (noteFrames == null)
|
if (noteFrames == null)
|
||||||
{
|
{
|
||||||
|
@ -123,17 +130,18 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
return noteFrames;
|
return noteFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNoteAssetPath(raw:Bool = false):String
|
function getNoteAssetPath(raw:Bool = false):Null<String>
|
||||||
{
|
{
|
||||||
if (raw)
|
if (raw)
|
||||||
{
|
{
|
||||||
var rawPath:Null<String> = _data?.assets?.note?.assetPath;
|
var rawPath:Null<String> = _data?.assets?.note?.assetPath;
|
||||||
if (rawPath == null) return fallback.getNoteAssetPath(true);
|
if (rawPath == null && fallback != null) return fallback.getNoteAssetPath(true);
|
||||||
return rawPath;
|
return rawPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// library:path
|
// library:path
|
||||||
var parts = getNoteAssetPath(true).split(Constants.LIBRARY_SEPARATOR);
|
var parts = getNoteAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||||
|
if (parts.length == 0) return null;
|
||||||
if (parts.length == 1) return getNoteAssetPath(true);
|
if (parts.length == 1) return getNoteAssetPath(true);
|
||||||
return parts[1];
|
return parts[1];
|
||||||
}
|
}
|
||||||
|
@ -141,57 +149,63 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
function getNoteAssetLibrary():Null<String>
|
function getNoteAssetLibrary():Null<String>
|
||||||
{
|
{
|
||||||
// library:path
|
// library:path
|
||||||
var parts = getNoteAssetPath(true).split(Constants.LIBRARY_SEPARATOR);
|
var parts = getNoteAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||||
|
if (parts.length == 0) return null;
|
||||||
if (parts.length == 1) return null;
|
if (parts.length == 1) return null;
|
||||||
return parts[0];
|
return parts[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildNoteAnimations(target:NoteSprite):Void
|
function buildNoteAnimations(target:NoteSprite):Void
|
||||||
{
|
{
|
||||||
var leftData:AnimationData = fetchNoteAnimationData(LEFT);
|
var leftData:Null<AnimationData> = fetchNoteAnimationData(LEFT);
|
||||||
target.animation.addByPrefix('purpleScroll', leftData.prefix, leftData.frameRate, leftData.looped, leftData.flipX, leftData.flipY);
|
if (leftData != null) target.animation.addByPrefix('purpleScroll', leftData.prefix ?? '', leftData.frameRate ?? 24, leftData.looped ?? false,
|
||||||
var downData:AnimationData = fetchNoteAnimationData(DOWN);
|
leftData.flipX, leftData.flipY);
|
||||||
target.animation.addByPrefix('blueScroll', downData.prefix, downData.frameRate, downData.looped, downData.flipX, downData.flipY);
|
var downData:Null<AnimationData> = fetchNoteAnimationData(DOWN);
|
||||||
var upData:AnimationData = fetchNoteAnimationData(UP);
|
if (downData != null) target.animation.addByPrefix('blueScroll', downData.prefix ?? '', downData.frameRate ?? 24, downData.looped ?? false,
|
||||||
target.animation.addByPrefix('greenScroll', upData.prefix, upData.frameRate, upData.looped, upData.flipX, upData.flipY);
|
downData.flipX, downData.flipY);
|
||||||
var rightData:AnimationData = fetchNoteAnimationData(RIGHT);
|
var upData:Null<AnimationData> = fetchNoteAnimationData(UP);
|
||||||
target.animation.addByPrefix('redScroll', rightData.prefix, rightData.frameRate, rightData.looped, rightData.flipX, rightData.flipY);
|
if (upData != null) target.animation.addByPrefix('greenScroll', upData.prefix ?? '', upData.frameRate ?? 24, upData.looped ?? false, upData.flipX,
|
||||||
|
upData.flipY);
|
||||||
|
var rightData:Null<AnimationData> = fetchNoteAnimationData(RIGHT);
|
||||||
|
if (rightData != null) target.animation.addByPrefix('redScroll', rightData.prefix ?? '', rightData.frameRate ?? 24, rightData.looped ?? false,
|
||||||
|
rightData.flipX, rightData.flipY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isNoteAnimated():Bool
|
public function isNoteAnimated():Bool
|
||||||
{
|
{
|
||||||
return _data.assets.note.animated;
|
return _data.assets?.note?.animated ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getNoteScale():Float
|
public function getNoteScale():Float
|
||||||
{
|
{
|
||||||
return _data.assets.note.scale;
|
return _data.assets?.note?.scale ?? 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchNoteAnimationData(dir:NoteDirection):AnimationData
|
function fetchNoteAnimationData(dir:NoteDirection):Null<AnimationData>
|
||||||
{
|
{
|
||||||
var result:Null<AnimationData> = switch (dir)
|
var result:Null<AnimationData> = switch (dir)
|
||||||
{
|
{
|
||||||
case LEFT: _data.assets.note.data.left.toNamed();
|
case LEFT: _data.assets?.note?.data?.left?.toNamed();
|
||||||
case DOWN: _data.assets.note.data.down.toNamed();
|
case DOWN: _data.assets?.note?.data?.down?.toNamed();
|
||||||
case UP: _data.assets.note.data.up.toNamed();
|
case UP: _data.assets?.note?.data?.up?.toNamed();
|
||||||
case RIGHT: _data.assets.note.data.right.toNamed();
|
case RIGHT: _data.assets?.note?.data?.right?.toNamed();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (result == null) ? fallback.fetchNoteAnimationData(dir) : result;
|
return (result == null && fallback != null) ? fallback.fetchNoteAnimationData(dir) : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHoldNoteAssetPath(raw:Bool = false):String
|
public function getHoldNoteAssetPath(raw:Bool = false):Null<String>
|
||||||
{
|
{
|
||||||
if (raw)
|
if (raw)
|
||||||
{
|
{
|
||||||
// TODO: figure out why ?. didn't work here
|
// TODO: figure out why ?. didn't work here
|
||||||
var rawPath:Null<String> = (_data?.assets?.holdNote == null) ? null : _data?.assets?.holdNote?.assetPath;
|
var rawPath:Null<String> = (_data?.assets?.holdNote == null) ? null : _data?.assets?.holdNote?.assetPath;
|
||||||
return (rawPath == null) ? fallback.getHoldNoteAssetPath(true) : rawPath;
|
return (rawPath == null && fallback != null) ? fallback.getHoldNoteAssetPath(true) : rawPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// library:path
|
// library:path
|
||||||
var parts = getHoldNoteAssetPath(true).split(Constants.LIBRARY_SEPARATOR);
|
var parts = getHoldNoteAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||||
|
if (parts.length == 0) return null;
|
||||||
if (parts.length == 1) return Paths.image(parts[0]);
|
if (parts.length == 1) return Paths.image(parts[0]);
|
||||||
return Paths.image(parts[1], parts[0]);
|
return Paths.image(parts[1], parts[0]);
|
||||||
}
|
}
|
||||||
|
@ -199,15 +213,15 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
public function isHoldNotePixel():Bool
|
public function isHoldNotePixel():Bool
|
||||||
{
|
{
|
||||||
var data = _data?.assets?.holdNote;
|
var data = _data?.assets?.holdNote;
|
||||||
if (data == null) return fallback.isHoldNotePixel();
|
if (data == null && fallback != null) return fallback.isHoldNotePixel();
|
||||||
return data.isPixel;
|
return data?.isPixel ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fetchHoldNoteScale():Float
|
public function fetchHoldNoteScale():Float
|
||||||
{
|
{
|
||||||
var data = _data?.assets?.holdNote;
|
var data = _data?.assets?.holdNote;
|
||||||
if (data == null) return fallback.fetchHoldNoteScale();
|
if (data == null && fallback != null) return fallback.fetchHoldNoteScale();
|
||||||
return data.scale;
|
return data?.scale ?? 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyStrumlineFrames(target:StrumlineNote):Void
|
public function applyStrumlineFrames(target:StrumlineNote):Void
|
||||||
|
@ -215,7 +229,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
// TODO: Add support for multi-Sparrow.
|
// TODO: Add support for multi-Sparrow.
|
||||||
// Will be less annoying after this is merged: https://github.com/HaxeFlixel/flixel/pull/2772
|
// 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() ?? '', getStrumlineAssetLibrary());
|
||||||
|
|
||||||
if (atlas == null)
|
if (atlas == null)
|
||||||
{
|
{
|
||||||
|
@ -224,31 +238,30 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
|
|
||||||
target.frames = atlas;
|
target.frames = atlas;
|
||||||
|
|
||||||
target.scale.x = _data.assets.noteStrumline.scale;
|
target.scale.set(_data.assets.noteStrumline?.scale ?? 1.0);
|
||||||
target.scale.y = _data.assets.noteStrumline.scale;
|
target.antialiasing = !(_data.assets.noteStrumline?.isPixel ?? false);
|
||||||
target.antialiasing = !_data.assets.noteStrumline.isPixel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStrumlineAssetPath(raw:Bool = false):String
|
function getStrumlineAssetPath(raw:Bool = false):Null<String>
|
||||||
{
|
{
|
||||||
if (raw)
|
if (raw)
|
||||||
{
|
{
|
||||||
var rawPath:Null<String> = _data?.assets?.noteStrumline?.assetPath;
|
var rawPath:Null<String> = _data?.assets?.noteStrumline?.assetPath;
|
||||||
if (rawPath == null) return fallback.getStrumlineAssetPath(true);
|
if (rawPath == null && fallback != null) return fallback.getStrumlineAssetPath(true);
|
||||||
return rawPath;
|
return rawPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// library:path
|
// library:path
|
||||||
var parts = getStrumlineAssetPath(true).split(Constants.LIBRARY_SEPARATOR);
|
var parts = getStrumlineAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||||
if (parts.length == 1) return getStrumlineAssetPath(true);
|
if (parts.length <= 1) return getStrumlineAssetPath(true);
|
||||||
return parts[1];
|
return parts[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStrumlineAssetLibrary():Null<String>
|
function getStrumlineAssetLibrary():Null<String>
|
||||||
{
|
{
|
||||||
// library:path
|
// library:path
|
||||||
var parts = getStrumlineAssetPath(true).split(Constants.LIBRARY_SEPARATOR);
|
var parts = getStrumlineAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||||
if (parts.length == 1) return null;
|
if (parts.length <= 1) return null;
|
||||||
return parts[0];
|
return parts[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,60 +272,592 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
|
|
||||||
function getStrumlineAnimationData(dir:NoteDirection):Array<AnimationData>
|
function getStrumlineAnimationData(dir:NoteDirection):Array<AnimationData>
|
||||||
{
|
{
|
||||||
var result:Array<AnimationData> = switch (dir)
|
var result:Array<Null<AnimationData>> = switch (dir)
|
||||||
{
|
{
|
||||||
case NoteDirection.LEFT: [
|
case NoteDirection.LEFT: [
|
||||||
_data.assets.noteStrumline.data.leftStatic.toNamed('static'),
|
_data.assets.noteStrumline?.data?.leftStatic?.toNamed('static'),
|
||||||
_data.assets.noteStrumline.data.leftPress.toNamed('press'),
|
_data.assets.noteStrumline?.data?.leftPress?.toNamed('press'),
|
||||||
_data.assets.noteStrumline.data.leftConfirm.toNamed('confirm'),
|
_data.assets.noteStrumline?.data?.leftConfirm?.toNamed('confirm'),
|
||||||
_data.assets.noteStrumline.data.leftConfirmHold.toNamed('confirm-hold'),
|
_data.assets.noteStrumline?.data?.leftConfirmHold?.toNamed('confirm-hold'),
|
||||||
];
|
];
|
||||||
case NoteDirection.DOWN: [
|
case NoteDirection.DOWN: [
|
||||||
_data.assets.noteStrumline.data.downStatic.toNamed('static'),
|
_data.assets.noteStrumline?.data?.downStatic?.toNamed('static'),
|
||||||
_data.assets.noteStrumline.data.downPress.toNamed('press'),
|
_data.assets.noteStrumline?.data?.downPress?.toNamed('press'),
|
||||||
_data.assets.noteStrumline.data.downConfirm.toNamed('confirm'),
|
_data.assets.noteStrumline?.data?.downConfirm?.toNamed('confirm'),
|
||||||
_data.assets.noteStrumline.data.downConfirmHold.toNamed('confirm-hold'),
|
_data.assets.noteStrumline?.data?.downConfirmHold?.toNamed('confirm-hold'),
|
||||||
];
|
];
|
||||||
case NoteDirection.UP: [
|
case NoteDirection.UP: [
|
||||||
_data.assets.noteStrumline.data.upStatic.toNamed('static'),
|
_data.assets.noteStrumline?.data?.upStatic?.toNamed('static'),
|
||||||
_data.assets.noteStrumline.data.upPress.toNamed('press'),
|
_data.assets.noteStrumline?.data?.upPress?.toNamed('press'),
|
||||||
_data.assets.noteStrumline.data.upConfirm.toNamed('confirm'),
|
_data.assets.noteStrumline?.data?.upConfirm?.toNamed('confirm'),
|
||||||
_data.assets.noteStrumline.data.upConfirmHold.toNamed('confirm-hold'),
|
_data.assets.noteStrumline?.data?.upConfirmHold?.toNamed('confirm-hold'),
|
||||||
];
|
];
|
||||||
case NoteDirection.RIGHT: [
|
case NoteDirection.RIGHT: [
|
||||||
_data.assets.noteStrumline.data.rightStatic.toNamed('static'),
|
_data.assets.noteStrumline?.data?.rightStatic?.toNamed('static'),
|
||||||
_data.assets.noteStrumline.data.rightPress.toNamed('press'),
|
_data.assets.noteStrumline?.data?.rightPress?.toNamed('press'),
|
||||||
_data.assets.noteStrumline.data.rightConfirm.toNamed('confirm'),
|
_data.assets.noteStrumline?.data?.rightConfirm?.toNamed('confirm'),
|
||||||
_data.assets.noteStrumline.data.rightConfirmHold.toNamed('confirm-hold'),
|
_data.assets.noteStrumline?.data?.rightConfirmHold?.toNamed('confirm-hold'),
|
||||||
];
|
];
|
||||||
|
default: [];
|
||||||
};
|
};
|
||||||
|
|
||||||
return result;
|
return thx.Arrays.filterNull(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyStrumlineOffsets(target:StrumlineNote)
|
public function applyStrumlineOffsets(target:StrumlineNote):Void
|
||||||
{
|
{
|
||||||
target.x += _data.assets.noteStrumline.offsets[0];
|
var offsets = _data?.assets?.noteStrumline?.offsets ?? [0.0, 0.0];
|
||||||
target.y += _data.assets.noteStrumline.offsets[1];
|
target.x += offsets[0];
|
||||||
|
target.y += offsets[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStrumlineScale():Float
|
public function getStrumlineScale():Float
|
||||||
{
|
{
|
||||||
return _data.assets.noteStrumline.scale;
|
return _data?.assets?.noteStrumline?.scale ?? 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isNoteSplashEnabled():Bool
|
public function isNoteSplashEnabled():Bool
|
||||||
{
|
{
|
||||||
var data = _data?.assets?.noteSplash?.data;
|
var data = _data?.assets?.noteSplash?.data;
|
||||||
if (data == null) return fallback.isNoteSplashEnabled();
|
if (data == null) return fallback?.isNoteSplashEnabled() ?? false;
|
||||||
return data.enabled;
|
return data.enabled ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isHoldNoteCoverEnabled():Bool
|
public function isHoldNoteCoverEnabled():Bool
|
||||||
{
|
{
|
||||||
var data = _data?.assets?.holdNoteCover?.data;
|
var data = _data?.assets?.holdNoteCover?.data;
|
||||||
if (data == null) return fallback.isHoldNoteCoverEnabled();
|
if (data == null) return fallback?.isHoldNoteCoverEnabled() ?? false;
|
||||||
return data.enabled;
|
return data.enabled ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a sprite for the given step of the countdown.
|
||||||
|
* @param step
|
||||||
|
* @return A `FunkinSprite`, or `null` if no graphic is available for this step.
|
||||||
|
*/
|
||||||
|
public function buildCountdownSprite(step:Countdown.CountdownStep):Null<FunkinSprite>
|
||||||
|
{
|
||||||
|
var result = new FunkinSprite();
|
||||||
|
|
||||||
|
switch (step)
|
||||||
|
{
|
||||||
|
case THREE:
|
||||||
|
if (_data.assets.countdownThree == null) return fallback?.buildCountdownSprite(step);
|
||||||
|
var assetPath = buildCountdownSpritePath(step);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.countdownThree?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.countdownThree?.scale ?? 1.0;
|
||||||
|
case TWO:
|
||||||
|
if (_data.assets.countdownTwo == null) return fallback?.buildCountdownSprite(step);
|
||||||
|
var assetPath = buildCountdownSpritePath(step);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.countdownTwo?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.countdownTwo?.scale ?? 1.0;
|
||||||
|
case ONE:
|
||||||
|
if (_data.assets.countdownOne == null) return fallback?.buildCountdownSprite(step);
|
||||||
|
var assetPath = buildCountdownSpritePath(step);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.countdownOne?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.countdownOne?.scale ?? 1.0;
|
||||||
|
case GO:
|
||||||
|
if (_data.assets.countdownGo == null) return fallback?.buildCountdownSprite(step);
|
||||||
|
var assetPath = buildCountdownSpritePath(step);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.countdownGo?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.countdownGo?.scale ?? 1.0;
|
||||||
|
default:
|
||||||
|
// TODO: Do something here?
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.scrollFactor.set(0, 0);
|
||||||
|
result.antialiasing = !isCountdownSpritePixel(step);
|
||||||
|
result.updateHitbox();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildCountdownSpritePath(step:Countdown.CountdownStep):Null<String>
|
||||||
|
{
|
||||||
|
var basePath:Null<String> = null;
|
||||||
|
switch (step)
|
||||||
|
{
|
||||||
|
case THREE:
|
||||||
|
basePath = _data.assets.countdownThree?.assetPath;
|
||||||
|
case TWO:
|
||||||
|
basePath = _data.assets.countdownTwo?.assetPath;
|
||||||
|
case ONE:
|
||||||
|
basePath = _data.assets.countdownOne?.assetPath;
|
||||||
|
case GO:
|
||||||
|
basePath = _data.assets.countdownGo?.assetPath;
|
||||||
|
default:
|
||||||
|
basePath = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (basePath == null) return fallback?.buildCountdownSpritePath(step);
|
||||||
|
|
||||||
|
var parts = basePath?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||||
|
if (parts.length < 1) return null;
|
||||||
|
if (parts.length == 1) return parts[0];
|
||||||
|
|
||||||
|
return parts[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildCountdownSpriteLibrary(step:Countdown.CountdownStep):Null<String>
|
||||||
|
{
|
||||||
|
var basePath:Null<String> = null;
|
||||||
|
switch (step)
|
||||||
|
{
|
||||||
|
case THREE:
|
||||||
|
basePath = _data.assets.countdownThree?.assetPath;
|
||||||
|
case TWO:
|
||||||
|
basePath = _data.assets.countdownTwo?.assetPath;
|
||||||
|
case ONE:
|
||||||
|
basePath = _data.assets.countdownOne?.assetPath;
|
||||||
|
case GO:
|
||||||
|
basePath = _data.assets.countdownGo?.assetPath;
|
||||||
|
default:
|
||||||
|
basePath = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (basePath == null) return fallback?.buildCountdownSpriteLibrary(step);
|
||||||
|
|
||||||
|
var parts = basePath?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||||
|
if (parts.length <= 1) return null;
|
||||||
|
|
||||||
|
return parts[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isCountdownSpritePixel(step:Countdown.CountdownStep):Bool
|
||||||
|
{
|
||||||
|
switch (step)
|
||||||
|
{
|
||||||
|
case THREE:
|
||||||
|
var result = _data.assets.countdownThree?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step);
|
||||||
|
return result ?? false;
|
||||||
|
case TWO:
|
||||||
|
var result = _data.assets.countdownTwo?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step);
|
||||||
|
return result ?? false;
|
||||||
|
case ONE:
|
||||||
|
var result = _data.assets.countdownOne?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step);
|
||||||
|
return result ?? false;
|
||||||
|
case GO:
|
||||||
|
var result = _data.assets.countdownGo?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step);
|
||||||
|
return result ?? false;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCountdownSpriteOffsets(step:Countdown.CountdownStep):Array<Float>
|
||||||
|
{
|
||||||
|
switch (step)
|
||||||
|
{
|
||||||
|
case THREE:
|
||||||
|
var result = _data.assets.countdownThree?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case TWO:
|
||||||
|
var result = _data.assets.countdownTwo?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case ONE:
|
||||||
|
var result = _data.assets.countdownOne?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case GO:
|
||||||
|
var result = _data.assets.countdownGo?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
default:
|
||||||
|
return [0, 0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCountdownSoundPath(step:Countdown.CountdownStep, raw:Bool = false):Null<String>
|
||||||
|
{
|
||||||
|
if (raw)
|
||||||
|
{
|
||||||
|
// TODO: figure out why ?. didn't work here
|
||||||
|
var rawPath:Null<String> = switch (step)
|
||||||
|
{
|
||||||
|
case Countdown.CountdownStep.THREE:
|
||||||
|
_data.assets.countdownThree?.data?.audioPath;
|
||||||
|
case Countdown.CountdownStep.TWO:
|
||||||
|
_data.assets.countdownTwo?.data?.audioPath;
|
||||||
|
case Countdown.CountdownStep.ONE:
|
||||||
|
_data.assets.countdownOne?.data?.audioPath;
|
||||||
|
case Countdown.CountdownStep.GO:
|
||||||
|
_data.assets.countdownGo?.data?.audioPath;
|
||||||
|
default:
|
||||||
|
null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (rawPath == null && fallback != null) ? fallback.getCountdownSoundPath(step, true) : rawPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// library:path
|
||||||
|
var parts = getCountdownSoundPath(step, true)?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||||
|
if (parts.length == 0) return null;
|
||||||
|
if (parts.length == 1) return Paths.image(parts[0]);
|
||||||
|
return Paths.sound(parts[1], parts[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildJudgementSprite(rating:String):Null<FunkinSprite>
|
||||||
|
{
|
||||||
|
var result = new FunkinSprite();
|
||||||
|
|
||||||
|
switch (rating)
|
||||||
|
{
|
||||||
|
case "sick":
|
||||||
|
if (_data.assets.judgementSick == null) return fallback?.buildJudgementSprite(rating);
|
||||||
|
var assetPath = buildJudgementSpritePath(rating);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.judgementSick?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.judgementSick?.scale ?? 1.0;
|
||||||
|
case "good":
|
||||||
|
if (_data.assets.judgementGood == null) return fallback?.buildJudgementSprite(rating);
|
||||||
|
var assetPath = buildJudgementSpritePath(rating);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.judgementGood?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.judgementGood?.scale ?? 1.0;
|
||||||
|
case "bad":
|
||||||
|
if (_data.assets.judgementBad == null) return fallback?.buildJudgementSprite(rating);
|
||||||
|
var assetPath = buildJudgementSpritePath(rating);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.judgementBad?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.judgementBad?.scale ?? 1.0;
|
||||||
|
case "shit":
|
||||||
|
if (_data.assets.judgementShit == null) return fallback?.buildJudgementSprite(rating);
|
||||||
|
var assetPath = buildJudgementSpritePath(rating);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.judgementShit?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.judgementShit?.scale ?? 1.0;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.scrollFactor.set(0.2, 0.2);
|
||||||
|
var isPixel = isJudgementSpritePixel(rating);
|
||||||
|
result.antialiasing = !isPixel;
|
||||||
|
result.pixelPerfectRender = isPixel;
|
||||||
|
result.pixelPerfectPosition = isPixel;
|
||||||
|
result.updateHitbox();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isJudgementSpritePixel(rating:String):Bool
|
||||||
|
{
|
||||||
|
switch (rating)
|
||||||
|
{
|
||||||
|
case "sick":
|
||||||
|
var result = _data.assets.judgementSick?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating);
|
||||||
|
return result ?? false;
|
||||||
|
case "good":
|
||||||
|
var result = _data.assets.judgementGood?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating);
|
||||||
|
return result ?? false;
|
||||||
|
case "bad":
|
||||||
|
var result = _data.assets.judgementBad?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating);
|
||||||
|
return result ?? false;
|
||||||
|
case "GO":
|
||||||
|
var result = _data.assets.judgementShit?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating);
|
||||||
|
return result ?? false;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildJudgementSpritePath(rating:String):Null<String>
|
||||||
|
{
|
||||||
|
var basePath:Null<String> = null;
|
||||||
|
switch (rating)
|
||||||
|
{
|
||||||
|
case "sick":
|
||||||
|
basePath = _data.assets.judgementSick?.assetPath;
|
||||||
|
case "good":
|
||||||
|
basePath = _data.assets.judgementGood?.assetPath;
|
||||||
|
case "bad":
|
||||||
|
basePath = _data.assets.judgementBad?.assetPath;
|
||||||
|
case "shit":
|
||||||
|
basePath = _data.assets.judgementShit?.assetPath;
|
||||||
|
default:
|
||||||
|
basePath = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (basePath == null) return fallback?.buildJudgementSpritePath(rating);
|
||||||
|
|
||||||
|
var parts = basePath?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||||
|
if (parts.length < 1) return null;
|
||||||
|
if (parts.length == 1) return parts[0];
|
||||||
|
|
||||||
|
return parts[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getJudgementSpriteOffsets(rating:String):Array<Float>
|
||||||
|
{
|
||||||
|
switch (rating)
|
||||||
|
{
|
||||||
|
case "sick":
|
||||||
|
var result = _data.assets.judgementSick?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case "good":
|
||||||
|
var result = _data.assets.judgementGood?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case "bad":
|
||||||
|
var result = _data.assets.judgementBad?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case "shit":
|
||||||
|
var result = _data.assets.judgementShit?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
default:
|
||||||
|
return [0, 0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildComboNumSprite(digit:Int):Null<FunkinSprite>
|
||||||
|
{
|
||||||
|
var result = new FunkinSprite();
|
||||||
|
|
||||||
|
switch (digit)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if (_data.assets.comboNumber0 == null) return fallback?.buildComboNumSprite(digit);
|
||||||
|
var assetPath = buildComboNumSpritePath(digit);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.comboNumber0?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.comboNumber0?.scale ?? 1.0;
|
||||||
|
case 1:
|
||||||
|
if (_data.assets.comboNumber1 == null) return fallback?.buildComboNumSprite(digit);
|
||||||
|
var assetPath = buildComboNumSpritePath(digit);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.comboNumber1?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.comboNumber1?.scale ?? 1.0;
|
||||||
|
case 2:
|
||||||
|
if (_data.assets.comboNumber2 == null) return fallback?.buildComboNumSprite(digit);
|
||||||
|
var assetPath = buildComboNumSpritePath(digit);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.comboNumber2?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.comboNumber2?.scale ?? 1.0;
|
||||||
|
case 3:
|
||||||
|
if (_data.assets.comboNumber3 == null) return fallback?.buildComboNumSprite(digit);
|
||||||
|
var assetPath = buildComboNumSpritePath(digit);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.comboNumber3?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.comboNumber3?.scale ?? 1.0;
|
||||||
|
case 4:
|
||||||
|
if (_data.assets.comboNumber4 == null) return fallback?.buildComboNumSprite(digit);
|
||||||
|
var assetPath = buildComboNumSpritePath(digit);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.comboNumber4?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.comboNumber4?.scale ?? 1.0;
|
||||||
|
case 5:
|
||||||
|
if (_data.assets.comboNumber5 == null) return fallback?.buildComboNumSprite(digit);
|
||||||
|
var assetPath = buildComboNumSpritePath(digit);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.comboNumber5?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.comboNumber5?.scale ?? 1.0;
|
||||||
|
case 6:
|
||||||
|
if (_data.assets.comboNumber6 == null) return fallback?.buildComboNumSprite(digit);
|
||||||
|
var assetPath = buildComboNumSpritePath(digit);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.comboNumber6?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.comboNumber6?.scale ?? 1.0;
|
||||||
|
case 7:
|
||||||
|
if (_data.assets.comboNumber7 == null) return fallback?.buildComboNumSprite(digit);
|
||||||
|
var assetPath = buildComboNumSpritePath(digit);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.comboNumber7?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.comboNumber7?.scale ?? 1.0;
|
||||||
|
case 8:
|
||||||
|
if (_data.assets.comboNumber8 == null) return fallback?.buildComboNumSprite(digit);
|
||||||
|
var assetPath = buildComboNumSpritePath(digit);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.comboNumber8?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.comboNumber8?.scale ?? 1.0;
|
||||||
|
case 9:
|
||||||
|
if (_data.assets.comboNumber9 == null) return fallback?.buildComboNumSprite(digit);
|
||||||
|
var assetPath = buildComboNumSpritePath(digit);
|
||||||
|
if (assetPath == null) return null;
|
||||||
|
result.loadTexture(assetPath);
|
||||||
|
result.scale.x = _data.assets.comboNumber9?.scale ?? 1.0;
|
||||||
|
result.scale.y = _data.assets.comboNumber9?.scale ?? 1.0;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isPixel = isComboNumSpritePixel(digit);
|
||||||
|
result.antialiasing = !isPixel;
|
||||||
|
result.pixelPerfectRender = isPixel;
|
||||||
|
result.pixelPerfectPosition = isPixel;
|
||||||
|
result.updateHitbox();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isComboNumSpritePixel(digit:Int):Bool
|
||||||
|
{
|
||||||
|
switch (digit)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
var result = _data.assets.comboNumber0?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
||||||
|
return result ?? false;
|
||||||
|
case 1:
|
||||||
|
var result = _data.assets.comboNumber1?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
||||||
|
return result ?? false;
|
||||||
|
case 2:
|
||||||
|
var result = _data.assets.comboNumber2?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
||||||
|
return result ?? false;
|
||||||
|
case 3:
|
||||||
|
var result = _data.assets.comboNumber3?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
||||||
|
return result ?? false;
|
||||||
|
case 4:
|
||||||
|
var result = _data.assets.comboNumber4?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
||||||
|
return result ?? false;
|
||||||
|
case 5:
|
||||||
|
var result = _data.assets.comboNumber5?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
||||||
|
return result ?? false;
|
||||||
|
case 6:
|
||||||
|
var result = _data.assets.comboNumber6?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
||||||
|
return result ?? false;
|
||||||
|
case 7:
|
||||||
|
var result = _data.assets.comboNumber7?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
||||||
|
return result ?? false;
|
||||||
|
case 8:
|
||||||
|
var result = _data.assets.comboNumber8?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
||||||
|
return result ?? false;
|
||||||
|
case 9:
|
||||||
|
var result = _data.assets.comboNumber9?.isPixel;
|
||||||
|
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
||||||
|
return result ?? false;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildComboNumSpritePath(digit:Int):Null<String>
|
||||||
|
{
|
||||||
|
var basePath:Null<String> = null;
|
||||||
|
switch (digit)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
basePath = _data.assets.comboNumber0?.assetPath;
|
||||||
|
case 1:
|
||||||
|
basePath = _data.assets.comboNumber1?.assetPath;
|
||||||
|
case 2:
|
||||||
|
basePath = _data.assets.comboNumber2?.assetPath;
|
||||||
|
case 3:
|
||||||
|
basePath = _data.assets.comboNumber3?.assetPath;
|
||||||
|
case 4:
|
||||||
|
basePath = _data.assets.comboNumber4?.assetPath;
|
||||||
|
case 5:
|
||||||
|
basePath = _data.assets.comboNumber5?.assetPath;
|
||||||
|
case 6:
|
||||||
|
basePath = _data.assets.comboNumber6?.assetPath;
|
||||||
|
case 7:
|
||||||
|
basePath = _data.assets.comboNumber7?.assetPath;
|
||||||
|
case 8:
|
||||||
|
basePath = _data.assets.comboNumber8?.assetPath;
|
||||||
|
case 9:
|
||||||
|
basePath = _data.assets.comboNumber9?.assetPath;
|
||||||
|
default:
|
||||||
|
basePath = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (basePath == null) return fallback?.buildComboNumSpritePath(digit);
|
||||||
|
|
||||||
|
var parts = basePath?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||||
|
if (parts.length < 1) return null;
|
||||||
|
if (parts.length == 1) return parts[0];
|
||||||
|
|
||||||
|
return parts[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getComboNumSpriteOffsets(digit:Int):Array<Float>
|
||||||
|
{
|
||||||
|
switch (digit)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
var result = _data.assets.comboNumber0?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case 1:
|
||||||
|
var result = _data.assets.comboNumber1?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case 2:
|
||||||
|
var result = _data.assets.comboNumber2?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case 3:
|
||||||
|
var result = _data.assets.comboNumber3?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case 4:
|
||||||
|
var result = _data.assets.comboNumber4?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case 5:
|
||||||
|
var result = _data.assets.comboNumber5?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case 6:
|
||||||
|
var result = _data.assets.comboNumber6?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case 7:
|
||||||
|
var result = _data.assets.comboNumber7?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case 8:
|
||||||
|
var result = _data.assets.comboNumber8?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
case 9:
|
||||||
|
var result = _data.assets.comboNumber9?.offsets;
|
||||||
|
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
||||||
|
return result ?? [0, 0];
|
||||||
|
default:
|
||||||
|
return [0, 0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy():Void {}
|
public function destroy():Void {}
|
||||||
|
@ -322,8 +867,17 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
return 'NoteStyle($id)';
|
return 'NoteStyle($id)';
|
||||||
}
|
}
|
||||||
|
|
||||||
static function _fetchData(id:String):Null<NoteStyleData>
|
static function _fetchData(id:String):NoteStyleData
|
||||||
{
|
{
|
||||||
return NoteStyleRegistry.instance.parseEntryDataWithMigration(id, NoteStyleRegistry.instance.fetchEntryVersion(id));
|
var result = NoteStyleRegistry.instance.parseEntryDataWithMigration(id, NoteStyleRegistry.instance.fetchEntryVersion(id));
|
||||||
|
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
throw 'Could not parse note style data for id: $id';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,9 @@ class ChartEditorHoldNoteSprite extends SustainTrail
|
||||||
|
|
||||||
override function setupHoldNoteGraphic(noteStyle:NoteStyle):Void
|
override function setupHoldNoteGraphic(noteStyle:NoteStyle):Void
|
||||||
{
|
{
|
||||||
loadGraphic(noteStyle.getHoldNoteAssetPath());
|
var graphicPath = noteStyle.getHoldNoteAssetPath();
|
||||||
|
if (graphicPath == null) return;
|
||||||
|
loadGraphic(graphicPath);
|
||||||
|
|
||||||
antialiasing = true;
|
antialiasing = true;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue