diff --git a/README.md b/README.md index c45a3ab..cb0ba62 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ This package contains simple tools to use in your project. -This package will be updated once I find another useful tool or someone suggest me one. - ## Features - **AudioManager** with Play, Pause and most of the other basic things, as well as some effects like FadeIn or FadeOut. @@ -12,6 +10,8 @@ This package will be updated once I find another useful tool or someone suggest - Basic menu with **music and SFX sliders** as well as **resolution and quality dropdowns.** - An **object pooler** with the ability to create pools with an undetermined size. - A basic **scene manager** with a loading screen with progress bar. +- A simple **timer** that allows you to easily create clocks, countdowns and stopwatches with TextMeshPro +- An **auto-save** feature to reduce the chances of loosing data on crashes. All of that comes with some editor menu items for creating all of that as fast as possible. @@ -33,13 +33,16 @@ Download latest package from the Release section Import SimpleTools.unitypackage ## Usage -### AudioManager +### **AudioManager** ```csharp +using SimpleTools.AudioManager; + AudioManager.instance.Play("Name"); //Plays the sound with that name AudioManager.instance.Play("Name", 1f); //Starts playing the sound "Name" in 1 second AudioManager.instance.PlayOneShot("Name"); //Plays one shot of that sound (Useful for repeated sounds) AudioManager.instance.PlayWithIntro("Intro", "Loop"); //Plays the intro and then the loop +AudioManager.instance.PlayRandomSound("Name1", "Name2", "Name3"); // Plays one shot of a random sound AudioManager.instance.Pause("Name"); //Pauses the sound AudioManager.instance.UnPause("Name"); //Unpauses the sound @@ -57,11 +60,13 @@ AudioManager.instance.FadeMutedIn("Name", 1f); //Fade In a muted sound with a sp AudioManager.instance.FadeMutedOut("Name", 1f); //Fade Out a sound without stopping it ``` -### ObjectPooler +### **ObjectPooler** The SpawnFromPool function always return a GameObject ```csharp +using SimpleTools.ObjectPooler; + Pool pool; //The pool scriptable object goes here Pooler.CreatePools(pool); //Create the pool, without creating it you cannot spawn it Pool[] pools; @@ -76,29 +81,50 @@ Pooler.SpawnFromPool("Name", Vector3.zero, transform, true); //Spawn into a spec Pooler.SpawnFromPool("Name", Vector3.zero, Quaternion.identity, transform, true); //Spawn into a specific position, rotation, parent and instantiate in worldSpace or not ``` -### Dialogue System +### **Dialogue System** The Dialogue function returns a bool (true if it's talking, false if it has ended) ```csharp +using SimpleTools.DialogueSystem; + Dialogue dialogue; //The dialogue scriptable object goes here -DialogueSystem.instance.Dialogue(dialogue); //Start/Continue the dialogue +DialogueManager.instance.Dialogue(dialogue); //Start/Continue the dialogue +DialogueManager.instance.Dialogue(dialogue, "Sound1", "Sound2"); //Start/Continue the dialogue with a random set of sounds for the text reveal ``` -### SceneManager +Text commands: + +``` + --> Sets font color within tags + --> Sets font size within tags + --> Draws a sprite from the TextMeshPro + --> Pauses during a period of time + --> Reproduces an animation + --> Changes reveal speed + --> Plays a sound effect + --> Fades a music out + --> Fades a music in +``` + +### **SceneManager** ```csharp +using SimpleTools.SceneManagement; + Loader.Load(0); //Loads a scene with a specific build index Loader.Load("Scene"); //Loads a scene with a specific name ``` -### ScreenShake +### **ScreenShake** ```csharp +using SimpleTools.Cinemachine; + ScreenShake.Shake(1f, .25f); //Shakes the camera with an intensity and duration ``` -### Timer +### **Timer** ```csharp using SimpleTools.Timer; @@ -116,7 +142,11 @@ timer.ResetTimer(); //Pause and sets the time to the default one timer.Restart(); //Restarts the timer ``` -### Editor +### **Auto-save** + +To enable auto-save you have access the menu from the top bar, *Simple Tools>Auto Save Configuration.* You can auto-save every several minutes or auto-save every time you enter play mode. + +### **Editor** You can easily set up some things by right clicking in your Project Tab and then selecting Tools and clicking on the one you want to create. diff --git a/Tools/AudioManager/AudioManager.cs b/Tools/AudioManager/AudioManager.cs index 4b6c3f5..56b4dd6 100644 --- a/Tools/AudioManager/AudioManager.cs +++ b/Tools/AudioManager/AudioManager.cs @@ -2,261 +2,291 @@ using UnityEngine; using System; -public class AudioManager : MonoBehaviour{ +namespace SimpleTools.AudioManager { + public class AudioManager : MonoBehaviour { - public static AudioManager instance; + public static AudioManager instance; - [SerializeField] Sounds soundList = default; + [SerializeField] Sounds soundList = default; - void Awake(){ - if(instance == null){ - instance = this; - }else{ - Destroy(gameObject); - return; - } - DontDestroyOnLoad(gameObject); + void Awake() { + if (instance == null) { + instance = this; + } else { + Destroy(gameObject); + return; + } + DontDestroyOnLoad(gameObject); - foreach(Sounds.List s in soundList.sounds){ - if(string.IsNullOrEmpty(s.name) || string.IsNullOrWhiteSpace(s.name)){ - Debug.LogWarning("The name one sound is empty"); - continue; - } + foreach (Sounds.List s in soundList.sounds) { + if (string.IsNullOrEmpty(s.name) || string.IsNullOrWhiteSpace(s.name)) { + Debug.LogWarning("The name one sound is empty"); + continue; + } - GameObject sound = new GameObject(s.name); - sound.transform.parent = transform; - s.source = sound.AddComponent(); + GameObject sound = new GameObject(s.name); + sound.transform.parent = transform; + s.source = sound.AddComponent(); - if(soundList.mainMixer && soundList.sfxMixer){ - if (s.type == Sounds.List.Type.Music) - s.source.outputAudioMixerGroup = soundList.mainMixer; - else - s.source.outputAudioMixerGroup = soundList.sfxMixer; - } + if (soundList.mainMixer && soundList.sfxMixer) { + if (s.type == Sounds.List.Type.Music) + s.source.outputAudioMixerGroup = soundList.mainMixer; + else + s.source.outputAudioMixerGroup = soundList.sfxMixer; + } - s.source.clip = s.clip; + s.source.clip = s.clip; - s.source.volume = s.volume; - s.source.pitch = s.pitch; - s.source.loop = s.loop; - } - } + s.source.volume = s.volume; + s.source.pitch = s.pitch; + s.source.loop = s.loop; + } + } - #region Play - /// Use this to play a sound with a specific name - /// It has to be in the Sound asset referenced in the AudioManager instance - /// - public void Play(string name){ - Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); - if(s == null){ - Debug.LogWarning("Sound: " + name + " not found!"); - return; - } - s.source.pitch = s.RandomPitch; - s.source.volume = s.RandomVolume; - s.source.Play(); - } - /// Use this to play a sound with a specific name and with a certain delay - /// It has to be in the Sound asset referenced in the AudioManager instance - /// - public void Play(string name, float delay){ - Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); - if (s == null){ - Debug.LogWarning("Sound: " + name + " not found!"); - return; - } - s.source.pitch = s.RandomPitch; - s.source.volume = s.RandomVolume; - s.source.PlayDelayed(delay); - } - /// Use this to play one shot of a sound with a specific name - /// It has to be in the Sound asset referenced in the AudioManager instance - /// - public void PlayOneShot(string name){ - Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); - if (s == null){ - Debug.LogWarning("Sound: " + name + " not found!"); - return; - } - s.source.pitch = s.RandomPitch; - s.source.volume = s.RandomVolume; - s.source.PlayOneShot(s.clip); - } - /// Use this to play an intro song and then start playing the song loop - /// It has to be in the Sound asset referenced in the AudioManager instance - /// - public void PlayWithIntro(string intro, string song){ - Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == intro); - if (s == null){ - Debug.LogWarning("Sound: " + intro + " not found!"); - return; - } - s.source.pitch = s.RandomPitch; - s.source.volume = s.RandomVolume; - s.source.Play(); + #region Play + /// Use this to play a sound with a specific name + /// It has to be in the Sound asset referenced in the AudioManager instance + /// + /// The name of the sound + public void Play(string name) { + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null) { + Debug.LogWarning("Sound: " + name + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = s.RandomVolume; + s.source.Play(); + } + /// Use this to play a sound with a specific name and with a certain delay + /// It has to be in the Sound asset referenced in the AudioManager instance + /// + /// The name of the sound + /// The delay in seconds + public void Play(string name, float delay) { + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null) { + Debug.LogWarning("Sound: " + name + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = s.RandomVolume; + s.source.PlayDelayed(delay); + } + /// Use this to play one shot of a sound with a specific name + /// It has to be in the Sound asset referenced in the AudioManager instance + /// + /// The name of the sound + public void PlayOneShot(string name) { + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null) { + Debug.LogWarning("Sound: " + name + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = s.RandomVolume; + s.source.PlayOneShot(s.clip); + } + /// Use this to play an intro song and then start playing the song loop + /// It has to be in the Sound asset referenced in the AudioManager instance + /// + /// The name of the intro song + /// The name of the song loop + public void PlayWithIntro(string intro, string song) { + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == intro); + if (s == null) { + Debug.LogWarning("Sound: " + intro + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = s.RandomVolume; + s.source.Play(); - float introDuration = s.clip.length; - Play(song, introDuration); - } - #endregion - #region Pause - /// Use this to pause a sound with a specific name - /// It has to be in the Sound asset referenced in the AudioManager instance - /// - public void Pause(string name){ - Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); - if (s == null){ - Debug.LogWarning("Sound: " + name + " not found!"); - return; - } - s.source.pitch = s.RandomPitch; - s.source.volume = s.RandomVolume; - s.source.Pause(); - } - /// Use this to unpause a sound with a specific name - /// It has to be in the Sound asset referenced in the AudioManager instance - /// - public void UnPause(string name){ - Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); - if (s == null){ - Debug.LogWarning("Sound: " + name + " not found!"); - return; - } - s.source.pitch = s.RandomPitch; - s.source.volume = s.RandomVolume; - s.source.UnPause(); - } - #endregion - #region Stop - /// Use this to stop a sound with a specific name - /// It has to be in the Sound asset referenced in the AudioManager instance - /// - public void Stop(string name){ - Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); - if (s == null){ - Debug.LogWarning("Sound: " + name + " not found!"); - return; - } - s.source.pitch = s.RandomPitch; - s.source.volume = s.RandomVolume; - s.source.Stop(); - } - /// Use this to stop all the sounds - /// It has to be in the Sound asset referenced in the AudioManager instance - /// - public void StopAll(){ - foreach (Sounds.List s in soundList.sounds){ - if (s.source){ - s.source.Stop(); - } - } - } - #endregion - /// This function returns the AudioSource that contains a specific sound - /// It has to be in the Sound asset referenced in the AudioManager instance - /// - public AudioSource GetSource(string name){ - Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); - if (s == null){ - Debug.LogWarning("Sound: " + name + " not found!"); - return null; - } - return s.source; - } - #region Fades - /// Use this to start playing a sound with a fade in - /// It has to be in the Sound asset referenced in the AudioManager instance - /// - public void FadeIn(string name, float duration){ - StartCoroutine(FadeInCoroutine(name, duration)); - } - IEnumerator FadeInCoroutine(string name, float fadeTime){ - AudioSource audioSource = GetSource(name); - if (audioSource != null && !audioSource.isPlaying){ - float volume = audioSource.volume; - audioSource.volume = 0; - audioSource.Play(); - while (audioSource.volume < volume){ - audioSource.volume += Time.deltaTime / fadeTime; - yield return null; - } + float introDuration = s.clip.length; + Play(song, introDuration); + } + /// Use this to play one shot of a random sound within a list + /// They have to be in the Sound asset referenced in the AudioManager instance + /// + /// The names of the sounds + public void PlayRandomSound(params string[] names) { + int random = UnityEngine.Random.Range(0, names.Length); + PlayOneShot(names[random]); + } + #endregion + #region Pause + /// Use this to pause a sound with a specific name + /// It has to be in the Sound asset referenced in the AudioManager instance + /// + /// The name of the sound + public void Pause(string name) { + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null) { + Debug.LogWarning("Sound: " + name + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = s.RandomVolume; + s.source.Pause(); + } + /// Use this to unpause a sound with a specific name + /// It has to be in the Sound asset referenced in the AudioManager instance + /// + /// The name of the sound + public void UnPause(string name) { + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null) { + Debug.LogWarning("Sound: " + name + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = s.RandomVolume; + s.source.UnPause(); + } + #endregion + #region Stop + /// Use this to stop a sound with a specific name + /// It has to be in the Sound asset referenced in the AudioManager instance + /// + /// The name of the sound + public void Stop(string name) { + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null) { + Debug.LogWarning("Sound: " + name + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = s.RandomVolume; + s.source.Stop(); + } + /// Use this to stop all the sounds + /// It has to be in the Sound asset referenced in the AudioManager instance + /// + public void StopAll() { + foreach (Sounds.List s in soundList.sounds) { + if (s.source) { + s.source.Stop(); + } + } + } + #endregion + /// This function returns the AudioSource that contains a specific sound + /// It has to be in the Sound asset referenced in the AudioManager instance + /// + /// The name of the sound + /// The AudioSource in the scene + public AudioSource GetSource(string name) { + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null) { + Debug.LogWarning("Sound: " + name + " not found!"); + return null; + } + return s.source; + } + #region Fades + /// Use this to start playing a sound with a fade in + /// It has to be in the Sound asset referenced in the AudioManager instance + /// + /// The name of the sound + /// The duration of the fade in + public void FadeIn(string name, float duration) { + StartCoroutine(FadeInCoroutine(name, duration)); + } + IEnumerator FadeInCoroutine(string name, float fadeTime) { + AudioSource audioSource = GetSource(name); + if (audioSource != null && !audioSource.isPlaying) { + float volume = audioSource.volume; + audioSource.volume = 0; + audioSource.Play(); + while (audioSource.volume < volume) { + audioSource.volume += Time.deltaTime / fadeTime; + yield return null; + } - audioSource.volume = volume; - } - } - /// Use this to stop playing a sound with a fade out - /// It has to be in the Sound asset referenced in the AudioManager instance - /// - public void FadeOut(string name, float duration){ - StartCoroutine(FadeOutCoroutine(name, duration)); - } - IEnumerator FadeOutCoroutine(string name, float fadeTime){ - AudioSource audioSource = GetSource(name); + audioSource.volume = volume; + } + } + /// Use this to stop playing a sound with a fade out + /// It has to be in the Sound asset referenced in the AudioManager instance + /// + /// The name of the sound + /// The duration of the fade out + public void FadeOut(string name, float duration) { + StartCoroutine(FadeOutCoroutine(name, duration)); + } + IEnumerator FadeOutCoroutine(string name, float fadeTime) { + AudioSource audioSource = GetSource(name); - if (audioSource && audioSource.isPlaying){ - float startVolume = audioSource.volume; + if (audioSource && audioSource.isPlaying) { + float startVolume = audioSource.volume; - while (audioSource.volume > 0){ - audioSource.volume -= startVolume * Time.deltaTime / fadeTime; - yield return null; - } + while (audioSource.volume > 0) { + audioSource.volume -= startVolume * Time.deltaTime / fadeTime; + yield return null; + } - audioSource.Stop(); - audioSource.volume = startVolume; - } - } + audioSource.Stop(); + audioSource.volume = startVolume; + } + } - /// Use this to start playing a sound muted - /// It has to be in the Sound asset referenced in the AudioManager instance - /// - public void PlayMuted(string name){ - Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); - if (s == null){ - Debug.LogWarning("Sound: " + name + " not found!"); - return; - } - s.source.pitch = s.RandomPitch; - s.source.volume = 0f; - s.source.Play(); - } - /// Use this to fade in a sound that is currently muted - /// It has to be in the Sound asset referenced in the AudioManager instance - /// WARNING: If the PlayMuted hasn't been called before, this function won't work - /// - public void FadeMutedIn(string name, float duration){ - StartCoroutine(FadeMutedInCoroutine(name, duration)); - } - IEnumerator FadeMutedInCoroutine(string name, float fadeTime){ - Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); - if (s == null){ - Debug.LogWarning("Sound: " + name + " not found!"); - yield break; - } + /// Use this to start playing a sound muted + /// It has to be in the Sound asset referenced in the AudioManager instance + /// + /// The name of the sound + public void PlayMuted(string name) { + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null) { + Debug.LogWarning("Sound: " + name + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = 0f; + s.source.Play(); + } + /// Use this to fade in a sound that is currently muted + /// It has to be in the Sound asset referenced in the AudioManager instance + /// WARNING: If the PlayMuted hasn't been called before, this function won't work + /// + /// The name of the sound + /// The duration of the fade in + public void FadeMutedIn(string name, float duration) { + StartCoroutine(FadeMutedInCoroutine(name, duration)); + } + IEnumerator FadeMutedInCoroutine(string name, float fadeTime) { + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null) { + Debug.LogWarning("Sound: " + name + " not found!"); + yield break; + } - while (s.source.volume < s.volume){ - s.source.volume += Time.deltaTime / fadeTime; - yield return null; - } - s.source.volume = s.volume; - } - /// Use this to fade out a sound and keep playing that muted - /// It has to be in the Sound asset referenced in the AudioManager instance - /// - public void FadeMutedOut(string name, float duration){ - StartCoroutine(FadeMutedOutCoroutine(name, duration)); - } - IEnumerator FadeMutedOutCoroutine(string name, float fadeTime){ - Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); - if (s == null){ - Debug.LogWarning("Sound: " + name + " not found!"); - yield break; - } + while (s.source.volume < s.volume) { + s.source.volume += Time.deltaTime / fadeTime; + yield return null; + } + s.source.volume = s.volume; + } + /// Use this to fade out a sound and keep playing that muted + /// It has to be in the Sound asset referenced in the AudioManager instance + /// + /// The name of the sound + /// The duration of the fade out + public void FadeMutedOut(string name, float duration) { + StartCoroutine(FadeMutedOutCoroutine(name, duration)); + } + IEnumerator FadeMutedOutCoroutine(string name, float fadeTime) { + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null) { + Debug.LogWarning("Sound: " + name + " not found!"); + yield break; + } - while (s.source.volume > 0){ - s.source.volume -= Time.deltaTime / fadeTime; - yield return null; - } - s.source.volume = 0; - } - #endregion -} + while (s.source.volume > 0) { + s.source.volume -= Time.deltaTime / fadeTime; + yield return null; + } + s.source.volume = 0; + } + #endregion + } +} \ No newline at end of file diff --git a/Tools/AudioManager/Sounds.cs b/Tools/AudioManager/Sounds.cs index 9f9a5e4..35e2dd0 100644 --- a/Tools/AudioManager/Sounds.cs +++ b/Tools/AudioManager/Sounds.cs @@ -1,50 +1,53 @@ using UnityEngine; using UnityEngine.Audio; -[CreateAssetMenu(fileName = "Sounds", menuName = "Simple Tools/Sounds", order = 11)] -public class Sounds : ScriptableObject{ +namespace SimpleTools.AudioManager { + [CreateAssetMenu(fileName = "Sounds", menuName = "Simple Tools/Sounds", order = 11)] + public class Sounds : ScriptableObject { - [Tooltip("The music mixer.")] - public AudioMixerGroup mainMixer = default; - [Tooltip("The SFX mixer.")] - public AudioMixerGroup sfxMixer = default; + [Tooltip("The music mixer.")] + public AudioMixerGroup mainMixer = default; + [Tooltip("The SFX mixer.")] + public AudioMixerGroup sfxMixer = default; - public List[] sounds; + public List[] sounds; - [System.Serializable] public class List{ - [Tooltip("Name of the sound. Each name has to be different between each other.")] - public string name; + [System.Serializable] + public class List { + [Tooltip("Name of the sound. Each name has to be different between each other.")] + public string name; - public AudioClip clip; + public AudioClip clip; - [System.Serializable] public enum Type { Music, SFX } - [Space] - [Tooltip("Is it part of the music or the SFX?")] public Type type; + [System.Serializable] public enum Type { Music, SFX } + [Space] + [Tooltip("Is it part of the music or the SFX?")] public Type type; - [Space] - [Tooltip("Default volume of the sound."), Range(0f, 1f)] public float volume; - [Tooltip("Variance percentage of the volume"), Range(0f, 1f)] public float volumeVariance; - [Tooltip("Default pitch of the sound."), Range(.1f, 3f)] public float pitch; - [Tooltip("Variance percentage of the pitch"), Range(0f, 1f)] public float pitchVariance; + [Space] + [Tooltip("Default volume of the sound."), Range(0f, 1f)] public float volume; + [Tooltip("Variance percentage of the volume"), Range(0f, 1f)] public float volumeVariance; + [Tooltip("Default pitch of the sound."), Range(.1f, 3f)] public float pitch; + [Tooltip("Variance percentage of the pitch"), Range(0f, 1f)] public float pitchVariance; - public bool loop; + public bool loop; - [HideInInspector] public AudioSource source; + [HideInInspector] public AudioSource source; - float randomVolume; - public float RandomVolume{ - get{ - randomVolume = volume * (1f + Random.Range(-volumeVariance / 2f, volumeVariance / 2f)); - return randomVolume; - } - } + float randomVolume; + public float RandomVolume { + get { + randomVolume = volume * (1f + Random.Range(-volumeVariance / 2f, volumeVariance / 2f)); + return randomVolume; + } + } - float randomPitch; - public float RandomPitch{ - get{ - randomPitch = pitch * (1f + Random.Range(-pitchVariance / 2f, pitchVariance / 2f)); - return randomPitch; - } - } - } -} + float randomPitch; + public float RandomPitch { + get { + randomPitch = pitch * (1f + Random.Range(-pitchVariance / 2f, pitchVariance / 2f)); + return randomPitch; + } + } + } + } +} \ No newline at end of file diff --git a/Tools/AutoSave.meta b/Tools/AutoSave.meta new file mode 100644 index 0000000..ca4fccd --- /dev/null +++ b/Tools/AutoSave.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2f2d8faa0dc23b34f9f347dc08bd85be +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/AutoSave/AutoSaveConfig.cs b/Tools/AutoSave/AutoSaveConfig.cs new file mode 100644 index 0000000..b0544df --- /dev/null +++ b/Tools/AutoSave/AutoSaveConfig.cs @@ -0,0 +1,124 @@ +#if UNITY_EDITOR +using UnityEngine; +using UnityEditor; +using System; +using System.Threading; +using UnityEditor.SceneManagement; +using System.Threading.Tasks; + +namespace SimpleTools.AutoSave { + public class AutoSaveConfig : EditorWindow { + + [MenuItem("Simple Tools/Auto Save Configuration")] + public static void ShowWindow(){ + EditorWindow w = GetWindow("Auto-save Configuration"); + w.position = new Rect(w.position.position, new Vector2(400, 150)); + var data = EditorPrefs.GetString("AutoSave", JsonUtility.ToJson(w, false)); + JsonUtility.FromJsonOverwrite(data, w); + } + + [InitializeOnLoadMethod] + static void OnInitialize(){ + int _index = EditorPrefs.GetInt("Index", 0); + bool _logging = EditorPrefs.GetBool("Logging", false); + ChangeAutoSaveMode(_index, _logging); + } + + protected void OnEnable() { + OnInitialize(); + } + + protected void OnDisable() { + var data = JsonUtility.ToJson(this, false); + EditorPrefs.SetString("AutoSave", data); + EditorPrefs.SetInt("Index", index); + EditorPrefs.SetBool("Logging", logging); + } + + readonly static string[] options = new string[] { "Disabled", "On Play", "1 Minute", "10 Minutes", "1 Hour" }; + public static int index; + public static bool enabled; + public static bool logging; + + void OnGUI() { + GUILayout.Label("Select auto-save mode:", EditorStyles.boldLabel); + int i = EditorGUILayout.Popup(index, options); + if (i != index) ChangeAutoSaveMode(i, logging); + + GUILayout.Label("Log a message every time a the scene gets saved."); + if (logging) { + if (GUILayout.Button("Disable Logging")){ + logging ^= true; + ChangeAutoSaveMode(i, logging); + } + + } else { + if (GUILayout.Button("Enable Logging")) { + logging ^= true; + ChangeAutoSaveMode(i, logging); + } + } + } + + static CancellationTokenSource _tokenSource; + static Task _task; + static int frequency; + static void ChangeAutoSaveMode(int mode, bool log){ + index = mode; + logging = log; + CancelTask(); + enabled = true; + EditorApplication.playModeStateChanged -= AutoSaveWhenPlayModeStarts; + + switch(index){ + case 0: + enabled = false; + return; + case 1: + EditorApplication.playModeStateChanged += AutoSaveWhenPlayModeStarts; + return; + case 2: + frequency = 1 * 60 * 1000; + break; + case 3: + frequency = 10 * 60 * 1000; + break; + case 4: + frequency = 60 * 60 * 1000; + break; + } + + _tokenSource = new CancellationTokenSource(); + _task = SaveInterval(_tokenSource.Token); + } + + static void AutoSaveWhenPlayModeStarts(PlayModeStateChange state){ + if(state == PlayModeStateChange.ExitingEditMode){ + EditorSceneManager.SaveOpenScenes(); + AssetDatabase.SaveAssets(); + if (logging) Debug.Log($"Auto-saved at {DateTime.Now:h:mm:ss tt}"); + } + } + + static void CancelTask() { + if (_task == null) return; + _tokenSource.Cancel(); + } + + static async Task SaveInterval(CancellationToken token) { + while (!token.IsCancellationRequested) { + await Task.Delay(frequency, token); + + if (token.IsCancellationRequested) break; + + if (!enabled || Application.isPlaying || BuildPipeline.isBuildingPlayer || EditorApplication.isCompiling) return; + if (!UnityEditorInternal.InternalEditorUtility.isApplicationActive) return; + + EditorSceneManager.SaveOpenScenes(); + AssetDatabase.SaveAssets(); + if (logging) Debug.Log($"Auto-saved at {DateTime.Now:h:mm:ss tt}"); + } + } + } +} +#endif \ No newline at end of file diff --git a/Tools/DialogueSystem/DialogueSystem.cs.meta b/Tools/AutoSave/AutoSaveConfig.cs.meta similarity index 83% rename from Tools/DialogueSystem/DialogueSystem.cs.meta rename to Tools/AutoSave/AutoSaveConfig.cs.meta index 8211dcb..d4e6164 100644 --- a/Tools/DialogueSystem/DialogueSystem.cs.meta +++ b/Tools/AutoSave/AutoSaveConfig.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: caad12703fd5c3349acc637253734ac9 +guid: e3f4095259fcc1f45991636604af9829 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Tools/Cinemachine/CMCameraTrigger.cs b/Tools/Cinemachine/CMCameraTrigger.cs index b89a5c0..2fbae3a 100644 --- a/Tools/Cinemachine/CMCameraTrigger.cs +++ b/Tools/Cinemachine/CMCameraTrigger.cs @@ -1,38 +1,41 @@ using UnityEngine; using Cinemachine; -public class CMCameraTrigger : MonoBehaviour{ +namespace SimpleTools.Cinemachine { + public class CMCameraTrigger : MonoBehaviour { - CinemachineVirtualCamera vcam; + CinemachineVirtualCamera vcam; + [SerializeField, Tooltip("Name of the collider's tag that will trigger the camera.")] string triggerTagName; - void Awake(){ - vcam = GetComponentInChildren(true); - vcam.gameObject.SetActive(false); - } + void Awake() { + vcam = GetComponentInChildren(true); + vcam.gameObject.SetActive(false); + } - #region 3D - void OnTriggerEnter(Collider col){ - if (col.CompareTag("Player")){ - vcam.gameObject.SetActive(true); - } - } - void OnTriggerExit(Collider col){ - if (col.CompareTag("Player")){ - vcam.gameObject.SetActive(true); - } - } - #endregion + #region 3D + void OnTriggerEnter(Collider col) { + if (col.CompareTag(triggerTagName)) { + vcam.gameObject.SetActive(true); + } + } + void OnTriggerExit(Collider col) { + if (col.CompareTag(triggerTagName)) { + vcam.gameObject.SetActive(true); + } + } + #endregion - #region 2D - void OnTriggerEnter2D(Collider2D col){ - if (col.CompareTag("Player")){ - vcam.gameObject.SetActive(true); - } - } - void OnTriggerExit2D(Collider2D col){ - if (col.CompareTag("Player")){ - vcam.gameObject.SetActive(false); - } - } - #endregion -} + #region 2D + void OnTriggerEnter2D(Collider2D col) { + if (col.CompareTag(triggerTagName)) { + vcam.gameObject.SetActive(true); + } + } + void OnTriggerExit2D(Collider2D col) { + if (col.CompareTag(triggerTagName)) { + vcam.gameObject.SetActive(false); + } + } + #endregion + } +} \ No newline at end of file diff --git a/Tools/Cinemachine/ScreenShake.cs b/Tools/Cinemachine/ScreenShake.cs index a9d8143..5d4aaa5 100644 --- a/Tools/Cinemachine/ScreenShake.cs +++ b/Tools/Cinemachine/ScreenShake.cs @@ -1,36 +1,38 @@ using Cinemachine; using UnityEngine; -public static class ScreenShake{ +namespace SimpleTools.Cinemachine { + public static class ScreenShake { - static CinemachineVirtualCamera vCam; - static ScreenShakeUpdate shakeUpdate; + static CinemachineVirtualCamera vCam; + static ScreenShakeUpdate shakeUpdate; - class ScreenShakeUpdate : MonoBehaviour { - [HideInInspector] public float shakeTimer; - [HideInInspector] public float shakeTimerTotal; - [HideInInspector] public float startingIntensity; + class ScreenShakeUpdate : MonoBehaviour { + [HideInInspector] public float shakeTimer; + [HideInInspector] public float shakeTimerTotal; + [HideInInspector] public float startingIntensity; - void Update(){ - if (shakeTimer > 0){ - shakeTimer -= Time.deltaTime; - CinemachineBasicMultiChannelPerlin multiChannelPerlin = vCam.GetCinemachineComponent(); - multiChannelPerlin.m_AmplitudeGain = Mathf.Lerp(startingIntensity, 0f, 1 - (shakeTimer / shakeTimerTotal)); - } - } - } + void Update() { + if (shakeTimer > 0) { + shakeTimer -= Time.deltaTime; + CinemachineBasicMultiChannelPerlin multiChannelPerlin = vCam.GetCinemachineComponent(); + multiChannelPerlin.m_AmplitudeGain = Mathf.Lerp(startingIntensity, 0f, 1 - (shakeTimer / shakeTimerTotal)); + } + } + } - /// Shake the camera - /// It needs a cinemachine camera with a noise profile in it. - /// - public static void Shake(float intensity, float time){ - if(vCam == null){ - vCam = Camera.main.GetComponent().ActiveVirtualCamera.VirtualCameraGameObject.GetComponent(); - } - if(shakeUpdate == null){ - shakeUpdate = new GameObject("ShakeUpdate").AddComponent(); - } - shakeUpdate.startingIntensity = intensity; - shakeUpdate.shakeTimer = shakeUpdate.shakeTimerTotal = time; - } -} + /// Shake the camera + /// It needs a cinemachine camera with a noise profile in it. + /// + public static void Shake(float intensity, float time) { + if (vCam == null) { + vCam = Camera.main.GetComponent().ActiveVirtualCamera.VirtualCameraGameObject.GetComponent(); + } + if (shakeUpdate == null) { + shakeUpdate = new GameObject("ShakeUpdate").AddComponent(); + } + shakeUpdate.startingIntensity = intensity; + shakeUpdate.shakeTimer = shakeUpdate.shakeTimerTotal = time; + } + } +} \ No newline at end of file diff --git a/Tools/DialogueSystem/Dialogue.cs b/Tools/DialogueSystem/Dialogue.cs index b7674d0..7b9ce5a 100644 --- a/Tools/DialogueSystem/Dialogue.cs +++ b/Tools/DialogueSystem/Dialogue.cs @@ -1,12 +1,16 @@ using UnityEngine; -[CreateAssetMenu(fileName = "New Character", menuName = "Simple Tools/Character", order = 11)] -public class Dialogue : ScriptableObject{ +namespace SimpleTools.DialogueSystem { + [CreateAssetMenu(fileName = "New Dialogue", menuName = "Simple Tools/Dialogue", order = 11)] + public class Dialogue : ScriptableObject { + public DialogueBox[] sentences; + } - public bool displayName; - public string characterName; - - [Space] - public Sprite characterImage; - [TextArea] public string[] sentences; -} + [System.Serializable] + public class DialogueBox { + public bool displayName; + public string characterName; + public Sprite characterImage; + [TextArea(5, 10)] public string sentence; + } +} \ No newline at end of file diff --git a/Tools/DialogueSystem/DialogueManager.cs b/Tools/DialogueSystem/DialogueManager.cs new file mode 100644 index 0000000..e69e584 --- /dev/null +++ b/Tools/DialogueSystem/DialogueManager.cs @@ -0,0 +1,126 @@ +using System.Collections.Generic; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +namespace SimpleTools.DialogueSystem { + public class DialogueManager : MonoBehaviour { + + DialogueVertexAnimator dialogueVertexAnimator; + + Queue sentences; + Queue displayNames; + Queue characterNames; + Queue characterImages; + bool talking; + + public DialogueManagerItems dialogueItems; + + public static DialogueManager instance; + void Awake() { + instance = this; + sentences = new Queue(); + displayNames = new Queue(); + characterNames = new Queue(); + characterImages = new Queue(); + + dialogueVertexAnimator = new DialogueVertexAnimator(dialogueItems.textBox); + } + + /// + /// This is the main function to call to start a dialogue. + /// + /// The dialogue to start. + /// A bool that is false if the dialogue has finished and true if it hasn't. + public bool Dialogue(Dialogue dialogue) { + return Dialogue(dialogue, string.Empty); + } + + /// + /// This is the main function to call to start a dialogue. + /// + /// The dialogue to start. + /// The sounds from the AudioManager that will be played on character reveal. + /// A bool that is false if the dialogue has finished and true if it hasn't. + public bool Dialogue(Dialogue dialogue, params string[] sounds) { + dialogueVertexAnimator.SetAudioSourceGroup(sounds); + + if (!talking) { + sentences.Clear(); + if (dialogue.sentences.Length != 0) { + foreach (DialogueBox sentence in dialogue.sentences) { + sentences.Enqueue(sentence.sentence); + displayNames.Enqueue(sentence.displayName); + characterNames.Enqueue(sentence.characterName); + characterImages.Enqueue(sentence.characterImage); + } + } else { + sentences.Enqueue("I am error. No text has been added"); + } + talking = true; + + if (sentences.Count == 0) { + if (dialogueVertexAnimator.IsMessageAnimating()) + return true; + talking = false; + return false; + } + + string sentenceToShow = sentences.Peek(); + bool displayName = displayNames.Peek(); + string characterName = characterNames.Peek(); + Sprite characterImage = characterImages.Peek(); + if (PlayDialogue(sentenceToShow, displayName, characterName, characterImage)) { + sentences.Dequeue(); + displayNames.Dequeue(); + characterNames.Dequeue(); + characterImages.Dequeue(); + } + return true; + } else { + if (sentences.Count == 0) { + if (dialogueVertexAnimator.IsMessageAnimating()) + return true; + talking = false; + return false; + } + + string sentenceToShow = sentences.Peek(); + bool displayName = displayNames.Peek(); + string characterName = characterNames.Peek(); + Sprite characterImage = characterImages.Peek(); + if (PlayDialogue(sentenceToShow, displayName, characterName, characterImage)) { + sentences.Dequeue(); + displayNames.Dequeue(); + characterNames.Dequeue(); + characterImages.Dequeue(); + } + return true; + } + } + + private Coroutine typeRoutine = null; + bool PlayDialogue(string message, bool displayName = false, string characterName = "", Sprite characterImage = null) { + if (dialogueVertexAnimator.IsMessageAnimating()) { + dialogueVertexAnimator.SkipToEndOfCurrentMessage(); + return false; //Next message hasn't been shown because the current one is still animating. + } + this.EnsureCoroutineStopped(ref typeRoutine); + dialogueVertexAnimator.textAnimating = false; + List commands = DialogueUtility.ProcessInputString(message, out string totalTextMessage); + typeRoutine = StartCoroutine(dialogueVertexAnimator.AnimateTextIn(commands, totalTextMessage, null)); + + dialogueItems.characterImage.sprite = characterImage; + dialogueItems.characterName.text = displayName ? characterName : "???"; + return true; //Next message shown successfully + } + } + + [System.Serializable] + public struct DialogueManagerItems { + public Image characterImage; + public TMP_Text characterName; + public TMP_Text textBox; + public Canvas canvas; + } +} \ No newline at end of file diff --git a/Tools/DialogueSystem/TMP_Animated.cs.meta b/Tools/DialogueSystem/DialogueManager.cs.meta similarity index 61% rename from Tools/DialogueSystem/TMP_Animated.cs.meta rename to Tools/DialogueSystem/DialogueManager.cs.meta index 8231160..1cc6cbc 100644 --- a/Tools/DialogueSystem/TMP_Animated.cs.meta +++ b/Tools/DialogueSystem/DialogueManager.cs.meta @@ -1,11 +1,11 @@ fileFormatVersion: 2 -guid: f713d84a3ae882945800780459e26170 +guid: 23d6a059fd2bc464a9cba3a5ced1724d MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {fileID: 2800000, guid: 2fd6421f253b4ef1a19526541f9ffc0c, type: 3} + icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: diff --git a/Tools/DialogueSystem/DialogueSystem.cs b/Tools/DialogueSystem/DialogueSystem.cs deleted file mode 100644 index 5e35cc3..0000000 --- a/Tools/DialogueSystem/DialogueSystem.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System.Collections.Generic; -using TMPro; -using UnityEngine; -using UnityEngine.UI; - -public class DialogueSystem : MonoBehaviour{ - - public static DialogueSystem instance; - - public GameObject nameField = default; - public TextMeshProUGUI nameText = default; - public TMP_Animated dialogue = default; - public Image faceImage = default; - - Queue sentences; - bool talking; - Animator anim; - - void Awake(){ - instance = this; - sentences = new Queue(); - anim = GetComponent(); - } - - /// Start or continue the dialogue - /// This function returns false if the dialogue has ended. - /// - public bool Dialogue(Dialogue dialogue){ - if(!talking){ - if (dialogue.displayName){ - nameText.text = dialogue.characterName; - nameField.SetActive(true); - nameText.gameObject.SetActive(true); - }else{ - nameField.SetActive(false); - nameText.gameObject.SetActive(false); - } - - if (dialogue.characterImage) - faceImage.sprite = dialogue.characterImage; - else - faceImage.sprite = null; - - sentences.Clear(); - if(dialogue.sentences.Length != 0){ - foreach (string sentence in dialogue.sentences){ - sentences.Enqueue(sentence); - } - }else{ - sentences.Enqueue("I am error. No text has been added"); - } - talking = true; - - if(sentences.Count == 0){ - talking = false; - return false; - } - - string sentenceToShow = sentences.Dequeue(); - this.dialogue.ReadText(sentenceToShow); - anim.SetBool("Talking", true); - return true; - }else{ - if (sentences.Count == 0){ - talking = false; - anim.SetBool("Talking", false); - return false; - } - - string sentenceToShow = sentences.Dequeue(); - this.dialogue.ReadText(sentenceToShow); - return true; - } - } -} diff --git a/Tools/DialogueSystem/DialogueUtility.cs b/Tools/DialogueSystem/DialogueUtility.cs new file mode 100644 index 0000000..da1fff6 --- /dev/null +++ b/Tools/DialogueSystem/DialogueUtility.cs @@ -0,0 +1,206 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System; + +namespace SimpleTools.DialogueSystem { + public class DialogueUtility : MonoBehaviour { + + // grab the remainder of the text until ">" or end of string + const string REMAINDER_REGEX = "(.*?((?=>)|(/|$)))"; + const string PAUSE_REGEX_STRING = "" + REMAINDER_REGEX + ")>"; + static readonly Regex pauseRegex = new Regex(PAUSE_REGEX_STRING); + const string SOUND_REGEX_STRING = "" + REMAINDER_REGEX + ")>"; + static readonly Regex soundRegex = new Regex(SOUND_REGEX_STRING); + const string PLAYMUSIC_REGEX_STRING = "" + REMAINDER_REGEX + ")>"; + static readonly Regex playMusicRegex = new Regex(PLAYMUSIC_REGEX_STRING); + const string STOPMUSIC_REGEX_STRING = "" + REMAINDER_REGEX + ")>"; + static readonly Regex stopMusicRegex = new Regex(STOPMUSIC_REGEX_STRING); + const string SPEED_REGEX_STRING = "" + REMAINDER_REGEX + ")>"; + static readonly Regex speedRegex = new Regex(SPEED_REGEX_STRING); + const string ANIM_START_REGEX_STRING = "" + REMAINDER_REGEX + ")>"; + static readonly Regex animStartRegex = new Regex(ANIM_START_REGEX_STRING); + const string ANIM_END_REGEX_STRING = ""; + static readonly Regex animEndRegex = new Regex(ANIM_END_REGEX_STRING); + + static readonly Dictionary pauseDictionary = new Dictionary{ + { "tiny", .1f }, + { "short", .25f }, + { "normal", 0.666f }, + { "long", 1f }, + { "read", 2f }, + }; + + public static List ProcessInputString(string message, out string processedMessage) { + List result = new List(); + processedMessage = message; + + processedMessage = HandlePauseTags(processedMessage, result); + processedMessage = HandleSoundTags(processedMessage, result); + processedMessage = HandlePlayMusicTags(processedMessage, result); + processedMessage = HandleStopMusicTags(processedMessage, result); + processedMessage = HandleSpeedTags(processedMessage, result); + processedMessage = HandleAnimStartTags(processedMessage, result); + processedMessage = HandleAnimEndTags(processedMessage, result); + + return result; + } + + static string HandleAnimEndTags(string processedMessage, List result) { + MatchCollection animEndMatches = animEndRegex.Matches(processedMessage); + foreach (Match match in animEndMatches) { + result.Add(new DialogueCommand { + position = VisibleCharactersUpToIndex(processedMessage, match.Index), + type = DialogueCommandType.AnimEnd, + }); + } + processedMessage = Regex.Replace(processedMessage, ANIM_END_REGEX_STRING, ""); + return processedMessage; + } + + static string HandleAnimStartTags(string processedMessage, List result) { + MatchCollection animStartMatches = animStartRegex.Matches(processedMessage); + foreach (Match match in animStartMatches) { + string stringVal = match.Groups["anim"].Value; + result.Add(new DialogueCommand { + position = VisibleCharactersUpToIndex(processedMessage, match.Index), + type = DialogueCommandType.AnimStart, + textAnimValue = GetTextAnimationType(stringVal) + }); + } + processedMessage = Regex.Replace(processedMessage, ANIM_START_REGEX_STRING, ""); + return processedMessage; + } + + static string HandleSpeedTags(string processedMessage, List result) { + MatchCollection speedMatches = speedRegex.Matches(processedMessage); + foreach (Match match in speedMatches) { + string stringVal = match.Groups["speed"].Value; + if (!float.TryParse(stringVal, out float val)) { + val = 150f; + } + result.Add(new DialogueCommand { + position = VisibleCharactersUpToIndex(processedMessage, match.Index), + type = DialogueCommandType.TextSpeedChange, + floatValue = val + }); + } + processedMessage = Regex.Replace(processedMessage, SPEED_REGEX_STRING, ""); + return processedMessage; + } + + static string HandlePauseTags(string processedMessage, List result) { + MatchCollection pauseMatches = pauseRegex.Matches(processedMessage); + foreach (Match match in pauseMatches) { + string val = match.Groups["pause"].Value; + string pauseName = val; + Debug.Assert(pauseDictionary.ContainsKey(pauseName), "no pause registered for '" + pauseName + "'"); + result.Add(new DialogueCommand { + position = VisibleCharactersUpToIndex(processedMessage, match.Index), + type = DialogueCommandType.Pause, + floatValue = pauseDictionary[pauseName] + }); + } + processedMessage = Regex.Replace(processedMessage, PAUSE_REGEX_STRING, ""); + return processedMessage; + } + static string HandleSoundTags(string processedMessage, List result) { + MatchCollection soundMatches = soundRegex.Matches(processedMessage); + foreach (Match match in soundMatches) { + string val = match.Groups["sound"].Value; + string soundName = val; + result.Add(new DialogueCommand { + position = VisibleCharactersUpToIndex(processedMessage, match.Index), + type = DialogueCommandType.Sound, + stringValue = soundName + }); + } + processedMessage = Regex.Replace(processedMessage, SOUND_REGEX_STRING, ""); + return processedMessage; + } + static string HandlePlayMusicTags(string processedMessage, List result) { + MatchCollection playMatches = playMusicRegex.Matches(processedMessage); + foreach (Match match in playMatches) { + string val = match.Groups["playmusic"].Value; + string functionName = val; + result.Add(new DialogueCommand { + position = VisibleCharactersUpToIndex(processedMessage, match.Index), + type = DialogueCommandType.PlayMusic, + stringValue = functionName + }); + } + processedMessage = Regex.Replace(processedMessage, PLAYMUSIC_REGEX_STRING, ""); + return processedMessage; + } + static string HandleStopMusicTags(string processedMessage, List result) { + MatchCollection stopMatches = stopMusicRegex.Matches(processedMessage); + foreach (Match match in stopMatches) { + string val = match.Groups["stopmusic"].Value; + string functionName = val; + result.Add(new DialogueCommand { + position = VisibleCharactersUpToIndex(processedMessage, match.Index), + type = DialogueCommandType.StopMusic, + stringValue = functionName + }); + } + processedMessage = Regex.Replace(processedMessage, STOPMUSIC_REGEX_STRING, ""); + return processedMessage; + } + + static TextAnimationType GetTextAnimationType(string stringVal) { + TextAnimationType result; + try { + result = (TextAnimationType)Enum.Parse(typeof(TextAnimationType), stringVal, true); + } catch (ArgumentException) { + Debug.LogError("Invalid Text Animation Type: " + stringVal); + result = TextAnimationType.none; + } + return result; + } + + static int VisibleCharactersUpToIndex(string message, int index) { + int result = 0; + bool insideBrackets = false; + for (int i = 0; i < index; i++) { + if (message[i] == '<') { + insideBrackets = true; + } else if (message[i] == '>') { + insideBrackets = false; + result--; + } + if (!insideBrackets) { + result++; + } else if (i + 6 < index && message.Substring(i, 6) == "sprite") { + result++; + } + } + return result; + } + } + public struct DialogueCommand { + public int position; + public DialogueCommandType type; + public float floatValue; + public string stringValue; + public TextAnimationType textAnimValue; + } + + public enum DialogueCommandType { + Pause, + TextSpeedChange, + AnimStart, + AnimEnd, + Sound, + PlayMusic, + StopMusic + } + + public enum TextAnimationType { + none, + shake, + wave, + wobble, + rainbow, + } +} \ No newline at end of file diff --git a/Tools/DialogueSystem/DialogueUtility.cs.meta b/Tools/DialogueSystem/DialogueUtility.cs.meta new file mode 100644 index 0000000..a98dbdc --- /dev/null +++ b/Tools/DialogueSystem/DialogueUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d4649243ed65dff45b7891eed22eb4c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/DialogueSystem/DialogueVertexAnimator.cs b/Tools/DialogueSystem/DialogueVertexAnimator.cs new file mode 100644 index 0000000..38d6008 --- /dev/null +++ b/Tools/DialogueSystem/DialogueVertexAnimator.cs @@ -0,0 +1,277 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using TMPro; +using UnityEngine; + +namespace SimpleTools.DialogueSystem { + public class DialogueVertexAnimator { + public bool textAnimating = false; + bool stopAnimating = false; + + readonly TMP_Text textBox; + string[] audioSourceGroup; + public void SetAudioSourceGroup(params string[] _audioSourceGroup) { + audioSourceGroup = _audioSourceGroup; + } + public DialogueVertexAnimator(TMP_Text _textBox) { + textBox = _textBox; + } + + static readonly Color32 clear = new Color32(0, 0, 0, 0); + const float CHAR_ANIM_TIME = 0.07f; + static readonly Vector3 vecZero = Vector3.zero; + public IEnumerator AnimateTextIn(List commands, string processedMessage, Action onFinish) { + textAnimating = true; + float secondsPerCharacter = 1f / 150f; + float timeOfLastCharacter = 0; + + TextAnimInfo[] textAnimInfo = SeparateOutTextAnimInfo(commands); + TMP_TextInfo textInfo = textBox.textInfo; + for (int i = 0; i < textInfo.meshInfo.Length; i++) { + TMP_MeshInfo meshInfer = textInfo.meshInfo[i]; + if (meshInfer.vertices != null) { + for (int j = 0; j < meshInfer.vertices.Length; j++) { + meshInfer.vertices[j] = vecZero; + } + } + } + + textBox.text = processedMessage; + textBox.ForceMeshUpdate(); + + TMP_MeshInfo[] cachedMeshInfo = textInfo.CopyMeshInfoVertexData(); + Color32[][] originalColors = new Color32[textInfo.meshInfo.Length][]; + for (int i = 0; i < originalColors.Length; i++) { + Color32[] theColors = textInfo.meshInfo[i].colors32; + originalColors[i] = new Color32[theColors.Length]; + Array.Copy(theColors, originalColors[i], theColors.Length); + } + int charCount = textInfo.characterCount; + float[] charAnimStartTimes = new float[charCount]; + for (int i = 0; i < charCount; i++) { + charAnimStartTimes[i] = -1; + } + int visableCharacterIndex = 0; + while (true) { + if (stopAnimating) { + for (int i = visableCharacterIndex; i < charCount; i++) { + charAnimStartTimes[i] = Time.unscaledTime; + } + visableCharacterIndex = charCount; + FinishAnimating(onFinish); + } + if (ShouldShowNextCharacter(secondsPerCharacter, timeOfLastCharacter)) { + if (visableCharacterIndex <= charCount) { + ExecuteCommandsForCurrentIndex(commands, visableCharacterIndex, ref secondsPerCharacter, ref timeOfLastCharacter); + if (visableCharacterIndex < charCount && ShouldShowNextCharacter(secondsPerCharacter, timeOfLastCharacter)) { + charAnimStartTimes[visableCharacterIndex] = Time.unscaledTime; + PlayDialogueSound(); + visableCharacterIndex++; + timeOfLastCharacter = Time.unscaledTime; + if (visableCharacterIndex == charCount) { + FinishAnimating(onFinish); + } + } + } + } + for (int j = 0; j < charCount; j++) { + TMP_CharacterInfo charInfo = textInfo.characterInfo[j]; + if (charInfo.isVisible) { + int vertexIndex = charInfo.vertexIndex; + int materialIndex = charInfo.materialReferenceIndex; + Color32[] destinationColors = textInfo.meshInfo[materialIndex].colors32; + Color32 theColor = j < visableCharacterIndex ? originalColors[materialIndex][vertexIndex] : clear; + destinationColors[vertexIndex + 0] = theColor; + destinationColors[vertexIndex + 1] = theColor; + destinationColors[vertexIndex + 2] = theColor; + destinationColors[vertexIndex + 3] = theColor; + + Vector3[] sourceVertices = cachedMeshInfo[materialIndex].vertices; + Vector3[] destinationVertices = textInfo.meshInfo[materialIndex].vertices; + float charSize = 0; + float charAnimStartTime = charAnimStartTimes[j]; + if (charAnimStartTime >= 0) { + float timeSinceAnimStart = Time.unscaledTime - charAnimStartTime; + charSize = Mathf.Min(1, timeSinceAnimStart / CHAR_ANIM_TIME); + } + + Vector3 animPosAdjustment = GetAnimPosAdjustment(textAnimInfo, j, textBox.fontSize, Time.unscaledTime); + Vector3 offset = (sourceVertices[vertexIndex + 0] + sourceVertices[vertexIndex + 2]) / 2; + destinationVertices[vertexIndex + 0] = ((sourceVertices[vertexIndex + 0] - offset) * charSize) + offset + animPosAdjustment; + destinationVertices[vertexIndex + 1] = ((sourceVertices[vertexIndex + 1] - offset) * charSize) + offset + animPosAdjustment; + destinationVertices[vertexIndex + 2] = ((sourceVertices[vertexIndex + 2] - offset) * charSize) + offset + animPosAdjustment; + destinationVertices[vertexIndex + 3] = ((sourceVertices[vertexIndex + 3] - offset) * charSize) + offset + animPosAdjustment; + for (int i = 0; i < 4; i++) { + Vector3 animVertexAdjustment = GetAnimVertexAdjustment(textAnimInfo, j, textBox.fontSize, Time.unscaledTime + i); + destinationVertices[vertexIndex + i] += animVertexAdjustment; + + Color animColorAdjustment = GetAnimColorAdjustment(textAnimInfo, j, Time.unscaledTime + i, destinationVertices[vertexIndex + i]); + if (animColorAdjustment == Color.white) + continue; + destinationColors[vertexIndex + i] += animColorAdjustment; + } + } + } + textBox.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32); + for (int i = 0; i < textInfo.meshInfo.Length; i++) { + TMP_MeshInfo theInfo = textInfo.meshInfo[i]; + theInfo.mesh.vertices = theInfo.vertices; + textBox.UpdateGeometry(theInfo.mesh, i); + } + yield return null; + } + } + + void ExecuteCommandsForCurrentIndex(List commands, int visableCharacterIndex, ref float secondsPerCharacter, ref float timeOfLastCharacter) { + for (int i = 0; i < commands.Count; i++) { + DialogueCommand command = commands[i]; + if (command.position == visableCharacterIndex) { + switch (command.type) { + case DialogueCommandType.Pause: + timeOfLastCharacter = Time.unscaledTime + command.floatValue; + break; + case DialogueCommandType.TextSpeedChange: + secondsPerCharacter = 1f / command.floatValue; + break; + case DialogueCommandType.Sound: + AudioManager.AudioManager.instance.PlayOneShot(command.stringValue); + break; + case DialogueCommandType.PlayMusic: + string[] split0 = command.stringValue.Split(','); + AudioManager.AudioManager.instance.FadeIn(split0[0], float.Parse(split0[1], CultureInfo.InvariantCulture)); + break; + case DialogueCommandType.StopMusic: + string[] split1 = command.stringValue.Split(','); + for (int j = 0; j < split1.Length; j++) { + Debug.Log(split1[j]); + } + AudioManager.AudioManager.instance.FadeOut(split1[0], float.Parse(split1[1], CultureInfo.InvariantCulture)); + break; + } + commands.RemoveAt(i); + i--; + } + } + } + + void FinishAnimating(Action onFinish) { + textAnimating = false; + stopAnimating = false; + onFinish?.Invoke(); + } + + const float NOISE_MAGNITUDE_ADJUSTMENT = 0.06f; + const float NOISE_FREQUENCY_ADJUSTMENT = 15f; + const float WAVE_MAGNITUDE_ADJUSTMENT = 0.06f; + const float WOBBLE_MAGNITUDE_ADJUSTMENT = 0.5f; + const float RAINBOW_LENGTH_ADJUSTMENT = .001f; + Vector3 GetAnimPosAdjustment(TextAnimInfo[] textAnimInfo, int charIndex, float fontSize, float time) { + float x = 0; + float y = 0; + for (int i = 0; i < textAnimInfo.Length; i++) { + TextAnimInfo info = textAnimInfo[i]; + if (charIndex >= info.startIndex && charIndex < info.endIndex) { + if (info.type == TextAnimationType.shake) { + float scaleAdjust = fontSize * NOISE_MAGNITUDE_ADJUSTMENT; + x += (Mathf.PerlinNoise((charIndex + time) * NOISE_FREQUENCY_ADJUSTMENT, 0) - 0.5f) * scaleAdjust; + y += (Mathf.PerlinNoise((charIndex + time) * NOISE_FREQUENCY_ADJUSTMENT, 1000) - 0.5f) * scaleAdjust; + } else if (info.type == TextAnimationType.wave) { + y += Mathf.Sin((charIndex * 1.5f) + (time * 6)) * fontSize * WAVE_MAGNITUDE_ADJUSTMENT; + } + } + } + return new Vector3(x, y, 0); + } + + Vector3 GetAnimVertexAdjustment(TextAnimInfo[] textAnimInfo, int charIndex, float fontSize, float time) { + float x = 0; + float y = 0; + for (int i = 0; i < textAnimInfo.Length; i++) { + TextAnimInfo info = textAnimInfo[i]; + if (charIndex >= info.startIndex && charIndex < info.endIndex) { + if (info.type == TextAnimationType.wobble) { + float scaleAdjust = fontSize * NOISE_MAGNITUDE_ADJUSTMENT; + x = Mathf.Sin(time * 3.3f) * scaleAdjust * WOBBLE_MAGNITUDE_ADJUSTMENT; + y = Mathf.Cos(time * 2.5f) * scaleAdjust * WOBBLE_MAGNITUDE_ADJUSTMENT; + } + } + } + return new Vector3(x, y, 0); + } + Color GetAnimColorAdjustment(TextAnimInfo[] textAnimInfo, int charIndex, float time, Vector3 destinationVertice) { + Color color = Color.white; + for (int i = 0; i < textAnimInfo.Length; i++) { + TextAnimInfo info = textAnimInfo[i]; + if (charIndex >= info.startIndex && charIndex < info.endIndex) { + if (info.type == TextAnimationType.rainbow) { + color = Color.HSVToRGB(Mathf.Repeat((time + destinationVertice.x * RAINBOW_LENGTH_ADJUSTMENT), 1f), .75f, 1); + } + } + } + return color; + } + + static bool ShouldShowNextCharacter(float secondsPerCharacter, float timeOfLastCharacter) { + return (Time.unscaledTime - timeOfLastCharacter) > secondsPerCharacter; + } + public void SkipToEndOfCurrentMessage() { + if (textAnimating) { + stopAnimating = true; + } + } + public bool IsMessageAnimating() { + return textAnimating; + } + + float timeUntilNextDialogueSound = 0; + float lastDialogueSound = 0; + void PlayDialogueSound() { + if (Time.unscaledTime - lastDialogueSound > timeUntilNextDialogueSound) { + timeUntilNextDialogueSound = UnityEngine.Random.Range(0.02f, 0.08f); + lastDialogueSound = Time.unscaledTime; + if (audioSourceGroup[0] != string.Empty) + AudioManager.AudioManager.instance.PlayRandomSound(audioSourceGroup); + } + } + + TextAnimInfo[] SeparateOutTextAnimInfo(List commands) { + List tempResult = new List(); + List animStartCommands = new List(); + List animEndCommands = new List(); + for (int i = 0; i < commands.Count; i++) { + DialogueCommand command = commands[i]; + if (command.type == DialogueCommandType.AnimStart) { + animStartCommands.Add(command); + commands.RemoveAt(i); + i--; + } else if (command.type == DialogueCommandType.AnimEnd) { + animEndCommands.Add(command); + commands.RemoveAt(i); + i--; + } + } + if (animStartCommands.Count != animEndCommands.Count) { + Debug.LogError("Unequal number of start and end animation commands. Start Commands: " + animStartCommands.Count + " End Commands: " + animEndCommands.Count); + } else { + for (int i = 0; i < animStartCommands.Count; i++) { + DialogueCommand startCommand = animStartCommands[i]; + DialogueCommand endCommand = animEndCommands[i]; + tempResult.Add(new TextAnimInfo { + startIndex = startCommand.position, + endIndex = endCommand.position, + type = startCommand.textAnimValue + }); + } + } + return tempResult.ToArray(); + } + } + + public struct TextAnimInfo { + public int startIndex; + public int endIndex; + public TextAnimationType type; + } +} \ No newline at end of file diff --git a/Tools/DialogueSystem/DialogueVertexAnimator.cs.meta b/Tools/DialogueSystem/DialogueVertexAnimator.cs.meta new file mode 100644 index 0000000..8f15ab6 --- /dev/null +++ b/Tools/DialogueSystem/DialogueVertexAnimator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dcef7fafd8716284392e9621424bfa6a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/DialogueSystem/TMP_Animated.cs b/Tools/DialogueSystem/TMP_Animated.cs deleted file mode 100644 index 904041b..0000000 --- a/Tools/DialogueSystem/TMP_Animated.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System.Collections; -using UnityEngine; -using UnityEngine.Events; - -namespace TMPro{ - [System.Serializable] public class TextRevealEvent : UnityEvent { } - [System.Serializable] public class DialogueEvent : UnityEvent { } - - public class TMP_Animated : TextMeshProUGUI{ - - float speed = 20; - - public TextRevealEvent onTextReveal; - public DialogueEvent onDialogueFinish; - - void Update(){ - /*if(Application.isPlaying) - this.Animate();*/ - } - - public void ReadText(string newText){ - text = string.Empty; - - string[] subTexts = newText.Split('<', '>'); - - string displayText = ""; - for (int i = 0; i < subTexts.Length; i++){ - if (i % 2 == 0) - displayText += subTexts[i]; - else if (!isCustomTag(subTexts[i].Replace(" ", ""))) - displayText += $"<{subTexts[i]}>"; - } - - bool isCustomTag(string tag){ - return tag.StartsWith("speed=") || tag.StartsWith("pause=") || tag.StartsWith("wave") || tag.StartsWith("rainbow") || tag.StartsWith("shake"); - } - - text = displayText; - maxVisibleCharacters = 0; - StartCoroutine(Read()); - - IEnumerator Read(){ - int subCounter = 0; - int visibleCounter = 0; - while(subCounter < subTexts.Length){ - if(subCounter % 2 == 1){ - yield return EvaluateTag(subTexts[subCounter].Replace(" ", "")); - }else{ - while(visibleCounter < subTexts[subCounter].Length){ - onTextReveal.Invoke(subTexts[subCounter][visibleCounter]); - visibleCounter++; - maxVisibleCharacters++; - //this.Animate(); - - yield return new WaitForSeconds(text[maxVisibleCharacters - 1] == ' ' ? 0 : (1f / speed)); - } - visibleCounter = 0; - } - subCounter++; - } - yield return null; - - WaitForSeconds EvaluateTag(string tag){ - if (tag.Length > 0){ - if (tag.StartsWith("speed=")){ - speed = float.Parse(tag.Split('=')[1]); - }else if (tag.StartsWith("pause=")){ - return new WaitForSeconds(float.Parse(tag.Split('=')[1])); - } - } - return null; - } - - onDialogueFinish.Invoke(); - } - } - } -} diff --git a/Tools/Editor/ToolsEditor.cs b/Tools/Editor/ToolsEditor.cs index acadbd3..c251913 100644 --- a/Tools/Editor/ToolsEditor.cs +++ b/Tools/Editor/ToolsEditor.cs @@ -11,527 +11,538 @@ using UnityEditor.SceneManagement; using UnityEngine.EventSystems; using UnityEditor.Experimental.SceneManagement; using System; +using SimpleTools.AudioManager; +using SimpleTools.DialogueSystem; +using SimpleTools.Cinemachine; +using SimpleTools.SceneManagement; +using SimpleTools.Menu; public class ToolsEditor{ - - [MenuItem("GameObject/Simple Tools/AudioManager", false, 10)] - static void CreateAudioManager(){ - GameObject audioManager = new GameObject("AudioManager"); - audioManager.AddComponent(); - } + + [MenuItem("GameObject/Simple Tools/AudioManager", false, 10)] + static void CreateAudioManager(){ + GameObject audioManager = new GameObject("AudioManager"); + audioManager.AddComponent(); + } - [MenuItem("GameObject/Simple Tools/Dialogue System", false, 10)] - static void CreateDialogueSystem(){ - GameObject dialogueCanvas = new GameObject("DialogueCanvas"); - dialogueCanvas.AddComponent(); - Canvas canvas = dialogueCanvas.AddComponent(); - canvas.renderMode = RenderMode.ScreenSpaceOverlay; - dialogueCanvas.AddComponent(); - dialogueCanvas.AddComponent(); + [MenuItem("GameObject/Simple Tools/Dialogue System", false, 10)] + static void CreateDialogueSystem(){ + GameObject dialogueCanvas = new GameObject("DialogueCanvas"); + dialogueCanvas.AddComponent(); + Canvas canvas = dialogueCanvas.AddComponent(); + canvas.renderMode = RenderMode.ScreenSpaceOverlay; + dialogueCanvas.AddComponent(); + dialogueCanvas.AddComponent(); - GameObject text = new GameObject("TMP_Animated"); - text.transform.SetParent(dialogueCanvas.transform); - text.AddComponent().text = "New Text"; - text.GetComponent().anchoredPosition = Vector2.zero; + GameObject text = new GameObject("DialogueText"); + text.transform.SetParent(dialogueCanvas.transform); + text.AddComponent().text = "Dialogue"; + text.GetComponent().anchoredPosition = Vector2.zero; - GameObject name = new GameObject("NameText"); - name.transform.SetParent(dialogueCanvas.transform); - name.AddComponent().text = "Name"; - name.GetComponent().anchoredPosition = Vector2.up * 50f; + GameObject name = new GameObject("NameText"); + name.transform.SetParent(dialogueCanvas.transform); + name.AddComponent().text = "Name"; + name.GetComponent().anchoredPosition = Vector2.up * 50f; - GameObject image = new GameObject("Image"); - image.transform.SetParent(dialogueCanvas.transform); - image.AddComponent(); - image.GetComponent().anchoredPosition = new Vector2(-150f, 25f); + GameObject image = new GameObject("Image"); + image.transform.SetParent(dialogueCanvas.transform); + image.AddComponent(); + image.GetComponent().anchoredPosition = new Vector2(-150f, 25f); - DialogueSystem dialogueSystem = dialogueCanvas.AddComponent(); - dialogueSystem.nameText = name.GetComponent(); - dialogueSystem.dialogue = text.GetComponent(); - dialogueSystem.faceImage = image.GetComponent(); - dialogueSystem.nameField = name; - } + DialogueManager dialogueManager = dialogueCanvas.AddComponent(); + Debug.Log(dialogueManager.dialogueItems); + dialogueManager.dialogueItems.textBox = text.GetComponent(); + dialogueManager.dialogueItems.characterName = name.GetComponent(); + dialogueManager.dialogueItems.characterImage = image.GetComponent(); + dialogueManager.dialogueItems.canvas = canvas; + //DialogueSystem dialogueSystem = dialogueCanvas.AddComponent(); + //dialogueSystem.nameText = name.GetComponent(); + //dialogueSystem.dialogue = text.GetComponent(); + //dialogueSystem.faceImage = image.GetComponent(); + //dialogueSystem.nameField = name; + } - [MenuItem("GameObject/Simple Tools/Camera Trigger/2D", false, 10)] - static void CreateCameraTrigger2D(){ - GameObject cameraTrigger = new GameObject("CameraTrigger2D"); - cameraTrigger.AddComponent(); - cameraTrigger.AddComponent(); + [MenuItem("GameObject/Simple Tools/Camera Trigger/2D", false, 10)] + static void CreateCameraTrigger2D(){ + GameObject cameraTrigger = new GameObject("CameraTrigger2D"); + cameraTrigger.AddComponent(); + cameraTrigger.AddComponent(); - GameObject vCam = new GameObject("CM vcam1"); - vCam.transform.SetParent(cameraTrigger.transform); - vCam.SetActive(false); - CinemachineVirtualCamera cam = vCam.AddComponent(); - cam.m_Lens.Orthographic = true; - } + GameObject vCam = new GameObject("CM vcam1"); + vCam.transform.SetParent(cameraTrigger.transform); + vCam.SetActive(false); + CinemachineVirtualCamera cam = vCam.AddComponent(); + cam.m_Lens.Orthographic = true; + } - [MenuItem("GameObject/Simple Tools/Camera Trigger/3D", false, 10)] - static void CreateCameraTrigger3D(){ - GameObject cameraTrigger = new GameObject("CameraTrigger3D"); - cameraTrigger.AddComponent(); - cameraTrigger.AddComponent(); + [MenuItem("GameObject/Simple Tools/Camera Trigger/3D", false, 10)] + static void CreateCameraTrigger3D(){ + GameObject cameraTrigger = new GameObject("CameraTrigger3D"); + cameraTrigger.AddComponent(); + cameraTrigger.AddComponent(); - GameObject vCam = new GameObject("CM vcam1"); - vCam.transform.SetParent(cameraTrigger.transform); - vCam.SetActive(false); - CinemachineVirtualCamera cam = vCam.AddComponent(); - cam.m_Lens.FieldOfView = 60f; - } + GameObject vCam = new GameObject("CM vcam1"); + vCam.transform.SetParent(cameraTrigger.transform); + vCam.SetActive(false); + CinemachineVirtualCamera cam = vCam.AddComponent(); + cam.m_Lens.FieldOfView = 60f; + } #if CINEMACHINE_271_OR_NEWER - [MenuItem("GameObject/Simple Tools/ScreenShake Camera/2D", false, 10)] - static void CreateScreenShakeCamera2d(){ - GameObject screenShakeCamera = new GameObject("ScreenShakeCamera"); - CinemachineVirtualCamera vCam = screenShakeCamera.AddComponent(); - vCam.m_Lens.ModeOverride = LensSettings.OverrideModes.Orthographic; + [MenuItem("GameObject/Simple Tools/ScreenShake Camera/2D", false, 10)] + static void CreateScreenShakeCamera2d(){ + GameObject screenShakeCamera = new GameObject("ScreenShakeCamera"); + CinemachineVirtualCamera vCam = screenShakeCamera.AddComponent(); + vCam.m_Lens.ModeOverride = LensSettings.OverrideModes.Orthographic; - CinemachineBasicMultiChannelPerlin shake = vCam.AddCinemachineComponent(); + CinemachineBasicMultiChannelPerlin shake = vCam.AddCinemachineComponent(); - NoiseSettings noise = (NoiseSettings)AssetDatabase.LoadAssetAtPath("Packages/com.unity.cinemachine/Presets/Noise/6D Shake.asset", typeof(NoiseSettings)); + NoiseSettings noise = (NoiseSettings)AssetDatabase.LoadAssetAtPath("Packages/com.unity.cinemachine/Presets/Noise/6D Shake.asset", typeof(NoiseSettings)); - shake.m_NoiseProfile = noise; - shake.m_AmplitudeGain = 0f; - shake.m_FrequencyGain = 1f; - } - [MenuItem("GameObject/Simple Tools/ScreenShake Camera/3D", false, 10)] - static void CreateScreenShakeCamera3d(){ - GameObject screenShakeCamera = new GameObject("ScreenShakeCamera"); - CinemachineVirtualCamera vCam = screenShakeCamera.AddComponent(); - vCam.m_Lens.ModeOverride = LensSettings.OverrideModes.Perspective; + shake.m_NoiseProfile = noise; + shake.m_AmplitudeGain = 0f; + shake.m_FrequencyGain = 1f; + } + [MenuItem("GameObject/Simple Tools/ScreenShake Camera/3D", false, 10)] + static void CreateScreenShakeCamera3d(){ + GameObject screenShakeCamera = new GameObject("ScreenShakeCamera"); + CinemachineVirtualCamera vCam = screenShakeCamera.AddComponent(); + vCam.m_Lens.ModeOverride = LensSettings.OverrideModes.Perspective; - CinemachineBasicMultiChannelPerlin shake = vCam.AddCinemachineComponent(); + CinemachineBasicMultiChannelPerlin shake = vCam.AddCinemachineComponent(); - NoiseSettings noise = (NoiseSettings)AssetDatabase.LoadAssetAtPath("Packages/com.unity.cinemachine/Presets/Noise/6D Shake.asset", typeof(NoiseSettings)); + NoiseSettings noise = (NoiseSettings)AssetDatabase.LoadAssetAtPath("Packages/com.unity.cinemachine/Presets/Noise/6D Shake.asset", typeof(NoiseSettings)); - shake.m_NoiseProfile = noise; - shake.m_AmplitudeGain = 0f; - shake.m_FrequencyGain = 1f; - } + shake.m_NoiseProfile = noise; + shake.m_AmplitudeGain = 0f; + shake.m_FrequencyGain = 1f; + } #else - [MenuItem("GameObject/Simple Tools/ScreenShake Camera", false, 10)] - static void CreateScreenShakeCamera2d(){ - GameObject screenShakeCamera = new GameObject("ScreenShakeCamera"); - CinemachineVirtualCamera vCam = screenShakeCamera.AddComponent(); + [MenuItem("GameObject/Simple Tools/ScreenShake Camera", false, 10)] + static void CreateScreenShakeCamera2d(){ + GameObject screenShakeCamera = new GameObject("ScreenShakeCamera"); + CinemachineVirtualCamera vCam = screenShakeCamera.AddComponent(); - CinemachineBasicMultiChannelPerlin shake = vCam.AddCinemachineComponent(); + CinemachineBasicMultiChannelPerlin shake = vCam.AddCinemachineComponent(); - NoiseSettings noise = (NoiseSettings)AssetDatabase.LoadAssetAtPath("Packages/com.unity.cinemachine/Presets/Noise/6D Shake.asset", typeof(NoiseSettings)); + NoiseSettings noise = (NoiseSettings)AssetDatabase.LoadAssetAtPath("Packages/com.unity.cinemachine/Presets/Noise/6D Shake.asset", typeof(NoiseSettings)); - shake.m_NoiseProfile = noise; - shake.m_AmplitudeGain = 0f; - shake.m_FrequencyGain = 1f; - } + shake.m_NoiseProfile = noise; + shake.m_AmplitudeGain = 0f; + shake.m_FrequencyGain = 1f; + } #endif - [MenuItem("Assets/Create/Simple Tools/Create Loading Scene")] - [MenuItem("Simple Tools/Create Loading Scene")] - static void CreateLoadingScene(){ - EditorSceneManager.SaveOpenScenes(); + [MenuItem("Assets/Create/Simple Tools/Create Loading Scene")] + [MenuItem("Simple Tools/Create Loading Scene")] + static void CreateLoadingScene(){ + EditorSceneManager.SaveOpenScenes(); - Scene loadingScene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); - loadingScene.name = "Loading"; + Scene loadingScene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); + loadingScene.name = "Loading"; - GameObject loaderCallback = new GameObject("LoaderCallback"); - loaderCallback.AddComponent(); + GameObject loaderCallback = new GameObject("LoaderCallback"); + loaderCallback.AddComponent(); - GameObject canvasObj = new GameObject("Canvas"); - Canvas canvas = canvasObj.AddComponent(); - canvas.renderMode = RenderMode.ScreenSpaceOverlay; + GameObject canvasObj = new GameObject("Canvas"); + Canvas canvas = canvasObj.AddComponent(); + canvas.renderMode = RenderMode.ScreenSpaceOverlay; - CanvasScaler canvasScaler = canvasObj.AddComponent(); - canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; - canvasScaler.referenceResolution = new Vector2Int(951, 535); - canvasScaler.matchWidthOrHeight = 1f; - - canvasObj.AddComponent(); + CanvasScaler canvasScaler = canvasObj.AddComponent(); + canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; + canvasScaler.referenceResolution = new Vector2Int(951, 535); + canvasScaler.matchWidthOrHeight = 1f; + + canvasObj.AddComponent(); - TextMeshProUGUI loadingText = new GameObject("LoadingText").AddComponent(); - loadingText.transform.SetParent(canvasObj.transform); - RectTransform loadingTextTransform = loadingText.GetComponent(); - loadingTextTransform.anchoredPosition = new Vector2Int(-333, -212); - loadingTextTransform.sizeDelta = new Vector2Int(237, 52); - loadingText.text = "LOADING..."; + TextMeshProUGUI loadingText = new GameObject("LoadingText").AddComponent(); + loadingText.transform.SetParent(canvasObj.transform); + RectTransform loadingTextTransform = loadingText.GetComponent(); + loadingTextTransform.anchoredPosition = new Vector2Int(-333, -212); + loadingTextTransform.sizeDelta = new Vector2Int(237, 52); + loadingText.text = "LOADING..."; - Image bg = new GameObject("bg").AddComponent(); - bg.transform.SetParent(canvasObj.transform); - RectTransform bgTransform = bg.GetComponent(); - bgTransform.anchoredPosition = new Vector2Int(0, -235); - bgTransform.sizeDelta = new Vector2Int(900, 20); - bg.color = new Color(36f / 255f, 36f / 255f, 36f / 255f); + Image bg = new GameObject("bg").AddComponent(); + bg.transform.SetParent(canvasObj.transform); + RectTransform bgTransform = bg.GetComponent(); + bgTransform.anchoredPosition = new Vector2Int(0, -235); + bgTransform.sizeDelta = new Vector2Int(900, 20); + bg.color = new Color(36f / 255f, 36f / 255f, 36f / 255f); - Image progressBar = new GameObject("ProgressBar").AddComponent(); - progressBar.transform.SetParent(bg.transform); - RectTransform progressBarTransform = progressBar.GetComponent(); - progressBarTransform.anchoredPosition = Vector2.zero; - progressBarTransform.sizeDelta = new Vector2Int(900, 20); + Image progressBar = new GameObject("ProgressBar").AddComponent(); + progressBar.transform.SetParent(bg.transform); + RectTransform progressBarTransform = progressBar.GetComponent(); + progressBarTransform.anchoredPosition = Vector2.zero; + progressBarTransform.sizeDelta = new Vector2Int(900, 20); - progressBar.sprite = (Sprite)AssetDatabase.LoadAssetAtPath("Packages/com.geri.simpletools/Simple Tools/Editor/Square.png", typeof(Sprite)); - progressBar.type = Image.Type.Filled; - progressBar.fillMethod = Image.FillMethod.Horizontal; - progressBar.fillOrigin = (int)Image.OriginHorizontal.Left; - progressBar.fillAmount = 1f; - progressBar.gameObject.AddComponent(); - } + progressBar.sprite = (Sprite)AssetDatabase.LoadAssetAtPath("Packages/com.geri.simpletools/Simple Tools/Editor/Square.png", typeof(Sprite)); + progressBar.type = Image.Type.Filled; + progressBar.fillMethod = Image.FillMethod.Horizontal; + progressBar.fillOrigin = (int)Image.OriginHorizontal.Left; + progressBar.fillAmount = 1f; + progressBar.gameObject.AddComponent(); + } #if UNITY_2019_3_OR_NEWER - [MenuItem("Assets/Create/Simple Tools/Create Menu Scene")] - [MenuItem("Simple Tools/Create Menu Scene")] - static void CreateMenuScene(){ - EditorSceneManager.SaveOpenScenes(); + [MenuItem("Assets/Create/Simple Tools/Create Menu Scene")] + [MenuItem("Simple Tools/Create Menu Scene")] + static void CreateMenuScene(){ + EditorSceneManager.SaveOpenScenes(); - Scene menuScene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); - menuScene.name = "Menu"; + Scene menuScene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); + menuScene.name = "Menu"; - GameObject canvasObj = new GameObject("Canvas"); - Canvas canvas = canvasObj.AddComponent(); - canvas.renderMode = RenderMode.ScreenSpaceOverlay; + GameObject canvasObj = new GameObject("Canvas"); + Canvas canvas = canvasObj.AddComponent(); + canvas.renderMode = RenderMode.ScreenSpaceOverlay; - CreateEventSystem(false, null); + CreateEventSystem(false, null); - CanvasScaler canvasScaler = canvasObj.AddComponent(); - canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; - canvasScaler.referenceResolution = new Vector2Int(951, 535); - canvasScaler.matchWidthOrHeight = 1f; + CanvasScaler canvasScaler = canvasObj.AddComponent(); + canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; + canvasScaler.referenceResolution = new Vector2Int(951, 535); + canvasScaler.matchWidthOrHeight = 1f; - canvasObj.AddComponent(); + canvasObj.AddComponent(); - GameObject qualityDropdown = TMP_DefaultControls.CreateDropdown(GetStandardResources()); - qualityDropdown.transform.SetParent(canvasObj.transform); - RectTransform qualityRectTransform = qualityDropdown.GetComponent(); - qualityRectTransform.anchoredPosition = Vector2.up * 15f; - qualityDropdown.name = "QualityDropdown"; + GameObject qualityDropdown = TMP_DefaultControls.CreateDropdown(GetStandardResources()); + qualityDropdown.transform.SetParent(canvasObj.transform); + RectTransform qualityRectTransform = qualityDropdown.GetComponent(); + qualityRectTransform.anchoredPosition = Vector2.up * 15f; + qualityDropdown.name = "QualityDropdown"; - GameObject resolutionDropdown = TMP_DefaultControls.CreateDropdown(GetStandardResources()); - resolutionDropdown.transform.SetParent(canvasObj.transform); - RectTransform resolutionRectTransform = resolutionDropdown.GetComponent(); - resolutionRectTransform.anchoredPosition = Vector2.down * 15f; - resolutionDropdown.name = "ResolutionDropdown"; + GameObject resolutionDropdown = TMP_DefaultControls.CreateDropdown(GetStandardResources()); + resolutionDropdown.transform.SetParent(canvasObj.transform); + RectTransform resolutionRectTransform = resolutionDropdown.GetComponent(); + resolutionRectTransform.anchoredPosition = Vector2.down * 15f; + resolutionDropdown.name = "ResolutionDropdown"; - GameObject musicSlider; - using (new FactorySwapToEditor()) - musicSlider = DefaultControls.CreateSlider(GetStandardUIResources()); - musicSlider.transform.SetParent(canvasObj.transform); - RectTransform musicRectTransform = musicSlider.GetComponent(); - musicRectTransform.anchoredPosition = Vector2.down * 40f; - musicSlider.name = "MusicSlider"; + GameObject musicSlider; + using (new FactorySwapToEditor()) + musicSlider = DefaultControls.CreateSlider(GetStandardUIResources()); + musicSlider.transform.SetParent(canvasObj.transform); + RectTransform musicRectTransform = musicSlider.GetComponent(); + musicRectTransform.anchoredPosition = Vector2.down * 40f; + musicSlider.name = "MusicSlider"; - GameObject sfxSlider; - using (new FactorySwapToEditor()) - sfxSlider = DefaultControls.CreateSlider(GetStandardUIResources()); - sfxSlider.transform.SetParent(canvasObj.transform); - RectTransform sfxRectTransform = sfxSlider.GetComponent(); - sfxRectTransform.anchoredPosition = Vector2.down * 60; - sfxSlider.name = "MusicSlider"; + GameObject sfxSlider; + using (new FactorySwapToEditor()) + sfxSlider = DefaultControls.CreateSlider(GetStandardUIResources()); + sfxSlider.transform.SetParent(canvasObj.transform); + RectTransform sfxRectTransform = sfxSlider.GetComponent(); + sfxRectTransform.anchoredPosition = Vector2.down * 60; + sfxSlider.name = "MusicSlider"; - GameObject playButton = TMP_DefaultControls.CreateButton(GetStandardResources()); - playButton.transform.SetParent(canvasObj.transform); - TMP_Text playTextComponent = playButton.GetComponentInChildren(); - playTextComponent.fontSize = 24; - playTextComponent.text = "PLAY"; - RectTransform playRectTransform = playButton.GetComponent(); - playRectTransform.anchoredPosition = Vector2.up * 45f; - playButton.name = "PlayButton"; + GameObject playButton = TMP_DefaultControls.CreateButton(GetStandardResources()); + playButton.transform.SetParent(canvasObj.transform); + TMP_Text playTextComponent = playButton.GetComponentInChildren(); + playTextComponent.fontSize = 24; + playTextComponent.text = "PLAY"; + RectTransform playRectTransform = playButton.GetComponent(); + playRectTransform.anchoredPosition = Vector2.up * 45f; + playButton.name = "PlayButton"; - GameObject quitButton = TMP_DefaultControls.CreateButton(GetStandardResources()); - quitButton.transform.SetParent(canvasObj.transform); - TMP_Text quitTextComponent = quitButton.GetComponentInChildren(); - quitTextComponent.fontSize = 24; - quitTextComponent.text = "QUIT"; - RectTransform quitRectTransform = quitButton.GetComponent(); - quitRectTransform.anchoredPosition = Vector2.down * 85f; - quitButton.name = "QuitButton"; + GameObject quitButton = TMP_DefaultControls.CreateButton(GetStandardResources()); + quitButton.transform.SetParent(canvasObj.transform); + TMP_Text quitTextComponent = quitButton.GetComponentInChildren(); + quitTextComponent.fontSize = 24; + quitTextComponent.text = "QUIT"; + RectTransform quitRectTransform = quitButton.GetComponent(); + quitRectTransform.anchoredPosition = Vector2.down * 85f; + quitButton.name = "QuitButton"; - MenuController menuController = canvasObj.AddComponent(); - Slider sliderMusic = menuController.musicSlider = musicSlider.GetComponent(); - Slider sliderSfx = menuController.sfxSlider = sfxSlider.GetComponent(); - TMP_Dropdown dropdownQuality = menuController.qualityDropdown = qualityDropdown.GetComponent(); - TMP_Dropdown dropdownResolution = menuController.resolutionDropdown = resolutionDropdown.GetComponent(); + MenuController menuController = canvasObj.AddComponent(); + Slider sliderMusic = menuController.musicSlider = musicSlider.GetComponent(); + Slider sliderSfx = menuController.sfxSlider = sfxSlider.GetComponent(); + TMP_Dropdown dropdownQuality = menuController.qualityDropdown = qualityDropdown.GetComponent(); + TMP_Dropdown dropdownResolution = menuController.resolutionDropdown = resolutionDropdown.GetComponent(); - sliderMusic.onValueChanged.AddListener(menuController.SetMusicVolume); - sliderSfx.onValueChanged.AddListener(menuController.SetSfxVolume); - dropdownQuality.onValueChanged.AddListener(menuController.SetQuality); - dropdownResolution.onValueChanged.AddListener(menuController.SetResolution); + sliderMusic.onValueChanged.AddListener(menuController.SetMusicVolume); + sliderSfx.onValueChanged.AddListener(menuController.SetSfxVolume); + dropdownQuality.onValueChanged.AddListener(menuController.SetQuality); + dropdownResolution.onValueChanged.AddListener(menuController.SetResolution); - playButton.GetComponent