mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-14 19:25:16 -05:00
Merge branch 'rewrite/master' into 70ltan/char-path-fix
This commit is contained in:
commit
6e1ff4a6b1
25 changed files with 1087 additions and 380 deletions
4
.github/actions/setup-haxe/action.yml
vendored
4
.github/actions/setup-haxe/action.yml
vendored
|
@ -60,8 +60,8 @@ runs:
|
|||
haxelib --debug --never deleterepo || true
|
||||
haxelib --debug --never newrepo
|
||||
echo "HAXEPATH=$(haxelib config)" >> "$GITHUB_ENV"
|
||||
haxelib --debug --never git haxelib https://github.com/HaxeFoundation/haxelib.git master
|
||||
haxelib --debug --global install hmm
|
||||
haxelib --debug --always --global git haxelib https://github.com/FunkinCrew/haxelib.git funkin-patches --skip-dependencies
|
||||
haxelib --debug --global --always git hmm https://github.com/FunkinCrew/hmm funkin-patches
|
||||
echo "TIMER_DEPS=$(date +%s)" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Restore cached dependencies
|
||||
|
|
2
assets
2
assets
|
@ -1 +1 @@
|
|||
Subproject commit 005c96f85f4304865acb196e7cc4d6d83f9d76d8
|
||||
Subproject commit 62c4a8203362c1b434de0d376046ebccb96da254
|
4
hmm.json
4
hmm.json
|
@ -104,7 +104,7 @@
|
|||
"type": "git",
|
||||
"dir": null,
|
||||
"url": "https://github.com/HaxeFoundation/hxcpp",
|
||||
"ref": "01cfee282a9a783e10c5a7774a3baaf547e6b0a7"
|
||||
"ref": "8dc8020f8465027de6c2aaaed90718bc693651ed"
|
||||
},
|
||||
{
|
||||
"name": "hxcpp-debug-server",
|
||||
|
@ -178,7 +178,7 @@
|
|||
"name": "openfl",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "228c1b5063911e2ad75cef6e3168ef0a4b9f9134",
|
||||
"ref": "8306425c497766739510ab29e876059c96f77bd2",
|
||||
"url": "https://github.com/FunkinCrew/openfl"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -263,7 +263,7 @@ abstract class BaseRegistry<T:(IRegistryEntry<J> & Constructible<EntryConstructo
|
|||
* @param version The entry's version (use `fetchEntryVersion(id)`).
|
||||
* @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)
|
||||
{
|
||||
|
|
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
|
||||
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.
|
||||
*/
|
||||
var data:T;
|
||||
@:optional
|
||||
var data:Null<T>;
|
||||
}
|
||||
|
||||
typedef NoteStyleData_Note =
|
||||
|
@ -131,7 +210,14 @@ typedef NoteStyleData_Note =
|
|||
var right:UnnamedAnimationData;
|
||||
}
|
||||
|
||||
typedef NoteStyleData_Countdown =
|
||||
{
|
||||
var audioPath:String;
|
||||
}
|
||||
|
||||
typedef NoteStyleData_HoldNote = {}
|
||||
typedef NoteStyleData_Judgement = {}
|
||||
typedef NoteStyleData_ComboNum = {}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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;
|
||||
static var _instance:Null<NoteStyleRegistry> = null;
|
||||
|
|
|
@ -93,8 +93,8 @@ class StageRegistry extends BaseRegistry<Stage, StageData>
|
|||
public function listBaseGameStageIds():Array<String>
|
||||
{
|
||||
return [
|
||||
"mainStage", "spookyMansion", "phillyTrain", "limoRide", "mallXmas", "mallEvil", "school", "schoolEvil", "tankmanBattlefield", "phillyStreets",
|
||||
"phillyBlazin",
|
||||
"mainStage", "spookyMansion", "phillyTrain", "phillyTrainErect", "limoRide", "limoRideErect", "mallXmas", "mallEvil", "school", "schoolEvil",
|
||||
"tankmanBattlefield", "phillyStreets", "phillyBlazin",
|
||||
];
|
||||
}
|
||||
|
||||
|
|
55
source/funkin/graphics/shaders/AdjustColorShader.hx
Normal file
55
source/funkin/graphics/shaders/AdjustColorShader.hx
Normal file
|
@ -0,0 +1,55 @@
|
|||
package funkin.graphics.shaders;
|
||||
|
||||
import flixel.addons.display.FlxRuntimeShader;
|
||||
import funkin.Paths;
|
||||
import openfl.utils.Assets;
|
||||
|
||||
class AdjustColorShader extends FlxRuntimeShader
|
||||
{
|
||||
public var hue(default, set):Float;
|
||||
public var saturation(default, set):Float;
|
||||
public var brightness(default, set):Float;
|
||||
public var contrast(default, set):Float;
|
||||
|
||||
public function new()
|
||||
{
|
||||
super(Assets.getText(Paths.frag('adjustColor')));
|
||||
// FlxG.debugger.addTrackerProfile(new TrackerProfile(HSVShader, ['hue', 'saturation', 'brightness', 'contrast']));
|
||||
hue = 0;
|
||||
saturation = 0;
|
||||
brightness = 0;
|
||||
contrast = 0;
|
||||
}
|
||||
|
||||
function set_hue(value:Float):Float
|
||||
{
|
||||
this.setFloat('hue', value);
|
||||
this.hue = value;
|
||||
|
||||
return this.hue;
|
||||
}
|
||||
|
||||
function set_saturation(value:Float):Float
|
||||
{
|
||||
this.setFloat('saturation', value);
|
||||
this.saturation = value;
|
||||
|
||||
return this.saturation;
|
||||
}
|
||||
|
||||
function set_brightness(value:Float):Float
|
||||
{
|
||||
this.setFloat('brightness', value);
|
||||
this.brightness = value;
|
||||
|
||||
return this.brightness;
|
||||
}
|
||||
|
||||
function set_contrast(value:Float):Float
|
||||
{
|
||||
this.setFloat('contrast', value);
|
||||
this.contrast = value;
|
||||
|
||||
return this.contrast;
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package funkin.graphics.shaders;
|
|||
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxG;
|
||||
import flixel.graphics.frames.FlxFrame;
|
||||
import flixel.addons.display.FlxRuntimeShader;
|
||||
import lime.graphics.opengl.GLProgram;
|
||||
import lime.utils.Log;
|
||||
|
@ -32,6 +33,9 @@ class RuntimePostEffectShader extends FlxRuntimeShader
|
|||
// equals (camera.viewLeft, camera.viewTop, camera.viewRight, camera.viewBottom)
|
||||
uniform vec4 uCameraBounds;
|
||||
|
||||
// equals (frame.left, frame.top, frame.right, frame.bottom)
|
||||
uniform vec4 uFrameBounds;
|
||||
|
||||
// screen coord -> world coord conversion
|
||||
// returns world coord in px
|
||||
vec2 screenToWorld(vec2 screenCoord) {
|
||||
|
@ -56,6 +60,25 @@ class RuntimePostEffectShader extends FlxRuntimeShader
|
|||
return (worldCoord - offset) / scale;
|
||||
}
|
||||
|
||||
// screen coord -> frame coord conversion
|
||||
// returns normalized frame coord
|
||||
vec2 screenToFrame(vec2 screenCoord) {
|
||||
float left = uFrameBounds.x;
|
||||
float top = uFrameBounds.y;
|
||||
float right = uFrameBounds.z;
|
||||
float bottom = uFrameBounds.w;
|
||||
float width = right - left;
|
||||
float height = bottom - top;
|
||||
|
||||
float clampedX = clamp(screenCoord.x, left, right);
|
||||
float clampedY = clamp(screenCoord.y, top, bottom);
|
||||
|
||||
return vec2(
|
||||
(clampedX - left) / (width),
|
||||
(clampedY - top) / (height)
|
||||
);
|
||||
}
|
||||
|
||||
// internally used to get the maximum `openfl_TextureCoordv`
|
||||
vec2 bitmapCoordScale() {
|
||||
return openfl_TextureCoordv / screenCoord;
|
||||
|
@ -80,6 +103,8 @@ class RuntimePostEffectShader extends FlxRuntimeShader
|
|||
{
|
||||
super(fragmentSource, null, glVersion);
|
||||
uScreenResolution.value = [FlxG.width, FlxG.height];
|
||||
uCameraBounds.value = [0, 0, FlxG.width, FlxG.height];
|
||||
uFrameBounds.value = [0, 0, FlxG.width, FlxG.height];
|
||||
}
|
||||
|
||||
// basically `updateViewInfo(FlxG.width, FlxG.height, FlxG.camera)` is good
|
||||
|
@ -89,6 +114,12 @@ class RuntimePostEffectShader extends FlxRuntimeShader
|
|||
uCameraBounds.value = [camera.viewLeft, camera.viewTop, camera.viewRight, camera.viewBottom];
|
||||
}
|
||||
|
||||
public function updateFrameInfo(frame:FlxFrame)
|
||||
{
|
||||
// NOTE: uv.width is actually the right pos and uv.height is the bottom pos
|
||||
uFrameBounds.value = [frame.uv.x, frame.uv.y, frame.uv.width, frame.uv.height];
|
||||
}
|
||||
|
||||
override function __createGLProgram(vertexSource:String, fragmentSource:String):GLProgram
|
||||
{
|
||||
try
|
||||
|
|
|
@ -32,6 +32,14 @@ class RuntimeRainShader extends RuntimePostEffectShader
|
|||
return time = value;
|
||||
}
|
||||
|
||||
public var spriteMode(default, set):Bool = false;
|
||||
|
||||
function set_spriteMode(value:Bool):Bool
|
||||
{
|
||||
this.setBool('uSpriteMode', value);
|
||||
return spriteMode = value;
|
||||
}
|
||||
|
||||
// The scale of the rain depends on the world coordinate system, so higher resolution makes
|
||||
// the raindrops smaller. This parameter can be used to adjust the total scale of the scene.
|
||||
// The size of the raindrops is proportional to the value of this parameter.
|
||||
|
|
|
@ -11,6 +11,9 @@ import funkin.modding.events.ScriptEvent.CountdownScriptEvent;
|
|||
import flixel.util.FlxTimer;
|
||||
import funkin.util.EaseUtil;
|
||||
import funkin.audio.FunkinSound;
|
||||
import openfl.utils.Assets;
|
||||
import funkin.data.notestyle.NoteStyleRegistry;
|
||||
import funkin.play.notes.notestyle.NoteStyle;
|
||||
|
||||
class Countdown
|
||||
{
|
||||
|
@ -19,6 +22,24 @@ class Countdown
|
|||
*/
|
||||
public static var countdownStep(default, null):CountdownStep = BEFORE;
|
||||
|
||||
/**
|
||||
* Which alternate graphic/sound on countdown to use.
|
||||
* This is set via the current notestyle.
|
||||
* For example, in Week 6 it is `pixel`.
|
||||
*/
|
||||
public static var soundSuffix:String = '';
|
||||
|
||||
/**
|
||||
* Which alternate graphic on countdown to use.
|
||||
* You can set this via script.
|
||||
* For example, in Week 6 it is `-pixel`.
|
||||
*/
|
||||
public static var graphicSuffix:String = '';
|
||||
|
||||
static var noteStyle:NoteStyle;
|
||||
|
||||
static var fallbackNoteStyle:Null<NoteStyle>;
|
||||
|
||||
/**
|
||||
* The currently running countdown. This will be null if there is no countdown running.
|
||||
*/
|
||||
|
@ -30,7 +51,7 @@ class Countdown
|
|||
* This will automatically stop and restart the countdown if it is already running.
|
||||
* @returns `false` if the countdown was cancelled by a script.
|
||||
*/
|
||||
public static function performCountdown(isPixelStyle:Bool):Bool
|
||||
public static function performCountdown():Bool
|
||||
{
|
||||
countdownStep = BEFORE;
|
||||
var cancelled:Bool = propagateCountdownEvent(countdownStep);
|
||||
|
@ -65,10 +86,10 @@ class Countdown
|
|||
// PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0));
|
||||
|
||||
// Countdown graphic.
|
||||
showCountdownGraphic(countdownStep, isPixelStyle);
|
||||
showCountdownGraphic(countdownStep);
|
||||
|
||||
// Countdown sound.
|
||||
playCountdownSound(countdownStep, isPixelStyle);
|
||||
playCountdownSound(countdownStep);
|
||||
|
||||
// Event handling bullshit.
|
||||
var cancelled:Bool = propagateCountdownEvent(countdownStep);
|
||||
|
@ -177,122 +198,69 @@ class Countdown
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieves the graphic to use for this step of the countdown.
|
||||
* TODO: Make this less dumb. Unhardcode it? Use modules? Use notestyles?
|
||||
*
|
||||
* This is public so modules can do lol funny shit.
|
||||
* Reset the countdown configuration to the default.
|
||||
*/
|
||||
public static function showCountdownGraphic(index:CountdownStep, isPixelStyle:Bool):Void
|
||||
public static function reset()
|
||||
{
|
||||
var spritePath:String = null;
|
||||
noteStyle = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
if (noteStyle != null && !force) return;
|
||||
|
||||
if (noteStyleId == null) noteStyleId = PlayState.instance?.currentChart?.noteStyle;
|
||||
|
||||
noteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyleId);
|
||||
if (noteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the graphic to use for this step of the countdown.
|
||||
*/
|
||||
public static function showCountdownGraphic(index:CountdownStep):Void
|
||||
{
|
||||
fetchNoteStyle();
|
||||
|
||||
var countdownSprite = noteStyle.buildCountdownSprite(index);
|
||||
if (countdownSprite == null) return;
|
||||
|
||||
var fadeEase = FlxEase.cubeInOut;
|
||||
|
||||
if (isPixelStyle)
|
||||
{
|
||||
fadeEase = EaseUtil.stepped(8);
|
||||
switch (index)
|
||||
{
|
||||
case TWO:
|
||||
spritePath = 'weeb/pixelUI/ready-pixel';
|
||||
case ONE:
|
||||
spritePath = 'weeb/pixelUI/set-pixel';
|
||||
case GO:
|
||||
spritePath = 'weeb/pixelUI/date-pixel';
|
||||
default:
|
||||
// null
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case TWO:
|
||||
spritePath = 'ready';
|
||||
case ONE:
|
||||
spritePath = 'set';
|
||||
case GO:
|
||||
spritePath = 'go';
|
||||
default:
|
||||
// null
|
||||
}
|
||||
}
|
||||
|
||||
if (spritePath == null) return;
|
||||
|
||||
var countdownSprite:FunkinSprite = FunkinSprite.create(spritePath);
|
||||
countdownSprite.scrollFactor.set(0, 0);
|
||||
|
||||
if (isPixelStyle) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE));
|
||||
|
||||
countdownSprite.antialiasing = !isPixelStyle;
|
||||
|
||||
countdownSprite.updateHitbox();
|
||||
countdownSprite.screenCenter();
|
||||
if (noteStyle.isCountdownSpritePixel(index)) fadeEase = EaseUtil.stepped(8);
|
||||
|
||||
// Fade sprite in, then out, then destroy it.
|
||||
FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100}, Conductor.instance.beatLengthMs / 1000,
|
||||
FlxTween.tween(countdownSprite, {alpha: 0}, Conductor.instance.beatLengthMs / 1000,
|
||||
{
|
||||
ease: FlxEase.cubeInOut,
|
||||
ease: fadeEase,
|
||||
onComplete: function(twn:FlxTween) {
|
||||
countdownSprite.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
FlxTween.tween(countdownSprite, {alpha: 0}, Conductor.instance.beatLengthMs / 1000,
|
||||
{
|
||||
ease: fadeEase
|
||||
});
|
||||
|
||||
countdownSprite.cameras = [PlayState.instance.camHUD];
|
||||
PlayState.instance.add(countdownSprite);
|
||||
countdownSprite.screenCenter();
|
||||
|
||||
var offsets = noteStyle.getCountdownSpriteOffsets(index);
|
||||
countdownSprite.x += offsets[0];
|
||||
countdownSprite.y += offsets[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the sound file to use for this step of the countdown.
|
||||
* TODO: Make this less dumb. Unhardcode it? Use modules? Use notestyles?
|
||||
*
|
||||
* This is public so modules can do lol funny shit.
|
||||
*/
|
||||
public static function playCountdownSound(index:CountdownStep, isPixelStyle:Bool):Void
|
||||
public static function playCountdownSound(step:CountdownStep):FunkinSound
|
||||
{
|
||||
var soundPath:String = null;
|
||||
fetchNoteStyle();
|
||||
var path = noteStyle.getCountdownSoundPath(step);
|
||||
if (path == null) return null;
|
||||
|
||||
if (isPixelStyle)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case THREE:
|
||||
soundPath = 'intro3-pixel';
|
||||
case TWO:
|
||||
soundPath = 'intro2-pixel';
|
||||
case ONE:
|
||||
soundPath = 'intro1-pixel';
|
||||
case GO:
|
||||
soundPath = 'introGo-pixel';
|
||||
default:
|
||||
// null
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case THREE:
|
||||
soundPath = 'intro3';
|
||||
case TWO:
|
||||
soundPath = 'intro2';
|
||||
case ONE:
|
||||
soundPath = 'intro1';
|
||||
case GO:
|
||||
soundPath = 'introGo';
|
||||
default:
|
||||
// null
|
||||
}
|
||||
}
|
||||
|
||||
if (soundPath == null) return;
|
||||
|
||||
FunkinSound.playOnce(Paths.sound(soundPath), Constants.COUNTDOWN_VOLUME);
|
||||
return FunkinSound.playOnce(path, Constants.COUNTDOWN_VOLUME);
|
||||
}
|
||||
|
||||
public static function decrement(step:CountdownStep):CountdownStep
|
||||
|
|
|
@ -306,7 +306,7 @@ class PauseSubState extends MusicBeatSubState
|
|||
metadataDifficulty.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT);
|
||||
if (PlayState.instance?.currentDifficulty != null)
|
||||
{
|
||||
metadataDifficulty.text += PlayState.instance.currentDifficulty.toTitleCase();
|
||||
metadataDifficulty.text += PlayState.instance.currentDifficulty.replace('-', ' ').toTitleCase();
|
||||
}
|
||||
metadataDifficulty.scrollFactor.set(0, 0);
|
||||
metadata.add(metadataDifficulty);
|
||||
|
|
|
@ -696,12 +696,7 @@ class PlayState extends MusicBeatSubState
|
|||
initMinimalMode();
|
||||
}
|
||||
initStrumlines();
|
||||
|
||||
// Initialize the judgements and combo meter.
|
||||
comboPopUps = new PopUpStuff();
|
||||
comboPopUps.zIndex = 900;
|
||||
add(comboPopUps);
|
||||
comboPopUps.cameras = [camHUD];
|
||||
initPopups();
|
||||
|
||||
#if discord_rpc
|
||||
// Initialize Discord Rich Presence.
|
||||
|
@ -902,7 +897,7 @@ class PlayState extends MusicBeatSubState
|
|||
health = Constants.HEALTH_STARTING;
|
||||
songScore = 0;
|
||||
Highscore.tallies.combo = 0;
|
||||
Countdown.performCountdown(currentStageId.startsWith('school'));
|
||||
Countdown.performCountdown();
|
||||
|
||||
needsReset = false;
|
||||
}
|
||||
|
@ -1729,6 +1724,21 @@ class PlayState extends MusicBeatSubState
|
|||
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.
|
||||
*/
|
||||
|
@ -1859,7 +1869,7 @@ class PlayState extends MusicBeatSubState
|
|||
public function startCountdown():Void
|
||||
{
|
||||
// If Countdown.performCountdown returns false, then the countdown was canceled by a script.
|
||||
var result:Bool = Countdown.performCountdown(currentStageId.startsWith('school'));
|
||||
var result:Bool = Countdown.performCountdown();
|
||||
if (!result) return;
|
||||
|
||||
isInCutscene = false;
|
||||
|
@ -3010,6 +3020,7 @@ class PlayState extends MusicBeatSubState
|
|||
|
||||
GameOverSubState.reset();
|
||||
PauseSubState.reset();
|
||||
Countdown.reset();
|
||||
|
||||
// Clear the static reference to this state.
|
||||
instance = null;
|
||||
|
|
|
@ -118,22 +118,6 @@ class BaseCharacter extends Bopper
|
|||
*/
|
||||
public var cameraFocusPoint(default, null):FlxPoint = new FlxPoint(0, 0);
|
||||
|
||||
override function set_animOffsets(value:Array<Float>):Array<Float>
|
||||
{
|
||||
if (animOffsets == null) value = [0, 0];
|
||||
if ((animOffsets[0] == value[0]) && (animOffsets[1] == value[1])) return value;
|
||||
|
||||
// Make sure animOffets are halved when scale is 0.5.
|
||||
var xDiff = (animOffsets[0] * this.scale.x / (this.isPixel ? 6 : 1)) - value[0];
|
||||
var yDiff = (animOffsets[1] * this.scale.y / (this.isPixel ? 6 : 1)) - value[1];
|
||||
|
||||
// Call the super function so that camera focus point is not affected.
|
||||
super.set_x(this.x + xDiff);
|
||||
super.set_y(this.y + yDiff);
|
||||
|
||||
return animOffsets = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the x position changes, other than via changing the animation offset,
|
||||
* then we need to update the camera focus point.
|
||||
|
|
|
@ -150,13 +150,17 @@ class HealthIcon extends FunkinSprite
|
|||
{
|
||||
if (characterId == 'bf-old')
|
||||
{
|
||||
isPixel = PlayState.instance.currentStage.getBoyfriend().isPixel;
|
||||
PlayState.instance.currentStage.getBoyfriend().initHealthIcon(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
characterId = 'bf-old';
|
||||
isPixel = false;
|
||||
loadCharacter(characterId);
|
||||
}
|
||||
|
||||
lerpIconSize(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -200,31 +204,45 @@ class HealthIcon extends FunkinSprite
|
|||
|
||||
if (bopEvery != 0)
|
||||
{
|
||||
// Lerp the health icon back to its normal size,
|
||||
// while maintaining aspect ratio.
|
||||
if (this.width > this.height)
|
||||
{
|
||||
// Apply linear interpolation while accounting for frame rate.
|
||||
var targetSize:Int = Std.int(MathUtil.coolLerp(this.width, HEALTH_ICON_SIZE * this.size.x, 0.15));
|
||||
|
||||
setGraphicSize(targetSize, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var targetSize:Int = Std.int(MathUtil.coolLerp(this.height, HEALTH_ICON_SIZE * this.size.y, 0.15));
|
||||
|
||||
setGraphicSize(0, targetSize);
|
||||
}
|
||||
lerpIconSize();
|
||||
|
||||
// Lerp the health icon back to its normal angle.
|
||||
this.angle = MathUtil.coolLerp(this.angle, 0, 0.15);
|
||||
|
||||
this.updateHitbox();
|
||||
}
|
||||
|
||||
this.updatePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the calculation to lerp the icon size. Usually called every frame, but can be forced to the target size.
|
||||
* Mainly forced when changing to old icon to not have a weird lerp related to changing from pixel icon to non-pixel old icon
|
||||
* @param force Force the icon immedialtely to be the target size. Defaults to false.
|
||||
*/
|
||||
function lerpIconSize(force:Bool = false):Void
|
||||
{
|
||||
// Lerp the health icon back to its normal size,
|
||||
// while maintaining aspect ratio.
|
||||
if (this.width > this.height)
|
||||
{
|
||||
// Apply linear interpolation while accounting for frame rate.
|
||||
var targetSize:Int = Std.int(MathUtil.coolLerp(this.width, HEALTH_ICON_SIZE * this.size.x, 0.15));
|
||||
|
||||
if (force) targetSize = Std.int(HEALTH_ICON_SIZE * this.size.x);
|
||||
|
||||
setGraphicSize(targetSize, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var targetSize:Int = Std.int(MathUtil.coolLerp(this.height, HEALTH_ICON_SIZE * this.size.y, 0.15));
|
||||
|
||||
if (force) targetSize = Std.int(HEALTH_ICON_SIZE * this.size.y);
|
||||
|
||||
setGraphicSize(0, targetSize);
|
||||
}
|
||||
|
||||
this.updateHitbox();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the position (and status) of the health icon.
|
||||
*/
|
||||
|
@ -412,6 +430,8 @@ class HealthIcon extends FunkinSprite
|
|||
|
||||
isLegacyStyle = !isNewSpritesheet(charId);
|
||||
|
||||
trace(' Loading health icon for character: $charId (legacy: $isLegacyStyle)');
|
||||
|
||||
if (!isLegacyStyle)
|
||||
{
|
||||
loadSparrow('icons/icon-$charId');
|
||||
|
|
|
@ -8,58 +8,51 @@ import funkin.graphics.FunkinSprite;
|
|||
import funkin.play.PlayState;
|
||||
import funkin.util.TimerUtil;
|
||||
import funkin.util.EaseUtil;
|
||||
import openfl.utils.Assets;
|
||||
import funkin.data.notestyle.NoteStyleRegistry;
|
||||
import funkin.play.notes.notestyle.NoteStyle;
|
||||
|
||||
@:nullSafety
|
||||
class PopUpStuff extends FlxTypedGroup<FunkinSprite>
|
||||
{
|
||||
public var offsets:Array<Int> = [0, 0];
|
||||
/**
|
||||
* The current note style to use. This determines which graphics to display.
|
||||
* For example, Week 6 uses the `pixel` note style, and mods can create their own.
|
||||
*/
|
||||
var noteStyle:NoteStyle;
|
||||
|
||||
override public function new()
|
||||
override public function new(noteStyle:NoteStyle)
|
||||
{
|
||||
super();
|
||||
|
||||
this.noteStyle = noteStyle;
|
||||
}
|
||||
|
||||
public function displayRating(daRating:String):Void
|
||||
public function displayRating(daRating:Null<String>)
|
||||
{
|
||||
var perfStart:Float = TimerUtil.start();
|
||||
|
||||
if (daRating == null) daRating = "good";
|
||||
|
||||
var ratingPath:String = daRating;
|
||||
|
||||
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);
|
||||
var rating:Null<FunkinSprite> = noteStyle.buildJudgementSprite(daRating);
|
||||
if (rating == null) return;
|
||||
|
||||
rating.zIndex = 1000;
|
||||
rating.x = (FlxG.width * 0.474) + offsets[0];
|
||||
// rating.x -= FlxG.camera.scroll.x * 0.2;
|
||||
rating.y = (FlxG.camera.height * 0.45 - 60) + offsets[1];
|
||||
|
||||
rating.x = (FlxG.width * 0.474);
|
||||
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.velocity.y -= FlxG.random.int(140, 175);
|
||||
rating.velocity.x -= FlxG.random.int(0, 10);
|
||||
|
||||
add(rating);
|
||||
|
||||
var fadeEase = null;
|
||||
|
||||
if (PlayState.instance.currentStageId.startsWith('school'))
|
||||
{
|
||||
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;
|
||||
var fadeEase = noteStyle.isJudgementSpritePixel(daRating) ? EaseUtil.stepped(2) : null;
|
||||
|
||||
FlxTween.tween(rating, {alpha: 0}, 0.2,
|
||||
{
|
||||
|
@ -70,62 +63,10 @@ class PopUpStuff extends FlxTypedGroup<FunkinSprite>
|
|||
startDelay: Conductor.instance.beatLengthMs * 0.001,
|
||||
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 pixelShitPart1:String = "";
|
||||
var pixelShitPart2:String = '';
|
||||
|
||||
if (PlayState.instance.currentStageId.startsWith('school'))
|
||||
{
|
||||
pixelShitPart1 = 'weeb/pixelUI/';
|
||||
pixelShitPart2 = '-pixel';
|
||||
}
|
||||
var comboSpr:FunkinSprite = FunkinSprite.create(pixelShitPart1 + 'combo' + pixelShitPart2);
|
||||
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 (PlayState.instance.currentStageId.startsWith('school'))
|
||||
{
|
||||
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 tempCombo:Int = combo;
|
||||
|
||||
|
@ -140,31 +81,27 @@ class PopUpStuff extends FlxTypedGroup<FunkinSprite>
|
|||
// seperatedScore.reverse();
|
||||
|
||||
var daLoop:Int = 1;
|
||||
for (i in seperatedScore)
|
||||
for (digit in seperatedScore)
|
||||
{
|
||||
var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, pixelShitPart1 + 'num' + Std.int(i) + pixelShitPart2);
|
||||
var numScore:Null<FunkinSprite> = noteStyle.buildComboNumSprite(digit);
|
||||
if (numScore == null) continue;
|
||||
|
||||
if (PlayState.instance.currentStageId.startsWith('school'))
|
||||
{
|
||||
numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 1));
|
||||
numScore.antialiasing = false;
|
||||
numScore.pixelPerfectRender = true;
|
||||
numScore.pixelPerfectPosition = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
numScore.setGraphicSize(Std.int(numScore.width * 0.45));
|
||||
numScore.antialiasing = true;
|
||||
}
|
||||
numScore.updateHitbox();
|
||||
numScore.x = (FlxG.width * 0.507) - (36 * daLoop) - 65;
|
||||
trace('numScore($daLoop) = ${numScore.x}');
|
||||
numScore.y = (FlxG.camera.height * 0.44);
|
||||
|
||||
var offsets = noteStyle.getComboNumSpriteOffsets(digit);
|
||||
numScore.x += offsets[0];
|
||||
numScore.y += offsets[1];
|
||||
|
||||
numScore.x = comboSpr.x - (36 * daLoop) - 65; //- 90;
|
||||
numScore.acceleration.y = FlxG.random.int(250, 300);
|
||||
numScore.velocity.y -= FlxG.random.int(130, 150);
|
||||
numScore.velocity.x = FlxG.random.float(-5, 5);
|
||||
|
||||
add(numScore);
|
||||
|
||||
var fadeEase = noteStyle.isComboNumSpritePixel(digit) ? EaseUtil.stepped(2) : null;
|
||||
|
||||
FlxTween.tween(numScore, {alpha: 0}, 0.2,
|
||||
{
|
||||
onComplete: function(tween:FlxTween) {
|
||||
|
@ -177,9 +114,5 @@ class PopUpStuff extends FlxTypedGroup<FunkinSprite>
|
|||
|
||||
daLoop++;
|
||||
}
|
||||
|
||||
trace('displayCombo took: ${TimerUtil.seconds(perfStart)}');
|
||||
|
||||
return combo;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,6 +75,13 @@ class StrumlineNote extends FlxSprite
|
|||
|
||||
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.applyStrumlineAnimations(this, this.direction);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package funkin.play.notes.notestyle;
|
||||
|
||||
import funkin.play.Countdown;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.graphics.frames.FlxFramesCollection;
|
||||
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,
|
||||
* and provides convenience methods for building sprites based on them.
|
||||
*/
|
||||
@:nullSafety
|
||||
class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||
{
|
||||
/**
|
||||
|
@ -42,12 +44,8 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
|||
this.id = id;
|
||||
_data = _fetchData(id);
|
||||
|
||||
if (_data == null)
|
||||
{
|
||||
throw 'Could not parse note style data for id: $id';
|
||||
}
|
||||
|
||||
this.fallback = NoteStyleRegistry.instance.fetchEntry(getFallbackID());
|
||||
var fallbackID = _data.fallback;
|
||||
if (fallbackID != null) this.fallback = NoteStyleRegistry.instance.fetchEntry(fallbackID);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,7 +70,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
|||
* Get the note style ID of the parent note style.
|
||||
* @return The string ID, or `null` if there is no parent.
|
||||
*/
|
||||
function getFallbackID():Null<String>
|
||||
public function getFallbackID():Null<String>
|
||||
{
|
||||
return _data.fallback;
|
||||
}
|
||||
|
@ -80,7 +78,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
|||
public function buildNoteSprite(target:NoteSprite):Void
|
||||
{
|
||||
// Apply the note sprite frames.
|
||||
var atlas:FlxAtlasFrames = buildNoteFrames(false);
|
||||
var atlas:Null<FlxAtlasFrames> = buildNoteFrames(false);
|
||||
|
||||
if (atlas == null)
|
||||
{
|
||||
|
@ -89,7 +87,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
|||
|
||||
target.frames = atlas;
|
||||
|
||||
target.antialiasing = !_data.assets.note.isPixel;
|
||||
target.antialiasing = !(_data.assets?.note?.isPixel ?? false);
|
||||
|
||||
// Apply the animations.
|
||||
buildNoteAnimations(target);
|
||||
|
@ -99,21 +97,30 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
|||
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.
|
||||
if (noteFrames?.parent?.isDestroyed ?? false) noteFrames = null;
|
||||
@:nullSafety(Off)
|
||||
{
|
||||
if (noteFrames?.parent?.isDestroyed ?? false) noteFrames = null;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -123,17 +130,18 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
|||
return noteFrames;
|
||||
}
|
||||
|
||||
function getNoteAssetPath(raw:Bool = false):String
|
||||
function getNoteAssetPath(raw:Bool = false):Null<String>
|
||||
{
|
||||
if (raw)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
return parts[1];
|
||||
}
|
||||
|
@ -141,57 +149,63 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
|||
function getNoteAssetLibrary():Null<String>
|
||||
{
|
||||
// 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;
|
||||
return parts[0];
|
||||
}
|
||||
|
||||
function buildNoteAnimations(target:NoteSprite):Void
|
||||
{
|
||||
var leftData:AnimationData = fetchNoteAnimationData(LEFT);
|
||||
target.animation.addByPrefix('purpleScroll', leftData.prefix, leftData.frameRate, leftData.looped, leftData.flipX, leftData.flipY);
|
||||
var downData:AnimationData = fetchNoteAnimationData(DOWN);
|
||||
target.animation.addByPrefix('blueScroll', downData.prefix, downData.frameRate, downData.looped, downData.flipX, downData.flipY);
|
||||
var upData:AnimationData = fetchNoteAnimationData(UP);
|
||||
target.animation.addByPrefix('greenScroll', upData.prefix, upData.frameRate, upData.looped, upData.flipX, upData.flipY);
|
||||
var rightData:AnimationData = fetchNoteAnimationData(RIGHT);
|
||||
target.animation.addByPrefix('redScroll', rightData.prefix, rightData.frameRate, rightData.looped, rightData.flipX, rightData.flipY);
|
||||
var leftData:Null<AnimationData> = fetchNoteAnimationData(LEFT);
|
||||
if (leftData != null) target.animation.addByPrefix('purpleScroll', leftData.prefix ?? '', leftData.frameRate ?? 24, leftData.looped ?? false,
|
||||
leftData.flipX, leftData.flipY);
|
||||
var downData:Null<AnimationData> = fetchNoteAnimationData(DOWN);
|
||||
if (downData != null) target.animation.addByPrefix('blueScroll', downData.prefix ?? '', downData.frameRate ?? 24, downData.looped ?? false,
|
||||
downData.flipX, downData.flipY);
|
||||
var upData:Null<AnimationData> = fetchNoteAnimationData(UP);
|
||||
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
|
||||
{
|
||||
return _data.assets.note.animated;
|
||||
return _data.assets?.note?.animated ?? false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
case LEFT: _data.assets.note.data.left.toNamed();
|
||||
case DOWN: _data.assets.note.data.down.toNamed();
|
||||
case UP: _data.assets.note.data.up.toNamed();
|
||||
case RIGHT: _data.assets.note.data.right.toNamed();
|
||||
case LEFT: _data.assets?.note?.data?.left?.toNamed();
|
||||
case DOWN: _data.assets?.note?.data?.down?.toNamed();
|
||||
case UP: _data.assets?.note?.data?.up?.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)
|
||||
{
|
||||
// TODO: figure out why ?. didn't work here
|
||||
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
|
||||
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]);
|
||||
return Paths.image(parts[1], parts[0]);
|
||||
}
|
||||
|
@ -199,15 +213,15 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
|||
public function isHoldNotePixel():Bool
|
||||
{
|
||||
var data = _data?.assets?.holdNote;
|
||||
if (data == null) return fallback.isHoldNotePixel();
|
||||
return data.isPixel;
|
||||
if (data == null && fallback != null) return fallback.isHoldNotePixel();
|
||||
return data?.isPixel ?? false;
|
||||
}
|
||||
|
||||
public function fetchHoldNoteScale():Float
|
||||
{
|
||||
var data = _data?.assets?.holdNote;
|
||||
if (data == null) return fallback.fetchHoldNoteScale();
|
||||
return data.scale;
|
||||
if (data == null && fallback != null) return fallback.fetchHoldNoteScale();
|
||||
return data?.scale ?? 1.0;
|
||||
}
|
||||
|
||||
public function applyStrumlineFrames(target:StrumlineNote):Void
|
||||
|
@ -215,7 +229,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() ?? '', getStrumlineAssetLibrary());
|
||||
|
||||
if (atlas == null)
|
||||
{
|
||||
|
@ -224,31 +238,30 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
|||
|
||||
target.frames = atlas;
|
||||
|
||||
target.scale.x = _data.assets.noteStrumline.scale;
|
||||
target.scale.y = _data.assets.noteStrumline.scale;
|
||||
target.antialiasing = !_data.assets.noteStrumline.isPixel;
|
||||
target.scale.set(_data.assets.noteStrumline?.scale ?? 1.0);
|
||||
target.antialiasing = !(_data.assets.noteStrumline?.isPixel ?? false);
|
||||
}
|
||||
|
||||
function getStrumlineAssetPath(raw:Bool = false):String
|
||||
function getStrumlineAssetPath(raw:Bool = false):Null<String>
|
||||
{
|
||||
if (raw)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// library:path
|
||||
var parts = getStrumlineAssetPath(true).split(Constants.LIBRARY_SEPARATOR);
|
||||
if (parts.length == 1) return getStrumlineAssetPath(true);
|
||||
var parts = getStrumlineAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||
if (parts.length <= 1) return getStrumlineAssetPath(true);
|
||||
return parts[1];
|
||||
}
|
||||
|
||||
function getStrumlineAssetLibrary():Null<String>
|
||||
{
|
||||
// library:path
|
||||
var parts = getStrumlineAssetPath(true).split(Constants.LIBRARY_SEPARATOR);
|
||||
if (parts.length == 1) return null;
|
||||
var parts = getStrumlineAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? [];
|
||||
if (parts.length <= 1) return null;
|
||||
return parts[0];
|
||||
}
|
||||
|
||||
|
@ -259,60 +272,592 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
|||
|
||||
function getStrumlineAnimationData(dir:NoteDirection):Array<AnimationData>
|
||||
{
|
||||
var result:Array<AnimationData> = switch (dir)
|
||||
var result:Array<Null<AnimationData>> = switch (dir)
|
||||
{
|
||||
case NoteDirection.LEFT: [
|
||||
_data.assets.noteStrumline.data.leftStatic.toNamed('static'),
|
||||
_data.assets.noteStrumline.data.leftPress.toNamed('press'),
|
||||
_data.assets.noteStrumline.data.leftConfirm.toNamed('confirm'),
|
||||
_data.assets.noteStrumline.data.leftConfirmHold.toNamed('confirm-hold'),
|
||||
_data.assets.noteStrumline?.data?.leftStatic?.toNamed('static'),
|
||||
_data.assets.noteStrumline?.data?.leftPress?.toNamed('press'),
|
||||
_data.assets.noteStrumline?.data?.leftConfirm?.toNamed('confirm'),
|
||||
_data.assets.noteStrumline?.data?.leftConfirmHold?.toNamed('confirm-hold'),
|
||||
];
|
||||
case NoteDirection.DOWN: [
|
||||
_data.assets.noteStrumline.data.downStatic.toNamed('static'),
|
||||
_data.assets.noteStrumline.data.downPress.toNamed('press'),
|
||||
_data.assets.noteStrumline.data.downConfirm.toNamed('confirm'),
|
||||
_data.assets.noteStrumline.data.downConfirmHold.toNamed('confirm-hold'),
|
||||
_data.assets.noteStrumline?.data?.downStatic?.toNamed('static'),
|
||||
_data.assets.noteStrumline?.data?.downPress?.toNamed('press'),
|
||||
_data.assets.noteStrumline?.data?.downConfirm?.toNamed('confirm'),
|
||||
_data.assets.noteStrumline?.data?.downConfirmHold?.toNamed('confirm-hold'),
|
||||
];
|
||||
case NoteDirection.UP: [
|
||||
_data.assets.noteStrumline.data.upStatic.toNamed('static'),
|
||||
_data.assets.noteStrumline.data.upPress.toNamed('press'),
|
||||
_data.assets.noteStrumline.data.upConfirm.toNamed('confirm'),
|
||||
_data.assets.noteStrumline.data.upConfirmHold.toNamed('confirm-hold'),
|
||||
_data.assets.noteStrumline?.data?.upStatic?.toNamed('static'),
|
||||
_data.assets.noteStrumline?.data?.upPress?.toNamed('press'),
|
||||
_data.assets.noteStrumline?.data?.upConfirm?.toNamed('confirm'),
|
||||
_data.assets.noteStrumline?.data?.upConfirmHold?.toNamed('confirm-hold'),
|
||||
];
|
||||
case NoteDirection.RIGHT: [
|
||||
_data.assets.noteStrumline.data.rightStatic.toNamed('static'),
|
||||
_data.assets.noteStrumline.data.rightPress.toNamed('press'),
|
||||
_data.assets.noteStrumline.data.rightConfirm.toNamed('confirm'),
|
||||
_data.assets.noteStrumline.data.rightConfirmHold.toNamed('confirm-hold'),
|
||||
_data.assets.noteStrumline?.data?.rightStatic?.toNamed('static'),
|
||||
_data.assets.noteStrumline?.data?.rightPress?.toNamed('press'),
|
||||
_data.assets.noteStrumline?.data?.rightConfirm?.toNamed('confirm'),
|
||||
_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];
|
||||
target.y += _data.assets.noteStrumline.offsets[1];
|
||||
var offsets = _data?.assets?.noteStrumline?.offsets ?? [0.0, 0.0];
|
||||
target.x += offsets[0];
|
||||
target.y += offsets[1];
|
||||
}
|
||||
|
||||
public function getStrumlineScale():Float
|
||||
{
|
||||
return _data.assets.noteStrumline.scale;
|
||||
return _data?.assets?.noteStrumline?.scale ?? 1.0;
|
||||
}
|
||||
|
||||
public function isNoteSplashEnabled():Bool
|
||||
{
|
||||
var data = _data?.assets?.noteSplash?.data;
|
||||
if (data == null) return fallback.isNoteSplashEnabled();
|
||||
return data.enabled;
|
||||
if (data == null) return fallback?.isNoteSplashEnabled() ?? false;
|
||||
return data.enabled ?? false;
|
||||
}
|
||||
|
||||
public function isHoldNoteCoverEnabled():Bool
|
||||
{
|
||||
var data = _data?.assets?.holdNoteCover?.data;
|
||||
if (data == null) return fallback.isHoldNoteCoverEnabled();
|
||||
return data.enabled;
|
||||
if (data == null) return fallback?.isHoldNoteCoverEnabled() ?? false;
|
||||
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 {}
|
||||
|
@ -322,8 +867,17 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -277,7 +277,8 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
|||
// If there are no difficulties in the metadata, there's a problem.
|
||||
if (metadata.playData.difficulties.length == 0)
|
||||
{
|
||||
trace('[WARN] Song $id has no difficulties listed in metadata!');
|
||||
trace('[SONG] Warning: Song $id (variation ${metadata.variation}) has no difficulties listed in metadata!');
|
||||
continue;
|
||||
}
|
||||
|
||||
// There may be more difficulties in the chart file than in the metadata,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package funkin.play.stage;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxCamera;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.util.FlxTimer;
|
||||
import funkin.modding.IScriptedClass.IPlayStateScriptedClass;
|
||||
|
@ -79,11 +80,6 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
|
|||
if (globalOffsets == null) globalOffsets = [0, 0];
|
||||
if (globalOffsets == value) return value;
|
||||
|
||||
var xDiff = globalOffsets[0] - value[0];
|
||||
var yDiff = globalOffsets[1] - value[1];
|
||||
|
||||
this.x += xDiff;
|
||||
this.y += yDiff;
|
||||
return globalOffsets = value;
|
||||
}
|
||||
|
||||
|
@ -97,12 +93,6 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
|
|||
if (animOffsets == null) animOffsets = [0, 0];
|
||||
if ((animOffsets[0] == value[0]) && (animOffsets[1] == value[1])) return value;
|
||||
|
||||
var xDiff = animOffsets[0] - value[0];
|
||||
var yDiff = animOffsets[1] - value[1];
|
||||
|
||||
this.x += xDiff;
|
||||
this.y += yDiff;
|
||||
|
||||
return animOffsets = value;
|
||||
}
|
||||
|
||||
|
@ -320,14 +310,7 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
|
|||
function applyAnimationOffsets(name:String):Void
|
||||
{
|
||||
var offsets = animationOffsets.get(name);
|
||||
if (offsets != null && !(offsets[0] == 0 && offsets[1] == 0))
|
||||
{
|
||||
this.animOffsets = [offsets[0] + globalOffsets[0], offsets[1] + globalOffsets[1]];
|
||||
}
|
||||
else
|
||||
{
|
||||
this.animOffsets = globalOffsets;
|
||||
}
|
||||
this.animOffsets = offsets;
|
||||
}
|
||||
|
||||
public function isAnimationFinished():Bool
|
||||
|
@ -351,6 +334,15 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
|
|||
return this.animation.curAnim.name;
|
||||
}
|
||||
|
||||
// override getScreenPosition (used by FlxSprite's draw method) to account for animation offsets.
|
||||
override function getScreenPosition(?result:FlxPoint, ?camera:FlxCamera):FlxPoint
|
||||
{
|
||||
var output:FlxPoint = super.getScreenPosition(result, camera);
|
||||
output.x -= (animOffsets[0] - globalOffsets[0]) * this.scale.x;
|
||||
output.y -= (animOffsets[1] - globalOffsets[1]) * this.scale.y;
|
||||
return output;
|
||||
}
|
||||
|
||||
public function onPause(event:PauseScriptEvent) {}
|
||||
|
||||
public function onResume(event:ScriptEvent) {}
|
||||
|
|
|
@ -5701,11 +5701,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
{
|
||||
case 'mainStage':
|
||||
PlayStatePlaylist.campaignId = 'week1';
|
||||
case 'spookyMansion':
|
||||
case 'spookyMansion' | 'spookyMansionErect':
|
||||
PlayStatePlaylist.campaignId = 'week2';
|
||||
case 'phillyTrain':
|
||||
case 'phillyTrain' | 'phillyTrainErect':
|
||||
PlayStatePlaylist.campaignId = 'week3';
|
||||
case 'limoRide':
|
||||
case 'limoRide' | 'limoRideErect':
|
||||
PlayStatePlaylist.campaignId = 'week4';
|
||||
case 'mallXmas' | 'mallEvil':
|
||||
PlayStatePlaylist.campaignId = 'week5';
|
||||
|
|
|
@ -60,7 +60,9 @@ class ChartEditorHoldNoteSprite extends SustainTrail
|
|||
|
||||
override function setupHoldNoteGraphic(noteStyle:NoteStyle):Void
|
||||
{
|
||||
loadGraphic(noteStyle.getHoldNoteAssetPath());
|
||||
var graphicPath = noteStyle.getHoldNoteAssetPath();
|
||||
if (graphicPath == null) return;
|
||||
loadGraphic(graphicPath);
|
||||
|
||||
antialiasing = true;
|
||||
|
||||
|
|
|
@ -291,28 +291,47 @@ class LoadingState extends MusicBeatSubState
|
|||
FunkinSprite.preparePurgeCache();
|
||||
FunkinSprite.cacheTexture(Paths.image('healthBar'));
|
||||
FunkinSprite.cacheTexture(Paths.image('menuDesat'));
|
||||
FunkinSprite.cacheTexture(Paths.image('combo'));
|
||||
FunkinSprite.cacheTexture(Paths.image('num0'));
|
||||
FunkinSprite.cacheTexture(Paths.image('num1'));
|
||||
FunkinSprite.cacheTexture(Paths.image('num2'));
|
||||
FunkinSprite.cacheTexture(Paths.image('num3'));
|
||||
FunkinSprite.cacheTexture(Paths.image('num4'));
|
||||
FunkinSprite.cacheTexture(Paths.image('num5'));
|
||||
FunkinSprite.cacheTexture(Paths.image('num6'));
|
||||
FunkinSprite.cacheTexture(Paths.image('num7'));
|
||||
FunkinSprite.cacheTexture(Paths.image('num8'));
|
||||
FunkinSprite.cacheTexture(Paths.image('num9'));
|
||||
// Lord have mercy on me and this caching -anysad
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/combo'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num0'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num1'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num2'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num3'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num4'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num5'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num6'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num7'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num8'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num9'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/combo'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num0'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num1'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num2'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num3'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num4'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num5'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num6'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num7'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num8'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num9'));
|
||||
FunkinSprite.cacheTexture(Paths.image('notes', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('noteSplashes', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('noteStrumline', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('NOTE_hold_assets'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ready', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('set', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('go', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('sick', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('good', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('bad', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('shit', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/countdown/funkin/ready', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/countdown/funkin/set', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/countdown/funkin/go', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/countdown/pixel/ready', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/countdown/pixel/set', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/countdown/pixel/go', 'shared'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/sick'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/good'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/bad'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/shit'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/sick'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/good'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/bad'));
|
||||
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/shit'));
|
||||
FunkinSprite.cacheTexture(Paths.image('miss', 'shared')); // TODO: remove this
|
||||
|
||||
// List all image assets in the level's library.
|
||||
|
|
|
@ -258,6 +258,11 @@ class Constants
|
|||
*/
|
||||
public static final DEFAULT_NOTE_STYLE:String = 'funkin';
|
||||
|
||||
/**
|
||||
* The default pixel note style for songs.
|
||||
*/
|
||||
public static final DEFAULT_PIXEL_NOTE_STYLE:String = 'pixel';
|
||||
|
||||
/**
|
||||
* The default album for songs in Freeplay.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue