Skip to content

Commit

Permalink
Lots of reported bugs fixed.
Browse files Browse the repository at this point in the history
  • Loading branch information
EliteMasterEric committed Oct 18, 2023
1 parent d47c5f5 commit cdab875
Show file tree
Hide file tree
Showing 14 changed files with 147 additions and 26 deletions.
6 changes: 6 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
"name": "Haxe Eval",
"type": "haxe-eval",
"request": "launch"
},
{
// Attaches the debugger to an already running game
"name": "HXCPP - Attach",
"type": "hxcpp",
"request": "attach"
}
]
}
2 changes: 1 addition & 1 deletion source/funkin/PauseSubState.hx
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ class PauseSubState extends MusicBeatSubState

case 'Exit to Chart Editor':
this.close();
if (FlxG.sound.music != null) FlxG.sound.music.stop();
if (FlxG.sound.music != null) FlxG.sound.music.pause(); // Don't reset song position!
PlayState.instance.close(); // This only works because PlayState is a substate!

case 'BACK':
Expand Down
51 changes: 45 additions & 6 deletions source/funkin/data/DataParse.hx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package funkin.data;

import funkin.data.song.importer.FNFLegacyData.LegacyNote;
import hxjsonast.Json;
import hxjsonast.Tools;
import hxjsonast.Json.JObjectField;
import haxe.ds.Either;
import funkin.data.song.importer.FNFLegacyData.LegacyNoteSection;
import funkin.data.song.importer.FNFLegacyData.LegacyNoteData;
import funkin.data.song.importer.FNFLegacyData.LegacyNoteSection;
import funkin.data.song.importer.FNFLegacyData.LegacyScrollSpeeds;
import haxe.ds.Either;
import hxjsonast.Json;
import hxjsonast.Json.JObjectField;
import hxjsonast.Tools;
import thx.semver.Version;
import thx.semver.VersionRule;

/**
* `json2object` has an annotation `@:jcustomparse` which allows for mutation of parsed values.
Expand All @@ -23,7 +25,8 @@ class DataParse
* `@:jcustomparse(funkin.data.DataParse.stringNotEmpty)`
* @param json Contains the `pos` and `value` of the property.
* @param name The name of the property.
* @throws If the property is not a string or is empty.
* @throws Error If the property is not a string or is empty.
* @return The string value.
*/
public static function stringNotEmpty(json:Json, name:String):String
{
Expand All @@ -37,6 +40,42 @@ class DataParse
}
}

/**
* `@:jcustomparse(funkin.data.DataParse.semverVersion)`
* @param json Contains the `pos` and `value` of the property.
* @param name The name of the property.
* @return The value of the property as a `thx.semver.Version`.
*/
public static function semverVersion(json:Json, name:String):Version
{
switch (json.value)
{
case JString(s):
if (s == "") throw 'Expected version property $name to be non-empty.';
return s;
default:
throw 'Expected version property $name to be a string, but it was ${json.value}.';
}
}

/**
* `@:jcustomparse(funkin.data.DataParse.semverVersionRule)`
* @param json Contains the `pos` and `value` of the property.
* @param name The name of the property.
* @return The value of the property as a `thx.semver.VersionRule`.
*/
public static function semverVersionRule(json:Json, name:String):VersionRule
{
switch (json.value)
{
case JString(s):
if (s == "") throw 'Expected version rule property $name to be non-empty.';
return s;
default:
throw 'Expected version rule property $name to be a string, but it was ${json.value}.';
}
}

/**
* Parser which outputs a Dynamic value, either a object or something else.
* @param json
Expand Down
23 changes: 23 additions & 0 deletions source/funkin/data/DataWrite.hx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package funkin.data;

import funkin.util.SerializerUtil;
import thx.semver.Version;
import thx.semver.VersionRule;

/**
* `json2object` has an annotation `@:jcustomwrite` which allows for custom serialization of values to be written to JSON.
Expand All @@ -9,9 +11,30 @@ import funkin.util.SerializerUtil;
*/
class DataWrite
{
/**
* `@:jcustomwrite(funkin.data.DataWrite.dynamicValue)`
* @param value
* @return String
*/
public static function dynamicValue(value:Dynamic):String
{
// Is this cheating? Yes. Do I care? No.
return SerializerUtil.toJSON(value);
}

/**
* `@:jcustomwrite(funkin.data.DataWrite.semverVersion)`
*/
public static function semverVersion(value:Version):String
{
return value.toString();
}

/**
* `@:jcustomwrite(funkin.data.DataWrite.semverVersionRule)`
*/
public static function semverVersionRule(value:VersionRule):String
{
return value.toString();
}
}
6 changes: 6 additions & 0 deletions source/funkin/data/song/SongData.hx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class SongMetadata
*
*/
// @:default(funkin.data.song.SongRegistry.SONG_METADATA_VERSION)
@:jcustomparse(funkin.data.DataParse.semverVersion)
@:jcustomwrite(funkin.data.DataWrite.semverVersion)
public var version:Version;

