Misc Additions #4 (#192)

* update icons

* add background loading of sound sequences

- fix bug with preFunction
- remove most of the old preloading code

* update spritesheets for karate man, marching orders

* file explorer chart loading

* update icon for trick on the class
This commit is contained in:
minenice55
2023-01-11 20:42:12 -05:00
committed by GitHub
parent ddc183acdd
commit 41e9d36177
89 changed files with 1970 additions and 459 deletions

View File

@ -2,8 +2,8 @@ using System;
public static class AppInfo {
//--- AutoGenerated.begin
public const string Version = "0.0.961";
public static readonly DateTime Date = new DateTime(2022, 10, 13, 16, 09, 43, 581, DateTimeKind.Utc);
public const string Version = "0.0.963";
public static readonly DateTime Date = new DateTime(2023, 01, 12, 00, 27, 14, 138, DateTimeKind.Utc);
//--- AutoGenerated.end
}

View File

@ -353,7 +353,8 @@ namespace HeavenStudio
Debug.LogWarning($"Unknown game {gameName} found in remix.json! Adding game...");
game = new Minigames.Minigame(gameName, DisplayName(gameName) + " \n<color=#eb5454>[inferred from remix.json]</color>", "", false, true, new List<Minigames.GameAction>());
EventCaller.instance.minigames.Add(game);
Editor.Editor.instance.AddIcon(game);
if (Editor.Editor.instance != null)
Editor.Editor.instance.AddIcon(game);
}
action = EventCaller.instance.GetGameAction(game, actionName);
if (action == null)

View File

@ -26,13 +26,55 @@ namespace HeavenStudio.Util
this.clips = new List<SequenceClip>(clips);
}
public MultiSound Play(float startBeat)
public MultiSound Play(float startBeat, params SequenceParams[] args)
{
List<MultiSound.Sound> sounds = new List<MultiSound.Sound>();
Dictionary<string, string> paramMaps = new Dictionary<string, string>();
foreach (SequenceClip clip in clips)
foreach (SequenceClip clipdat in clips)
{
sounds.Add(new MultiSound.Sound(clip.clip, startBeat + clip.beat, clip.pitch, clip.volume, clip.looping, clip.offset));
string clip = clipdat.clip;
float beat = clipdat.beat;
float pitch = clipdat.pitch;
float volume = clipdat.volume;
bool looping = clipdat.looping;
float offset = clipdat.offset;
if (args != null && clipdat.parameters != null && clipdat.parameters.Length > 0)
{
paramMaps.Clear();
// map param names to overrides
foreach (SequenceParams prm in clipdat.parameters)
{
if (!paramMaps.ContainsKey(prm.name))
paramMaps.Add(prm.name, prm.map);
}
// apply overrides
foreach (SequenceParams prm in args)
{
if (paramMaps.ContainsKey(prm.name))
{
string map = paramMaps[prm.name];
switch (map)
{
case "beat":
beat = prm.value;
break;
case "pitch":
pitch = prm.value;
break;
case "volume":
volume = prm.value;
break;
case "offset":
offset = prm.value;
break;
default:
break;
}
}
}
}
sounds.Add(new MultiSound.Sound(clip, startBeat + beat, pitch, volume, looping, offset));
}
return MultiSound.Play(sounds.ToArray(), game, force);
@ -41,16 +83,6 @@ namespace HeavenStudio.Util
[Serializable]
public struct SequenceClip
{
public SequenceClip(string clip, float beat, float pitch = 1f, float volume = 1f, bool looping = false, float offset = 0f)
{
this.clip = clip;
this.beat = beat;
this.pitch = pitch;
this.volume = volume;
this.looping = looping;
this.offset = offset;
}
[Tooltip("Filename of clip to use (will look in assetbundles before resources)")]
public string clip;
[Tooltip("Beat to play clip at relative to start of sequence")]
@ -65,6 +97,9 @@ namespace HeavenStudio.Util
public bool looping;
[Tooltip("Offset to start playing clip")]
public float offset;
[Tooltip("Set of possible value overrides for clip data")]
public SequenceParams[] parameters;
}
[Serializable]
@ -75,5 +110,26 @@ namespace HeavenStudio.Util
[Tooltip("Sequence to play")]
public SoundSequence sequence;
}
[Serializable]
public struct SequenceParams
{
//SequenceParams used in minigame code
public SequenceParams(string name, float value)
{
this.map = "";
this.name = name;
this.value = value;
}
[Tooltip("Inspector use only; Sequence Clip value to override")]
public string map;
[Tooltip("Name of parameter")]
public string name;
[NonSerialized]
public float value;
}
}
}

