Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 107 additions & 48 deletions source/funkin/ui/debug/charting/ChartEditorState.hx
Original file line number Diff line number Diff line change
Expand Up @@ -3345,8 +3345,14 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
menubarItemToggleToolboxEventData.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_EVENT_DATA_LAYOUT, event.value);
menubarItemToggleToolboxFreeplay.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_FREEPLAY_LAYOUT, event.value);
menubarItemToggleToolboxPlaytestProperties.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_PLAYTEST_PROPERTIES_LAYOUT, event.value);
menubarItemToggleToolboxPlayerPreview.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT, event.value);
menubarItemToggleToolboxOpponentPreview.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT, event.value);
menubarItemToggleToolboxPlayerPreview.onChange = event -> {
this.setToolboxState(CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT, event.value);
playerPreviewDirty = event.value;
}
menubarItemToggleToolboxOpponentPreview.onChange = event -> {
this.setToolboxState(CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT, event.value);
opponentPreviewDirty = event.value;
}

// TODO: Pass specific HaxeUI components to add context menus to them.
// registerContextMenu(null, Paths.ui('chart-editor/context/test'));
Expand Down Expand Up @@ -3669,7 +3675,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
var oldStepTime:Float = Conductor.instance.currentStepTime;
var oldSongPosition:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset;
updateSongTime();
handleHitsounds(oldSongPosition, Conductor.instance.songPosition + Conductor.instance.instrumentalOffset);
handleMusicPositionUpdate(oldSongPosition, Conductor.instance.songPosition + Conductor.instance.instrumentalOffset);
// Resync vocals.
if (Math.abs(audioInstTrack.time - audioVocalTrackGroup.time) > 100)
{
Expand All @@ -3687,7 +3693,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// Else, move the entire view.
var oldSongPosition:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset;
updateSongTime();
handleHitsounds(oldSongPosition, Conductor.instance.songPosition + Conductor.instance.instrumentalOffset);
handleMusicPositionUpdate(oldSongPosition, Conductor.instance.songPosition + Conductor.instance.instrumentalOffset);
// Resync vocals.
if (Math.abs(audioInstTrack.time - audioVocalTrackGroup.time) > 100)
{
Expand Down Expand Up @@ -3904,7 +3910,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// If a new event is needed, call buildEventSprite.
var eventSprite:ChartEditorEventSprite = renderedEvents.recycle(() -> new ChartEditorEventSprite(this), false, true);
eventSprite.parentState = this;
trace('Creating new Event... (${renderedEvents.members.length})');
// trace('Creating new Event... (${renderedEvents.members.length})');

if (eventData?.value != null && (eventData?.value?.ease != null && eventData?.value?.easeDir == null))
{
Expand Down Expand Up @@ -5392,8 +5398,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
function handleToolboxes():Void
{
handleDifficultyToolbox();
// handlePlayerPreviewToolbox();
// handleOpponentPreviewToolbox();
handlePlayerPreviewToolbox();
handleOpponentPreviewToolbox();
}

function handleDifficultyToolbox():Void
Expand All @@ -5416,15 +5422,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
function handlePlayerPreviewToolbox():Void
{
// Manage the Select Difficulty tree view.
var charPreviewToolbox:Null<CollapsibleDialog> = this.getToolbox_OLD(CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT);
var charPreviewToolbox:Null<CollapsibleDialog> = this.getToolboxUnCast(CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT);
if (charPreviewToolbox == null) return;

// TODO: Re-enable the player preview once we figure out the performance issues.
var charPlayer:Null<CharacterPlayer> = null; // charPreviewToolbox.findComponent('charPlayer');
var charPlayer:Null<CharacterPlayer> = charPreviewToolbox.findComponent('charPlayer');
if (charPlayer == null) return;

currentPlayerCharacterPlayer = charPlayer;

if (playerPreviewDirty)
{
playerPreviewDirty = false;
Expand All @@ -5442,28 +5444,28 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
charPlayer.targetScale = 0.5;

charPreviewToolbox.title = 'Player Preview - ${charPlayer.charName}';
charPreviewToolbox.invalidateComponentLayout();
}
}

if (charPreviewToolbox != null && !charPreviewToolbox.minimized)
{
charPreviewToolbox.width = charPlayer.width + 32;
charPreviewToolbox.height = charPlayer.height + 64;
}
if (charPreviewToolbox != null && !charPreviewToolbox.minimized)
{
charPreviewToolbox.width = charPlayer.width + 32;
charPreviewToolbox.height = charPlayer.height + 64;
}
currentPlayerCharacterPlayer = charPlayer;
}

function handleOpponentPreviewToolbox():Void
{
// Manage the Select Difficulty tree view.
var charPreviewToolbox:Null<CollapsibleDialog> = this.getToolbox_OLD(CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT);
var charPreviewToolbox:Null<CollapsibleDialog> = this.getToolboxUnCast(CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT);
if (charPreviewToolbox == null) return;

// TODO: Re-enable the player preview once we figure out the performance issues.
var charPlayer:Null<CharacterPlayer> = null; // charPreviewToolbox.findComponent('charPlayer');
var charPlayer:Null<CharacterPlayer> = charPreviewToolbox.findComponent('charOpponent');
if (charPlayer == null) return;

currentOpponentCharacterPlayer = charPlayer;

if (opponentPreviewDirty)
{
opponentPreviewDirty = false;
Expand All @@ -5481,14 +5483,16 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
charPlayer.targetScale = 0.5;

charPreviewToolbox.title = 'Opponent Preview - ${charPlayer.charName}';
charPreviewToolbox.invalidateComponentLayout();
}
}

if (charPreviewToolbox != null && !charPreviewToolbox.minimized)
{
charPreviewToolbox.width = charPlayer.width + 32;
charPreviewToolbox.height = charPlayer.height + 64;
}
if (charPreviewToolbox != null && !charPreviewToolbox.minimized)
{
charPreviewToolbox.width = charPlayer.width + 32;
charPreviewToolbox.height = charPlayer.height + 64;
}
currentOpponentCharacterPlayer = charPlayer;
}

function handleSelectionButtons():Void
Expand Down Expand Up @@ -5745,32 +5749,40 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
/**
* Handle aligning the health icons next to the grid.
*/
var _charIconData = null;

@:access(funkin.play.character.BaseCharacter)
function handleHealthIcons():Void
{
if (healthIconsDirty)
{
var charDataBF = CharacterDataParser.fetchCharacterData(currentSongMetadata.playData.characters.player);
var charDataDad = CharacterDataParser.fetchCharacterData(currentSongMetadata.playData.characters.opponent);
_charIconData = currentPlayerCharacterPlayer?.character?._data ?? CharacterDataParser.fetchCharacterData(currentSongMetadata.playData.characters.player);

if (healthIconBF != null)
{
healthIconBF.configure(charDataBF?.healthIcon);
healthIconBF.configure(_charIconData?.healthIcon);
healthIconBF.size *= 0.5; // Make the icon smaller in Chart Editor.
healthIconBF.flipX = !healthIconBF.flipX; // BF faces the other way.
}

if (buttonSelectPlayer != null)
{
buttonSelectPlayer.text = charDataBF?.name ?? 'Player';
buttonSelectPlayer.text = _charIconData?.name ?? 'Player';
}

_charIconData = currentOpponentCharacterPlayer?.character?._data ?? CharacterDataParser.fetchCharacterData(currentSongMetadata.playData.characters.opponent);

if (healthIconDad != null)
{
healthIconDad.configure(charDataDad?.healthIcon);
healthIconDad.configure(_charIconData?.healthIcon);
healthIconDad.size *= 0.5; // Make the icon smaller in Chart Editor.
}
if (buttonSelectOpponent != null)
{
buttonSelectOpponent.text = charDataDad?.name ?? 'Opponent';
buttonSelectOpponent.text = _charIconData?.name ?? 'Opponent';
}
healthIconsDirty = false;
_charIconData = null;
}

// Right align, and visibly center, the BF health icon.
Expand Down Expand Up @@ -6818,9 +6830,20 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
/**
* Handle the playback of hitsounds.
*/
function handleHitsounds(oldSongPosition:Float, newSongPosition:Float):Void
var _scriptNoteObj:NoteSprite = null;

var _noteScriptEvent:NoteScriptEvent = null;

var _currentEvents = null;
var _allowedEvents = null;
var _eventTarget:Null<CharacterPlayer> = null;

public static var _allowedEventsNames:Array<String> = ['PlayAnimation'];

function handleMusicPositionUpdate(oldSongPosition:Float, newSongPosition:Float):Void
{
if (!hitsoundsEnabled) return;
_currentEvents = SongDataUtils.getEventsInTimeRange(currentSongChartEventData, oldSongPosition, newSongPosition);
_allowedEvents = SongDataUtils.getEventsWithKind(_currentEvents, _allowedEventsNames);

// Assume notes are sorted by time.
for (noteData in currentSongChartNoteData)
Expand All @@ -6830,32 +6853,66 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
if (noteData.time < oldSongPosition) // Note is in the past.
continue;

if (noteData.time > newSongPosition) // Note is in the future.
return; // Assume all notes are also in the future.

// Note was just hit.
if (noteData.time > newSongPosition) break;

// Character preview.
/**
* We hit a note.
* We're gonna create scripted event and dispatch it al over ChartEditor.
*/
_scriptNoteObj = new NoteSprite(NoteStyleRegistry.instance.fetchDefault());
_scriptNoteObj.noteData = noteData;
_scriptNoteObj.kill();
_scriptNoteObj.direction = _scriptNoteObj.noteData?.getDirection() ?? 0;
_scriptNoteObj.scrollFactor.set();

// NoteScriptEvent takes a sprite, ehe. Need to rework that.
var tempNote:NoteSprite = new NoteSprite(NoteStyleRegistry.instance.fetchDefault());
tempNote.noteData = noteData;
tempNote.scrollFactor.set(0, 0);
var event:NoteScriptEvent = new HitNoteScriptEvent(tempNote, 0.0, 0, 'perfect', false, 0);
dispatchEvent(event);
_noteScriptEvent = new HitNoteScriptEvent(_scriptNoteObj, 0.0, 0, (noteData.getStrumlineIndex() == 0 ? 'perfect' : 'sick'), false, 0);
dispatchEvent(_noteScriptEvent);

// Calling event.cancelEvent() skips all the other logic! Neat!
if (event.eventCanceled) continue;
if (_noteScriptEvent.eventCanceled)
{
_scriptNoteObj.destroy();
_scriptNoteObj = null;

_noteScriptEvent = null;

continue;
}

// Hitsounds.
switch (noteData.getStrumlineIndex())
if (hitsoundsEnabled) switch (noteData.getStrumlineIndex())
{
case 0: // Player
if (hitsoundVolumePlayer > 0) this.playSound(Paths.sound('chartingSounds/hitNotePlayer'), hitsoundVolumePlayer);
case 1: // Opponent
if (hitsoundVolumeOpponent > 0) this.playSound(Paths.sound('chartingSounds/hitNoteOpponent'), hitsoundVolumeOpponent);
}
}
// Clearing memory before next event call.
_scriptNoteObj?.destroy();
_scriptNoteObj = null;

_noteScriptEvent = null;
for (data in _allowedEvents)
{
switch (data.eventKind)
{
case "PlayAnimation":
switch (data.getString('target').toLowerCase().trim())
{
case 'boyfriend' | 'bf' | 'player':
_eventTarget = currentPlayerCharacterPlayer;
case 'dad' | 'opponent' | 'enemy':
_eventTarget = currentOpponentCharacterPlayer;
default:
}
if (_eventTarget != null) _eventTarget.playAnimManually(data.getString('anim') ?? 'idle', data.getBool('force') ?? false);
}
}

_currentEvents = null;
_allowedEvents.resize(0);
_eventTarget = null;
}

function stopAudioPlayback():Void
Expand Down Expand Up @@ -6925,6 +6982,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState

// Many things get reset when song length changes.
healthIconsDirty = true;
playerPreviewDirty = true;
opponentPreviewDirty = true;
}

public function loadSubtitles():Void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,19 @@ class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu
charButton.onClick = _ -> {
switch (charType)
{
case BF: chartEditorState.currentSongMetadata.playData.characters.player = charId;
case BF:
chartEditorState.currentSongMetadata.playData.characters.player = charId;
chartEditorState.playerPreviewDirty = true;
case GF: chartEditorState.currentSongMetadata.playData.characters.girlfriend = charId;
case DAD: chartEditorState.currentSongMetadata.playData.characters.opponent = charId;
case DAD:
chartEditorState.currentSongMetadata.playData.characters.opponent = charId;
chartEditorState.opponentPreviewDirty = true;
default: throw 'Invalid charType: ' + charType;
};

defaultText = (charId != "") ? '${charData.name} [${charId}]' : 'None';
chartEditorState.healthIconsDirty = true;

chartEditorState.refreshToolbox(ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,14 @@ class ChartEditorToolboxHandler
* @param id The asset ID of the toolbox layout.
* @return The toolbox.
*/
public static function getToolbox_OLD(state:ChartEditorState, id:String):Null<CollapsibleDialog>
public static function getToolboxUnCast(state:ChartEditorState, id:String):Null<CollapsibleDialog>
{
var toolbox:Null<CollapsibleDialog> = state.activeToolboxes.get(id);

// Initialize the toolbox without showing it.
if (toolbox == null) toolbox = initToolbox(state, id);

if (toolbox == null) throw 'ChartEditorToolboxHandler.getToolbox_OLD() - Could not retrieve or build toolbox: $id';
if (toolbox == null) throw 'ChartEditorToolboxHandler.getToolboxUnCast() - Could not retrieve or build toolbox: $id';

return toolbox;
}
Expand Down Expand Up @@ -346,8 +346,8 @@ class ChartEditorToolboxHandler
if (toolbox == null) return null;

// Starting position.
toolbox.x = 200;
toolbox.y = 350;
toolbox.x = 700;
toolbox.y = 150;

toolbox.onDialogClosed = function(event:DialogEvent) {
state.menubarItemToggleToolboxPlayerPreview.selected = false;
Expand Down Expand Up @@ -376,14 +376,14 @@ class ChartEditorToolboxHandler

// Starting position.
toolbox.x = 200;
toolbox.y = 350;
toolbox.y = 150;

toolbox.onDialogClosed = (event:DialogEvent) -> {
state.menubarItemToggleToolboxOpponentPreview.selected = false;
}

var charPlayer:Null<CharacterPlayer> = toolbox.findComponent('charPlayer');
if (charPlayer == null) throw 'ChartEditorToolboxHandler.buildToolboxOpponentPreviewLayout() - Could not find charPlayer component.';
var charPlayer:Null<CharacterPlayer> = toolbox.findComponent('charOpponent');
if (charPlayer == null) throw 'ChartEditorToolboxHandler.buildToolboxOpponentPreviewLayout() - Could not find charOpponent component.';
// TODO: We need to implement character swapping in ChartEditorState.
charPlayer.loadCharacter('dad');
charPlayer.characterType = CharacterType.DAD;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ class ChartEditorDifficultyToolbox extends ChartEditorBaseToolbox
{
chartEditorState.currentSongMetadata = songMetadata;
chartEditorState.healthIconsDirty = true;
chartEditorState.playerPreviewDirty = true;
chartEditorState.opponentPreviewDirty = true;

chartEditorState.refreshToolbox(ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT);
chartEditorState.success('Replaced Metadata', 'Replaced metadata with file (${fileReference.name})');
}
Expand Down
Loading