@:default("Unknown")
Expand Down Expand Up @@ -203,6 +205,8 @@ class SongMusicData
*
*/
// @:default(funkin.data.song.SongRegistry.SONG_METADATA_VERSION)
@:jcustomparse(funkin.data.DataParse.semverVersion)
@:jcustomwrite(funkin.data.DataWrite.semverVersion)
public var version:Version;

@:default("Unknown")
Expand Down Expand Up @@ -367,6 +371,8 @@ class SongCharacterData
class SongChartData
{
@:default(funkin.data.song.SongRegistry.SONG_CHART_DATA_VERSION)
@:jcustomparse(funkin.data.DataParse.semverVersion)
@:jcustomwrite(funkin.data.DataWrite.semverVersion)
public var version:Version;

public var scrollSpeed:Map<String, Float>;
Expand Down
7 changes: 4 additions & 3 deletions source/funkin/data/song/SongDataUtils.hx
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ class SongDataUtils

typedef SongClipboardItems =
{
?valid:Bool,
notes:Array<SongNoteData>,
events:Array<SongEventData>
@:optional
var valid:Bool;
var notes:Array<SongNoteData>;
var events:Array<SongEventData>;
}
2 changes: 2 additions & 0 deletions source/funkin/data/song/migrator/SongData_v2_0_0.hx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class SongMetadata_v2_0_0
// ==========
// UNMODIFIED VALUES
// ==========
@:jcustomparse(funkin.data.DataParse.semverVersion)
@:jcustomwrite(funkin.data.DataWrite.semverVersion)
public var version:Version;

@:default("Unknown")
Expand Down
12 changes: 8 additions & 4 deletions source/funkin/play/HealthIcon.hx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ class HealthIcon extends FlxSprite
if (value == characterId) return value;

characterId = value ?? Constants.DEFAULT_HEALTH_ICON;
loadCharacter(characterId);
return characterId;
}

Expand All @@ -138,7 +137,6 @@ class HealthIcon extends FlxSprite
if (value == isPixel) return value;

isPixel = value;
loadCharacter(characterId);
return isPixel;
}