View File

@ -38,6 +38,10 @@ namespace HeavenStudio
private double dspStartTime;
public double dspStartTimeAsDouble => dspStartTime;
//the beat we started at
private double startBeat;
public double startBeatAsDouble => startBeat;
// an AudioSource attached to this GameObject that will play the music.
public AudioSource musicSource;
@ -150,6 +154,7 @@ namespace HeavenStudio
}
lastAbsTime = Time.realtimeSinceStartupAsDouble;
dspStartTime = AudioSettings.dspTime;
startBeat = beat;
// GameManager.instance.SetCurrentEventToClosest(songPositionInBeats);
}
@ -193,7 +198,7 @@ namespace HeavenStudio
public void LateUpdate()
{
if (metronome)
if (metronome && isPlaying)
{
if (ReportBeat(ref lastReportedBeat))
{
@ -260,7 +265,7 @@ namespace HeavenStudio
return GameManager.instance.Beatmap.tempoChanges;
}
public double GetSongPosFromBeat(float beat)
public double GetSongPosFromBeat(double beat)
{
var chart = GameManager.instance.Beatmap;
SetBpm(chart.bpm);

View File

@ -31,7 +31,7 @@ namespace HeavenStudio
private void Start()
{
CreateDebugUI(out Title); SetText(Title, "Rhythm Heaven Mania v1.0 BRAEDON DEBUG PLAYTEST");
CreateDebugUI(out Title); SetText(Title, $"Heaven Studio {GlobalGameManager.buildTime}");
CreateDebugUI(out SongPosBeats);
CreateDebugUI(out SongPos);
CreateDebugUI(out SecPerBeat);

View File

@ -19,7 +19,8 @@ namespace HeavenStudio
public List<GameObject> SoundObjects = new List<GameObject>();
[Header("Components")]
public TextAsset txt;
public string txt;
public string ext;
public Camera GameCamera, CursorCam, OverlayCamera;
public GameObject GameLetterbox;
public CircleCursor CircleCursor;
@ -83,17 +84,6 @@ namespace HeavenStudio
GameObject fade = new GameObject();
this.fade = fade.AddComponent<Games.Global.Flash>();
if (txt != null)
{
string json = txt.text;
Beatmap = JsonConvert.DeserializeObject<DynamicBeatmap>(json);
}
else
{
NewRemix();
}
SortEventsList();
GlobalGameManager.Init();
@ -106,13 +96,16 @@ namespace HeavenStudio
GameObject textbox = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Textbox"));
textbox.name = "Textbox";
if (playOnStart)
if (txt != null && ext != null)
{
Play(startBeat);
LoadRemix(txt, ext);
}
else
{
NewRemix();
}
// SetCurrentGame(eventCaller.GamesHolder.transform.GetComponentsInChildren<Transform>()[1].name);
SortEventsList();
if (Beatmap.entities.Count >= 1)
{
@ -123,6 +116,11 @@ namespace HeavenStudio
{
SetGame("noGame");
}
if (playOnStart)
{
Play(startBeat);
}
}
public void NewRemix()
@ -190,7 +188,7 @@ namespace HeavenStudio
var inf = GetGameInfo(gameName);
if (inf.usesAssetBundle && !inf.AssetsLoaded)
{
Debug.Log("ASYNC loading assetbundle for game " + gameName);
Debug.Log($"ASYNC loading assetbundles for game {gameName}");
StartCoroutine(inf.LoadCommonAssetBundleAsync());
StartCoroutine(inf.LoadLocalizedAssetBundleAsync());
}
@ -204,23 +202,23 @@ namespace HeavenStudio
if (start + seekTime >= entities[currentPreEvent])
{
var entitiesAtSameBeat = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentPreEvent].beat && !EventCaller.FXOnlyGames().Contains(EventCaller.instance.GetMinigame(c.datamodel.Split('/')[0])));
for (int i = 0; i < entitiesAtSameBeat.Count; i++)
foreach (DynamicBeatmap.DynamicEntity entity in entitiesAtSameBeat)
{
string gameName = entitiesAtSameBeat[i].datamodel.Split('/')[0];
string gameName = entity.datamodel.Split('/')[0];
var inf = GetGameInfo(gameName);
if (inf.usesAssetBundle && !inf.AssetsLoaded)
{
Debug.Log("ASYNC loading assetbundle for game " + gameName);
Debug.Log($"ASYNC loading assetbundles for game {gameName}");
StartCoroutine(inf.LoadCommonAssetBundleAsync());
StartCoroutine(inf.LoadLocalizedAssetBundleAsync());
}
currentPreEvent++;
}
currentPreEvent++;
}
}
}
public void SeekAheadAndDoPreEvent(float start, float seekTime = 1f)
public void SeekAheadAndDoPreEvent(float start, float seekTime = 2f)
{
List<float> entities = Beatmap.entities.Select(c => c.beat).ToList();
if (currentPreSequence < Beatmap.entities.Count && currentPreSequence >= 0)
@ -231,9 +229,16 @@ namespace HeavenStudio
var entitiesAtSameBeat = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentPreSequence].beat);
foreach (DynamicBeatmap.DynamicEntity entity in entitiesAtSameBeat)
{
string gameName = entity.datamodel.Split('/')[0];
var inf = GetGameInfo(gameName);
if (inf.usesAssetBundle && inf.AssetsLoaded && !inf.SequencesPreloaded)
{
Debug.Log($"Preloading game {gameName}");
PreloadGameSequences(gameName);
}
eventCaller.CallPreEvent(entity);
currentPreSequence++;
}
currentPreSequence++;
}
}
}
@ -291,14 +296,14 @@ namespace HeavenStudio
//seek ahead to preload games that have assetbundles
SeekAheadAndPreload(Conductor.instance.songPositionInBeats, seekTime);
SeekAheadAndDoPreEvent(Conductor.instance.songPositionInBeats, 1f);
SeekAheadAndDoPreEvent(Conductor.instance.songPositionInBeats, 2f);
if (currentEvent < Beatmap.entities.Count && currentEvent >= 0)
{
if (Conductor.instance.songPositionInBeats >= entities[currentEvent] /*&& SongPosLessThanClipLength(Conductor.instance.songPositionInBeats)*/)
{
// allows for multiple events on the same beat to be executed on the same frame, so no more 1-frame delay
var entitiesAtSameBeat = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentEvent].beat && !EventCaller.FXOnlyGames().Contains(EventCaller.instance.GetMinigame(c.datamodel.Split('/')[0])));
var entitiesAtSameBeat = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentEvent].beat && !EventCaller.FXOnlyGames().Contains(EventCaller.instance.GetMinigame(c.datamodel.Split('/')[0])));
var fxEntities = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentEvent].beat && EventCaller.FXOnlyGames().Contains(EventCaller.instance.GetMinigame(c.datamodel.Split('/')[0])));
// FX entities should ALWAYS execute before gameplay entities
@ -308,17 +313,16 @@ namespace HeavenStudio
currentEvent++;
}
for (int i = 0; i < entitiesAtSameBeat.Count; i++)
foreach (DynamicBeatmap.DynamicEntity entity in entitiesAtSameBeat)
{
var entity = entitiesAtSameBeat[i];
// if game isn't loaded, preload game so whatever event that would be called will still run outside if needed
if (entitiesAtSameBeat[i].datamodel.Split('/')[0] != currentGame && !preloadedGames.Contains(preloadedGames.Find(c => c.name == entitiesAtSameBeat[i].datamodel.Split('/')[0])))
if (entity.datamodel.Split('/')[0] != currentGame)
{
eventCaller.CallEvent(entitiesAtSameBeat[i], false);
eventCaller.CallEvent(entity, false);
}
else
{
eventCaller.CallEvent(entitiesAtSameBeat[i], true);
eventCaller.CallEvent(entity, true);
}
// Thank you to @shshwdr for bring this to my attention
@ -328,8 +332,6 @@ namespace HeavenStudio
// currentEvent += gameManagerEntities.Count;
}
}
}
public void ToggleInputs(bool inputs)
@ -380,6 +382,11 @@ namespace HeavenStudio
SetCurrentEventToClosest(beat);
onBeatChanged?.Invoke(beat);
KillAllSounds();
if (playOnStart)
{
Play(0);
}
}
public void KillAllSounds()
@ -549,47 +556,21 @@ namespace HeavenStudio
{
Destroy(currentGameO);
var instantiate = true;
if (preloadedGames.Count > 0)
{
for (int i = 0; i < preloadedGames.Count; i++)
{
if (preloadedGames[i].gameObject != null)
{
if (preloadedGames[i].gameObject.name == game)
{
preloadedGames[i].SetActive(true);
currentGameO = preloadedGames[i];
preloadedGames.Remove(preloadedGames[i]);
instantiate = false;
}
}
}
}
if (instantiate)
{
currentGameO = Instantiate(GetGame(game));
currentGameO.transform.parent = eventCaller.GamesHolder.transform;
currentGameO.name = game;
}
currentGameO = Instantiate(GetGame(game));
currentGameO.transform.parent = eventCaller.GamesHolder.transform;
currentGameO.name = game;
SetCurrentGame(game);
ResetCamera();
}
private void PreloadGame(string game)
public void PreloadGameSequences(string game)
{
if (preloadedGames.Contains(preloadedGames.Find(c => c.name == game)))
return;
var g = Instantiate(GetGame(game));
g.transform.parent = eventCaller.GamesHolder.transform;
g.SetActive(false);
g.name = game;
preloadedGames.Add(g);
var gameInfo = GetGameInfo(game);
//load the games' sound sequences
if (gameInfo != null && gameInfo.LoadedSoundSequences == null)
gameInfo.LoadedSoundSequences = GetGame(game).GetComponent<Minigame>().SoundSequences;
}
public GameObject GetGame(string name)

