mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2025-04-21 11:21:06 -04:00
Many improvements to chart system and song format logic
This commit is contained in:
parent
fc4f398157
commit
6e8feecef1
17 changed files with 1415 additions and 265 deletions
|
@ -181,6 +181,7 @@
|
|||
|
||||
<haxedef name="CAN_OPEN_LINKS" unless="switch" />
|
||||
<haxedef name="CAN_CHEAT" if="switch debug" />
|
||||
<haxedef name="haxeui_no_mouse_reset" />
|
||||
|
||||
<!-- Skip the Intro -->
|
||||
<section if="debug">
|
||||
|
|
4
hmm.json
4
hmm.json
|
@ -49,14 +49,14 @@
|
|||
"name": "haxeui-core",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "9b3a2fb",
|
||||
"ref": "fc8d656b",
|
||||
"url": "https://github.com/haxeui/haxeui-core/"
|
||||
},
|
||||
{
|
||||
"name": "haxeui-flixel",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "master",
|
||||
"ref": "80941a7",
|
||||
"url": "https://github.com/haxeui/haxeui-flixel"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -524,10 +524,7 @@ class FreeplayState extends MusicBeatSubstate
|
|||
PlayState.currentSong_NEW = SongDataParser.fetchSong(songs[curSelected].songName.toLowerCase());
|
||||
PlayState.isStoryMode = false;
|
||||
PlayState.storyDifficulty = curDifficulty;
|
||||
PlayState.storyDifficulty_NEW = 'easy';
|
||||
// SongLoad.curDiff = Highscore.formatSong()
|
||||
|
||||
SongLoad.curDiff = switch (curDifficulty)
|
||||
PlayState.storyDifficulty_NEW = switch (curDifficulty)
|
||||
{
|
||||
case 0:
|
||||
'easy';
|
||||
|
@ -537,6 +534,9 @@ class FreeplayState extends MusicBeatSubstate
|
|||
'hard';
|
||||
default: 'normal';
|
||||
};
|
||||
// SongLoad.curDiff = Highscore.formatSong()
|
||||
|
||||
SongLoad.curDiff = PlayState.storyDifficulty_NEW;
|
||||
|
||||
PlayState.storyWeek = songs[curSelected].week;
|
||||
trace(' CUR WEEK ' + PlayState.storyWeek);
|
||||
|
@ -565,7 +565,17 @@ class FreeplayState extends MusicBeatSubstate
|
|||
intendedScore = FlxG.random.int(0, 100000);
|
||||
|
||||
PlayState.storyDifficulty = curDifficulty;
|
||||
PlayState.storyDifficulty_NEW = 'easy';
|
||||
PlayState.storyDifficulty_NEW = switch (curDifficulty)
|
||||
{
|
||||
case 0:
|
||||
'easy';
|
||||
case 1:
|
||||
'normal';
|
||||
case 2:
|
||||
'hard';
|
||||
default:
|
||||
'normal';
|
||||
};
|
||||
|
||||
grpDifficulties.group.forEach(function(spr)
|
||||
{
|
||||
|
|
|
@ -7,7 +7,6 @@ import flixel.graphics.FlxGraphic;
|
|||
import flixel.math.FlxPoint;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.util.FlxColor;
|
||||
import funkin.charting.ChartingState;
|
||||
import funkin.modding.module.ModuleHandler;
|
||||
import funkin.play.PlayState;
|
||||
import funkin.play.character.CharacterData.CharacterDataParser;
|
||||
|
@ -15,8 +14,6 @@ import funkin.play.event.SongEvent.SongEventHandler;
|
|||
import funkin.play.song.SongData.SongDataParser;
|
||||
import funkin.play.stage.StageData;
|
||||
import funkin.ui.PreferencesMenu;
|
||||
import funkin.ui.animDebugShit.DebugBoundingState;
|
||||
import funkin.ui.stageBuildShit.StageBuilderState;
|
||||
import funkin.util.macro.MacroUtil;
|
||||
import openfl.display.BitmapData;
|
||||
|
||||
|
@ -198,14 +195,14 @@ class InitState extends FlxTransitionableState
|
|||
PlayState.currentSong_NEW = SongDataParser.fetchSong(song);
|
||||
PlayState.isStoryMode = isStoryMode;
|
||||
PlayState.storyDifficulty = dif;
|
||||
PlayState.storyDifficulty_NEW = 'easy';
|
||||
SongLoad.curDiff = switch (dif)
|
||||
PlayState.storyDifficulty_NEW = switch (dif)
|
||||
{
|
||||
case 0: 'easy';
|
||||
case 1: 'normal';
|
||||
case 2: 'hard';
|
||||
default: 'normal';
|
||||
};
|
||||
SongLoad.curDiff = PlayState.storyDifficulty_NEW;
|
||||
PlayState.storyWeek = week;
|
||||
LoadingState.loadAndSwitchState(new PlayState());
|
||||
}
|
||||
|
|
|
@ -189,7 +189,7 @@ class PauseSubState extends MusicBeatSubstate
|
|||
SongLoad.curDiff = daSelected.toLowerCase();
|
||||
|
||||
PlayState.storyDifficulty = curSelected;
|
||||
PlayState.storyDifficulty_NEW = 'easy';
|
||||
PlayState.storyDifficulty_NEW = daSelected.toLowerCase();
|
||||
|
||||
PlayState.needsReset = true;
|
||||
|
||||
|
|
|
@ -378,8 +378,7 @@ class StoryMenuState extends MusicBeatState
|
|||
PlayState.campaignScore = 0;
|
||||
|
||||
PlayState.storyDifficulty = curDifficulty;
|
||||
PlayState.storyDifficulty_NEW = 'easy';
|
||||
SongLoad.curDiff = switch (curDifficulty)
|
||||
PlayState.storyDifficulty_NEW = switch (curDifficulty)
|
||||
{
|
||||
case 0:
|
||||
'easy';
|
||||
|
@ -390,6 +389,7 @@ class StoryMenuState extends MusicBeatState
|
|||
default:
|
||||
'normal';
|
||||
};
|
||||
SongLoad.curDiff = PlayState.storyDifficulty_NEW;
|
||||
|
||||
new FlxTimer().start(1, function(tmr:FlxTimer)
|
||||
{
|
||||
|
|
|
@ -396,7 +396,7 @@ class PlayState extends MusicBeatState
|
|||
healthBar = new FlxBar(healthBarBG.x + 4, healthBarBG.y + 4, RIGHT_TO_LEFT, Std.int(healthBarBG.width - 8), Std.int(healthBarBG.height - 8), this,
|
||||
'healthLerp', 0, 2);
|
||||
healthBar.scrollFactor.set();
|
||||
healthBar.createFilledBar(Constants.HEALTH_BAR_RED, Constants.HEALTH_BAR_GREEN);
|
||||
healthBar.createFilledBar(Constants.COLOR_HEALTH_BAR_RED, Constants.COLOR_HEALTH_BAR_GREEN);
|
||||
add(healthBar);
|
||||
|
||||
initStage();
|
||||
|
@ -711,8 +711,19 @@ class PlayState extends MusicBeatState
|
|||
|
||||
// TODO: Switch playable character by manipulating this value.
|
||||
// TODO: How to choose which one to use for story mode?
|
||||
|
||||
var playableChars = currentChart.getPlayableChars();
|
||||
var currentPlayer = 'bf';
|
||||
|
||||
if (playableChars.length == 0)
|
||||
{
|
||||
trace('WARNING: No playable characters found for this song.');
|
||||
}
|
||||
else if (playableChars.indexOf(currentPlayer) == -1)
|
||||
{
|
||||
currentPlayer = playableChars[0];
|
||||
}
|
||||
|
||||
var currentCharData:SongPlayableChar = currentChart.getPlayableChar(currentPlayer);
|
||||
|
||||
//
|
||||
|
|
|
@ -212,6 +212,11 @@ class SongDifficulty
|
|||
return chars.get(id);
|
||||
}
|
||||
|
||||
public function getPlayableChars():Array<String>
|
||||
{
|
||||
return [for (i in chars.keys()) i];
|
||||
}
|
||||
|
||||
public function getEvents():Array<SongEvent>
|
||||
{
|
||||
return cast events;
|
||||
|
|
|
@ -13,6 +13,7 @@ class SongDataUtils
|
|||
/**
|
||||
* Given an array of SongNoteData objects, return a new array of SongNoteData objects
|
||||
* whose timestamps are shifted by the given amount.
|
||||
* Does not mutate the original array.
|
||||
*
|
||||
* @param notes The notes to modify.
|
||||
* @param offset The time difference to apply in milliseconds.
|
||||
|
@ -26,7 +27,8 @@ class SongDataUtils
|
|||
}
|
||||
|
||||
/**
|
||||
* Remove a certain subset of notes from an array of SongNoteData objects.
|
||||
* Return a new array without a certain subset of notes from an array of SongNoteData objects.
|
||||
* Does not mutate the original array.
|
||||
*
|
||||
* @param notes The array of notes to be subtracted from.
|
||||
* @param subtrahend The notes to remove from the `notes` array. Yes, subtrahend is a real word.
|
||||
|
@ -50,7 +52,8 @@ class SongDataUtils
|
|||
}
|
||||
|
||||
/**
|
||||
* Remove a certain subset of events from an array of SongEventData objects.
|
||||
* Return a new array without a certain subset of events from an array of SongEventData objects.
|
||||
* Does not mutate the original array.
|
||||
*
|
||||
* @param events The array of events to be subtracted from.
|
||||
* @param subtrahend The events to remove from the `events` array. Yes, subtrahend is a real word.
|
||||
|
@ -67,6 +70,25 @@ class SongDataUtils
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array of notes whose note data is flipped (player becomes opponent and vice versa)
|
||||
* Does not mutate the original array.
|
||||
*/
|
||||
public static function flipNotes(notes:Array<SongNoteData>, ?strumlineSize:Int = 4):Array<SongNoteData>
|
||||
{
|
||||
return notes.map(function(note:SongNoteData):SongNoteData
|
||||
{
|
||||
var newData = note.data;
|
||||
|
||||
if (newData < strumlineSize)
|
||||
newData += strumlineSize;
|
||||
else
|
||||
newData -= strumlineSize;
|
||||
|
||||
return new SongNoteData(note.time, newData, note.length, note.kind);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an array of notes to be used as the clipboard data.
|
||||
*
|
||||
|
@ -77,6 +99,9 @@ class SongDataUtils
|
|||
return offsetSongNoteData(sortNotes(notes), -Std.int(notes[0].time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort an array of notes by strum time.
|
||||
*/
|
||||
public static function sortNotes(notes:Array<SongNoteData>, ?desc:Bool = false):Array<SongNoteData>
|
||||
{
|
||||
// TODO: Modifies the array in place. Is this okay?
|
||||
|
@ -87,6 +112,9 @@ class SongDataUtils
|
|||
return notes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize an array of note data and write it to the clipboard.
|
||||
*/
|
||||
public static function writeNotesToClipboard(notes:Array<SongNoteData>):Void
|
||||
{
|
||||
var notesString = SerializerUtil.toJSON(notes);
|
||||
|
@ -98,6 +126,9 @@ class SongDataUtils
|
|||
trace(notesString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an array of note data from the clipboard and deserialize it.
|
||||
*/
|
||||
public static function readNotesFromClipboard():Array<SongNoteData>
|
||||
{
|
||||
var notesString = ClipboardUtil.getClipboard();
|
||||
|
@ -117,4 +148,37 @@ class SongDataUtils
|
|||
return notes;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a list of notes to only include notes that are within the given time range.
|
||||
*/
|
||||
public static function getNotesInTimeRange(notes:Array<SongNoteData>, start:Float, end:Float):Array<SongNoteData>
|
||||
{
|
||||
return notes.filter(function(note:SongNoteData):Bool
|
||||
{
|
||||
return note.time >= start && note.time <= end;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a list of notes to only include notes whose data is within the given range.
|
||||
*/
|
||||
public static function getNotesInDataRange(notes:Array<SongNoteData>, start:Int, end:Int):Array<SongNoteData>
|
||||
{
|
||||
return notes.filter(function(note:SongNoteData):Bool
|
||||
{
|
||||
return note.data >= start && note.data <= end;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a list of notes to only include notes whose data is one of the given values.
|
||||
*/
|
||||
public static function getNotesWithData(notes:Array<SongNoteData>, data:Array<Int>):Array<SongNoteData>
|
||||
{
|
||||
return notes.filter(function(note:SongNoteData):Bool
|
||||
{
|
||||
return data.indexOf(note.data) != -1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,10 +38,12 @@ interface ChartEditorCommand
|
|||
class AddNotesCommand implements ChartEditorCommand
|
||||
{
|
||||
private var notes:Array<SongNoteData>;
|
||||
private var appendToSelection:Bool;
|
||||
|
||||
public function new(notes:Array<SongNoteData>)
|
||||
public function new(notes:Array<SongNoteData>, appendToSelection:Bool = false)
|
||||
{
|
||||
this.notes = notes;
|
||||
this.appendToSelection = appendToSelection;
|
||||
}
|
||||
|
||||
public function execute(state:ChartEditorState):Void
|
||||
|
@ -51,7 +53,15 @@ class AddNotesCommand implements ChartEditorCommand
|
|||
state.currentSongChartNoteData.push(note);
|
||||
}
|
||||
|
||||
state.currentSelection = notes;
|
||||
if (appendToSelection)
|
||||
{
|
||||
state.currentSelection = state.currentSelection.concat(notes);
|
||||
}
|
||||
else
|
||||
{
|
||||
state.currentSelection = notes;
|
||||
}
|
||||
|
||||
state.playSound(Paths.sound('funnyNoise/funnyNoise-08'));
|
||||
|
||||
state.noteDisplayDirty = true;
|
||||
|
@ -171,6 +181,9 @@ class SwitchDifficultyCommand implements ChartEditorCommand
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds one or more notes to the selection.
|
||||
*/
|
||||
class SelectNotesCommand implements ChartEditorCommand
|
||||
{
|
||||
private var notes:Array<SongNoteData>;
|
||||
|
@ -251,6 +264,43 @@ class DeselectNotesCommand implements ChartEditorCommand
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the selection rather than appends it.
|
||||
* Deselects any notes that are not in the new selection.
|
||||
*/
|
||||
class SetNoteSelectionCommand implements ChartEditorCommand
|
||||
{
|
||||
private var notes:Array<SongNoteData>;
|
||||
private var previousSelection:Array<SongNoteData>;
|
||||
|
||||
public function new(notes:Array<SongNoteData>, ?previousSelection:Array<SongNoteData>)
|
||||
{
|
||||
this.notes = notes;
|
||||
this.previousSelection = previousSelection == null ? [] : previousSelection;
|
||||
}
|
||||
|
||||
public function execute(state:ChartEditorState):Void
|
||||
{
|
||||
state.currentSelection = notes;
|
||||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
}
|
||||
|
||||
public function undo(state:ChartEditorState):Void
|
||||
{
|
||||
state.currentSelection = previousSelection;
|
||||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
}
|
||||
|
||||
public function toString():String
|
||||
{
|
||||
return 'Select ${notes.length} Notes';
|
||||
}
|
||||
}
|
||||
|
||||
class SelectAllNotesCommand implements ChartEditorCommand
|
||||
{
|
||||
private var previousSelection:Array<SongNoteData>;
|
||||
|
@ -281,6 +331,36 @@ class SelectAllNotesCommand implements ChartEditorCommand
|
|||
}
|
||||
}
|
||||
|
||||
class InvertSelectedNotesCommand implements ChartEditorCommand
|
||||
{
|
||||
private var previousSelection:Array<SongNoteData>;
|
||||
|
||||
public function new(?previousSelection:Array<SongNoteData>)
|
||||
{
|
||||
this.previousSelection = previousSelection == null ? [] : previousSelection;
|
||||
}
|
||||
|
||||
public function execute(state:ChartEditorState):Void
|
||||
{
|
||||
state.currentSelection = SongDataUtils.subtractNotes(state.currentSongChartNoteData, previousSelection);
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
}
|
||||
|
||||
public function undo(state:ChartEditorState):Void
|
||||
{
|
||||
state.currentSelection = previousSelection;
|
||||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
}
|
||||
|
||||
public function toString():String
|
||||
{
|
||||
return 'Invert Selected Notes';
|
||||
}
|
||||
}
|
||||
|
||||
class DeselectAllNotesCommand implements ChartEditorCommand
|
||||
{
|
||||
private var previousSelection:Array<SongNoteData>;
|
||||
|
@ -352,6 +432,52 @@ class CutNotesCommand implements ChartEditorCommand
|
|||
}
|
||||
}
|
||||
|
||||
class FlipNotesCommand implements ChartEditorCommand
|
||||
{
|
||||
private var notes:Array<SongNoteData>;
|
||||
private var flippedNotes:Array<SongNoteData>;
|
||||
|
||||
public function new(notes:Array<SongNoteData>)
|
||||
{
|
||||
this.notes = notes;
|
||||
}
|
||||
|
||||
public function execute(state:ChartEditorState):Void
|
||||
{
|
||||
// Delete the notes.
|
||||
state.currentSongChartNoteData = SongDataUtils.subtractNotes(state.currentSongChartNoteData, notes);
|
||||
|
||||
// Add the flipped notes.
|
||||
flippedNotes = SongDataUtils.flipNotes(notes);
|
||||
state.currentSongChartNoteData = state.currentSongChartNoteData.concat(flippedNotes);
|
||||
|
||||
state.currentSelection = flippedNotes;
|
||||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
state.sortChartData();
|
||||
}
|
||||
|
||||
public function undo(state:ChartEditorState):Void
|
||||
{
|
||||
state.currentSongChartNoteData = SongDataUtils.subtractNotes(state.currentSongChartNoteData, flippedNotes);
|
||||
state.currentSongChartNoteData = state.currentSongChartNoteData.concat(notes);
|
||||
|
||||
state.currentSelection = notes;
|
||||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
|
||||
state.sortChartData();
|
||||
}
|
||||
|
||||
public function toString():String
|
||||
{
|
||||
var len:Int = notes.length;
|
||||
return 'Flip $len Notes';
|
||||
}
|
||||
}
|
||||
|
||||
class PasteNotesCommand implements ChartEditorCommand
|
||||
{
|
||||
private var targetTimestamp:Float;
|
||||
|
@ -399,13 +525,12 @@ class PasteNotesCommand implements ChartEditorCommand
|
|||
class AddEventsCommand implements ChartEditorCommand
|
||||
{
|
||||
private var events:Array<SongEventData>;
|
||||
private var appendToSelection:Bool;
|
||||
|
||||
// private var previousSelection:Array<SongEventData>;
|
||||
|
||||
public function new(events:Array<SongEventData>, ?previousSelection:Array<SongEventData>)
|
||||
public function new(events:Array<SongEventData>, ?appendToSelection:Bool = false)
|
||||
{
|
||||
this.events = events;
|
||||
// this.previousSelection = previousSelection == null ? [] : previousSelection;
|
||||
this.appendToSelection = appendToSelection;
|
||||
}
|
||||
|
||||
public function execute(state:ChartEditorState):Void
|
||||
|
@ -423,8 +548,8 @@ class AddEventsCommand implements ChartEditorCommand
|
|||
public function undo(state:ChartEditorState):Void
|
||||
{
|
||||
state.currentSongChartEventData = SongDataUtils.subtractEvents(state.currentSongChartEventData, events);
|
||||
// TODO: Allow selecting events.
|
||||
// state.currentSelection = previousSelection;
|
||||
|
||||
state.currentSelection = [];
|
||||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
|
@ -438,3 +563,42 @@ class AddEventsCommand implements ChartEditorCommand
|
|||
return 'Add $len Events';
|
||||
}
|
||||
}
|
||||
|
||||
class ExtendNoteLengthCommand implements ChartEditorCommand
|
||||
{
|
||||
private var note:SongNoteData;
|
||||
private var oldLength:Float;
|
||||
private var newLength:Float;
|
||||
|
||||
public function new(note:SongNoteData, newLength:Float)
|
||||
{
|
||||
this.note = note;
|
||||
this.oldLength = note.length;
|
||||
this.newLength = newLength;
|
||||
}
|
||||
|
||||
public function execute(state:ChartEditorState):Void
|
||||
{
|
||||
note.length = newLength;
|
||||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
|
||||
state.sortChartData();
|
||||
}
|
||||
|
||||
public function undo(state:ChartEditorState):Void
|
||||
{
|
||||
note.length = oldLength;
|
||||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
|
||||
state.sortChartData();
|
||||
}
|
||||
|
||||
public function toString():String
|
||||
{
|
||||
return 'Extend Note Length';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package funkin.ui.debug.charting;
|
||||
|
||||
class ChartEditorDialogHandler
|
||||
{
|
||||
}
|
|
@ -23,6 +23,16 @@ class ChartEditorNoteSprite extends FlxSprite
|
|||
*/
|
||||
public var noteSkin(default, set):String = 'Normal';
|
||||
|
||||
/**
|
||||
* This note is the previous sprite in a sustain chain.
|
||||
*/
|
||||
public var parentNoteSprite(default, set):ChartEditorNoteSprite = null;
|
||||
|
||||
/**
|
||||
* This note is the next sprite in a sustain chain.
|
||||
*/
|
||||
public var childNoteSprite(default, set):ChartEditorNoteSprite = null;
|
||||
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
|
@ -41,22 +51,20 @@ class ChartEditorNoteSprite extends FlxSprite
|
|||
this.animation.addByPrefix('tapUpNormal', 'green instance');
|
||||
this.animation.addByPrefix('tapRightNormal', 'red instance');
|
||||
|
||||
this.animation.addByPrefix('holdLeftNormal', 'purple hold piece instance');
|
||||
this.animation.addByPrefix('holdDownNormal', 'blue hold piece instance');
|
||||
this.animation.addByPrefix('holdUpNormal', 'green hold piece instance');
|
||||
this.animation.addByPrefix('holdRightNormal', 'red hold piece instance');
|
||||
this.animation.addByPrefix('holdLeftNormal', 'LeftHoldPiece');
|
||||
this.animation.addByPrefix('holdDownNormal', 'DownHoldPiece');
|
||||
this.animation.addByPrefix('holdUpNormal', 'UpHoldPiece');
|
||||
this.animation.addByPrefix('holdRightNormal', 'RightHoldPiece');
|
||||
|
||||
this.animation.addByPrefix('holdEndLeftNormal', 'pruple end hold instance');
|
||||
this.animation.addByPrefix('holdEndDownNormal', 'blue end hold instance');
|
||||
this.animation.addByPrefix('holdEndUpNormal', 'green end hold instance');
|
||||
this.animation.addByPrefix('holdEndRightNormal', 'red end hold instance');
|
||||
this.animation.addByPrefix('holdEndLeftNormal', 'LeftHoldEnd');
|
||||
this.animation.addByPrefix('holdEndDownNormal', 'DownHoldEnd');
|
||||
this.animation.addByPrefix('holdEndUpNormal', 'UpHoldEnd');
|
||||
this.animation.addByPrefix('holdEndRightNormal', 'RightHoldEnd');
|
||||
|
||||
this.animation.addByPrefix('tapLeftPixel', 'pixel4');
|
||||
this.animation.addByPrefix('tapDownPixel', 'pixel5');
|
||||
this.animation.addByPrefix('tapUpPixel', 'pixel6');
|
||||
this.animation.addByPrefix('tapRightPixel', 'pixel7');
|
||||
|
||||
resizeNote();
|
||||
}
|
||||
|
||||
static var noteFrameCollection:FlxFramesCollection = null;
|
||||
|
@ -77,6 +85,12 @@ class ChartEditorNoteSprite extends FlxSprite
|
|||
{
|
||||
noteFrameCollection.pushFrame(frame);
|
||||
}
|
||||
var frameCollectionNormal2 = Paths.getSparrowAtlas('NoteHoldNormal');
|
||||
|
||||
for (frame in frameCollectionNormal2.frames)
|
||||
{
|
||||
noteFrameCollection.pushFrame(frame);
|
||||
}
|
||||
|
||||
// Pixel notes
|
||||
var graphicPixel = FlxG.bitmap.add(Paths.image('weeb/pixelUI/arrows-pixels', 'week6'), false, null);
|
||||
|
@ -98,18 +112,27 @@ class ChartEditorNoteSprite extends FlxSprite
|
|||
|
||||
if (this.noteData == null)
|
||||
{
|
||||
// Disown parent.
|
||||
this.parentNoteSprite = null;
|
||||
if (this.childNoteSprite != null)
|
||||
{
|
||||
// Kill all children and disown them.
|
||||
this.childNoteSprite.noteData = null;
|
||||
this.childNoteSprite = null;
|
||||
}
|
||||
this.kill();
|
||||
return this.noteData;
|
||||
}
|
||||
|
||||
this.visible = true;
|
||||
|
||||
// Update the position to match the note skin.
|
||||
setNotePosition();
|
||||
|
||||
// Update the animation to match the note skin.
|
||||
// Update the animation to match the note data.
|
||||
// Animation is updated first so size is correct before updating position.
|
||||
playNoteAnimation();
|
||||
|
||||
// Update the position to match the note data.
|
||||
setNotePosition();
|
||||
|
||||
return this.noteData;
|
||||
}
|
||||
|
||||
|
@ -149,25 +172,125 @@ class ChartEditorNoteSprite extends FlxSprite
|
|||
cursorColumn += ChartEditorState.STRUMLINE_SIZE;
|
||||
}
|
||||
}
|
||||
this.x = cursorColumn * ChartEditorState.GRID_SIZE;
|
||||
|
||||
// Notes far in the song will start far down, but the group they belong to will have a high negative offset.
|
||||
// TODO: stepTime doesn't account for fluctuating BPMs.
|
||||
this.y = this.noteData.stepTime * ChartEditorState.GRID_SIZE;
|
||||
if (parentNoteSprite == null)
|
||||
{
|
||||
this.x = cursorColumn * ChartEditorState.GRID_SIZE;
|
||||
|
||||
// Notes far in the song will start far down, but the group they belong to will have a high negative offset.
|
||||
// TODO: stepTime doesn't account for fluctuating BPMs.
|
||||
this.y = this.noteData.stepTime * ChartEditorState.GRID_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this is a hold note, we need to adjust the position to be centered.
|
||||
if (parentNoteSprite.parentNoteSprite == null)
|
||||
{
|
||||
this.x = parentNoteSprite.x;
|
||||
this.x += (ChartEditorState.GRID_SIZE / 2);
|
||||
this.x -= this.width / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.x = parentNoteSprite.x;
|
||||
}
|
||||
|
||||
this.y = parentNoteSprite.y;
|
||||
if (parentNoteSprite.parentNoteSprite == null)
|
||||
{
|
||||
this.y += parentNoteSprite.height / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.y += parentNoteSprite.height - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function set_parentNoteSprite(value:ChartEditorNoteSprite):ChartEditorNoteSprite
|
||||
{
|
||||
this.parentNoteSprite = value;
|
||||
|
||||
if (this.parentNoteSprite != null)
|
||||
{
|
||||
this.noteData = this.parentNoteSprite.noteData;
|
||||
this.noteSkin = this.parentNoteSprite.noteSkin;
|
||||
}
|
||||
|
||||
return this.parentNoteSprite;
|
||||
}
|
||||
|
||||
function set_childNoteSprite(value:ChartEditorNoteSprite):ChartEditorNoteSprite
|
||||
{
|
||||
this.childNoteSprite = value;
|
||||
|
||||
if (this.parentNoteSprite != null)
|
||||
{
|
||||
this.noteData = this.parentNoteSprite.noteData;
|
||||
this.noteSkin = this.parentNoteSprite.noteSkin;
|
||||
}
|
||||
|
||||
return this.childNoteSprite;
|
||||
}
|
||||
|
||||
function playNoteAnimation()
|
||||
{
|
||||
var animationName = 'tap${this.noteData.getDirectionName()}${this.noteSkin}';
|
||||
this.animation.play(animationName);
|
||||
}
|
||||
// Decide whether to display a note or a sustain.
|
||||
var baseAnimationName:String = 'tap';
|
||||
if (this.parentNoteSprite != null)
|
||||
baseAnimationName = (this.childNoteSprite != null) ? 'hold' : 'holdEnd';
|
||||
|
||||
function resizeNote()
|
||||
{
|
||||
this.setGraphicSize(ChartEditorState.GRID_SIZE);
|
||||
// Play the appropriate animation for the type, direction, and skin.
|
||||
var animationName = '${baseAnimationName}${this.noteData.getDirectionName()}${this.noteSkin}';
|
||||
|
||||
this.animation.play(animationName);
|
||||
|
||||
// Resize note.
|
||||
|
||||
switch (baseAnimationName)
|
||||
{
|
||||
case 'tap':
|
||||
this.setGraphicSize(0, ChartEditorState.GRID_SIZE);
|
||||
case 'hold':
|
||||
if (parentNoteSprite.parentNoteSprite == null)
|
||||
{
|
||||
this.setGraphicSize(Std.int(ChartEditorState.GRID_SIZE / 2), Std.int(ChartEditorState.GRID_SIZE / 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setGraphicSize(Std.int(ChartEditorState.GRID_SIZE / 2), ChartEditorState.GRID_SIZE);
|
||||
}
|
||||
case 'holdEnd':
|
||||
this.setGraphicSize(Std.int(ChartEditorState.GRID_SIZE / 2), Std.int(ChartEditorState.GRID_SIZE / 2));
|
||||
}
|
||||
this.updateHitbox();
|
||||
|
||||
// TODO: Make this an attribute of the note skin.
|
||||
this.antialiasing = (noteSkin != 'Pixel');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this note (or its parent) is currently visible.
|
||||
*/
|
||||
public function isNoteVisible(viewAreaBottom:Float, viewAreaTop:Float):Bool
|
||||
{
|
||||
var outsideViewArea = (this.y + this.height < viewAreaTop || this.y > viewAreaBottom);
|
||||
|
||||
if (!outsideViewArea)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Check if this note's parent or child is visible.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getBaseNoteSprite()
|
||||
{
|
||||
if (this.parentNoteSprite == null)
|
||||
return this;
|
||||
else
|
||||
return this.parentNoteSprite;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
172
source/funkin/ui/debug/charting/ChartEditorThemeHandler.hx
Normal file
172
source/funkin/ui/debug/charting/ChartEditorThemeHandler.hx
Normal file
|
@ -0,0 +1,172 @@
|
|||
package funkin.ui.debug.charting;
|
||||
|
||||
import flixel.addons.display.FlxGridOverlay;
|
||||
import flixel.addons.display.FlxSliceSprite;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.util.FlxColor;
|
||||
import openfl.display.BitmapData;
|
||||
import openfl.geom.Rectangle;
|
||||
|
||||
/**
|
||||
* Available themes for the chart editor state.
|
||||
*/
|
||||
enum ChartEditorTheme
|
||||
{
|
||||
Light;
|
||||
Dark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static functions which handle building themed UI elements for a provided ChartEditorState.
|
||||
*/
|
||||
class ChartEditorThemeHandler
|
||||
{
|
||||
// TODO: There's probably a better system of organization for these colors.
|
||||
// An enum of typedefs or something?
|
||||
// ================================
|
||||
static final BACKGROUND_COLOR_LIGHT:FlxColor = 0xFF673AB7;
|
||||
static final BACKGROUND_COLOR_DARK:FlxColor = 0xFF673AB7;
|
||||
|
||||
// Color 1 of the grid pattern. Alternates with Color 2.
|
||||
static final GRID_COLOR_1_LIGHT:FlxColor = 0xFFE7E6E6;
|
||||
static final GRID_COLOR_1_DARK:FlxColor = 0xFF181919;
|
||||
|
||||
// Color 2 of the grid pattern. Alternates with Color 1.
|
||||
static final GRID_COLOR_2_LIGHT:FlxColor = 0xFFD9D5D5;
|
||||
static final GRID_COLOR_2_DARK:FlxColor = 0xFF262A2A;
|
||||
|
||||
// Vertical divider between characters.
|
||||
static final GRID_STRUMLINE_DIVIDER_COLOR_LIGHT:FlxColor = 0xFF000000;
|
||||
static final GRID_STRUMLINE_DIVIDER_COLOR_DARK:FlxColor = 0xFFC4C4C4;
|
||||
static final GRID_STRUMLINE_DIVIDER_WIDTH:Float = 2;
|
||||
|
||||
// Horizontal divider between measures.
|
||||
static final GRID_MEASURE_DIVIDER_COLOR_LIGHT:FlxColor = 0xFF000000;
|
||||
static final GRID_MEASURE_DIVIDER_COLOR_DARK:FlxColor = 0xFFC4C4C4;
|
||||
static final GRID_MEASURE_DIVIDER_WIDTH:Float = 2;
|
||||
|
||||
// Border on the square highlighting selected notes.
|
||||
static final SELECTION_SQUARE_BORDER_COLOR_LIGHT:FlxColor = 0xFF339933;
|
||||
static final SELECTION_SQUARE_BORDER_COLOR_DARK:FlxColor = 0xFF339933;
|
||||
static final SELECTION_SQUARE_BORDER_WIDTH:Int = 1;
|
||||
|
||||
// Fill on the square highlighting selected notes.
|
||||
// Make sure this is transparent so you can see the notes underneath.
|
||||
static final SELECTION_SQUARE_FILL_COLOR_LIGHT:FlxColor = 0x4033FF33;
|
||||
static final SELECTION_SQUARE_FILL_COLOR_DARK:FlxColor = 0x4033FF33;
|
||||
|
||||
// TODO: Un-hardcode these to be based on time signature.
|
||||
static final STEPS_PER_BEAT:Int = 4;
|
||||
static final BEATS_PER_MEASURE:Int = 4;
|
||||
|
||||
public static function updateTheme(state:ChartEditorState):Void
|
||||
{
|
||||
updateBackground(state);
|
||||
updateGridBitmap(state);
|
||||
updateSelectionSquare(state);
|
||||
}
|
||||
|
||||
static function updateBackground(state:ChartEditorState):Void
|
||||
{
|
||||
state.menuBG.color = switch (state.currentTheme)
|
||||
{
|
||||
case ChartEditorTheme.Light: BACKGROUND_COLOR_LIGHT;
|
||||
case ChartEditorTheme.Dark: BACKGROUND_COLOR_DARK;
|
||||
default: BACKGROUND_COLOR_LIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the checkerboard background image of the chart editor, and adds dividing lines to it.
|
||||
* @param dark Whether to draw the grid in a dark color instead of a light one.
|
||||
*/
|
||||
static function updateGridBitmap(state:ChartEditorState):Void
|
||||
{
|
||||
var gridColor1:FlxColor = switch (state.currentTheme)
|
||||
{
|
||||
case Light: GRID_COLOR_1_LIGHT;
|
||||
case Dark: GRID_COLOR_1_DARK;
|
||||
default: GRID_COLOR_1_LIGHT;
|
||||
};
|
||||
|
||||
var gridColor2:FlxColor = switch (state.currentTheme)
|
||||
{
|
||||
case Light: GRID_COLOR_2_LIGHT;
|
||||
case Dark: GRID_COLOR_2_DARK;
|
||||
default: GRID_COLOR_2_LIGHT;
|
||||
};
|
||||
|
||||
// Draw the base grid.
|
||||
|
||||
// 2 * (Strumline Size) + 1 grid squares wide, by (4 * quarter notes per measure) grid squares tall.
|
||||
// This gets reused to fill the screen.
|
||||
var gridWidth = ChartEditorState.GRID_SIZE * (ChartEditorState.STRUMLINE_SIZE * 2 + 1);
|
||||
var gridHeight = ChartEditorState.GRID_SIZE * (STEPS_PER_BEAT * BEATS_PER_MEASURE);
|
||||
state.gridBitmap = FlxGridOverlay.createGrid(ChartEditorState.GRID_SIZE, ChartEditorState.GRID_SIZE, gridWidth, gridHeight, true, gridColor1,
|
||||
gridColor2);
|
||||
|
||||
// Draw dividers between the strumlines.
|
||||
|
||||
var gridStrumlineDividerColor:FlxColor = switch (state.currentTheme)
|
||||
{
|
||||
case Light: GRID_STRUMLINE_DIVIDER_COLOR_LIGHT;
|
||||
case Dark: GRID_STRUMLINE_DIVIDER_COLOR_DARK;
|
||||
default: GRID_STRUMLINE_DIVIDER_COLOR_LIGHT;
|
||||
};
|
||||
|
||||
// Divider at 1 * (Strumline Size)
|
||||
var dividerLineAX = ChartEditorState.GRID_SIZE * (ChartEditorState.STRUMLINE_SIZE) - (GRID_STRUMLINE_DIVIDER_WIDTH / 2);
|
||||
state.gridBitmap.fillRect(new Rectangle(dividerLineAX, 0, GRID_STRUMLINE_DIVIDER_WIDTH, state.gridBitmap.height), gridStrumlineDividerColor);
|
||||
// Divider at 2 * (Strumline Size)
|
||||
var dividerLineBX = ChartEditorState.GRID_SIZE * (ChartEditorState.STRUMLINE_SIZE * 2) - (GRID_STRUMLINE_DIVIDER_WIDTH / 2);
|
||||
state.gridBitmap.fillRect(new Rectangle(dividerLineBX, 0, GRID_STRUMLINE_DIVIDER_WIDTH, state.gridBitmap.height), gridStrumlineDividerColor);
|
||||
|
||||
// Draw dividers between the measures.
|
||||
|
||||
var gridMeasureDividerColor:FlxColor = switch (state.currentTheme)
|
||||
{
|
||||
case Light: GRID_MEASURE_DIVIDER_COLOR_LIGHT;
|
||||
case Dark: GRID_MEASURE_DIVIDER_COLOR_DARK;
|
||||
default: GRID_MEASURE_DIVIDER_COLOR_LIGHT;
|
||||
};
|
||||
|
||||
// Divider at top
|
||||
state.gridBitmap.fillRect(new Rectangle(0, 0, state.gridBitmap.width, GRID_MEASURE_DIVIDER_WIDTH / 2), gridMeasureDividerColor);
|
||||
// Divider at bottom
|
||||
var dividerLineBY = state.gridBitmap.height - (GRID_MEASURE_DIVIDER_WIDTH / 2);
|
||||
state.gridBitmap.fillRect(new Rectangle(0, dividerLineBY, GRID_MEASURE_DIVIDER_WIDTH / 2, state.gridBitmap.height), gridMeasureDividerColor);
|
||||
}
|
||||
|
||||
static function updateSelectionSquare(state:ChartEditorState):Void
|
||||
{
|
||||
var selectionSquareBorderColor:FlxColor = switch (state.currentTheme)
|
||||
{
|
||||
case Light: SELECTION_SQUARE_BORDER_COLOR_LIGHT;
|
||||
case Dark: SELECTION_SQUARE_BORDER_COLOR_DARK;
|
||||
default: SELECTION_SQUARE_BORDER_COLOR_LIGHT;
|
||||
};
|
||||
|
||||
var selectionSquareFillColor:FlxColor = switch (state.currentTheme)
|
||||
{
|
||||
case Light: SELECTION_SQUARE_FILL_COLOR_LIGHT;
|
||||
case Dark: SELECTION_SQUARE_FILL_COLOR_DARK;
|
||||
default: SELECTION_SQUARE_FILL_COLOR_LIGHT;
|
||||
};
|
||||
|
||||
state.selectionSquareBitmap = new BitmapData(ChartEditorState.GRID_SIZE, ChartEditorState.GRID_SIZE, true);
|
||||
|
||||
state.selectionSquareBitmap.fillRect(new Rectangle(0, 0, ChartEditorState.GRID_SIZE, ChartEditorState.GRID_SIZE), selectionSquareBorderColor);
|
||||
state.selectionSquareBitmap.fillRect(new Rectangle(SELECTION_SQUARE_BORDER_WIDTH, SELECTION_SQUARE_BORDER_WIDTH,
|
||||
ChartEditorState.GRID_SIZE - (SELECTION_SQUARE_BORDER_WIDTH * 2), ChartEditorState.GRID_SIZE - (SELECTION_SQUARE_BORDER_WIDTH * 2)),
|
||||
selectionSquareFillColor);
|
||||
|
||||
state.selectionBoxSprite = new FlxSliceSprite(state.selectionSquareBitmap,
|
||||
new FlxRect(SELECTION_SQUARE_BORDER_WIDTH
|
||||
+ 4, SELECTION_SQUARE_BORDER_WIDTH
|
||||
+ 4,
|
||||
ChartEditorState.GRID_SIZE
|
||||
- (2 * SELECTION_SQUARE_BORDER_WIDTH + 8), ChartEditorState.GRID_SIZE
|
||||
- (2 * SELECTION_SQUARE_BORDER_WIDTH + 8)),
|
||||
32, 32);
|
||||
}
|
||||
}
|
184
source/funkin/ui/debug/charting/ChartEditorToolboxHandler.hx
Normal file
184
source/funkin/ui/debug/charting/ChartEditorToolboxHandler.hx
Normal file
|
@ -0,0 +1,184 @@
|
|||
package funkin.ui.debug.charting;
|
||||
|
||||
import haxe.ui.components.DropDown;
|
||||
import haxe.ui.containers.Group;
|
||||
import haxe.ui.containers.dialogs.Dialog;
|
||||
import haxe.ui.events.UIEvent;
|
||||
|
||||
/**
|
||||
* Available tools for the chart editor state.
|
||||
*/
|
||||
enum ChartEditorToolMode
|
||||
{
|
||||
Select;
|
||||
Place;
|
||||
}
|
||||
|
||||
class ChartEditorToolboxHandler
|
||||
{
|
||||
public static function setToolboxState(state:ChartEditorState, id:String, shown:Bool):Void
|
||||
{
|
||||
if (shown)
|
||||
showToolbox(state, id);
|
||||
else
|
||||
hideToolbox(state, id);
|
||||
}
|
||||
|
||||
public static function showToolbox(state:ChartEditorState, id:String)
|
||||
{
|
||||
var toolbox:Dialog = state.activeToolboxes.get(id);
|
||||
|
||||
if (toolbox == null)
|
||||
toolbox = initToolbox(state, id);
|
||||
|
||||
if (toolbox != null)
|
||||
{
|
||||
toolbox.showDialog(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('ChartEditorToolboxHandler.showToolbox() - Could not retrieve toolbox: $id');
|
||||
}
|
||||
}
|
||||
|
||||
public static function hideToolbox(state:ChartEditorState, id:String):Void
|
||||
{
|
||||
var toolbox:Dialog = state.activeToolboxes.get(id);
|
||||
|
||||
if (toolbox == null)
|
||||
toolbox = initToolbox(state, id);
|
||||
|
||||
if (toolbox != null)
|
||||
{
|
||||
toolbox.hideDialog(DialogButton.CANCEL);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('ChartEditorToolboxHandler.hideToolbox() - Could not retrieve toolbox: $id');
|
||||
}
|
||||
}
|
||||
|
||||
public static function minimizeToolbox(state:ChartEditorState, id:String):Void
|
||||
{
|
||||
}
|
||||
|
||||
public static function maximizeToolbox(state:ChartEditorState, id:String):Void
|
||||
{
|
||||
}
|
||||
|
||||
public static function initToolbox(state:ChartEditorState, id:String):Dialog
|
||||
{
|
||||
var toolbox:Dialog = null;
|
||||
switch (id)
|
||||
{
|
||||
case ChartEditorState.CHART_EDITOR_TOOLBOX_TOOLS_LAYOUT:
|
||||
toolbox = buildToolboxToolsLayout(state);
|
||||
case ChartEditorState.CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT:
|
||||
toolbox = buildToolboxNoteDataLayout(state);
|
||||
case ChartEditorState.CHART_EDITOR_TOOLBOX_EVENTDATA_LAYOUT:
|
||||
toolbox = buildToolboxEventDataLayout(state);
|
||||
case ChartEditorState.CHART_EDITOR_TOOLBOX_SONGDATA_LAYOUT:
|
||||
toolbox = buildToolboxSongDataLayout(state);
|
||||
default:
|
||||
trace('ChartEditorToolboxHandler.initToolbox() - Unknown toolbox ID: $id');
|
||||
toolbox = null;
|
||||
}
|
||||
|
||||
state.activeToolboxes.set(id, toolbox);
|
||||
|
||||
return toolbox;
|
||||
}
|
||||
|
||||
static function buildToolboxToolsLayout(state:ChartEditorState):Dialog
|
||||
{
|
||||
var toolbox:Dialog = cast state.buildComponent(ChartEditorState.CHART_EDITOR_TOOLBOX_TOOLS_LAYOUT);
|
||||
|
||||
// Starting position.
|
||||
toolbox.x = 50;
|
||||
toolbox.y = 50;
|
||||
|
||||
toolbox.onDialogClosed = (event:DialogEvent) ->
|
||||
{
|
||||
state.setUISelected('menubarItemToggleToolboxTools', false);
|
||||
}
|
||||
|
||||
var toolsGroup:Group = toolbox.findComponent("toolboxToolsGroup", Group);
|
||||
|
||||
toolsGroup.onChange = (event:UIEvent) ->
|
||||
{
|
||||
switch (event.target.id)
|
||||
{
|
||||
case 'toolboxToolsGroupSelect':
|
||||
state.currentToolMode = ChartEditorToolMode.Select;
|
||||
case 'toolboxToolsGroupPlace':
|
||||
state.currentToolMode = ChartEditorToolMode.Place;
|
||||
default:
|
||||
trace('ChartEditorToolboxHandler.buildToolboxToolsLayout() - Unknown toolbox tool selected: $event.target.id');
|
||||
}
|
||||
}
|
||||
|
||||
return toolbox;
|
||||
}
|
||||
|
||||
static function buildToolboxNoteDataLayout(state:ChartEditorState):Dialog
|
||||
{
|
||||
var toolbox:Dialog = cast state.buildComponent(ChartEditorState.CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT);
|
||||
|
||||
// Starting position.
|
||||
toolbox.x = 75;
|
||||
toolbox.y = 100;
|
||||
|
||||
toolbox.onDialogClosed = (event:DialogEvent) ->
|
||||
{
|
||||
state.setUISelected('menubarItemToggleToolboxNotes', false);
|
||||
}
|
||||
|
||||
var toolboxNotesNoteKind:DropDown = toolbox.findComponent("toolboxNotesNoteKind", DropDown);
|
||||
|
||||
toolboxNotesNoteKind.onChange = (event:UIEvent) ->
|
||||
{
|
||||
state.selectedNoteKind = event.data.id;
|
||||
}
|
||||
|
||||
return toolbox;
|
||||
}
|
||||
|
||||
static function buildToolboxEventDataLayout(state:ChartEditorState):Dialog
|
||||
{
|
||||
var toolbox:Dialog = cast state.buildComponent(ChartEditorState.CHART_EDITOR_TOOLBOX_EVENTDATA_LAYOUT);
|
||||
|
||||
// Starting position.
|
||||
toolbox.x = 100;
|
||||
toolbox.y = 150;
|
||||
|
||||
toolbox.onDialogClosed = (event:DialogEvent) ->
|
||||
{
|
||||
state.setUISelected('menubarItemToggleToolboxEvents', false);
|
||||
}
|
||||
|
||||
return toolbox;
|
||||
}
|
||||
|
||||
static function buildToolboxSongDataLayout(state:ChartEditorState):Dialog
|
||||
{
|
||||
var toolbox:Dialog = cast state.buildComponent(ChartEditorState.CHART_EDITOR_TOOLBOX_SONGDATA_LAYOUT);
|
||||
|
||||
// Starting position.
|
||||
toolbox.x = 950;
|
||||
toolbox.y = 50;
|
||||
|
||||
toolbox.onDialogClosed = (event:DialogEvent) ->
|
||||
{
|
||||
state.setUISelected('menubarItemToggleToolboxSong', false);
|
||||
}
|
||||
|
||||
return toolbox;
|
||||
}
|
||||
|
||||
static function buildDialog(state:ChartEditorState, id:String):Dialog
|
||||
{
|
||||
var dialog:Dialog = cast state.buildComponent(id);
|
||||
dialog.destroyOnClose = false;
|
||||
return dialog;
|
||||
}
|
||||
}
|
3
source/funkin/ui/haxeui/components/README.md
Normal file
3
source/funkin/ui/haxeui/components/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# funkin.ui.haxeui.components
|
||||
|
||||
Since there is a line in `source/module.xml` pointing to this folder, all components in this folder will automatically be accessible in any HaxeUI layouts.
|
|
@ -6,27 +6,29 @@ import lime.app.Application;
|
|||
class Constants
|
||||
{
|
||||
/**
|
||||
* The scale factor to use when increasing the size of pixel art graphics.
|
||||
* ENGINE AND VERSION DATA
|
||||
*/
|
||||
public static final PIXEL_ART_SCALE = 6;
|
||||
// ==============================
|
||||
|
||||
public static final HEALTH_BAR_RED:FlxColor = 0xFFFF0000;
|
||||
public static final HEALTH_BAR_GREEN:FlxColor = 0xFF66FF33;
|
||||
|
||||
public static final COUNTDOWN_VOLUME = 0.6;
|
||||
|
||||
public static final VERSION_SUFFIX = ' PROTOTYPE';
|
||||
public static var VERSION(get, null):String;
|
||||
|
||||
public static final FREAKY_MENU_BPM = 102;
|
||||
|
||||
// Change this if you're making an engine.
|
||||
/**
|
||||
* The title of the game, for debug printing purposes.
|
||||
* Change this if you're making an engine.
|
||||
*/
|
||||
public static final TITLE = "Friday Night Funkin'";
|
||||
|
||||
#if debug
|
||||
public static final GIT_HASH = funkin.util.macro.GitCommit.getGitCommitHash();
|
||||
public static final GIT_BRANCH = funkin.util.macro.GitCommit.getGitBranch();
|
||||
/**
|
||||
* The current version number of the game.
|
||||
* Modify this in the `project.xml` file.
|
||||
*/
|
||||
public static var VERSION(get, null):String;
|
||||
|
||||
/**
|
||||
* A suffix to add to the game version.
|
||||
* Add a suffix to prototype builds and remove it for releases.
|
||||
*/
|
||||
public static final VERSION_SUFFIX = ' PROTOTYPE';
|
||||
|
||||
#if debug
|
||||
static function get_VERSION():String
|
||||
{
|
||||
return 'v${Application.current.meta.get('version')} (${GIT_BRANCH} : ${GIT_HASH})' + VERSION_SUFFIX;
|
||||
|
@ -38,6 +40,74 @@ class Constants
|
|||
}
|
||||
#end
|
||||
|
||||
public static final URL_KICKSTARTER:String = "https://www.kickstarter.com/projects/funkin/friday-night-funkin-the-full-ass-game/";
|
||||
/**
|
||||
* URL DATA
|
||||
*/
|
||||
// ==============================
|
||||
|
||||
/**
|
||||
* Link to download the game on Itch.io.
|
||||
*/
|
||||
public static final URL_ITCH:String = "https://ninja-muffin24.itch.io/funkin/purchase";
|
||||
|
||||
/**
|
||||
* Link to the game's page on Kickstarter.
|
||||
*/
|
||||
public static final URL_KICKSTARTER:String = "https://www.kickstarter.com/projects/funkin/friday-night-funkin-the-full-ass-game/";
|
||||
|
||||
/**
|
||||
* GIT REPO DATA
|
||||
*/
|
||||
// ==============================
|
||||
|
||||
#if debug
|
||||
/**
|
||||
* The current Git branch.
|
||||
*/
|
||||
public static final GIT_BRANCH = funkin.util.macro.GitCommit.getGitBranch();
|
||||
|
||||
/**
|
||||
* The current Git commit hash.
|
||||
*/
|
||||
public static final GIT_HASH = funkin.util.macro.GitCommit.getGitCommitHash();
|
||||
#end
|
||||
|
||||
/**
|
||||
* COLORS
|
||||
*/
|
||||
// ==============================
|
||||
|
||||
/**
|
||||
* The color used by the enemy health bar.
|
||||
*/
|
||||
public static final COLOR_HEALTH_BAR_RED:FlxColor = 0xFFFF0000;
|
||||
|
||||
/**
|
||||
* The color used by the player health bar.
|
||||
*/
|
||||
public static final COLOR_HEALTH_BAR_GREEN:FlxColor = 0xFF66FF33;
|
||||
|
||||
/**
|
||||
* OTHER
|
||||
*/
|
||||
// ==============================
|
||||
|
||||
/**
|
||||
* The scale factor to use when increasing the size of pixel art graphics.
|
||||
*/
|
||||
public static final PIXEL_ART_SCALE = 6;
|
||||
|
||||
/**
|
||||
* The BPM of the title screen and menu music.
|
||||
* TODO: Move to metadata file.
|
||||
*/
|
||||
public static final FREAKY_MENU_BPM = 102;
|
||||
|
||||
/**
|
||||
* The volume at which to play the countdown before the song starts.
|
||||
*/
|
||||
public static final COUNTDOWN_VOLUME = 0.6;
|
||||
|
||||
public static final DEFAULT_VARIATION = 'default';
|
||||
public static final DEFAULT_DIFFICULTY = 'normal';
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue