diff --git a/OldschoolBeatSaber.sln b/OldschoolBeatSaber.sln new file mode 100644 index 0000000..bfdf9e1 --- /dev/null +++ b/OldschoolBeatSaber.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32630.192 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OldschoolBeatSaber", "OldschoolBeatSaber\OldschoolBeatSaber.csproj", "{C24FA7EE-EBF3-4CBF-9237-20B7A5094797}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C24FA7EE-EBF3-4CBF-9237-20B7A5094797}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C24FA7EE-EBF3-4CBF-9237-20B7A5094797}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C24FA7EE-EBF3-4CBF-9237-20B7A5094797}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C24FA7EE-EBF3-4CBF-9237-20B7A5094797}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D8D59EE6-8906-44D4-9124-3C4DF56EC7FB} + EndGlobalSection +EndGlobal diff --git a/OldschoolBeatSaber/Behaviours/FlickeringSign.cs b/OldschoolBeatSaber/Behaviours/FlickeringSign.cs new file mode 100644 index 0000000..5f904be --- /dev/null +++ b/OldschoolBeatSaber/Behaviours/FlickeringSign.cs @@ -0,0 +1,45 @@ +using System.Collections; +using TMPro; +using UnityEngine; + +namespace OldschoolBeatSaber.Behaviours +{ + public class FlickeringSign : MonoBehaviour + { + [SerializeField] private TextMeshPro _text; + [SerializeField] private TubeLight _light; + [SerializeField] private float _minOnDelay = .05f; + [SerializeField] private float _maxOnDelay = .4f; + [SerializeField] private float _minOffDelay = .05f; + [SerializeField] private float _maxOffDelay = .4f; + [SerializeField] private Color _onColor; + [SerializeField] private Color _offColor; + [SerializeField] private TMP_FontAsset _onFont; + [SerializeField] private TMP_FontAsset _offFont; + + private void OnEnable() + { + StartCoroutine(FlickeringCoroutine()); + } + + private IEnumerator FlickeringCoroutine() + { + while (true) + { + yield return new WaitForSeconds(UnityEngine.Random.Range(_minOnDelay, _maxOnDelay)); + SetOn(false); + + yield return new WaitForSeconds(UnityEngine.Random.Range(_minOffDelay, _maxOffDelay)); + SetOn(true); + } + } + + private void SetOn(bool on) + { + var color = !on ? _offColor : _onColor; + _text.color = color; + _text.font = !on ? _offFont : _onFont; + _light.color = color; + } + } +} diff --git a/OldschoolBeatSaber/Behaviours/MenuFogParams.cs b/OldschoolBeatSaber/Behaviours/MenuFogParams.cs new file mode 100644 index 0000000..7d44950 --- /dev/null +++ b/OldschoolBeatSaber/Behaviours/MenuFogParams.cs @@ -0,0 +1,62 @@ +using IPA.Utilities; +using OldschoolBeatSaber.Interfaces; +using System.Linq; +using UnityEngine; +using Zenject; + +namespace OldschoolBeatSaber.Behaviours +{ + public class MenuFogParams : MonoBehaviour, IOnActivate, IOnDeactivate + { + private static readonly FieldAccessor.Accessor _fogParamsAccessor + = FieldAccessor.GetAccessor("_fogParams"); + + [SerializeField] private float _attenuation = .1f; + [SerializeField] private float _offset; + [SerializeField] private float _heightFogStartY = -300f; + [SerializeField] private float _heightFogHeight = 10f; + [SerializeField] + [Min(0f)] private float _brightness = .1f; + [SerializeField] + [Range(0f, 1f)] private float _autoExposureIntensity = 1f; + + private BloomFogEnvironmentParams _bloomFogEnvironmentParams; + private BloomFogEnvironmentParams _customBloomFogEnvironmentParams; + private BloomFogEnvironment _bloomFogEnvironment; + + public void OnActivate(DiContainer container) + { + // not good but whatever. + if (_bloomFogEnvironment == null) + { + _bloomFogEnvironment = Resources.FindObjectsOfTypeAll() + .Where(x => x.gameObject.scene.name == "MainMenu") + .FirstOrDefault(); + } + + if (_customBloomFogEnvironmentParams == null) + { + _customBloomFogEnvironmentParams = ScriptableObject.CreateInstance(); + _customBloomFogEnvironmentParams.attenuation = _attenuation; + _customBloomFogEnvironmentParams.offset = _offset; + _customBloomFogEnvironmentParams.heightFogStartY = _heightFogStartY; + _customBloomFogEnvironmentParams.heightFogHeight = _heightFogHeight; + _customBloomFogEnvironmentParams.brightness = _brightness; + _customBloomFogEnvironmentParams.autoExposureIntensity = _autoExposureIntensity; + } + + _bloomFogEnvironment.enabled = false; + _bloomFogEnvironmentParams = _fogParamsAccessor(ref _bloomFogEnvironment); + _fogParamsAccessor(ref _bloomFogEnvironment) = _customBloomFogEnvironmentParams; + _bloomFogEnvironment.enabled = true; + } + + public void OnDeactivate() + { + _bloomFogEnvironment.enabled = false; + _fogParamsAccessor(ref _bloomFogEnvironment) = _bloomFogEnvironmentParams; + UnityEngine.Object.Destroy(_customBloomFogEnvironmentParams); + _bloomFogEnvironment.enabled = true; + } + } +} diff --git a/OldschoolBeatSaber/Behaviours/MenuSceneSetup.cs b/OldschoolBeatSaber/Behaviours/MenuSceneSetup.cs new file mode 100644 index 0000000..b97c722 --- /dev/null +++ b/OldschoolBeatSaber/Behaviours/MenuSceneSetup.cs @@ -0,0 +1,17 @@ +using OldschoolBeatSaber.Behaviours.UI; +using UnityEngine; +using VRUI; + +namespace OldschoolBeatSaber.Behaviours +{ + public class MenuSceneSetup : MonoBehaviour + { + [SerializeField] private VRUIScreenSystem _screenSystem; + [SerializeField] private MenuMasterViewController _menuMasterViewController; + + private void Start() + { + _screenSystem.mainScreen.SetRootViewController(_menuMasterViewController); + } + } +} diff --git a/OldschoolBeatSaber/Behaviours/TubeLight.cs b/OldschoolBeatSaber/Behaviours/TubeLight.cs new file mode 100644 index 0000000..9966e78 --- /dev/null +++ b/OldschoolBeatSaber/Behaviours/TubeLight.cs @@ -0,0 +1,124 @@ +using IPA.Utilities; +using OldschoolBeatSaber.Interfaces; +using OldschoolBeatSaber.Utilities; +using System.Linq; +using UnityEngine; +using Zenject; + +namespace OldschoolBeatSaber.Behaviours +{ + public class TubeLight : MonoBehaviour, IOnActivate + { + private static readonly FieldAccessor.Accessor _meshRendererAccessor = + FieldAccessor.GetAccessor("_meshRenderer"); + + private static readonly FieldAccessor.Accessor _lightTypeAccessor + = FieldAccessor.GetAccessor("_lightType"); + + private static readonly FieldAccessor.Accessor _mainEffectPostProcessEnabledAccessor + = FieldAccessor.GetAccessor("_mainEffectPostProcessEnabled"); + private static readonly FieldAccessor.Accessor _centerAccessor + = FieldAccessor.GetAccessor("_center"); + private static readonly FieldAccessor.Accessor _colorAlphaMultiplierAccessor + = FieldAccessor.GetAccessor("_colorAlphaMultiplier"); + private static readonly FieldAccessor.Accessor _parametricBoxControllerAccessor + = FieldAccessor.GetAccessor("_parametricBoxController"); + + public enum BoxLightType + { + None, + Opaque, + Transparent + } + + [SerializeField] private float _width = .5f; + [SerializeField] private float _length = 1f; + [SerializeField] + [Range(0f, 1f)] private float _center = 1f; + [SerializeField] private Color _color = Color.cyan; + [SerializeField] private float _colorAlphaMultiplier = 1f; + [SerializeField] private float _bloomFogIntensityMultiplier = 1f; + [SerializeField] private BoxLightType _boxLightType; + + private BoolSO _mainEffectPostProcessEnabled; + private TubeBloomPrePassLight _tubeBloomPrePassLight; + + public Color color + { + get + { + if (_tubeBloomPrePassLight != null) + return _tubeBloomPrePassLight.color; + + return _color; // We'll fallback, just in-case. + } + set + { + _color = value; + + if (_tubeBloomPrePassLight != null) + _tubeBloomPrePassLight.color = _color; + } + } + + [Inject] + public void Construct() + { + _mainEffectPostProcessEnabled = ScriptableObject.CreateInstance(); + _mainEffectPostProcessEnabled.value = true; + } + + public void OnActivate(DiContainer container) + { + container.Inject(this); + + if (_tubeBloomPrePassLight == null) + { + var activeSelf = gameObject.activeSelf; + gameObject.SetActive(false); + + _tubeBloomPrePassLight = gameObject.AddComponent(); + + BloomPrePassLight bloomPrePassLight = _tubeBloomPrePassLight; + _lightTypeAccessor(ref bloomPrePassLight) = BloomPrePassLight.bloomLightsDict.Keys.First(x => x.name == "AddBloomPrePassLightType"); + + _mainEffectPostProcessEnabledAccessor(ref _tubeBloomPrePassLight) = _mainEffectPostProcessEnabled; + _centerAccessor(ref _tubeBloomPrePassLight) = _center; + _colorAlphaMultiplierAccessor(ref _tubeBloomPrePassLight) = _colorAlphaMultiplier; + _tubeBloomPrePassLight.width = _width * 2f; + _tubeBloomPrePassLight.length = _length; + _tubeBloomPrePassLight.color = _color; + _tubeBloomPrePassLight.bloomFogIntensityMultiplier = _bloomFogIntensityMultiplier; + + if (_boxLightType != BoxLightType.None) + { + var boxLightGameObject = new GameObject("BoxLight"); + boxLightGameObject.SetActive(false); + boxLightGameObject.layer = 13; // NeonLight + var boxLightTransform = boxLightGameObject.transform; + boxLightTransform.SetParent(transform); + boxLightTransform.localRotation = Quaternion.Euler(Vector3.zero); + + var boxLightMeshFilter = boxLightGameObject.AddComponent(); + boxLightMeshFilter.mesh = ResourceUtility.TubeMesh; + var boxLightMeshRenderer = boxLightGameObject.AddComponent(); + boxLightMeshRenderer.sharedMaterial = _boxLightType switch + { + BoxLightType.Opaque => ResourceUtility.EnvLightOpaqueMaterial, + BoxLightType.Transparent => ResourceUtility.EnvLightMaterial, + _ => null + }; + + var boxLightParametricBoxController = boxLightGameObject.AddComponent(); + _meshRendererAccessor(ref boxLightParametricBoxController) = boxLightMeshRenderer; + + boxLightGameObject.SetActive(true); + + _parametricBoxControllerAccessor(ref _tubeBloomPrePassLight) = boxLightParametricBoxController; + } + + gameObject.SetActive(activeSelf); + } + } + } +} diff --git a/OldschoolBeatSaber/Behaviours/UI/ButtonClickSignal.cs b/OldschoolBeatSaber/Behaviours/UI/ButtonClickSignal.cs new file mode 100644 index 0000000..b9d99f6 --- /dev/null +++ b/OldschoolBeatSaber/Behaviours/UI/ButtonClickSignal.cs @@ -0,0 +1,40 @@ +using IPA.Utilities; +using OldschoolBeatSaber.Interfaces; +using OldschoolBeatSaber.Utilities; +using UnityEngine; +using UnityEngine.UI; +using Zenject; + +namespace OldschoolBeatSaber.Behaviours.UI +{ + public class ButtonClickSignal : MonoBehaviour, IOnActivate + { + private static readonly FieldAccessor.Accessor _buttonClickedSignalAccessor = + FieldAccessor.GetAccessor("_buttonClickedSignal"); + private static readonly FieldAccessor.Accessor _buttonAccessor + = FieldAccessor.GetAccessor("_button"); + + private Signal _uiButtonWasPressedSignal; + private SignalOnUIButtonClick _signalOnUIButtonClick; + + public void OnActivate(DiContainer container) + { + container.Inject(this); + + if (_uiButtonWasPressedSignal == null) + _uiButtonWasPressedSignal = ResourceUtility.Find("UIButtonWasPressed"); + + if (_signalOnUIButtonClick == null) + { + var activeSelf = gameObject.activeSelf; + gameObject.SetActive(false); + + _signalOnUIButtonClick = gameObject.AddComponent(); + _buttonClickedSignalAccessor(ref _signalOnUIButtonClick) = _uiButtonWasPressedSignal; + _buttonAccessor(ref _signalOnUIButtonClick) = gameObject.GetComponent