View File

@ -31,7 +31,8 @@ namespace HeavenStudio.Games.Loaders
{
new Param("toggle", false, "Disable call", "Disable the idol's call")
},
inactiveFunction = delegate { var e = eventCaller.currentEntity; FanClub.WarnHai(e.beat, e["toggle"]);}
inactiveFunction = delegate { var e = eventCaller.currentEntity; FanClub.WarnHai(e.beat, e["toggle"]);},
preFunction = delegate { var e = eventCaller.currentEntity; FanClub.HaiSound(e.beat, e["toggle"]); }
},
new GameAction("I suppose", "I Suppose!")
{
@ -42,7 +43,8 @@ namespace HeavenStudio.Games.Loaders
new Param("type", FanClub.KamoneResponseType.Through, "Response type", "Type of response to use"),
new Param("toggle", false, "Disable call", "Disable the idol's call")
},
inactiveFunction = delegate { var e = eventCaller.currentEntity; FanClub.WarnKamone(e.beat, e["toggle"], 0, e["type"]);}
inactiveFunction = delegate { var e = eventCaller.currentEntity; FanClub.WarnKamone(e.beat, e["toggle"], 0, e["type"]);},
preFunction = delegate { var e = eventCaller.currentEntity; FanClub.KamoneSound(e.beat, e["toggle"], 0, e["type"]); }
},
new GameAction("double clap", "Double Clap")
{
@ -52,7 +54,8 @@ namespace HeavenStudio.Games.Loaders
{
new Param("toggle", false, "Disable call", "Disable the call")
},
inactiveFunction = delegate { var e = eventCaller.currentEntity; FanClub.WarnBigReady(e.beat, e["toggle"]); }
inactiveFunction = delegate { var e = eventCaller.currentEntity; FanClub.WarnBigReady(e.beat, e["toggle"]); },
preFunction = delegate { var e = eventCaller.currentEntity; FanClub.BigReadySound(e.beat, e["toggle"]); }
},
new GameAction("play idol animation", "Idol Coreography")
{
@ -526,8 +529,6 @@ namespace HeavenStudio.Games
const float HAIS_LENGTH = 4.5f;
public void CallHai(float beat, bool noSound = false, int type = 0)
{
if (!noSound)
PlaySoundSequence("arisa_hai", beat);
responseToggle = false;
DisableBop(beat, 8f);
@ -550,20 +551,21 @@ namespace HeavenStudio.Games
new BeatAction.Action(beat + 7f, delegate { PlayOneClap(beat + 7f); DoIdolClaps();}),
});
PlaySoundSequence("crowd_hai", beat + 4f);
PlaySoundSequence("fanClub", "crowd_hai", beat + 4f);
}
public static void WarnHai(float beat, bool noSound = false, int type = 0)
{
wantHais = beat;
if (noSound) return;
MultiSound.Play(new MultiSound.Sound[] {
new MultiSound.Sound("fanClub/arisa_hai_1_jp", beat),
new MultiSound.Sound("fanClub/arisa_hai_2_jp", beat + 1f),
new MultiSound.Sound("fanClub/arisa_hai_3_jp", beat + 2f),
}, forcePlay:true);
}
public static void HaiSound(float beat, bool noSound = false, int type = 0)
{
if (noSound) return;
PlaySoundSequence("fanClub", "arisa_hai", beat);
}
public void ContinueHais(float beat, int type = 0)
{
CallHai(beat, true, type);
@ -575,13 +577,6 @@ namespace HeavenStudio.Games
bool doJump = (responseType == (int) KamoneResponseType.Jump || responseType == (int) KamoneResponseType.JumpFast);
bool isBig = (responseType == (int) KamoneResponseType.ThroughFast || responseType == (int) KamoneResponseType.JumpFast);
DisableResponse(beat, 2f);
if (!noSound)
{
if (isBig)
PlaySoundSequence("arisa_kamone_fast", beat);
else
PlaySoundSequence("arisa_kamone", beat);
}
responseToggle = true;
DisableBop(beat, (doJump) ? 6.25f : 5.25f);
@ -614,29 +609,25 @@ namespace HeavenStudio.Games
}),
});
PlaySoundSequence("crowd_kamone", beat + 2f);
PlaySoundSequence("fanClub", "crowd_kamone", beat + 2f);
}
public static void WarnKamone(float beat, bool noSound = false, int type = 0, int responseType = (int) KamoneResponseType.Through)
{
wantKamone = beat;
wantKamoneType = responseType;
}
public static void KamoneSound(float beat, bool noSound = false, int type = 0, int responseType = (int) KamoneResponseType.Through)
{
if (noSound) return;
if (responseType == (int) KamoneResponseType.ThroughFast || responseType == (int) KamoneResponseType.JumpFast)
{
MultiSound.Play(new MultiSound.Sound[] {
new MultiSound.Sound("fanClub/arisa_ka_fast_jp", beat),
new MultiSound.Sound("fanClub/arisa_mo_fast_jp", beat + 0.25f),
new MultiSound.Sound("fanClub/arisa_ne_fast_jp", beat + 0.5f),
}, forcePlay:true);
PlaySoundSequence("fanClub", "arisa_kamone_fast", beat);
}
else
{
MultiSound.Play(new MultiSound.Sound[] {
new MultiSound.Sound("fanClub/arisa_ka_jp", beat),
new MultiSound.Sound("fanClub/arisa_mo_jp", beat + 0.5f, offset: 0.07407407f),
new MultiSound.Sound("fanClub/arisa_ne_jp", beat + 1f, offset: 0.07407407f),
}, forcePlay:true);
PlaySoundSequence("fanClub", "arisa_kamone", beat);
}
}
@ -648,9 +639,6 @@ namespace HeavenStudio.Games
const float BIGCALL_LENGTH = 2.75f;
public void CallBigReady(float beat, bool noSound = false)
{
if (!noSound)
PlaySoundSequence("crowd_big_ready", beat);
Prepare(beat + 1.5f);
Prepare(beat + 2f);
@ -669,8 +657,12 @@ namespace HeavenStudio.Games
public static void WarnBigReady(float beat, bool noSound = false)
{
wantBigReady = beat;
}
public static void BigReadySound(float beat, bool noSound = false)
{
if (noSound) return;
Jukebox.PlayOneShotGame("fanClub/crowd_big_ready", beat);
PlaySoundSequence("fanClub", "crowd_big_ready", beat);
}
public void ContinueBigReady(float beat)

View File

@ -216,16 +216,18 @@ namespace HeavenStudio.Games
return sameTime;
}
public MultiSound PlaySoundSequence(string name, float startBeat)
public static MultiSound PlaySoundSequence(string game, string name, float startBeat, params SoundSequence.SequenceParams[] args)
{
foreach (SoundSequence.SequenceKeyValue pair in SoundSequences)
Minigames.Minigame gameInfo = GameManager.instance.GetGameInfo(game);
foreach (SoundSequence.SequenceKeyValue pair in gameInfo.LoadedSoundSequences)
{
if (pair.name == name)
{
// Debug.Log($"Playing sound sequence {name} at beat {startBeat}");
return pair.sequence.Play(startBeat);
}
}
Debug.LogWarning($"Sound sequence {name} not found in game {this.name} (did you build AssetBundles?)");
Debug.LogWarning($"Sound sequence {name} not found in game {game} (did you build AssetBundles?)");
return null;
}
}

