Files
UnityExplorer_Fix/src/UI/Widgets/TimeScaleWidget.cs
2022-06-23 06:03:58 +10:00

114 lines
3.4 KiB
C#

using HarmonyLib;
using UniverseLib.UI;
using UniverseLib.UI.Models;
#if UNHOLLOWER
using IL2CPPUtils = UnhollowerBaseLib.UnhollowerUtils;
#endif
#if INTEROP
using IL2CPPUtils = Il2CppInterop.Common.Il2CppInteropUtils;
#endif
namespace UnityExplorer.UI.Widgets
{
internal class TimeScaleWidget
{
public TimeScaleWidget(GameObject parent)
{
Instance = this;
ConstructUI(parent);
InitPatch();
}
static TimeScaleWidget Instance;
ButtonRef lockBtn;
bool locked;
InputFieldRef timeInput;
float desiredTime;
bool settingTimeScale;
public void Update()
{
// Fallback in case Time.timeScale patch failed for whatever reason
if (locked)
SetTimeScale(desiredTime);
if (!timeInput.Component.isFocused)
timeInput.Text = Time.timeScale.ToString("F2");
}
void SetTimeScale(float time)
{
settingTimeScale = true;
Time.timeScale = time;
settingTimeScale = false;
}
// UI event listeners
void OnTimeInputEndEdit(string val)
{
if (float.TryParse(val, out float f))
{
SetTimeScale(f);
desiredTime = f;
}
}
void OnPauseButtonClicked()
{
OnTimeInputEndEdit(timeInput.Text);
locked = !locked;
Color color = locked ? new Color(0.3f, 0.3f, 0.2f) : new Color(0.2f, 0.2f, 0.2f);
RuntimeHelper.SetColorBlock(lockBtn.Component, color, color * 1.2f, color * 0.7f);
lockBtn.ButtonText.text = locked ? "Unlock" : "Lock";
}
// UI Construction
void ConstructUI(GameObject parent)
{
Text timeLabel = UIFactory.CreateLabel(parent, "TimeLabel", "Time:", TextAnchor.MiddleRight, Color.grey);
UIFactory.SetLayoutElement(timeLabel.gameObject, minHeight: 25, minWidth: 35);
timeInput = UIFactory.CreateInputField(parent, "TimeInput", "timeScale");
UIFactory.SetLayoutElement(timeInput.Component.gameObject, minHeight: 25, minWidth: 40);
timeInput.Component.GetOnEndEdit().AddListener(OnTimeInputEndEdit);
timeInput.Text = string.Empty;
timeInput.Text = Time.timeScale.ToString();
lockBtn = UIFactory.CreateButton(parent, "PauseButton", "Lock", new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(lockBtn.Component.gameObject, minHeight: 25, minWidth: 50);
lockBtn.OnClick += OnPauseButtonClicked;
}
// Only allow Time.timeScale to be set if the user hasn't "locked" it or if we are setting the value internally.
static void InitPatch()
{
try
{
MethodInfo target = typeof(Time).GetProperty("timeScale").GetSetMethod();
#if CPP
if (IL2CPPUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(target) == null)
return;
#endif
ExplorerCore.Harmony.Patch(target,
prefix: new(AccessTools.Method(typeof(TimeScaleWidget), nameof(Prefix_Time_set_timeScale))));
}
catch { }
}
static bool Prefix_Time_set_timeScale()
{
return !Instance.locked || Instance.settingTimeScale;
}
}
}