diff --git a/SimpleTools/LICENSE.md b/SimpleTools/LICENSE.md
new file mode 100644
index 0000000..58c3550
--- /dev/null
+++ b/SimpleTools/LICENSE.md
@@ -0,0 +1,19 @@
+Copyright (c) 2021 Geri
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/SimpleTools/LICENSE.md.meta b/SimpleTools/LICENSE.md.meta
new file mode 100644
index 0000000..de5ec90
--- /dev/null
+++ b/SimpleTools/LICENSE.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 535f36a1918d4d2479031f3ca2725323
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/README.md b/SimpleTools/README.md
new file mode 100644
index 0000000..b9678df
--- /dev/null
+++ b/SimpleTools/README.md
@@ -0,0 +1,145 @@
+# Simple Tools
+
+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.
+- Some Cinemachine tools for making a **camera trigger** and an easy way for creating a **screen shake camera.**
+- Basic **dialogue system** that works with TextMeshPro.
+- 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.
+
+All of that comes with some editor menu items for creating all of that as fast as possible.
+
+## How to install
+
+First install the TextMeshPro and Cinemachine into your Unity project
+
+### Git Installation (Best way to get latest version)
+
+If you have git in your computer, you can open Package Manager inside Unity, select "Add package from Git url...", and paste link [https://github.com/GerardGascon/SimpleTools.git](https://github.com/GerardGascon/SimpleTools.git)
+
+or
+
+Open the manifest.json file of your Unity project. Add "com.geri.simpletools": "[https://github.com/GerardGascon/SimpleTools.git](https://github.com/GerardGascon/SimpleTools.git)"
+
+### Manual Installation
+
+Download latest package from the Release section Import SimpleTools.unitypackage to your Unity Project
+
+## Usage
+
+### 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.Pause("Name"); //Pauses the sound
+AudioManager.instance.UnPause("Name"); //Unpauses the sound
+
+AudioManager.instance.Stop("Name"); //Stops the sound
+AudioManager.instance.StopAll(); //Stops all the sounds that are being played
+
+AudioManager.instance.GetSource("Name"); //Gets the AudioSource with that name
+
+AudioManager.instance.FadeIn("Name", 1f); //Fade In the source with a specific duration
+AudioManager.instance.FadeOut("Name", 1f); //Fade Out the source with a specific duration
+
+AudioManager.instance.PlayMuted("Name"); //Play a sound muted
+AudioManager.instance.FadeMutedIn("Name", 1f); //Fade In a muted sound with a specific duration
+AudioManager.instance.FadeMutedOut("Name", 1f); //Fade Out a sound without stopping it
+```
+
+### 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;
+Pooler.CreatePools(pools); //Create multiple pools
+Pooler.Destroy(gameObject); //Destroys a GameObject and returns it into the pool scene
+
+Pooler.SpawnFromPool("Name", Vector3.zero); //Spawns an object into a specific position
+Pooler.SpawnFromPool("Name", Vector3.zero, Quaternion.identity); //Spawn into a specific position and rotation
+Pooler.SpawnFromPool("Name", Vector3.zero, transform); //Spawn into a specific position and parent
+Pooler.SpawnFromPool("Name", Vector3.zero, Quaternion.identity, transform); //Spawn into a specific position, rotation and parent
+Pooler.SpawnFromPool("Name", Vector3.zero, transform, true); //Spawn into a specific position, parent and instantiate in worldSpace or not
+Pooler.SpawnFromPool("Name", Vector3.zero, Quaternion.identity, transform, true); //Spawn into a specific position, rotation, parent and instantiate in worldSpace or not
+```
+
+### 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
+DialogueSystem.instance.Dialogue(dialogue, "Sound1", "Sound2"); //Start/Continue the dialogue with a random set of sounds for the text reveal
+```
+
+Text commands:
+
+```html
+ --> 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
+```
+
+### 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
+
+```csharp
+using SimpleTools.Cinemachine;
+
+ScreenShake.Shake(1f, .25f); //Shakes the camera with an intensity and duration
+```
+
+### Timer
+
+```csharp
+using SimpleTools.Timer;
+
+//Setup a stopwatch that updates at an unscaled time
+Timer timer = textMeshProText.SetupTimer(TimerType.Stopwatch, TimerUpdate.UnscaledTime);
+//Setup a clock
+Timer timer = textMeshProText.SetupTimer(TimerType.Clock, TimerUpdate.UnscaledTime);
+//Setup a countdown with the default time of 60 seconds
+Timer timer = textMeshProText.SetupTimer(TimerType.Countdown, TimerUpdate.UnscaledTime, 60f);
+
+timer.Play(); //Play or resume the timer
+timer.Stop(); //Pause the timer
+timer.ResetTimer(); //Pause and sets the time to the default one
+timer.Restart(); //Restarts the timer
+```
+
+### 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.
+
+Also you can right click in the Hierarchy for easily creating some GameObjects with the Tools in it.
\ No newline at end of file
diff --git a/SimpleTools/README.md.meta b/SimpleTools/README.md.meta
new file mode 100644
index 0000000..3c5c492
--- /dev/null
+++ b/SimpleTools/README.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: ee23fd1b6b87e954f836c97747d4c083
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools.meta b/SimpleTools/Tools.meta
new file mode 100644
index 0000000..b32c30e
--- /dev/null
+++ b/SimpleTools/Tools.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 78a1b199ab0716542b34cc9a3dd3a9df
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools/AudioManager.meta b/SimpleTools/Tools/AudioManager.meta
new file mode 100644
index 0000000..f12a26c
--- /dev/null
+++ b/SimpleTools/Tools/AudioManager.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1d98cf7b5d008ba4a832612b94195e04
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools/AudioManager/AudioManager.cs b/SimpleTools/Tools/AudioManager/AudioManager.cs
new file mode 100644
index 0000000..7ce5230
--- /dev/null
+++ b/SimpleTools/Tools/AudioManager/AudioManager.cs
@@ -0,0 +1,271 @@
+using System.Collections;
+using UnityEngine;
+using System;
+
+namespace SimpleTools.AudioManager {
+ public class AudioManager : MonoBehaviour {
+
+ public static AudioManager instance;
+
+ [SerializeField] Sounds soundList = default;
+
+ 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;
+ }
+
+ 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;
+ }
+
+ s.source.clip = s.clip;
+
+ 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();
+
+ 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
+ ///
+ 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
+ ///
+ 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;
+ }
+
+ 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);
+
+ if (audioSource && audioSource.isPlaying) {
+ float startVolume = audioSource.volume;
+
+ while (audioSource.volume > 0) {
+ audioSource.volume -= startVolume * Time.deltaTime / fadeTime;
+ yield return null;
+ }
+
+ 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;
+ }
+
+ 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 > 0) {
+ s.source.volume -= Time.deltaTime / fadeTime;
+ yield return null;
+ }
+ s.source.volume = 0;
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/SimpleTools/Tools/AudioManager/AudioManager.cs.meta b/SimpleTools/Tools/AudioManager/AudioManager.cs.meta
new file mode 100644
index 0000000..4a77e93
--- /dev/null
+++ b/SimpleTools/Tools/AudioManager/AudioManager.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7d2879f3876727040b4f0cc799ec7ada
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools/AudioManager/AudioManager.png b/SimpleTools/Tools/AudioManager/AudioManager.png
new file mode 100644
index 0000000..712262f
Binary files /dev/null and b/SimpleTools/Tools/AudioManager/AudioManager.png differ
diff --git a/SimpleTools/Tools/AudioManager/AudioManager.png.meta b/SimpleTools/Tools/AudioManager/AudioManager.png.meta
new file mode 100644
index 0000000..61ce9f6
--- /dev/null
+++ b/SimpleTools/Tools/AudioManager/AudioManager.png.meta
@@ -0,0 +1,96 @@
+fileFormatVersion: 2
+guid: af0857324620d1d4b8b6bf41b6cdecfc
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: -1
+ aniso: -1
+ mipBias: -100
+ wrapU: -1
+ wrapV: -1
+ wrapW: -1
+ nPOTScale: 1
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 0
+ spriteTessellationDetail: -1
+ textureType: 0
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools/AudioManager/Sounds.cs b/SimpleTools/Tools/AudioManager/Sounds.cs
new file mode 100644
index 0000000..35e2dd0
--- /dev/null
+++ b/SimpleTools/Tools/AudioManager/Sounds.cs
@@ -0,0 +1,53 @@
+using UnityEngine;
+using UnityEngine.Audio;
+
+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;
+
+ 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;
+
+ public AudioClip clip;
+
+ [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;
+
+ public bool loop;
+
+ [HideInInspector] public AudioSource source;
+
+ 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;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/SimpleTools/Tools/AudioManager/Sounds.cs.meta b/SimpleTools/Tools/AudioManager/Sounds.cs.meta
new file mode 100644
index 0000000..a22e5ea
--- /dev/null
+++ b/SimpleTools/Tools/AudioManager/Sounds.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6ded47588579f3047b1c3cd72cd87044
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: af0857324620d1d4b8b6bf41b6cdecfc, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools/Cinemachine.meta b/SimpleTools/Tools/Cinemachine.meta
new file mode 100644
index 0000000..608d7cd
--- /dev/null
+++ b/SimpleTools/Tools/Cinemachine.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5a2ff5ceb779d824d811d139fa608262
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools/Cinemachine/CMCameraTrigger.cs b/SimpleTools/Tools/Cinemachine/CMCameraTrigger.cs
new file mode 100644
index 0000000..8afd47a
--- /dev/null
+++ b/SimpleTools/Tools/Cinemachine/CMCameraTrigger.cs
@@ -0,0 +1,40 @@
+using UnityEngine;
+using Cinemachine;
+
+namespace SimpleTools.Cinemachine {
+ public class CMCameraTrigger : MonoBehaviour {
+
+ CinemachineVirtualCamera vcam;
+
+ 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 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
+ }
+}
\ No newline at end of file
diff --git a/SimpleTools/Tools/Cinemachine/CMCameraTrigger.cs.meta b/SimpleTools/Tools/Cinemachine/CMCameraTrigger.cs.meta
new file mode 100644
index 0000000..7d3bb42
--- /dev/null
+++ b/SimpleTools/Tools/Cinemachine/CMCameraTrigger.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 368758c1440a4cb4c867e140e8934c09
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools/Cinemachine/ScreenShake.cs b/SimpleTools/Tools/Cinemachine/ScreenShake.cs
new file mode 100644
index 0000000..5d4aaa5
--- /dev/null
+++ b/SimpleTools/Tools/Cinemachine/ScreenShake.cs
@@ -0,0 +1,38 @@
+using Cinemachine;
+using UnityEngine;
+
+namespace SimpleTools.Cinemachine {
+ public static class ScreenShake {
+
+ static CinemachineVirtualCamera vCam;
+ static ScreenShakeUpdate shakeUpdate;
+
+ 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));
+ }
+ }
+ }
+
+ /// 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/SimpleTools/Tools/Cinemachine/ScreenShake.cs.meta b/SimpleTools/Tools/Cinemachine/ScreenShake.cs.meta
new file mode 100644
index 0000000..048e505
--- /dev/null
+++ b/SimpleTools/Tools/Cinemachine/ScreenShake.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 181034c7ad5ece241a2737ab35d47c5c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools/DialogueSystem.meta b/SimpleTools/Tools/DialogueSystem.meta
new file mode 100644
index 0000000..b94d838
--- /dev/null
+++ b/SimpleTools/Tools/DialogueSystem.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 645cca644899cc74882ea9bc1d9c5aa9
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools/DialogueSystem/Dialogue.cs b/SimpleTools/Tools/DialogueSystem/Dialogue.cs
new file mode 100644
index 0000000..7b9ce5a
--- /dev/null
+++ b/SimpleTools/Tools/DialogueSystem/Dialogue.cs
@@ -0,0 +1,16 @@
+using UnityEngine;
+
+namespace SimpleTools.DialogueSystem {
+ [CreateAssetMenu(fileName = "New Dialogue", menuName = "Simple Tools/Dialogue", order = 11)]
+ public class Dialogue : ScriptableObject {
+ public DialogueBox[] 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/SimpleTools/Tools/DialogueSystem/Dialogue.cs.meta b/SimpleTools/Tools/DialogueSystem/Dialogue.cs.meta
new file mode 100644
index 0000000..63ccf99
--- /dev/null
+++ b/SimpleTools/Tools/DialogueSystem/Dialogue.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bd553cd05b84d614b998afe62e37c17c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 4dfc626116fd10c4f972c17720d957ac, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools/DialogueSystem/Dialogue.png b/SimpleTools/Tools/DialogueSystem/Dialogue.png
new file mode 100644
index 0000000..3bff2d3
Binary files /dev/null and b/SimpleTools/Tools/DialogueSystem/Dialogue.png differ
diff --git a/SimpleTools/Tools/DialogueSystem/Dialogue.png.meta b/SimpleTools/Tools/DialogueSystem/Dialogue.png.meta
new file mode 100644
index 0000000..4991597
--- /dev/null
+++ b/SimpleTools/Tools/DialogueSystem/Dialogue.png.meta
@@ -0,0 +1,96 @@
+fileFormatVersion: 2
+guid: 4dfc626116fd10c4f972c17720d957ac
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: -1
+ aniso: -1
+ mipBias: -100
+ wrapU: -1
+ wrapV: -1
+ wrapW: -1
+ nPOTScale: 1
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 0
+ spriteTessellationDetail: -1
+ textureType: 0
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools/DialogueSystem/DialogueManager.cs b/SimpleTools/Tools/DialogueSystem/DialogueManager.cs
new file mode 100644
index 0000000..4b025a9
--- /dev/null
+++ b/SimpleTools/Tools/DialogueSystem/DialogueManager.cs
@@ -0,0 +1,111 @@
+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 DialogueItems 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);
+ }
+
+ public bool Dialogue(Dialogue dialogue) {
+ return Dialogue(dialogue, string.Empty);
+ }
+
+ 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) {
+ 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) {
+ 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 DialogueItems {
+ public Image characterImage;
+ public TMP_Text characterName;
+ public TMP_Text textBox;
+ public Canvas canvas;
+ }
+}
\ No newline at end of file
diff --git a/SimpleTools/Tools/DialogueSystem/DialogueManager.cs.meta b/SimpleTools/Tools/DialogueSystem/DialogueManager.cs.meta
new file mode 100644
index 0000000..1cc6cbc
--- /dev/null
+++ b/SimpleTools/Tools/DialogueSystem/DialogueManager.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 23d6a059fd2bc464a9cba3a5ced1724d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools/DialogueSystem/DialogueUtility.cs b/SimpleTools/Tools/DialogueSystem/DialogueUtility.cs
new file mode 100644
index 0000000..98a67c3
--- /dev/null
+++ b/SimpleTools/Tools/DialogueSystem/DialogueUtility.cs
@@ -0,0 +1,170 @@
+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 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 = 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 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
+ }
+
+ public enum TextAnimationType {
+ none,
+ shake,
+ wave,
+ wobble,
+ rainbow,
+ }
+}
\ No newline at end of file
diff --git a/SimpleTools/Tools/DialogueSystem/DialogueUtility.cs.meta b/SimpleTools/Tools/DialogueSystem/DialogueUtility.cs.meta
new file mode 100644
index 0000000..a98dbdc
--- /dev/null
+++ b/SimpleTools/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/SimpleTools/Tools/DialogueSystem/DialogueVertexAnimator.cs b/SimpleTools/Tools/DialogueSystem/DialogueVertexAnimator.cs
new file mode 100644
index 0000000..24eb6e4
--- /dev/null
+++ b/SimpleTools/Tools/DialogueSystem/DialogueVertexAnimator.cs
@@ -0,0 +1,265 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+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;
+ }
+ 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), .6f, 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/SimpleTools/Tools/DialogueSystem/DialogueVertexAnimator.cs.meta b/SimpleTools/Tools/DialogueSystem/DialogueVertexAnimator.cs.meta
new file mode 100644
index 0000000..8f15ab6
--- /dev/null
+++ b/SimpleTools/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/SimpleTools/Tools/Editor.meta b/SimpleTools/Tools/Editor.meta
new file mode 100644
index 0000000..550a16f
--- /dev/null
+++ b/SimpleTools/Tools/Editor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 53d517df853ee5d44b788e900f897c54
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools/Editor/Square.png b/SimpleTools/Tools/Editor/Square.png
new file mode 100644
index 0000000..8eb1b1e
Binary files /dev/null and b/SimpleTools/Tools/Editor/Square.png differ
diff --git a/SimpleTools/Tools/Editor/Square.png.meta b/SimpleTools/Tools/Editor/Square.png.meta
new file mode 100644
index 0000000..f6ffc2c
--- /dev/null
+++ b/SimpleTools/Tools/Editor/Square.png.meta
@@ -0,0 +1,104 @@
+fileFormatVersion: 2
+guid: d93624141d1826749b7f50e692cc2a93
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 0
+ aniso: 1
+ mipBias: 0
+ wrapU: 0
+ wrapV: 0
+ wrapW: 0
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 3
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 4
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 0
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: 4
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline:
+ - - {x: -2, y: -2}
+ - {x: -2, y: 2}
+ - {x: 2, y: 2}
+ - {x: 2, y: -2}
+ physicsShape:
+ - - {x: -2, y: -2}
+ - {x: -2, y: 2}
+ - {x: 2, y: 2}
+ - {x: 2, y: -2}
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/SimpleTools/Tools/Editor/ToolsEditor.cs b/SimpleTools/Tools/Editor/ToolsEditor.cs
new file mode 100644
index 0000000..c251913
--- /dev/null
+++ b/SimpleTools/Tools/Editor/ToolsEditor.cs
@@ -0,0 +1,548 @@
+#if UNITY_EDITOR
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using UnityEngine.UI;
+using TMPro;
+using Cinemachine;
+using UnityEngine.SceneManagement;
+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/Dialogue System", false, 10)]
+ static void CreateDialogueSystem(){
+ GameObject dialogueCanvas = new GameObject("DialogueCanvas");
+ dialogueCanvas.AddComponent();
+ Canvas canvas = dialogueCanvas.AddComponent