View File

@ -1,5 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;
using UnityEngine;
using UnityEngine.Audio;
@ -9,13 +15,37 @@ namespace HeavenStudio
{
public TextAsset level;
public AudioClip music;
public GameObject canvas;
public bool debugUI;
public bool playOnStart = false;
public bool editor = false;
string json = "";
string ext = "";
private void Start()
{
string[] args = System.Environment.GetCommandLineArgs();
string input = "";
for (int i = 1; i < args.Length; i++) {
// first arg is always this executable
Debug.Log(args[i]);
if (args[i].IndexOfAny(Path.GetInvalidPathChars()) == -1)
{
if (File.Exists(args[i]))
{
input = args[i];
editor = false;
playOnStart = true;
}
}
else if (args[i] == "-debug")
{
debugUI = true;
}
}
GameObject Cameras = Instantiate(Resources.Load<GameObject>("Prefabs/Cameras")); Cameras.name = "Cameras";
GameObject MainCamera = Cameras.transform.GetChild(0).gameObject;
GameObject CursorCamera = Cameras.transform.GetChild(1).gameObject;
@ -33,7 +63,6 @@ namespace HeavenStudio
GameManager gameManager = GameManager.AddComponent<GameManager>();
gameManager.playOnStart = playOnStart;
gameManager.txt = level;
gameManager.GamesHolder = Games;
gameManager.CircleCursor = Cursor.transform.GetChild(0).GetComponent<CircleCursor>();
gameManager.GameCamera = MainCamera.GetComponent<Camera>();
@ -64,8 +93,58 @@ namespace HeavenStudio
}
else
{
this.GetComponent<HeavenStudio.Editor.Editor>().enabled = false;
this.GetComponent<HeavenStudio.Editor.EditorTheme>().enabled = false;
this.GetComponent<HeavenStudio.Editor.BoxSelection>().enabled = false;
canvas.SetActive(false);
OpenCmdRemix(input);
Debug.Log(json);
gameManager.txt = json;
gameManager.ext = ext;
gameManager.Init();
}
}
public void OpenCmdRemix(string path)
{
if (path == string.Empty) return;
if (!File.Exists(path)) return;
byte[] MusicBytes;
bool loadedMusic = false;
string extension = path.GetExtension();
using var zipFile = File.Open(path, FileMode.Open);
using var archive = new ZipArchive(zipFile, ZipArchiveMode.Read);
foreach (var entry in archive.Entries)
switch (entry.Name)
{
case "remix.json":
{
using var stream = entry.Open();
using var reader = new StreamReader(stream);
json = reader.ReadToEnd();
ext = extension;
break;
}
case "song.ogg":
{
using var stream = entry.Open();
using var memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
MusicBytes = memoryStream.ToArray();
Conductor.instance.musicSource.clip = OggVorbis.VorbisPlugin.ToAudioClip(MusicBytes, "music");
loadedMusic = true;
break;
}
}
if (!loadedMusic)
{
Conductor.instance.musicSource.clip = null;
MusicBytes = null;
}
}
}
}

View File

@ -48,6 +48,7 @@ namespace HeavenStudio.Editor
private void Update()
{
if (Editor.instance == null) return;
float deltaTimelineX = timelineContent.transform.localPosition.x - timelineLastX;
Camera camera = Editor.instance.EditorCamera;

View File

@ -31,6 +31,7 @@ namespace HeavenStudio.Editor
private void Start()
{
if (Editor.instance == null) return;
specialLayers.GetComponent<Image>().color = theme.properties.SpecialLayersCol.Hex2RGB();
tempoLayer.GetComponent<Image>().color = theme.properties.TempoLayerCol.Hex2RGB();
musicLayer.GetComponent<Image>().color = theme.properties.MusicLayerCol.Hex2RGB();

View File

@ -37,6 +37,7 @@ namespace HeavenStudio
public bool usesAssetBundle => (wantAssetBundle != "");
public bool hasLocales => (supportedLocales.Count > 0);
public bool AssetsLoaded => (((hasLocales && localeLoaded && currentLoadedLocale == defaultLocale) || (!hasLocales)) && commonLoaded);
public bool SequencesPreloaded => soundSequences != null;
private AssetBundle bundleCommon = null;
private bool commonLoaded = false;
@ -46,6 +47,14 @@ namespace HeavenStudio
private bool localeLoaded = false;
private bool localePreloaded = false;
private SoundSequence.SequenceKeyValue[] soundSequences = null;
public SoundSequence.SequenceKeyValue[] LoadedSoundSequences
{
get => soundSequences;
set => soundSequences = value;
}
public Minigame(string name, string displayName, string color, bool threeD, bool fxOnly, List<GameAction> actions, List<string> tags = null, string assetBundle = "", string defaultLocale = "en", List<string> supportedLocales = null)
{
this.name = name;

View File

@ -38,27 +38,28 @@ namespace HeavenStudio.Util
audioSource.pitch = pitch;
audioSource.volume = volume;
audioSource.loop = looping;
Conductor cnd = Conductor.instance;
if (beat == -1 && !scheduled)
{
audioSource.PlayScheduled(AudioSettings.dspTime);
playInstant = true;
played = true;
startTime = Conductor.instance.songPositionAsDouble;
startTime = cnd.songPositionAsDouble;
StartCoroutine(NotRelyOnBeatSound());
}
else
{
playInstant = false;
scheduledPitch = Conductor.instance.musicSource.pitch;
startTime = (AudioSettings.dspTime + (Conductor.instance.GetSongPosFromBeat(beat) - Conductor.instance.songPositionAsDouble)/(double)scheduledPitch);
scheduledPitch = cnd.musicSource.pitch;
startTime = cnd.dspStartTimeAsDouble + ((cnd.GetSongPosFromBeat(beat - cnd.startBeatAsDouble))/(double)scheduledPitch);
audioSource.PlayScheduled(startTime);
Debug.Log($"Scheduling future sound {clip.name} for beat {beat} (scheduled: {startTime}, current time: {AudioSettings.dspTime})");
}
}
private void Update()
{
Conductor cnd = Conductor.instance;
if (!played)
{
if (scheduled)
@ -78,12 +79,11 @@ namespace HeavenStudio.Util
}
else
{
if (!played && scheduledPitch != Conductor.instance.musicSource.pitch)
if (!played && scheduledPitch != cnd.musicSource.pitch)
{
scheduledPitch = Conductor.instance.musicSource.pitch;
startTime = (AudioSettings.dspTime + (Conductor.instance.GetSongPosFromBeat(beat) - Conductor.instance.songPositionAsDouble)/(double)scheduledPitch);
scheduledPitch = cnd.musicSource.pitch;
startTime = (AudioSettings.dspTime + (cnd.GetSongPosFromBeat(beat) - cnd.songPositionAsDouble)/(double)scheduledPitch);
audioSource.SetScheduledStartTime(startTime);
Debug.Log($"Rescheduling future sound {clip.name} for beat {beat} (scheduled: {startTime}, current time: {AudioSettings.dspTime})");
}
}
}
@ -93,7 +93,7 @@ namespace HeavenStudio.Util
{
if (looping && loopEndBeat != -1) // Looping sounds play forever unless params are set.
{
if (Conductor.instance.songPositionInBeats > loopEndBeat)
if (cnd.songPositionInBeats > loopEndBeat)
{
KillLoop(fadeTime);
loopIndex++;