1
0
Fork 0
mirror of https://github.com/ninjamuffin99/Funkin.git synced 2025-06-21 10:01:32 +00:00

Merge branch 'develop' into main-to-develop

This commit is contained in:
Abnormal 2025-02-03 23:22:56 +00:00 committed by GitHub
commit 246de95e46
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 383 additions and 53 deletions

View file

@ -187,6 +187,8 @@ class InitState extends FlxState
ModuleHandler.loadModuleCache();
ModuleHandler.callOnCreate();
funkin.input.Cursor.hide();
trace('Parsing game data took: ${TimerUtil.ms(perfStart)}');
}

View file

@ -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.
*/

View file

@ -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;

View file

@ -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.

View file

@ -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.
*/

View file

@ -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;
}
}

View file

@ -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.
*

View file

@ -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) {}
}

View file

@ -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;

View file

@ -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)

View file

@ -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();

View file

@ -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;
}

View file

@ -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));
}

View file

@ -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) {}
}

View file

@ -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) {}
}

View file

@ -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;
}
}
}

View file

@ -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.

View file

@ -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()

View file

@ -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;

View file

@ -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,

View file

@ -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);
}
}

View file

@ -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
*/

View file

@ -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);
}
}