update from Release 1 (#464)

* Integration of Jukebox Library (#451)

* add Jukebox library

todo:
- saving / loading of new format
- inferrence of unknown data like past versions
- move the temporary float casts to proper use of double
- make sound related functions take double for timing
- inform people that the Jukebox sound player was renamed to SoundByte lol

* make sound, input scheduling, and super curve use double precision

* successfully load charts

* editor works again

v1 riqs can be saved and loaded

* first tempo and volume markers are unmovable

fix loading of charts' easing values

* use gsync / freesync

* update Jukebox refs to SoundByte

* game events use double part 1

Air Rally - Glee Club converted

* don't load song if chart load fails

* finish conversion of all minigames

* remove editor waveform toggle

* timeline now respects added song offset length

clear cache files on app close
prepped notes for dsp sync

* update timeline length when offset changed

* update to latest Jukebox

* make error panel object in global game manager

* improve conductor music scheduling

* added error message box

fix first game events sometimes not playing

* editor fixes (#459)

* ditch loading dialog

doesn't show up when it's supposed to

* format song offset in editor

* remove VorbisPlugin

* Update Editor.cs

* make base datamodels for special entity reading (#463)

* make base datamodels for special entity reading

* fix crop stomp breaking when no game switch or remix end is set

* fix save shortcut

fix loading charts with no music
This commit is contained in:
minenice55 2023-06-11 12:13:01 -04:00 committed by GitHub
parent a6559d63bf
commit ce3e6f2d91
4 changed files with 91 additions and 28 deletions

View File

@ -188,6 +188,11 @@ namespace HeavenStudio
} }
current = load.Current; current = load.Current;
} }
catch (System.IO.FileNotFoundException f)
{
Debug.LogWarning("chart has no music: " + f.Message);
Conductor.instance.musicSource.clip = null;
}
catch (Exception e) catch (Exception e)
{ {
Debug.LogError($"Failed to load music: {e.Message}"); Debug.LogError($"Failed to load music: {e.Message}");

View File

@ -160,16 +160,23 @@ namespace HeavenStudio.Games
// find out when the next game switch (or remix end) happens // find out when the next game switch (or remix end) happens
var allEnds = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame", "end" }); var allEnds = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame", "end" });
allEnds.Sort((x, y) => x.beat.CompareTo(y.beat)); if (allEnds.Count == 0)
//get the beat of the closest end event
foreach (var end in allEnds)
{ {
if (end.datamodel.Split(2) == "cropStomp") continue; endBeat = double.MaxValue;
if (end.beat > startBeat) }
else
{
allEnds.Sort((x, y) => x.beat.CompareTo(y.beat));
//get the beat of the closest end event
foreach (var end in allEnds)
{ {
endBeat = end.beat; if (end.datamodel.Split(2) == "cropStomp") continue;
break; if (end.beat > startBeat)
{
endBeat = end.beat;
break;
}
} }
} }

View File

@ -315,7 +315,7 @@ namespace HeavenStudio.Editor
} }
else else
{ {
if (currentRemixPath == string.Empty) if (currentRemixPath == string.Empty || currentRemixPath == null)
{ {
SaveRemixFilePanel(); SaveRemixFilePanel();
} }
@ -370,15 +370,16 @@ namespace HeavenStudio.Editor
public void LoadRemix(bool create = false) public void LoadRemix(bool create = false)
{ {
if (create) if (create)
{
GameManager.instance.NewRemix(); GameManager.instance.NewRemix();
currentRemixPath = string.Empty;
}
else else
{ {
GameManager.instance.LoadRemix(true); GameManager.instance.LoadRemix(true);
} }
Timeline.instance.LoadRemix(); Timeline.instance.LoadRemix();
Timeline.FitToSong(); Timeline.FitToSong();
currentRemixPath = string.Empty;
} }
public void OpenRemix() public void OpenRemix()

View File

@ -73,6 +73,70 @@ namespace HeavenStudio
{"resultrepeat_ng", "Next time, follow the example better."}, // "Try Again" message for call-and-response games (two-liner) {"resultrepeat_ng", "Next time, follow the example better."}, // "Try Again" message for call-and-response games (two-liner)
}; };
static Dictionary<string, object> tempoChangeModel = new()
{
{"tempo", 120f},
{"swing", 0f},
{"timeSignature", new Vector2(4, 4)},
};
static Dictionary<string, object> volumeChangeModel = new()
{
{"volume", 1f},
{"fade", Util.EasingFunction.Ease.Instant},
};
static Dictionary<string, object> sectionMarkModel = new()
{
{"sectionName", ""},
{"isCheckpoint", false},
{"startPerfect", false},
{"breakSection", false},
{"extendsPrevious", false},
{"sectionWeight", 1f},
};
static void PreProcessSpecialEntity(RiqEntity e, Dictionary<string, object> model)
{
foreach (var t in model)
{
string propertyName = t.Key;
Type type = t.Value.GetType();
if (!e.dynamicData.ContainsKey(propertyName))
{
e.CreateProperty(propertyName, t.Value);
}
Type pType = e[propertyName].GetType();
if (pType != type)
{
try
{
if (type == typeof(Util.EasingFunction.Ease) && (pType == typeof(string) || pType == typeof(int) || pType == typeof(long)))
{
if (pType == typeof(int) || pType == typeof(long) || pType == typeof(Jukebox.EasingFunction.Ease))
{
e[propertyName] = (Util.EasingFunction.Ease)e[propertyName];
}
else
e[propertyName] = Enum.Parse(typeof(Util.EasingFunction.Ease), (string)e[propertyName]);
}
else if (type.IsEnum)
e[propertyName] = (int)e[propertyName];
else if (pType == typeof(Newtonsoft.Json.Linq.JObject))
e[propertyName] = e[propertyName].ToObject(type);
else
e[propertyName] = Convert.ChangeType(e[propertyName], type);
}
catch
{
Debug.LogWarning($"Could not convert {propertyName} to {type}! Using default value...");
// use default value
e.CreateProperty(propertyName, t.Value);
}
}
}
}
/// <summary> /// <summary>
/// processes an riq beatmap after it is loaded /// processes an riq beatmap after it is loaded
/// </summary> /// </summary>
@ -179,31 +243,17 @@ namespace HeavenStudio
foreach (var tempo in data.tempoChanges) foreach (var tempo in data.tempoChanges)
{ {
tempo["tempo"] = (float)tempo["tempo"]; PreProcessSpecialEntity(tempo, tempoChangeModel);
tempo["swing"] = (float)tempo["swing"];
if (tempo.dynamicData.ContainsKey("timeSignature"))
tempo["timeSignature"] = (Vector2)tempo["timeSignature"];
else
tempo.dynamicData.Add("timeSignature", new Vector2(4, 4));
} }
foreach (var vol in data.volumeChanges) foreach (var vol in data.volumeChanges)
{ {
vol["volume"] = (float)vol["volume"]; PreProcessSpecialEntity(vol, volumeChangeModel);
if (vol["fade"].GetType() == typeof(string))
vol["fade"] = Enum.Parse(typeof(Util.EasingFunction.Ease), (string)vol["fade"]);
else
vol["fade"] = (Util.EasingFunction.Ease)vol["fade"];
} }
foreach (var section in data.beatmapSections) foreach (var section in data.beatmapSections)
{ {
section["sectionName"] = (string)section["sectionName"]; PreProcessSpecialEntity(section, sectionMarkModel);
section["isCheckpoint"] = (bool)section["isCheckpoint"];
section["startPerfect"] = (bool)section["startPerfect"];
section["breakSection"] = (bool)section["breakSection"];
section["extendsPrevious"] = (bool)section["extendsPrevious"];
section["sectionWeight"] = (float)section["sectionWeight"];
} }
//go thru each property of the model beatmap and add any missing keyvalue pair //go thru each property of the model beatmap and add any missing keyvalue pair