diff --git a/.vscode/settings.json b/.vscode/settings.json index 7a9d9139e..b57ab7aa3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -72,7 +72,6 @@ "haxecheckstyle.externalSourceRoots": [], "haxecheckstyle.configurationFile": "checkstyle.json", "haxecheckstyle.codeSimilarityBufferSize": 100, - "lime.projectFile": "project.hxp", "lime.targets": [ { "name": "windows", "enabled": true, "label": "Windows" }, { "name": "mac", "enabled": true, "label": "macOS" }, @@ -80,8 +79,8 @@ { "name": "html5", "enabled": true, "label": "HTML5" }, { "name": "android", "enabled": true, "label": "Android" }, { "name": "ios", "enabled": true, "label": "iOS" }, + { "name": "hl", "enabled": true, "label": "HashLink" }, // Disabled targets - { "name": "hl", "enabled": false, "label": "HashLink" }, { "name": "air", "enabled": false }, { "name": "electron", "enabled": false }, { "name": "flash", "enabled": false }, diff --git a/assets b/assets index bdea9cf4d..4f8a4e1bd 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit bdea9cf4d994cec6fb4cd3a0ca504cbee1fd2bd6 +Subproject commit 4f8a4e1bd9112d136757f652f8b041f93ec0d46d diff --git a/hmm.json b/hmm.json index ca9900b85..c9959436d 100644 --- a/hmm.json +++ b/hmm.json @@ -4,7 +4,7 @@ "name": "FlxPartialSound", "type": "git", "dir": null, - "ref": "26ed20b9c181a576f4cbe18ccdea38912c01476e", + "ref": "2f984e244f1544ca98c0e03b9b21ae570f07ac55", "url": "https://github.com/FunkinCrew/FlxPartialSound.git" }, { @@ -169,7 +169,7 @@ "name": "lime", "type": "git", "dir": null, - "ref": "cae0c0bc10915f6281625d07e5527f3cecb4347f", + "ref": "a3c915161ae66c24e76d968b1b6f4c08d61e314f", "url": "https://github.com/FunkinCrew/lime" }, { @@ -183,14 +183,14 @@ "name": "openfl", "type": "git", "dir": null, - "ref": "5399946b68fd98f345d6b3e52b95ed6b78bf427c", + "ref": "92d7607f309c6c0705456a2e943f1aa0f052463d", "url": "https://github.com/FunkinCrew/openfl" }, { "name": "polymod", "type": "git", "dir": null, - "ref": "6ed7a8940bacec2b474020fc0c155838ad280b8d", + "ref": "47f8f74a8498647cfbda2feb7fb8c943845b4c62", "url": "https://github.com/FunkinCrew/polymod" }, { diff --git a/project.hxp b/project.hxp index 747137d18..b2f60f60e 100644 --- a/project.hxp +++ b/project.hxp @@ -114,11 +114,7 @@ class Project extends HXProject */ static final ANDROID_TARGET_SDK_VERSION:Int = 35; - static final ANDROID_EXTENSIONS:Array = [ - "funkin.extensions.CallbackUtil", - "funkin.extensions.FNFCExtension", - "funkin.extensions.AudioSession" - ]; + static final ANDROID_EXTENSIONS:Array = ["funkin.extensions.CallbackUtil", "funkin.extensions.FNFCExtension", "funkin.extensions.AudioSession"]; /** * The team ID to use for the iOS app. Configured in XCode. @@ -171,11 +167,7 @@ class Project extends HXProject /** * Asset path globs to exclude on platforms with `CENSOR_EXPLETIVES` disabled. */ - static final EXCLUDE_ASSETS_UNCENSORED:Array = [ - "stressCutscene-censored.mp4", - "stressPicoCutscene-censored.mp4", - "darnellCutscene-censored.mp4" - ]; + static final EXCLUDE_ASSETS_UNCENSORED:Array = ["stressCutscene-censored.mp4", "stressPicoCutscene-censored.mp4", "darnellCutscene-censored.mp4"]; // // ASSET EMBEDDING @@ -894,7 +886,7 @@ class Project extends HXProject // Should be true on desktop, non-tester builds. // We don't want testers to accidentally leak songs to their Discord friends! - FEATURE_DISCORD_RPC.apply(this, isDesktop() && !FEATURE_DEBUG_FUNCTIONS.isEnabled(this)); + FEATURE_DISCORD_RPC.apply(this, isDesktop() && !FEATURE_DEBUG_FUNCTIONS.isEnabled(this) && !isHashLink()); FEATURE_LOST_FOCUS_VOLUME.apply(this, isDesktop()); @@ -1228,21 +1220,12 @@ class Project extends HXProject intentFilter.addChild(category); } - final intentFilterDatas:Map> = [ - "android:mimeType" => ["application/zip"], - // When this is added, it makes the game show up only when it's a FNFC file. + final intentFilterDatas:Map> = ["android:mimeType" => ["application/zip"], // When this is added, it makes the game show up only when it's a FNFC file. // But it also for some reason make it not show up at all in ZArchiver no matter what the file is... // "android:host" => ["*"], - "android:scheme" => ["file", "content"], - // I think having all these makes it so the extension check would work even when the files has dots like "epic-song-v2.0.fnfc" - "android:pathPattern" => [ - ".*\\.fnfc", - ".*\\..*\\.fnfc", - ".*\\..*\\..*\\.fnfc", - ".*\\..*\\..*\\..*\\.fnfc", - ".*\\..*\\..*\\..*\\..*\\.fnfc" - ] - ]; + "android:scheme" => ["file", "content"], // I think having all these makes it so the extension check would work even when the files has dots like "epic-song-v2.0.fnfc" + "android:pathPattern" => [".*\\.fnfc", ".*\\..*\\.fnfc", ".*\\..*\\..*\\.fnfc", ".*\\..*\\..*\\..*\\.fnfc", ".*\\..*\\..*\\..*\\..*\\.fnfc"]]; for (key => values in intentFilterDatas) { @@ -1351,12 +1334,12 @@ class Project extends HXProject addHaxelib('thx.core'); // General utility library, "the lodash of Haxe" addHaxelib('thx.semver'); // Version string handling - if (isDebug()) + if (isDebug() && isCPP()) { addHaxelib('hxcpp-debug-server'); // VSCode debug support } - if (isDesktop() || isMobile() && !isHashLink() && FEATURE_VIDEO_PLAYBACK.isEnabled(this)) + if ((isDesktop() || isMobile()) && FEATURE_VIDEO_PLAYBACK.isEnabled(this)) { // hxvlc doesn't function on HashLink or non-desktop platforms // It's also unnecessary if video playback is disabled diff --git a/source/funkin/Preferences.hx b/source/funkin/Preferences.hx index ffe61c04a..17d5aceab 100644 --- a/source/funkin/Preferences.hx +++ b/source/funkin/Preferences.hx @@ -148,6 +148,17 @@ class Preferences return DebugDisplayMode.Off; #end + #if hl + // Account for when debugDisplay used to be a boolean + var options:Null = Save.instance?.options; + if (options != null && Std.isOfType(options.debugDisplay, Bool)) + { + var convertedDebugDisplay = cast(options.debugDisplay, Bool) ? DebugDisplayMode.Simple : DebugDisplayMode.Off; + options.debugDisplay = convertedDebugDisplay; + Save.system.flush(); + } + #end + return Save?.instance?.options?.debugDisplay ?? 'Off'; } diff --git a/source/funkin/audio/waveform/WaveformDataParser.hx b/source/funkin/audio/waveform/WaveformDataParser.hx index d1da84d51..5a1343bd5 100644 --- a/source/funkin/audio/waveform/WaveformDataParser.hx +++ b/source/funkin/audio/waveform/WaveformDataParser.hx @@ -3,10 +3,14 @@ package funkin.audio.waveform; @:nullSafety class WaveformDataParser { + @:native("int16_max") static final INT16_MAX:Int = 32767; + @:native("int16_min") static final INT16_MIN:Int = -32768; + @:native("int8_max") static final INT8_MAX:Int = 127; + @:native("int8_min") static final INT8_MIN:Int = -128; public static function interpretFlxSound(sound:Null):Null diff --git a/source/funkin/data/DataError.hx b/source/funkin/data/DataError.hx index 2b8fd19c8..5c41b7db8 100644 --- a/source/funkin/data/DataError.hx +++ b/source/funkin/data/DataError.hx @@ -53,7 +53,7 @@ class DataError case TEnum(c): trace(' ERROR '.error() + '(${Type.getEnumName(c)}) ${e.toString()}'); default: - trace(' ERROR '.error() + '(${Type.typeof(e)}) ${e.toString()}'); + trace(' ERROR '.error() + '(${Type.typeof(e)}) ${Std.string(e)}'); } } diff --git a/source/funkin/data/song/importer/OsuManiaImporter.hx b/source/funkin/data/song/importer/OsuManiaImporter.hx index ad9391e7b..35279d1a2 100644 --- a/source/funkin/data/song/importer/OsuManiaImporter.hx +++ b/source/funkin/data/song/importer/OsuManiaImporter.hx @@ -46,7 +46,7 @@ class OsuManiaImporter { var parts:Array = line.split(":"); var key:String = StringTools.trim(parts.shift()); - var value:String = StringTools.trim(parts.join(":")); + var value:Any = parseValue(StringTools.trim(parts.join(":"))); if (Reflect.field(result, currentSection) == null) Reflect.setField(result, currentSection, { }); Reflect.setField(Reflect.field(result, currentSection), key, value); @@ -200,4 +200,22 @@ class OsuManiaImporter return new ManiaHitObject(time, noteD, holdDuration); }); } + + static function parseValue(v:String):Any + { + var result:Null; + + if (v.contains('.')) + { + result = Std.parseFloat(v); + if (!Math.isNaN(result)) return result; + } + else + { + result = Std.parseInt(v); + if (result != null) return result; + } + + return v; + } } diff --git a/source/funkin/input/PreciseInputManager.hx b/source/funkin/input/PreciseInputManager.hx index 33a490a1b..060a4cb97 100644 --- a/source/funkin/input/PreciseInputManager.hx +++ b/source/funkin/input/PreciseInputManager.hx @@ -152,7 +152,7 @@ class PreciseInputManager extends FlxKeyManager // This is because of browser safeguards against timing attacks. // See https://web.dev/coop-coep to enable headers which allow for more precise timestamps. return haxe.Int64.fromFloat(js.Browser.window.performance.now()) * NS_PER_MS; - #elseif cpp + #elseif lime_cffi // NOTE: If the game hard crashes on this line, rebuild Lime! // `lime rebuild windows -clean` return lime._internal.backend.native.NativeCFFI.lime_sdl_get_ticks() * NS_PER_MS; diff --git a/source/funkin/play/cutscene/VideoCutscene.hx b/source/funkin/play/cutscene/VideoCutscene.hx index 1fedc2241..e22291f99 100644 --- a/source/funkin/play/cutscene/VideoCutscene.hx +++ b/source/funkin/play/cutscene/VideoCutscene.hx @@ -70,6 +70,7 @@ class VideoCutscene { if (PlayState.instance == null) return; + #if FEATURE_VIDEO_PLAYBACK if (!openfl.Assets.exists(filePath)) { // Display a popup. @@ -78,8 +79,7 @@ class VideoCutscene return; } - - var rawFilePath = Paths.stripLibrary(filePath); + #end // Trigger the cutscene. Don't play the song in the background. PlayState.instance.isInCutscene = true; @@ -100,13 +100,18 @@ class VideoCutscene } #end + #if NO_FEATURE_VIDEO_PLAYBACK + trace(" WARNING ".bold().bg_yellow() + " Video playback is not enabled. Calling video end callback instead."); + finishVideo(); + #else #if html5 - playVideoHTML5(rawFilePath); + playVideoHTML5(Paths.stripLibrary(filePath)); #elseif hxvlc playVideoNative(filePath); #else throw "No video support for this platform!"; #end + #end } public static function isPlaying():Bool diff --git a/source/funkin/ui/charSelect/IntroSubState.hx b/source/funkin/ui/charSelect/IntroSubState.hx index 17f10b98f..528126d40 100644 --- a/source/funkin/ui/charSelect/IntroSubState.hx +++ b/source/funkin/ui/charSelect/IntroSubState.hx @@ -48,6 +48,10 @@ class IntroSubState extends MusicBeatSubState playVideoNative(LIGHTS_VIDEO_PATH); #end + #if NO_FEATURE_VIDEO_PLAYBACK + onLightsEnd(); + #end + // // Im TOO lazy to even care, so uh, yep // FlxG.camera.zoom = 0.66666666666666666666666666666667; // vid.x = -(FlxG.width - (FlxG.width * FlxG.camera.zoom)); diff --git a/source/funkin/ui/debug/FunkinDebugDisplay.hx b/source/funkin/ui/debug/FunkinDebugDisplay.hx index c7b019c5f..42f8665de 100644 --- a/source/funkin/ui/debug/FunkinDebugDisplay.hx +++ b/source/funkin/ui/debug/FunkinDebugDisplay.hx @@ -11,7 +11,7 @@ import openfl.text.TextFormat; /** * A debug overlay showing useful info. */ -#if cpp +#if lime_cffi @:access(lime._internal.backend.native.NativeCFFI) #end class FunkinDebugDisplay extends Sprite @@ -149,7 +149,7 @@ class FunkinDebugDisplay extends Sprite override function __enterFrame(deltaTime:Int):Void { - #if cpp + #if lime_cffi final currentTime:Float = lime._internal.backend.native.NativeCFFI.lime_sdl_get_ticks(); #elseif html5 final currentTime:Float = js.Browser.window.performance.now(); diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 2cea068c3..2d7f8649c 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -3455,7 +3455,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState if (audioInstTrack != null) audioInstTrack.volume = volume; menubarLabelVolumeInstrumental.text = 'Instrumental - ${Std.int(event.value)}%'; }; - previousAudioVolumes[3] = menubarLabelVolumeInstrumental.value; + previousAudioVolumes[3] = menubarItemVolumeInstrumental.value; menubarItemVolumeVocalsPlayer.onChange = event -> { @@ -3463,7 +3463,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState audioVocalTrackGroup.playerVolume = volume; menubarLabelVolumeVocalsPlayer.text = 'Player - ${Std.int(event.value)}%'; }; - previousAudioVolumes[4] = menubarLabelVolumeVocalsPlayer.value; + previousAudioVolumes[4] = menubarItemVolumeVocalsPlayer.value; menubarItemVolumeVocalsOpponent.onChange = event -> { @@ -3471,7 +3471,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState audioVocalTrackGroup.opponentVolume = volume; menubarLabelVolumeVocalsOpponent.text = 'Enemy - ${Std.int(event.value)}%'; }; - previousAudioVolumes[5] = menubarLabelVolumeVocalsOpponent.value; + previousAudioVolumes[5] = menubarItemVolumeVocalsOpponent.value; menubarItemPlaybackSpeed.onChange = event -> { @@ -4071,7 +4071,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState eventSprite.parentState = this; // trace('Creating new Event... (${renderedEvents.members.length})'); - if (eventData?.value != null && (eventData?.value?.ease != null && eventData?.value?.easeDir == null)) + if (eventData?.value != null && (eventData.getString("ease") != null && eventData.getInt("easeDir") == null)) { eventData.value = migrateEventEaseDirectionFields(eventData.value); } diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorWelcomeDialog.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorWelcomeDialog.hx index 28d41eb83..b23262ce1 100644 --- a/source/funkin/ui/debug/charting/dialogs/ChartEditorWelcomeDialog.hx +++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorWelcomeDialog.hx @@ -88,8 +88,16 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog linkRecentChart.tooltip = chartPath; #if sys - var lastModified:String = "Last Modified: " + sys.FileSystem.stat(chartPath).mtime.toString(); - linkRecentChart.tooltip += "\n" + lastModified; + if (!FileUtil.fileExists(chartPath)) + { + trace('Previously loaded chart file (${chartPath}) does not exist, disabling link...'); + linkRecentChart.disabled = true; + } + else + { + var lastModified:String = "Last Modified: " + sys.FileSystem.stat(chartPath).mtime.toString(); + linkRecentChart.tooltip += "\n" + lastModified; + } #end linkRecentChart.onClick = function(_event) @@ -111,12 +119,6 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog } } - if (!FileUtil.fileExists(chartPath)) - { - trace('Previously loaded chart file (${chartPath}) does not exist, disabling link...'); - linkRecentChart.disabled = true; - } - splashRecentContainer.addComponent(linkRecentChart); } diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx index a697c83e9..d969e6d9f 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx @@ -374,7 +374,7 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox { if (field.type == FRAME) return; - var value = event.target.value; + var value:Any = event.target.value; if (field.type == ENUM) { var drp:DropDown = cast event.target; diff --git a/source/funkin/ui/debug/stageeditor/toolboxes/StageEditorCharacterToolbox.hx b/source/funkin/ui/debug/stageeditor/toolboxes/StageEditorCharacterToolbox.hx index 9a9a2a949..0fd56fb75 100644 --- a/source/funkin/ui/debug/stageeditor/toolboxes/StageEditorCharacterToolbox.hx +++ b/source/funkin/ui/debug/stageeditor/toolboxes/StageEditorCharacterToolbox.hx @@ -57,7 +57,7 @@ class StageEditorCharacterToolbox extends StageEditorDefaultToolbox charCamX.onChange = charCamY.onChange = function(_) { if (state.selectedChar == null) return; - state.charCamOffsets[state.selectedChar.characterType] = [charCamX.pos, charCamY.pos]; + state.charCamOffsets[state.selectedChar.characterType] = [charCamX.pos ?? 0, charCamY.pos ?? 0]; state.updateMarkerPos(); } diff --git a/source/funkin/ui/freeplay/SongItemGroup.hx b/source/funkin/ui/freeplay/SongItemGroup.hx index cf6a7a54f..d089fffa9 100644 --- a/source/funkin/ui/freeplay/SongItemGroup.hx +++ b/source/funkin/ui/freeplay/SongItemGroup.hx @@ -14,9 +14,14 @@ class SongItemGroup extends FlxTypedGroup var rankBlurredShader:GaussianBlurShader = new GaussianBlurShader(1); var favIconBlurredShader:GaussianBlurShader = new GaussianBlurShader(1.2); + #if hl + // What the hell is the compiler about on here? + override function recycle(?cls:Class, ?factory:Void->Dynamic, force:Bool = false, revive:Bool = true):SongMenuItem + #else override function recycle(?cls:Class, ?factory:Void->SongMenuItem, force:Bool = false, revive:Bool = true):SongMenuItem + #end { - var capsule:SongMenuItem = super.recycle(cls, factory, force, revive); + var capsule:SongMenuItem = super.recycle(#if hl cast #end cls, factory, force, revive); // Apply the same shader instance to some elements so that we can use one draw call to render multiple of them. capsule.fakeBlurredRanking.shader = rankBlurredShader; diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index de5983951..eb23b4bea 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -65,7 +65,9 @@ class TitleState extends MusicBeatState var titleText:FunkinSprite; var maskShader = new LeftMaskShader(); + #if FEATURE_VIDEO_PLAYBACK var attractTimer:FlxTimer; + #end function startIntro():Void { @@ -155,8 +157,10 @@ class TitleState extends MusicBeatState else initialized = true; + #if FEATURE_VIDEO_PLAYBACK trace('Opening Attract state in ${Constants.TITLE_ATTRACT_DELAY} seconds...'); attractTimer = new FlxTimer().start(Constants.TITLE_ATTRACT_DELAY, (_:FlxTimer) -> moveToAttract()); + #end } /** @@ -286,11 +290,13 @@ class TitleState extends MusicBeatState function moveToMainMenu():Void { + #if FEATURE_VIDEO_PLAYBACK if (attractTimer != null) { attractTimer.cancel(); attractTimer = null; } + #end funkin.FunkinMemory.purgeCache(); FlxG.switchState(() -> new MainMenuState()); @@ -339,8 +345,10 @@ class TitleState extends MusicBeatState FlxG.camera.flash(FlxColor.WHITE, 1); FunkinSound.playOnce(Paths.sound('confirmMenu'), 0.7); + #if FEATURE_VIDEO_PLAYBACK // Stop the attract timer so you can listen to the whole song! attractTimer.cancel(); + #end } function createCoolText(textArray:Array):Void diff --git a/source/funkin/util/MemoryUtil.hx b/source/funkin/util/MemoryUtil.hx index e1487946e..91fc14f84 100644 --- a/source/funkin/util/MemoryUtil.hx +++ b/source/funkin/util/MemoryUtil.hx @@ -38,6 +38,11 @@ class MemoryUtil #elseif js var result:String = 'JS-MNS:'; result += '\n- Memory Used: ${getGCMemory()} bytes'; + #elseif hl + var result:String = 'HL-MNNS:'; + result += '\n- Memory Used: ${hl.Gc.stats().currentMemory} bytes'; + result += '\n- Memory Allocated: ${hl.Gc.stats().totalAllocated} bytes'; + result += '\n- Memory Allocation Count: ${hl.Gc.stats().allocationCount}'; #else var result:String = 'Unknown GC'; #end @@ -110,6 +115,8 @@ class MemoryUtil { #if cpp cpp.vm.Gc.enable(true); + #elseif hl + hl.Gc.enable(true); #else throw 'Not implemented!'; #end @@ -122,6 +129,8 @@ class MemoryUtil { #if cpp cpp.vm.Gc.enable(false); + #elseif hl + hl.Gc.enable(false); #else throw 'Not implemented!'; #end @@ -136,6 +145,9 @@ class MemoryUtil { #if cpp cpp.vm.Gc.run(major); + #elseif hl + // Doesn't seem to have just a collect function? + hl.Gc.major(); #else throw 'Not implemented!'; #end diff --git a/source/funkin/util/SerializerUtil.hx b/source/funkin/util/SerializerUtil.hx index fafdbe691..bad8b4313 100644 --- a/source/funkin/util/SerializerUtil.hx +++ b/source/funkin/util/SerializerUtil.hx @@ -68,7 +68,7 @@ class SerializerUtil /** * Customize how certain types are serialized when converting to JSON. */ - static function replacer(key:String, value:Dynamic):Dynamic + static function replacer(key:Dynamic, value:Dynamic):Dynamic { // Hacky because you can't use `isOfType` on a struct. if (key == "version") diff --git a/templates/haxe/ApplicationMain.hx b/templates/haxe/ApplicationMain.hx index efefe6c01..b0d2d8673 100644 --- a/templates/haxe/ApplicationMain.hx +++ b/templates/haxe/ApplicationMain.hx @@ -7,7 +7,9 @@ import haxe.macro.Expr; #end #if (linux && !macro) +#if cpp import hxgamemode.GamemodeClient; +#end @:image('art/icons/iconOG.png') class ApplicationIcon extends lime.graphics.Image {} @@ -56,7 +58,7 @@ class ApplicationMain public static function create(config):Void { - #if linux + #if (linux && cpp) GamemodeClient.request_start(); #end @@ -192,7 +194,7 @@ class ApplicationMain lime.system.System.exit(result); #end - #if linux + #if (linux && cpp) GamemodeClient.request_end(); #end }