Re did the hierarchy for all files.

This commit is contained in:
Martin Johnson 2023-03-17 23:41:38 -04:00
parent efdd2742db
commit 0311340f01
174 changed files with 2400 additions and 460 deletions

View File

@ -1,44 +0,0 @@
using UnityEngine;
using UnityEngine.Events;
namespace Common
{
public class TimerWrapper : MonoBehaviour
{
public UnityAction OnTimerOver;
[SerializeField, Min(0)] private float startTime;
[SerializeField] private bool countDown = true;
[SerializeField] private bool startOnAwake;
[SerializeField] private bool startOnStart;
private Timer timer;
public bool IsRunning => timer.IsRunning;
public float CurrentTime => timer.CurrentTime;
private void Awake()
{
timer = new Timer(startTime, countDown);
timer.OnTimeOver += OnTimeOver;
if (startOnAwake) timer.Start();
}
private void Start()
{
if (startOnStart) timer.Start();
}
private void Update()
{
timer.Tick(Time.deltaTime);
}
public void StartTimer() => timer.Start();
public void PauseTimer() => timer.Pause();
public void StopTimer() => timer.Stop();
public void ResetTimer() => timer.Reset();
private void OnTimeOver() => OnTimerOver?.Invoke();
}
}

View File

@ -1,133 +0,0 @@
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;
/// <summary>
/// Scene auto loader.
/// </summary>
/// <description>
/// This class adds a File > Scene Autoload menu containing options to select
/// a "master scene" enable it to be auto-loaded when the user presses play
/// in the editor. When enabled, the selected scene will be loaded on play,
/// then the original scene will be reloaded on stop.
///
/// Based on an idea on this thread:
/// http://forum.unity3d.com/threads/157502-Executing-first-scene-in-build-settings-when-pressing-play-button-in-editor
/// </description>
[InitializeOnLoad]
public static class SceneAutoLoader
{
// Static constructor binds a playmode-changed callback.
// [InitializeOnLoad] above makes sure this gets executed.
static SceneAutoLoader()
{
EditorApplication.playModeStateChanged += OnPlayModeChanged;
}
// Menu items to select the "master" scene and control whether or not to load it.
[MenuItem("File/Scene Autoload/Select Master Scene...")]
private static void SelectMasterScene()
{
string masterScene = EditorUtility.OpenFilePanel("Select Master Scene", Application.dataPath, "unity");
masterScene = masterScene.Replace(Application.dataPath, "Assets"); //project relative instead of absolute path
if (!string.IsNullOrEmpty(masterScene))
{
MasterScene = masterScene;
LoadMasterOnPlay = true;
}
}
[MenuItem("File/Scene Autoload/Load Master On Play", true)]
private static bool ShowLoadMasterOnPlay()
{
return !LoadMasterOnPlay;
}
[MenuItem("File/Scene Autoload/Load Master On Play")]
private static void EnableLoadMasterOnPlay()
{
LoadMasterOnPlay = true;
}
[MenuItem("File/Scene Autoload/Don't Load Master On Play", true)]
private static bool ShowDontLoadMasterOnPlay()
{
return LoadMasterOnPlay;
}
[MenuItem("File/Scene Autoload/Don't Load Master On Play")]
private static void DisableLoadMasterOnPlay()
{
LoadMasterOnPlay = false;
}
// Play mode change callback handles the scene load/reload.
private static void OnPlayModeChanged(PlayModeStateChange state)
{
if (!LoadMasterOnPlay)
{
return;
}
if (!EditorApplication.isPlaying && EditorApplication.isPlayingOrWillChangePlaymode)
{
// User pressed play -- autoload master scene.
PreviousScene = SceneManager.GetActiveScene().path;
if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
try
{
EditorSceneManager.OpenScene(MasterScene);
}
catch
{
Debug.LogError($"error: scene not found: {MasterScene}");
EditorApplication.isPlaying = false;
}
}
else
{
// User cancelled the save operation -- cancel play as well.
EditorApplication.isPlaying = false;
}
}
// isPlaying check required because cannot OpenScene while playing
if (!EditorApplication.isPlaying && !EditorApplication.isPlayingOrWillChangePlaymode)
{
// User pressed stop -- reload previous scene.
try
{
EditorSceneManager.OpenScene(PreviousScene);
}
catch
{
Debug.LogError($"error: scene not found: {PreviousScene}");
}
}
}
// Properties are remembered as editor preferences.
private const string EDITOR_PREF_LOAD_MASTER_ON_PLAY = "SceneAutoLoader.LoadMasterOnPlay";
private const string EDITOR_PREF_MASTER_SCENE = "SceneAutoLoader.MasterScene";
private const string EDITOR_PREF_PREVIOUS_SCENE = "SceneAutoLoader.PreviousScene";
private static bool LoadMasterOnPlay
{
get => EditorPrefs.GetBool(EDITOR_PREF_LOAD_MASTER_ON_PLAY, false);
set => EditorPrefs.SetBool(EDITOR_PREF_LOAD_MASTER_ON_PLAY, value);
}
private static string MasterScene
{
get => EditorPrefs.GetString(EDITOR_PREF_MASTER_SCENE, "Master.unity");
set => EditorPrefs.SetString(EDITOR_PREF_MASTER_SCENE, value);
}
private static string PreviousScene
{
get => EditorPrefs.GetString(EDITOR_PREF_PREVIOUS_SCENE, SceneManager.GetActiveScene().path);
set => EditorPrefs.SetString(EDITOR_PREF_PREVIOUS_SCENE, value);
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8bcf92219d69926459de23970607d69e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 23f202c345849144b9aa12e1b7bd7c6c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f02c11902918fdc4495c07de5f6cb328
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,7 +1,7 @@
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
namespace RangedValue namespace JohnsonUtils.Attributes
{ {
[CustomPropertyDrawer(typeof(RangedFloat), true)] [CustomPropertyDrawer(typeof(RangedFloat), true)]
public class RangedFloatDrawer : PropertyDrawer public class RangedFloatDrawer : PropertyDrawer

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ecba4d36f1be9fb4b9549aef53914004
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,6 +1,6 @@
using System; using System;
namespace RangedValue namespace JohnsonUtils.Attributes
{ {
public class MinMaxRangeAttribute : Attribute public class MinMaxRangeAttribute : Attribute
{ {

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f5c78e6a4385cd048a2515d2c310d89a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,6 +1,6 @@
using System; using System;
namespace RangedValue namespace JohnsonUtils.Attributes
{ {
[Serializable] [Serializable]
public struct RangedFloat public struct RangedFloat

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 689ad0d6f7f50b54aa91d1cf2464f254
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

3
JohnsonUtils/Audio.meta Normal file
View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ccc532b9cdd14d6ea2f4027e8d4a9952
timeCreated: 1679072656

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9a966376e35785a4c922cad29ccdae3e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,9 +1,11 @@
using UnityEngine; using JetBrains.Annotations;
using UnityEngine;
namespace AudioEvent namespace JohnsonUtils.Audio
{ {
public abstract class AudioEvent : ScriptableObject public abstract class AudioEvent : ScriptableObject
{ {
[PublicAPI]
public abstract void Play(AudioSource source); public abstract void Play(AudioSource source);
} }
} }

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a4d29285acc5dc94a96eea002ef6a3a2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3d0932566c8043a4b937245e2b36f64c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,23 +1,23 @@
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
namespace AudioEvent namespace JohnsonUtils.Audio
{ {
[CustomEditor(typeof(AudioEvent), true)] [CustomEditor(typeof(AudioEvent), true)]
public class AudioEventInspector : Editor public class AudioEventInspector : UnityEditor.Editor
{ {
[SerializeField] private AudioSource _audioSource; [SerializeField] private AudioSource audioSource;
private void OnEnable() private void OnEnable()
{ {
_audioSource = audioSource =
EditorUtility.CreateGameObjectWithHideFlags("Audio preview", HideFlags.HideAndDontSave, EditorUtility.CreateGameObjectWithHideFlags("Audio preview", HideFlags.HideAndDontSave,
typeof(AudioSource)).GetComponent<AudioSource>(); typeof(AudioSource)).GetComponent<AudioSource>();
} }
private void OnDisable() private void OnDisable()
{ {
DestroyImmediate(_audioSource.gameObject); DestroyImmediate(audioSource.gameObject);
} }
@ -28,7 +28,7 @@ namespace AudioEvent
EditorGUI.BeginDisabledGroup(serializedObject.isEditingMultipleObjects); EditorGUI.BeginDisabledGroup(serializedObject.isEditingMultipleObjects);
if (GUILayout.Button("Preview")) if (GUILayout.Button("Preview"))
{ {
((AudioEvent) target).Play(_audioSource); ((AudioEvent) target).Play(audioSource);
} }
EditorGUI.EndDisabledGroup(); EditorGUI.EndDisabledGroup();

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 80d27edc2350afc4aa26e2b0f21c804e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,15 +1,15 @@
using RangedValue; using JohnsonUtils.Attributes;
using UnityEngine; using UnityEngine;
namespace AudioEvent namespace JohnsonUtils.Audio
{ {
[CreateAssetMenu(menuName = "ScriptableObject/SimpleAudioEvent")] [CreateAssetMenu(menuName = "ScriptableObject/SimpleAudioEvent")]
public class SimpleAudioEvent : AudioEvent public class SimpleAudioEvent : AudioEvent
{ {
public AudioClip[] Clips; public AudioClip[] Clips;
public RangedFloat Volume = new RangedFloat(0.9f,1f); public RangedFloat Volume = new (0.9f,1f);
[MinMaxRange(0, 2)] public RangedFloat Pitch = new RangedFloat(0.95f,1.05f); [MinMaxRange(0, 2)] public RangedFloat Pitch = new (0.95f,1.05f);
public override void Play(AudioSource source) public override void Play(AudioSource source)
{ {

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 812a0d40f751a99469384da85b231dc0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6c5f62191df2e694db21497847d5649f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 06c5c26b1b4379a45a83ca062577134e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,24 +1,30 @@
using System; using System;
using JetBrains.Annotations;
using Sirenix.OdinInspector; using Sirenix.OdinInspector;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
#if ODIN_INSPECTOR
#endif
namespace Canvases.Components namespace JohnsonUtils.Canvases
{ {
public class ButtonUIComponent : UISelectableComponentBase public class ButtonUIComponent : UISelectableComponentBase
{ {
public event Action OnClick; public event Action OnClick;
[Header("Association"), SerializeField, Required] #if ODIN_INSPECTOR
[Required]
#endif
[Header("Association"), SerializeField]
private Button button; private Button button;
[Header("Configuration"), SerializeField] [Header("Configuration"), SerializeField, UsedImplicitly]
private ButtonNavigationType buttonNavigationType; private ButtonNavigationType buttonNavigationType;
private enum ButtonNavigationType private enum ButtonNavigationType
{ {
Forward, [UsedImplicitly] Forward,
Backward [UsedImplicitly] Backward
} }
public Color Color public Color Color
@ -26,11 +32,13 @@ namespace Canvases.Components
set => button.image.color = value; set => button.image.color = value;
} }
[PublicAPI]
public bool Enabled public bool Enabled
{ {
set => button.interactable = value; set => button.interactable = value;
} }
[PublicAPI]
public void Select() => button.Select(); public void Select() => button.Select();
protected override void SetSelectableGameObject() => Selectable = button; protected override void SetSelectableGameObject() => Selectable = button;
@ -49,7 +57,6 @@ namespace Canvases.Components
private void OnButtonClicked() private void OnButtonClicked()
{ {
// PlayClickedSound();
OnClick?.Invoke(); OnClick?.Invoke();
} }

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4f8583985379cfa409fa5463af6f62ae
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,22 +1,25 @@
using Sirenix.OdinInspector; 
using Sirenix.OdinInspector;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
namespace Canvases.Components namespace JohnsonUtils.Canvases
{ {
// ReSharper disable once InconsistentNaming Reason: UI should be capitalized
public class ImageUIComponent : UIComponentBase public class ImageUIComponent : UIComponentBase
{ {
[Header("Association")][Required] [Header("Association")]
#if ODIN_INSPECTOR
[Required]
#endif
[SerializeField] private Image image; [SerializeField] private Image image;
private Color initialColor; private Color _initialColor;
private void Awake() => initialColor = image.color; private void Awake() => _initialColor = image.color;
private void Start() => Debug.Assert(image, $"A {nameof(image)} must be assigned to a {nameof(ImageUIComponent)}"); private void Start() => Debug.Assert(image, $"A {nameof(image)} must be assigned to a {nameof(ImageUIComponent)}");
public void ResetColor() => image.color = initialColor; public void ResetColor() => image.color = _initialColor;
public Sprite Sprite public Sprite Sprite
{ {

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9d0ab7cb6305cee4ea667a7cedab0cc9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,17 +1,22 @@
using System; using System;
using System.Collections; using System.Collections;
using JetBrains.Annotations;
using Sirenix.OdinInspector; using Sirenix.OdinInspector;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
#if ODIN_INSPECTOR
#endif
namespace Canvases.Components namespace JohnsonUtils.Canvases
{ {
// ReSharper disable once InconsistentNaming Reason: UI should be capitalized
public class SliderUIComponent : UISelectableComponentBase public class SliderUIComponent : UISelectableComponentBase
{ {
public event Action<float> OnValueChanged; [UsedImplicitly] public event Action<float> OnValueChanged;
[Header("Association"), SerializeField, Required] #if ODIN_INSPECTOR
[Required]
#endif
[Header("Association"), SerializeField]
private Slider slider; private Slider slider;
[SerializeField] private Image backgroundImage; [SerializeField] private Image backgroundImage;
@ -23,36 +28,39 @@ namespace Canvases.Components
[SerializeField] private Color valueIncreaseColor = Color.green; [SerializeField] private Color valueIncreaseColor = Color.green;
[SerializeField] private Color valueDecreaseColor = Color.red; [SerializeField] private Color valueDecreaseColor = Color.red;
private float targetValue; private float _targetValue;
private float currentValue; private float _currentValue;
private Coroutine animationRoutine; private Coroutine _animationRoutine;
private Color initialColor = Color.black; private Color _initialColor = Color.black;
[UsedImplicitly]
public float Value public float Value
{ {
get => currentValue; get => _currentValue;
set set
{ {
if (isChangeValueAnimated) if (isChangeValueAnimated)
{ {
targetValue = value; _targetValue = value;
StartAnimation(); StartAnimation();
} }
else else
{ {
currentValue = value; _currentValue = value;
slider.value = value; slider.value = value;
} }
} }
} }
[UsedImplicitly]
public float MaxValue public float MaxValue
{ {
get => slider.maxValue; get => slider.maxValue;
set => slider.maxValue = value; set => slider.maxValue = value;
} }
[UsedImplicitly]
public Color BackgroundColor public Color BackgroundColor
{ {
set set
@ -64,18 +72,20 @@ namespace Canvases.Components
} }
} }
[UsedImplicitly]
public Color FillColor public Color FillColor
{ {
set set
{ {
if (fillImage != null) if (fillImage != null)
{ {
initialColor = value; _initialColor = value;
fillImage.color = initialColor; fillImage.color = _initialColor;
} }
} }
} }
[UsedImplicitly]
public Color FrameColor public Color FrameColor
{ {
set set
@ -104,10 +114,10 @@ namespace Canvases.Components
private void StartAnimation() private void StartAnimation()
{ {
if (animationRoutine != null) if (_animationRoutine != null)
StopCoroutine(animationRoutine); StopCoroutine(_animationRoutine);
animationRoutine = StartCoroutine(AnimateValueChange(targetValue > currentValue)); _animationRoutine = StartCoroutine(AnimateValueChange(_targetValue > _currentValue));
} }
private IEnumerator AnimateValueChange(bool isValueChangePositive) private IEnumerator AnimateValueChange(bool isValueChangePositive)
@ -116,10 +126,10 @@ namespace Canvases.Components
{ {
fillImage.color = valueIncreaseColor; fillImage.color = valueIncreaseColor;
while (currentValue < targetValue) while (_currentValue < _targetValue)
{ {
currentValue += animationSpeed * Time.deltaTime; _currentValue += animationSpeed * Time.deltaTime;
slider.value = currentValue; slider.value = _currentValue;
yield return null; yield return null;
} }
} }
@ -127,17 +137,17 @@ namespace Canvases.Components
{ {
fillImage.color = valueDecreaseColor; fillImage.color = valueDecreaseColor;
while (currentValue > targetValue) while (_currentValue > _targetValue)
{ {
currentValue -= animationSpeed * Time.deltaTime; _currentValue -= animationSpeed * Time.deltaTime;
slider.value = currentValue; slider.value = _currentValue;
yield return null; yield return null;
} }
} }
currentValue = targetValue; _currentValue = _targetValue;
slider.value = currentValue; slider.value = _currentValue;
fillImage.color = initialColor; fillImage.color = _initialColor;
} }
private void OnSliderChanged(float value) => OnValueChanged?.Invoke(value); private void OnSliderChanged(float value) => OnValueChanged?.Invoke(value);

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 876f9760c3e58b248a8c3028ee11c049
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,16 +1,20 @@
using Sirenix.OdinInspector; 
using JetBrains.Annotations;
using Sirenix.OdinInspector;
using TMPro; using TMPro;
using UnityEngine; using UnityEngine;
namespace Canvases.Components namespace JohnsonUtils.Canvases
{ {
// ReSharper disable once InconsistentNaming Reason: UI should be capitalized
public class TextUIComponent : UIComponentBase public class TextUIComponent : UIComponentBase
{ {
[Header("Association"), Required, SerializeField] #if ODIN_INSPECTOR
[Required]
#endif
[Header("Association"), SerializeField]
private TMP_Text text; private TMP_Text text;
private string initialText; private string _initialText;
public string Text public string Text
{ {
@ -18,20 +22,23 @@ namespace Canvases.Components
set => text.text = string.IsNullOrEmpty(value) ? string.Empty : value; set => text.text = string.IsNullOrEmpty(value) ? string.Empty : value;
} }
[UsedImplicitly]
public Color Color public Color Color
{ {
get => text.color; get => text.color;
set => text.color = value; set => text.color = value;
} }
private void Awake() => initialText = text.text; private void Awake() => _initialText = text.text;
private void Start() => Debug.Assert(text, $"A {nameof(text)} must be assigned to a {nameof(TMP_Text)}"); private void Start() => Debug.Assert(text, $"A {nameof(text)} must be assigned to a {nameof(TMP_Text)}");
public void ResetText() => text.text = initialText;
public void ResetText() => text.text = _initialText;
[PublicAPI]
public void AddText(string textToAdd) => text.text += textToAdd; public void AddText(string textToAdd) => text.text += textToAdd;
[PublicAPI]
public void EraseText() => text.text = string.Empty; public void EraseText() => text.text = string.Empty;
private void OnValidate() private void OnValidate()

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6abb350662ec32f4382b6053030a04e8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,18 +1,24 @@
using System; using System;
using JetBrains.Annotations;
using Sirenix.OdinInspector; using Sirenix.OdinInspector;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
#if ODIN_INSPECTOR
#endif
namespace Canvases.Components namespace JohnsonUtils.Canvases
{ {
// ReSharper disable once InconsistentNaming Reason: UI should be capitalized
public class ToggleUIComponent : UISelectableComponentBase public class ToggleUIComponent : UISelectableComponentBase
{ {
public event Action<bool> OnValueChanged; [UsedImplicitly] public event Action<bool> OnValueChanged;
[Header("Association"), Required, SerializeField] #if ODIN_INSPECTOR
[Required]
#endif
[Header("Association"), SerializeField]
private Toggle toggle; private Toggle toggle;
[PublicAPI]
public bool IsOn => toggle.isOn; public bool IsOn => toggle.isOn;
private void Start() private void Start()
@ -29,6 +35,7 @@ namespace Canvases.Components
protected override void SetSelectableGameObject() => Selectable = toggle; protected override void SetSelectableGameObject() => Selectable = toggle;
[PublicAPI]
public void Invert() => toggle.isOn = !toggle.isOn; public void Invert() => toggle.isOn = !toggle.isOn;
private void OnToggleChanged(bool value) => OnValueChanged?.Invoke(value); private void OnToggleChanged(bool value) => OnValueChanged?.Invoke(value);

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8bbf0d600bb435648859a6613e816656
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,15 +1,16 @@
using UnityEngine; using JetBrains.Annotations;
using Utilities.Extensions; using JohnsonUtils.Utilities;
using UnityEngine;
namespace Canvases.Components namespace JohnsonUtils.Canvases
{ {
// ReSharper disable once InconsistentNaming Reason: UI should be capitalized
public abstract class UIComponentBase : MonoBehaviour public abstract class UIComponentBase : MonoBehaviour
{ {
public void Show() => gameObject.Show(); public void Show() => gameObject.Show();
public void Hide() => gameObject.Hide(); public void Hide() => gameObject.Hide();
[PublicAPI]
public void ToggleDisplay() => gameObject.SetActive(!gameObject.activeInHierarchy); public void ToggleDisplay() => gameObject.SetActive(!gameObject.activeInHierarchy);
public void SetActive(bool active) => gameObject.SetActive(active); public void SetActive(bool active) => gameObject.SetActive(active);

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ce11554684acbfa458b1e1aac7d6f738
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,25 +1,26 @@
using System; using System;
using JetBrains.Annotations;
using JohnsonUtils.Utilities;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems; using UnityEngine.EventSystems;
using UnityEngine.UI; using UnityEngine.UI;
using Utilities.Extensions;
namespace Canvases.Components namespace JohnsonUtils.Canvases
{ {
public abstract class UISelectableComponentBase : UIComponentBase public abstract class UISelectableComponentBase : UIComponentBase
{ {
public event Action OnSelected; [UsedImplicitly] public event Action OnSelected;
protected Selectable Selectable = null; protected Selectable Selectable = null;
private EventTrigger.Entry selectEventTriggerEntry; private EventTrigger.Entry _selectEventTriggerEntry;
private CanvasGroup parentCanvasGroup; private CanvasGroup _parentCanvasGroup;
private void Awake() private void Awake()
{ {
SetSelectableGameObject(); SetSelectableGameObject();
AddSelectEventTrigger(); AddSelectEventTrigger();
parentCanvasGroup = gameObject.GetComponentInParents<CanvasGroup>(); _parentCanvasGroup = gameObject.GetComponentInParents<CanvasGroup>();
} }
protected abstract void SetSelectableGameObject(); protected abstract void SetSelectableGameObject();
@ -27,26 +28,25 @@ namespace Canvases.Components
private void AddSelectEventTrigger() private void AddSelectEventTrigger()
{ {
EventTrigger eventTrigger = Selectable.gameObject.GetOrAddComponent<EventTrigger>(); EventTrigger eventTrigger = Selectable.gameObject.GetOrAddComponent<EventTrigger>();
selectEventTriggerEntry = new EventTrigger.Entry _selectEventTriggerEntry = new EventTrigger.Entry
{ {
eventID = EventTriggerType.Select eventID = EventTriggerType.Select
}; };
selectEventTriggerEntry.callback.AddListener(OnSelectableSelected); _selectEventTriggerEntry.callback.AddListener(OnSelectableSelected);
eventTrigger.triggers.Add(selectEventTriggerEntry); eventTrigger.triggers.Add(_selectEventTriggerEntry);
} }
private void OnSelectableSelected(BaseEventData data) private void OnSelectableSelected(BaseEventData data)
{ {
if (!Selectable.interactable || parentCanvasGroup != null && !parentCanvasGroup.interactable) if (!Selectable.interactable || _parentCanvasGroup != null && !_parentCanvasGroup.interactable)
return; return;
// Play select sound
OnSelected?.Invoke(); OnSelected?.Invoke();
} }
protected virtual void OnDestroy() protected virtual void OnDestroy()
{ {
selectEventTriggerEntry?.callback.RemoveListener(OnSelectableSelected); _selectEventTriggerEntry?.callback.RemoveListener(OnSelectableSelected);
} }
} }
} }

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c7554ebd4dc164f4e8bb12a69c5e3388
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e3085bb90bae8d647bcf799a94ba0f9c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cf6a9d522618ee54cb581eb4942a7062
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,11 +1,11 @@
using System; using System;
using Canvases.Components; using JetBrains.Annotations;
using JohnsonUtils.Utilities;
using JohnsonUtils.Utilities.Icons;
using UnityEngine; using UnityEngine;
using UnityEngine.InputSystem; using UnityEngine.InputSystem;
using Utilities;
using Utilities.Extensions;
namespace Canvases.Menu.Rebind namespace JohnsonUtils.Canvases
{ {
public class RebindActionUI : MonoBehaviour public class RebindActionUI : MonoBehaviour
{ {
@ -15,68 +15,69 @@ namespace Canvases.Menu.Rebind
[SerializeField] private RebindReferences mainBindingReferences; [SerializeField] private RebindReferences mainBindingReferences;
[SerializeField] private RebindReferences altBindingReferences; [SerializeField] private RebindReferences altBindingReferences;
private TextUIComponent rebindOverlay; private TextUIComponent _rebindOverlay;
private InputAction action; private InputAction _action;
private InputActionRebindingExtensions.RebindingOperation rebindOperation; private InputActionRebindingExtensions.RebindingOperation _rebindOperation;
[PublicAPI]
public void ResetToDefault() public void ResetToDefault()
{ {
action.actionMap.Disable(); _action.actionMap.Disable();
action.RemoveBindingOverride(mainBindingReferences.Index); _action.RemoveBindingOverride(mainBindingReferences.Index);
action.RemoveBindingOverride(altBindingReferences.Index); _action.RemoveBindingOverride(altBindingReferences.Index);
UpdateBindingDisplay(); UpdateBindingDisplay();
action.actionMap.Enable(); _action.actionMap.Enable();
} }
private void StartInteractiveRebind(int index) private void StartInteractiveRebind(int index)
{ {
action.actionMap.Disable(); _action.actionMap.Disable();
PerformInteractiveRebind(index); PerformInteractiveRebind(index);
action.actionMap.Enable(); _action.actionMap.Enable();
} }
private void PerformInteractiveRebind(int bindingIndex) private void PerformInteractiveRebind(int bindingIndex)
{ {
rebindOperation?.Cancel(); // Will null out rebindOperation. _rebindOperation?.Cancel(); // Will null out rebindOperation.
void CleanUp(InputActionRebindingExtensions.RebindingOperation rebindingOperation) void CleanUp(InputActionRebindingExtensions.RebindingOperation rebindingOperation)
{ {
if (rebindOverlay != null) if (_rebindOverlay != null)
{ {
rebindOverlay.SetActive(false); _rebindOverlay.SetActive(false);
} }
UpdateBindingDisplay(); UpdateBindingDisplay();
rebindOperation?.Dispose(); _rebindOperation?.Dispose();
rebindOperation = null; _rebindOperation = null;
} }
// Configure the rebind. // Configure the rebind.
rebindOperation = action.PerformInteractiveRebinding(bindingIndex) _rebindOperation = _action.PerformInteractiveRebinding(bindingIndex)
.OnCancel(CleanUp) .OnCancel(CleanUp)
.OnComplete(CleanUp); .OnComplete(CleanUp);
// If it's a part binding, show the name of the part in the UI. // If it's a part binding, show the name of the part in the UI.
string partName = string.Empty; string partName = string.Empty;
if (action.bindings[bindingIndex].isPartOfComposite) if (_action.bindings[bindingIndex].isPartOfComposite)
partName = $"Binding '{action.bindings[bindingIndex].name}'. "; partName = $"Binding '{_action.bindings[bindingIndex].name}'. ";
// Bring up rebind overlay, if we have one. // Bring up rebind overlay, if we have one.
if (rebindOverlay != null) if (_rebindOverlay != null)
{ {
rebindOverlay.Show(); _rebindOverlay.Show();
string text = !string.IsNullOrEmpty(rebindOperation.expectedControlType) string text = !string.IsNullOrEmpty(_rebindOperation.expectedControlType)
? $"{partName}Waiting for {rebindOperation.expectedControlType} input..." ? $"{partName}Waiting for {_rebindOperation.expectedControlType} input..."
: $"{partName}Waiting for input..."; : $"{partName}Waiting for input...";
rebindOverlay.Text =text; _rebindOverlay.Text =text;
} }
// If we have no rebind overlay and no callback but we have a binding text label, // If we have no rebind overlay and no callback but we have a binding text label,
// temporarily set the binding text label to "<Waiting>". // temporarily set the binding text label to "<Waiting>".
if (rebindOverlay == null && mainBindingReferences.Text != null) if (_rebindOverlay == null && mainBindingReferences.Text != null)
mainBindingReferences.Text.Text = "<Waiting...>"; mainBindingReferences.Text.Text = "<Waiting...>";
rebindOperation.Start(); _rebindOperation.Start();
} }
protected void OnEnable() protected void OnEnable()
@ -87,17 +88,17 @@ namespace Canvases.Menu.Rebind
protected void OnDisable() protected void OnDisable()
{ {
rebindOperation?.Dispose(); _rebindOperation?.Dispose();
rebindOperation = null; _rebindOperation = null;
} }
private void UpdateActionLabel() private void UpdateActionLabel()
{ {
if (actionLabel == null) return; if (actionLabel == null) return;
string actionLabelText = action.bindings[mainBindingReferences.Index].isPartOfComposite string actionLabelText = _action.bindings[mainBindingReferences.Index].isPartOfComposite
? action.bindings[mainBindingReferences.Index].name.Capitalize() ? _action.bindings[mainBindingReferences.Index].name.Capitalize()
: action.name; : _action.name;
if (actionLabelText.Equals("Dash")) actionLabelText = "Tackle"; if (actionLabelText.Equals("Dash")) actionLabelText = "Tackle";
actionLabel.Text = actionLabelText; actionLabel.Text = actionLabelText;
@ -111,14 +112,14 @@ namespace Canvases.Menu.Rebind
string mainControlPath = string.Empty; string mainControlPath = string.Empty;
string altControlPath = string.Empty; string altControlPath = string.Empty;
if (action != null) if (_action != null)
{ {
if (mainBindingReferences.Index != -1) if (mainBindingReferences.Index != -1)
mainDisplayString = action.GetBindingDisplayString(mainBindingReferences.Index, mainDisplayString = _action.GetBindingDisplayString(mainBindingReferences.Index,
out deviceLayoutName, out deviceLayoutName,
out mainControlPath); out mainControlPath);
if (altBindingReferences.Index != -1) if (altBindingReferences.Index != -1)
altDisplayString = action.GetBindingDisplayString(altBindingReferences.Index, out _, altDisplayString = _action.GetBindingDisplayString(altBindingReferences.Index, out _,
out altControlPath); out altControlPath);
} }
@ -162,25 +163,25 @@ namespace Canvases.Menu.Rebind
private bool CheckDuplicateBindings(int bindingIndex) private bool CheckDuplicateBindings(int bindingIndex)
{ {
if (action == null) return false; if (_action == null) return false;
InputBinding newBinding = action.bindings[bindingIndex]; InputBinding newBinding = _action.bindings[bindingIndex];
if (newBinding.effectivePath.IsNullOrEmpty()) return false; if (newBinding.effectivePath.IsNullOrEmpty()) return false;
foreach (InputBinding binding in action.actionMap.bindings) foreach (InputBinding binding in _action.actionMap.bindings)
{ {
if (binding.action == newBinding.action) continue; if (binding.action == newBinding.action) continue;
if (binding.effectivePath == newBinding.effectivePath) return true; if (binding.effectivePath == newBinding.effectivePath) return true;
} }
if (!action.bindings[0].isComposite) return false; if (!_action.bindings[0].isComposite) return false;
for (int i = 1; i < action.bindings.Count; i++) for (int i = 1; i < _action.bindings.Count; i++)
{ {
if (i == bindingIndex) continue; if (i == bindingIndex) continue;
if (action.bindings[i].effectivePath == newBinding.effectivePath) if (_action.bindings[i].effectivePath == newBinding.effectivePath)
{ {
return true; return true;
} }
@ -194,8 +195,8 @@ namespace Canvases.Menu.Rebind
{ {
mainBindingReferences.Index = bindingIndex; mainBindingReferences.Index = bindingIndex;
altBindingReferences.Index = bindingIndex + 1; altBindingReferences.Index = bindingIndex + 1;
action = inputAction; _action = inputAction;
rebindOverlay = overlay; _rebindOverlay = overlay;
UpdateBindingUIEvent += onUpdateBindingUIEvent; UpdateBindingUIEvent += onUpdateBindingUIEvent;
UpdateActionLabel(); UpdateActionLabel();
UpdateBindingDisplay(); UpdateBindingDisplay();

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 64b55bf76536f164aaab1dd531664de6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +1,7 @@
using System; using System;
using Canvases.Components;
using UnityEngine; using UnityEngine;
namespace Canvases.Menu.Rebind namespace JohnsonUtils.Canvases
{ {
[Serializable] [Serializable]
public class RebindReferences public class RebindReferences

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2dcf8a5a568340a44885781e6143f5d1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,34 +1,37 @@
using System.Collections.Generic; using System.Collections.Generic;
using Canvases.Components; using JetBrains.Annotations;
using JohnsonUtils.Utilities;
using JohnsonUtils.Utilities.Icons;
using UnityEngine; using UnityEngine;
using UnityEngine.InputSystem; using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Utilities; using UnityEngine.InputSystem.Utilities;
using Utilities;
using Utilities.Extensions;
namespace Canvases.Menu.Rebind namespace JohnsonUtils.Canvases
{ {
public class RebindUI : MonoBehaviour public class RebindUI : MonoBehaviour
{ {
[SerializeField] private ImageUIComponent background;
[SerializeField] private GameObject rebindMenuContent; [SerializeField, UsedImplicitly] private ImageUIComponent background;
[SerializeField] private TextUIComponent currentControlScheme; [SerializeField, UsedImplicitly] private GameObject rebindMenuContent;
[SerializeField] private ButtonUIComponent resetAllButton; [SerializeField, UsedImplicitly] private TextUIComponent currentControlScheme;
[SerializeField] private RectTransform scrollRectContent; [SerializeField, UsedImplicitly] private ButtonUIComponent resetAllButton;
[SerializeField] private TextUIComponent rebindOverlayText; [SerializeField, UsedImplicitly] private RectTransform scrollRectContent;
[SerializeField] private RebindActionUI rebindPrefab; [SerializeField, UsedImplicitly] private TextUIComponent rebindOverlayText;
[SerializeField] private ButtonUIComponent applyButton; [SerializeField, UsedImplicitly] private RebindActionUI rebindPrefab;
[SerializeField, UsedImplicitly] private ButtonUIComponent applyButton;
private PlayerInputAction playerInputActionRef; //TODO ProjectInit replace this by your action map
private IInputActionCollection2 _playerInputActionRef;
private RebindActionUI firstButton; [UsedImplicitly] private RebindActionUI _firstButton;
private readonly List<RebindActionUI> rebindUIs = new List<RebindActionUI>(); private readonly List<RebindActionUI> _rebindUIs = new();
private bool isInitialized; private bool _isInitialized;
private void Start() private void Start()
{ {
// Bind to OnInputDeviceChanged //TODO ProjectInit Bind to OnInputDeviceChanged
Debug.LogWarning($"Didn't init Start method on {GetType()} on {name} ");
} }
private void OnEnable() private void OnEnable()
@ -43,7 +46,8 @@ namespace Canvases.Menu.Rebind
private void OnDestroy() private void OnDestroy()
{ {
// Unbind to OnInputDeviceChanged //TODO ProjectInit Unbind to OnInputDeviceChanged
Debug.LogWarning($"Didn't init OnDestroy method on {GetType()} on {name} ");
} }
private void OnApplyPressed() private void OnApplyPressed()
@ -52,10 +56,10 @@ namespace Canvases.Menu.Rebind
// Hide // Hide
} }
[UsedImplicitly]
private void OnResetAll() private void OnResetAll()
{ {
playerInputActionRef.RemoveAllBindingOverrides(); _playerInputActionRef.RemoveAllBindingOverrides();
UpdateAllRebindUI(); UpdateAllRebindUI();
// UpdateBindings // UpdateBindings
} }
@ -63,7 +67,7 @@ namespace Canvases.Menu.Rebind
private void AddBindingsButton(string deviceName) private void AddBindingsButton(string deviceName)
{ {
currentControlScheme.Text = $"< {deviceName.ToUpper()} >"; currentControlScheme.Text = $"< {deviceName.ToUpper()} >";
ReadOnlyArray<InputAction> inputActions = playerInputActionRef.Player.Get().actions; ReadOnlyArray<InputAction> inputActions = new (); //TODO ProjectInit Get the actions from the Action map
bool first = true; bool first = true;
foreach (var inputAction in inputActions) foreach (var inputAction in inputActions)
{ {
@ -78,12 +82,12 @@ namespace Canvases.Menu.Rebind
private void SpawnButton(InputAction inputAction, int mainBindingIndex, bool first) private void SpawnButton(InputAction inputAction, int mainBindingIndex, bool first)
{ {
RebindActionUI actionButton = Instantiate(rebindPrefab, scrollRectContent); RebindActionUI actionButton = Instantiate(rebindPrefab, scrollRectContent);
rebindUIs.Add(actionButton); _rebindUIs.Add(actionButton);
actionButton.name = $"Rebind UI for {inputAction.name}"; actionButton.name = $"Rebind UI for {inputAction.name}";
actionButton.Initialize(mainBindingIndex, inputAction, rebindOverlayText, OnUpdateBindingUIEvent); actionButton.Initialize(mainBindingIndex, inputAction, rebindOverlayText, OnUpdateBindingUIEvent);
if (first) if (first)
{ {
firstButton = actionButton; _firstButton = actionButton;
} }
} }
@ -95,15 +99,16 @@ namespace Canvases.Menu.Rebind
private void UpdateAllRebindUI() private void UpdateAllRebindUI()
{ {
foreach (RebindActionUI rebindActionUI in rebindUIs) foreach (RebindActionUI rebindActionUI in _rebindUIs)
{ {
rebindActionUI.UpdateBindingDisplay(false); rebindActionUI.UpdateBindingDisplay(false);
} }
} }
[UsedImplicitly]
private void OnInputDeviceChanged(string newDevice) private void OnInputDeviceChanged(string newDevice)
{ {
rebindUIs.Clear(); _rebindUIs.Clear();
scrollRectContent.DestroyChildren(); scrollRectContent.DestroyChildren();
AddBindingsButton(newDevice); AddBindingsButton(newDevice);
} }

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8dad699e20297a040b2b80c77a5b1bca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
JohnsonUtils/Common.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5d0141492d11e22478d4b5486f51fbd0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 683fe2cb49ca4070b175e6045de4e470
timeCreated: 1679073047

View File

@ -0,0 +1,11 @@
using Sirenix.OdinInspector;
using UnityEngine;
namespace JohnsonUtils.Common
{
[CreateAssetMenu(menuName = "Settings/Game Settings")]
public class GameSettings : ScriptableObject
{
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6663ab9aa38d41ada29802c63e8d1fa2
timeCreated: 1647204922

View File

@ -1,24 +1,27 @@
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using UnityEngine; using UnityEngine;
namespace Common namespace JohnsonUtils.Common
{ {
public class SettingsSystem : PersistentSingleton<SettingsSystem> public class SettingsSystem : PersistentSingleton<SettingsSystem>
{ {
private const string SETTINGS_FOLDER_PATH = "Settings"; private const string SETTINGS_FOLDER_PATH = "Settings";
[PublicAPI]
public static GameSettings GameSettings => Instance.GameSetting; public static GameSettings GameSettings => Instance.GameSetting;
private GameSettings gameSetting; private GameSettings _gameSetting;
private GameSettings GameSetting => gameSetting; private GameSettings GameSetting => _gameSetting;
protected override void Awake() protected override void Awake()
{ {
base.Awake(); base.Awake();
LoadSettings(out gameSetting); LoadSettings(out _gameSetting);
} }
[PublicAPI]
private void LoadSettings<T>(out T memberToInitialize) where T : ScriptableObject private void LoadSettings<T>(out T memberToInitialize) where T : ScriptableObject
{ {
T[] loadedSettingsList = Resources.LoadAll<T>(SETTINGS_FOLDER_PATH); T[] loadedSettingsList = Resources.LoadAll<T>(SETTINGS_FOLDER_PATH);
@ -32,6 +35,7 @@ namespace Common
memberToInitialize = loadedSettingsList.First(); memberToInitialize = loadedSettingsList.First();
} }
[PublicAPI]
private void LoadAllSettings<T>(out T[] memberToInitialize) where T : ScriptableObject private void LoadAllSettings<T>(out T[] memberToInitialize) where T : ScriptableObject
{ {
T[] loadedSettingsList = Resources.LoadAll<T>(SETTINGS_FOLDER_PATH); T[] loadedSettingsList = Resources.LoadAll<T>(SETTINGS_FOLDER_PATH);

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ac33069eef60cbf41bcf2290969baaf6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,13 +1,15 @@
using System; using System;
using JetBrains.Annotations;
using JohnsonUtils.Utilities;
using UnityEngine; using UnityEngine;
using Utilities.Extensions;
namespace Common namespace JohnsonUtils.Common
{ {
public abstract class AbstractSingleton<T> : MonoBehaviour where T : AbstractSingleton<T> public abstract class AbstractSingleton<T> : MonoBehaviour where T : AbstractSingleton<T>
{ {
protected static T SharedInstance; protected static T SharedInstance;
[PublicAPI]
public static bool HasInstance => SharedInstance != null; public static bool HasInstance => SharedInstance != null;
protected virtual void Awake() protected virtual void Awake()
@ -62,7 +64,7 @@ namespace Common
{ {
Debug.LogWarning($"New instance of type {typeof(T).Name} detected. " + Debug.LogWarning($"New instance of type {typeof(T).Name} detected. " +
"This new instance is becoming the default instance."); "This new instance is becoming the default instance.");
SharedInstance = (T) Convert.ChangeType(this, typeof(T));; SharedInstance = (T) Convert.ChangeType(this, typeof(T));
return; return;
} }
@ -83,6 +85,7 @@ namespace Common
/// </summary> /// </summary>
public abstract class PersistentSingleton<T> : AbstractSingleton<T> where T : PersistentSingleton<T> public abstract class PersistentSingleton<T> : AbstractSingleton<T> where T : PersistentSingleton<T>
{ {
[PublicAPI]
public static T Instance public static T Instance
{ {
get get
@ -92,6 +95,7 @@ namespace Common
} }
} }
[PublicAPI]
public static void CreateIfDoesNotExist() public static void CreateIfDoesNotExist()
{ {
if (!HasInstance && Application.isPlaying) if (!HasInstance && Application.isPlaying)

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9604fea7e06f5b049a9284f29fed926a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,6 +1,6 @@
using System; using System;
namespace Common namespace JohnsonUtils.Common
{ {
public class Timer public class Timer
{ {
@ -10,43 +10,43 @@ namespace Common
public float CurrentTime { get; private set; } public float CurrentTime { get; private set; }
private readonly float startingTime; private readonly float _startingTime;
private readonly bool isCountDown; private readonly bool _isCountDown;
private bool isEnabled; private bool _isEnabled;
public Timer(float startTime, bool countDown = true) public Timer(float startTime, bool countDown = true)
{ {
IsRunning = false; IsRunning = false;
isEnabled = true; _isEnabled = true;
startingTime = startTime; _startingTime = startTime;
isCountDown = countDown; _isCountDown = countDown;
Init(); Init();
} }
private void Init() private void Init()
{ {
CurrentTime = startingTime; CurrentTime = _startingTime;
} }
public void Tick(float dt) public void Tick(float dt)
{ {
if (!IsRunning || !isEnabled) return; if (!IsRunning || !_isEnabled) return;
CurrentTime += isCountDown ? -dt : dt; CurrentTime += _isCountDown ? -dt : dt;
if (CurrentTime < 0) if (CurrentTime < 0)
{ {
CurrentTime = 0; CurrentTime = 0;
IsRunning = false; IsRunning = false;
isEnabled = false; _isEnabled = false;
OnTimeOver?.Invoke(); OnTimeOver?.Invoke();
} }
} }
public void Reset() public void Reset()
{ {
isEnabled = true; _isEnabled = true;
CurrentTime = isCountDown ? startingTime : 0; CurrentTime = _isCountDown ? _startingTime : 0;
} }
public void Start() => IsRunning = true; public void Start() => IsRunning = true;
@ -54,7 +54,7 @@ namespace Common
public void Stop() public void Stop()
{ {
IsRunning = false; IsRunning = false;
isEnabled = false; _isEnabled = false;
CurrentTime = 0; CurrentTime = 0;
} }
} }

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0a63bf39f5084f244a0d173ffaa33830
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,45 @@
using JetBrains.Annotations;
using UnityEngine;
using UnityEngine.Events;
namespace JohnsonUtils.Common
{
public class TimerWrapper : MonoBehaviour
{
[PublicAPI] public UnityAction OnTimerOver;
[SerializeField, Min(0)] private float startTime;
[SerializeField] private bool countDown = true;
[SerializeField] private bool startOnAwake;
[SerializeField] private bool startOnStart;
private Timer _timer;
[PublicAPI] public bool IsRunning => _timer.IsRunning;
[PublicAPI] public float CurrentTime => _timer.CurrentTime;
private void Awake()
{
_timer = new Timer(startTime, countDown);
_timer.OnTimeOver += OnTimeOver;
if (startOnAwake) _timer.Start();
}
private void Start()
{
if (startOnStart) _timer.Start();
}
private void Update()
{
_timer.Tick(Time.deltaTime);
}
[PublicAPI] public void StartTimer() => _timer.Start();
[PublicAPI] public void PauseTimer() => _timer.Pause();
[PublicAPI] public void StopTimer() => _timer.Stop();
[PublicAPI] public void ResetTimer() => _timer.Reset();
private void OnTimeOver() => OnTimerOver?.Invoke();
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bd620e23d11c4614686cb5f542a4a465
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1c62f54d128b1614995abe5cb166e69f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b166f29acfae6f249968b2471f1bbbd7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -3,10 +3,10 @@ using System.IO;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
namespace SaveSystem namespace JohnsonUtils.SaveSystem
{ {
[CustomEditor(typeof(SaveManager), true)] [CustomEditor(typeof(SaveManager), true)]
public class SaveManagerInspector : Editor public class SaveManagerInspector : UnityEditor.Editor
{ {
public override void OnInspectorGUI() public override void OnInspectorGUI()
{ {

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8ae65abf022e1be4292f3e2dabfce042
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,6 +1,6 @@
using System; using System;
namespace SaveSystem namespace JohnsonUtils.SaveSystem
{ {
[Serializable] [Serializable]
public class GameData public class GameData

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 57b18c872a3211e40b79bb602e00f99b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,4 +1,4 @@
namespace SaveSystem namespace JohnsonUtils.SaveSystem
{ {
public interface ISaveData public interface ISaveData
{ {

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bf2bda9e88708e14eb87e377f412381b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,17 +1,19 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Core; using JetBrains.Annotations;
using JohnsonUtils.Common;
using UnityEngine; using UnityEngine;
using UnityEngine.Events; using UnityEngine.Events;
namespace SaveSystem namespace JohnsonUtils.SaveSystem
{ {
public class SaveManager : Singleton<SaveManager> public class SaveManager : Singleton<SaveManager>
{ {
[UsedImplicitly]
public static UnityAction<GameData> OnLoadCompleted; public static UnityAction<GameData> OnLoadCompleted;
private static readonly List<ISaveData> SaveDataList = new List<ISaveData>(); private static readonly List<ISaveData> SaveDataList = new ();
private GameData _saveGame; private GameData _saveGame;
private int _loadedGameNumber = -1; private int _loadedGameNumber = -1;
@ -34,7 +36,7 @@ namespace SaveSystem
string json = JsonUtility.ToJson(_saveGame); string json = JsonUtility.ToJson(_saveGame);
byte[] plainTextBytes = System.Text.Encoding.UTF8.GetBytes(json); byte[] plainTextBytes = System.Text.Encoding.UTF8.GetBytes(json);
string b64 = Convert.ToBase64String(plainTextBytes); string b64 = Convert.ToBase64String(plainTextBytes);
using StreamWriter sw = new StreamWriter($"saveData{saveNumber:00}.sgd"); using StreamWriter sw = new ($"saveData{saveNumber:00}.sgd");
sw.Write(b64); sw.Write(b64);
_loadedGameNumber = -1; _loadedGameNumber = -1;
} }
@ -46,7 +48,7 @@ namespace SaveSystem
saveData.Save(ref _saveGame); saveData.Save(ref _saveGame);
} }
string json = JsonUtility.ToJson(_saveGame); string json = JsonUtility.ToJson(_saveGame);
using StreamWriter sw = new StreamWriter($"saveData01.json"); using StreamWriter sw = new ($"saveData01.json");
sw.Write(json); sw.Write(json);
} }
@ -56,7 +58,7 @@ namespace SaveSystem
{ {
try try
{ {
using StreamReader sr = new StreamReader($"saveData{saveNumber:00}.sgd"); using StreamReader sr = new ($"saveData{saveNumber:00}.sgd");
string b64 = sr.ReadToEnd(); string b64 = sr.ReadToEnd();
byte[] plainTextBytes = Convert.FromBase64String(b64); byte[] plainTextBytes = Convert.FromBase64String(b64);
string json = System.Text.Encoding.UTF8.GetString(plainTextBytes); string json = System.Text.Encoding.UTF8.GetString(plainTextBytes);
@ -77,6 +79,7 @@ namespace SaveSystem
OnLoadCompleted?.Invoke(_saveGame); OnLoadCompleted?.Invoke(_saveGame);
} }
[PublicAPI]
public static void Register(ISaveData saveData) public static void Register(ISaveData saveData)
{ {
if (!SaveDataList.Contains(saveData)) if (!SaveDataList.Contains(saveData))
@ -84,7 +87,8 @@ namespace SaveSystem
SaveDataList.Add(saveData); SaveDataList.Add(saveData);
} }
} }
[PublicAPI]
public static void Unregister(ISaveData saveData) public static void Unregister(ISaveData saveData)
{ {
SaveDataList.Remove(saveData); SaveDataList.Remove(saveData);

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6a7057bb52fdff64086ec05f1083489f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fc748c629d04cd4498473f0ebd5fd372
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,14 +1,15 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using UnityEngine; using UnityEngine;
using Object = UnityEngine.Object; using Object = UnityEngine.Object;
namespace Utilities namespace JohnsonUtils.Utilities
{ {
public static class DontDestroyOnLoadUtils public static class DontDestroyOnLoadUtils
{ {
private static readonly List<GameObject> ManagedObjects = new List<GameObject>(); private static readonly List<GameObject> ManagedObjects = new ();
public static void Add(GameObject gameObject) public static void Add(GameObject gameObject)
{ {
@ -16,6 +17,7 @@ namespace Utilities
Object.DontDestroyOnLoad(gameObject); Object.DontDestroyOnLoad(gameObject);
} }
[PublicAPI]
public static void DestroyAll(Func<GameObject, bool> filter = null) public static void DestroyAll(Func<GameObject, bool> filter = null)
{ {
foreach (GameObject managedObject in ManagedObjects.ToList()) foreach (GameObject managedObject in ManagedObjects.ToList())

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8ea9ccf7d1dd3d445abb63da703379be
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 135a3c76938248c884cb0ce9c18de68c
timeCreated: 1679109633

View File

@ -0,0 +1,136 @@
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace JohnsonUtils.Utilities
{
/// <summary>
/// Scene auto loader.
/// </summary>
/// <description>
/// This class adds a File > Scene Autoload menu containing options to select
/// a "master scene" enable it to be auto-loaded when the user presses play
/// in the editor. When enabled, the selected scene will be loaded on play,
/// then the original scene will be reloaded on stop.
///
/// Based on an idea on this thread:
/// http://forum.unity3d.com/threads/157502-Executing-first-scene-in-build-settings-when-pressing-play-button-in-editor
/// </description>
[InitializeOnLoad]
public static class SceneAutoLoader
{
// Static constructor binds a playmode-changed callback.
// [InitializeOnLoad] above makes sure this gets executed.
static SceneAutoLoader()
{
EditorApplication.playModeStateChanged += OnPlayModeChanged;
}
// Menu items to select the "master" scene and control whether or not to load it.
[MenuItem("File/Scene Autoload/Select Master Scene...")]
private static void SelectMasterScene()
{
string masterScene = EditorUtility.OpenFilePanel("Select Master Scene", Application.dataPath, "unity");
masterScene = masterScene.Replace(Application.dataPath, "Assets"); //project relative instead of absolute path
if (!string.IsNullOrEmpty(masterScene))
{
MasterScene = masterScene;
LoadMasterOnPlay = true;
}
}
[MenuItem("File/Scene Autoload/Load Master On Play", true)]
private static bool ShowLoadMasterOnPlay()
{
return !LoadMasterOnPlay;
}
[MenuItem("File/Scene Autoload/Load Master On Play")]
private static void EnableLoadMasterOnPlay()
{
LoadMasterOnPlay = true;
}
[MenuItem("File/Scene Autoload/Don't Load Master On Play", true)]
private static bool ShowDontLoadMasterOnPlay()
{
return LoadMasterOnPlay;
}
[MenuItem("File/Scene Autoload/Don't Load Master On Play")]
private static void DisableLoadMasterOnPlay()
{
LoadMasterOnPlay = false;
}
// Play mode change callback handles the scene load/reload.
private static void OnPlayModeChanged(PlayModeStateChange state)
{
if (!LoadMasterOnPlay)
{
return;
}
if (!EditorApplication.isPlaying && EditorApplication.isPlayingOrWillChangePlaymode)
{
// User pressed play -- autoload master scene.
PreviousScene = SceneManager.GetActiveScene().path;
if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
try
{
EditorSceneManager.OpenScene(MasterScene);
}
catch
{
Debug.LogError($"error: scene not found: {MasterScene}");
EditorApplication.isPlaying = false;
}
}
else
{
// User cancelled the save operation -- cancel play as well.
EditorApplication.isPlaying = false;
}
}
// isPlaying check required because cannot OpenScene while playing
if (!EditorApplication.isPlaying && !EditorApplication.isPlayingOrWillChangePlaymode)
{
// User pressed stop -- reload previous scene.
try
{
EditorSceneManager.OpenScene(PreviousScene);
}
catch
{
Debug.LogError($"error: scene not found: {PreviousScene}");
}
}
}
// Properties are remembered as editor preferences.
private const string EDITOR_PREF_LOAD_MASTER_ON_PLAY = "SceneAutoLoader.LoadMasterOnPlay";
private const string EDITOR_PREF_MASTER_SCENE = "SceneAutoLoader.MasterScene";
private const string EDITOR_PREF_PREVIOUS_SCENE = "SceneAutoLoader.PreviousScene";
private static bool LoadMasterOnPlay
{
get => EditorPrefs.GetBool(EDITOR_PREF_LOAD_MASTER_ON_PLAY, false);
set => EditorPrefs.SetBool(EDITOR_PREF_LOAD_MASTER_ON_PLAY, value);
}
private static string MasterScene
{
get => EditorPrefs.GetString(EDITOR_PREF_MASTER_SCENE, "Master.unity");
set => EditorPrefs.SetString(EDITOR_PREF_MASTER_SCENE, value);
}
private static string PreviousScene
{
get => EditorPrefs.GetString(EDITOR_PREF_PREVIOUS_SCENE, SceneManager.GetActiveScene().path);
set => EditorPrefs.SetString(EDITOR_PREF_PREVIOUS_SCENE, value);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 33bc754a27011cb4dbcbb8ca2806c681
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bd5040a05d81fbe4d91cb7e4ca276a3d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -2,7 +2,7 @@
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
namespace Utilities.Extensions namespace JohnsonUtils.Utilities
{ {
public static class CollectionExtensions public static class CollectionExtensions
{ {

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b5fb94e75a817a546ae336e4f83bc091
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -3,7 +3,7 @@ using Fusion;
#endif #endif
using UnityEngine; using UnityEngine;
namespace Utilities.Extensions namespace JohnsonUtils.Utilities
{ {
public static class GameObjectExtensions public static class GameObjectExtensions
{ {

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 11c2e39b23f8fe0438c1c428ff35d31a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,7 +1,7 @@
using UnityEngine; using UnityEngine;
using UnityEngine.InputSystem; using UnityEngine.InputSystem;
namespace Utilities.Extensions namespace JohnsonUtils.Utilities
{ {
public static class InputActionExtensions public static class InputActionExtensions
{ {

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8242e3fda713f7d4e9221e2dc0c19f3c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,4 +1,4 @@
namespace Utilities.Extensions namespace JohnsonUtils.Utilities
{ {
public static class StringExtensions public static class StringExtensions
{ {

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5add9befbd2881544901a6f360eff0e3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,6 +1,6 @@
using UnityEngine; using UnityEngine;
namespace Utilities.Extensions namespace JohnsonUtils.Utilities
{ {
public static class TransformExtensions public static class TransformExtensions
{ {

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a9990d71fe137014da6d88ccc7f3fd79
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,6 +1,6 @@
using UnityEngine; using UnityEngine;
namespace Utilities.Extensions namespace JohnsonUtils.Utilities
{ {
public static class VectorExtensions public static class VectorExtensions
{ {

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bd30f74b9d046c343b219f71af36214e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,13 +1,14 @@
using System.Collections.Generic; using System.Collections.Generic;
using JetBrains.Annotations;
using UnityEngine; using UnityEngine;
namespace Utilities namespace JohnsonUtils.Utilities
{ {
public static class Helpers public static class Helpers
{ {
private static readonly Dictionary<float, WaitForSeconds> WaitDictionary = private static readonly Dictionary<float, WaitForSeconds> WaitDictionary = new();
new Dictionary<float, WaitForSeconds>();
[PublicAPI]
public static WaitForSeconds GetWait(float time) public static WaitForSeconds GetWait(float time)
{ {
if (WaitDictionary.TryGetValue(time, out var wait)) return wait; if (WaitDictionary.TryGetValue(time, out var wait)) return wait;

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 63f4821a0b83c2946a1030f57ca89855
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a61e6af0b88652a43b607e4e5c97eb91
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,11 +1,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Scriptables;
using UnityEngine; using UnityEngine;
using UnityEngine.InputSystem; using UnityEngine.InputSystem;
using static UnityEngine.InputSystem.InputSystem; using static UnityEngine.InputSystem.InputSystem;
namespace Utilities namespace JohnsonUtils.Utilities.Icons
{ {
public static class BindingsIconsUtil public static class BindingsIconsUtil
{ {
@ -15,8 +14,8 @@ namespace Utilities
private static void Init() private static void Init()
{ {
xbox = Resources.Load<GamepadIcons>("InputSystem/GamePadIcons_Xbox"); xbox = Resources.Load<GamepadIcons>("InputSystem/GamepadIcons_Xbox");
ps4 = Resources.Load<GamepadIcons>("InputSystem/GamePadIcons_PS"); ps4 = Resources.Load<GamepadIcons>("InputSystem/GamepadIcons_PS");
mouseKeyboard = Resources.Load<MouseKeyboardIcons>("InputSystem/MouseKeyboardIcons"); mouseKeyboard = Resources.Load<MouseKeyboardIcons>("InputSystem/MouseKeyboardIcons");
} }

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f226afe07acb8a748a642771fd14b4c0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,57 @@
using UnityEngine;
namespace JohnsonUtils.Utilities.Icons
{
[CreateAssetMenu(fileName = "GamepadIcons_", menuName = "AssetPack/GamePad Icons", order = 0)]
public class GamepadIcons : ScriptableObject
{
public Sprite ButtonEast;
public Sprite ButtonNorth;
public Sprite ButtonSouth;
public Sprite ButtonWest;
public Sprite Dpad;
public Sprite DpadUp;
public Sprite DpadDown;
public Sprite DpadLeft;
public Sprite DpadRight;
public Sprite LeftShoulder;
public Sprite LeftStick;
public Sprite LeftTrigger;
public Sprite RightShoulder;
public Sprite RightStick;
public Sprite RightTrigger;
public Sprite SelectButton;
public Sprite StartButton;
public Sprite LeftStickPress;
public Sprite RightStickPress;
public Sprite GetSprite(string controlPath)
{
// From the input system, we get the path of the control on device. So we can just
// map from that to the sprites we have for gamepads.
return controlPath switch
{
"buttonSouth" => ButtonSouth,
"buttonNorth" => ButtonNorth,
"buttonEast" => ButtonEast,
"buttonWest" => ButtonWest,
"start" => StartButton,
"select" => SelectButton,
"leftTrigger" => LeftTrigger,
"rightTrigger" => RightTrigger,
"leftShoulder" => LeftShoulder,
"rightShoulder" => RightShoulder,
"dpad" => Dpad,
"dpad/up" => DpadUp,
"dpad/down" => DpadDown,
"dpad/left" => DpadLeft,
"dpad/right" => DpadRight,
"leftStick" => LeftStick,
"rightStick" => RightStick,
"leftStickPress" => LeftStickPress,
"rightStickPress" => RightStickPress,
_ => null
};
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 05c8d9a76dc13a34db3c143d9f20b866
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,186 @@
using UnityEngine;
namespace JohnsonUtils.Utilities.Icons
{
[CreateAssetMenu(fileName = "MouseKeyboardIcons_", menuName = "AssetPack/MouseKeyboard Icons", order = 0)]
public class MouseKeyboardIcons : ScriptableObject
{
public Sprite Zero;
public Sprite One;
public Sprite Two;
public Sprite Three;
public Sprite Four;
public Sprite Five;
public Sprite Six;
public Sprite Seven;
public Sprite Eight;
public Sprite Nine;
public Sprite Alt;
public Sprite ArrowDown;
public Sprite ArrowLeft;
public Sprite ArrowRight;
public Sprite ArrowUp;
public Sprite Asterisk;
public Sprite Backspace;
public Sprite Ctrl;
public Sprite Delete;
public Sprite End;
public Sprite Enter;
public Sprite Escape;
public Sprite F1;
public Sprite F2;
public Sprite F3;
public Sprite F4;
public Sprite F5;
public Sprite F6;
public Sprite F7;
public Sprite F8;
public Sprite F9;
public Sprite F10;
public Sprite F11;
public Sprite F12;
public Sprite Home;
public Sprite LetterA;
public Sprite LetterB;
public Sprite LetterC;
public Sprite LetterD;
public Sprite LetterE;
public Sprite LetterF;
public Sprite LetterG;
public Sprite LetterH;
public Sprite LetterI;
public Sprite LetterJ;
public Sprite LetterK;
public Sprite LetterL;
public Sprite LetterM;
public Sprite LetterN;
public Sprite LetterO;
public Sprite LetterP;
public Sprite LetterQ;
public Sprite LetterR;
public Sprite LetterS;
public Sprite LetterT;
public Sprite LetterU;
public Sprite LetterV;
public Sprite LetterW;
public Sprite LetterX;
public Sprite LetterY;
public Sprite LetterZ;
public Sprite MarkLeft;
public Sprite MarkRight;
public Sprite Minus;
public Sprite Plus;
public Sprite MouseLeft;
public Sprite MouseMiddle;
public Sprite MouseRight;
public Sprite MouseNone;
public Sprite PageDown;
public Sprite PageUp;
public Sprite QuestionMark;
public Sprite Quote;
public Sprite Semicolon;
public Sprite Shift;
public Sprite Slash;
public Sprite Space;
public Sprite Tab;
public Sprite Tilda;
public Sprite GetSprite(string controlPath)
{
// From the input system, we get the path of the control on device. So we can just
// map from that to the sprites we have for gamepads.
return controlPath.ToLower() switch
{
"0" => Zero,
"1" => One,
"2" => Two,
"3" => Three,
"4" => Four,
"5" => Five,
"6" => Six,
"7" => Seven,
"8" => Eight,
"9" => Nine,
"alt" => Alt,
"leftalt" => Alt,
"rightalt" => Alt,
"downarrow" => ArrowDown,
"leftarrow" => ArrowLeft,
"rightarrow" => ArrowRight,
"uparrow" => ArrowUp,
"*" => Asterisk,
"backspace" => Backspace,
"ctrl" => Ctrl,
"leftctrl" => Ctrl,
"rightctrl" => Ctrl,
"delete" => Delete,
"end" => End,
"enter" => Enter,
"escape" => Escape,
"f1" => F1,
"f2" => F2,
"f3" => F3,
"f4" => F4,
"f5" => F5,
"f6" => F6,
"f7" => F7,
"f8" => F8,
"f9" => F9,
"f10" => F10,
"f11" => F11,
"f12" => F12,
"home" => Home,
"a" => LetterA,
"b" => LetterB,
"c" => LetterC,
"d" => LetterD,
"e" => LetterE,
"f" => LetterF,
"g" => LetterG,
"h" => LetterH,
"i" => LetterI,
"j" => LetterJ,
"k" => LetterK,
"l" => LetterL,
"m" => LetterM,
"n" => LetterN,
"o" => LetterO,
"p" => LetterP,
"q" => LetterQ,
"r" => LetterR,
"s" => LetterS,
"t" => LetterT,
"u" => LetterU,
"v" => LetterV,
"w" => LetterW,
"x" => LetterX,
"y" => LetterY,
"z" => LetterZ,
"[" => MarkLeft,
"]" => MarkRight,
"-" => Minus,
"+" => Plus,
"leftmouse" => MouseLeft,
"middlemouse" => MouseMiddle,
"rightmouse" => MouseRight,
"leftbutton" => MouseLeft,
"middlebutton" => MouseMiddle,
"rightbutton" => MouseRight,
"press" => MouseNone,
"pagedown" => PageDown,
"pageup" => PageUp,
"?" => QuestionMark,
"\"" => Quote,
";" => Semicolon,
"shift" => Shift,
"leftshift" => Shift,
"rightshift" => Shift,
"/" => Slash,
"space" => Space,
"tab" => Tab,
"~" => Tilda,
_ => null
};
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 230adb9d1f61b4342af8190654725fa7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -2,23 +2,23 @@
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
namespace Util namespace JohnsonUtils.Utilities
{ {
[Serializable] [Serializable]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
{ {
[SerializeField] private List<TKey> _keys = new List<TKey>(); [SerializeField] private List<TKey> keys = new ();
[SerializeField] private List<TValue> _values = new List<TValue>(); [SerializeField] private List<TValue> values = new ();
public void OnBeforeSerialize() public void OnBeforeSerialize()
{ {
_keys.Clear(); keys.Clear();
_values.Clear(); values.Clear();
foreach (KeyValuePair<TKey,TValue> pair in this) foreach (KeyValuePair<TKey,TValue> pair in this)
{ {
_keys.Add(pair.Key); keys.Add(pair.Key);
_values.Add(pair.Value); values.Add(pair.Value);
} }
} }
@ -26,16 +26,16 @@ namespace Util
{ {
Clear(); Clear();
if (_keys.Count != _values.Count) if (keys.Count != values.Count)
{ {
throw new Exception( throw new Exception(
$"There are {_keys.Count} keys and {_values.Count} values after deserialization." + $"There are {keys.Count} keys and {values.Count} values after deserialization." +
" Make sure that both key and value types are serializable."); " Make sure that both key and value types are serializable.");
} }
for (int i = 0; i < _keys.Count; ++i) for (int i = 0; i < keys.Count; ++i)
{ {
Add(_keys[i], _values[i]); Add(keys[i], values[i]);
} }
} }
} }

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: de5e88e7664d4b04fa189a30e345f404
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,150 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeEditing/Unity/AdditionalFileLayout/Pattern/@EntryValue">&lt;Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"
xmlns:unity="urn:schemas-jetbrains-com:member-reordering-patterns-unity"&gt;
&lt;!-- Pattern to match classes used by Unity that contain serialised fields and event
function methods. Based on the standard "Default Pattern", this will also order
event functions before normal methods, and does not reorder serialised fields,
as this order is reflected in the Unity editor's Inspector --&gt;
&lt;TypePattern DisplayName="Unity classes" Priority="100"&gt;
&lt;TypePattern.Match&gt;
&lt;unity:SerializableClass /&gt;
&lt;/TypePattern.Match&gt;
&lt;Entry DisplayName="Public Delegates" Priority="100"&gt;
&lt;Entry.Match&gt;
&lt;And&gt;
&lt;Access Is="Public" /&gt;
&lt;Kind Is="Delegate" /&gt;
&lt;/And&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Name /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="Public Enums" Priority="100"&gt;
&lt;Entry.Match&gt;
&lt;And&gt;
&lt;Access Is="Public" /&gt;
&lt;Kind Is="Enum" /&gt;
&lt;/And&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Name /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="Static Fields and Constants"&gt;
&lt;Entry.Match&gt;
&lt;Or&gt;
&lt;Kind Is="Constant" /&gt;
&lt;And&gt;
&lt;Kind Is="Field" /&gt;
&lt;Static /&gt;
&lt;/And&gt;
&lt;/Or&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Kind&gt;
&lt;Kind.Order&gt;
&lt;DeclarationKind&gt;Constant&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Field&lt;/DeclarationKind&gt;
&lt;/Kind.Order&gt;
&lt;/Kind&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="Serialized Fields"&gt;
&lt;Entry.Match&gt;
&lt;unity:SerializedField /&gt;
&lt;/Entry.Match&gt;
&lt;!-- No sorting --&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="Non-serialised Fields"&gt;
&lt;Entry.Match&gt;
&lt;And&gt;
&lt;Kind Is="Field" /&gt;
&lt;Not&gt;
&lt;unity:SerializedField /&gt;
&lt;/Not&gt;
&lt;/And&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Readonly /&gt;
&lt;Name /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="Constructors"&gt;
&lt;Entry.Match&gt;
&lt;Kind Is="Constructor" /&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Static/&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="Properties, Indexers"&gt;
&lt;Entry.Match&gt;
&lt;Or&gt;
&lt;Kind Is="Property" /&gt;
&lt;Kind Is="Indexer" /&gt;
&lt;/Or&gt;
&lt;/Entry.Match&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="Event Functions"&gt;
&lt;Entry.Match&gt;
&lt;unity:EventFunction /&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;!-- Prioritises common event functions. For alphabetical, replace with &lt;Name /&gt; --&gt;
&lt;unity:EventFunctionName /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="Interface Implementations" Priority="100"&gt;
&lt;Entry.Match&gt;
&lt;And&gt;
&lt;Kind Is="Member" /&gt;
&lt;ImplementsInterface /&gt;
&lt;/And&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;ImplementsInterface Immediate="true" /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="All other members" /&gt;
&lt;Entry DisplayName="Nested Types"&gt;
&lt;Entry.Match&gt;
&lt;Kind Is="Type" /&gt;
&lt;/Entry.Match&gt;
&lt;/Entry&gt;
&lt;/TypePattern&gt;
&lt;/Patterns&gt;
</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=5f0fdb63_002Dc892_002D4d2c_002D9324_002D15c80b22a7ef/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Instance" AccessRightKinds="Public" Description="Unity serialized field"&gt;&lt;ElementKinds&gt;&lt;Kind Name="UNITY_SERIALISED_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=5f0fdb63_002Dc892_002D4d2c_002D9324_002D15c80b22a7ef/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Unity serialized field"&gt;&lt;ElementKinds&gt;&lt;Kind Name="UNITY_SERIALISED_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Despawn/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Despawned/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Interacter/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Interruptible/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Rebinded/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Scriptables/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unrebindable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Verticality/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=wwise/@EntryIndexedValue">True</s:Boolean>
</wpf:ResourceDictionary>

8
Plugins/Sirenix.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6383ca44913a0d345a222149fef5d148
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c30fee7fb69eba342846aaf23d0c168a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More