mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2025-06-21 18:23:12 +00:00
Merge branch 'develop' into main-to-develop
This commit is contained in:
commit
246de95e46
|
@ -187,6 +187,8 @@ class InitState extends FlxState
|
|||
ModuleHandler.loadModuleCache();
|
||||
ModuleHandler.callOnCreate();
|
||||
|
||||
funkin.input.Cursor.hide();
|
||||
|
||||
trace('Parsing game data took: ${TimerUtil.ms(perfStart)}');
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,13 @@ typedef AlbumData =
|
|||
*/
|
||||
public var albumTitleAsset:String;
|
||||
|
||||
/**
|
||||
* Offsets for the album title.
|
||||
*/
|
||||
@:optional
|
||||
@:default([0, 0])
|
||||
public var albumTitleOffsets:Null<Array<Float>>;
|
||||
|
||||
/**
|
||||
* An optional array of animations for the album title.
|
||||
*/
|
||||
|
|
|
@ -983,6 +983,7 @@ class Controls extends FlxActionSet
|
|||
Control.FREEPLAY_FAVORITE => getDefaultGamepadBinds(Control.FREEPLAY_FAVORITE),
|
||||
Control.FREEPLAY_LEFT => getDefaultGamepadBinds(Control.FREEPLAY_LEFT),
|
||||
Control.FREEPLAY_RIGHT => getDefaultGamepadBinds(Control.FREEPLAY_RIGHT),
|
||||
Control.FREEPLAY_CHAR_SELECT => getDefaultGamepadBinds(Control.FREEPLAY_CHAR_SELECT),
|
||||
Control.VOLUME_UP => getDefaultGamepadBinds(Control.VOLUME_UP),
|
||||
Control.VOLUME_DOWN => getDefaultGamepadBinds(Control.VOLUME_DOWN),
|
||||
Control.VOLUME_MUTE => getDefaultGamepadBinds(Control.VOLUME_MUTE),
|
||||
|
@ -1033,11 +1034,13 @@ class Controls extends FlxActionSet
|
|||
case Control.CUTSCENE_ADVANCE:
|
||||
return [A];
|
||||
case Control.FREEPLAY_FAVORITE:
|
||||
[FlxGamepadInputID.BACK]; // Back (i.e. Select)
|
||||
return [Y]; // Back (i.e. Select)
|
||||
case Control.FREEPLAY_LEFT:
|
||||
[LEFT_SHOULDER];
|
||||
return [LEFT_SHOULDER];
|
||||
case Control.FREEPLAY_RIGHT:
|
||||
[RIGHT_SHOULDER];
|
||||
return [RIGHT_SHOULDER];
|
||||
case Control.FREEPLAY_CHAR_SELECT:
|
||||
return [X];
|
||||
case Control.VOLUME_UP:
|
||||
[];
|
||||
case Control.VOLUME_DOWN:
|
||||
|
@ -1602,10 +1605,10 @@ enum Control
|
|||
NOTE_UP;
|
||||
NOTE_RIGHT;
|
||||
// UI
|
||||
UI_UP;
|
||||
UI_LEFT;
|
||||
UI_RIGHT;
|
||||
UI_DOWN;
|
||||
UI_UP;
|
||||
UI_RIGHT;
|
||||
RESET;
|
||||
ACCEPT;
|
||||
BACK;
|
||||
|
|
|
@ -37,6 +37,9 @@ interface IStateChangingScriptedClass extends IScriptedClass
|
|||
public function onSubStateOpenEnd(event:SubStateScriptEvent):Void;
|
||||
public function onSubStateCloseBegin(event:SubStateScriptEvent):Void;
|
||||
public function onSubStateCloseEnd(event:SubStateScriptEvent):Void;
|
||||
|
||||
public function onFocusLost(event:FocusScriptEvent):Void;
|
||||
public function onFocusGained(event:FocusScriptEvent):Void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -140,7 +143,7 @@ interface IPlayStateScriptedClass extends INoteScriptedClass extends IBPMSyncedS
|
|||
/**
|
||||
* Called when the player restarts the song, either via pause menu or restarting after a game over.
|
||||
*/
|
||||
public function onSongRetry(event:ScriptEvent):Void;
|
||||
public function onSongRetry(event:SongRetryEvent):Void;
|
||||
|
||||
/**
|
||||
* Called when the player presses a key when no note is on the strumline.
|
||||
|
|
|
@ -414,6 +414,28 @@ class SongLoadScriptEvent extends ScriptEvent
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AAn event that is fired when the player retries the song.
|
||||
*/
|
||||
class SongRetryEvent extends ScriptEvent
|
||||
{
|
||||
/**
|
||||
* The new difficulty of the song.
|
||||
*/
|
||||
public var difficulty(default, null):String;
|
||||
|
||||
public function new(difficulty:String):Void
|
||||
{
|
||||
super(SONG_RETRY, false);
|
||||
this.difficulty = difficulty;
|
||||
}
|
||||
|
||||
public override function toString():String
|
||||
{
|
||||
return 'SongRetryEvent(difficulty=$difficulty)';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired when moving out of or into an FlxState.
|
||||
*/
|
||||
|
@ -436,6 +458,22 @@ class StateChangeScriptEvent extends ScriptEvent
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired when the game loses or gains focus.
|
||||
*/
|
||||
class FocusScriptEvent extends ScriptEvent
|
||||
{
|
||||
public function new(type:ScriptEventType):Void
|
||||
{
|
||||
super(type, false);
|
||||
}
|
||||
|
||||
public override function toString():String
|
||||
{
|
||||
return 'FocusScriptEvent(type=' + type + ')';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired when moving out of or into an FlxSubState.
|
||||
*/
|
||||
|
|
|
@ -124,7 +124,7 @@ class ScriptEventDispatcher
|
|||
t.onSongEnd(event);
|
||||
return;
|
||||
case SONG_RETRY:
|
||||
t.onSongRetry(event);
|
||||
t.onSongRetry(cast event);
|
||||
return;
|
||||
case GAME_OVER:
|
||||
t.onGameOver(event);
|
||||
|
@ -177,6 +177,12 @@ class ScriptEventDispatcher
|
|||
case SUBSTATE_CLOSE_END:
|
||||
t.onSubStateCloseEnd(cast event);
|
||||
return;
|
||||
case FOCUS_LOST:
|
||||
t.onFocusLost(cast event);
|
||||
return;
|
||||
case FOCUS_GAINED:
|
||||
t.onFocusGained(cast event);
|
||||
return;
|
||||
default: // Continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -223,6 +223,20 @@ enum abstract ScriptEventType(String) from String to String
|
|||
*/
|
||||
var SUBSTATE_CLOSE_END = 'SUBSTATE_CLOSE_END';
|
||||
|
||||
/**
|
||||
* Called when the game regains focus.
|
||||
*
|
||||
* This event is not cancelable.
|
||||
*/
|
||||
var FOCUS_GAINED = 'FOCUS_GAINED';
|
||||
|
||||
/**
|
||||
* Called when the game loses focus.
|
||||
*
|
||||
* This event is not cancelable.
|
||||
*/
|
||||
var FOCUS_LOST = 'FOCUS_LOST';
|
||||
|
||||
/**
|
||||
* Called when the game starts a conversation.
|
||||
*
|
||||
|
|
|
@ -109,6 +109,10 @@ class Module implements IPlayStateScriptedClass implements IStateChangingScripte
|
|||
|
||||
public function onStateChangeEnd(event:StateChangeScriptEvent) {}
|
||||
|
||||
public function onFocusGained(event:FocusScriptEvent) {}
|
||||
|
||||
public function onFocusLost(event:FocusScriptEvent) {}
|
||||
|
||||
public function onSubStateOpenBegin(event:SubStateScriptEvent) {}
|
||||
|
||||
public function onSubStateOpenEnd(event:SubStateScriptEvent) {}
|
||||
|
@ -117,5 +121,5 @@ class Module implements IPlayStateScriptedClass implements IStateChangingScripte
|
|||
|
||||
public function onSubStateCloseEnd(event:SubStateScriptEvent) {}
|
||||
|
||||
public function onSongRetry(event:ScriptEvent) {}
|
||||
public function onSongRetry(event:SongRetryEvent) {}
|
||||
}
|
||||
|
|
|
@ -649,6 +649,7 @@ class PauseSubState extends MusicBeatSubState
|
|||
// So if you switch difficulty on the last song of a week you get a really low overall score.
|
||||
PlayStatePlaylist.campaignScore = 0;
|
||||
PlayStatePlaylist.campaignDifficulty = difficulty;
|
||||
PlayState.instance.previousDifficulty = PlayState.instance.currentDifficulty;
|
||||
PlayState.instance.currentDifficulty = PlayStatePlaylist.campaignDifficulty;
|
||||
|
||||
FreeplayState.rememberedDifficulty = difficulty;
|
||||
|
|
|
@ -332,6 +332,11 @@ class PlayState extends MusicBeatSubState
|
|||
*/
|
||||
public var disableKeys:Bool = false;
|
||||
|
||||
/**
|
||||
* The previous difficulty the player was playing on.
|
||||
*/
|
||||
public var previousDifficulty:String = Constants.DEFAULT_DIFFICULTY;
|
||||
|
||||
public var isSubState(get, never):Bool;
|
||||
|
||||
function get_isSubState():Bool
|
||||
|
@ -603,6 +608,7 @@ class PlayState extends MusicBeatSubState
|
|||
// Apply parameters.
|
||||
currentSong = params.targetSong;
|
||||
if (params.targetDifficulty != null) currentDifficulty = params.targetDifficulty;
|
||||
previousDifficulty = currentDifficulty;
|
||||
if (params.targetVariation != null) currentVariation = params.targetVariation;
|
||||
if (params.targetInstrumental != null) currentInstrumental = params.targetInstrumental;
|
||||
isPracticeMode = params.practiceMode ?? false;
|
||||
|
@ -813,7 +819,11 @@ class PlayState extends MusicBeatSubState
|
|||
|
||||
prevScrollTargets = [];
|
||||
|
||||
dispatchEvent(new ScriptEvent(SONG_RETRY));
|
||||
var retryEvent = new SongRetryEvent(currentDifficulty);
|
||||
|
||||
previousDifficulty = currentDifficulty;
|
||||
|
||||
dispatchEvent(retryEvent);
|
||||
|
||||
resetCamera();
|
||||
|
||||
|
@ -906,7 +916,7 @@ class PlayState extends MusicBeatSubState
|
|||
Conductor.instance.formatOffset = 0.0;
|
||||
}
|
||||
|
||||
Conductor.instance.update(); // Normal conductor update.
|
||||
Conductor.instance.update(Conductor.instance.songPosition + elapsed * 1000, false); // Normal conductor update.
|
||||
}
|
||||
|
||||
var androidPause:Bool = false;
|
||||
|
@ -1447,7 +1457,9 @@ class PlayState extends MusicBeatSubState
|
|||
}
|
||||
|
||||
if (!startingSong
|
||||
&& (Math.abs(FlxG.sound.music.time - correctSync) > 5 || Math.abs(playerVoicesError) > 5 || Math.abs(opponentVoicesError) > 5))
|
||||
&& (Math.abs(FlxG.sound.music.time - correctSync) > 100
|
||||
|| Math.abs(playerVoicesError) > 100
|
||||
|| Math.abs(opponentVoicesError) > 100))
|
||||
{
|
||||
trace("VOCALS NEED RESYNC");
|
||||
if (vocals != null)
|
||||
|
|
|
@ -36,11 +36,31 @@ class Strumline extends FlxSpriteGroup
|
|||
|
||||
static var RENDER_DISTANCE_MS(get, never):Float;
|
||||
|
||||
/**
|
||||
* The custom render distance for the strumline.
|
||||
* This should be in miliseconds only! Not pixels.
|
||||
*/
|
||||
public static var CUSTOM_RENDER_DISTANCE_MS:Float = 0.0;
|
||||
|
||||
/**
|
||||
* Whether to use the custom render distance.
|
||||
* If false, the render distance will be calculated based on the screen height.
|
||||
*/
|
||||
public static var USE_CUSTOM_RENDER_DISTANCE:Bool = false;
|
||||
|
||||
static function get_RENDER_DISTANCE_MS():Float
|
||||
{
|
||||
if (USE_CUSTOM_RENDER_DISTANCE) return CUSTOM_RENDER_DISTANCE_MS;
|
||||
return FlxG.height / Constants.PIXELS_PER_MS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to play note splashes or not
|
||||
* TODO: Make this a setting!
|
||||
* IE: Settings.noSplash
|
||||
*/
|
||||
public var showNotesplash:Bool = true;
|
||||
|
||||
/**
|
||||
* Whether this strumline is controlled by the player's inputs.
|
||||
* False means it's controlled by the opponent or Bot Play.
|
||||
|
@ -74,6 +94,11 @@ class Strumline extends FlxSpriteGroup
|
|||
return _conductorInUse = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the game should auto position notes.
|
||||
*/
|
||||
public var customPositionData:Bool = false;
|
||||
|
||||
/**
|
||||
* The notes currently being rendered on the strumline.
|
||||
* This group iterates over this every frame to update note positions.
|
||||
|
@ -376,7 +401,7 @@ class Strumline extends FlxSpriteGroup
|
|||
|
||||
var vwoosh:Bool = note.holdNoteSprite == null;
|
||||
// Set the note's position.
|
||||
note.y = this.y - INITIAL_OFFSET + calculateNoteYPos(note.strumTime, vwoosh);
|
||||
if (!customPositionData) note.y = this.y - INITIAL_OFFSET + calculateNoteYPos(note.strumTime, vwoosh);
|
||||
|
||||
// If the note is miss
|
||||
var isOffscreen = Preferences.downscroll ? note.y > FlxG.height : note.y < -note.height;
|
||||
|
@ -446,13 +471,16 @@ class Strumline extends FlxSpriteGroup
|
|||
|
||||
var vwoosh:Bool = false;
|
||||
|
||||
if (Preferences.downscroll)
|
||||
if (!customPositionData)
|
||||
{
|
||||
holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) - holdNote.height + STRUMLINE_SIZE / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) + yOffset + STRUMLINE_SIZE / 2;
|
||||
if (Preferences.downscroll)
|
||||
{
|
||||
holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) - holdNote.height + STRUMLINE_SIZE / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) + yOffset + STRUMLINE_SIZE / 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up the cover.
|
||||
|
@ -475,13 +503,16 @@ class Strumline extends FlxSpriteGroup
|
|||
holdNote.visible = false;
|
||||
}
|
||||
|
||||
if (Preferences.downscroll)
|
||||
if (!customPositionData)
|
||||
{
|
||||
holdNote.y = this.y - INITIAL_OFFSET - holdNote.height + STRUMLINE_SIZE / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
holdNote.y = this.y - INITIAL_OFFSET + STRUMLINE_SIZE / 2;
|
||||
if (Preferences.downscroll)
|
||||
{
|
||||
holdNote.y = this.y - INITIAL_OFFSET - holdNote.height + STRUMLINE_SIZE / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
holdNote.y = this.y - INITIAL_OFFSET + STRUMLINE_SIZE / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -490,13 +521,16 @@ class Strumline extends FlxSpriteGroup
|
|||
holdNote.visible = true;
|
||||
var vwoosh:Bool = false;
|
||||
|
||||
if (Preferences.downscroll)
|
||||
if (!customPositionData)
|
||||
{
|
||||
holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) - holdNote.height + STRUMLINE_SIZE / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) + STRUMLINE_SIZE / 2;
|
||||
if (Preferences.downscroll)
|
||||
{
|
||||
holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) - holdNote.height + STRUMLINE_SIZE / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) + STRUMLINE_SIZE / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -708,8 +742,7 @@ class Strumline extends FlxSpriteGroup
|
|||
|
||||
public function playNoteSplash(direction:NoteDirection):Void
|
||||
{
|
||||
// TODO: Add a setting to disable note splashes.
|
||||
// if (Settings.noSplash) return;
|
||||
if (!showNotesplash) return;
|
||||
if (!noteStyle.isNoteSplashEnabled()) return;
|
||||
|
||||
var splash:NoteSplash = this.constructNoteSplash();
|
||||
|
@ -729,8 +762,7 @@ class Strumline extends FlxSpriteGroup
|
|||
|
||||
public function playNoteHoldCover(holdNote:SustainTrail):Void
|
||||
{
|
||||
// TODO: Add a setting to disable note splashes.
|
||||
// if (Settings.noSplash) return;
|
||||
if (!showNotesplash) return;
|
||||
if (!noteStyle.isHoldNoteCoverEnabled()) return;
|
||||
|
||||
var cover:NoteHoldCover = this.constructNoteHoldCover();
|
||||
|
|
|
@ -86,6 +86,11 @@ class SustainTrail extends FlxSprite
|
|||
*/
|
||||
public var bottomClip:Float = 0.9;
|
||||
|
||||
/**
|
||||
* Whether the note will recieve custom vertex data
|
||||
*/
|
||||
public var customVertexData:Bool = false;
|
||||
|
||||
public var isPixel:Bool;
|
||||
public var noteStyleOffsets:Array<Float>;
|
||||
|
||||
|
@ -110,11 +115,68 @@ class SustainTrail extends FlxSprite
|
|||
setupHoldNoteGraphic(noteStyle);
|
||||
noteStyleOffsets = noteStyle.getHoldNoteOffsets();
|
||||
|
||||
indices = new DrawData<Int>(12, true, TRIANGLE_VERTEX_INDICES);
|
||||
setIndices(TRIANGLE_VERTEX_INDICES);
|
||||
|
||||
this.active = true; // This NEEDS to be true for the note to be drawn!
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the indices for the triangles.
|
||||
* @param indices The indices to set.
|
||||
*/
|
||||
public function setIndices(indices:Array<Int>):Void
|
||||
{
|
||||
if (this.indices.length == indices.length)
|
||||
{
|
||||
for (i in 0...indices.length)
|
||||
{
|
||||
this.indices[i] = indices[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.indices = new DrawData<Int>(indices.length, false, indices);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the vertices for the triangles.
|
||||
* @param vertices The vertices to set.
|
||||
*/
|
||||
public function setVertices(vertices:Array<Float>):Void
|
||||
{
|
||||
if (this.vertices.length == vertices.length)
|
||||
{
|
||||
for (i in 0...vertices.length)
|
||||
{
|
||||
this.vertices[i] = vertices[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.vertices = new DrawData<Float>(vertices.length, false, vertices);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the UV data for the triangles.
|
||||
* @param uvtData The UV data to set.
|
||||
*/
|
||||
public function setUVTData(uvtData:Array<Float>):Void
|
||||
{
|
||||
if (this.uvtData.length == uvtData.length)
|
||||
{
|
||||
for (i in 0...uvtData.length)
|
||||
{
|
||||
this.uvtData[i] = uvtData[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.uvtData = new DrawData<Float>(uvtData.length, false, uvtData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates hold note graphic and applies correct zooming
|
||||
* @param noteStyle The note style
|
||||
|
@ -214,7 +276,7 @@ class SustainTrail extends FlxSprite
|
|||
*/
|
||||
public function updateClipping(songTime:Float = 0):Void
|
||||
{
|
||||
if (graphic == null)
|
||||
if (graphic == null || customVertexData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -643,11 +643,11 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
|||
|
||||
public function onGameOver(event:ScriptEvent):Void {};
|
||||
|
||||
public function onSongRetry(event:ScriptEvent):Void {};
|
||||
public function onSongRetry(event:SongRetryEvent):Void {};
|
||||
|
||||
public function onNoteIncoming(event:NoteScriptEvent) {}
|
||||
public function onNoteIncoming(event:NoteScriptEvent) {};
|
||||
|
||||
public function onNoteHit(event:HitNoteScriptEvent) {}
|
||||
public function onNoteHit(event:HitNoteScriptEvent) {};
|
||||
|
||||
public function onNoteMiss(event:NoteScriptEvent):Void {};
|
||||
|
||||
|
@ -955,12 +955,14 @@ class SongDifficulty
|
|||
// Add player vocals.
|
||||
for (playerVoice in playerVoiceList)
|
||||
{
|
||||
if (!Assets.exists(playerVoice)) continue;
|
||||
result.addPlayerVoice(FunkinSound.load(playerVoice));
|
||||
}
|
||||
|
||||
// Add opponent vocals.
|
||||
for (opponentVoice in opponentVoiceList)
|
||||
{
|
||||
if (!Assets.exists(opponentVoice)) continue;
|
||||
result.addOpponentVoice(FunkinSound.load(opponentVoice));
|
||||
}
|
||||
|
||||
|
|
|
@ -389,5 +389,5 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
|
|||
|
||||
public function onSongLoaded(event:SongLoadScriptEvent) {}
|
||||
|
||||
public function onSongRetry(event:ScriptEvent) {}
|
||||
public function onSongRetry(event:SongRetryEvent) {}
|
||||
}
|
||||
|
|
|
@ -901,5 +901,5 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements
|
|||
|
||||
public function onSongLoaded(event:SongLoadScriptEvent) {}
|
||||
|
||||
public function onSongRetry(event:ScriptEvent) {}
|
||||
public function onSongRetry(event:SongRetryEvent) {}
|
||||
}
|
||||
|
|
|
@ -623,7 +623,7 @@ class Save
|
|||
else
|
||||
{
|
||||
// Level has score data, but the score is 0.
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -818,7 +818,7 @@ class Save
|
|||
else
|
||||
{
|
||||
// Level has score data, but the score is 0.
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,6 +87,20 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler
|
|||
dispatchEvent(new UpdateScriptEvent(elapsed));
|
||||
}
|
||||
|
||||
override function onFocus():Void
|
||||
{
|
||||
super.onFocus();
|
||||
|
||||
dispatchEvent(new FocusScriptEvent(FOCUS_GAINED));
|
||||
}
|
||||
|
||||
override function onFocusLost():Void
|
||||
{
|
||||
super.onFocusLost();
|
||||
|
||||
dispatchEvent(new FocusScriptEvent(FOCUS_LOST));
|
||||
}
|
||||
|
||||
function createWatermarkText()
|
||||
{
|
||||
// Both have an xPos of 0, but a width equal to the full screen.
|
||||
|
|
|
@ -89,6 +89,20 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler
|
|||
dispatchEvent(new UpdateScriptEvent(elapsed));
|
||||
}
|
||||
|
||||
override function onFocus():Void
|
||||
{
|
||||
super.onFocus();
|
||||
|
||||
dispatchEvent(new FocusScriptEvent(FOCUS_GAINED));
|
||||
}
|
||||
|
||||
override function onFocusLost():Void
|
||||
{
|
||||
super.onFocusLost();
|
||||
|
||||
dispatchEvent(new FocusScriptEvent(FOCUS_LOST));
|
||||
}
|
||||
|
||||
public function initConsoleHelpers():Void {}
|
||||
|
||||
function reloadAssets()
|
||||
|
|
|
@ -76,6 +76,14 @@ class Album implements IRegistryEntry<AlbumData>
|
|||
return _data.albumTitleAsset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the offsets for the album title.
|
||||
*/
|
||||
public function getAlbumTitleOffsets():Null<Array<Float>>
|
||||
{
|
||||
return _data.albumTitleOffsets;
|
||||
}
|
||||
|
||||
public function hasAlbumTitleAnimations()
|
||||
{
|
||||
return _data.albumTitleAnimations.length > 0;
|
||||
|
|
|
@ -112,7 +112,7 @@ class AlbumRoll extends FlxSpriteGroup
|
|||
var albumGraphic = Paths.image(albumData.getAlbumArtAssetKey());
|
||||
newAlbumArt.replaceFrameGraphic(0, albumGraphic);
|
||||
|
||||
buildAlbumTitle(albumData.getAlbumTitleAssetKey());
|
||||
buildAlbumTitle(albumData.getAlbumTitleAssetKey(), albumData.getAlbumTitleOffsets());
|
||||
|
||||
applyExitMovers();
|
||||
|
||||
|
@ -198,7 +198,7 @@ class AlbumRoll extends FlxSpriteGroup
|
|||
albumTitle.visible = true;
|
||||
}
|
||||
|
||||
public function buildAlbumTitle(assetKey:String):Void
|
||||
public function buildAlbumTitle(assetKey:String, ?titleOffsets:Null<Array<Float>>):Void
|
||||
{
|
||||
if (albumTitle != null)
|
||||
{
|
||||
|
@ -206,6 +206,11 @@ class AlbumRoll extends FlxSpriteGroup
|
|||
albumTitle = null;
|
||||
}
|
||||
|
||||
if (titleOffsets == null)
|
||||
{
|
||||
titleOffsets = [0, 0];
|
||||
}
|
||||
|
||||
albumTitle = FunkinSprite.createSparrow(925, 500, assetKey);
|
||||
albumTitle.visible = albumTitle.frames != null && newAlbumArt.visible;
|
||||
albumTitle.animation.addByPrefix('idle', 'idle0', 24, true);
|
||||
|
@ -219,6 +224,9 @@ class AlbumRoll extends FlxSpriteGroup
|
|||
|
||||
albumTitle.zIndex = 1000;
|
||||
|
||||
albumTitle.x += titleOffsets[0];
|
||||
albumTitle.y += titleOffsets[1];
|
||||
|
||||
if (_exitMovers != null) _exitMovers.set([albumTitle],
|
||||
{
|
||||
x: FlxG.width,
|
||||
|
|
|
@ -3,10 +3,13 @@ package funkin.ui.options;
|
|||
import flixel.FlxCamera;
|
||||
import flixel.FlxObject;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
||||
import funkin.ui.AtlasText.AtlasFont;
|
||||
import funkin.ui.options.OptionsState.Page;
|
||||
import funkin.graphics.FunkinCamera;
|
||||
import funkin.graphics.FunkinSprite;
|
||||
import funkin.ui.TextMenuList.TextMenuItem;
|
||||
import funkin.audio.FunkinSound;
|
||||
import funkin.ui.options.MenuItemEnums;
|
||||
|
@ -18,8 +21,12 @@ class PreferencesMenu extends Page
|
|||
{
|
||||
var items:TextMenuList;
|
||||
var preferenceItems:FlxTypedSpriteGroup<FlxSprite>;
|
||||
var preferenceDesc:Array<String> = [];
|
||||
var itemDesc:FlxText;
|
||||
var itemDescBox:FunkinSprite;
|
||||
|
||||
var menuCamera:FlxCamera;
|
||||
var hudCamera:FlxCamera;
|
||||
var camFollow:FlxObject;
|
||||
|
||||
public function new()
|
||||
|
@ -29,47 +36,81 @@ class PreferencesMenu extends Page
|
|||
menuCamera = new FunkinCamera('prefMenu');
|
||||
FlxG.cameras.add(menuCamera, false);
|
||||
menuCamera.bgColor = 0x0;
|
||||
|
||||
hudCamera = new FlxCamera();
|
||||
FlxG.cameras.add(hudCamera, false);
|
||||
hudCamera.bgColor = 0x0;
|
||||
|
||||
camera = menuCamera;
|
||||
|
||||
add(items = new TextMenuList());
|
||||
add(preferenceItems = new FlxTypedSpriteGroup<FlxSprite>());
|
||||
|
||||
add(itemDescBox = new FunkinSprite());
|
||||
itemDescBox.cameras = [hudCamera];
|
||||
|
||||
add(itemDesc = new FlxText(0, 0, 1180, null, 32));
|
||||
itemDesc.cameras = [hudCamera];
|
||||
|
||||
createPrefItems();
|
||||
createPrefDescription();
|
||||
|
||||
camFollow = new FlxObject(FlxG.width / 2, 0, 140, 70);
|
||||
if (items != null) camFollow.y = items.selectedItem.y;
|
||||
|
||||
menuCamera.follow(camFollow, null, 0.06);
|
||||
menuCamera.follow(camFollow, null, 0.085);
|
||||
var margin = 160;
|
||||
menuCamera.deadzone.set(0, margin, menuCamera.width, 40);
|
||||
menuCamera.deadzone.set(0, margin, menuCamera.width, menuCamera.height - margin * 2);
|
||||
menuCamera.minScrollY = 0;
|
||||
|
||||
items.onChange.add(function(selected) {
|
||||
camFollow.y = selected.y;
|
||||
itemDesc.text = preferenceDesc[items.selectedIndex];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the description for preferences.
|
||||
*/
|
||||
function createPrefDescription():Void
|
||||
{
|
||||
itemDescBox.makeSolidColor(1, 1, FlxColor.BLACK);
|
||||
itemDescBox.alpha = 0.6;
|
||||
itemDesc.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
|
||||
itemDesc.borderSize = 3;
|
||||
|
||||
// Update the text.
|
||||
itemDesc.text = preferenceDesc[items.selectedIndex];
|
||||
itemDesc.screenCenter();
|
||||
itemDesc.y += 270;
|
||||
|
||||
// Create the box around the text.
|
||||
itemDescBox.setPosition(itemDesc.x - 10, itemDesc.y - 10);
|
||||
itemDescBox.setGraphicSize(Std.int(itemDesc.width + 20), Std.int(itemDesc.height + 25));
|
||||
itemDescBox.updateHitbox();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the menu items for each of the preferences.
|
||||
*/
|
||||
function createPrefItems():Void
|
||||
{
|
||||
createPrefItemCheckbox('Naughtyness', 'Toggle displaying raunchy content', function(value:Bool):Void {
|
||||
createPrefItemCheckbox('Naughtyness', 'If enabled, raunchy content (such as swearing, etc.) will be displayed.', function(value:Bool):Void {
|
||||
Preferences.naughtyness = value;
|
||||
}, Preferences.naughtyness);
|
||||
createPrefItemCheckbox('Downscroll', 'Enable to make notes move downwards', function(value:Bool):Void {
|
||||
createPrefItemCheckbox('Downscroll', 'If enabled, this will make the notes move downwards.', function(value:Bool):Void {
|
||||
Preferences.downscroll = value;
|
||||
}, Preferences.downscroll);
|
||||
createPrefItemCheckbox('Flashing Lights', 'Disable to dampen flashing effects', function(value:Bool):Void {
|
||||
createPrefItemCheckbox('Flashing Lights', 'If disabled, it will dampen flashing effects. Useful for people with photosensitive epilepsy.', function(value:Bool):Void {
|
||||
Preferences.flashingLights = value;
|
||||
}, Preferences.flashingLights);
|
||||
createPrefItemCheckbox('Camera Zooming on Beat', 'Disable to stop the camera bouncing to the song', function(value:Bool):Void {
|
||||
createPrefItemCheckbox('Camera Zooms', 'If disabled, camera stops bouncing to the song.', function(value:Bool):Void {
|
||||
Preferences.zoomCamera = value;
|
||||
}, Preferences.zoomCamera);
|
||||
createPrefItemCheckbox('Debug Display', 'Enable to show FPS and other debug stats', function(value:Bool):Void {
|
||||
createPrefItemCheckbox('Debug Display', 'If enabled, FPS and other debug stats will be displayed.', function(value:Bool):Void {
|
||||
Preferences.debugDisplay = value;
|
||||
}, Preferences.debugDisplay);
|
||||
createPrefItemCheckbox('Auto Pause', 'Automatically pause the game when it loses focus', function(value:Bool):Void {
|
||||
createPrefItemCheckbox('Auto Pause', 'If enabled, game automatically pauses when it loses focus.', function(value:Bool):Void {
|
||||
Preferences.autoPause = value;
|
||||
}, Preferences.autoPause);
|
||||
|
||||
|
@ -134,6 +175,7 @@ class PreferencesMenu extends Page
|
|||
});
|
||||
|
||||
preferenceItems.add(checkbox);
|
||||
preferenceDesc.push(prefDesc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,6 +194,7 @@ class PreferencesMenu extends Page
|
|||
var item = new NumberPreferenceItem(0, (120 * items.length) + 30, prefName, defaultValue, min, max, step, precision, onChange, valueFormatter);
|
||||
items.addItem(prefName, item);
|
||||
preferenceItems.add(item.lefthandText);
|
||||
preferenceDesc.push(prefDesc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -172,6 +215,7 @@ class PreferencesMenu extends Page
|
|||
var item = new NumberPreferenceItem(0, (120 * items.length) + 30, prefName, defaultValue, min, max, 10, 0, newCallback, formatter);
|
||||
items.addItem(prefName, item);
|
||||
preferenceItems.add(item.lefthandText);
|
||||
preferenceDesc.push(prefDesc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,5 +229,6 @@ class PreferencesMenu extends Page
|
|||
var item = new EnumPreferenceItem(0, (120 * items.length) + 30, prefName, values, defaultValue, onChange);
|
||||
items.addItem(prefName, item);
|
||||
preferenceItems.add(item.lefthandText);
|
||||
preferenceDesc.push(prefDesc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,11 @@ class Constants
|
|||
}
|
||||
#end
|
||||
|
||||
/**
|
||||
* Whether or not the game is a debug build.
|
||||
*/
|
||||
public static final DEBUG_BUILD:Bool = #if FEATURE_DEBUG_FUNCTIONS true #else false #end;
|
||||
|
||||
/**
|
||||
* URL DATA
|
||||
*/
|
||||
|
|
|
@ -44,8 +44,58 @@ class ReflectUtil
|
|||
return Reflect.field(obj, name);
|
||||
}
|
||||
|
||||
public static function setAnonymousField(obj:Dynamic, name:String, value:Dynamic):Void
|
||||
{
|
||||
return Reflect.setField(obj, name, value);
|
||||
}
|
||||
|
||||
public static function hasAnonymousField(obj:Dynamic, name:String):Bool
|
||||
{
|
||||
return Reflect.hasField(obj, name);
|
||||
}
|
||||
|
||||
public static function copyAnonymousFieldsOf(obj:Dynamic):Dynamic
|
||||
{
|
||||
return Reflect.copy(obj);
|
||||
}
|
||||
|
||||
public static function deleteAnonymousField(obj:Dynamic, name:String):Bool
|
||||
{
|
||||
return Reflect.deleteField(obj, name);
|
||||
}
|
||||
|
||||
public static function compareValues(valueA:Dynamic, valueB:Dynamic):Int
|
||||
{
|
||||
return Reflect.compare(valueA, valueB);
|
||||
}
|
||||
|
||||
public static function isObject(value:Dynamic):Bool
|
||||
{
|
||||
return Reflect.isObject(value);
|
||||
}
|
||||
|
||||
public static function isFunction(value:Dynamic):Bool
|
||||
{
|
||||
return Reflect.isFunction(value);
|
||||
}
|
||||
|
||||
public static function isEnumValue(value:Dynamic):Bool
|
||||
{
|
||||
return Reflect.isEnumValue(value);
|
||||
}
|
||||
|
||||
public static function getProperty(obj:Dynamic, name:String):Dynamic
|
||||
{
|
||||
return Reflect.getProperty(obj, name);
|
||||
}
|
||||
|
||||
public static function setProperty(obj:Dynamic, name:String, value:Dynamic):Void
|
||||
{
|
||||
return Reflect.setProperty(obj, name, value);
|
||||
}
|
||||
|
||||
public static function compareMethods(functionA:Dynamic, functionB:Dynamic):Bool
|
||||
{
|
||||
return Reflect.compareMethods(functionA, functionB);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue