Game Overlays (#280)

* add accuracy display

* temp BG for show

* separate overlays prefab

make proper shader for star effects

* aim shakiness display

* implement testing skill star

* fully functional skill star

* separate section display from editor

* fully separate chart section display from timeline

* add section to overlays

* fix nullreference issues

* start game layout settings

* add game settings script

* fix nonfunctioning scoring

* invert y position logic on timing bar

* add perfect challenge functionality

* fix section not showing up in editor

add perfect challenge option

* add timing display minimal mode

* Update PerfectAndPractice.png

* show gismo for minigame bounds in editor

* add ability to disable overlays in editor

* prepare medals

add new timing display graphic

* hide screen preview

* per-axis camera control

added per request

* section medals basic functionality

* add medal get animations

* fix bug with perfect icons

* visual enhancements

* adjust look of timing display minmode

address audio ducking issues(?)

* prepare overlay lyt editor

add viewport pan, rotate, scale
adjust audio setting

* add layout editor UI elements

* dynamic overlay creation

* fix default single timing disp

* set up overlay settings controls

* start UI events

* runtime uuid for component reference

* layout editor affects overlay elements

* show overlay element previews while editing

* advanced audio settings

* fix bug in drop-down creation

* fallback defaults for the new stuff

* fix textbox & overlay visibility bugs
This commit is contained in:
minenice55
2023-03-10 23:51:22 -05:00
committed by GitHub
parent 11d4abf1eb
commit d5ae99d8ba
136 changed files with 131638 additions and 1043 deletions

View File

@ -7,6 +7,7 @@ using UnityEngine;
using Starpelly;
using Newtonsoft.Json;
using HeavenStudio.Games;
using HeavenStudio.Common;
namespace HeavenStudio
{
@ -21,7 +22,7 @@ namespace HeavenStudio
[Header("Components")]
public string txt;
public string ext;
public Camera GameCamera, CursorCam, OverlayCamera;
public Camera GameCamera, CursorCam, OverlayCamera, StaticCamera;
public GameObject GameLetterbox;
public CircleCursor CircleCursor;
[HideInInspector] public GameObject GamesHolder;
@ -44,11 +45,7 @@ namespace HeavenStudio
public bool autoplay;
public bool canInput = true;
public DynamicBeatmap.ChartSection currentSection, nextSection;
public float sectionProgress { get {
if (currentSection == null) return 0;
if (nextSection == null) return (Conductor.instance.songPositionInBeats - currentSection.beat) / (endBeat - currentSection.beat);
return (Conductor.instance.songPositionInBeats - currentSection.beat) / (nextSection.beat - currentSection.beat);
}}
public float sectionProgress { get; private set; }
public event Action<float> onBeatChanged;
public event Action<DynamicBeatmap.ChartSection> onSectionChange;
@ -88,6 +85,7 @@ namespace HeavenStudio
return totalPlayerAccuracy / totalInputs;
}
}
bool skillStarCollected = false;
private void Awake()
{
@ -125,8 +123,23 @@ namespace HeavenStudio
Conductor.instance.SetVolume(Beatmap.musicVolume);
Conductor.instance.firstBeatOffset = Beatmap.firstBeatOffset;
GameObject textbox = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Textbox"));
textbox.name = "Textbox";
// note: serialize this shit in the inspector //
GameObject textbox = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Textbox"));
textbox.name = "Textbox";
GameObject overlays = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Overlays"));
overlays.name = "Overlays";
GameObject timingDisp = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Overlays/TimingAccuracy"));
timingDisp.name = "TimingDisplay";
GameObject skillStarDisp = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Overlays/SkillStar"));
skillStarDisp.name = "SkillStar";
GoForAPerfect.instance.Disable();
/////
if (txt != null && ext != null)
{
LoadRemix(txt, ext);
@ -206,12 +219,25 @@ namespace HeavenStudio
}
}
public void ScoreInputAccuracy(double accuracy, bool late, double weight = 1)
public void ScoreInputAccuracy(double accuracy, bool late, double time, double weight = 1, bool doDisplay = true)
{
totalInputs += weight;
totalPlayerAccuracy += accuracy * weight;
if (accuracy < Minigame.rankOkThreshold && weight > 0)
{
SkillStarManager.instance.KillStar();
}
if (SkillStarManager.instance.IsEligible && !skillStarCollected && accuracy >= 1f)
{
if (SkillStarManager.instance.DoStarJust())
skillStarCollected = true;
}
// push the hit event to the timing display
if (doDisplay)
TimingAccuracyDisplay.instance.MakeAccuracyVfx(time, late);
}
public void SeekAheadAndPreload(double start, float seekTime = 8f)
@ -292,7 +318,6 @@ namespace HeavenStudio
}
}
// LateUpdate works a bit better(?) but causes some bugs (like issues with bop animations).
private void Update()
{
PlayerInput.UpdateInputControllers();
@ -301,16 +326,16 @@ namespace HeavenStudio
return;
if (!Conductor.instance.isPlaying)
return;
Conductor cond = Conductor.instance;
List<float> entities = Beatmap.entities.Select(c => c.beat).ToList();
List<float> tempoChanges = Beatmap.tempoChanges.Select(c => c.beat).ToList();
if (currentTempoEvent < Beatmap.tempoChanges.Count && currentTempoEvent >= 0)
{
if (Conductor.instance.songPositionInBeatsAsDouble >= tempoChanges[currentTempoEvent])
if (cond.songPositionInBeatsAsDouble >= tempoChanges[currentTempoEvent])
{
Conductor.instance.SetBpm(Beatmap.tempoChanges[currentTempoEvent].tempo);
cond.SetBpm(Beatmap.tempoChanges[currentTempoEvent].tempo);
currentTempoEvent++;
}
}
@ -318,9 +343,9 @@ namespace HeavenStudio
List<float> volumeChanges = Beatmap.volumeChanges.Select(c => c.beat).ToList();
if (currentVolumeEvent < Beatmap.volumeChanges.Count && currentVolumeEvent >= 0)
{
if (Conductor.instance.songPositionInBeatsAsDouble >= volumeChanges[currentVolumeEvent])
if (cond.songPositionInBeatsAsDouble >= volumeChanges[currentVolumeEvent])
{
Conductor.instance.SetVolume(Beatmap.volumeChanges[currentVolumeEvent].volume);
cond.SetVolume(Beatmap.volumeChanges[currentVolumeEvent].volume);
currentVolumeEvent++;
}
}
@ -328,7 +353,7 @@ namespace HeavenStudio
List<float> chartSections = Beatmap.beatmapSections.Select(c => c.beat).ToList();
if (currentSectionEvent < Beatmap.beatmapSections.Count && currentSectionEvent >= 0)
{
if (Conductor.instance.songPositionInBeatsAsDouble >= chartSections[currentSectionEvent])
if (cond.songPositionInBeatsAsDouble >= chartSections[currentSectionEvent])
{
Debug.Log("Section " + Beatmap.beatmapSections[currentSectionEvent].sectionName + " started");
currentSection = Beatmap.beatmapSections[currentSectionEvent];
@ -343,13 +368,13 @@ namespace HeavenStudio
float seekTime = 8f;
//seek ahead to preload games that have assetbundles
SeekAheadAndPreload(Conductor.instance.songPositionInBeatsAsDouble, seekTime);
SeekAheadAndPreload(cond.songPositionInBeatsAsDouble, seekTime);
SeekAheadAndDoPreEvent(Conductor.instance.songPositionInBeatsAsDouble);
if (currentEvent < Beatmap.entities.Count && currentEvent >= 0)
{
if (Conductor.instance.songPositionInBeatsAsDouble >= entities[currentEvent])
if (cond.songPositionInBeatsAsDouble >= entities[currentEvent])
{
// 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])));
@ -380,10 +405,26 @@ namespace HeavenStudio
// Thank you to @shshwdr for bring this to my attention
currentEvent++;
}
// currentEvent += gameManagerEntities.Count;
}
}
if (currentSection == null)
{
sectionProgress = 0;
}
else
{
float currectSectionStart = (float)cond.GetSongPosFromBeat(currentSection.beat);
if (nextSection == null)
sectionProgress = (cond.songPosition - currectSectionStart) / ((float)cond.GetSongPosFromBeat(endBeat) - currectSectionStart);
else
sectionProgress = (cond.songPosition - currectSectionStart) / ((float)cond.GetSongPosFromBeat(nextSection.beat) - currectSectionStart);
}
}
private void LateUpdate() {
OverlaysManager.instance.TogleOverlaysVisibility(Editor.Editor.instance == null || Editor.Editor.instance.fullscreen || ((PersistentDataManager.gameSettings.overlaysInEditor) && (!Editor.Editor.instance.fullscreen)) || HeavenStudio.Editor.GameSettings.InPreview);
}
public void ToggleInputs(bool inputs)
@ -402,6 +443,15 @@ namespace HeavenStudio
totalInputs = 0;
totalPlayerAccuracy = 0;
TimingAccuracyDisplay.instance.ResetArrow();
SkillStarManager.instance.Reset();
skillStarCollected = false;
GoForAPerfect.instance.perfect = true;
GoForAPerfect.instance.Disable();
SectionMedalsManager.instance.Reset();
StartCoroutine(PlayCo(beat));
onBeatChanged?.Invoke(beat);
}
@ -441,6 +491,12 @@ namespace HeavenStudio
onBeatChanged?.Invoke(beat);
KillAllSounds();
// I feel like I should standardize the names
SkillStarManager.instance.KillStar();
TimingAccuracyDisplay.instance.StopStarFlash();
GoForAPerfect.instance.Disable();
SectionMedalsManager.instance.OnRemixEnd();
Debug.Log($"Average input offset for playthrough: {averageInputOffset}ms");
Debug.Log($"Accuracy for playthrough: {(PlayerAccuracy * 100) : 0.00}");