Expand All @@ -165,17 +163,23 @@ class HealthIcon extends FlxSprite
{
if (data == null)
{
this.isPixel = false;
this.characterId = Constants.DEFAULT_HEALTH_ICON;
this.isPixel = false;

loadCharacter(characterId);

this.size.set(1.0, 1.0);
this.offset.x = 0.0;
this.offset.y = 0.0;
this.flipX = false;
}
else
{
this.isPixel = data.isPixel ?? false;
this.characterId = data.id;
this.isPixel = data.isPixel ?? false;

loadCharacter(characterId);

this.size.set(data.scale ?? 1.0, data.scale ?? 1.0);
this.offset.x = (data.offsets != null) ? data.offsets[0] : 0.0;
this.offset.y = (data.offsets != null) ? data.offsets[1] : 0.0;
Expand Down
10 changes: 9 additions & 1 deletion source/funkin/play/PlayState.hx
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,15 @@ class PlayState extends MusicBeatSubState
FlxG.sound.music.pause();
FlxG.sound.music.time = (startTimestamp);

vocals = currentChart.buildVocals();
if (!overrideMusic)
{
vocals = currentChart.buildVocals();

if (vocals.members.length == 0)
{
trace('WARNING: No vocals found for this song.');
}
}
vocals.pause();
vocals.time = 0;

Expand Down
6 changes: 6 additions & 0 deletions source/funkin/play/song/Song.hx
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,12 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
{
if (metadata == null || metadata.playData == null) continue;

// If there are no difficulties in the metadata, there's a problem.
if (metadata.playData.difficulties.length == 0)
{
throw 'Song $id has no difficulties listed in metadata!';
}

// There may be more difficulties in the chart file than in the metadata,
// (i.e. non-playable charts like the one used for Pico on the speaker in Stress)
// but all the difficulties in the metadata must be in the chart file.
Expand Down
2 changes: 2 additions & 0 deletions source/funkin/save/Save.hx
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,8 @@ typedef RawSaveData =
/**
* A semantic versioning string for the save data format.
*/
@:jcustomparse(funkin.data.DataParse.semverVersion)
@:jcustomwrite(funkin.data.DataWrite.semverVersion)
var version:Version;

var api:SaveApiData;
Expand Down
11 changes: 8 additions & 3 deletions source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,6 @@ class ChartEditorDialogHandler
{
if (ChartEditorAudioHandler.loadInstFromBytes(state, selectedFile.bytes, instId))
{
trace('Selected file: ' + selectedFile.fullPath);
#if !mac
NotificationManager.instance.addNotification(
{
Expand All @@ -415,13 +414,12 @@ class ChartEditorDialogHandler
});
#end

state.switchToCurrentInstrumental();
dialog.hideDialog(DialogButton.APPLY);
removeDropHandler(onDropFile);
}
else
{
trace('Failed to load instrumental (${selectedFile.fullPath})');

#if !mac
NotificationManager.instance.addNotification(
{
Expand Down Expand Up @@ -452,6 +450,7 @@ class ChartEditorDialogHandler
});
#end

state.switchToCurrentInstrumental();
dialog.hideDialog(DialogButton.APPLY);
removeDropHandler(onDropFile);
}
Expand Down Expand Up @@ -570,6 +569,12 @@ class ChartEditorDialogHandler

var newSongMetadata:SongMetadata = new SongMetadata('', '', 'default');

newSongMetadata.playData.difficulties = switch (targetVariation)
{
case 'erect': ['erect', 'nightmare'];
default: ['easy', 'normal', 'hard'];
};

var inputSongName:Null<TextField> = dialog.findComponent('inputSongName', TextField);
if (inputSongName == null) throw 'Could not locate inputSongName TextField in Song Metadata dialog';
inputSongName.onChange = function(event:UIEvent) {
Expand Down
22 changes: 14 additions & 8 deletions source/funkin/ui/debug/charting/ChartEditorState.hx
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,9 @@ class ChartEditorState extends HaxeUIState
notePreviewDirty = true;
notePreviewViewportBoundsDirty = true;

// Make sure the difficulty we selected is in the list of difficulties.
currentSongMetadata.playData.difficulties.pushUnique(selectedDifficulty);

return selectedDifficulty;
}

Expand Down Expand Up @@ -971,6 +974,7 @@ class ChartEditorState extends HaxeUIState
result = [];
trace('Initializing blank note data for difficulty ' + selectedDifficulty);
currentSongChartData.notes.set(selectedDifficulty, result);
currentSongMetadata.playData.difficulties.pushUnique(selectedDifficulty);
return result;
}
return result;
Expand All @@ -979,6 +983,7 @@ class ChartEditorState extends HaxeUIState
function set_currentSongChartNoteData(value:Array<SongNoteData>):Array<SongNoteData>
{
currentSongChartData.notes.set(selectedDifficulty, value);
currentSongMetadata.playData.difficulties.pushUnique(selectedDifficulty);
return value;
}

Expand Down Expand Up @@ -4089,7 +4094,7 @@ class ChartEditorState extends HaxeUIState
}

subStateClosed.add(fixCamera);
subStateClosed.add(updateConductor);
subStateClosed.add(resetConductorAfterTest);

FlxTransitionableState.skipNextTransIn = false;
FlxTransitionableState.skipNextTransOut = false;
Expand Down Expand Up @@ -4122,10 +4127,9 @@ class ChartEditorState extends HaxeUIState
add(this.component);
}

function updateConductor(_:FlxSubState = null):Void
function resetConductorAfterTest(_:FlxSubState = null):Void
{
var targetPos = scrollPositionInMs;
Conductor.update(targetPos);
moveSongToScrollPosition();
}

public function postLoadInstrumental():Void
Expand Down Expand Up @@ -4179,12 +4183,14 @@ class ChartEditorState extends HaxeUIState
function moveSongToScrollPosition():Void
{
// Update the songPosition in the audio tracks.
if (audioInstTrack != null) audioInstTrack.time = scrollPositionInMs + playheadPositionInMs;
if (audioInstTrack != null)
{
audioInstTrack.time = scrollPositionInMs + playheadPositionInMs;
// Update the songPosition in the Conductor.
Conductor.update(audioInstTrack.time);
}
if (audioVocalTrackGroup != null) audioVocalTrackGroup.time = scrollPositionInMs + playheadPositionInMs;

// Update the songPosition in the Conductor.
Conductor.update(audioInstTrack.time);

// We need to update the note sprites because we changed the scroll position.
noteDisplayDirty = true;
}
Expand Down
13 changes: 13 additions & 0 deletions source/funkin/util/tools/ArrayTools.hx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ class ArrayTools
return null;
}

/**
* Push an element to the array if it is not already present.
* @param input The array to push to
* @param element The element to push
* @return Whether the element was pushed
*/
public static function pushUnique<T>(input:Array<T>, element:T):Bool
{
if (input.contains(element)) return false;
input.push(element);
return true;
}

/**
* Remove all elements from the array, without creating a new array.
* @param array The array to clear.
Expand Down

0 comments on commit cdab875

Please sign in to comment.