mirror of
https://github.com/RHeavenStudioPlus/HeavenStudioPlus.git
synced 2024-11-25 02:55:15 +00:00
fix game asset loading for real (#861)
fix copy paste not using timeline marker's time correct more uses of swung / unswung beat
This commit is contained in:
parent
104a5896d6
commit
85064ab397
8 changed files with 243 additions and 229 deletions
|
@ -51,7 +51,7 @@ namespace HeavenStudio.Common
|
|||
_renderer.material.mainTextureOffset = new Vector2(NormalizedX, -NormalizedY) * Tile;
|
||||
|
||||
if (AutoScroll) {
|
||||
float songPos = Conductor.instance.songPositionInBeats/100;
|
||||
float songPos = Conductor.instance.unswungSongPositionInBeats/100;
|
||||
NormalizedX = songPos*AutoScrollX;
|
||||
NormalizedY = songPos*AutoScrollY;
|
||||
}
|
||||
|
|
|
@ -167,7 +167,9 @@ namespace HeavenStudio
|
|||
|
||||
SeekMusicToTime(startPos, offset);
|
||||
|
||||
songPos = startPos;
|
||||
songPosBeat = GetBeatFromSongPos(time);
|
||||
songPositionInBeatsAsDouble = GetSwungBeat(songPosBeat);
|
||||
|
||||
gameManager.SetCurrentEventToClosest(beat, true);
|
||||
}
|
||||
|
|
|
@ -181,15 +181,13 @@ namespace HeavenStudio
|
|||
|
||||
if (!preLoaded)
|
||||
{
|
||||
if (Beatmap.Entities.Count >= 1)
|
||||
if (Beatmap.Entities.Count == 0)
|
||||
{
|
||||
string game = Beatmap.Entities[0].datamodel.Split(0);
|
||||
SetCurrentGame(game);
|
||||
StartCoroutine(WaitAndSetGame(game));
|
||||
SetGame("noGame");
|
||||
}
|
||||
else
|
||||
{
|
||||
SetGame("noGame");
|
||||
SetCurrentEventToClosest(0, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,7 +378,7 @@ namespace HeavenStudio
|
|||
inf = GetGameInfo(gameName);
|
||||
if (inf != null && !(inf.inferred || inf.fxOnly))
|
||||
{
|
||||
if (inf.usesAssetBundle && !(inf.AssetsLoaded || inf.AlreadyLoading))
|
||||
if (inf.UsesAssetBundle && !(inf.AssetsLoaded || inf.AlreadyLoading))
|
||||
{
|
||||
gamesToPreload.Add(inf);
|
||||
Debug.Log($"ASYNC loading assetbundles for game {gameName}");
|
||||
|
@ -409,7 +407,7 @@ namespace HeavenStudio
|
|||
inf = GetGameInfo(gameName);
|
||||
if (inf != null && !(inf.inferred || inf.fxOnly))
|
||||
{
|
||||
if (inf.usesAssetBundle && !inf.AssetsLoaded)
|
||||
if (inf.UsesAssetBundle && !inf.AssetsLoaded)
|
||||
{
|
||||
gamesToPreload.Add(inf);
|
||||
Debug.Log($"ASYNC loading assetbundles for game {gameName}");
|
||||
|
@ -445,13 +443,6 @@ namespace HeavenStudio
|
|||
|
||||
foreach (RiqEntity entity in entitiesInRange)
|
||||
{
|
||||
string gameName = entity.datamodel.Split('/')[0];
|
||||
var inf = GetGameInfo(gameName);
|
||||
if (inf != null && inf.usesAssetBundle && inf.AssetsLoaded && !inf.SequencesPreloaded)
|
||||
{
|
||||
// Debug.Log($"Preparing game {gameName}");
|
||||
PreloadGameSequences(gameName);
|
||||
}
|
||||
eventCaller.CallPreEvent(entity);
|
||||
currentPreSequence++;
|
||||
}
|
||||
|
@ -579,7 +570,7 @@ namespace HeavenStudio
|
|||
|
||||
foreach (RiqEntity entity in entitiesInRange)
|
||||
{
|
||||
// if game isn't loaded, preload game so whatever event that would be called will still run outside if needed
|
||||
// if game isn't loaded, run inactive event
|
||||
if (entity.datamodel.Split('/')[0] != currentGame)
|
||||
{
|
||||
eventCaller.CallEvent(entity, false);
|
||||
|
@ -628,13 +619,17 @@ namespace HeavenStudio
|
|||
{
|
||||
if (string.IsNullOrEmpty(name)) return;
|
||||
Sound sound;
|
||||
if (game == "common") {
|
||||
if (game == "common")
|
||||
{
|
||||
sound = SoundByte.PlayOneShot(name, beat, pitch, volume, looping, null, (offset / 1000f));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
SoundByte.PreloadGameAudioClips(game);
|
||||
sound = SoundByte.PlayOneShotGame(game + "/" + name, beat, pitch, volume, looping, true, (offset / 1000f));
|
||||
}
|
||||
if (looping) {
|
||||
if (looping)
|
||||
{
|
||||
BeatAction.New(null, new() {
|
||||
new(beat + length, () => sound.KillLoop(0)),
|
||||
});
|
||||
|
@ -644,7 +639,8 @@ namespace HeavenStudio
|
|||
public void PlayAnimationArbitrary(string animator, string animation, float scale)
|
||||
{
|
||||
Transform animTrans = minigameObj.transform.Find(animator);
|
||||
if (animTrans != null && animTrans.TryGetComponent(out Animator anim)) {
|
||||
if (animTrans != null && animTrans.TryGetComponent(out Animator anim))
|
||||
{
|
||||
anim.DoScaledAnimationAsync(animation, scale);
|
||||
}
|
||||
}
|
||||
|
@ -1020,18 +1016,13 @@ namespace HeavenStudio
|
|||
if (canPreload)
|
||||
{
|
||||
Minigames.Minigame inf = GetGameInfo(newGame);
|
||||
if (inf != null && inf.usesAssetBundle && !inf.AssetsLoaded)
|
||||
if (inf != null && inf.UsesAssetBundle && !inf.AssetsLoaded)
|
||||
{
|
||||
preload.Add(inf);
|
||||
}
|
||||
}
|
||||
StartCoroutine(WaitAndSetGame(newGame));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetGame(newGame);
|
||||
}
|
||||
SetCurrentGame(newGame);
|
||||
}
|
||||
|
||||
List<RiqEntity> allEnds = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "end" });
|
||||
if (allEnds.Count > 0)
|
||||
|
@ -1099,6 +1090,13 @@ namespace HeavenStudio
|
|||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// While playing a chart, switches the currently active game
|
||||
/// Should only be called by chart entities
|
||||
/// </summary>
|
||||
/// <param name="game">name of the game to switch to</param>
|
||||
/// <param name="beat">beat of the chart entity calling the switch</param>
|
||||
/// <param name="flash">hide the screen during the switch</param>
|
||||
public void SwitchGame(string game, double beat, bool flash)
|
||||
{
|
||||
if (game != currentGame)
|
||||
|
@ -1142,11 +1140,16 @@ namespace HeavenStudio
|
|||
SetAmbientGlowToCurrentMinigameColor();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Immediately sets the current minigame to the specified game
|
||||
/// </summary>
|
||||
/// <param name="game"></param>
|
||||
/// <param name="useMinigameColor"></param>
|
||||
private void SetGame(string game, bool useMinigameColor = true)
|
||||
{
|
||||
ResetCamera(); // resetting camera before setting new minigame so minigames can set camera values in their awake call - Rasmus
|
||||
|
||||
GameObject prefab = GetGame(game);
|
||||
GameObject prefab = GetGamePrefab(game);
|
||||
if (prefab == null) return;
|
||||
|
||||
Destroy(minigameObj);
|
||||
|
@ -1166,13 +1169,13 @@ namespace HeavenStudio
|
|||
SetCurrentGame(game, useMinigameColor);
|
||||
}
|
||||
|
||||
public void DestroyGame()
|
||||
{
|
||||
SoundByte.UnloadAudioClips();
|
||||
SetGame("noGame");
|
||||
}
|
||||
|
||||
string currentGameRequest = null;
|
||||
/// <summary>
|
||||
/// Waits for a given game to preload, then sets it as the current game
|
||||
/// </summary>
|
||||
/// <param name="game"></param>
|
||||
/// <param name="useMinigameColor"></param>
|
||||
/// <returns></returns>
|
||||
private IEnumerator WaitAndSetGame(string game, bool useMinigameColor = true)
|
||||
{
|
||||
if (game == currentGameRequest)
|
||||
|
@ -1181,7 +1184,7 @@ namespace HeavenStudio
|
|||
}
|
||||
currentGameRequest = game;
|
||||
var inf = GetGameInfo(game);
|
||||
if (inf != null && inf.usesAssetBundle)
|
||||
if (inf != null && inf.UsesAssetBundle)
|
||||
{
|
||||
if (!(inf.AssetsLoaded || inf.AlreadyLoading))
|
||||
{
|
||||
|
@ -1199,16 +1202,18 @@ namespace HeavenStudio
|
|||
}
|
||||
}
|
||||
|
||||
public void PreloadGameSequences(string game)
|
||||
public void DestroyGame()
|
||||
{
|
||||
var gameInfo = GetGameInfo(game);
|
||||
//load the games' sound sequences
|
||||
// TODO: sound sequences sould be stored in a ScriptableObject
|
||||
if (gameInfo != null && gameInfo.LoadedSoundSequences == null)
|
||||
gameInfo.LoadedSoundSequences = GetGame(game).GetComponent<Minigame>().SoundSequences;
|
||||
SoundByte.UnloadAudioClips();
|
||||
SetGame("noGame");
|
||||
}
|
||||
|
||||
public GameObject GetGame(string name)
|
||||
/// <summary>
|
||||
/// Get the game prefab for a given game name
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public GameObject GetGamePrefab(string name)
|
||||
{
|
||||
if (name is null or "" or "noGame")
|
||||
{
|
||||
|
@ -1242,19 +1247,12 @@ namespace HeavenStudio
|
|||
}
|
||||
|
||||
GameObject prefab;
|
||||
if (gameInfo.usesAssetBundle)
|
||||
if (gameInfo.UsesAssetBundle)
|
||||
{
|
||||
//game is packed in an assetbundle, load from that instead
|
||||
if (gameInfo.AssetsLoaded && gameInfo.LoadedPrefab != null) return gameInfo.LoadedPrefab;
|
||||
// couldn't load cached prefab, try loading from assetbundle
|
||||
try
|
||||
{
|
||||
Debug.LogWarning($"Game prefab wasn't cached, loading from assetbundle for game {name}");
|
||||
return gameInfo.LoadGamePrefab();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogWarning($"Failed to load assetbundle for game {name}, using sync loading: {e.Message}");
|
||||
// couldn't load cached prefab, try loading from resources (usually indev games with mispacked assetbundles)
|
||||
Debug.LogWarning($"Failed to load prefab for game {name} from assetbundle, trying Resources...");
|
||||
prefab = Resources.Load<GameObject>($"Games/{name}");
|
||||
if (prefab != null)
|
||||
{
|
||||
|
@ -1266,7 +1264,6 @@ namespace HeavenStudio
|
|||
return Resources.Load<GameObject>($"Games/noGame");
|
||||
}
|
||||
}
|
||||
}
|
||||
// games with no assetbundle (usually indev games)
|
||||
prefab = Resources.Load<GameObject>($"Games/{name}");
|
||||
if (prefab != null)
|
||||
|
@ -1293,10 +1290,13 @@ namespace HeavenStudio
|
|||
|
||||
public bool TryGetMinigame<T>(out T mg) where T : Minigame
|
||||
{
|
||||
if (minigame is T tempMinigame) {
|
||||
if (minigame is T tempMinigame)
|
||||
{
|
||||
mg = tempMinigame;
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
mg = null;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -220,7 +220,7 @@ namespace HeavenStudio.Editor.Commands
|
|||
for (var i = 0; i < original.Count; i++)
|
||||
{
|
||||
var entity = original[i].DeepCopy();
|
||||
entity.beat = Conductor.instance.songPositionInBeatsAsDouble + (entity.beat - firstEntityBeat);
|
||||
entity.beat = Timeline.instance.PlaybackBeat + (entity.beat - firstEntityBeat);
|
||||
entityIds.Add(Guid.NewGuid());
|
||||
|
||||
pasteEntityData.Add(entity);
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace HeavenStudio.Editor.Track
|
|||
|
||||
private Vector2 relativeMousePos;
|
||||
public Vector2 RelativeMousePos => relativeMousePos;
|
||||
public float PlaybackBeat = 0.0f;
|
||||
public double PlaybackBeat = 0d;
|
||||
|
||||
public static float SnapInterval() { return instance.snapInterval; }
|
||||
|
||||
|
@ -420,19 +420,19 @@ namespace HeavenStudio.Editor.Track
|
|||
}
|
||||
else
|
||||
{
|
||||
SongBeat.text = $"Beat {string.Format("{0:0.000}", cond.songPositionInBeats)}";
|
||||
SongBeat.text = $"Beat {string.Format("{0:0.000}", cond.songPositionInBeatsAsDouble)}";
|
||||
SongPos.text = FormatTime(cond.songPositionAsDouble);
|
||||
}
|
||||
|
||||
// Metronome animation
|
||||
{
|
||||
var rectTransform = MetronomeBTN.transform.GetChild(1).GetComponent<RectTransform>();
|
||||
var rot = 0.0f;
|
||||
if (Conductor.instance.metronome)
|
||||
RectTransform rectTransform = MetronomeBTN.transform.GetChild(1).GetComponent<RectTransform>();
|
||||
float rot = 0f;
|
||||
if (cond.metronome)
|
||||
{
|
||||
var startBeat = Mathf.FloorToInt(Conductor.instance.songPositionInBeats - 0.5f);
|
||||
var nm = Conductor.instance.GetLoopPositionFromBeat(0.5f, 1f, ignoreSwing: false);
|
||||
var loop = (startBeat % 2 == 0) ? Mathf.SmoothStep(-1.1f, 1f, nm) : Mathf.SmoothStep(1f, -1f, nm);
|
||||
int startBeat = (int)Math.Floor(cond.songPositionInBeats - 0.5);
|
||||
float nm = cond.GetLoopPositionFromBeat(0.5f, 1f, ignoreSwing: false);
|
||||
float loop = (startBeat % 2 == 0) ? Mathf.SmoothStep(-1.1f, 1f, nm) : Mathf.SmoothStep(1f, -1f, nm);
|
||||
|
||||
rot = loop * 45f;
|
||||
}
|
||||
|
@ -631,12 +631,12 @@ namespace HeavenStudio.Editor.Track
|
|||
}
|
||||
}
|
||||
|
||||
public void Play(bool fromStart, float time)
|
||||
public void Play(bool fromStart, double time)
|
||||
{
|
||||
GameManager.instance.SafePlay(time, 0, false);
|
||||
if (!Conductor.instance.isPaused)
|
||||
{
|
||||
TimelineSongPosLineRef.transform.localPosition = new Vector3(time * PixelsPerBeat, TimelineSongPosLineRef.transform.localPosition.y);
|
||||
TimelineSongPosLineRef.transform.localPosition = new Vector3((float)time * PixelsPerBeat, TimelineSongPosLineRef.transform.localPosition.y);
|
||||
}
|
||||
|
||||
SetTimeButtonColors(false, true, true);
|
||||
|
@ -649,7 +649,7 @@ namespace HeavenStudio.Editor.Track
|
|||
SetTimeButtonColors(true, false, true);
|
||||
}
|
||||
|
||||
public void Stop(float time)
|
||||
public void Stop(double time)
|
||||
{
|
||||
if (TimelineSongPosLineRef != null)
|
||||
TimelineSongPosLineRef.gameObject.SetActive(false);
|
||||
|
@ -840,7 +840,8 @@ namespace HeavenStudio.Editor.Track
|
|||
{
|
||||
for (int i = 0; i < ep.Count; i++)
|
||||
{
|
||||
object returnVal = ep[i].parameter switch {
|
||||
object returnVal = ep[i].parameter switch
|
||||
{
|
||||
EntityTypes.Integer intVal => intVal.val,
|
||||
EntityTypes.Note noteVal => noteVal.val,
|
||||
EntityTypes.Float floatVal => floatVal.val,
|
||||
|
@ -850,7 +851,8 @@ namespace HeavenStudio.Editor.Track
|
|||
_ => ep[i].parameter,
|
||||
};
|
||||
|
||||
if (returnVal.GetType().IsEnum) {
|
||||
if (returnVal.GetType().IsEnum)
|
||||
{
|
||||
returnVal = (int)ep[i].parameter;
|
||||
}
|
||||
|
||||
|
@ -907,8 +909,10 @@ namespace HeavenStudio.Editor.Track
|
|||
{
|
||||
var newEntity = entity.DeepCopy();
|
||||
// there's gotta be a better way to do this. i just don't know how... -AJ
|
||||
foreach ((var key, var value) in new Dictionary<string, dynamic>(newEntity.dynamicData)) {
|
||||
if (value is EntityTypes.DropdownObj dd) {
|
||||
foreach ((var key, var value) in new Dictionary<string, dynamic>(newEntity.dynamicData))
|
||||
{
|
||||
if (value is EntityTypes.DropdownObj dd)
|
||||
{
|
||||
newEntity[key] = new EntityTypes.DropdownObj(dd.value, dd.Values);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -393,26 +393,26 @@ namespace HeavenStudio
|
|||
public List<string> supportedLocales;
|
||||
public bool inferred;
|
||||
|
||||
public bool usesAssetBundle => wantAssetBundle is not null or "";
|
||||
public bool hasLocales => supportedLocales.Count > 0;
|
||||
public bool AssetsLoaded => ((hasLocales && localeLoaded && currentLoadedLocale == defaultLocale) || (!hasLocales)) && commonLoaded && (!loadingPrefab) && loadComplete;
|
||||
public bool UsesAssetBundle => (wantAssetBundle is not null or "") && (!badBundle);
|
||||
public bool HasLocales => supportedLocales.Count > 0;
|
||||
public bool AssetsLoaded => (!badBundle) && ((HasLocales && audioLoaded && currentLoadedLocale == defaultLocale) || (!HasLocales)) && resourcesLoaded && loadComplete;
|
||||
public bool AlreadyLoading => alreadyLoading;
|
||||
public bool LoadingPrefab => loadingPrefab;
|
||||
|
||||
public bool SequencesPreloaded => soundSequences != null;
|
||||
public string LoadableName => inferred ? "noGame" : name;
|
||||
public GameObject LoadedPrefab => loadedPrefab;
|
||||
|
||||
private AssetBundle bundleCommon = null;
|
||||
private bool commonLoaded = false;
|
||||
private bool commonPreloaded = false;
|
||||
private string currentLoadedLocale = "";
|
||||
private AssetBundle bundleLocalized = null;
|
||||
private bool localeLoaded = false;
|
||||
private bool localePreloaded = false;
|
||||
private AssetBundle bundleResources = null;
|
||||
private bool resourcesLoaded = false;
|
||||
private bool resourcesPreloaded = false;
|
||||
private AssetBundle bundleAudio = null;
|
||||
private bool audioLoaded = false;
|
||||
private bool audioPreloaded = false;
|
||||
private GameObject loadedPrefab = null;
|
||||
private bool badBundle = false;
|
||||
// eventually implement secondary assetbundles for localization instead of one "common" and one "locale"
|
||||
|
||||
bool loadingPrefab = false;
|
||||
bool loadComplete = false;
|
||||
|
||||
private SoundSequence.SequenceKeyValue[] soundSequences = null;
|
||||
|
@ -465,114 +465,132 @@ namespace HeavenStudio
|
|||
this.chronologicalSortKey = chronologicalSortKey;
|
||||
}
|
||||
|
||||
public AssetBundle GetLocalizedAssetBundle()
|
||||
{
|
||||
if (bundleLocalized != null && !localeLoaded)
|
||||
{
|
||||
bundleLocalized.Unload(true);
|
||||
bundleLocalized = null;
|
||||
localeLoaded = false;
|
||||
localePreloaded = false;
|
||||
}
|
||||
if (!hasLocales) return null;
|
||||
if (!usesAssetBundle) return null;
|
||||
if (bundleLocalized == null || currentLoadedLocale != defaultLocale) //TEMPORARY: use the game's default locale until we add localization support
|
||||
{
|
||||
if (localeLoaded) return bundleLocalized;
|
||||
// TODO: try/catch for missing assetbundles
|
||||
currentLoadedLocale = defaultLocale;
|
||||
bundleLocalized = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, wantAssetBundle + "/locale." + defaultLocale));
|
||||
localeLoaded = true;
|
||||
}
|
||||
return bundleLocalized;
|
||||
}
|
||||
|
||||
public AssetBundle GetCommonAssetBundle()
|
||||
{
|
||||
if (bundleCommon != null && !commonLoaded)
|
||||
{
|
||||
bundleCommon.Unload(true);
|
||||
bundleCommon = null;
|
||||
commonLoaded = false;
|
||||
commonPreloaded = false;
|
||||
}
|
||||
if (commonLoaded) return bundleCommon;
|
||||
if (!usesAssetBundle) return null;
|
||||
if (bundleCommon == null)
|
||||
{
|
||||
// TODO: try/catch for missing assetbundles
|
||||
bundleCommon = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, wantAssetBundle + "/common"));
|
||||
commonLoaded = true;
|
||||
}
|
||||
return bundleCommon;
|
||||
}
|
||||
|
||||
bool alreadyLoading = false;
|
||||
public async UniTaskVoid LoadAssetsAsync()
|
||||
{
|
||||
if (alreadyLoading || AssetsLoaded || !usesAssetBundle) return;
|
||||
if (alreadyLoading || AssetsLoaded || !UsesAssetBundle) return;
|
||||
loadComplete = false;
|
||||
alreadyLoading = true;
|
||||
loadingPrefab = true;
|
||||
await UniTask.WhenAll(LoadCommonAssetBundleAsync(), LoadLocalizedAssetBundleAsync());
|
||||
await UniTask.WhenAll(LoadGamePrefabAsync(), LoadCommonAudioClips(), LoadLocalizedAudioClips());
|
||||
await UniTask.WhenAll(LoadResourcesAssetBundleAsync(), LoadAudioAssetBundleAsync());
|
||||
if (badBundle)
|
||||
{
|
||||
Debug.LogWarning($"Bad bundle for {name}");
|
||||
alreadyLoading = false;
|
||||
loadComplete = true;
|
||||
return;
|
||||
}
|
||||
await UniTask.WhenAll(LoadGamePrefabAsync(), PrepareResources(), PrepareAudio());
|
||||
SoundByte.PreloadGameAudioClips(this);
|
||||
alreadyLoading = false;
|
||||
loadComplete = true;
|
||||
}
|
||||
|
||||
public async UniTask LoadCommonAssetBundleAsync()
|
||||
public AssetBundle GetAudioAssetBundle()
|
||||
{
|
||||
if (bundleCommon != null && !commonLoaded)
|
||||
if (bundleAudio != null && !audioLoaded)
|
||||
{
|
||||
await bundleCommon.UnloadAsync(true);
|
||||
bundleCommon = null;
|
||||
commonLoaded = false;
|
||||
commonPreloaded = false;
|
||||
bundleAudio.Unload(true);
|
||||
bundleAudio = null;
|
||||
audioLoaded = false;
|
||||
audioPreloaded = false;
|
||||
}
|
||||
|
||||
if (commonPreloaded || commonLoaded) return;
|
||||
commonPreloaded = true;
|
||||
if (!usesAssetBundle) return;
|
||||
if (bundleCommon != null) return;
|
||||
|
||||
AssetBundle bundle = await AssetBundle.LoadFromFileAsync(Path.Combine(Application.streamingAssetsPath, wantAssetBundle + "/common")).ToUniTask(timing: PlayerLoopTiming.PreLateUpdate);
|
||||
|
||||
bundleCommon = bundle;
|
||||
commonLoaded = true;
|
||||
}
|
||||
|
||||
public async UniTask LoadLocalizedAssetBundleAsync()
|
||||
if (!HasLocales) return null;
|
||||
if (!UsesAssetBundle) return null;
|
||||
if (bundleAudio == null || currentLoadedLocale != defaultLocale) //TEMPORARY: use the game's default locale until we add localization support
|
||||
{
|
||||
if (bundleLocalized != null && !localeLoaded)
|
||||
{
|
||||
await bundleLocalized.UnloadAsync(true);
|
||||
bundleLocalized = null;
|
||||
localeLoaded = false;
|
||||
localePreloaded = false;
|
||||
}
|
||||
|
||||
if (!hasLocales) return;
|
||||
if (localePreloaded) return;
|
||||
localePreloaded = true;
|
||||
if (!usesAssetBundle) return;
|
||||
if (localeLoaded && bundleLocalized != null && currentLoadedLocale == defaultLocale) return;
|
||||
|
||||
AssetBundle bundle = await AssetBundle.LoadFromFileAsync(Path.Combine(Application.streamingAssetsPath, wantAssetBundle + "/locale." + defaultLocale)).ToUniTask(timing: PlayerLoopTiming.PreLateUpdate);
|
||||
if (localeLoaded && bundleLocalized != null && currentLoadedLocale == defaultLocale) return;
|
||||
|
||||
bundleLocalized = bundle;
|
||||
if (audioLoaded) return bundleAudio;
|
||||
// TODO: try/catch for missing assetbundles
|
||||
currentLoadedLocale = defaultLocale;
|
||||
localeLoaded = true;
|
||||
bundleAudio = AssetBundle.LoadFromFile(Path.GetFullPath(Path.Combine(Application.streamingAssetsPath, wantAssetBundle, "locale." + defaultLocale)));
|
||||
audioLoaded = true;
|
||||
}
|
||||
return bundleAudio;
|
||||
}
|
||||
|
||||
public AssetBundle GetResourcesAssetBundle()
|
||||
{
|
||||
if (badBundle) return null;
|
||||
string path = Path.GetFullPath(Path.Combine(Application.streamingAssetsPath, wantAssetBundle, "common"));
|
||||
if (bundleResources != null && !resourcesLoaded)
|
||||
{
|
||||
bundleResources.Unload(true);
|
||||
bundleResources = null;
|
||||
resourcesLoaded = false;
|
||||
resourcesPreloaded = false;
|
||||
}
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
badBundle = true;
|
||||
return null;
|
||||
}
|
||||
if (resourcesLoaded) return bundleResources;
|
||||
if (!UsesAssetBundle) return null;
|
||||
if (bundleResources == null)
|
||||
{
|
||||
bundleResources = AssetBundle.LoadFromFile(path);
|
||||
resourcesLoaded = true;
|
||||
}
|
||||
return bundleResources;
|
||||
}
|
||||
|
||||
public async UniTask LoadResourcesAssetBundleAsync()
|
||||
{
|
||||
if (badBundle) return;
|
||||
string path = Path.GetFullPath(Path.Combine(Application.streamingAssetsPath, wantAssetBundle, "common"));
|
||||
if (bundleResources != null && !resourcesLoaded)
|
||||
{
|
||||
await bundleResources.UnloadAsync(true);
|
||||
bundleResources = null;
|
||||
resourcesLoaded = false;
|
||||
resourcesPreloaded = false;
|
||||
}
|
||||
// ignore all AB checks if path doesn't exist
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
badBundle = true;
|
||||
return;
|
||||
}
|
||||
if (resourcesPreloaded || resourcesLoaded) return;
|
||||
resourcesPreloaded = true;
|
||||
if (!UsesAssetBundle) return;
|
||||
if (bundleResources != null) return;
|
||||
AssetBundle bundle = await AssetBundle.LoadFromFileAsync(path).ToUniTask(timing: PlayerLoopTiming.PreLateUpdate);
|
||||
bundleResources = bundle;
|
||||
resourcesLoaded = true;
|
||||
}
|
||||
|
||||
public async UniTask LoadAudioAssetBundleAsync()
|
||||
{
|
||||
if (bundleAudio != null && !audioLoaded)
|
||||
{
|
||||
await bundleAudio.UnloadAsync(true);
|
||||
bundleAudio = null;
|
||||
audioLoaded = false;
|
||||
audioPreloaded = false;
|
||||
}
|
||||
|
||||
if (!HasLocales) return;
|
||||
if (audioPreloaded) return;
|
||||
audioPreloaded = true;
|
||||
if (!UsesAssetBundle) return;
|
||||
if (audioLoaded && bundleAudio != null && currentLoadedLocale == defaultLocale) return;
|
||||
|
||||
AssetBundle bundle = await AssetBundle.LoadFromFileAsync(Path.GetFullPath(Path.Combine(Application.streamingAssetsPath, wantAssetBundle, "locale." + defaultLocale))).ToUniTask(timing: PlayerLoopTiming.PreLateUpdate);
|
||||
if (audioLoaded && bundleAudio != null && currentLoadedLocale == defaultLocale) return;
|
||||
|
||||
bundleAudio = bundle;
|
||||
currentLoadedLocale = defaultLocale;
|
||||
audioLoaded = true;
|
||||
}
|
||||
|
||||
public async UniTask LoadGamePrefabAsync()
|
||||
{
|
||||
if (!usesAssetBundle) return;
|
||||
if (!commonLoaded) return;
|
||||
if (bundleCommon == null) return;
|
||||
if (!UsesAssetBundle) return;
|
||||
if (!resourcesLoaded) return;
|
||||
if (bundleResources == null) return;
|
||||
if (badBundle) return;
|
||||
|
||||
AssetBundleRequest request = bundleCommon.LoadAssetAsync<GameObject>(name);
|
||||
AssetBundleRequest request = bundleResources.LoadAssetAsync<GameObject>(name);
|
||||
request.completed += (op) => OnPrefabLoaded(op as AssetBundleRequest);
|
||||
await request;
|
||||
loadedPrefab = request.asset as GameObject;
|
||||
|
@ -589,59 +607,49 @@ namespace HeavenStudio
|
|||
soundSequences = minigame.SoundSequences;
|
||||
}
|
||||
loadedPrefab = prefab;
|
||||
loadingPrefab = false;
|
||||
}
|
||||
|
||||
public GameObject LoadGamePrefab()
|
||||
public async UniTask PrepareResources()
|
||||
{
|
||||
if (!usesAssetBundle) return null;
|
||||
if (!resourcesLoaded) return;
|
||||
if (bundleResources == null) return;
|
||||
|
||||
loadedPrefab = GetCommonAssetBundle().LoadAsset<GameObject>(name);
|
||||
return loadedPrefab;
|
||||
}
|
||||
|
||||
public async UniTask LoadCommonAudioClips()
|
||||
{
|
||||
if (!commonLoaded) return;
|
||||
if (bundleCommon == null) return;
|
||||
|
||||
var assets = bundleCommon.LoadAllAssetsAsync();
|
||||
var assets = bundleResources.LoadAllAssetsAsync();
|
||||
await assets;
|
||||
}
|
||||
|
||||
public async UniTask LoadLocalizedAudioClips()
|
||||
public async UniTask PrepareAudio()
|
||||
{
|
||||
if (!localeLoaded) return;
|
||||
if (bundleLocalized == null) return;
|
||||
if (!audioLoaded) return;
|
||||
if (bundleAudio == null) return;
|
||||
|
||||
var assets = bundleLocalized.LoadAllAssetsAsync();
|
||||
var assets = bundleAudio.LoadAllAssetsAsync();
|
||||
await assets;
|
||||
}
|
||||
|
||||
public async UniTask UnloadAllAssets()
|
||||
{
|
||||
if (!usesAssetBundle) return;
|
||||
if (!UsesAssetBundle) return;
|
||||
if (loadedPrefab != null)
|
||||
{
|
||||
loadedPrefab = null;
|
||||
}
|
||||
if (bundleCommon != null)
|
||||
if (bundleResources != null)
|
||||
{
|
||||
await bundleCommon.UnloadAsync(true);
|
||||
bundleCommon = null;
|
||||
commonLoaded = false;
|
||||
commonPreloaded = false;
|
||||
await bundleResources.UnloadAsync(true);
|
||||
bundleResources = null;
|
||||
resourcesLoaded = false;
|
||||
resourcesPreloaded = false;
|
||||
}
|
||||
if (bundleLocalized != null)
|
||||
if (bundleAudio != null)
|
||||
{
|
||||
await bundleLocalized.UnloadAsync(true);
|
||||
bundleLocalized = null;
|
||||
localeLoaded = false;
|
||||
localePreloaded = false;
|
||||
await bundleAudio.UnloadAsync(true);
|
||||
bundleAudio = null;
|
||||
audioLoaded = false;
|
||||
audioPreloaded = false;
|
||||
}
|
||||
SoundByte.UnloadAudioClips(name);
|
||||
loadComplete = false;
|
||||
loadingPrefab = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1377,8 +1385,8 @@ namespace HeavenStudio
|
|||
string gameName = ((EntityTypes.DropdownObj)e["game"]).CurrentValue;
|
||||
List<string> clips;
|
||||
if (eventCaller.minigames.TryGetValue(gameName, out Minigame game) && game != null) {
|
||||
IEnumerable<AudioClip> audioClips = game.GetCommonAssetBundle().LoadAllAssets<AudioClip>();
|
||||
var localAssBun = game.GetLocalizedAssetBundle();
|
||||
IEnumerable<AudioClip> audioClips = game.GetResourcesAssetBundle().LoadAllAssets<AudioClip>();
|
||||
var localAssBun = game.GetAudioAssetBundle();
|
||||
if (localAssBun != null) {
|
||||
audioClips = audioClips.Concat(localAssBun.LoadAllAssets<AudioClip>());
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace HeavenStudio.Common
|
|||
[SerializeField] private Animator starAnim;
|
||||
[SerializeField] private ParticleSystem starParticle;
|
||||
|
||||
public double StarTargetTime { get { return starStart + starLength; } }
|
||||
public double StarTargetTime { get { return cond.GetUnSwungBeat(starStart + starLength); } }
|
||||
public bool IsEligible { get; private set; }
|
||||
public bool IsCollected { get { return state == StarState.Collected; } }
|
||||
|
||||
|
@ -42,13 +42,13 @@ namespace HeavenStudio.Common
|
|||
if (cond.songPositionInBeatsAsDouble > starStart && state == StarState.In)
|
||||
{
|
||||
double offset = cond.SecsToBeats(Minigame.AceEarlyTime() - 1, cond.GetBpmAtBeat(StarTargetTime));
|
||||
if (cond.songPositionInBeatsAsDouble <= starStart + starLength + offset)
|
||||
if (cond.unswungSongPositionInBeatsAsDouble <= StarTargetTime + offset)
|
||||
starAnim.DoScaledAnimation("StarIn", starStart, starLength + (float)offset);
|
||||
else
|
||||
starAnim.Play("StarIn", -1, 1f);
|
||||
|
||||
offset = cond.SecsToBeats(Minigame.AceLateTime() - 1, cond.GetBpmAtBeat(StarTargetTime));
|
||||
if (cond.songPositionInBeatsAsDouble > starStart + starLength + offset)
|
||||
if (cond.unswungSongPositionInBeatsAsDouble > StarTargetTime + offset)
|
||||
KillStar();
|
||||
}
|
||||
}
|
||||
|
@ -94,8 +94,8 @@ namespace HeavenStudio.Common
|
|||
public bool DoStarJust()
|
||||
{
|
||||
if (state == StarState.In &&
|
||||
cond.songPositionInBeatsAsDouble >= StarTargetTime + cond.SecsToBeats(Minigame.AceEarlyTime()-1, cond.GetBpmAtBeat(StarTargetTime)) &&
|
||||
cond.songPositionInBeatsAsDouble <= StarTargetTime + cond.SecsToBeats(Minigame.AceLateTime()-1, cond.GetBpmAtBeat(StarTargetTime))
|
||||
cond.unswungSongPositionInBeatsAsDouble >= StarTargetTime + cond.SecsToBeats(Minigame.AceEarlyTime() - 1, cond.GetBpmAtBeat(StarTargetTime)) &&
|
||||
cond.unswungSongPositionInBeatsAsDouble <= StarTargetTime + cond.SecsToBeats(Minigame.AceLateTime() - 1, cond.GetBpmAtBeat(StarTargetTime))
|
||||
)
|
||||
{
|
||||
state = StarState.Collected;
|
||||
|
@ -111,7 +111,7 @@ namespace HeavenStudio.Common
|
|||
|
||||
public void KillStar()
|
||||
{
|
||||
if (state == StarState.In && cond.songPositionInBeatsAsDouble >= starStart + starLength*0.5f || !cond.isPlaying)
|
||||
if (state == StarState.In && cond.songPositionInBeatsAsDouble >= starStart + (starLength * 0.5f) || !cond.isPlaying)
|
||||
{
|
||||
IsEligible = false;
|
||||
state = StarState.Out;
|
||||
|
|
|
@ -81,9 +81,9 @@ namespace HeavenStudio.Util
|
|||
|
||||
public static void PreloadGameAudioClips(Minigames.Minigame inf)
|
||||
{
|
||||
if (inf.usesAssetBundle)
|
||||
if (inf.UsesAssetBundle)
|
||||
{
|
||||
var cmnAb = inf.GetCommonAssetBundle();
|
||||
var cmnAb = inf.GetResourcesAssetBundle();
|
||||
if (cmnAb != null)
|
||||
{
|
||||
cmnAb.LoadAllAssetsAsync<AudioClip>().completed += (op) =>
|
||||
|
@ -94,7 +94,7 @@ namespace HeavenStudio.Util
|
|||
}
|
||||
};
|
||||
}
|
||||
var locAb = inf.GetLocalizedAssetBundle();
|
||||
var locAb = inf.GetAudioAssetBundle();
|
||||
if (locAb != null)
|
||||
{
|
||||
locAb.LoadAllAssetsAsync<AudioClip>().completed += (op) =>
|
||||
|
@ -131,9 +131,9 @@ namespace HeavenStudio.Util
|
|||
name = $"games/{name}";
|
||||
}
|
||||
if (audioClips.ContainsKey(name)) return;
|
||||
if (inf.usesAssetBundle)
|
||||
if (inf.UsesAssetBundle)
|
||||
{
|
||||
var cmnAb = inf.GetCommonAssetBundle();
|
||||
var cmnAb = inf.GetResourcesAssetBundle();
|
||||
if (cmnAb != null && cmnAb.Contains(name))
|
||||
{
|
||||
var request = cmnAb.LoadAssetAsync<AudioClip>(name);
|
||||
|
@ -144,7 +144,7 @@ namespace HeavenStudio.Util
|
|||
}
|
||||
else
|
||||
{
|
||||
var locAb = inf.GetLocalizedAssetBundle();
|
||||
var locAb = inf.GetAudioAssetBundle();
|
||||
if (locAb != null && locAb.Contains(name))
|
||||
{
|
||||
var request = locAb.LoadAssetAsync<AudioClip>(name);
|
||||
|
@ -232,12 +232,12 @@ namespace HeavenStudio.Util
|
|||
var inf = GameManager.instance.GetGameInfo(game);
|
||||
//first try the game's common assetbundle
|
||||
// Debug.Log("Jukebox loading sound " + soundName + " from common");
|
||||
clip = inf.GetCommonAssetBundle()?.LoadAsset<AudioClip>(soundName);
|
||||
clip = inf.GetResourcesAssetBundle()?.LoadAsset<AudioClip>(soundName);
|
||||
//then the localized one
|
||||
if (clip == null)
|
||||
{
|
||||
// Debug.Log("Jukebox loading sound " + soundName + " from locale");
|
||||
clip = inf.GetLocalizedAssetBundle()?.LoadAsset<AudioClip>(soundName);
|
||||
clip = inf.GetAudioAssetBundle()?.LoadAsset<AudioClip>(soundName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -274,7 +274,7 @@ namespace HeavenStudio.Util
|
|||
var inf = GameManager.instance.GetGameInfo(gameName);
|
||||
if (inf != null)
|
||||
{
|
||||
return GetClipLength($"games/{name}", pitch, inf.usesAssetBundle ? gameName : null);
|
||||
return GetClipLength($"games/{name}", pitch, inf.UsesAssetBundle ? gameName : null);
|
||||
}
|
||||
|
||||
return double.NaN;
|
||||
|
@ -301,12 +301,12 @@ namespace HeavenStudio.Util
|
|||
var inf = GameManager.instance.GetGameInfo(game);
|
||||
//first try the game's common assetbundle
|
||||
// Debug.Log("Jukebox loading sound " + soundName + " from common");
|
||||
clip = inf.GetCommonAssetBundle()?.LoadAsset<AudioClip>(soundName);
|
||||
clip = inf.GetResourcesAssetBundle()?.LoadAsset<AudioClip>(soundName);
|
||||
//then the localized one
|
||||
if (clip == null)
|
||||
{
|
||||
// Debug.Log("Jukebox loading sound " + soundName + " from locale");
|
||||
clip = inf.GetLocalizedAssetBundle()?.LoadAsset<AudioClip>(soundName);
|
||||
clip = inf.GetAudioAssetBundle()?.LoadAsset<AudioClip>(soundName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -374,12 +374,12 @@ namespace HeavenStudio.Util
|
|||
var inf = GameManager.instance.GetGameInfo(game);
|
||||
//first try the game's common assetbundle
|
||||
// Debug.Log("Jukebox loading sound " + soundName + " from common");
|
||||
clip = inf.GetCommonAssetBundle()?.LoadAsset<AudioClip>(soundName);
|
||||
clip = inf.GetResourcesAssetBundle()?.LoadAsset<AudioClip>(soundName);
|
||||
//then the localized one
|
||||
if (clip == null)
|
||||
{
|
||||
// Debug.Log("Jukebox loading sound " + soundName + " from locale");
|
||||
clip = inf.GetLocalizedAssetBundle()?.LoadAsset<AudioClip>(soundName);
|
||||
clip = inf.GetAudioAssetBundle()?.LoadAsset<AudioClip>(soundName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -424,7 +424,7 @@ namespace HeavenStudio.Util
|
|||
var inf = GameManager.instance.GetGameInfo(gameName);
|
||||
if (GameManager.instance.currentGame == gameName || forcePlay)
|
||||
{
|
||||
return PlayOneShot($"games/{name}", beat, pitch, volume, looping, inf.usesAssetBundle ? gameName : null, offset, ignoreConductorPause);
|
||||
return PlayOneShot($"games/{name}", beat, pitch, volume, looping, inf.UsesAssetBundle ? gameName : null, offset, ignoreConductorPause);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -440,7 +440,7 @@ namespace HeavenStudio.Util
|
|||
var inf = GameManager.instance.GetGameInfo(gameName);
|
||||
if (GameManager.instance.currentGame == gameName || forcePlay)
|
||||
{
|
||||
return PlayOneShotScheduled($"games/{name}", targetTime, pitch, volume, looping, inf.usesAssetBundle ? gameName : null, ignoreConductorPause);
|
||||
return PlayOneShotScheduled($"games/{name}", targetTime, pitch, volume, looping, inf.UsesAssetBundle ? gameName : null, ignoreConductorPause);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
Loading…
Reference in a new issue