Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Loading State #15386

Merged
merged 2 commits into from
Sep 15, 2024
Merged
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
110 changes: 73 additions & 37 deletions source/states/LoadingState.hx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import openfl.display.BitmapData;
import openfl.utils.AssetType;
import openfl.utils.Assets as OpenFlAssets;
import flixel.graphics.FlxGraphic;
import flixel.system.FlxAssets;
import flixel.FlxState;

import flash.media.Sound;

import backend.Song;
import backend.StageData;
import objects.Character;
Expand Down Expand Up @@ -243,13 +246,15 @@ class LoadingState extends MusicBeatState

public static function checkLoaded():Bool
{
mutex.acquire();
for (key => bitmap in requestedBitmaps)
{
if (bitmap != null && Paths.cacheBitmap(originalBitmapKeys.get(key), bitmap) != null) trace('finished preloading image $key');
else trace('failed to cache image $key');
}
requestedBitmaps.clear();
originalBitmapKeys.clear();
mutex.release();
return (loaded == loadMax && initialThreadCompleted);
}

Expand Down Expand Up @@ -519,58 +524,27 @@ class LoadingState extends MusicBeatState
loaded = 0;

//then start threads
for (sound in soundsToPrepare) initThread(() -> Paths.sound(sound), 'sound $sound');
for (music in musicToPrepare) initThread(() -> Paths.music(music), 'music $music');
for (song in songsToPrepare) initThread(() -> Paths.returnSound(song, 'songs', true, false), 'song $song');
for (sound in soundsToPrepare) initThread(() -> preloadSound('sounds/$sound'), 'sound $sound');
for (music in musicToPrepare) initThread(() -> preloadSound('music/$music'), 'music $music');
for (song in songsToPrepare) initThread(() -> preloadSound(song, 'songs', true, false), 'song $song');

// for images, they get to have their own thread
for (image in imagesToPrepare)
Thread.create(() -> {
mutex.acquire();
try {
var requestKey:String = 'images/$image';
#if TRANSLATIONS_ALLOWED requestKey = Language.getFileTranslation(requestKey); #end
if(requestKey.lastIndexOf('.') < 0) requestKey += '.png';

if (!Paths.currentTrackedAssets.exists(requestKey))
{
var bitmap:BitmapData = null;
var file:String = Paths.getPath(requestKey, IMAGE);
if (#if sys FileSystem.exists(file) || #end OpenFlAssets.exists(file, IMAGE))
{
#if sys
bitmap = BitmapData.fromFile(file);
#else
bitmap = OpenFlAssets.getBitmapData(file);
#end
requestedBitmaps.set(file, bitmap);
originalBitmapKeys.set(file, requestKey);
}
else trace('no such image $image exists');
}
}
catch(e:haxe.Exception)
{
trace('ERROR! fail on preloading image $image');
}
mutex.release();
loaded++;
});
for (image in imagesToPrepare) initThread(() -> preloadGraphic(image), 'image $image');
}

static function initThread(func:Void->Dynamic, traceData:String)
{
Thread.create(() -> {
mutex.acquire();
try {
if (func() != null) trace('finished preloading $traceData');
else trace('ERROR! fail on preloading $traceData');
}
catch(e:Dynamic) {
trace('ERROR! fail on preloading $traceData');
}
mutex.release();
mutex.acquire();
loaded++;
mutex.release();
});
}

Expand Down Expand Up @@ -631,4 +605,66 @@ class LoadingState extends MusicBeatState
trace(e.details());
}
}

// thread safe sound loader
static function preloadSound(key:String, ?path:String, ?modsAllowed:Bool = true, ?beepOnNull:Bool = true):Null<Sound>
{
var file:String = Paths.getPath(Language.getFileTranslation(key) + '.${Paths.SOUND_EXT}', SOUND, path, modsAllowed);

//trace('precaching sound: $file');
if(!Paths.currentTrackedSounds.exists(file))
{
if (#if sys FileSystem.exists(file) || #end OpenFlAssets.exists(file, SOUND))
{
var sound:Sound = OpenFlAssets.getSound(file, false);
mutex.acquire();
Paths.currentTrackedSounds.set(file, sound);
mutex.release();
}
else if (beepOnNull)
{
trace('SOUND NOT FOUND: $key, PATH: $path');
FlxG.log.error('SOUND NOT FOUND: $key, PATH: $path');
return FlxAssets.getSound('flixel/sounds/beep');
}
}
mutex.acquire();
Paths.localTrackedAssets.push(file);
mutex.release();

return Paths.currentTrackedSounds.get(file);
}

// thread safe sound loader
static function preloadGraphic(key:String):Null<BitmapData>
{
try {
var requestKey:String = 'images/$key';
#if TRANSLATIONS_ALLOWED requestKey = Language.getFileTranslation(requestKey); #end
if(requestKey.lastIndexOf('.') < 0) requestKey += '.png';

if (!Paths.currentTrackedAssets.exists(requestKey))
{
var file:String = Paths.getPath(requestKey, IMAGE);
if (#if sys FileSystem.exists(file) || #end OpenFlAssets.exists(file, IMAGE))
{
var bitmap:BitmapData = OpenFlAssets.getBitmapData(file, false);
mutex.acquire();
requestedBitmaps.set(file, bitmap);
originalBitmapKeys.set(file, requestKey);
mutex.release();
return bitmap;
}
else trace('no such image $key exists');
}

return Paths.currentTrackedAssets.get(requestKey).bitmap;
}
catch(e:haxe.Exception)
{
trace('ERROR! fail on preloading image $key');
}

return null;
}
}