diff --git a/CHANGELOG.md b/CHANGELOG.md index 3382d24415..2e592361eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,20 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 This patch resolves a critical issue which could cause user's save data to become corrupted. It is recommended that users switch to this version immediately and avoid using version 0.5.2. ### Fixed - Fixed a critical issue in which the Stage Editor theme value could not be parsed by older versions of the game, resulting in all save data being destroyed. - - Added a check that prevents save data from being loaded if it is corrupted rather than overriding it. -- `optionsChartEditor.chartEditorLiveInputStyle` in the save data converted from an Enum to a String to fix save data compatibility issues. + - Added a check which prevents save data from being loaded if it is corrupted rather than overriding it. - `optionsStageEditor.theme` in the save data converted from an Enum to a String to fix save data compatibility issues. - In the future, Enum values should not be used in order to prevent incompatibilities caused by introducing new types to the save data that older versions cannot parse. -- Fixed an issue where some publicly distributed release builds of the game were not updated to the latest version. - +- `optionsChartEditor.theme` in the save data converted from an Enum to a String to fix save data compatibility issues. +- `optionsChartEditor.chartEditorLiveInputStyle` in the save data converted from an Enum to a String to fix save data compatibility issues. +- Fixed an issue where some publicly distributed builds of the game were debug builds instead of release builds. ## [0.5.2] - 2024-10-11 -### Added -- Added InverseDotsShader that emulates flash selections ([097dbf5](https://github.com/FunkinCrew/Funkin/commit/097dbf5bb4346d431d8ca9f0ec4bc5b5e6f4523f)) - by @ninjamuffin99 -- Added a new reworked Stage Editor ([27a0b44](https://github.com/FunkinCrew/Funkin/pull/3482/commits/27a0b4426f86f04362f97e16e2eff580c9402f34)) - by @JustKolosaki in [#3482](https://github.com/FunkinCrew/Funkin/pull/3482) -- Added the `color` attribute to stage prop JSON data to allow them to be tinted without code. ([27a0b44](https://github.com/FunkinCrew/Funkin/pull/3482/commits/27a0b4426f86f04362f97e16e2eff580c9402f34)) - by @JustKolosaki -- Added the `angle` attribute to stage prop JSON data to allow them to be rotated without code. ([27a0b44](https://github.com/FunkinCrew/Funkin/pull/3482/commits/27a0b4426f86f04362f97e16e2eff580c9402f34)) - by @JustKolosaki -- Added the `blend` attribute to the stage prop JSON data to allow blend modes to be applied without code. ([27a0b44](https://github.com/FunkinCrew/Funkin/pull/3482/commits/27a0b4426f86f04362f97e16e2eff580c9402f34)) - by @JustKolosaki + ### Changed - (docs) Delete Modding.md since we have a separate modding documentation ([a42240e](https://github.com/FunkinCrew/Funkin/commit/a42240e6a595d33034f2c887bf38a350d1fa0f15)) - by @AbnormalPoof in [#3651](https://github.com/FunkinCrew/Funkin/pull/3651) - (docs) Create a git cliff template for easier changelog stuff ([91b4544](https://github.com/FunkinCrew/Funkin/commit/91b4544f7ebc51485e3e28c3d716ba6ee69ad885)) - by @ninjamuffin99 in [#3652](https://github.com/FunkinCrew/Funkin/pull/3652) @@ -43,16 +38,17 @@ This patch resolves a critical issue which could cause user's save data to becom - The dialog now shows up on the animation debugger view ([1fde59f](https://github.com/FunkinCrew/Funkin/commit/1fde59f999eac94eb10fc22094885de2f5310705)) - by @EliteMasterEric in [#3530](https://github.com/FunkinCrew/Funkin/pull/3530) - Center preloader 'fnf' and 'dsp' text so it doesn't clip anymore ([165ad60](https://github.com/FunkinCrew/Funkin/commit/165ad6015539a295e9eefdaef291c312e9566b26)) - by @Burgerballs in [#3567](https://github.com/FunkinCrew/Funkin/pull/3567) - `Song.getFirstValidVariation()` now properly takes into account multiple variations/difficulty input ([d2e2987](https://github.com/FunkinCrew/Funkin/commit/d2e29879fe2acc6febfe0f335f655b741d630c34)) - by @ninjamuffin99 in [#3506](https://github.com/FunkinCrew/Funkin/pull/3506) -- (debug) No more fullscreening when typing "F" in the flixel debugger console ([29b6763](https://github.com/FunkinCrew/Funkin/commit/29b6763290df05d42039806f3d142740568c80f0)) - by @ninjamuffin99 -- Fix crash in LatencyState when exiting / cleaning up state data ([39b1a42](https://github.com/FunkinCrew/Funkin/commit/39b1a42cfeafe2b7be8b66e2fe529e853d9ae197)) - by @lemz1 in [#3493](https://github.com/FunkinCrew/Funkin/pull/3493) -- Add additional classes to Polymod blacklist for security ([b0b73c8](https://github.com/FunkinCrew/Funkin/commit/b0b73c83994f33118c6a69550da9ec8ec1c07adc)) - by @EliteMasterEric in [#3558](https://github.com/FunkinCrew/Funkin/pull/3558) -- Stop allowing inputs after selecting a character ([dbf66ac](https://github.com/FunkinCrew/Funkin/commit/dbf66ac250137262866d75f7c1387645b35d88d0)) - by @ACrazyTown in [#3398](https://github.com/FunkinCrew/Funkin/pull/3398) -- Fix conflict with modded StrumlineNote sprite looping animation ([bc546e8](https://github.com/FunkinCrew/Funkin/commit/bc546e86aa77ffc795b3f079de5f590289a9c583)) - by @DaWaterMalone in [#3577](https://github.com/FunkinCrew/Funkin/pull/3577) -- Properly format the millisecond counter in the chart editor playbar ([f1b6e6c](https://github.com/FunkinCrew/Funkin/commit/f1b6e6c4e42455e0c2900d738ebc24893f2479a0)) - by @afreetoplaynoob in [#3537](https://github.com/FunkinCrew/Funkin/pull/3537) -- Fixed an issue where the player and girlfriend would disappear or overlap themselves in Character Select ([community fix by @gamerbross](https://github.com/FunkinCrew/Funkin/pull/3457)) -- Fixed an issue where the game would show the wrong girlfriend in Character Select ([community fix by @gamerbross](https://github.com/FunkinCrew/Funkin/pull/3457)) -- Fixed an issue where the cursor wouldn't update properly in Character Select ([community fix by @gamerbross](https://github.com/FunkinCrew/Funkin/pull/3457)) -- Fixed an issue where the player would display double after entering character select or when spamming buttons ([community fix by @gamerbross](https://github.com/FunkinCrew/Funkin/pull/3457)) +- (freeplay) Proper variation / difficulty loading for Freeplay Menu ([c0314c8](https://github.com/FunkinCrew/Funkin/commit/c0314c85ecd5116641aff3de8e9153f7fe48e79c)) - by @ninjamuffin99 +- Picos songs properly load on freeplay ([1d2bd61](https://github.com/FunkinCrew/Funkin/commit/1d2bd61119e5f418df7f11d7ef2a0fdedee17d3d)) - by @ninjamuffin99 +- (debug) No more fullscreening when typing "F" in the flixel debugger console ([29b6763](https://github.com/FunkinCrew/Funkin/commit/29b6763290df05d42039806f3d142740568c80f0)) - by @ninjamuffin99 +- Fix the user song offsets being applied incorrectly ([410cfe9](https://github.com/FunkinCrew/Funkin/commit/410cfe972d6df9de4d4d128375cf8380c4f06d92)) - by @JustKolosaki +- Fix crash in LatencyState when exiting / cleaning up state data ([39b1a42](https://github.com/FunkinCrew/Funkin/commit/39b1a42cfeafe2b7be8b66e2fe529e853d9ae197)) - by @lemz1 +- Add additional classes to Polymod Blacklist ([b0b73c8](https://github.com/FunkinCrew/Funkin/commit/b0b73c83994f33118c6a69550da9ec8ec1c07adc)) - by @EliteMasterEric +- Stop allowing inputs after selecting a character ([dbf66ac](https://github.com/FunkinCrew/Funkin/commit/dbf66ac250137262866d75f7c1387645b35d88d0)) - by @ACrazyTown +- Fixed an issue where the player and girlfriend would disappear or overlap themselves in Character Select (community fix by gamerbross) +- Fixed an issue where the game would show the wrong girlfriend in Character Select (community fix by gamerbross) +- Fixed an issue where the cursor wouldn't update properly in Character Select (community fix by gamerbross) +- Fixed an issue where the player would display double after entering character select or when spamming buttons (community fix by gamerbross) ## New Contributors for 0.5.2 * @JustKolosaki made their first contribution in [#3482](https://github.com/FunkinCrew/Funkin/pull/3482) @@ -302,19 +298,17 @@ which would remove their rank if they had a lower one. - Fixed an issue where Nene's visualizer would not play on Desktop builds - Fixed a bug where the game would silently fail to load saves on HTML5 - Fixed some bugs with the props on the Story Menu not bopping properly -- Additional fixes to the Loading bar on HTML5 ([thanks lemz1!](https://github.com/FunkinCrew/Funkin/pull/2553)) -- Fixed several bugs with the TitleState, including missing music when returning from the Main Menu ([thanks gamerbross!](https://github.com/FunkinCrew/Funkin/pull/2539)) -- Fixed a camera bug in the Main Menu ([thanks richTrash21!](https://github.com/FunkinCrew/Funkin/pull/2576)) -- Fixed a bug where changing difficulties in Story mode wouldn't update the score ([thanks sector-a!](https://github.com/FunkinCrew/Funkin/pull/2585)) -- Fixed a crash in Freeplay caused by a level referencing an invalid song ([thanks gamerbross!](https://github.com/FunkinCrew/Funkin/pull/2457)) -- Fixed a bug where pressing the volume keys would stop the Toy commercial ([thanks gamerbross!](https://github.com/FunkinCrew/Funkin/pull/2540)) -- Fixed a bug where the Chart Editor Playtest would crash when losing ([thanks gamerbross!](https://github.com/FunkinCrew/Funkin/pull/2518)) -- Fixed a bug where hold notes would display improperly in the Chart Editor when downscroll was enabled for gameplay ([thanks gamerbross!](https://github.com/FunkinCrew/Funkin/pull/2565)) -- Fixed a bug where hold notes would be positioned wrong on downscroll ([thanks MaybeMaru!](https://github.com/FunkinCrew/Funkin/pull/2488)) -- Removed a large number of unused imports to optimize builds ([thanks Ethan-makes-music!](https://github.com/FunkinCrew/Funkin/pull/2624)) -- Improved debug logging for unscripted stages ([thanks gamerbross!](https://github.com/FunkinCrew/Funkin/pull/2603)) -- Fixed a crash on Linux caused by an old version of hxCodec ([thanks Noobz4Life!](https://github.com/FunkinCrew/Funkin/pull/2472)) -- Optimized animation handling for characters ([thanks richTrash21!](https://github.com/FunkinCrew/Funkin/pull/2493)) +- Additional fixes to the Loading bar on HTML5 (thanks lemz1!) +- Fixed several bugs with the TitleState, including missing music when returning from the Main Menu (thanks gamerbross!) +- Fixed a camera bug in the Main Menu (thanks richTrash21!) +- Fixed a bug where changing difficulties in Story mode wouldn't update the score (thanks sectorA!) +- Fixed a crash in Freeplay caused by a level referencing an invalid song (thanks gamerbross!) +- Fixed a bug where pressing the volume keys would stop the Toy commercial (thanks gamerbross!) +- Fixed a bug where the Chart Editor Playtest would crash when losing (thanks gamerbross!) +- Fixed a bug where hold notes would display improperly in the Chart Editor when downscroll was enabled for gameplay (thanks gamerbross!) +- Fixed a bug where hold notes would be positioned wrong on downscroll (thanks MaybeMaru!) +- Removed a large number of unused imports to optimize builds (thanks Ethan-makes-music!) +- Improved debug logging for unscripted stages (thanks gamerbross!) - Made improvements to compiling documentation (thanks gedehari!) - Fixed an issue where the Chart Editor would use an incorrect instrumental on imported Legacy songs ([thanks gamerbross!](https://github.com/FunkinCrew/Funkin/pull/2604)) - Fixed a bug where opening the game from the command line would crash the preloader ([thanks NotHyper-474!](https://github.com/FunkinCrew/Funkin/pull/2629)) @@ -429,7 +423,7 @@ which would remove their rank if they had a lower one. - Improvements to video cutscenes and dialogue, allowing them to be easily skipped or restarted. - Updated Polymod by several major versions, allowing for fully dynamic asset replacement and support for scripted classes. - Completely refactored almost every part of the game's code for performance, stability, and extensibility. - - This is not the Ludem Dare game held together with sticks and glue you played three years ago. + - This is not the Ludum Dare game held together with sticks and glue you played three years ago. - Characters, stages, songs, story levels, and dialogue are now built from JSON data registries rather than being hardcoded. - All of these also support attaching scripts for custom behavior, more documentation on this soon. - You can forcibly reload the game's JSON data and scripts by pressing F5. diff --git a/hmm.json b/hmm.json index 8ff572b30b..50879416b6 100644 --- a/hmm.json +++ b/hmm.json @@ -11,7 +11,7 @@ "name": "flixel", "type": "git", "dir": null, - "ref": "f2b090d6c608471e730b051c8ee22b8b378964b1", + "ref": "ffa691cb2d2d81de35b900a4411e4062ac84ab58", "url": "https://github.com/FunkinCrew/flixel" }, { diff --git a/project.hxp b/project.hxp index 280f840eb4..e79dde189d 100644 --- a/project.hxp +++ b/project.hxp @@ -25,7 +25,7 @@ class Project extends HXProject { * REMEMBER TO CHANGE THIS WHEN THE GAME UPDATES! * You only have to change it here, the rest of the game will query this value. */ - static final VERSION:String = "0.5.2"; + static final VERSION:String = "0.5.3"; /** * The game's name. Used as the default window title. @@ -460,7 +460,6 @@ class Project extends HXProject { // Should be false unless explicitly requested. GITHUB_BUILD.apply(this, false); - FEATURE_STAGE_EDITOR.apply(this, false); FEATURE_NEWGROUNDS.apply(this, false); FEATURE_GHOST_TAPPING.apply(this, false); @@ -471,10 +470,14 @@ class Project extends HXProject { FEATURE_FUNKVIS.apply(this, true); FEATURE_PARTIAL_SOUNDS.apply(this, true); FEATURE_VIDEO_PLAYBACK.apply(this, true); + FEATURE_STAGE_EDITOR.apply(this, true); // Should be true on debug builds or if GITHUB_BUILD is enabled. FEATURE_DEBUG_FUNCTIONS.apply(this, isDebug() || GITHUB_BUILD.isEnabled(this)); - FEATURE_LOG_TRACE.apply(this, isDebug()); + + // Got a lot of complains about this being turned off by default on some builds. + // TODO: Look into ways to optimize logging (maybe by using a thread pool?) + FEATURE_LOG_TRACE.apply(this, true); // Should default to true on workspace builds and false on release builds. REDIRECT_ASSETS_FOLDER.apply(this, isDebug() && isDesktop()); diff --git a/source/funkin/data/stage/CHANGELOG.md b/source/funkin/data/stage/CHANGELOG.md index bf9d750cc7..f83ce608d4 100644 --- a/source/funkin/data/stage/CHANGELOG.md +++ b/source/funkin/data/stage/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.3] +### Added +- Added the `color` attribute on stage props to tint them. +- Added the `blend` attribute on stage props to apply blend modes. +- Added the `angle` attribute on stage props to apply a rotation to them. + ## [1.0.2] ### Added - Added the ability to specify `flipX` and `flipY` on stage props to horizontally or vertically flip, respectively. diff --git a/source/funkin/data/stage/StageRegistry.hx b/source/funkin/data/stage/StageRegistry.hx index e11166bddd..0c546d0ab9 100644 --- a/source/funkin/data/stage/StageRegistry.hx +++ b/source/funkin/data/stage/StageRegistry.hx @@ -11,9 +11,9 @@ class StageRegistry extends BaseRegistry * Handle breaking changes by incrementing this value * and adding migration to the `migrateStageData()` function. */ - public static final STAGE_DATA_VERSION:thx.semver.Version = "1.0.2"; + public static final STAGE_DATA_VERSION:thx.semver.Version = "1.0.3"; - public static final STAGE_DATA_VERSION_RULE:thx.semver.VersionRule = ">=1.0.0 <=1.0.2"; + public static final STAGE_DATA_VERSION_RULE:thx.semver.VersionRule = ">=1.0.0 <=1.0.3"; public static var instance(get, never):StageRegistry; static var _instance:Null = null; diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 2280686400..aeb87231fe 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1,17 +1,13 @@ package funkin.play; -import flixel.addons.display.FlxPieDial; import flixel.addons.transition.FlxTransitionableState; import flixel.addons.transition.Transition; import flixel.FlxCamera; import flixel.FlxObject; -import flixel.FlxState; import flixel.FlxSubState; import flixel.math.FlxMath; import flixel.math.FlxPoint; -import flixel.math.FlxRect; import flixel.text.FlxText; -import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.ui.FlxBar; import flixel.util.FlxColor; @@ -22,7 +18,6 @@ import funkin.audio.FunkinSound; import funkin.audio.VoicesGroup; import funkin.data.dialogue.conversation.ConversationRegistry; import funkin.data.event.SongEventRegistry; -import funkin.data.notestyle.NoteStyleData; import funkin.data.notestyle.NoteStyleRegistry; import funkin.data.song.SongData.SongCharacterData; import funkin.data.song.SongData.SongEventData; @@ -45,7 +40,6 @@ import funkin.play.cutscene.VanillaCutscenes; import funkin.play.cutscene.VideoCutscene; import funkin.play.notes.NoteDirection; import funkin.play.notes.notekind.NoteKindManager; -import funkin.play.notes.NoteSplash; import funkin.play.notes.NoteSprite; import funkin.play.notes.notestyle.NoteStyle; import funkin.play.notes.Strumline; @@ -58,15 +52,9 @@ import funkin.ui.debug.charting.ChartEditorState; import funkin.ui.debug.stage.StageOffsetSubState; import funkin.ui.mainmenu.MainMenuState; import funkin.ui.MusicBeatSubState; -import funkin.ui.options.PreferencesMenu; -import funkin.ui.story.StoryMenuState; import funkin.ui.transition.LoadingState; import funkin.util.SerializerUtil; import haxe.Int64; -import lime.ui.Haptic; -import openfl.display.BitmapData; -import openfl.geom.Rectangle; -import openfl.Lib; #if FEATURE_DISCORD_RPC import funkin.api.discord.DiscordClient; #end @@ -760,24 +748,6 @@ class PlayState extends MusicBeatSubState refresh(); } - public override function draw():Void - { - // if (FlxG.renderBlit) - // { - // camGame.fill(BACKGROUND_COLOR); - // } - // else if (FlxG.renderTile) - // { - // FlxG.log.warn("PlayState background not displayed properly on tile renderer!"); - // } - // else - // { - // FlxG.log.warn("PlayState background not displayed properly, unknown renderer!"); - // } - - super.draw(); - } - function assertChartExists():Bool { // Returns null if the song failed to load or doesn't have the selected difficulty. diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 8403a1a775..52cf18b7ff 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -1,25 +1,23 @@ package funkin.save; import flixel.util.FlxSave; -import funkin.util.FileUtil; import funkin.input.Controls.Device; import funkin.play.scoring.Scoring; import funkin.play.scoring.Scoring.ScoringRank; import funkin.save.migrator.RawSaveData_v1_0_0; import funkin.save.migrator.SaveDataMigrator; -import funkin.save.migrator.SaveDataMigrator; import funkin.ui.debug.charting.ChartEditorState.ChartEditorLiveInputStyle; import funkin.ui.debug.charting.ChartEditorState.ChartEditorTheme; import funkin.ui.debug.stageeditor.StageEditorState.StageEditorTheme; +import funkin.util.FileUtil; import funkin.util.SerializerUtil; import thx.semver.Version; -import thx.semver.Version; @:nullSafety class Save { - public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.4"; - public static final SAVE_DATA_VERSION_RULE:thx.semver.VersionRule = "2.0.x"; + public static final SAVE_DATA_VERSION:thx.semver.Version = "2.1.0"; + public static final SAVE_DATA_VERSION_RULE:thx.semver.VersionRule = ">=2.1.0 <2.2.0"; // We load this version's saves from a new save path, to maintain SOME level of backwards compatibility. static final SAVE_PATH:String = 'FunkinCrew'; @@ -961,39 +959,61 @@ class Save */ static function loadFromSlot(slot:Int):Save { - trace("[SAVE] Loading save from slot " + slot + "..."); - - // Prevent crashes if the save data is corrupted. - SerializerUtil.initSerializer(); + trace('[SAVE] Loading save from slot $slot...'); FlxG.save.bind('$SAVE_NAME${slot}', SAVE_PATH); - if (FlxG.save.isEmpty()) + switch (FlxG.save.status) { - trace('[SAVE] Save data is empty, checking for legacy save data...'); - var legacySaveData = fetchLegacySaveData(); - if (legacySaveData != null) - { - trace('[SAVE] Found legacy save data, converting...'); - var gameSave = SaveDataMigrator.migrateFromLegacy(legacySaveData); - FlxG.save.mergeData(gameSave.data, true); - return gameSave; - } - else - { - trace('[SAVE] No legacy save data found.'); - var gameSave = new Save(); + case EMPTY: + trace('[SAVE] Save data in slot ${slot} is empty, checking for legacy save data...'); + var legacySaveData = fetchLegacySaveData(); + if (legacySaveData != null) + { + trace('[SAVE] Found legacy save data, converting...'); + var gameSave = SaveDataMigrator.migrateFromLegacy(legacySaveData); + FlxG.save.mergeData(gameSave.data, true); + return gameSave; + } + else + { + trace('[SAVE] No legacy save data found.'); + var gameSave = new Save(); + FlxG.save.mergeData(gameSave.data, true); + return gameSave; + } + case ERROR(_): + return handleSaveDataError(slot); + case BOUND(_, _): + trace('[SAVE] Loaded existing save data in slot ${slot}.'); + var gameSave = SaveDataMigrator.migrate(FlxG.save.data); FlxG.save.mergeData(gameSave.data, true); + return gameSave; - } + } + } + + /** + * Call this when there is an error loading the save data in slot X. + */ + static function handleSaveDataError(slot:Int):Save + { + var msg = 'There was an error loading your save data in slot ${slot}.'; + msg += '\nPlease report this issue to the developers.'; + lime.app.Application.current.window.alert(msg, "Save Data Failure"); + + // Don't touch that slot anymore. + // Instead, load the next available slot. + + var nextSlot = slot + 1; + + if (nextSlot < 1000) + { + return loadFromSlot(nextSlot); } else { - trace('[SAVE] Found existing save data.'); - var gameSave = SaveDataMigrator.migrate(FlxG.save.data); - FlxG.save.mergeData(gameSave.data, true); - - return gameSave; + throw "End of save data slots. Can't load any more."; } } @@ -1058,7 +1078,15 @@ class Save { var targetSaveData = new FlxSave(); targetSaveData.bind('$SAVE_NAME${slot}', SAVE_PATH); - return !targetSaveData.isEmpty(); + switch (targetSaveData.status) + { + case EMPTY: + return false; + case ERROR(_): + return false; + case BOUND(_, _): + return true; + } } /** diff --git a/source/funkin/save/changelog.md b/source/funkin/save/changelog.md index 41d6e68aee..aa98d30961 100644 --- a/source/funkin/save/changelog.md +++ b/source/funkin/save/changelog.md @@ -5,11 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2.0.4] - 2024-09-12 -Note to self: Only update to 2.1.0 when migration is needed. +## [2.1.0] - 2024-10-18 +This version introduces changes to save data loading in order to improve compatibility with older versions. +### Changed +- `optionsStageEditor.theme` converted from an Enum to a String to fix save data compatibility issues. + - In the future, Enum values should not be used in order to prevent incompatibilities caused by introducing new types to the save data that older versions cannot parse. +- `optionsChartEditor.theme` converted from an Enum to a String to fix save data compatibility issues. +- `optionsChartEditor.chartEditorLiveInputStyle` converted from an Enum to a String to fix save data compatibility issues. + +## [2.0.6] - 2024-10-11 ### Added -- `unlocks.charactersSeen:Array` to `Save` -- `unlocks.oldChar:Bool` to `Save` +- `optionsStageEditor` to `Save` for storing user preferences for the stage editor. ## [2.0.5] - 2024-05-21 ### Fixed @@ -17,6 +23,8 @@ Note to self: Only update to 2.1.0 when migration is needed. ## [2.0.4] - 2024-05-21 ### Added +- `unlocks.charactersSeen:Array` to `Save` +- `unlocks.oldChar:Bool` to `Save` - `favoriteSongs:Array` to `Save` ## [2.0.3] - 2024-01-09 diff --git a/source/funkin/save/migrator/SaveDataMigrator.hx b/source/funkin/save/migrator/SaveDataMigrator.hx index 7a929322a0..3dc012fce4 100644 --- a/source/funkin/save/migrator/SaveDataMigrator.hx +++ b/source/funkin/save/migrator/SaveDataMigrator.hx @@ -32,6 +32,10 @@ class SaveDataMigrator var save:Save = new Save(saveDataWithDefaults); return save; } + else if (VersionUtil.validateVersion(version, "2.0.x")) + { + return migrate_v2_0_0(inputData); + } else { var message:String = 'Error migrating save data, expected ${Save.SAVE_DATA_VERSION}.'; @@ -43,6 +47,20 @@ class SaveDataMigrator } } + static function migrate_v2_0_0(inputData:Dynamic):Save + { + // Import the structured data. + var saveDataWithDefaults:RawSaveData = cast thx.Objects.deepCombine(Save.getDefault(), inputData); + + // Reset these values to valid ones. + saveDataWithDefaults.optionsChartEditor.chartEditorLiveInputStyle = funkin.ui.debug.charting.ChartEditorState.ChartEditorLiveInputStyle.None; + saveDataWithDefaults.optionsChartEditor.theme = funkin.ui.debug.charting.ChartEditorState.ChartEditorTheme.Light; + saveDataWithDefaults.optionsStageEditor.theme = funkin.ui.debug.stageeditor.StageEditorState.StageEditorTheme.Light; + + var save:Save = new Save(saveDataWithDefaults); + return save; + } + /** * Migrate from 1.x to the latest version. */ diff --git a/source/funkin/save/migrator/SaveData_v2_0_0.hx b/source/funkin/save/migrator/SaveData_v2_0_0.hx new file mode 100644 index 0000000000..5369d87371 --- /dev/null +++ b/source/funkin/save/migrator/SaveData_v2_0_0.hx @@ -0,0 +1,26 @@ +package funkin.save.migrator; + +// Internal enums used to ensure old save data can be parsed by the default Haxe unserializer. +// In the future, only primitive types and abstract enums should be used in save data! + +@:native("funkin.ui.debug.stageeditor.StageEditorTheme") +enum StageEditorTheme +{ + Light; + Dark; +} + +@:native("funkin.ui.debug.charting.ChartEditorTheme") +enum ChartEditorTheme +{ + Light; + Dark; +} + +@:native("funkin.ui.debug.charting.ChartEditorLiveInputStyle") +enum ChartEditorLiveInputStyle +{ + None; + NumberKeys; + WASDKeys; +} diff --git a/source/funkin/ui/debug/DebugMenuSubState.hx b/source/funkin/ui/debug/DebugMenuSubState.hx index 6fc6be9378..709a80f2b8 100644 --- a/source/funkin/ui/debug/DebugMenuSubState.hx +++ b/source/funkin/ui/debug/DebugMenuSubState.hx @@ -55,17 +55,20 @@ class DebugMenuSubState extends MusicBeatSubState // Create each menu item. // Call onMenuChange when the first item is created to move the camera . #if FEATURE_CHART_EDITOR - onMenuChange(createItem("CHART EDITOR", openChartEditor)); + createItem("CHART EDITOR", openChartEditor); #end - // createItem("Input Offset Testing", openInputOffsetTesting); - createItem("CHARACTER SELECT", openCharSelect, true); createItem("ANIMATION EDITOR", openAnimationEditor); + #if FEATURE_STAGE_EDITOR createItem("STAGE EDITOR", openStageEditor); + #end createItem("CHARACTER CREATOR", openCharCreator); + // createItem("Input Offset Testing", openInputOffsetTesting); + // createItem("CHARACTER SELECT", openCharSelect, true); // createItem("TEST STICKERS", testStickers); #if sys createItem("OPEN CRASH LOG FOLDER", openLogFolder); #end + onMenuChange(items.members[0]); FlxG.camera.focusOn(new FlxPoint(camFocusPoint.x, camFocusPoint.y + 500)); } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 0810bae303..723d0c9763 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -94,6 +94,7 @@ import funkin.ui.mainmenu.MainMenuState; import funkin.ui.transition.LoadingState; import funkin.util.Constants; import funkin.util.FileUtil; +import funkin.util.MathUtil; import funkin.util.logging.CrashHandler; import funkin.util.SortUtil; import funkin.util.WindowUtil; @@ -244,7 +245,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState /** * Duration, in seconds, for the scroll easing animation. */ - public static final SCROLL_EASE_DURATION:Float = 0.2; + public static final SCROLL_EASE_DURATION:Float = 0.4; // Other @@ -773,9 +774,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState /** * The current process that is lerping the scroll position. - * Used to cancel the previous lerp if the user scrolls again. */ - var currentScrollEase:Null; + var currentScrollEase:Null; /** * The position where the user middle clicked to place a scroll anchor. @@ -2707,6 +2707,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState playbarHeadLayout.playbarHead.width = FlxG.width; playbarHeadLayout.playbarHead.height = 10; playbarHeadLayout.playbarHead.styleString = 'padding-left: 0px; padding-right: 0px; border-left: 0px; border-right: 0px;'; + playbarHeadLayout.playbarHead.min = 0; playbarHeadLayout.playbarHead.onDragStart = function(_:DragEvent) { playbarHeadDragging = true; @@ -2723,13 +2724,12 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState } } - playbarHeadLayout.playbarHead.onDrag = function(_:DragEvent) { + playbarHeadLayout.playbarHead.onDrag = function(d:DragEvent) { if (playbarHeadDragging) { - // Set the song position to where the playhead was moved to. - scrollPositionInPixels = (songLengthInPixels) * playbarHeadLayout.playbarHead.value / 100; // Update the conductor and audio tracks to match. - moveSongToScrollPosition(); + currentScrollEase = d.value; + easeSongToScrollPosition(currentScrollEase); } } @@ -2740,8 +2740,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState if (playbarHeadDraggingWasPlaying) { playbarHeadDraggingWasPlaying = false; + // Disabled code to resume song playback on drag. - // startAudioPlayback(); + startAudioPlayback(); } } @@ -3417,10 +3418,14 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState audioInstTrack.time = -Conductor.instance.instrumentalOffset; } } + + if (!audioInstTrack.isPlaying && currentScrollEase != scrollPositionInPixels) easeSongToScrollPosition(currentScrollEase); } if (audioInstTrack != null && audioInstTrack.isPlaying) { + currentScrollEase = scrollPositionInPixels; + if (FlxG.keys.pressed.ALT) { // If middle mouse panning during song playback, we move ONLY the playhead, without scrolling. Neat! @@ -3869,7 +3874,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState } // Mouse Wheel = Scroll - if (FlxG.mouse.wheel != 0 && !FlxG.keys.pressed.CONTROL) + if (FlxG.mouse.wheel != 0) { scrollAmount = -50 * FlxG.mouse.wheel; shouldPause = true; @@ -4057,27 +4062,13 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState shouldPause = true; } - if (Math.abs(scrollAmount) > GRID_SIZE * 8) - { - shouldEase = true; - } + shouldEase = true; + if (shouldPause) stopAudioPlayback(); // Resync the conductor and audio tracks. - if (scrollAmount != 0 || playheadAmount != 0) - { - this.playheadPositionInPixels += playheadAmount; - if (shouldEase) - { - easeSongToScrollPosition(this.scrollPositionInPixels + scrollAmount); - } - else - { - // Apply the scroll amount. - this.scrollPositionInPixels += scrollAmount; - moveSongToScrollPosition(); - } - } - if (shouldPause) stopAudioPlayback(); + if (playheadAmount != 0) this.playheadPositionInPixels += playheadAmount; + + if (scrollAmount != 0) currentScrollEase += scrollAmount; } /** @@ -4333,15 +4324,13 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState { // Scroll up. var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.viewY; - scrollPositionInPixels -= diff * 0.5; // Too fast! - moveSongToScrollPosition(); + currentScrollEase -= diff * 0.5; // Too fast! } else if (FlxG.mouse.viewY > (playbarHeadLayout?.y ?? 0.0)) { // Scroll down. var diff:Float = FlxG.mouse.viewY - (playbarHeadLayout?.y ?? 0.0); - scrollPositionInPixels += diff * 0.5; // Too fast! - moveSongToScrollPosition(); + currentScrollEase += (diff * 0.5); // Too fast! } // Render the selection box. @@ -4480,8 +4469,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState var clickedPosInPixels:Float = FlxMath.remapToRange(FlxG.mouse.viewY, (notePreview?.y ?? 0.0), (notePreview?.y ?? 0.0) + (notePreview?.height ?? 0.0), 0, songLengthInPixels); - scrollPositionInPixels = clickedPosInPixels; - moveSongToScrollPosition(); + currentScrollEase = clickedPosInPixels; + easeSongToScrollPosition(currentScrollEase); } else if (scrollAnchorScreenPos != null) { @@ -4540,15 +4529,13 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState { // Scroll up. var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.viewY; - scrollPositionInPixels -= diff * 0.5; // Too fast! - moveSongToScrollPosition(); + currentScrollEase -= (diff * 0.5); } else if (FlxG.mouse.viewY > (playbarHeadLayout?.y ?? 0.0)) { // Scroll down. var diff:Float = FlxG.mouse.viewY - (playbarHeadLayout?.y ?? 0.0); - scrollPositionInPixels += diff * 0.5; // Too fast! - moveSongToScrollPosition(); + currentScrollEase += (diff * 0.5); } // Calculate distance between the position dragged to and the original position. @@ -5142,18 +5129,15 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState { if (playbarHeadLayout == null) throw "ERROR: Tried to handle playbar, but playbarHeadLayout is null!"; + // Move the playhead to match the song position, if we aren't dragging it. + playbarHeadLayout.playbarHead.pos = currentScrollEase; + + playbarHeadLayout.playbarHead.max = songLengthInPixels; + // Make sure the playbar is never nudged out of the correct spot. playbarHeadLayout.x = 4; playbarHeadLayout.y = FlxG.height - 48 - 8; - // Move the playhead to match the song position, if we aren't dragging it. - if (!playbarHeadDragging) - { - var songPosPercent = scrollPositionInPixels / (songLengthInPixels) * 100; - - if (playbarHeadLayout.playbarHead.value != songPosPercent) playbarHeadLayout.playbarHead.value = songPosPercent; - } - var songPos:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset; var songPosMilliseconds:String = Std.string(Math.floor(Math.abs(songPos) % 1000)).lpad('0', 2).substr(0, 2); var songPosSeconds:String = Std.string(Math.floor((Math.abs(songPos) / 1000) % 60)).lpad('0', 2); @@ -6134,43 +6118,12 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState */ function easeSongToScrollPosition(targetScrollPosition:Float):Void { - if (currentScrollEase != null) cancelScrollEase(currentScrollEase); - - currentScrollEase = FlxTween.tween(this, {scrollPositionInPixels: targetScrollPosition}, SCROLL_EASE_DURATION, - { - ease: FlxEase.quintInOut, - onUpdate: this.onScrollEaseUpdate, - onComplete: this.cancelScrollEase, - type: ONESHOT - }); - } - - /** - * Callback function executed every frame that the scroll position is being eased. - * @param _ - */ - function onScrollEaseUpdate(_:FlxTween):Void - { + currentScrollEase = Math.max(0, targetScrollPosition); + currentScrollEase = Math.min(currentScrollEase, songLengthInPixels); + scrollPositionInPixels = MathUtil.smoothLerp(scrollPositionInPixels, currentScrollEase, FlxG.elapsed, SCROLL_EASE_DURATION, 1 / 1000); moveSongToScrollPosition(); } - /** - * Callback function executed when cancelling an existing scroll position ease. - * Ensures that the ease is immediately cancelled and the scroll position is set to the target value. - */ - function cancelScrollEase(_:FlxTween):Void - { - if (currentScrollEase != null) - { - @:privateAccess - var targetScrollPosition:Float = currentScrollEase._properties.scrollPositionInPixels; - - currentScrollEase.cancel(); - currentScrollEase = null; - this.scrollPositionInPixels = targetScrollPosition; - } - } - /** * Fix the current scroll position after exiting the PlayState used when testing. */ @@ -6351,6 +6304,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState { if (audioInstTrack == null) return; + currentScrollEase = this.scrollPositionInPixels; + if (audioInstTrack.isPlaying) { // Pause @@ -6544,22 +6499,22 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState /** * Available input modes for the chart editor state. Numbers/arrows/WASD available for other keybinds. */ -enum ChartEditorLiveInputStyle +enum abstract ChartEditorLiveInputStyle(String) { /** * No hotkeys to place notes at the playbar. */ - None; + var None; /** * 1/2/3/4 to place notes on opponent's side, 5/6/7/8 to place notes on player's side. */ - NumberKeys; + var NumberKeys; /** * WASD to place notes on opponent's side, Arrow keys to place notes on player's side. */ - WASDKeys; + var WASDKeys; } typedef ChartEditorParams = @@ -6578,15 +6533,15 @@ typedef ChartEditorParams = /** * Available themes for the chart editor state. */ -enum ChartEditorTheme +enum abstract ChartEditorTheme(String) { /** * The default theme for the chart editor. */ - Light; + var Light; /** * A theme which introduces darker colors. */ - Dark; + var Dark; } diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorThemeHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorThemeHandler.hx index e42102a529..ac8985dc15 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorThemeHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorThemeHandler.hx @@ -253,42 +253,23 @@ class ChartEditorThemeHandler var bottomTickY:Float = state.measureTickBitmap.height - (measureTickWidth / 2); state.measureTickBitmap.fillRect(new Rectangle(0, bottomTickY, state.measureTickBitmap.width, measureTickWidth / 2), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - // Draw the beat ticks. - var beatTick2Y:Float = state.measureTickBitmap.height * 1 / Conductor.instance.beatsPerMeasure - (beatTickWidth / 2); - var beatTick3Y:Float = state.measureTickBitmap.height * 2 / Conductor.instance.beatsPerMeasure - (beatTickWidth / 2); - var beatTick4Y:Float = state.measureTickBitmap.height * 3 / Conductor.instance.beatsPerMeasure - (beatTickWidth / 2); - var beatTickLength:Float = state.measureTickBitmap.width * 2 / 3; - state.measureTickBitmap.fillRect(new Rectangle(0, beatTick2Y, beatTickLength, beatTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.measureTickBitmap.fillRect(new Rectangle(0, beatTick3Y, beatTickLength, beatTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.measureTickBitmap.fillRect(new Rectangle(0, beatTick4Y, beatTickLength, beatTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - - // Draw the step ticks. - // TODO: Make this a loop or something. - var stepTick2Y:Float = state.measureTickBitmap.height * 1 / Conductor.instance.stepsPerMeasure - (stepTickWidth / 2); - var stepTick3Y:Float = state.measureTickBitmap.height * 2 / Conductor.instance.stepsPerMeasure - (stepTickWidth / 2); - var stepTick4Y:Float = state.measureTickBitmap.height * 3 / Conductor.instance.stepsPerMeasure - (stepTickWidth / 2); - var stepTick6Y:Float = state.measureTickBitmap.height * 5 / Conductor.instance.stepsPerMeasure - (stepTickWidth / 2); - var stepTick7Y:Float = state.measureTickBitmap.height * 6 / Conductor.instance.stepsPerMeasure - (stepTickWidth / 2); - var stepTick8Y:Float = state.measureTickBitmap.height * 7 / Conductor.instance.stepsPerMeasure - (stepTickWidth / 2); - var stepTick10Y:Float = state.measureTickBitmap.height * 9 / Conductor.instance.stepsPerMeasure - (stepTickWidth / 2); - var stepTick11Y:Float = state.measureTickBitmap.height * 10 / Conductor.instance.stepsPerMeasure - (stepTickWidth / 2); - var stepTick12Y:Float = state.measureTickBitmap.height * 11 / Conductor.instance.stepsPerMeasure - (stepTickWidth / 2); - var stepTick14Y:Float = state.measureTickBitmap.height * 13 / Conductor.instance.stepsPerMeasure - (stepTickWidth / 2); - var stepTick15Y:Float = state.measureTickBitmap.height * 14 / Conductor.instance.stepsPerMeasure - (stepTickWidth / 2); - var stepTick16Y:Float = state.measureTickBitmap.height * 15 / Conductor.instance.stepsPerMeasure - (stepTickWidth / 2); - var stepTickLength:Float = state.measureTickBitmap.width * 1 / 3; - state.measureTickBitmap.fillRect(new Rectangle(0, stepTick2Y, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.measureTickBitmap.fillRect(new Rectangle(0, stepTick3Y, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.measureTickBitmap.fillRect(new Rectangle(0, stepTick4Y, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.measureTickBitmap.fillRect(new Rectangle(0, stepTick6Y, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.measureTickBitmap.fillRect(new Rectangle(0, stepTick7Y, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.measureTickBitmap.fillRect(new Rectangle(0, stepTick8Y, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.measureTickBitmap.fillRect(new Rectangle(0, stepTick10Y, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.measureTickBitmap.fillRect(new Rectangle(0, stepTick11Y, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.measureTickBitmap.fillRect(new Rectangle(0, stepTick12Y, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.measureTickBitmap.fillRect(new Rectangle(0, stepTick14Y, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.measureTickBitmap.fillRect(new Rectangle(0, stepTick15Y, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.measureTickBitmap.fillRect(new Rectangle(0, stepTick16Y, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); + // Draw the beat and step ticks. No need for two seperate loops thankfully. + // This'll be fun to update when beat tuplets become functional. + for (i in 1...(Conductor.instance.stepsPerMeasure)) + { + if ((i % Constants.STEPS_PER_BEAT) == 0) // If we're on a beat, draw a beat tick. + { + var beatTickY:Float = state.measureTickBitmap.height * i / Conductor.instance.stepsPerMeasure - (beatTickWidth / 2); + var beatTickLength:Float = state.measureTickBitmap.width * 2 / 3; + state.measureTickBitmap.fillRect(new Rectangle(0, beatTickY, beatTickLength, beatTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); + } + else // Else, draw a step tick. + { + var stepTickY:Float = state.measureTickBitmap.height * i / Conductor.instance.stepsPerMeasure - (stepTickWidth / 2); + var stepTickLength:Float = state.measureTickBitmap.width * 1 / 3; + state.measureTickBitmap.fillRect(new Rectangle(0, stepTickY, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT); + } + } } /** @@ -314,23 +295,16 @@ class ChartEditorThemeHandler state.offsetTickBitmap.fillRect(new Rectangle(rightTickX, 0, majorTickWidth / 2, majorTickLength), GRID_MEASURE_DIVIDER_COLOR_LIGHT); // Draw the minor ticks. - var minorTick2X:Float = state.offsetTickBitmap.width * 1 / 10 - (minorTickWidth / 2); - var minorTick3X:Float = state.offsetTickBitmap.width * 2 / 10 - (minorTickWidth / 2); - var minorTick4X:Float = state.offsetTickBitmap.width * 3 / 10 - (minorTickWidth / 2); - var minorTick5X:Float = state.offsetTickBitmap.width * 4 / 10 - (minorTickWidth / 2); - var minorTick7X:Float = state.offsetTickBitmap.width * 6 / 10 - (minorTickWidth / 2); - var minorTick8X:Float = state.offsetTickBitmap.width * 7 / 10 - (minorTickWidth / 2); - var minorTick9X:Float = state.offsetTickBitmap.width * 8 / 10 - (minorTickWidth / 2); - var minorTick10X:Float = state.offsetTickBitmap.width * 9 / 10 - (minorTickWidth / 2); - var minorTickLength:Float = state.offsetTickBitmap.height * 1 / 3; - state.offsetTickBitmap.fillRect(new Rectangle(minorTick2X, 0, minorTickWidth, minorTickLength), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.offsetTickBitmap.fillRect(new Rectangle(minorTick3X, 0, minorTickWidth, minorTickLength), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.offsetTickBitmap.fillRect(new Rectangle(minorTick4X, 0, minorTickWidth, minorTickLength), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.offsetTickBitmap.fillRect(new Rectangle(minorTick5X, 0, minorTickWidth, minorTickLength), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.offsetTickBitmap.fillRect(new Rectangle(minorTick7X, 0, minorTickWidth, minorTickLength), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.offsetTickBitmap.fillRect(new Rectangle(minorTick8X, 0, minorTickWidth, minorTickLength), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.offsetTickBitmap.fillRect(new Rectangle(minorTick9X, 0, minorTickWidth, minorTickLength), GRID_MEASURE_DIVIDER_COLOR_LIGHT); - state.offsetTickBitmap.fillRect(new Rectangle(minorTick10X, 0, minorTickWidth, minorTickLength), GRID_MEASURE_DIVIDER_COLOR_LIGHT); + for (i in 1...11) + { + if (i % 5 == 0) + { + continue; + } + var minorTickX:Float = state.offsetTickBitmap.width * i / 10 - (minorTickWidth / 2); + var minorTickLength:Float = state.offsetTickBitmap.height * 1 / 3; + state.offsetTickBitmap.fillRect(new Rectangle(minorTickX, 0, minorTickWidth, minorTickLength), GRID_MEASURE_DIVIDER_COLOR_LIGHT); + } // Draw the offset ticks. // var ticksWidth:Int = Std.int(ChartEditorState.GRID_SIZE * TOTAL_COLUMN_COUNT); // 1 grid squares wide. diff --git a/source/funkin/ui/debug/stageeditor/StageEditorState.hx b/source/funkin/ui/debug/stageeditor/StageEditorState.hx index a928e78959..fbc8d01c7d 100644 --- a/source/funkin/ui/debug/stageeditor/StageEditorState.hx +++ b/source/funkin/ui/debug/stageeditor/StageEditorState.hx @@ -1458,17 +1458,17 @@ class StageEditorState extends UIState /** * Available themes for the stage editor state. */ -enum StageEditorTheme +enum abstract StageEditorTheme(String) { /** * The default theme for the stage editor. */ - Light; + var Light; /** * A theme which introduces stage colors. */ - Dark; + var Dark; } enum StageEditorDialogType diff --git a/source/funkin/ui/transition/preload/FunkinPreloader.hx b/source/funkin/ui/transition/preload/FunkinPreloader.hx index 41ad3f479f..cda1eef7fd 100644 --- a/source/funkin/ui/transition/preload/FunkinPreloader.hx +++ b/source/funkin/ui/transition/preload/FunkinPreloader.hx @@ -136,8 +136,6 @@ class FunkinPreloader extends FlxBasePreloader // We can't even call trace() yet, until Flixel loads. trace('Initializing custom preloader...'); - funkin.util.CLIUtil.resetWorkingDir(); - this.siteLockTitleText = Constants.SITE_LOCK_TITLE; this.siteLockBodyText = Constants.SITE_LOCK_DESC; } diff --git a/source/funkin/util/SerializerUtil.hx b/source/funkin/util/SerializerUtil.hx index fa602cc733..c87d3f6c00 100644 --- a/source/funkin/util/SerializerUtil.hx +++ b/source/funkin/util/SerializerUtil.hx @@ -63,31 +63,6 @@ class SerializerUtil } } - public static function initSerializer():Void - { - haxe.Unserializer.DEFAULT_RESOLVER = new FunkinTypeResolver(); - } - - /** - * Serialize a Haxe object using the built-in Serializer. - * @param input The object to serialize - * @return The serialized object as a string - */ - public static function fromHaxeObject(input:Dynamic):String - { - return haxe.Serializer.run(input); - } - - /** - * Convert a serialized Haxe object back into a Haxe object. - * @param input The serialized object as a string - * @return The deserialized object - */ - public static function toHaxeObject(input:String):Dynamic - { - return haxe.Unserializer.run(input); - } - /** * Customize how certain types are serialized when converting to JSON. */ @@ -115,26 +90,3 @@ class SerializerUtil return result; } } - -class FunkinTypeResolver -{ - public function new() - { - // Blank constructor. - } - - public function resolveClass(name:String):Class - { - if (name == 'Dynamic') - { - FlxG.log.warn('Found invalid class type in save data, indicates partial save corruption.'); - return null; - } - return Type.resolveClass(name); - }; - - public function resolveEnum(name:String):Enum - { - return Type.resolveEnum(name); - }; -}