├── .gitattributes ├── .gitignore ├── README.md └── RatKing └── Base ├── Editor ├── DisableShortcutsDuringPlay.cs ├── DynamicVariableDrawer.cs ├── DynamicVariablesDrawer.cs ├── EditorHelpers.cs ├── EventVarFloatEditor.cs ├── EventVarIntEditor.cs ├── OptionalPropertyDrawer.cs ├── PlayModeEditReminder.cs ├── Position2Drawer.cs ├── Position3Drawer.cs ├── RangePropertyDrawer.cs ├── RatKingTools.cs ├── SoundTypeEditor.cs ├── StoneBuilder.cs ├── StoneBuilderSettings.cs ├── TemplateVariablesDrawer.cs ├── VarFloatEditor.cs └── VarIntEditor.cs ├── Examples ├── Localisation │ ├── English.json │ └── languages.json └── TemplateVars │ ├── SampleClassWithInstancedTemplateVars.cs │ └── SampleTypeWithTemplateVars.cs ├── ImageEffects ├── GlobalFog.cs └── GlobalFog.shader ├── Materials ├── Creature.physicMaterial └── VertexColored.mat ├── ScriptTemplates └── 81-C# Script-NewBehaviourScript.cs.txt ├── Scripts ├── Audio │ ├── Music.cs │ ├── Sound.cs │ ├── SoundType.cs │ └── Sounds.cs ├── Child.cs ├── Creature.cs ├── EnumFlagAttribute.cs ├── Events.cs ├── ExtensionMethods.cs ├── FPSCounter.cs ├── FileHandling.cs ├── GUI │ ├── EditorGUIExtended.cs │ ├── QuickGizmos.cs │ └── QuickIMGUI.cs ├── Graphics │ ├── AmbientOcclusion.cs │ ├── CameraFacingBillboard.cs │ ├── Particler.cs │ ├── Swoosh.cs │ ├── WobbleAnimation.cs │ └── WobbleAnimations.cs ├── Helpers │ ├── AudioExtras.cs │ ├── CameraExtras.cs │ ├── ColorExtras.cs │ ├── ConfigFile.cs │ ├── DataStructures.cs │ ├── Debugging.cs │ ├── GameObjects.cs │ ├── Geometry.cs │ ├── GizmoExtras.cs │ ├── MaterialExtras.cs │ ├── Math.cs │ ├── OBJ.cs │ ├── Pathfinding.cs │ ├── PhysicsExtras.cs │ ├── Randomness.cs │ ├── Security.cs │ └── StringExtras.cs ├── Hotkeys.cs ├── Optional.cs ├── Pause.cs ├── PlayerInput.cs ├── Poolable.cs ├── Positions.cs ├── Range.cs ├── Signal.cs ├── Testing.cs ├── Tweens.cs ├── Updater.cs └── Variables │ ├── DynamicVariable.cs │ ├── DynamicVariables.cs │ ├── EventVarFloat.cs │ ├── EventVarInt.cs │ ├── FloatyFloats.cs │ ├── InstancedVariablesContainer.cs │ ├── ListType.cs │ ├── TemplateVar.T.cs │ ├── TemplateVar.cs │ ├── TemplateVarBool.cs │ ├── TemplateVarFloat.cs │ ├── TemplateVarInt.cs │ ├── TemplateVarList.cs │ ├── TemplateVarString.cs │ ├── TemplateVariables.cs │ ├── VarFloat.cs │ └── VarInt.cs ├── Shaders ├── BoxMappingDiffuse.shader ├── MyFont.shader ├── MyFontAlways.shader ├── Rim.shader ├── RimTransparent.shader ├── SelfIllumDiffuse.shader ├── SelfIllumDiffuseNoDepth.shader ├── SelfIllumTransparent.shader ├── SelfIllumTransparentGeometry.shader ├── SelfIllumTransparentZwrite.shader ├── VertexColored.shader ├── VertexColoredAlpha.shader ├── VertexColoredCutout.shader ├── VertexColoredCutoutAlpha.shader └── VertexLit.shader └── _ThirdParty ├── Editor ├── NormalSolver.cs └── UnityHook.cs └── SimpleJSON ├── Changelog.txt ├── LICENSE ├── SimpleJSON.cs ├── SimpleJSONBinary.cs ├── SimpleJSONDotNetTypes.cs └── SimpleJSONUnity.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | *.meta 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # unity-base-code 2 | Code (and maybe other stuff) I mostly use in game jams 3 | 4 | Contains several helper classes 5 | 6 | Can create a quick&dirty character controller 7 | 8 | A lot of the stuff is probably outdated -------------------------------------------------------------------------------- /RatKing/Base/Editor/DisableShortcutsDuringPlay.cs: -------------------------------------------------------------------------------- 1 | #define ACTIVATE_ONLY_WHEN_GAME_WINDOW_FOCUSED 2 | //#define REMOVE_TOOLBAR_DURING_PLAY 3 | 4 | // original: https://forum.unity.com/threads/unwanted-editor-hotkeys-in-game-mode.182073/#post-6964244 5 | 6 | #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN 7 | using System; 8 | using System.Runtime.InteropServices; 9 | using System.Text; 10 | #endif 11 | using System.Linq; 12 | using UnityEditor; 13 | using UnityEditor.ShortcutManagement; 14 | using UnityEngine; 15 | 16 | namespace RatKing.Base { 17 | 18 | [InitializeOnLoad] 19 | public static class DisableShortcutsDuringPlay { 20 | static bool activated = false; 21 | 22 | static DisableShortcutsDuringPlay() { 23 | EditorApplication.playModeStateChanged += PlayModeStateChanged; 24 | EditorApplication.quitting += Quitting; 25 | } 26 | 27 | private static void PlayModeStateChanged(PlayModeStateChange playModeStateChange) { 28 | switch (playModeStateChange) { 29 | case PlayModeStateChange.EnteredPlayMode: 30 | #if !ACTIVATE_ONLY_WHEN_GAME_WINDOW_FOCUSED 31 | Activate(); 32 | #endif 33 | 34 | new GameObject("DisableShortcutsDuringPlay", typeof(DisableShortcutsDuringPlayBehaviour)); 35 | break; 36 | 37 | case PlayModeStateChange.ExitingPlayMode: 38 | ShortcutManager.instance.activeProfileId = "Default"; 39 | break; 40 | } 41 | } 42 | 43 | public static void Activate() { 44 | if (activated) { return; } 45 | 46 | if (ShortcutManager.instance.GetAvailableProfileIds().Contains("Play")) { 47 | ShortcutManager.instance.activeProfileId = "Play"; 48 | } 49 | else { 50 | ShortcutManager.instance.CreateProfile("Play"); 51 | ShortcutManager.instance.activeProfileId = "Play"; 52 | 53 | foreach (string shortcutId in ShortcutManager.instance.GetAvailableShortcutIds()) { 54 | if (shortcutId != "Main Menu/Edit/Play") { 55 | ShortcutManager.instance.RebindShortcut(shortcutId, ShortcutBinding.empty); 56 | } 57 | } 58 | } 59 | 60 | activated = true; 61 | } 62 | public static void Deactivate() { 63 | if (!activated) { return; } 64 | ShortcutManager.instance.activeProfileId = "Default"; 65 | activated = false; 66 | } 67 | 68 | private static void Quitting() { 69 | Deactivate(); 70 | } 71 | } 72 | 73 | public class DisableShortcutsDuringPlayBehaviour : MonoBehaviour { 74 | 75 | #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN 76 | private delegate int EnumThreadWndProc(IntPtr hWnd, IntPtr lParam); 77 | 78 | [DllImport("user32.dll")] static extern int EnumThreadWindows(uint dwThreadId, EnumThreadWndProc lpfn, IntPtr lParam); 79 | [DllImport("kernel32.dll")] static extern uint GetCurrentThreadId(); 80 | [DllImport("user32.dll")] static extern int GetClassNameA(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); 81 | 82 | [DllImport("user32.dll")] private static extern IntPtr GetMenu(IntPtr hWnd); 83 | [DllImport("user32.dll")] private static extern int SetMenu(IntPtr hWnd, IntPtr hMenu); 84 | [DllImport("user32.dll")] private static extern int DrawMenuBar(IntPtr hWnd); 85 | 86 | [DllImport("user32.dll")] private static extern int GetWindowLongA(IntPtr hWnd, int nIndex); 87 | [DllImport("user32.dll")] private static extern int SetWindowLongA(IntPtr hWnd, int nIndex, int dwNewLong); 88 | 89 | private const int GWL_STYLE = -16; 90 | 91 | private const int WS_CAPTION = 0x00C00000; 92 | private const int WS_SYSMENU = 0x00080000; 93 | 94 | private IntPtr hFrameWnd; 95 | private IntPtr hFrameMenu; 96 | 97 | bool inactiveToolbar; 98 | #endif 99 | 100 | private void Awake() { 101 | #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN 102 | int EnumThreadWndProc(IntPtr hWnd, IntPtr lParam) { 103 | StringBuilder className = new StringBuilder(64); 104 | GetClassNameA(hWnd, className, 64); 105 | if (className.ToString() == "UnityContainerWndClass") { 106 | hFrameWnd = hWnd; 107 | hFrameMenu = GetMenu(hWnd); 108 | return 0; 109 | } 110 | return 1; 111 | } 112 | EnumThreadWindows(GetCurrentThreadId(), EnumThreadWndProc, IntPtr.Zero); 113 | #endif 114 | gameObject.hideFlags = HideFlags.HideInHierarchy; 115 | 116 | GameObject.DontDestroyOnLoad(gameObject); 117 | } 118 | 119 | #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN 120 | void ActivateToolbar() { 121 | if (!inactiveToolbar) { return; } 122 | SetWindowLongA(hFrameWnd, GWL_STYLE, GetWindowLongA(hFrameWnd, GWL_STYLE) | (WS_CAPTION | WS_SYSMENU)); 123 | SetMenu(hFrameWnd, hFrameMenu); 124 | DrawMenuBar(hFrameWnd); 125 | inactiveToolbar = false; 126 | } 127 | 128 | void DeactivateToolbar() { 129 | if (inactiveToolbar) { return; } 130 | SetWindowLongA(hFrameWnd, GWL_STYLE, GetWindowLongA(hFrameWnd, GWL_STYLE) & ~(WS_CAPTION | WS_SYSMENU)); 131 | SetMenu(hFrameWnd, IntPtr.Zero); 132 | DrawMenuBar(hFrameWnd); 133 | inactiveToolbar = true; 134 | } 135 | #endif 136 | 137 | private void Update() { 138 | #if ACTIVATE_ONLY_WHEN_GAME_WINDOW_FOCUSED 139 | if (EditorWindow.focusedWindow != null && EditorWindow.focusedWindow.titleContent.text == "Game") { 140 | DisableShortcutsDuringPlay.Activate(); 141 | #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN 142 | DeactivateToolbar(); 143 | #endif 144 | } 145 | else { 146 | DisableShortcutsDuringPlay.Deactivate(); 147 | #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN 148 | ActivateToolbar(); 149 | #endif 150 | } 151 | #else 152 | 153 | #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN 154 | if (Time.frameCount == 3) { 155 | DeactivateToolbar(); 156 | } 157 | #endif 158 | 159 | #endif 160 | } 161 | 162 | private void OnDestroy() { 163 | #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN 164 | ActivateToolbar(); 165 | #endif 166 | DisableShortcutsDuringPlay.Deactivate(); 167 | } 168 | } 169 | 170 | } -------------------------------------------------------------------------------- /RatKing/Base/Editor/DynamicVariableDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Reflection; 4 | 5 | namespace RatKing.Base { 6 | 7 | [CustomPropertyDrawer(typeof(DynamicVariable))] 8 | public class DynamicVariableDrawer : PropertyDrawer { 9 | // from https://github.com/lordofduct/spacepuppy-unity-framework/blob/master/SpacepuppyBaseEditor/EditorHelper.cs 10 | private static object GetValue_Imp(object source, string name) { 11 | if (source == null) return null; 12 | var type = source.GetType(); 13 | while (type != null) { 14 | var f = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 15 | if (f != null) return f.GetValue(source); 16 | var p = type.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); 17 | if (p != null) return p.GetValue(source, null); 18 | type = type.BaseType; 19 | } 20 | return null; 21 | } 22 | private static object GetValue_Imp(object source, string name, int index) { 23 | var enumerable = GetValue_Imp(source, name) as System.Collections.IEnumerable; 24 | if (enumerable == null) return null; 25 | var enm = enumerable.GetEnumerator(); 26 | for (int i = 0; i <= index; i++) { if (!enm.MoveNext()) return null; } 27 | return enm.Current; 28 | } 29 | public static object GetTargetObjectOfProperty(SerializedProperty prop) { 30 | if (prop == null) return null; 31 | var path = prop.propertyPath.Replace(".Array.data[", "["); 32 | object obj = prop.serializedObject.targetObject; 33 | var elements = path.Split('.'); 34 | foreach (var element in elements) { 35 | if (element.Contains("[")) { 36 | var elementName = element.Substring(0, element.IndexOf("[")); 37 | var index = System.Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", "")); 38 | obj = GetValue_Imp(obj, elementName, index); 39 | } 40 | else { 41 | obj = GetValue_Imp(obj, element); 42 | } 43 | } 44 | return obj; 45 | } 46 | 47 | // 48 | 49 | //public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { 50 | // var dVariable = GetTargetObjectOfProperty(property) as DynamicVariables; 51 | //} 52 | 53 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { 54 | var isDirty = false; 55 | var serializedObject = property.serializedObject; 56 | var dVariable = GetTargetObjectOfProperty(property) as DynamicVariable; 57 | var variable = dVariable.Variable; 58 | 59 | GUI.Label(position, label); 60 | position.x += EditorGUIUtility.labelWidth; 61 | position.width -= EditorGUIUtility.labelWidth; 62 | var rect = position; 63 | 64 | if (!string.IsNullOrEmpty(variable?.ID)) { 65 | rect.width = 30f; 66 | GUI.Label(rect, variable.Unity3DGetButtonName().ToUpper()); 67 | rect.x += rect.width; 68 | rect.width = position.width - 30f - 45f; 69 | if (variable.Unity3DSetValue(rect)) { isDirty = true; } 70 | rect.x += rect.width; 71 | rect.width = 45f; 72 | if (GUI.Button(rect, "Clear")) { dVariable.Clear(); isDirty = true; } 73 | } 74 | else { 75 | rect.width /= 5f; if (GUI.Button(rect, DynamicVarString.Unity3DButtonName)) { dVariable.Set(); isDirty = true; } 76 | rect.x += rect.width; if (GUI.Button(rect, DynamicVarInt.Unity3DButtonName)) { dVariable.Set(); isDirty = true; } 77 | rect.x += rect.width; if (GUI.Button(rect, DynamicVarFloat.Unity3DButtonName)) { dVariable.Set(); isDirty = true; } 78 | rect.x += rect.width; if (GUI.Button(rect, DynamicVarBool.Unity3DButtonName)) { dVariable.Set(); isDirty = true; } 79 | rect.x += rect.width; if (GUI.Button(rect, DynamicVarObject.Unity3DButtonName)) { dVariable.Set(); isDirty = true; } 80 | // can add more types here 81 | } 82 | 83 | if (isDirty) { SetDirty(serializedObject); } 84 | serializedObject.ApplyModifiedProperties(); 85 | } 86 | 87 | void SetDirty(SerializedObject so) { 88 | if (so == null || so.targetObject == null) { return; } 89 | so.ApplyModifiedProperties(); 90 | EditorUtility.SetDirty(so.targetObject); 91 | if (AssetDatabase.IsMainAsset(so.targetObject)) { // TODO? 92 | // AssetDatabase.SaveAssets(); 93 | } 94 | else { 95 | var c = so.targetObject as Component; 96 | if (c != null) { UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(c.gameObject.scene); } 97 | } 98 | } 99 | } 100 | 101 | } -------------------------------------------------------------------------------- /RatKing/Base/Editor/DynamicVariablesDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | 6 | namespace RatKing.Base { 7 | 8 | [CustomPropertyDrawer(typeof(DynamicVariables))] 9 | public class DynamicVariablesDrawer : PropertyDrawer { 10 | const float labelsHeight = 18f; 11 | const float buttonsHeight = 20f; 12 | const float entriesHeight = 20f; 13 | 14 | static GUIStyle headerStyle; 15 | 16 | public static GUIStyle GetHeaderStyle() { 17 | if (headerStyle == null) { headerStyle = new GUIStyle(GUI.skin.GetStyle("label")) { richText = true }; } 18 | return headerStyle; 19 | } 20 | 21 | // 22 | 23 | // from https://github.com/lordofduct/spacepuppy-unity-framework/blob/master/SpacepuppyBaseEditor/EditorHelper.cs 24 | private static object GetValue_Imp(object source, string name) { 25 | if (source == null) return null; 26 | var type = source.GetType(); 27 | while (type != null) { 28 | var f = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 29 | if (f != null) return f.GetValue(source); 30 | var p = type.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); 31 | if (p != null) return p.GetValue(source, null); 32 | type = type.BaseType; 33 | } 34 | return null; 35 | } 36 | private static object GetValue_Imp(object source, string name, int index) { 37 | var enumerable = GetValue_Imp(source, name) as System.Collections.IEnumerable; 38 | if (enumerable == null) return null; 39 | var enm = enumerable.GetEnumerator(); 40 | for (int i = 0; i <= index; i++) { if (!enm.MoveNext()) return null; } 41 | return enm.Current; 42 | } 43 | public static object GetTargetObjectOfProperty(SerializedProperty prop) { 44 | if (prop == null) return null; 45 | var path = prop.propertyPath.Replace(".Array.data[", "["); 46 | object obj = prop.serializedObject.targetObject; 47 | var elements = path.Split('.'); 48 | foreach (var element in elements) { 49 | if (element.Contains("[")) { 50 | var elementName = element.Substring(0, element.IndexOf("[")); 51 | var index = System.Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", "")); 52 | obj = GetValue_Imp(obj, elementName, index); 53 | } 54 | else { 55 | obj = GetValue_Imp(obj, element); 56 | } 57 | } 58 | return obj; 59 | } 60 | 61 | // 62 | 63 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { 64 | var dVariable = GetTargetObjectOfProperty(property) as DynamicVariables; 65 | var variables = dVariable.Variables; 66 | var h = labelsHeight + buttonsHeight * 2; 67 | if (variables != null && variables.Count > 0) { h += variables.Count * entriesHeight + labelsHeight; } 68 | return h; 69 | } 70 | 71 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { 72 | var headerStyle = GetHeaderStyle(); 73 | 74 | var serializedObject = property.serializedObject; 75 | var dVariable = GetTargetObjectOfProperty(property) as DynamicVariables; 76 | var variables = dVariable.Variables; 77 | var variablesCount = variables != null ? variables.Count : 0; 78 | 79 | var r = new Rect(); 80 | position.width -= 5f; 81 | var w = position.width; 82 | GUI.Box(position, GUIContent.none); 83 | GUI.BeginGroup(position); 84 | 85 | r.Set(0f, 0f, w, labelsHeight); 86 | GUI.Label(r, label.text + " (" + variablesCount + "):", headerStyle); 87 | //GUI.changed = false; 88 | 89 | var isDirty = false; 90 | 91 | if (variablesCount > 0) { 92 | var typeWidth = 32f; 93 | var idWidth = Screen.width * 0.25f; 94 | r.Set(0f, r.y + r.height, 0f, labelsHeight); 95 | r.width = typeWidth; GUI.Label(r, "Typ"); 96 | r.x += r.width; r.width = idWidth; GUI.Label(r, "ID"); 97 | r.x += r.width; r.width = w - r.x; GUI.Label(r, "Value"); 98 | 99 | int i = 0; 100 | foreach (var v in variables) { 101 | r.Set(0f, r.y + r.height, w - 50f, entriesHeight); 102 | if (v != null) { 103 | var rw = r.width; r.width = typeWidth; GUI.Label(r, v.Unity3DGetButtonName().ToUpper()); 104 | r.x += r.width; r.width = idWidth; var oldID = v.ID; v.ID = GUI.TextField(r, v.ID ?? ""); isDirty = isDirty || (v.ID != oldID); 105 | r.x += r.width; r.width = rw - (idWidth + typeWidth); if (v.Unity3DSetValue(r)) { isDirty = true; } 106 | } 107 | 108 | r.x += r.width; r.width = 30f; 109 | if (GUI.Button(r, "-")) { 110 | // delete a variable 111 | variables.Remove(v); 112 | if (variables.Count == 0) { variables = null; } 113 | SetDirty(serializedObject); 114 | serializedObject.ApplyModifiedProperties(); 115 | return; 116 | } 117 | // sorting the variables: 118 | r.x += r.width; r.width = 20f; 119 | if (i++ != 0 && GUI.Button(r, "^")) { 120 | variables.Remove(v); 121 | variables.Insert(i - 2, v); 122 | SetDirty(serializedObject); 123 | serializedObject.ApplyModifiedProperties(); 124 | return; 125 | } 126 | } 127 | } 128 | 129 | r.Set(0f, r.y + r.height, w / 5f, buttonsHeight); 130 | if (GUI.Button(r, "+" + DynamicVarString.Unity3DButtonName)) { AddVariable(property, ref variables); } 131 | r.x += r.width; if (GUI.Button(r, "+" + DynamicVarInt.Unity3DButtonName) ) { AddVariable(property, ref variables); } 132 | r.x += r.width; if (GUI.Button(r, "+" + DynamicVarFloat.Unity3DButtonName) ) { AddVariable(property, ref variables); } 133 | r.x += r.width; if (GUI.Button(r, "+" + DynamicVarBool.Unity3DButtonName) ) { AddVariable(property, ref variables); } 134 | r.x += r.width; if (GUI.Button(r, "+" + DynamicVarObject.Unity3DButtonName)) { AddVariable(property, ref variables); } 135 | // can add more types here 136 | 137 | r.Set(0f, r.y + r.height, w, buttonsHeight); 138 | if (GUI.Button(r, "Clear all")) { 139 | variables.Clear(); 140 | variables = null; 141 | isDirty = true; 142 | } 143 | 144 | if (isDirty) { SetDirty(serializedObject); } 145 | 146 | GUI.EndGroup(); 147 | 148 | serializedObject.ApplyModifiedProperties(); 149 | } 150 | 151 | void AddVariable(SerializedProperty property, ref List variables) where T : IDynamicVar, new() { 152 | if (variables == null) { variables = new List(); } 153 | variables.Add(new T()); 154 | SetDirty(property.serializedObject); 155 | } 156 | 157 | void SetDirty(SerializedObject so) { 158 | if (so == null || so.targetObject == null) { return; } 159 | so.ApplyModifiedProperties(); 160 | EditorUtility.SetDirty(so.targetObject); 161 | if (AssetDatabase.IsMainAsset(so.targetObject)) { // TODO? 162 | // AssetDatabase.SaveAssets(); 163 | } 164 | else { 165 | var c = so.targetObject as Component; 166 | if (c != null) { UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(c.gameObject.scene); } 167 | } 168 | } 169 | } 170 | 171 | } -------------------------------------------------------------------------------- /RatKing/Base/Editor/EditorHelpers.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | namespace RatKing.Base { 5 | 6 | public class EditorHelpers { 7 | 8 | public static GUIStyle headerStyle; 9 | 10 | public static GUIStyle GetHeaderStyle() { 11 | if (headerStyle == null) { 12 | headerStyle = new GUIStyle(GUI.skin.GetStyle("label")) { richText = true }; 13 | } 14 | return headerStyle; 15 | } 16 | 17 | /// 18 | /// Text area where you can write stuff. It saves the value 19 | /// 20 | public static void TextArea(string label, ref string value, string saveInEditorPrevs = null, string saveInPlayerPrevs = null) { 21 | GUILayout.BeginHorizontal(); 22 | GUILayout.Label(label, GUILayout.Width(90), GUILayout.ExpandWidth(false)); 23 | var newValue = EditorGUILayout.TextField(string.IsNullOrEmpty(value) ? "" : value, GUILayout.Width(10), GUILayout.ExpandWidth(true)); 24 | GUILayout.EndHorizontal(); 25 | if (newValue.Trim() != value) { 26 | value = newValue.Trim(); 27 | if (!string.IsNullOrEmpty(saveInEditorPrevs)) { EditorPrefs.SetString(saveInEditorPrevs, value); } 28 | if (!string.IsNullOrEmpty(saveInPlayerPrevs)) { PlayerPrefs.SetString(saveInPlayerPrevs, value); } 29 | } 30 | } 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /RatKing/Base/Editor/EventVarFloatEditor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | namespace RatKing.Base { 7 | 8 | [CustomEditor(typeof(EventVarFloat))] 9 | [CanEditMultipleObjects] 10 | public class EventVarFloatEditor : Editor { 11 | public override void OnInspectorGUI() { 12 | base.OnInspectorGUI(); 13 | 14 | if (!serializedObject.isEditingMultipleObjects) { 15 | var evf = serializedObject.isEditingMultipleObjects ? null : (EventVarFloat)serializedObject.targetObject; 16 | EditorGUILayout.Space(); 17 | EditorGUILayout.LabelField("Current Value: " + evf.Value); 18 | EditorUtility.SetDirty(target); 19 | } 20 | } 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /RatKing/Base/Editor/EventVarIntEditor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | namespace RatKing.Base { 7 | 8 | [CustomEditor(typeof(EventVarInt))] 9 | [CanEditMultipleObjects] 10 | public class EventVarIntEditor : Editor { 11 | public override void OnInspectorGUI() { 12 | base.OnInspectorGUI(); 13 | 14 | if (!serializedObject.isEditingMultipleObjects) { 15 | var evi = serializedObject.isEditingMultipleObjects ? null : (EventVarInt)serializedObject.targetObject; 16 | EditorGUILayout.Space(); 17 | EditorGUILayout.LabelField("Current Value: " + evi.Value); 18 | EditorUtility.SetDirty(target); 19 | } 20 | } 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /RatKing/Base/Editor/OptionalPropertyDrawer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | //#if ODIN_INSPECTOR 6 | //using Sirenix.OdinInspector.Editor; 7 | //using Sirenix.Utilities.Editor; 8 | //#endif 9 | 10 | namespace RatKing.Base { 11 | 12 | // from https://www.youtube.com/watch?v=uZmWgQ7cLNI 13 | 14 | //#if ODIN_INSPECTOR 15 | // public class OptionalPropertyDrawer : OdinValueDrawer> { 16 | // protected override void DrawPropertyLayout(GUIContent label) { 17 | // var optional = this.ValueEntry.SmartValue; 18 | // 19 | // var enabled = this.Property.Children["k__BackingField"]; 20 | // var value = this.Property.Children["k__BackingField"]; 21 | // 22 | // enabled.Draw(label); 23 | // EditorGUI.BeginDisabledGroup(!optional.Enabled); 24 | // value.Draw(GUIContent.none); 25 | // EditorGUI.EndDisabledGroup(); 26 | // 27 | // this.ValueEntry.SmartValue = optional; 28 | // } 29 | //#else 30 | 31 | [CustomPropertyDrawer(typeof(Optional<>))] 32 | public class OptionalPropertyDrawer : PropertyDrawer { 33 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { 34 | var valProp = property.FindPropertyRelative("value"); 35 | return EditorGUI.GetPropertyHeight(valProp); 36 | } 37 | 38 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { 39 | //base.OnGUI(position, property, label); 40 | var valProp = property.FindPropertyRelative("value"); 41 | var enableProp = property.FindPropertyRelative("enabled"); 42 | 43 | position.width -= 24f; 44 | EditorGUI.BeginDisabledGroup(!enableProp.boolValue); 45 | EditorGUI.PropertyField(position, valProp, label, true); 46 | EditorGUI.EndDisabledGroup(); 47 | 48 | position.x += position.width + 34f; 49 | position.width = position.height = EditorGUI.GetPropertyHeight(enableProp); 50 | position.x -= position.width + 12f; 51 | EditorGUI.PropertyField(position, enableProp, GUIContent.none); 52 | } 53 | //#endif 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /RatKing/Base/Editor/PlayModeEditReminder.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | [InitializeOnLoad, ExecuteInEditMode] 4 | public static class PlayModeEditReminder { 5 | static GUIStyle style; 6 | static PlayModeEditReminder() { 7 | #if UNITY_2019_2_OR_NEWER 8 | SceneView.duringSceneGui += OnSceneGUI; 9 | #else 10 | SceneView.onSceneGUIDelegate += OnSceneGUI; 11 | #endif 12 | } 13 | static void OnSceneGUI(SceneView view) { 14 | if (Application.isPlaying && Selection.activeGameObject != null && Selection.activeGameObject.scene.name != null) { 15 | Handles.BeginGUI(); 16 | if (style == null) { 17 | style = new GUIStyle(GUI.skin.GetStyle("label")) { 18 | fontSize = 20, 19 | contentOffset = Vector2.zero, 20 | overflow = new RectOffset(), 21 | margin = new RectOffset(0,0,0,40), 22 | alignment = TextAnchor.LowerCenter, 23 | fontStyle = FontStyle.Bold, 24 | wordWrap = true, 25 | stretchHeight = true 26 | }; 27 | } 28 | var c = Mathf.Sin(Time.realtimeSinceStartup * 15f) * 0.5f + 0.5f; 29 | style.normal.textColor = new Color(1f, c, c, 1f); 30 | GUILayout.Label("PLAY MODE IS ACTIVE, CHANGES WON'T GET SAVED!", style); 31 | Handles.EndGUI(); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /RatKing/Base/Editor/Position2Drawer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | namespace RatKing.Base { 7 | 8 | [CustomPropertyDrawer(typeof(Position2))] 9 | public class Position2PropertyDrawer : PropertyDrawer { 10 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { 11 | EditorGUI.BeginProperty(position, label, property); 12 | position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label); 13 | var indent = EditorGUI.indentLevel; 14 | EditorGUI.indentLevel = 0; 15 | 16 | var width = position.width * 0.5f - 2f; 17 | var xRect = new Rect(position.x, position.y, width, position.height); 18 | var yRect = new Rect(position.x + width + 4f, position.y, width, position.height); 19 | 20 | EditorGUIUtility.labelWidth = 12f; 21 | EditorGUI.PropertyField(xRect, property.FindPropertyRelative("x"), new GUIContent("X")); 22 | EditorGUI.PropertyField(yRect, property.FindPropertyRelative("y"), new GUIContent("Y")); 23 | 24 | EditorGUI.indentLevel = indent; 25 | 26 | EditorGUI.EndProperty(); 27 | } 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /RatKing/Base/Editor/Position3Drawer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | namespace RatKing.Base { 7 | 8 | [CustomPropertyDrawer(typeof(Position3))] 9 | public class Position3PropertyDrawer : PropertyDrawer { 10 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { 11 | EditorGUI.BeginProperty(position, label, property); 12 | position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label); 13 | var indent = EditorGUI.indentLevel; 14 | EditorGUI.indentLevel = 0; 15 | 16 | var width = position.width / 3f - 1f; 17 | var xRect = new Rect(position.x, position.y, width, position.height); 18 | var yRect = new Rect(position.x + width + 1.5f, position.y, width, position.height); 19 | var zRect = new Rect(position.x + 2f * width + 3f, position.y, width, position.height); 20 | 21 | EditorGUIUtility.labelWidth = 10f; 22 | EditorGUI.PropertyField(xRect, property.FindPropertyRelative("x"), new GUIContent("X")); 23 | EditorGUI.PropertyField(yRect, property.FindPropertyRelative("y"), new GUIContent("Y")); 24 | EditorGUI.PropertyField(zRect, property.FindPropertyRelative("z"), new GUIContent("Z")); 25 | 26 | EditorGUI.indentLevel = indent; 27 | 28 | EditorGUI.EndProperty(); 29 | } 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /RatKing/Base/Editor/RangePropertyDrawer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | namespace RatKing.Base { 7 | 8 | [CustomPropertyDrawer(typeof(RangeInt))] 9 | [CustomPropertyDrawer(typeof(RangeFloat))] 10 | public class RangePropertyDrawer : PropertyDrawer { 11 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { 12 | EditorGUI.BeginProperty(position, label, property); 13 | position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label); 14 | var indent = EditorGUI.indentLevel; 15 | EditorGUI.indentLevel = 0; 16 | 17 | var width = position.width * 0.5f; 18 | var minRect = new Rect(position.x, position.y, width, position.height); 19 | var maxRect = new Rect(position.x + width, position.y, width, position.height); 20 | 21 | EditorGUIUtility.labelWidth = 32f; 22 | EditorGUI.PropertyField(minRect, property.FindPropertyRelative("min"), new GUIContent("min")); 23 | EditorGUI.PropertyField(maxRect, property.FindPropertyRelative("max"), new GUIContent("max")); 24 | 25 | EditorGUI.indentLevel = indent; 26 | 27 | EditorGUI.EndProperty(); 28 | } 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /RatKing/Base/Editor/SoundTypeEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Reflection; 6 | 7 | namespace RatKing.Base { 8 | 9 | [CustomEditor(typeof(SoundType))] 10 | [CanEditMultipleObjects] 11 | public class SoundTypeEditor : Editor { 12 | SerializedProperty clips; 13 | SerializedProperty volume; 14 | SerializedProperty pitch; 15 | SerializedProperty priority; 16 | SerializedProperty waitSeconds; 17 | SerializedProperty loop; 18 | SerializedProperty pan; 19 | SerializedProperty spatialBlend; 20 | SerializedProperty spread3D; 21 | SerializedProperty dopplerLevel; 22 | SerializedProperty distance3D; 23 | SerializedProperty startCount; 24 | SerializedProperty addCount; 25 | SerializedProperty variables; 26 | 27 | // 28 | 29 | void OnEnable() { 30 | clips = serializedObject.FindProperty("clips"); 31 | volume = serializedObject.FindProperty("volume"); 32 | pitch = serializedObject.FindProperty("pitch"); 33 | priority = serializedObject.FindProperty("priority"); 34 | waitSeconds = serializedObject.FindProperty("waitSeconds"); 35 | loop = serializedObject.FindProperty("loop"); 36 | pan = serializedObject.FindProperty("pan"); 37 | spatialBlend = serializedObject.FindProperty("spatialBlend"); 38 | spread3D = serializedObject.FindProperty("spread3D"); 39 | dopplerLevel = serializedObject.FindProperty("dopplerLevel"); 40 | distance3D = serializedObject.FindProperty("distance3D"); 41 | startCount = serializedObject.FindProperty("startCount"); 42 | addCount = serializedObject.FindProperty("addCount"); 43 | variables = serializedObject.FindProperty("variables"); 44 | StopAllClips(); 45 | } 46 | 47 | public override void OnInspectorGUI() { 48 | //base.OnInspectorGUI(); 49 | serializedObject.Update(); 50 | 51 | // AUDIO STUFF 52 | 53 | EditorGUILayout.PropertyField(clips, true); 54 | if (GUILayout.Button("Test") && clips != null && clips.arraySize > 0) { 55 | var idx = UnityEngine.Random.Range(0, clips.arraySize); 56 | var clip = clips.GetArrayElementAtIndex(idx).objectReferenceValue as AudioClip; 57 | if (Camera.main != null && clip != null) { 58 | PlayClip(clip); 59 | //StopTest(); 60 | 61 | //testSource = new GameObject("__TEMP__DELETE_ME__").AddComponent(); 62 | //testSource.gameObject.hideFlags = HideFlags.DontSave; 63 | //testSource.PlayOneShot(clip); 64 | 65 | //float timer = (float)EditorApplication.timeSinceStartup + clip.length; 66 | //testUpdateCall = () => { if (timer < EditorApplication.timeSinceStartup) { StopTest(); } }; 67 | //testStateChangeCall = (PlayModeStateChange state) => { StopTest(); }; 68 | //EditorApplication.playModeStateChanged += testStateChangeCall; 69 | //EditorApplication.update += testUpdateCall; 70 | } 71 | } 72 | EditorGUILayout.PropertyField(volume); 73 | EditorGUILayout.PropertyField(pitch); 74 | EditorGUILayout.PropertyField(priority); 75 | EditorGUILayout.PropertyField(waitSeconds); 76 | EditorGUILayout.PropertyField(loop); 77 | EditorGUILayout.PropertyField(pan); 78 | EditorGUILayout.PropertyField(spatialBlend); 79 | if (spatialBlend.floatValue > 0f) { 80 | EditorGUILayout.PropertyField(spread3D); 81 | EditorGUILayout.PropertyField(dopplerLevel); 82 | EditorGUILayout.PropertyField(distance3D); 83 | } 84 | 85 | EditorGUILayout.PropertyField(startCount); 86 | EditorGUILayout.PropertyField(addCount); 87 | 88 | EditorGUILayout.PropertyField(variables); 89 | 90 | serializedObject.ApplyModifiedProperties(); 91 | } 92 | 93 | #if UNITY_2019_2_OR_NEWER 94 | // https://forum.unity.com/threads/way-to-play-audio-in-editor-using-an-editor-script.132042/#post-4767824 95 | 96 | public static void PlayClip(AudioClip clip, int startSample = 0, bool loop = false) { 97 | System.Reflection.Assembly unityEditorAssembly = typeof(AudioImporter).Assembly; 98 | System.Type audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil"); 99 | System.Reflection.MethodInfo method = audioUtilClass.GetMethod( 100 | #if UNITY_2020_2_OR_NEWER 101 | "PlayPreviewClip", 102 | #else 103 | "PlayClip", 104 | #endif 105 | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public, 106 | null, 107 | new System.Type[] { typeof(AudioClip), typeof(int), typeof(bool) }, 108 | null 109 | ); 110 | method.Invoke( 111 | null, 112 | new object[] { clip, startSample, loop } 113 | ); 114 | } 115 | 116 | #else 117 | // https://answers.unity.com/questions/36388/how-to-play-audioclip-in-edit-mode.html 118 | 119 | public static void PlayClip(AudioClip clip) { 120 | var unityEditorAssembly = typeof(AudioImporter).Assembly; 121 | var audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil"); 122 | var method = audioUtilClass.GetMethod( 123 | "PlayClip", 124 | BindingFlags.Static | BindingFlags.Public, 125 | null, 126 | new System.Type[] { 127 | typeof(AudioClip) 128 | }, 129 | null 130 | ); 131 | method.Invoke( 132 | null, 133 | new object[] { 134 | clip 135 | } 136 | ); 137 | } 138 | #endif 139 | 140 | public static void StopAllClips() { 141 | var unityEditorAssembly = typeof(AudioImporter).Assembly; 142 | var audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil"); 143 | var method = audioUtilClass.GetMethod( 144 | #if UNITY_2020_2_OR_NEWER 145 | "StopAllPreviewClips", 146 | #else 147 | "StopAllClips", 148 | #endif 149 | BindingFlags.Static | BindingFlags.Public, 150 | null, 151 | new System.Type[] { }, 152 | null 153 | ); 154 | method.Invoke( 155 | null, 156 | new object[] { } 157 | ); 158 | } 159 | } 160 | 161 | } -------------------------------------------------------------------------------- /RatKing/Base/Editor/StoneBuilderSettings.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | 4 | namespace RatKing.Base { 5 | 6 | [System.Serializable] 7 | public class StoneBuilderSettings : ScriptableObject { 8 | // saved in file (ie. gets versioned): 9 | public string gameShortName = "AppName"; 10 | public string subfolderName = "GameFolder"; 11 | public string version = "0.0.1"; 12 | public bool useBundleVersion = false; 13 | public List levels = new List(); 14 | public Object[] includedFiles = new Object[0]; 15 | public Object[] includedFilesWithDirStruct = new Object[0]; 16 | [Multiline] public string script = ""; 17 | public bool createItchBat = false; 18 | public string itchUsername; 19 | public string itchGamename; 20 | public string itchAdditionalTags; 21 | [Multiline] public string itchAddScript = ""; 22 | // saved in playerprefs (ie. individual for each workstation): 23 | [System.NonSerialized] public string buildPath = "C:/BUILDS"; 24 | [System.NonSerialized] public List targetsActive = new List(); 25 | #if UNITY_EDITOR 26 | [System.NonSerialized] public UnityEditor.BuildOptions optionsMask; 27 | #endif 28 | [System.NonSerialized] public bool openAfterBuild; 29 | [System.NonSerialized] public bool ignorePDB = true; 30 | [System.NonSerialized] public bool packWinBinsAs7Zip = true; 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /RatKing/Base/Editor/TemplateVariablesDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | [CustomPropertyDrawer(typeof(TemplateVariables))] 8 | public class TemplateVariablesDrawer : PropertyDrawer { 9 | static readonly float labelsHeight = 18f; 10 | static readonly float buttonsHeight = 20f; 11 | static readonly float entriesHeight = 20f; 12 | 13 | // 14 | 15 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { 16 | var serializedObject = property.serializedObject; 17 | var templateVariables = fieldInfo.GetValue(serializedObject.targetObject) as TemplateVariables; 18 | var variables = templateVariables.List; 19 | var h = labelsHeight + buttonsHeight * 2; 20 | if (variables != null && variables.Count > 0) { h += variables.Count * entriesHeight + labelsHeight; } 21 | return h; 22 | } 23 | 24 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { 25 | var headerStyle = EditorHelpers.GetHeaderStyle(); 26 | 27 | //EditorGUI.BeginProperty(position, label, property); 28 | 29 | var serializedObject = property.serializedObject; 30 | var templateVariables = fieldInfo.GetValue(serializedObject.targetObject) as TemplateVariables; 31 | var variables = templateVariables.List; 32 | var variablesCount = variables != null ? variables.Count : 0; 33 | 34 | var r = new Rect(); 35 | position.width -= 5f; 36 | var w = position.width; 37 | GUI.Box(position, GUIContent.none); 38 | GUI.BeginGroup(position); 39 | 40 | r.Set(0f, 0f, w, labelsHeight); 41 | GUI.Label(r, "" + label.text + " (" + variablesCount + "):", headerStyle); 42 | //GUI.changed = false; 43 | 44 | if (variablesCount > 0) { 45 | r.Set(0f, r.y + r.height, 0f, labelsHeight); 46 | r.width = 38f; GUI.Label(r, "TYP"); 47 | r.x += r.width; r.width = 62f; GUI.Label(r, "ID"); 48 | r.x += r.width; r.width = w - r.x; GUI.Label(r, "VAL"); 49 | 50 | int i = 0; 51 | for (var iter = variables.GetEnumerator(); iter.MoveNext();) { 52 | var v = iter.Current; 53 | 54 | r.Set(0f, r.y + r.height, w - 50f, entriesHeight); 55 | if (v != null && v.Unity3DDrawAndCheck(r)) { 56 | Selection.activeObject = v; 57 | } 58 | 59 | r.x += r.width; r.width = 30f; 60 | if (GUI.Button(r, "-")) { 61 | // delete a variable 62 | variables.Remove(v); 63 | Object.DestroyImmediate(v, true); 64 | AssetDatabase.SaveAssets(); 65 | if (variables.Count == 0) { variables = null; } 66 | return; 67 | } 68 | // sorting the variables: 69 | r.x += r.width; r.width = 20f; 70 | if (i != 0 && GUI.Button(r, "^")) { 71 | variables.Remove(v); 72 | variables.Insert(i - 1, v); 73 | AssetDatabase.SaveAssets(); 74 | return; 75 | } 76 | ++i; 77 | } 78 | } 79 | 80 | r.Set(0f, r.y + r.height, w / 5f, buttonsHeight); 81 | if (GUI.Button(r, "+Txt" )) { AddVariable(serializedObject.targetObject, ref variables); } 82 | r.x += r.width; if (GUI.Button(r, "+Int" )) { AddVariable(serializedObject.targetObject, ref variables); } 83 | r.x += r.width; if (GUI.Button(r, "+Float")) { AddVariable(serializedObject.targetObject, ref variables); } 84 | r.x += r.width; if (GUI.Button(r, "+Bool" )) { AddVariable(serializedObject.targetObject, ref variables); } 85 | r.x += r.width; if (GUI.Button(r, "+List" )) { AddVariable(serializedObject.targetObject, ref variables); } 86 | // can add more types here 87 | 88 | r.Set(0f, r.y + r.height, w, buttonsHeight); 89 | if (GUI.Button(r, "Clear all")) { 90 | var objs = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(serializedObject.targetObject)); 91 | for (int j = 0; j < objs.Length; ++j) { 92 | if (objs[j] is TemplateVar) { 93 | if (variables.Contains((TemplateVar)objs[j])) { // comment this check if you want to delete all sub-SOs because they got stuck 94 | Object.DestroyImmediate(objs[j], true); 95 | } 96 | } 97 | } 98 | variables.Clear(); 99 | variables = null; 100 | AssetDatabase.SaveAssets(); 101 | return; 102 | } 103 | 104 | GUI.EndGroup(); 105 | 106 | //EditorGUI.EndProperty(); 107 | } 108 | 109 | public static void AddVariable(Object asset, ref List variables) where T : TemplateVar { 110 | if (variables == null) { variables = new List(); } 111 | var si = ScriptableObject.CreateInstance(); 112 | variables.Add(si); 113 | EditorUtility.SetDirty(si); 114 | AssetDatabase.AddObjectToAsset(si, asset); 115 | AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(asset)); 116 | } 117 | } 118 | 119 | } -------------------------------------------------------------------------------- /RatKing/Base/Editor/VarFloatEditor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | namespace RatKing.Base { 7 | 8 | [CustomEditor(typeof(VarFloat))] 9 | [CanEditMultipleObjects] 10 | public class VarFloatEditor : Editor { 11 | public override void OnInspectorGUI() { 12 | base.OnInspectorGUI(); 13 | 14 | if (!serializedObject.isEditingMultipleObjects) { 15 | var vf = serializedObject.isEditingMultipleObjects ? null : (VarFloat)serializedObject.targetObject; 16 | EditorGUILayout.Space(); 17 | EditorGUILayout.LabelField("Current Value: " + vf.value); 18 | EditorUtility.SetDirty(target); 19 | } 20 | } 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /RatKing/Base/Editor/VarIntEditor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | namespace RatKing.Base { 7 | 8 | [CustomEditor(typeof(VarInt))] 9 | [CanEditMultipleObjects] 10 | public class VarIntEditor : Editor { 11 | public override void OnInspectorGUI() { 12 | base.OnInspectorGUI(); 13 | 14 | if (!serializedObject.isEditingMultipleObjects) { 15 | var vi = serializedObject.isEditingMultipleObjects ? null : (VarInt)serializedObject.targetObject; 16 | EditorGUILayout.Space(); 17 | EditorGUILayout.LabelField("Current Value: " + vi.value); 18 | EditorUtility.SetDirty(target); 19 | } 20 | } 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /RatKing/Base/Examples/Localisation/English.json: -------------------------------------------------------------------------------- 1 | { 2 | "buildings": { 3 | "townhall": { 4 | "name": "A townhall", 5 | "description": "Increases your influence" 6 | }, 7 | "townhall": { 8 | "name": "A mill", 9 | "description": "Makes flour." 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /RatKing/Base/Examples/Localisation/languages.json: -------------------------------------------------------------------------------- 1 | { 2 | "English": { 3 | "name": "English", 4 | "code": "en", 5 | "file": "English.json" 6 | } 7 | } -------------------------------------------------------------------------------- /RatKing/Base/Examples/TemplateVars/SampleClassWithInstancedTemplateVars.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base.Samples { 6 | 7 | public class SampleClassWithInstancedTemplateVars { 8 | public SampleTypeWithTemplateVars Type { get; private set; } 9 | public Base.InstancedVariablesContainer Variables { get; private set; } 10 | 11 | // 12 | 13 | public SampleClassWithInstancedTemplateVars(SampleTypeWithTemplateVars type) { 14 | Type = type; 15 | Variables = new Base.InstancedVariablesContainer(type.Variables); 16 | } 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /RatKing/Base/Examples/TemplateVars/SampleTypeWithTemplateVars.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base.Samples { 6 | 7 | public class SampleTypeWithTemplateVars : ScriptableObject { 8 | [SerializeField] string id = ""; 9 | public string ID { get => id; } 10 | [SerializeField] Base.TemplateVariables constants = null; 11 | public Base.TemplateVariables Constants { get => constants; } 12 | [SerializeField] Base.TemplateVariables variables = null; 13 | public Base.TemplateVariables Variables { get => variables; } 14 | 15 | // 16 | 17 | public T GetVariable(string id, T standardValue = default) where T:Base.TemplateVar { 18 | if (variables != null) { return variables.Get(id, standardValue); } 19 | return standardValue; 20 | } 21 | 22 | // "Constants" are just variables, but they should not be overwritten per instanced object 23 | public T GetConstant(string id, T standardValue = default) { 24 | if (constants != null) { return constants.GetByBaseType(id, standardValue); } 25 | return standardValue; 26 | } 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /RatKing/Base/ImageEffects/GlobalFog.shader: -------------------------------------------------------------------------------- 1 | // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' 2 | 3 | Shader "Hidden/A Rat King/GlobalFog" { 4 | Properties { 5 | _MainTex ("Base (RGB)", 2D) = "black" {} 6 | _Color ("Color", Color) = (0.5, 0.5, 0.5, 0.5) 7 | } 8 | 9 | CGINCLUDE 10 | 11 | #include "UnityCG.cginc" 12 | 13 | uniform sampler2D _MainTex; 14 | uniform sampler2D_float _CameraDepthTexture; 15 | 16 | // x = fog height 17 | // y = FdotC (CameraY-FogHeight) 18 | // z = k (FdotC > 0.0) 19 | // w = a/2 20 | uniform float4 _HeightParams; 21 | 22 | // x = start distance 23 | uniform float4 _DistanceParams; 24 | 25 | int4 _SceneFogMode; // x = fog mode, y = use radial flag 26 | float4 _SceneFogParams; 27 | half4 _Color; 28 | #ifndef UNITY_APPLY_FOG 29 | half4 unity_FogDensity; 30 | #endif 31 | 32 | uniform float4 _MainTex_TexelSize; 33 | 34 | // for fast world space reconstruction 35 | uniform float4x4 _FrustumCornersWS; 36 | uniform float4 _CameraWS; 37 | 38 | struct v2f { 39 | float4 pos : SV_POSITION; 40 | float2 uv : TEXCOORD0; 41 | float2 uv_depth : TEXCOORD1; 42 | float4 interpolatedRay : TEXCOORD2; 43 | }; 44 | 45 | v2f vert (appdata_img v) 46 | { 47 | v2f o; 48 | half index = v.vertex.z; 49 | v.vertex.z = 0.1; 50 | o.pos = UnityObjectToClipPos(v.vertex); 51 | o.uv = v.texcoord.xy; 52 | o.uv_depth = v.texcoord.xy; 53 | 54 | #if UNITY_UV_STARTS_AT_TOP 55 | if (_MainTex_TexelSize.y < 0) 56 | o.uv.y = 1-o.uv.y; 57 | #endif 58 | 59 | o.interpolatedRay = _FrustumCornersWS[(int)index]; 60 | o.interpolatedRay.w = index; 61 | 62 | return o; 63 | } 64 | 65 | // Applies one of standard fog formulas, given fog coordinate (i.e. distance) 66 | half ComputeFogFactor (float coord) 67 | { 68 | float fogFac = 0.0; 69 | if (_SceneFogMode.x == 1) // linear 70 | { 71 | // factor = (end-z)/(end-start) = z * (-1/(end-start)) + (end/(end-start)) 72 | fogFac = coord * _SceneFogParams.z + _SceneFogParams.w; 73 | } 74 | if (_SceneFogMode.x == 2) // exp 75 | { 76 | // factor = exp(-density*z) 77 | fogFac = _SceneFogParams.y * coord; fogFac = exp2(-fogFac); 78 | } 79 | if (_SceneFogMode.x == 3) // exp2 80 | { 81 | // factor = exp(-(density*z)^2) 82 | fogFac = _SceneFogParams.x * coord; fogFac = exp2(-fogFac*fogFac); 83 | } 84 | return saturate(fogFac); 85 | } 86 | 87 | // Distance-based fog 88 | float ComputeDistance (float3 camDir, float zdepth) 89 | { 90 | float dist; 91 | if (_SceneFogMode.y == 1) 92 | dist = length(camDir); 93 | else 94 | dist = zdepth * _ProjectionParams.z; 95 | // Built-in fog starts at near plane, so match that by 96 | // subtracting the near value. Not a perfect approximation 97 | // if near plane is very large, but good enough. 98 | dist -= _ProjectionParams.y; 99 | return dist; 100 | } 101 | 102 | // Linear half-space fog, from https://www.terathon.com/lengyel/Lengyel-UnifiedFog.pdf 103 | float ComputeHalfSpace (float3 wsDir) 104 | { 105 | float3 wpos = _CameraWS + wsDir; 106 | float FH = _HeightParams.x; 107 | float3 C = _CameraWS; 108 | float3 V = wsDir; 109 | float3 P = wpos; 110 | float3 aV = _HeightParams.w * V; 111 | float FdotC = _HeightParams.y; 112 | float k = _HeightParams.z; 113 | float FdotP = P.y-FH; 114 | float FdotV = wsDir.y; 115 | float c1 = k * (FdotP + FdotC); 116 | float c2 = (1-2*k) * FdotP; 117 | float g = min(c2, 0.0); 118 | g = -length(aV) * (c1 - g * g / abs(FdotV+1.0e-5f)); 119 | return g; 120 | } 121 | 122 | half4 ComputeFog (v2f i, bool distance, bool height) : SV_Target 123 | { 124 | half4 sceneColor = tex2D(_MainTex, i.uv); 125 | 126 | // Reconstruct world space position & direction 127 | // towards this screen pixel. 128 | float rawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth); 129 | float dpth = Linear01Depth(rawDepth); 130 | float4 wsDir = dpth * i.interpolatedRay; 131 | float4 wsPos = _CameraWS + wsDir; 132 | 133 | // Compute fog distance 134 | float g = _DistanceParams.x; 135 | if (distance) 136 | g += ComputeDistance (wsDir, dpth); 137 | if (height) 138 | g += ComputeHalfSpace (wsDir); 139 | 140 | // Compute fog amount 141 | half fogFac = ComputeFogFactor (max(0.0,g)); 142 | // Do not fog skybox 143 | if (rawDepth >= 0.999999) 144 | fogFac = 1.0; 145 | //return fogFac; // for debugging 146 | 147 | // Lerp between fog color & original scene color 148 | // by fog amount 149 | return lerp(sceneColor, lerp (_Color, sceneColor, fogFac), _Color.a); 150 | } 151 | 152 | ENDCG 153 | 154 | SubShader 155 | { 156 | ZTest Always Cull Off ZWrite Off Fog { Mode Off } 157 | 158 | // 0: distance + height 159 | Pass 160 | { 161 | CGPROGRAM 162 | #pragma vertex vert 163 | #pragma fragment frag 164 | half4 frag (v2f i) : SV_Target { return ComputeFog (i, true, true); } 165 | ENDCG 166 | } 167 | // 1: distance 168 | Pass 169 | { 170 | CGPROGRAM 171 | #pragma vertex vert 172 | #pragma fragment frag 173 | half4 frag (v2f i) : SV_Target { return ComputeFog (i, true, false); } 174 | ENDCG 175 | } 176 | // 2: height 177 | Pass 178 | { 179 | CGPROGRAM 180 | #pragma vertex vert 181 | #pragma fragment frag 182 | half4 frag (v2f i) : SV_Target { return ComputeFog (i, false, true); } 183 | ENDCG 184 | } 185 | } 186 | 187 | Fallback off 188 | 189 | } 190 | -------------------------------------------------------------------------------- /RatKing/Base/Materials/Creature.physicMaterial: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!134 &13400000 4 | PhysicMaterial: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInternal: {fileID: 0} 8 | m_Name: Creature 9 | dynamicFriction: 0 10 | staticFriction: 0 11 | bounciness: 0 12 | frictionCombine: 1 13 | bounceCombine: 1 14 | -------------------------------------------------------------------------------- /RatKing/Base/Materials/VertexColored.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: VertexColored 10 | m_Shader: {fileID: 4800000, guid: 0582bd648409a6644b883b87916e04ac, type: 3} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _MainTex: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | m_Floats: 26 | - _Emission: 0 27 | m_Colors: 28 | - _Color: {r: 1, g: 1, b: 1, a: 1} 29 | -------------------------------------------------------------------------------- /RatKing/Base/ScriptTemplates/81-C# Script-NewBehaviourScript.cs.txt: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace RatKing { 6 | 7 | public class #SCRIPTNAME# : MonoBehaviour { 8 | } 9 | 10 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Audio/Music.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine.Audio; 5 | 6 | namespace RatKing.Base { 7 | 8 | public class Music : MonoBehaviour { 9 | 10 | class MusicSource { 11 | public AudioSource source; 12 | public float targetVolume; 13 | public float fadeSpeed; 14 | public float curVolume; 15 | public bool unused; 16 | public int priority; 17 | } 18 | 19 | public static float GlobalVolume = 1f; 20 | 21 | static AudioMixerGroup curMixerGroup; 22 | static GameObject go; 23 | static readonly Dictionary> sources = new Dictionary>(); 24 | static Music Inst; 25 | 26 | // 27 | 28 | [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] 29 | static void OnRuntimeInitializeOnLoad() { 30 | Inst = null; 31 | GlobalVolume = 1f; 32 | curMixerGroup = null; 33 | sources.Clear(); 34 | } 35 | 36 | // 37 | 38 | static void Init() { 39 | if (Inst != null) { return; } 40 | go = new GameObject(""); 41 | DontDestroyOnLoad(go); 42 | Inst = go.AddComponent(); 43 | } 44 | 45 | void Update() { 46 | for (var iter = sources.GetEnumerator(); iter.MoveNext();) { 47 | var curSources = iter.Current.Value; 48 | 49 | // check priority first, remove sources 50 | var priority = -1; 51 | var mainIndex = -1; 52 | for (int i = curSources.Count - 1; i >= 0; --i) { 53 | var s = curSources[i]; 54 | if (s.source == null) { curSources.RemoveAt(i); continue; } 55 | if (s.unused || s.targetVolume <= 0f) { continue; } 56 | if (s.priority <= priority) { continue; } 57 | priority = s.priority; 58 | mainIndex = i; 59 | } 60 | 61 | for (int i = curSources.Count - 1; i >= 0; --i) { 62 | var s = curSources[i]; 63 | if (s.unused) { continue; } 64 | var targetVolume = (i == mainIndex) ? s.targetVolume : 0f; 65 | if (!Mathf.Approximately(s.curVolume, targetVolume)) { 66 | s.curVolume = Mathf.MoveTowards(s.curVolume, targetVolume, s.fadeSpeed * Time.unscaledDeltaTime); 67 | s.source.volume = s.curVolume * GlobalVolume; 68 | if (s.curVolume <= 0f && i == mainIndex) { s.unused = true; s.source.Stop(); } 69 | } 70 | else { 71 | s.source.volume = targetVolume * GlobalVolume; 72 | } 73 | } 74 | } 75 | } 76 | 77 | static MusicSource CreateSource(string layer = "") { 78 | if (Inst == null) { Init(); } 79 | var s = new MusicSource(); 80 | var ss = s.source = go.AddComponent(); 81 | ss.spatialBlend = 0f; 82 | ss.volume = s.targetVolume = s.curVolume = 0f; 83 | ss.playOnAwake = false; 84 | ss.loop = true; 85 | s.unused = false; 86 | if (!sources.ContainsKey(layer)) { sources[layer] = new List() { s }; } 87 | else { sources[layer].Add(s); } 88 | return s; 89 | } 90 | 91 | static void SetTargetVolume(MusicSource source, float targetVolume, float fadeTime) { 92 | source.targetVolume = targetVolume; 93 | var t = Mathf.Abs(source.curVolume - targetVolume); 94 | source.fadeSpeed = t / fadeTime; 95 | //Debug.Log("--> " + source.source.clip + " to " + targetVolume + " over " + fadeTime + " seconds -> speed = " + source.fadeSpeed); 96 | Inst.enabled = true; 97 | } 98 | 99 | public static void Stop(float fadeTime = 5f, int priority = -1, string layer = null) { 100 | //Debug.Log("STOP MUSIC"); 101 | if (Inst == null) { return; } 102 | if (layer == null) { 103 | for (var iter = sources.GetEnumerator(); iter.MoveNext();) { 104 | var curSources = iter.Current.Value; 105 | if (fadeTime > 0f) { foreach (var s in curSources) { if (!s.unused && (priority == -1 || s.priority == priority)) { SetTargetVolume(s, 0f, fadeTime); } } } 106 | else { foreach (var s in curSources) { if (priority == -1 || s.priority == priority) { s.unused = true; s.source.volume = 0f; s.source.Stop(); } } } 107 | } 108 | } 109 | else { 110 | if (!sources.ContainsKey(layer)) { return; } 111 | var curSources = sources[layer]; 112 | if (fadeTime > 0f) { foreach (var s in curSources) { if (!s.unused && (priority == -1 || s.priority == priority)) { SetTargetVolume(s, 0f, fadeTime); } } } 113 | else { foreach (var s in curSources) { if (priority == -1 || s.priority == priority) { s.unused = true; s.source.volume = 0f; s.source.Stop(); } } } 114 | } 115 | } 116 | 117 | public static void SetAudioMixerGroup(AudioMixerGroup group) { 118 | if (sources != null && sources.Count > 0) { 119 | foreach (var s in sources) { 120 | foreach (var m in s.Value) { 121 | m.source.outputAudioMixerGroup = group; 122 | } 123 | } 124 | } 125 | curMixerGroup = group; 126 | } 127 | 128 | public static void Play(AudioClip clip, float volume = 0.3f, float fadeTime = 5f, int priority = 0, string layer = "") { 129 | if (layer == null) { return; } 130 | if (Inst == null) { if (clip == null || volume <= 0f) { return; } Init(); } 131 | if (clip == null) { Stop(fadeTime, priority, layer); return; } 132 | 133 | // already playing? 134 | List curSources = null; 135 | if (sources.ContainsKey(layer)) { curSources = sources[layer]; } 136 | if (curSources != null) { 137 | foreach (var s in curSources) { 138 | if (!s.unused && s.source.clip == clip) { 139 | Stop(fadeTime, priority, layer); // stop all others 140 | SetTargetVolume(s, volume, fadeTime); 141 | s.priority = priority; 142 | return; 143 | } 144 | } 145 | } 146 | 147 | // new playing 148 | MusicSource useSource = null; 149 | if (curSources != null) { 150 | foreach (var s in curSources) { 151 | if (s.unused) { if (useSource == null) { useSource = s; } } 152 | // else { SetTargetVolume(s, 0f, fadeTime); } 153 | } 154 | } 155 | if (useSource == null) { useSource = CreateSource(layer); } 156 | useSource.source.outputAudioMixerGroup = curMixerGroup; 157 | useSource.source.clip = clip; 158 | SetTargetVolume(useSource, volume, fadeTime); 159 | useSource.unused = false; 160 | useSource.priority = priority; 161 | useSource.source.Play(); 162 | } 163 | } 164 | 165 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Audio/Sound.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace RatKing.Base { 4 | 5 | public class Sound : MonoBehaviour { 6 | public SoundType Type { get; private set; } 7 | public bool IsPaused { get; private set; } 8 | public bool InUse { get; private set; } 9 | public Transform Follow { get; set; } 10 | public string Tag { get; set; } 11 | public AudioSource Source { get { return source; } } 12 | 13 | AudioSource source; 14 | 15 | // 16 | 17 | float volume; 18 | public float Volume { 19 | get { return volume; } 20 | set { 21 | if (!InUse || source == null) { return; } 22 | source.volume = (volume = value) * Sounds.GlobalVolume; 23 | } 24 | } 25 | 26 | public bool IsPlaying { 27 | get { 28 | return InUse && source != null && source.isPlaying; 29 | } 30 | } 31 | 32 | // 33 | 34 | public static Sound Play(SoundType type, Transform follow, string tag = null) { 35 | return type != null ? type.Play(follow, tag) : null; 36 | } 37 | 38 | public static Sound Play(SoundType type, Vector3 position, string tag = null) { 39 | return type != null ? type.Play(position, tag) : null; 40 | } 41 | 42 | public static Sound Play(SoundType type, string tag = null) { 43 | return type != null ? type.Play(tag) : null; 44 | } 45 | 46 | public static bool TryPlay(out Sound sound, SoundType type, Transform follow, string tag = null) { 47 | sound = type != null ? type.Play(follow, tag) : null; 48 | return sound != null; 49 | } 50 | 51 | public static bool TryPlay(out Sound sound, SoundType type, Vector3 position, string tag = null) { 52 | sound = type != null ? type.Play(position, tag) : null; 53 | return sound != null; 54 | } 55 | 56 | public static bool TryPlay(out Sound sound, SoundType type, string tag = null) { 57 | sound = type != null ? type.Play(tag) : null; 58 | return sound != null; 59 | } 60 | 61 | public static bool Stop(Sound sound) { 62 | if (sound == null) { return false; } 63 | sound.Stop(); 64 | return true; 65 | } 66 | 67 | public static bool StopAndSetNull(ref Sound sound) { 68 | if (sound == null) { return false; } 69 | sound.Stop(); 70 | sound = null; 71 | return true; 72 | } 73 | 74 | // 75 | 76 | public void PlayType(SoundType type, int clipIndex = -1, Vector3 pos = default) { 77 | Tag = null; 78 | Follow = null; 79 | InUse = true; 80 | IsPaused = false; 81 | Type = type; 82 | var src = source = GetComponent(); 83 | src.transform.position = pos; 84 | if (clipIndex >= 0) { type.CurPlayIndex = clipIndex % Type.Clips.Length; } 85 | else if (type.Clips.Length == 1) { type.CurPlayIndex = 0; } 86 | else if (type.RandomOrder) { type.CurPlayIndex = (type.CurPlayIndex < 0) ? Random.Range(0, type.Clips.Length) : (type.CurPlayIndex + Random.Range(0, type.Clips.Length - 1)) % type.Clips.Length; } 87 | else { type.CurPlayIndex = (type.CurPlayIndex + 1) % type.Clips.Length; } 88 | src.clip = type.Clips[type.CurPlayIndex]; 89 | src.volume = (volume = type.Volume.Random()) * Sounds.GlobalVolume; 90 | src.pitch = type.Pitch.Random(); 91 | src.outputAudioMixerGroup = type.MixerGroup; 92 | if (type.SpatialBlend > 0f) { 93 | src.minDistance = type.Distance3D.min; 94 | src.maxDistance = type.Distance3D.max; 95 | } 96 | src.Play(); 97 | } 98 | 99 | public bool Pause() { 100 | if (!InUse || IsPaused) { return false; } 101 | IsPaused = true; 102 | source.Pause(); 103 | return true; 104 | } 105 | 106 | public bool Resume() { 107 | if (!InUse || !IsPaused) { return false; } 108 | IsPaused = false; 109 | source.Play(); 110 | return true; 111 | } 112 | 113 | public bool Stop() { 114 | if (!InUse) { return false; } 115 | IsPaused = false; 116 | source.Stop(); 117 | InUse = false; 118 | return true; 119 | } 120 | 121 | public bool Rewind() { 122 | if (!InUse) { return false; } 123 | source.time = 0f; 124 | return true; 125 | } 126 | 127 | public bool SetNormalizedTime(float t) { 128 | if (!InUse || source.clip == null) { return false; } 129 | source.time = Mathf.Repeat(t, 1f) * source.clip.length; 130 | return true; 131 | } 132 | } 133 | 134 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Audio/SoundType.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine.Audio; 5 | 6 | namespace RatKing.Base { 7 | 8 | [CreateAssetMenu(fileName = "SND", menuName = "Rat King/New Sound Type")] 9 | public class SoundType : ScriptableObject { 10 | [SerializeField] AudioMixerGroup mixerGroup = null; 11 | [SerializeField] AudioClip[] clips = null; 12 | [SerializeField] bool randomOrder = true; 13 | [SerializeField] RangeFloat volume = new RangeFloat(0.5f, 0.6f); 14 | [SerializeField] RangeFloat pitch = new RangeFloat(1f, 1f); 15 | [SerializeField, Range(0f, 1f)] float priority = 0.5f; 16 | [SerializeField] RangeFloat waitSeconds = new RangeFloat(0f, 0f); 17 | [SerializeField] bool loop = false; 18 | [SerializeField, Range(-1f, 1f)] float pan = 0f; 19 | [Header("2D or 3D")] 20 | [SerializeField, Range(0f, 1f)] float spatialBlend = 0f; 21 | [SerializeField, Range(0f, 360f)] float spread3D = 0f; 22 | [SerializeField, Range(0f, 5f)] float dopplerLevel = 1f; 23 | [SerializeField] RangeFloat distance3D = new RangeFloat(5f, 20f); 24 | [Header("Pooling")] 25 | [SerializeField] int startCount = 3; 26 | [SerializeField] int addCount = 1; 27 | [Header("User Data")] 28 | [SerializeField] DynamicVariables variables = new(); 29 | 30 | public AudioMixerGroup MixerGroup { get { return mixerGroup; } } 31 | public AudioClip[] Clips { get { return clips; } } 32 | public bool RandomOrder { get { return randomOrder; } } 33 | public RangeFloat Volume { get { return volume; } } 34 | public RangeFloat Pitch { get { return pitch; } } 35 | public float Priority { get { return priority; } } 36 | public RangeFloat WaitSeconds { get { return waitSeconds; } } 37 | public bool Loop { get { return loop; } } 38 | public float Pan { get { return pan; } } 39 | public float SpatialBlend { get { return spatialBlend; } } 40 | public float Spread3D { get { return spread3D; } } 41 | public float DopplerLevel { get { return dopplerLevel; } } 42 | public RangeFloat Distance3D { get { return distance3D; } } 43 | public int PoolStartCount { get { return startCount; } } 44 | public int PoolAddCount { get { return addCount; } } 45 | public DynamicVariables UserData { get { return variables; } } 46 | 47 | public int CurPlayIndex { get; set; } = -1; 48 | 49 | // 50 | 51 | public Sound Play(Transform follow, string tag = null) { 52 | if (follow == null) { return null; } 53 | var sound = Sounds.GetOrCreateInstance().Play(this, follow.position); 54 | if (sound == null) { return null; } 55 | sound.Follow = follow; 56 | sound.Tag = tag; 57 | return sound; 58 | } 59 | 60 | public Sound Play(Vector3 position, string tag = null) { 61 | var sound = Sounds.GetOrCreateInstance().Play(this, position); 62 | if (sound == null) { return null; } 63 | sound.Tag = tag; 64 | return sound; 65 | } 66 | 67 | public Sound Play(string tag = null) { 68 | var sound = Sounds.GetOrCreateInstance().Play(this); 69 | if (sound == null) { return null; } 70 | sound.Tag = tag; 71 | return sound; 72 | } 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Child.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace RatKing.Base { 6 | 7 | public class Child : MonoBehaviour { 8 | [SerializeField] Transform root = null; 9 | public Transform Root => root; 10 | 11 | #if UNITY_EDITOR 12 | void OnValidate() { 13 | if (root == null) { root = transform.parent; } 14 | } 15 | #endif 16 | 17 | // 18 | 19 | public void ChangeRoot(Transform root) { 20 | this.root = root; 21 | } 22 | 23 | public T GetRootComponent() where T : Component { 24 | return (root != null ? root : transform).GetComponent(); 25 | } 26 | 27 | public T[] GetRootComponents() where T : Component { 28 | return (root != null ? root : transform).GetComponents(); 29 | } 30 | 31 | public T GetRootComponentInChildren(bool includeInactive = false) where T : Component { 32 | return (root != null ? root : transform).GetComponentInChildren(includeInactive); 33 | } 34 | 35 | public T[] GetRootComponentsInChildren( bool includeInactive = false) where T : Component { 36 | return (root != null ? root : transform).GetComponentsInChildren(includeInactive); 37 | } 38 | } 39 | 40 | public static class Root { 41 | public static Transform Get(Component t) { 42 | if (t == null) { return null; } 43 | if (t.TryGetComponent(out Child c)) { return c.Root; } 44 | return t.transform; 45 | } 46 | 47 | public static GameObject Get(GameObject go) { 48 | if (go == null) { return null; } 49 | if (go.TryGetComponent(out Child c)) { return c.Root.gameObject; } 50 | return go; 51 | } 52 | 53 | public static T GetComponent(Component t) where T : Component { 54 | if (t == null) { return null; } 55 | if (t.TryGetComponent(out Child c)) { return c.Root.GetComponent(); } 56 | return t.GetComponent(); 57 | } 58 | 59 | public static T GetComponent(GameObject go) where T : Component { 60 | if (go == null) { return null; } 61 | if (go.TryGetComponent(out Child c)) { return c.Root.GetComponent(); } 62 | return go.GetComponent(); 63 | } 64 | 65 | public static bool TryGetComponent(Component t, out T result) where T : Component { 66 | if (t == null) { result = null; return false; } 67 | if (t.TryGetComponent(out Child c)) { return c.Root.TryGetComponent(out result); } 68 | return t.TryGetComponent(out result); 69 | } 70 | 71 | public static bool TryGetComponent(GameObject go, out T result) where T : Component { 72 | if (go == null) { result = null; return false; } 73 | if (go.TryGetComponent(out Child c)) { return c.Root.TryGetComponent(out result); } 74 | return go.TryGetComponent(out result); 75 | } 76 | 77 | public static T[] GetComponents(Component t) where T : Component { 78 | if (t == null) { return null; } 79 | if (t.TryGetComponent(out Child c)) { return c.Root.GetComponents(); } 80 | return t.GetComponents(); 81 | } 82 | 83 | public static T[] GetComponents(GameObject go) where T : Component { 84 | if (go == null) { return null; } 85 | if (go.TryGetComponent(out Child c)) { return c.Root.GetComponents(); } 86 | return go.GetComponents(); 87 | } 88 | 89 | public static T GetComponentInChildren(Component t, bool includeInactive = false) where T : Component { 90 | if (t == null) { return null; } 91 | if (t.TryGetComponent(out Child c)) { return c.Root.GetComponentInChildren(includeInactive); } 92 | return t.GetComponentInChildren(includeInactive); 93 | } 94 | 95 | public static T GetComponentInChildren(GameObject go, bool includeInactive = false) where T : Component { 96 | if (go == null) { return null; } 97 | if (go.TryGetComponent(out Child c)) { return c.Root.GetComponentInChildren(includeInactive); } 98 | return go.GetComponentInChildren(includeInactive); 99 | } 100 | 101 | public static bool TryGetComponentInChildren(Component t, out T result, bool includeInactive = false) where T : Component { 102 | if (t == null) { result = null; return false; } 103 | if (t.TryGetComponent(out Child c)) { result = c.Root.GetComponentInChildren(includeInactive); return result != null; } 104 | result = t.GetComponentInChildren(includeInactive); return result != null; 105 | } 106 | 107 | public static bool TryGetComponentInChildren(GameObject go, out T result, bool includeInactive = false) where T : Component { 108 | if (go == null) { result = null; return false; } 109 | if (go.TryGetComponent(out Child c)) { result = c.Root.GetComponentInChildren(includeInactive); return result != null; } 110 | result = go.GetComponentInChildren(includeInactive); return result != null; 111 | } 112 | 113 | public static T[] GetComponentsInChildren(Component t, bool includeInactive = false) where T : Component { 114 | if (t == null) { return null; } 115 | if (t.TryGetComponent(out Child c)) { return c.Root.GetComponentsInChildren(includeInactive); } 116 | return t.GetComponentsInChildren(includeInactive); 117 | } 118 | 119 | public static T[] GetComponentsInChildren(GameObject go, bool includeInactive = false) where T : Component { 120 | if (go == null) { return null; } 121 | if (go.TryGetComponent(out Child c)) { return c.Root.GetComponentsInChildren(includeInactive); } 122 | return go.GetComponentsInChildren(includeInactive); 123 | } 124 | } 125 | 126 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/EnumFlagAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using UnityEngine; 4 | #if UNITY_EDITOR 5 | using UnityEditor; 6 | #endif 7 | 8 | // source: https://gist.github.com/ikriz/b0f9d96205629e19859e 9 | 10 | public class EnumFlagAttribute : PropertyAttribute { 11 | public string enumName; 12 | 13 | public EnumFlagAttribute() { } 14 | 15 | public EnumFlagAttribute(string name) { 16 | enumName = name; 17 | } 18 | } 19 | 20 | #if UNITY_EDITOR 21 | [CustomPropertyDrawer(typeof(EnumFlagAttribute))] 22 | public class EnumFlagDrawer : PropertyDrawer { 23 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { 24 | EnumFlagAttribute flagSettings = (EnumFlagAttribute)attribute; 25 | Enum targetEnum = (Enum)Enum.ToObject(fieldInfo.FieldType, property.intValue); 26 | 27 | GUIContent propName = new GUIContent(flagSettings.enumName); 28 | if (string.IsNullOrEmpty(flagSettings.enumName)) 29 | propName = label; 30 | 31 | EditorGUI.BeginProperty(position, label, property); 32 | #if UNITY_2017_1_OR_NEWER 33 | Enum enumNew = EditorGUI.EnumFlagsField(position, propName, targetEnum); 34 | #else 35 | Enum enumNew = EditorGUI.EnumMaskField(position, propName, targetEnum); 36 | #endif 37 | property.intValue = (int)Convert.ChangeType(enumNew, fieldInfo.FieldType); 38 | EditorGUI.EndProperty(); 39 | } 40 | } 41 | #endif -------------------------------------------------------------------------------- /RatKing/Base/Scripts/FPSCounter.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEngine.UI; 4 | 5 | namespace RatKing.Base { 6 | 7 | public class FPSCounter : MonoBehaviour { 8 | [SerializeField] TMPro.TextMeshProUGUI uiText = null; 9 | [SerializeField] float updateTime = 0.5f; 10 | // 11 | int i; 12 | float ms; 13 | float fps; 14 | 15 | void Update() { 16 | ms += Time.deltaTime; 17 | fps += (1f / Time.deltaTime); 18 | ++i; 19 | if (ms > updateTime) { 20 | ms /= (float)i; 21 | fps /= (float)i; 22 | uiText.text = $"{(ms*1000):0.0}ms\n{fps:0.0}"; 23 | i = 0; 24 | fps = ms = 0f; 25 | } 26 | } 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/GUI/EditorGUIExtended.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace RatKing.Base { 5 | 6 | public static class EditorGUIExtended { 7 | static Texture2D texLine; 8 | static Matrix4x4 saveMatrix; 9 | static Rect lineRect; 10 | 11 | // 12 | 13 | static EditorGUIExtended() { 14 | texLine = new Texture2D(1, 5, TextureFormat.ARGB32, true); 15 | texLine.SetPixel(0, 0, new Color(1, 1, 1, 0)); 16 | texLine.SetPixel(0, 1, Color.white); 17 | texLine.SetPixel(0, 2, Color.white); 18 | texLine.SetPixel(0, 3, Color.white); 19 | texLine.SetPixel(0, 4, new Color(1, 1, 1, 0)); 20 | texLine.Apply(); 21 | SetLineWidth(5f); 22 | } 23 | 24 | public static void SetLineWidth(float w) { 25 | lineRect = new Rect(0f, -w * 0.5f, 1f, w); 26 | } 27 | 28 | public static void BeginDrawingSeveralLines() { 29 | saveMatrix = GUI.matrix; 30 | } 31 | public static void DrawOneLineOfSeveral(Vector2 pointA, Vector2 pointB) { 32 | var delta = pointB - pointA; 33 | var length = delta.magnitude; 34 | if (length < 0.01f) { return; } 35 | GUI.matrix = saveMatrix * Matrix4x4.TRS(pointA, Quaternion.Euler(0f, 0f, Mathf.Atan2(delta.y, delta.x) * Mathf.Rad2Deg), new Vector3(length, 1f, 1f)); 36 | GUI.DrawTexture(lineRect, texLine); 37 | } 38 | public static void DrawOneRayOfSeveral(Vector2 point, Vector2 direction) { 39 | var length = direction.magnitude; 40 | if (length < 0.01f) { return; } 41 | GUI.matrix = saveMatrix * Matrix4x4.TRS(point, Quaternion.Euler(0f, 0f, Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg), new Vector3(length, 1f, 1f)); 42 | GUI.DrawTexture(lineRect, texLine); 43 | } 44 | public static void EndDrawingSeveralLines() { 45 | GUI.matrix = saveMatrix; 46 | } 47 | 48 | public static void DrawLine(Vector2 pointA, Vector2 pointB) { 49 | var delta = pointB - pointA; 50 | var length = delta.magnitude; 51 | if (length < 0.01f) { return; } 52 | var saveMatrix = GUI.matrix; 53 | GUI.matrix = saveMatrix * Matrix4x4.TRS(pointA, Quaternion.Euler(0f, 0f, Mathf.Atan2(delta.y, delta.x) * Mathf.Rad2Deg), new Vector3(length, 1f, 1f)); 54 | GUI.DrawTexture(lineRect, texLine); 55 | GUI.matrix = saveMatrix; 56 | } 57 | public static void DrawRay(Vector2 point, Vector2 direction) { 58 | var length = direction.magnitude; 59 | if (length < 0.01f) { return; } 60 | var saveMatrix = GUI.matrix; 61 | GUI.matrix = saveMatrix * Matrix4x4.TRS(point, Quaternion.Euler(0f, 0f, Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg), new Vector3(length, 1f, 1f)); 62 | GUI.DrawTexture(lineRect, texLine); 63 | GUI.matrix = saveMatrix; 64 | } 65 | 66 | private static Vector2 GetPt(Vector2 p1, Vector2 p2, float perc) { 67 | return p1 + ((p2 - p1) * perc); 68 | } 69 | 70 | public static void DrawBezier(Vector2[] points, int segments = 15) { 71 | if (!IsBezierInsideScreen(points)) { return; } 72 | float granularity = 1f / segments; 73 | var last = points[0]; 74 | var A = points[1] - points[0]; 75 | var B = points[2] - points[1]; 76 | var C = points[3] - points[2]; 77 | BeginDrawingSeveralLines(); 78 | for (float p = granularity; p < 1f; p += granularity) { 79 | var a = points[0] + A * p; 80 | var b = points[1] + B * p; 81 | var c = points[2] + C * p; 82 | var d = a + (b - a) * p; 83 | var e = b + (c - b) * p; 84 | var now = d + (e - d) * p; 85 | DrawOneLineOfSeveral(last, now); 86 | last = now; 87 | } 88 | DrawOneLineOfSeveral(last, points[3]); 89 | EndDrawingSeveralLines(); 90 | } 91 | 92 | // 93 | 94 | public static void GetPointOnBezier(Vector2[] points, float t, out Vector2 v) { 95 | var mt = 1f - t; 96 | var mt2 = mt*mt; 97 | var mt3 = mt2*mt; 98 | var t2 = t*t; 99 | v = new Vector2() { 100 | x = points[0].x * mt3 + points[1].x * 3 * mt2 * t + points[2].x * 3 * mt * t2 + points[3].x * t * t2, 101 | y = points[0].y * mt3 + points[1].y * 3 * mt2 * t + points[2].y * 3 * mt * t2 + points[3].y * t * t2 102 | }; 103 | } 104 | 105 | public static bool IsRectInsideScreen(Rect rect) { 106 | var min = GUI.matrix.MultiplyPoint(rect.min); 107 | var max = GUI.matrix.MultiplyPoint(rect.max); 108 | //var min = GUIUtility.GUIToScreenPoint(new Vector2(rect.xMin, rect.yMin)); 109 | //var max = GUIUtility.GUIToScreenPoint(new Vector2(rect.xMax, rect.yMax)); 110 | return min.x > -rect.width && max.x < (Screen.width + rect.width) && min.y > -rect.height && max.y < (Screen.height + rect.height); 111 | } 112 | 113 | public static bool IsBezierInsideScreen(Vector2[] points) { 114 | if (points.Length != 4) { return false; } 115 | var min = points[0]; 116 | var max = points[0]; 117 | for (int i = 1; i < 4; ++i) { 118 | if (points[i].x < min.x) { min.x = points[i].x; } 119 | if (points[i].x > max.x) { max.x = points[i].x; } 120 | if (points[i].y < min.y) { min.y = points[i].y; } 121 | if (points[i].y > max.y) { max.y = points[i].y; } 122 | } 123 | //min = GUIUtility.GUIToScreenPoint(min); 124 | //max = GUIUtility.GUIToScreenPoint(max); 125 | min = GUI.matrix.MultiplyPoint(min); 126 | max = GUI.matrix.MultiplyPoint(max); 127 | var width = max.x - min.x; 128 | var height = max.y - min.y; 129 | return min.x > -width && max.x < (Screen.width + width) && min.y > -height && max.y < (Screen.height + height); 130 | } 131 | } 132 | 133 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/GUI/QuickGizmos.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | 4 | namespace RatKing.Base { 5 | 6 | public class QuickGizmos : MonoBehaviour { 7 | 8 | static Material CreateTransparentMaterial() { 9 | if (UnityEngine.Rendering.GraphicsSettings.renderPipelineAsset == null) { 10 | colorName = "_Color"; 11 | return new Material(Shader.Find("Legacy Shaders/Transparent/Diffuse")); 12 | } 13 | else { 14 | colorName = "_BaseColor"; 15 | return Material.Instantiate(UnityEngine.Rendering.GraphicsSettings.renderPipelineAsset.defaultMaterial); 16 | } 17 | } 18 | 19 | static string colorName = "_Color"; 20 | public enum GizmoType { Sphere, Box, WiredSphere, WiredBox } 21 | struct QuickGizmo { 22 | public GizmoType type; 23 | public Matrix4x4 matrix; 24 | public Color color; 25 | public bool renderInGame; 26 | public QuickGizmo(GizmoType type, Vector3 position, Quaternion rotation, Vector3 scale, Color color, bool renderInGame) { 27 | this.type = type; 28 | matrix = new Matrix4x4(); 29 | matrix.SetTRS(position, rotation, scale); 30 | this.color = color; 31 | this.renderInGame = renderInGame; 32 | } 33 | } 34 | 35 | static QuickGizmos inst; 36 | static Mesh boxMesh, sphereMesh; 37 | static Material material; 38 | readonly static List gizmos = new List(); 39 | readonly static List gizmoTime = new List(); 40 | readonly static MaterialPropertyBlock matProperties = new MaterialPropertyBlock(); 41 | 42 | // 43 | 44 | [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] 45 | static void OnRuntimeInitializeOnLoad() { 46 | inst = null; 47 | gizmos.Clear(); 48 | gizmoTime.Clear(); 49 | matProperties.Clear(); 50 | } 51 | 52 | // 53 | 54 | static void CreateInstance() { 55 | if (inst != null) { return; } 56 | var go = Camera.main.gameObject; 57 | inst = go.AddComponent(); 58 | var boxGO = GameObject.CreatePrimitive(PrimitiveType.Cube); 59 | boxMesh = boxGO.GetComponent().mesh; 60 | DestroyImmediate(boxGO); 61 | var sphereGO = GameObject.CreatePrimitive(PrimitiveType.Sphere); 62 | sphereMesh = sphereGO.GetComponent().mesh; 63 | DestroyImmediate(sphereGO); 64 | material = CreateTransparentMaterial(); 65 | } 66 | 67 | // 68 | 69 | public static void DrawBox(Vector3 pos, Quaternion rot, Vector3 extents, Color color, float seconds = 0f, bool renderInGame = true) { 70 | #if UNITY_EDITOR 71 | if (seconds < 0f || color.a <= 0f) { return; } 72 | CreateInstance(); 73 | gizmos.Add(new QuickGizmo(GizmoType.Box, pos, rot, extents * 2f, color, renderInGame)); 74 | gizmoTime.Add(Time.realtimeSinceStartup + seconds); 75 | if (gizmos.Count == 1) { inst.enabled = true; } 76 | #endif 77 | } 78 | 79 | public static void DrawWiredBox(Vector3 pos, Quaternion rot, Vector3 extents, Color color, float seconds = 0f) { 80 | #if UNITY_EDITOR 81 | if (seconds < 0f || color.a <= 0f) { return; } 82 | CreateInstance(); 83 | gizmos.Add(new QuickGizmo(GizmoType.WiredBox, pos, rot, extents * 2f, color, false)); 84 | gizmoTime.Add(Time.realtimeSinceStartup + seconds); 85 | if (gizmos.Count == 1) { inst.enabled = true; } 86 | #endif 87 | } 88 | 89 | public static void DrawBox(Vector3 pos, Quaternion rot, float extents, Color color, float seconds = 0f, bool renderInGame = true) { 90 | #if UNITY_EDITOR 91 | DrawBox(pos, Quaternion.identity, Vector3.one * extents, color, seconds, renderInGame); 92 | #endif 93 | } 94 | 95 | public static void DrawWiredBox(Vector3 pos, Quaternion rot, float extents, Color color, float seconds = 0f) { 96 | #if UNITY_EDITOR 97 | DrawWiredBox(pos, Quaternion.identity, Vector3.one * extents, color, seconds); 98 | #endif 99 | } 100 | 101 | public static void DrawBox(Vector3 pos, Vector3 extents, Color color, float seconds = 0f, bool renderInGame = true) { 102 | #if UNITY_EDITOR 103 | DrawBox(pos, Quaternion.identity, extents, color, seconds, renderInGame); 104 | #endif 105 | } 106 | 107 | public static void DrawWiredBox(Vector3 pos, Vector3 extents, Color color, float seconds = 0f) { 108 | #if UNITY_EDITOR 109 | DrawWiredBox(pos, Quaternion.identity, extents, color, seconds); 110 | #endif 111 | } 112 | 113 | public static void DrawBox(Vector3 pos, float extents, Color color, float seconds = 0f, bool renderInGame = true) { 114 | #if UNITY_EDITOR 115 | DrawBox(pos, Quaternion.identity, Vector3.one * extents, color, seconds, renderInGame); 116 | #endif 117 | } 118 | 119 | public static void DrawWiredBox(Vector3 pos, float extents, Color color, float seconds = 0f) { 120 | #if UNITY_EDITOR 121 | DrawWiredBox(pos, Quaternion.identity, Vector3.one * extents, color, seconds); 122 | #endif 123 | } 124 | 125 | public static void DrawSphere(Vector3 pos, float radius, Color color, float seconds = 0f, bool renderInGame = true) { 126 | #if UNITY_EDITOR 127 | if (seconds < 0f || color.a <= 0f) { return; } 128 | CreateInstance(); 129 | gizmos.Add(new QuickGizmo(GizmoType.Sphere, pos, Quaternion.identity, Vector3.one * radius * 2f, color, renderInGame)); 130 | gizmoTime.Add(Time.realtimeSinceStartup + seconds); 131 | if (gizmos.Count == 1) { inst.enabled = true; } 132 | #endif 133 | } 134 | 135 | public static void DrawWiredSphere(Vector3 pos, float radius, Color color, float seconds = 0f) { 136 | #if UNITY_EDITOR 137 | if (seconds < 0f || color.a <= 0f) { return; } 138 | CreateInstance(); 139 | gizmos.Add(new QuickGizmo(GizmoType.WiredSphere, pos, Quaternion.identity, Vector3.one * radius * 2f, color, false)); 140 | gizmoTime.Add(Time.realtimeSinceStartup + seconds); 141 | if (gizmos.Count == 1) { inst.enabled = true; } 142 | #endif 143 | } 144 | 145 | // 146 | 147 | /// 148 | /// check life times 149 | /// 150 | void LateUpdate() { 151 | for (int i = gizmos.Count - 1; i >= 0; --i) { 152 | if (gizmoTime[i] < -100000f) { 153 | gizmos.RemoveAt(i); 154 | gizmoTime.RemoveAt(i); 155 | if (gizmos.Count == 0) { inst.enabled = false; } 156 | } 157 | else if (gizmoTime[i] < Time.realtimeSinceStartup) { 158 | gizmoTime[i] = -100001f; // so it shows the gizmo at least 1 frame 159 | } 160 | } 161 | } 162 | 163 | /// 164 | /// Render the ingame gizmos 165 | /// 166 | /// void On 167 | void Update() { 168 | for (int i = gizmos.Count - 1; i >= 0; --i) { 169 | var g = gizmos[i]; 170 | if (!g.renderInGame) { continue; } 171 | switch (g.type) { 172 | case GizmoType.Box: 173 | matProperties.SetColor(colorName, g.color); 174 | Graphics.DrawMesh(boxMesh, g.matrix, material, 0, Camera.main, 0, matProperties, false, false); 175 | break; 176 | case GizmoType.Sphere: 177 | matProperties.SetColor(colorName, g.color); 178 | Graphics.DrawMesh(sphereMesh, g.matrix, material, 0, Camera.main, 0, matProperties, false, false); 179 | break; 180 | } 181 | } 182 | } 183 | 184 | /// 185 | /// Render the ineditor gizmos 186 | /// 187 | void OnDrawGizmos() { 188 | if (inst == null) { return; } 189 | for (int i = gizmos.Count - 1; i >= 0; --i) { 190 | var g = gizmos[i]; 191 | Gizmos.matrix = g.matrix; 192 | Gizmos.color = g.color; 193 | switch (g.type) { 194 | case GizmoType.Box: Gizmos.DrawCube(Vector3.zero, Vector3.one); break; 195 | case GizmoType.WiredBox: Gizmos.DrawWireCube(Vector3.zero, Vector3.one); break; 196 | case GizmoType.Sphere: Gizmos.DrawSphere(Vector3.zero, 0.5f); break; 197 | case GizmoType.WiredSphere: Gizmos.DrawWireSphere(Vector3.zero, 0.5f); break; 198 | } 199 | } 200 | } 201 | } 202 | 203 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/GUI/QuickIMGUI.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public class QuickIMGUI : MonoBehaviour { 8 | 9 | static QuickIMGUI inst; 10 | static event System.Action OnDraw; 11 | static event System.Action OnDrawOnce; 12 | public static readonly Dictionary ByIDs = new(); 13 | static int onDrawOnceCounter; 14 | // 15 | public static Texture2D texWhite; 16 | public static Texture2D texWhiteTransparent; 17 | 18 | // 19 | 20 | [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] 21 | static void OnRuntimeInitializeOnLoad() { 22 | inst = null; 23 | OnDraw = null; 24 | OnDrawOnce = null; 25 | onDrawOnceCounter = 0; 26 | ByIDs.Clear(); 27 | } 28 | 29 | // 30 | 31 | public static void CreateInstance() { 32 | if (inst != null) { return; } 33 | var go = new GameObject(""); 34 | DontDestroyOnLoad(go); 35 | inst = go.AddComponent(); 36 | // 37 | texWhite = new Texture2D(1, 1); texWhite.SetPixel(0, 0, Color.white); 38 | texWhite.Apply(); 39 | texWhiteTransparent = new Texture2D(1, 1); texWhiteTransparent.SetPixel(0, 0, new Color(1f, 1f, 1f, 0.5f)); 40 | texWhiteTransparent.Apply(); 41 | } 42 | 43 | public static void DrawOnce(System.Action onDraw) { 44 | if (onDraw == null) { return; } 45 | CreateInstance(); 46 | if (OnDrawOnce == null && OnDraw == null) { inst.gameObject.SetActive(true); } 47 | OnDrawOnce += onDraw; 48 | onDrawOnceCounter = 2; 49 | } 50 | 51 | public static void Add(System.Action onDraw) { 52 | if (onDraw == null) { return; } 53 | CreateInstance(); 54 | if (OnDrawOnce == null && OnDraw == null) { inst.gameObject.SetActive(true); } 55 | OnDraw += onDraw; 56 | } 57 | 58 | public static void Remove(System.Action onDraw) { 59 | if (inst == null || onDraw == null) { return; } 60 | OnDraw -= onDraw; 61 | if (OnDrawOnce == null && OnDraw == null) { inst.gameObject.SetActive(false); } 62 | } 63 | 64 | public static void Add(string ID, System.Action onDraw) { 65 | if (string.IsNullOrEmpty(ID) || onDraw == null) { return; } 66 | CreateInstance(); 67 | if (ByIDs.ContainsKey(ID)) { Debug.LogError("Trying to add ID twice"); return; } 68 | if (OnDrawOnce == null && OnDraw == null) { inst.gameObject.SetActive(true); } 69 | OnDraw += onDraw; 70 | ByIDs[ID] = onDraw; 71 | } 72 | 73 | public static void Remove(string ID) { 74 | if (inst == null || string.IsNullOrEmpty(ID)) { return; } 75 | System.Action onDraw; 76 | if (ByIDs.TryGetValue(ID, out onDraw)) { 77 | OnDraw -= onDraw; 78 | ByIDs.Remove(ID); 79 | if (OnDrawOnce == null && OnDraw == null) { inst.gameObject.SetActive(false); } 80 | } 81 | } 82 | 83 | // 84 | 85 | void OnGUI() { 86 | if (OnDraw != null) { OnDraw(); } 87 | 88 | if (OnDrawOnce != null) { 89 | OnDrawOnce(); 90 | onDrawOnceCounter--; 91 | if (onDrawOnceCounter <= 0) { 92 | OnDrawOnce = null; 93 | if (OnDraw == null) { gameObject.SetActive(false); } 94 | } 95 | } 96 | 97 | } 98 | } 99 | 100 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Graphics/CameraFacingBillboard.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | [DefaultExecutionOrder(6000)] 8 | public class CameraFacingBillboard : MonoBehaviour { 9 | 10 | static CamFaceBillboards mgr; 11 | 12 | public class CamFaceBillboards : MonoBehaviour { 13 | List bbs; 14 | Transform camT; 15 | public static void Create() { 16 | var go = new GameObject(""); 17 | mgr = go.AddComponent(); 18 | mgr.bbs = new List(); 19 | } 20 | public void Add(CameraFacingBillboard bb) { 21 | bbs.Add(bb); 22 | } 23 | public void Remove(CameraFacingBillboard bb) { 24 | bbs.Remove(bb); 25 | } 26 | void LateUpdate() { 27 | if (camT == null || !camT.gameObject.activeInHierarchy) { var cam = Camera.main; if (cam == null) { return; } camT = cam.transform; } 28 | for (var iter = bbs.GetEnumerator(); iter.MoveNext(); ) { 29 | var cur = iter.Current; 30 | var targetPos = cur.transform.position - camT.forward; 31 | if (cur.upOnly) { targetPos.y = cur.transform.position.y; } // TODO 32 | cur.transform.LookAt(targetPos, camT.up); 33 | cur.transform.Rotate(cur.additionalRotation); // TODO 34 | } 35 | } 36 | } 37 | 38 | // 39 | 40 | [SerializeField] bool upOnly = true; 41 | [SerializeField] Vector3 additionalRotation = Vector3.zero; 42 | 43 | // 44 | 45 | public bool UpOnly { get { return upOnly; } set { upOnly = value; } } 46 | public Vector3 AdditionalRotation { get { return additionalRotation; } set { additionalRotation = value; } } 47 | 48 | void OnEnable() { 49 | if (mgr == null) { CamFaceBillboards.Create(); } 50 | mgr.Add(this); 51 | } 52 | 53 | void OnDisable() { 54 | mgr.Remove(this); 55 | } 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Graphics/Particler.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_2_6 || UNITY_2_6_1 || UNITY_3_0 || UNITY_3_0_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 2 | #define UNITY_OLD 3 | #else 4 | #define UNITY_5 5 | #endif 6 | 7 | #if UNITY_5 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2 8 | #define PARTICLE_SYSTEM_UPDATE_5_3 9 | #endif 10 | 11 | using UnityEngine; 12 | using System.Collections; 13 | 14 | namespace RatKing.Base { 15 | 16 | public class Particler : MonoBehaviour { 17 | [Tooltip("Can be null, will get the first ParticleSystem component.")] 18 | [SerializeField] ParticleSystem particles = null; 19 | [Tooltip("Use Follow() to change during gameplay.")] 20 | [SerializeField] Transform follow = null; 21 | [SerializeField] bool followWithoutRotation = false; 22 | // 23 | Coroutine following; 24 | Vector3 followOffset; 25 | Quaternion startRotDelta; 26 | 27 | // 28 | 29 | public Particler Instantiate(Transform start, bool follow) { 30 | var go = (GameObject)Instantiate(gameObject, start.position, start.rotation); 31 | var bp = go.GetComponent(); 32 | if (follow) { bp.Follow(start, followWithoutRotation); } 33 | return bp; 34 | } 35 | 36 | public Particler Instantiate(Vector3 position, Quaternion rotation) { 37 | var go = (GameObject)Instantiate(gameObject, position, rotation); 38 | return go.GetComponent(); 39 | } 40 | 41 | public Particler Instantiate(Vector3 position) { 42 | var go = (GameObject)Instantiate(gameObject, position, Quaternion.identity); 43 | return go.GetComponent(); 44 | } 45 | 46 | public Particler Instantiate() { 47 | var go = (GameObject)Instantiate(gameObject); 48 | return go.GetComponent(); 49 | } 50 | 51 | // 52 | 53 | public void Follow(Transform follow, bool followWithoutRotation) { 54 | this.followWithoutRotation = followWithoutRotation; 55 | if (this.follow == null) { 56 | StopAllCoroutines(); 57 | } 58 | else { 59 | StopCoroutine(following); 60 | } 61 | this.follow = follow; 62 | if (follow != null) { 63 | followOffset = follow.InverseTransformPoint(transform.position); 64 | startRotDelta = Quaternion.Inverse(follow.rotation) * transform.rotation; 65 | following = StartCoroutine(FollowCR()); 66 | } 67 | } 68 | 69 | public void StopParticles() { 70 | if (particles != null) { 71 | #if PARTICLE_SYSTEM_UPDATE_5_3 72 | var pe = particles.emission; 73 | pe.enabled = false; 74 | #else 75 | particles.enableEmission = false; 76 | #endif 77 | } 78 | } 79 | 80 | // 81 | 82 | IEnumerator Start() { 83 | if (particles == null) { 84 | particles = GetComponent(); 85 | } 86 | if (follow != null) { 87 | StartCoroutine(FollowCR()); 88 | } 89 | 90 | #if !UNITY_5_5_OR_NEWER 91 | yield return new WaitForSeconds(particles.startDelay); 92 | #endif 93 | var wait = new WaitForSeconds(0.25f); 94 | 95 | for (;;) { 96 | yield return wait; 97 | if (!particles.IsAlive() || particles.particleCount == 0) { 98 | Destroy(gameObject); 99 | } 100 | } 101 | } 102 | 103 | IEnumerator FollowCR() { 104 | while (follow != null) { 105 | transform.position = follow.TransformPoint(followOffset); 106 | if (!followWithoutRotation) { transform.rotation = follow.rotation * startRotDelta; } 107 | 108 | yield return null; 109 | } 110 | } 111 | } 112 | 113 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Graphics/WobbleAnimation.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace RatKing.Base { 6 | 7 | public class WobbleAnimation { 8 | public float factor = 0f; 9 | public float seconds = 1f; 10 | public float startSeconds = 1f; 11 | public float strength = 1f; 12 | public WobbleAnimations.Type type = WobbleAnimations.Type.Scale; 13 | public Transform target; 14 | public Vector3 originalScale; 15 | public Vector3 rotationAxis; 16 | public Quaternion originalRotation; 17 | public float startTime = 0f; 18 | public bool ignoreTimeScale; 19 | 20 | public void IgnoreTimeScale(bool ignore = true) { ignoreTimeScale = ignore; } 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Graphics/WobbleAnimations.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace RatKing.Base { 6 | 7 | public class WobbleAnimations : MonoBehaviour { 8 | public enum Type { 9 | Scale, 10 | Rotation, 11 | Both 12 | } 13 | 14 | // 15 | 16 | static WobbleAnimations Inst; 17 | static readonly List animations = new List(); 18 | 19 | // 20 | 21 | [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] 22 | static void OnRuntimeInitializeOnLoad() { 23 | Inst = null; 24 | animations.Clear(); 25 | } 26 | 27 | // 28 | 29 | public static WobbleAnimation StartFor(Transform target, float seconds, float strength = 1f, Type type = Type.Scale, Vector3 rotAxis = default(Vector3)) { 30 | if (Inst == null) { Inst = new GameObject("").AddComponent(); } 31 | 32 | var wa = animations.Find(w => w.target == target); 33 | if (wa != null) { 34 | wa.seconds = seconds; 35 | return wa; 36 | } 37 | wa = new WobbleAnimation() { 38 | factor = 0f, 39 | target = target, 40 | startSeconds = seconds, 41 | seconds = seconds, 42 | strength = strength, 43 | type = type, 44 | originalScale = target.localScale, 45 | rotationAxis = rotAxis, 46 | originalRotation = target.localRotation, 47 | startTime = Random.value * Mathf.PI, 48 | ignoreTimeScale = true 49 | }; 50 | animations.Add(wa); 51 | return wa; 52 | } 53 | 54 | // 55 | 56 | void Update() { 57 | for (int i = animations.Count - 1; i >= 0; --i) { 58 | var a = animations[i]; 59 | if (a.target == null) { 60 | animations.RemoveAt(i); 61 | continue; 62 | } 63 | 64 | var dt = a.ignoreTimeScale ? Time.unscaledDeltaTime : Time.deltaTime; 65 | var time = a.ignoreTimeScale ? Time.unscaledTime : Time.time; 66 | a.seconds -= dt; 67 | 68 | //var targetFactor = 1f + Mathf.Log(a.seconds / a.startSeconds) * 0.1f; 69 | //var targetFactor = Mathf.Sqrt(Mathf.Sqrt(a.seconds / a.startSeconds)); 70 | //var targetFactor = Mathf.Sqrt(a.seconds / a.startSeconds); 71 | var targetFactor = Mathf.Clamp01(a.seconds / a.startSeconds); 72 | a.factor = Mathf.MoveTowards(a.factor, targetFactor, dt * 10f); 73 | 74 | if (a.factor <= 0f && a.seconds <= 0f) { 75 | if (a.type == Type.Scale || a.type == Type.Both) { a.target.localScale = a.originalScale; } 76 | if (a.type == Type.Rotation || a.type == Type.Both) { a.target.localRotation = a.originalRotation; } 77 | animations.RemoveAt(i); 78 | continue; 79 | } 80 | 81 | if (a.type == Type.Scale || a.type == Type.Both) { 82 | a.target.localScale = Mathf.Lerp( 83 | 1f, 84 | Base.Math.Remap(Mathf.Sin(a.startTime + time * 20f), -1f, 1f, Mathf.LerpUnclamped(1f, 0.75f, a.strength), Mathf.LerpUnclamped(1f, 1.5f, a.strength)), 85 | a.factor) * a.originalScale; 86 | } 87 | if (a.type == Type.Rotation || a.type == Type.Both) { 88 | a.target.localRotation = a.originalRotation; 89 | a.target.Rotate(a.rotationAxis, a.strength * a.factor * Mathf.Sin(a.startTime + time * 15f) * 15f, Space.Self); 90 | } 91 | } 92 | } 93 | } 94 | 95 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/AudioExtras.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public static class AudioExtras { 8 | // source: https://twitter.com/i/web/status/785798323038937088 9 | public static float VolumeToDB(float volume) { 10 | if (volume <= 0f) { return -80f; } 11 | return 20f * Mathf.Log10(volume); 12 | } 13 | public static float DBToVolume(float dB) { 14 | return Mathf.Pow(10f, dB * 0.05f); 15 | } 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/CameraExtras.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public static class CameraExtras { 8 | public static float GetWideFOV(this Camera cam) { 9 | return GetWideFOV(cam.fieldOfView, Screen.width * cam.rect.width, Screen.height * cam.rect.height); 10 | } 11 | public static float GetWideFOV(float fov, float w = -1f, float h = -1f) { 12 | if (w < 0f) w = Screen.width; 13 | if (h < 0f) h = Screen.height; 14 | return 2f * Mathf.Atan(w * Mathf.Tan(fov * Mathf.Deg2Rad * 0.5f) / h) * Mathf.Rad2Deg; 15 | } 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/ColorExtras.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public static class ColorExtras { 8 | public static Color GetFromHexa(string hexCode, Color stdCol) { 9 | if (string.IsNullOrEmpty(hexCode)) { return stdCol; } 10 | int r = Mathf.RoundToInt(stdCol.r * 255f); 11 | int g = Mathf.RoundToInt(stdCol.g * 255f); 12 | int b = Mathf.RoundToInt(stdCol.b * 255f); 13 | int a = Mathf.RoundToInt(stdCol.a * 255f); 14 | hexCode = hexCode.Trim(new[] { ' ', '\t', '\n', '\r', '#' }); 15 | if (hexCode.Length > 1 && hexCode[1] == 'x') { hexCode = hexCode.Substring(2); } 16 | if (hexCode.Length >= 6) { 17 | int n; 18 | if (int.TryParse(hexCode.Substring(0, 2), System.Globalization.NumberStyles.HexNumber, System.Globalization.NumberFormatInfo.InvariantInfo, out n)) { r = n; } 19 | if (int.TryParse(hexCode.Substring(2, 2), System.Globalization.NumberStyles.HexNumber, System.Globalization.NumberFormatInfo.InvariantInfo, out n)) { g = n; } 20 | if (int.TryParse(hexCode.Substring(4, 2), System.Globalization.NumberStyles.HexNumber, System.Globalization.NumberFormatInfo.InvariantInfo, out n)) { b = n; } 21 | if (hexCode.Length >= 8) { // alpha 22 | if (int.TryParse(hexCode.Substring(6, 2), System.Globalization.NumberStyles.HexNumber, System.Globalization.NumberFormatInfo.InvariantInfo, out n)) { a = n; } 23 | } 24 | } 25 | return new Color(r / 255f, g / 255f, b / 255f, a / 255f); 26 | } 27 | // from http://wiki.unity3d.com/index.php?title=HexConverter 28 | public static string RGBToHex(Color color) { 29 | var hex = "0123456789ABCDEF"; 30 | var red = color.r * 255; 31 | var green = color.g * 255; 32 | var blue = color.b * 255; 33 | var a = (color.r < 0f || color.r > 1f) ? '~' : hex[Mathf.FloorToInt(red / 16)]; 34 | var b = (color.r < 0f || color.r > 1f) ? '~' : hex[Mathf.FloorToInt(red % 16)]; 35 | var c = (color.g < 0f || color.g > 1f) ? '~' : hex[Mathf.FloorToInt(green / 16)]; 36 | var d = (color.g < 0f || color.g > 1f) ? '~' : hex[Mathf.FloorToInt(green % 16)]; 37 | var e = (color.b < 0f || color.b > 1f) ? '~' : hex[Mathf.FloorToInt(blue / 16)]; 38 | var f = (color.b < 0f || color.b > 1f) ? '~' : hex[Mathf.FloorToInt(blue % 16)]; 39 | 40 | return "" + a + b + c + d + e + f; 41 | } 42 | // 43 | public static bool Approx(this Color c1, Color c2, float epsilon = 0.01f) { 44 | return c1.r < c2.r + epsilon && c1.r > c2.r - epsilon && 45 | c1.g < c2.g + epsilon && c1.g > c2.g - epsilon && 46 | c1.b < c2.b + epsilon && c1.b > c2.b - epsilon; 47 | } 48 | // 49 | // from http://www.cs.rit.edu/~ncs/color/t_convert.html 50 | // r,g,b values are from 0 to 1 | h = [0,360], s = [0,1], v = [0,1] | if s == 0, then h = -1 (undefined) 51 | public static void RGBtoHSV(float r, float g, float b, out float h, out float s, out float v) { 52 | float min, max, delta; 53 | 54 | float[] rgb = new float[] { r, g, b }; 55 | min = Mathf.Min(rgb); 56 | max = Mathf.Max(rgb); 57 | v = max; 58 | 59 | delta = max - min; 60 | 61 | if (max != 0f) { 62 | s = delta / max; 63 | } 64 | else { 65 | s = 0f; 66 | h = -1f; 67 | return; 68 | } 69 | 70 | if (r == max) 71 | h = (g - b) / delta; 72 | else if (g == max) 73 | h = 2f + (b - r) / delta; 74 | else 75 | h = 4f + (r - g) / delta; 76 | 77 | h *= 60f; 78 | if (h < 0f) 79 | h += 360f; 80 | } 81 | public static void HSVtoRGB(out float r, out float g, out float b, float h, float s, float v) { 82 | int i; 83 | float f, p, q, t; 84 | 85 | if (s == 0f) { 86 | r = g = b = v; 87 | return; 88 | } 89 | 90 | h /= 60f; 91 | i = Mathf.FloorToInt(h); 92 | f = h - i; 93 | p = v * (1f - s); 94 | q = v * (1f - s * f); 95 | t = v * (1f - s * (1f - f)); 96 | 97 | switch (i) { 98 | case 0: r = v; g = t; b = p; break; 99 | case 1: r = q; g = v; b = p; break; 100 | case 2: r = p; g = v; b = t; break; 101 | case 3: r = p; g = q; b = v; break; 102 | case 4: r = t; g = p; b = v; break; 103 | default: r = v; g = p; b = q; break; 104 | } 105 | } 106 | public static Color WithAlpha(this Color c, float a) { 107 | return new Color(c.r, c.g, c.b, a); 108 | } 109 | } 110 | 111 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/ConfigFile.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace RatKing.Base { 6 | 7 | // use: 8 | // the config file must be in the asset folder (unity editor), in the root folder (windows) 9 | // TODO mac, linux 10 | // every key is/becomes lowercase 11 | // # is comment 12 | // standard separator is : 13 | // bool is true/false and on/off 14 | 15 | public class ConfigFile { 16 | static readonly HashSet valuesDefine = new HashSet(); 17 | static readonly Dictionary valuesString = new Dictionary(); 18 | static readonly Dictionary valuesBool = new Dictionary(); 19 | static readonly Dictionary valuesNumber = new Dictionary(); 20 | 21 | // 22 | 23 | public ConfigFile(string filename = "config.txt") : this(filename, '#', ":") { 24 | } 25 | 26 | 27 | public ConfigFile(string filename, char comment, string separator) { 28 | #if UNITY_EDITOR 29 | var path = Application.dataPath + "/" + filename; 30 | #else 31 | var path = Application.dataPath + "/../" + filename; 32 | #endif 33 | float valueNumber; 34 | 35 | if (System.IO.File.Exists(path)) { 36 | var txt = System.IO.File.OpenText(path); 37 | var content = txt.ReadToEnd(); 38 | var lines = content.Split(new[] { "\r\n", "\n" }, System.StringSplitOptions.RemoveEmptyEntries); 39 | for (int l = 0; l < lines.Length; ++l) { 40 | var trimmedLine = lines[l].Trim(); 41 | if (trimmedLine.Length == 0 || trimmedLine[0] == comment) { continue; } 42 | var line = trimmedLine.Split(new[] { separator }, System.StringSplitOptions.RemoveEmptyEntries); 43 | if (line.Length == 0 || line[0].Trim().Length == 0) { 44 | continue; 45 | } 46 | else if (line.Length == 1) { 47 | valuesDefine.Add(line[0].Trim().ToLower()); 48 | } 49 | else { 50 | var key = line[0].Trim().ToLower(); 51 | var value = trimmedLine.Substring(line[0].Length + separator.Length).Trim().ToLower(); 52 | if (value == "yes" || value == "on" || value == "true") { 53 | valuesBool[key] = true; 54 | } 55 | else if (value == "no" || value == "off" || value == "false") { 56 | valuesBool[key] = false; 57 | } 58 | else if (float.TryParse(value, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out valueNumber)) { 59 | valuesNumber[key] = valueNumber; 60 | valuesBool[key] = valueNumber != 0; 61 | } 62 | valuesString[key] = trimmedLine.Substring(line[0].Length + separator.Length); 63 | } 64 | } 65 | } 66 | } 67 | 68 | // 69 | 70 | public bool IsDefined(string key) { 71 | return valuesDefine.Contains(key.ToLower()); 72 | } 73 | 74 | public bool HasBool(string key) { 75 | return valuesBool.ContainsKey(key.ToLower()); 76 | } 77 | public bool GetBool(string key, bool standard = false) { 78 | bool value; 79 | if (valuesBool.TryGetValue(key.ToLower(), out value)) { return value; } 80 | return standard; 81 | } 82 | 83 | public bool HasNumber(string key) { 84 | return valuesNumber.ContainsKey(key.ToLower()); 85 | } 86 | public float GetNumber(string key, float standard = 0f) { 87 | float value; 88 | if (valuesNumber.TryGetValue(key.ToLower(), out value)) { return value; } 89 | return standard; 90 | } 91 | 92 | public bool HasString(string key) { 93 | return valuesString.ContainsKey(key.ToLower()); 94 | } 95 | public string GetString(string key, string standard = "") { 96 | string value; 97 | if (valuesString.TryGetValue(key.ToLower(), out value)) { return value; } 98 | return standard; 99 | } 100 | } 101 | 102 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/DataStructures.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public static class DataStructures { 8 | static System.Random randomGenerator; 9 | 10 | public static void Shuffle(this IList ls, System.Random generator = null) { 11 | if (generator == null) { 12 | if (randomGenerator == null) { randomGenerator = new System.Random(); } 13 | generator = randomGenerator; 14 | } 15 | int n = ls.Count; 16 | while (n > 1) { 17 | n--; 18 | int k = generator.Next(n + 1); 19 | T value = ls[k]; 20 | ls[k] = ls[n]; 21 | ls[n] = value; 22 | } 23 | } 24 | 25 | public static T GetRandomElement(this HashSet hs, System.Random generator = null) { 26 | if (hs.Count > 0) { 27 | if (generator == null) { 28 | if (randomGenerator == null) { randomGenerator = new System.Random(); } 29 | generator = randomGenerator; 30 | } 31 | int r = generator.Next(0, hs.Count); 32 | foreach (T elem in hs) 33 | if (r-- <= 0) 34 | return elem; 35 | } 36 | return default(T); 37 | } 38 | 39 | public static T GetRandomElement(this List ls, System.Random generator = null) { 40 | if (ls.Count == 0) { return default(T); } 41 | if (generator == null) { 42 | if (randomGenerator == null) { randomGenerator = new System.Random(); } 43 | generator = randomGenerator; 44 | } 45 | return ls[generator.Next(0, ls.Count)]; 46 | } 47 | 48 | public static KeyValuePair GetRandomElement(this Dictionary ds, System.Random generator = null) { 49 | if (ds.Count > 0) { 50 | if (generator == null) { 51 | if (randomGenerator == null) { randomGenerator = new System.Random(); } 52 | generator = randomGenerator; 53 | } 54 | int r = generator.Next(0, ds.Count); 55 | foreach (var elem in ds) 56 | if (r-- <= 0) 57 | return elem; 58 | } 59 | return default(KeyValuePair); 60 | } 61 | 62 | public static T GetRandomElement(this T[] array, System.Random generator = null) { 63 | if (array.Length == 0) { return default(T); } 64 | if (generator == null) { 65 | if (randomGenerator == null) { randomGenerator = new System.Random(); } 66 | generator = randomGenerator; 67 | } 68 | return array[generator.Next(0, array.Length)]; 69 | } 70 | 71 | public static T GetFirstElement(this HashSet hs) { 72 | foreach (T elem in hs) 73 | return elem; 74 | return default(T); 75 | } 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/Debugging.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public class Debugging : MonoBehaviour { 8 | static Debugging inst; 9 | 10 | static void CreateInstance() { 11 | if (inst != null) 12 | return; 13 | var go = new GameObject(""); 14 | inst = go.AddComponent(); 15 | } 16 | 17 | public static void CreateScreenshot(string prefix, string folder = "screenshots") { 18 | CreateInstance(); 19 | System.DateTime t = System.DateTime.Now; 20 | 21 | string time = t.Year + "" 22 | + (t.Month < 10 ? "0" : "") + t.Month + "" 23 | + (t.Day < 10 ? "0" : "") + t.Day + "_" 24 | + (t.Hour < 10 ? "0" : "") + t.Hour + "" 25 | + (t.Minute < 10 ? "0" : "") + t.Minute + "" 26 | + (t.Second < 10 ? "0" : "") + t.Second + "_" 27 | + (t.Millisecond < 100 ? "0" : "") + (t.Millisecond < 10 ? "0" : "") + t.Millisecond; 28 | 29 | #if UNITY_WEBPLAYER 30 | #if UNITY_2017_1_OR_NEWER 31 | ScreenCapture.CaptureScreenshot(folder + "/" + prefix + "_" + time + ".png"); 32 | #else 33 | Application.CaptureScreenshot(folder + "/" + prefix + "_" + time + ".png"); 34 | #endif 35 | #else 36 | 37 | #if UNITY_EDITOR 38 | if (!System.IO.Directory.Exists(Application.dataPath + "/../../" + folder)) { 39 | System.IO.Directory.CreateDirectory(Application.dataPath + "/../../" + folder); 40 | } 41 | var path = "Assets/../../" + folder + "/" + prefix + "_" + time; 42 | #if UNITY_2017_1_OR_NEWER 43 | ScreenCapture.CaptureScreenshot(path + ".png"); 44 | #else 45 | Application.CaptureScreenshot(path + ".png"); 46 | #endif 47 | inst.StartCoroutine(inst.CreateScreenshotCR(path)); 48 | #else 49 | string p = Application.platform == RuntimePlatform.OSXPlayer ? "/../../" : "/../"; 50 | if (!System.IO.Directory.Exists(Application.dataPath + p + folder)) 51 | System.IO.Directory.CreateDirectory(Application.dataPath + "/../" + folder); 52 | 53 | var path = Application.dataPath + p + folder + "/" + prefix + "_" + time; 54 | #if UNITY_2017_1_OR_NEWER 55 | ScreenCapture.CaptureScreenshot(path + ".png"); 56 | #else 57 | Application.CaptureScreenshot(path + ".png"); 58 | #endif 59 | inst.StartCoroutine(inst.CreateScreenshotCR(path)); 60 | #endif 61 | } 62 | IEnumerator CreateScreenshotCR(string path, int quality = 99) { 63 | bool error = true; 64 | float wait = Time.time + 0.5f; 65 | while (wait > Time.time) { 66 | yield return null; // wait for png actually existing 67 | if (System.IO.File.Exists(path + ".png")) { 68 | error = false; 69 | break; 70 | } 71 | } 72 | if (!error) { 73 | var texture = new Texture2D(2, 2, TextureFormat.RGB24, false); 74 | var data = System.IO.File.ReadAllBytes(path + ".png"); 75 | texture.LoadImage(data); 76 | System.IO.File.WriteAllBytes(path + ".jpg", texture.EncodeToJPG(quality)); 77 | System.IO.File.Delete(path + ".png"); 78 | UnityEngine.Debug.Log("Screenshot: " + path + ".jpg"); 79 | } 80 | else { 81 | UnityEngine.Debug.Log("Error creating screenshot! " + path); 82 | yield break; 83 | } 84 | } 85 | #endif 86 | } 87 | 88 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/GameObjects.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public static class GameObjects { 8 | public static bool CheckLayerMask(GameObject go, int layerMask) { 9 | return ((1 << go.layer) & layerMask) != 0; 10 | } 11 | 12 | public static GameObject Create(string name, Vector3 pos, Quaternion rot, Transform parent = null) { 13 | var go = new GameObject(name); 14 | var t = go.transform; 15 | if (parent != null) { t.SetParent(parent); } 16 | t.position = pos; 17 | t.rotation = rot; 18 | return go; 19 | } 20 | 21 | public static Transform CreateTransform(string name, Transform parent = null) { 22 | var t = new GameObject(name).transform; 23 | if (parent != null) { 24 | t.SetParent(parent); 25 | t.localPosition = Vector3.zero; 26 | t.localRotation = Quaternion.identity; 27 | } 28 | return t; 29 | } 30 | 31 | public static bool IsNullOrInactive(this Transform transform) { return transform == null || !transform.gameObject.activeInHierarchy; } 32 | public static bool IsNullOrInactive(this GameObject gameObject) { return gameObject == null || !gameObject.activeInHierarchy; } 33 | 34 | /// 35 | /// Checks if there is a Poolable and uses this one if possible 36 | /// 37 | /// 38 | /// 39 | public static GameObject Clone(GameObject go) { 40 | if (go == null) { return null; } 41 | var poolable = go.GetComponent(); 42 | if (poolable != null) { return poolable.PoolPop().gameObject; } 43 | return GameObject.Instantiate(go); 44 | } 45 | 46 | /// 47 | /// Checks if there is a Poolable and uses this one if possible 48 | /// 49 | /// 50 | /// 51 | /// 52 | public static GameObject Clone(GameObject go, Vector3 pos) { 53 | if (go == null) { return null; } 54 | var poolable = go.GetComponent(); 55 | if (poolable != null) { return poolable.PoolPop(pos).gameObject; } 56 | return GameObject.Instantiate(go, pos, Quaternion.identity); 57 | } 58 | 59 | /// 60 | /// Checks if there is a Poolable and uses this one if possible 61 | /// 62 | /// 63 | /// 64 | /// 65 | /// 66 | public static GameObject Clone(GameObject go, Vector3 pos, Quaternion rot) { 67 | if (go == null) { return null; } 68 | var poolable = go.GetComponent(); 69 | if (poolable != null) { return poolable.PoolPop(pos, rot).gameObject; } 70 | return GameObject.Instantiate(go, pos, rot); 71 | } 72 | 73 | /// 74 | /// Checks if there is a Poolable and uses this one if possible 75 | /// 76 | /// 77 | public static void Remove(GameObject go) { 78 | if (go == null) { return; } 79 | var poolable = go.GetComponent(); 80 | if (poolable != null && poolable.IsPushable()) { poolable.PoolPush(); } 81 | else { Object.Destroy(go); } 82 | } 83 | 84 | /// 85 | /// Checks if A is before B in the hierarchy 86 | /// 87 | /// The transform to check 88 | /// The transform to compare with 89 | public static bool IsAfterInHierarchy(this Transform A, Transform B) { 90 | if (A == null || A == B) { return false; } 91 | if (B == null) { return true; } 92 | var hierarchyA = new List(); // TODO: cache, or remove 93 | while (true) { 94 | hierarchyA.Add(A); 95 | if (A.parent == null) { break; } 96 | A = A.parent; 97 | if (A == B) { return true; } // B is a (grand)parent of A 98 | } 99 | while (true) { 100 | var idx = hierarchyA.IndexOf(B.parent); 101 | if (idx == 0) { return false; } // A is a (grand)parent of B 102 | if (idx > 0) { return hierarchyA[idx - 1].GetSiblingIndex() > B.GetSiblingIndex(); } 103 | if (B.parent == null) { break; } 104 | B = B.parent; 105 | } 106 | return A.GetSiblingIndex() > B.GetSiblingIndex(); // A and B don't share any parent 107 | } 108 | } 109 | 110 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/Geometry.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public static class Geometry { 8 | public static void SetLayerRecursively(this Transform t, int layer) { 9 | for (int i = 0; i < t.childCount; ++i) { 10 | Transform child = t.GetChild(i); 11 | SetLayerRecursively(child, layer); 12 | } 13 | t.gameObject.layer = layer; 14 | } 15 | 16 | // from: http://answers.unity3d.com/questions/7789/calculating-tangents-vector4.html 17 | public static void CalculateMeshTangents(this Mesh mesh) { 18 | //speed up math by copying the mesh arrays 19 | int[] triangles = mesh.triangles; 20 | Vector3[] vertices = mesh.vertices; 21 | Vector2[] uv = mesh.uv; 22 | Vector3[] normals = mesh.normals; 23 | 24 | //variable definitions 25 | int triangleCount = triangles.Length; 26 | int vertexCount = vertices.Length; 27 | 28 | Vector3[] tan1 = new Vector3[vertexCount]; 29 | Vector3[] tan2 = new Vector3[vertexCount]; 30 | 31 | Vector4[] tangents = new Vector4[vertexCount]; 32 | 33 | for (long a = 0; a < triangleCount; a += 3) { 34 | long i1 = triangles[a + 0]; 35 | long i2 = triangles[a + 1]; 36 | long i3 = triangles[a + 2]; 37 | 38 | Vector3 v1 = vertices[i1]; 39 | Vector3 v2 = vertices[i2]; 40 | Vector3 v3 = vertices[i3]; 41 | 42 | Vector2 w1 = uv[i1]; 43 | Vector2 w2 = uv[i2]; 44 | Vector2 w3 = uv[i3]; 45 | 46 | float x1 = v2.x - v1.x; 47 | float x2 = v3.x - v1.x; 48 | float y1 = v2.y - v1.y; 49 | float y2 = v3.y - v1.y; 50 | float z1 = v2.z - v1.z; 51 | float z2 = v3.z - v1.z; 52 | 53 | float s1 = w2.x - w1.x; 54 | float s2 = w3.x - w1.x; 55 | float t1 = w2.y - w1.y; 56 | float t2 = w3.y - w1.y; 57 | 58 | float r = 1f / (s1 * t2 - s2 * t1); 59 | 60 | Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); 61 | Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); 62 | 63 | tan1[i1] += sdir; 64 | tan1[i2] += sdir; 65 | tan1[i3] += sdir; 66 | 67 | tan2[i1] += tdir; 68 | tan2[i2] += tdir; 69 | tan2[i3] += tdir; 70 | } 71 | 72 | 73 | for (long a = 0; a < vertexCount; ++a) { 74 | Vector3 n = normals[a]; 75 | Vector3 t = tan1[a]; 76 | 77 | //Vector3 tmp = (t - n * Vector3.Dot(n, t)).normalized; 78 | //tangents[a] = new Vector4(tmp.x, tmp.y, tmp.z); 79 | Vector3.OrthoNormalize(ref n, ref t); 80 | tangents[a].x = t.x; 81 | tangents[a].y = t.y; 82 | tangents[a].z = t.z; 83 | 84 | tangents[a].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[a]) < 0f) ? -1f : 1f; 85 | } 86 | 87 | mesh.tangents = tangents; 88 | } 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/GizmoExtras.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public static class GizmoExtras { 8 | public static void DrawWireCircle(this Transform trans, float radius, int prec = 100) { 9 | float fac = 360f / (float)prec; 10 | Vector3 v = trans.forward * radius; 11 | for (int i = 0; i < prec; ++i) { 12 | Vector3 t = Math.Rotate(v, trans.up, fac); 13 | Gizmos.DrawLine(trans.position + v, trans.position + t); 14 | v = t; 15 | } 16 | } 17 | static Vector3 otherOne = new Vector3(0.5f, -2.0f, 3.5f); 18 | public static void DrawWireCircle(Vector3 center, Vector3 axis, float radius, int prec = 100) { 19 | float fac = 360f / (float)prec; 20 | Vector3 v = Vector3.Cross(axis, (Vector3.Dot(axis, Vector3.one) == 0.0f ? otherOne : Vector3.one)).normalized * radius; 21 | for (int i = 0; i < prec; ++i) { 22 | Vector3 t = Math.Rotate(v, axis, fac); 23 | Gizmos.DrawLine(center + v, center + t); 24 | v = t; 25 | } 26 | } 27 | 28 | public static void DrawWireCapsule(Transform transform, CapsuleCollider capsule, int prec = 6) { 29 | var axis = capsule.direction == 0 ? transform.right : capsule.direction == 2 ? transform.forward : transform.up; 30 | DrawWireCapsule(transform.position + capsule.center, axis, capsule.radius, capsule.height, prec); 31 | } 32 | 33 | public static void DrawWireCapsule(Vector3 center, Vector3 axis, float radius, float height, int prec = 6) { 34 | var innerHeight = height - radius * 2f; 35 | var dprec = prec * 2; 36 | float fac = 360f / (float)dprec; 37 | Vector3 v = Vector3.Cross(axis, (Vector3.Dot(axis, Vector3.one) == 0.0f ? otherOne : Vector3.one)).normalized * radius; 38 | var top = center + axis * (innerHeight * 0.5f); 39 | var bottom = center - axis * (innerHeight * 0.5f); 40 | for (int i = 0; i < dprec; ++i) { 41 | Vector3 t = Math.Rotate(v, axis, fac); 42 | Gizmos.DrawLine(bottom + v, bottom + t); 43 | Gizmos.DrawLine(top + v, top + t); 44 | Gizmos.DrawLine(top + v, bottom + v); 45 | if (i <= prec) { 46 | // spheres 47 | Vector3 st = top + t, sb = bottom + t; 48 | Vector3 a = Vector3.Cross(t, axis); 49 | for (int j = 0; j < prec; ++j) { 50 | var stn = Math.RotateAround(st, top, a, fac); 51 | var sbn = Math.RotateAround(sb, bottom, -a, fac); 52 | Gizmos.DrawLine(st, stn); 53 | Gizmos.DrawLine(sb, sbn); 54 | st = stn; 55 | sb = sbn; 56 | } 57 | } 58 | v = t; 59 | } 60 | } 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/MaterialExtras.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public static class MaterialExtras { 8 | 9 | public class Pool { 10 | static Dictionary> usedMaterialByColor = new Dictionary>(); 11 | static Dictionary> usedMaterialByShader = new Dictionary>(); 12 | static Dictionary usedMaterialByShader_R = new Dictionary(); 13 | 14 | public static Material Get(Material material, Color color) { 15 | if (!usedMaterialByColor.ContainsKey(material)) 16 | usedMaterialByColor[material] = new Dictionary(); 17 | 18 | if (!usedMaterialByColor[material].ContainsKey(color)) { 19 | Material newMaterial = (Material)Material.Instantiate(material); 20 | newMaterial.color = color; 21 | usedMaterialByColor[material][color] = newMaterial; 22 | return newMaterial; 23 | } 24 | 25 | return usedMaterialByColor[material][color]; 26 | } 27 | 28 | public static Material Get(Material material, Shader shader) { 29 | if (!usedMaterialByShader.ContainsKey(material)) { 30 | usedMaterialByShader[material] = new Dictionary(); 31 | } 32 | if (!usedMaterialByShader[material].ContainsKey(shader)) { 33 | Material newMaterial = (Material)Material.Instantiate(material); 34 | newMaterial.shader = shader; 35 | usedMaterialByShader[material][shader] = newMaterial; 36 | usedMaterialByShader_R[newMaterial] = material; 37 | return newMaterial; 38 | } 39 | return usedMaterialByShader[material][shader]; 40 | } 41 | public static Material Reset(Material manipulatedMaterial) { 42 | if (!usedMaterialByShader_R.ContainsKey(manipulatedMaterial)) { 43 | return null; 44 | } 45 | return usedMaterialByShader_R[manipulatedMaterial]; 46 | } 47 | } 48 | 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/Pathfinding.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public static class Pathfinding { 8 | public class Waypoint where T : IPosition { // TODO make poolable 9 | public T pos; 10 | public Vector3 worldPos; 11 | public bool solid; 12 | public List> neighbours = new List>(); 13 | public Creature creature; 14 | public Creature nextCreature; 15 | //public int type; 16 | public Waypoint(T pos, bool solid) { this.pos = pos; worldPos = pos.ToVector(); this.solid = solid; } 17 | } 18 | 19 | public class Node where T : IPosition { // TODO make poolable 20 | public Node parent = null; 21 | public Waypoint block; 22 | public int F = 0; 23 | public int G = 0; 24 | public int H = 0; 25 | public Node(Waypoint block) { this.block = block; } 26 | public Node(Waypoint block, Node parent, int F, int G, int H) { this.block = block; this.parent = parent; this.F = F; this.G = G; this.H = H; } 27 | }; 28 | 29 | // Finds A Path Between Two Blocks, Returns The Path In An Array 30 | public static bool Find(Waypoint A, Waypoint B, out Waypoint[] path, int maxLength, bool ignoreCreatures) where T : IPosition { 31 | if (A == null || B == null) { 32 | path = null; 33 | return false; 34 | } 35 | 36 | path = null; 37 | List> open = new List>(maxLength); 38 | List> closed = new List>(maxLength); 39 | Node current = null; 40 | open.Add(new Node(A)); 41 | 42 | // pathfinding! 43 | for (;;) { 44 | 45 | // no nodes any more, but target not found? -> end 46 | if (open.Count == 0) 47 | return false; 48 | 49 | current = open[0]; // list is sorted! 50 | 51 | // remove node from open list and move it into closed list 52 | open.Remove(current); 53 | closed.Add(current); 54 | 55 | // target found? -> end the search! 56 | if (current.block == B) { 57 | int pathLength = 0; 58 | Node counter = current; 59 | 60 | do // go backwards, for counting only 61 | { 62 | 63 | counter = counter.parent; 64 | ++pathLength; 65 | } while (counter != null); 66 | 67 | path = new Waypoint[pathLength]; 68 | 69 | // go forward, for building path 70 | for (int i = 0; i < pathLength; ++i) { 71 | path[pathLength - i - 1] = current.block; 72 | current = current.parent; 73 | } 74 | 75 | return true; 76 | } 77 | 78 | int G = current.G + 1; // Position.GetSqrDistance(current.block.absPosition, neighbour.absPosition); 79 | if (G > maxLength) continue; // return false; 80 | 81 | // iterate through connections 82 | int nm = current.block.neighbours.Count; 83 | for (int i = 0; i < nm; ++i) { 84 | Waypoint neighBlock = current.block.neighbours[i]; 85 | if (neighBlock == null || (!ignoreCreatures && neighBlock != B && neighBlock.creature != null)) 86 | continue; 87 | 88 | // node is already in closed list? 89 | if (closed.Find(n => n.block == neighBlock) != null) 90 | continue; 91 | 92 | // node is already in open list? 93 | Node oldNode = open.Find(n => n.block == neighBlock); 94 | if (oldNode != null) { 95 | if (G < oldNode.G) { 96 | oldNode.G = G; 97 | oldNode.F = G + oldNode.H; 98 | oldNode.parent = current; 99 | open.Sort((Node a, Node b) => a.F - b.F); 100 | } 101 | } 102 | else { 103 | int H = neighBlock.pos.GetManhattanDistanceTo(B.pos); 104 | // int H = Mathf.RoundToInt(Mathf.Abs(neighBlock.worldPos.x - B.worldPos.x) + Mathf.Abs(neighBlock.worldPos.y - B.worldPos.y) + Mathf.Abs(neighBlock.worldPos.z - B.worldPos.z)); 105 | int F = G + H; 106 | Node newNode = new Node(neighBlock, current, F, G, H); 107 | open.Add(newNode); 108 | open.Sort((Node a, Node b) => a.F - b.F); 109 | } 110 | } 111 | } 112 | } 113 | } 114 | 115 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/PhysicsExtras.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public class PhysicsExtras { 8 | public static void WakeUpEverythingAround(GameObject go, float padding, bool disableMyColliders, int layerMaskPlayer) { 9 | var colliders = go.GetComponentsInChildren(false); 10 | if (colliders.Length > 0) { 11 | var bounds = colliders[0].bounds; 12 | for (int i = colliders.Length - 1; i >= 1; --i) { 13 | var c = colliders[i]; 14 | bounds.Encapsulate(c.bounds); 15 | } 16 | bounds.size += Vector3.one * padding * 2f; 17 | foreach (var c in Physics.OverlapBox(bounds.center, bounds.extents, Quaternion.identity, ~layerMaskPlayer, QueryTriggerInteraction.Collide)) { 18 | var r = c.attachedRigidbody; 19 | if (r != null) { r.WakeUp(); } 20 | } 21 | if (disableMyColliders) { 22 | foreach (var c in go.GetComponentsInChildren(false)) { c.enabled = false; } 23 | } 24 | } 25 | } 26 | 27 | public static void WakeUpEverythingAround(Vector3 pos, Vector3 size, GameObject go, int layerMaskPlayer) { 28 | foreach (var c in Physics.OverlapBox(pos, size * 0.5f, Quaternion.identity, ~layerMaskPlayer, QueryTriggerInteraction.Collide)) { 29 | //Base.QuickGizmos.DrawBox(pos, Quaternion.identity, size * 0.5f, Color.yellow, 1f); 30 | var r = c.attachedRigidbody; 31 | if (r != null) { r.WakeUp(); } 32 | } 33 | } 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/Randomness.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public static class Randomness { 8 | public static Color GetColor(float? alpha = null) { 9 | return new Color(Random.value, Random.value, Random.value, alpha == null ? Random.value : alpha.Value); 10 | } 11 | 12 | public static class Probabilities { 13 | public static int GetRandomIndex(float[] probabilities, System.Random generator = null) { 14 | var count = probabilities.Length; 15 | var s = 0f; 16 | for (int i = 0; i < count; ++i) { s += probabilities[i]; } 17 | var r = (generator == null ? Random.value : generator.NextDouble()) * s; 18 | for (int i = count - 1; i >= 0; --i) { 19 | s -= probabilities[i]; 20 | if (r > s) { return i; } 21 | } 22 | return probabilities.Length - 1; 23 | } 24 | } 25 | // 26 | public static class SimplexNoise { 27 | // from: http://stephencarmody.wikispaces.com/Simplex+Noise 28 | 29 | static int i, j, k; 30 | static int[] A = new int[] { 0, 0, 0 }; 31 | static float u, v, w, s; 32 | static float onethird = 0.333333333f; 33 | static float onesixth = 0.166666667f; 34 | static int[] T = new int[] { 0x15, 0x38, 0x32, 0x2c, 0x0d, 0x13, 0x07, 0x2a }; 35 | 36 | // 37 | 38 | public static float NoiseLoop(float x, float y, float t, float T) { 39 | return ((T - t) * Noise(x, y, t) + t * Noise(x, y, t - T)) / T; 40 | } 41 | 42 | // returns a value in the range of about [-0.347 .. 0.347] 43 | public static float Noise(Vector3 v) { 44 | return Noise(v.x, v.y, v.z); 45 | } 46 | public static float Noise(float x, float y, float z) { 47 | // Skew input space to relative coordinate in simplex cell 48 | s = (x + y + z) * onethird; 49 | i = Fastfloor(x + s); 50 | j = Fastfloor(y + s); 51 | k = Fastfloor(z + s); 52 | 53 | // Unskew cell origin back to (x, y , z) space 54 | s = (i + j + k) * onesixth; 55 | u = x - i + s; 56 | v = y - j + s; 57 | w = z - k + s; ; 58 | 59 | A[0] = A[1] = A[2] = 0; 60 | 61 | // For 3D case, the simplex shape is a slightly irregular tetrahedron. 62 | // Determine which simplex we're in 63 | int hi = u >= w ? u >= v ? 0 : 1 : v >= w ? 1 : 2; 64 | int lo = u < w ? u < v ? 0 : 1 : v < w ? 1 : 2; 65 | 66 | return k_m(hi) + k_m(3 - hi - lo) + k_m(lo) + k_m(0); 67 | } 68 | 69 | // normalized (goes [0..1], but only circa!) 70 | public static float NormalizedNoise(Vector3 v) { 71 | return (Noise(v) + 0.347f) * 1.4409f; 72 | } 73 | public static float NormalizedNoise(float x, float y, float z) { 74 | return (Noise(x, y, z) + 0.347f) * 1.4409f; 75 | } 76 | 77 | // normalized (goes [-1..1], but only circa!) 78 | public static float NoiseMinusPlus1(Vector3 v) { 79 | return Noise(v) * 1.4409f; 80 | } 81 | public static float NoiseMinusPlus1(float x, float y, float z) { 82 | return Noise(x, y, z) * 1.4409f; 83 | } 84 | 85 | // 86 | 87 | static int Fastfloor(float n) { 88 | return n > 0 ? (int)(n) : (int)(n - 1); 89 | } 90 | 91 | static float k_m(int a) { 92 | s = (A[0] + A[1] + A[2]) * onesixth; 93 | float x = u - A[0] + s; 94 | float y = v - A[1] + s; 95 | float z = w - A[2] + s; 96 | float t = 0.6f - x * x - y * y - z * z; 97 | int h = Shuffle(i + A[0], j + A[1], k + A[2]); 98 | A[a]++; 99 | if (t < 0) return 0; 100 | int b5 = h >> 5 & 1; 101 | int b4 = h >> 4 & 1; 102 | int b3 = h >> 3 & 1; 103 | int b2 = h >> 2 & 1; 104 | int b = h & 3; 105 | float p = b == 1 ? x : b == 2 ? y : z; 106 | float q = b == 1 ? y : b == 2 ? z : x; 107 | float r = b == 1 ? z : b == 2 ? x : y; 108 | p = b5 == b3 ? -p : p; 109 | q = b5 == b4 ? -q : q; 110 | r = b5 != (b4 ^ b3) ? -r : r; 111 | t *= t; 112 | return 8 * t * t * (p + (b == 0 ? q + r : b2 == 0 ? q : r)); 113 | } 114 | 115 | static int Shuffle(int i, int j, int k) { 116 | return b_m(i, j, k, 0) + b_m(j, k, i, 1) + b_m(k, i, j, 2) + b_m(i, j, k, 3) + 117 | b_m(j, k, i, 4) + b_m(k, i, j, 5) + b_m(i, j, k, 6) + b_m(j, k, i, 7); 118 | } 119 | 120 | static int b_m(int i, int j, int k, int B) { 121 | return T[b2_m(i, B) << 2 | b2_m(j, B) << 1 | b2_m(k, B)]; 122 | } 123 | 124 | static int b2_m(int N, int B) { 125 | return N >> B & 1; 126 | } 127 | } 128 | 129 | // 130 | 131 | public static Vector2 OnUnitCircle() { 132 | var angle = Random.value * Mathf.PI * 2f; 133 | return new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)); 134 | } 135 | } 136 | 137 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/Security.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public static class Security { 8 | public static string MD5Sum(string strToEncrypt) { 9 | var ue = new System.Text.UTF8Encoding(); 10 | byte[] bytes = ue.GetBytes(strToEncrypt); 11 | 12 | // encrypt bytes 13 | var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); 14 | byte[] hashBytes = md5.ComputeHash(bytes); 15 | 16 | // Convert the encrypted bytes back to a string (base 16) 17 | string hashString = ""; 18 | 19 | for (int i = 0; i < hashBytes.Length; i++) { 20 | hashString += System.Convert.ToString(hashBytes[i], 16).PadLeft(2, '0'); 21 | } 22 | 23 | return hashString.PadLeft(32, '0'); 24 | } 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Helpers/StringExtras.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public static class StringExtras { 8 | public static char[] linesSplitter = new char[1] { '\n' }; 9 | public static char[] spaceSplitter = new char[5] { ' ', '\n', '\t', '\r', '\0' }; 10 | // 11 | public static string DisplayScore(int score, int digits = 7) { 12 | string text = string.Empty; 13 | int ts = score; 14 | do { 15 | ts /= 10; 16 | digits--; 17 | } while (ts > 0); 18 | for (int i = digits - 1; i >= 0; --i) 19 | text += "0"; 20 | return text + score; 21 | } 22 | public static string DisplayMinutes(int seconds) { 23 | int s = seconds % 60; 24 | int m = seconds / 60; 25 | return m.ToString() + ":" + (s < 10 ? ("0" + s) : s.ToString()); 26 | } 27 | public static string DisplayHours(int seconds) { 28 | int h = seconds / (60 * 60); 29 | int m = (seconds / 60) % 60; 30 | int s = seconds % 60; 31 | return (h < 10 ? ("0" + h) : h.ToString()) + ":" + (m < 10 ? ("0" + m) : m.ToString()) + ":" + (s < 10 ? ("0" + s) : s.ToString()); 32 | } 33 | 34 | public static string CreateID(int numBlocks = 4, int lengthBlock = 4, string delimiter = "-", string possibleCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxyzZ1234567890") { 35 | string code = ""; 36 | for (int i = 0; i < numBlocks; ++i) { 37 | if (i != 0) code += delimiter; 38 | for (int j = 0; j < lengthBlock; ++j) 39 | code += possibleCharacters[UnityEngine.Random.Range(0, possibleCharacters.Length)].ToString(); 40 | } 41 | return code; 42 | } 43 | 44 | public static string Escape(this string text) { 45 | if (string.IsNullOrEmpty(text)) { return text; } 46 | return text.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\r\n", "\\n").Replace("\r", "\\r").Replace("\n", "\\n").Replace("\t", "\\t"); 47 | } 48 | 49 | // from https://stackoverflow.com/questions/2661169/how-can-i-unescape-and-reescape-strings-in-net 50 | public static string Unescape(this string text) { 51 | if (string.IsNullOrEmpty(text)) { return text; } 52 | var length = text.Length; 53 | var result = new System.Text.StringBuilder(length); 54 | for (int i = 0; i < length; ) { 55 | int j = text.IndexOf('\\', i); 56 | if (j < 0 || j == length - 1) { j = length; } 57 | if (j - i > 0) { result.Append(text, i, j - i); } 58 | if (j >= length) { break; } 59 | switch (text[j + 1]) { 60 | case 'n': result.Append('\n'); break; // Line feed 61 | case 'r': result.Append('\r'); break; // Carriage return 62 | case 't': result.Append('\t'); break; // Tab 63 | case '"': result.Append('"'); break; // Don't escape 64 | case '\\': result.Append('\\'); break; // Don't escape 65 | default: result.Append('\\').Append(text[j + 1]); break; 66 | } 67 | i = j + 2; 68 | //UnityEngine.Debug.Log(result.ToString()); 69 | } 70 | return result.ToString(); 71 | } 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Hotkeys.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace RatKing.Base { 6 | 7 | public class Hotkeys { 8 | 9 | public class Entry { 10 | Hotkeys parent; 11 | public string keyCode; // shortcut 12 | public bool shift, ctrl, alt; // shortcut modifiers 13 | public System.Action Action { get; private set; } = null; 14 | public int Priority => (shift ? 1 : 0) + (ctrl ? 2 : 0) + (alt ? 4 : 0); 15 | 16 | // 17 | 18 | public Entry(string keyCode, System.Action action, Hotkeys parent = null) { 19 | this.parent = parent; 20 | Set(keyCode, action); 21 | } 22 | 23 | public void Enable() { 24 | if (parent == null) { return; } 25 | if (!parent.entries.Contains(this)) { parent.entries.Add(this); parent.entries.Sort((a, b) => b.Priority - a.Priority); } 26 | } 27 | 28 | public void Disable() => parent?.entries.Remove(this); 29 | 30 | public string GetKeyCodeText() { 31 | return (shift ? "shift " : "") + (ctrl ? "ctrl " : "") + (alt ? "alt " : "") + keyCode; 32 | } 33 | 34 | public void Set(string keyCode, System.Action action) { 35 | this.Action = action; 36 | GetCode(ref keyCode, out this.keyCode, out this.shift, out this.ctrl, out this.alt); 37 | parent?.entries.Sort((a, b) => b.Priority - a.Priority); 38 | } 39 | 40 | public void Set(string keyCode) { 41 | GetCode(ref keyCode, out this.keyCode, out shift, out ctrl, out alt); 42 | parent?.entries.Sort((a, b) => b.Priority - a.Priority); 43 | } 44 | 45 | // 46 | 47 | public bool CheckInputRigid() { 48 | if (string.IsNullOrWhiteSpace(keyCode)) { return false; } 49 | if (shift != (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))) { return false; } 50 | if (ctrl != (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))) { return false; } 51 | if (alt != (Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt))) { return false; } 52 | return Input.GetKeyDown(keyCode); 53 | } 54 | 55 | public bool CheckInput() { 56 | if (string.IsNullOrWhiteSpace(keyCode)) { return false; } 57 | if (shift && !(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))) { return false; } 58 | if (ctrl && !(Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))) { return false; } 59 | if (alt && !(Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt))) { return false; } 60 | return Input.GetKeyDown(keyCode); 61 | } 62 | 63 | // 64 | 65 | void GetCode(ref string whole, out string code, out bool shift, out bool ctrl, out bool alt) { 66 | whole = (whole ?? "").Trim().ToLower(); 67 | shift = ctrl = alt = false; 68 | var parts = whole.Split(Base.StringExtras.spaceSplitter, System.StringSplitOptions.RemoveEmptyEntries); 69 | code = ""; 70 | foreach (var p in parts) { 71 | var c = p.Trim(); 72 | if (c == "shift") { shift = true; } 73 | else if (c == "ctrl") { ctrl = true; } 74 | else if (c == "alt") { alt = true; } 75 | else if (code == "" && !c.Contains("shift") && !c.Contains("ctrl") && !c.Contains("alt")) { 76 | code = c; 77 | try { Input.GetKey(c); } 78 | catch { code = ""; } 79 | } 80 | } 81 | if (string.IsNullOrWhiteSpace(code)) { shift = ctrl = alt = false; } 82 | } 83 | } 84 | 85 | // 86 | 87 | readonly List entries = new(); 88 | 89 | // 90 | 91 | public void CheckAndExecute() { 92 | for (int i = 0, c = entries.Count; i < c; ++i) { 93 | if (entries[i].CheckInput()) { entries[i].Action?.Invoke(); break; } 94 | } 95 | } 96 | 97 | public Entry Add(string keyCode, System.Action action) { 98 | var entry = new Entry(keyCode, action, this); 99 | entries.Add(entry); 100 | return entry; 101 | } 102 | } 103 | 104 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Optional.cs: -------------------------------------------------------------------------------- 1 | #if ODIN_INSPECTOR 2 | using Sirenix.OdinInspector; 3 | #endif 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using UnityEngine; 7 | 8 | namespace RatKing.Base { 9 | 10 | // from https://www.youtube.com/watch?v=uZmWgQ7cLNI 11 | 12 | [System.Serializable] 13 | #if ODIN_INSPECTOR 14 | [HideReferenceObjectPicker] 15 | #endif 16 | // public class Optional { 17 | // [field: SerializeField] public T Value { get; set; } 18 | // [field: SerializeField] public bool Enabled { get; set; } 19 | // public Optional(T value, bool enabled = true) { Value = value; Enabled = enabled; } 20 | // public Optional Set(T value, bool enabled = true) { Value = value; Enabled = enabled; return this; } 21 | // } 22 | // 23 | //} 24 | 25 | public class Optional { 26 | [SerializeField] private bool enabled; 27 | [SerializeField] private T value; 28 | 29 | public bool Enabled { get => enabled; set => enabled = value; } 30 | public T Value { get => value; set => this.value = value; } 31 | 32 | public Optional(T value, bool enabled = true) { this.value = value; this.enabled = enabled; } 33 | public Optional Set(T value, bool enabled = true) { this.value = value; this.enabled = enabled; return this; } 34 | } 35 | 36 | public static class OptionalExtensions { 37 | public static T Get(this Optional opt, T std) { 38 | if (opt != null && opt.Enabled) { return opt.Value; } 39 | return std; 40 | } 41 | public static bool TryGet(this Optional opt, out T value) { 42 | if (opt != null && opt.Enabled) { value = opt.Value; return true; } 43 | value = default; return false; 44 | } 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Pause.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public class Pause : MonoBehaviour { 8 | 9 | public static readonly Event EVENT = new Event("pause_event"); 10 | static Pause inst = null; 11 | 12 | class Pausing { 13 | public float timeScale; 14 | public float fadeTo = -1f; 15 | public float fadeSpeed = -1f; 16 | public System.Action onFadeDone = null; 17 | public Pausing(float factor) { this.timeScale = factor; } 18 | } 19 | 20 | List layers = new List(); 21 | List pausings = new List(); 22 | 23 | // 24 | 25 | [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] 26 | static void OnRuntimeInitializeOnLoad() { 27 | inst = null; 28 | Base.Events.UnregisterAll(EVENT); 29 | } 30 | 31 | // 32 | 33 | void Update() { 34 | var target = 1f; 35 | 36 | // find lowest one 37 | for (int i = pausings.Count - 1; i>= 0; --i) { 38 | var pausing = pausings[i]; 39 | if (pausing.fadeTo >= 0f) { 40 | pausing.timeScale = Mathf.MoveTowards(pausing.timeScale, pausing.fadeTo, pausing.fadeSpeed * Time.unscaledDeltaTime); 41 | if (pausing.timeScale == pausing.fadeTo) { 42 | if (pausing.onFadeDone != null) { pausing.onFadeDone(); pausing.onFadeDone = null; } 43 | if (pausing.fadeTo == 1f) { layers.RemoveAt(i); pausings.RemoveAt(i); continue; } 44 | pausing.fadeTo = pausing.fadeSpeed = -1f; 45 | } 46 | } 47 | if (pausing.timeScale < target) { target = pausing.timeScale; } 48 | } 49 | 50 | var nextTimeScale = Mathf.MoveTowards(Time.timeScale, target, 1f); 51 | if (Time.timeScale > 0f && nextTimeScale <= 0f) { 52 | Base.Events.BroadcastAll(EVENT, true); 53 | } 54 | else if (Time.timeScale <= 0f && nextTimeScale > 0f) { 55 | Base.Events.BroadcastAll(EVENT, false); 56 | } 57 | Time.timeScale = nextTimeScale; 58 | } 59 | 60 | void OnDestroy() { 61 | Time.timeScale = 1f; 62 | } 63 | 64 | // 65 | 66 | static void CreateInstance() { 67 | if (inst != null) { return; } 68 | inst = new GameObject("").AddComponent(); 69 | DontDestroyOnLoad(inst.gameObject); 70 | } 71 | 72 | // 73 | 74 | public static bool Is() { 75 | return Time.timeScale <= 0f; 76 | } 77 | 78 | public static void Do(string layer, float seconds = 0f, System.Action onDone = null) { 79 | CreateInstance(); 80 | // 81 | var idx = inst.layers.IndexOf(layer); 82 | if (idx < 0) { 83 | idx = inst.layers.Count; 84 | inst.layers.Add(layer); 85 | inst.pausings.Add(new Pausing(1f)); 86 | } 87 | 88 | var pausing = inst.pausings[idx]; 89 | 90 | if (seconds > 0f) { 91 | pausing.fadeTo = 0f; 92 | pausing.fadeSpeed = pausing.timeScale / seconds; 93 | pausing.onFadeDone = onDone; 94 | } 95 | else { 96 | if (onDone != null) { onDone(); } 97 | pausing.timeScale = 0f; 98 | pausing.fadeTo = pausing.fadeSpeed = -1f; 99 | pausing.onFadeDone = null; 100 | } 101 | } 102 | 103 | public static void Undo(string layer, float seconds = 0f, System.Action onUndone = null) { 104 | if (inst == null) { return; } 105 | 106 | var idx = inst.layers.IndexOf(layer); 107 | if (idx < 0) { 108 | if (onUndone != null) { onUndone(); } 109 | return; 110 | } 111 | 112 | var pausing = inst.pausings[idx]; 113 | 114 | if (seconds > 0f) { 115 | pausing.fadeTo = 1f; 116 | pausing.fadeSpeed = (1f - pausing.timeScale) / seconds; 117 | pausing.onFadeDone = onUndone; 118 | } 119 | else { 120 | if (onUndone != null) { onUndone(); } 121 | inst.layers.RemoveAt(idx); 122 | inst.pausings.RemoveAt(idx); 123 | } 124 | } 125 | } 126 | 127 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/PlayerInput.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | namespace RatKing.Base { 5 | 6 | [SelectionBase] 7 | [RequireComponent(typeof(Creature))] 8 | public class PlayerInput : MonoBehaviour { 9 | [Header("Rotating")] 10 | [SerializeField] float yawRotSpeed = 10f; 11 | [SerializeField] float pitchRotSpeed = 10f; 12 | [SerializeField] float pitchMax = 80f; 13 | [SerializeField] float pitchMin = -80f; 14 | [SerializeField] float mouseSensitivity = 1f; 15 | [SerializeField] float smoothness = 1f; 16 | [Header("Components")] 17 | [SerializeField] Creature creature = null; 18 | 19 | float macMouseFactor = 1f; 20 | float pitch = 0f, smoothedPitch = 0f, smoothPitchVel = 0f; 21 | float yaw = 0f, smoothedYaw = 0f, smoothYawVel = 0f; 22 | bool catchMouse = true; 23 | Transform camDummy; 24 | 25 | public Creature Creature { get { return creature; } } 26 | public Transform RotTrans { get { return creature.RotateTransform; } } 27 | bool moveAllowed = true; 28 | 29 | // 30 | 31 | void Start() { 32 | creature = creature == null ? GetComponentInChildren() : creature; 33 | #if UNITY_WEBPLAYER 34 | if (Application.platform == RuntimePlatform.OSXWebPlayer) { 35 | #elif UNITY_2017_1_OR_NEWER 36 | if (Application.platform == RuntimePlatform.OSXPlayer) 37 | #else 38 | if (Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXDashboardPlayer) 39 | #endif 40 | macMouseFactor = 0.18f; 41 | 42 | camDummy = new GameObject("CamDummy").transform; 43 | camDummy.SetPositionAndRotation(RotTrans.position, RotTrans.rotation); 44 | camDummy.SetParent(RotTrans.parent); 45 | RotTrans.SetParent(null); 46 | } 47 | 48 | void Update() { 49 | // move 50 | 51 | if (moveAllowed) { 52 | creature.FactorX = Input.GetAxis("Horizontal"); 53 | creature.FactorZ = Input.GetAxis("Vertical"); 54 | } 55 | else { 56 | creature.FactorX = creature.FactorZ = 0f; 57 | } 58 | 59 | // jump 60 | 61 | if (moveAllowed && Input.GetButtonDown("Jump")) 62 | creature.Jump(); 63 | 64 | // look 65 | 66 | if (moveAllowed && Input.GetKeyDown(KeyCode.Tab)) { 67 | if (catchMouse) { 68 | Cursor.visible = true; 69 | Cursor.lockState = CursorLockMode.None; 70 | } 71 | catchMouse = !catchMouse; 72 | } 73 | 74 | if (catchMouse) { 75 | Cursor.visible = false; 76 | Cursor.lockState = CursorLockMode.Locked; 77 | } 78 | } 79 | 80 | void LateUpdate() { 81 | if (moveAllowed && catchMouse) { 82 | yaw += Input.GetAxis("Mouse X") * yawRotSpeed * macMouseFactor * mouseSensitivity; 83 | smoothedYaw = Mathf.SmoothDamp(smoothedYaw, yaw, ref smoothYawVel, smoothness); 84 | 85 | pitch += Input.GetAxis("Mouse Y") * -pitchRotSpeed * macMouseFactor * mouseSensitivity * 1.1f; 86 | pitch = Mathf.Clamp(pitch, pitchMin, pitchMax); 87 | smoothedPitch = Mathf.SmoothDamp(smoothedPitch, pitch, ref smoothPitchVel, smoothness); 88 | 89 | RotTrans.localEulerAngles = new Vector3(smoothedPitch, Mathf.Repeat(smoothedYaw + 180f, 360f) - 180f, 0f); 90 | } 91 | 92 | RotTrans.position = camDummy.position; 93 | } 94 | 95 | void OnDisable() { 96 | Cursor.visible = true; 97 | Cursor.lockState = CursorLockMode.None; 98 | } 99 | 100 | // 101 | 102 | public void AllowMove(bool allow) { 103 | if (!allow) { 104 | creature.FactorX = creature.FactorZ = 0f; 105 | Cursor.visible = true; 106 | Cursor.lockState = CursorLockMode.None; 107 | catchMouse = false; 108 | } 109 | else { 110 | Cursor.visible = false; 111 | Cursor.lockState = CursorLockMode.Locked; 112 | catchMouse = true; 113 | } 114 | moveAllowed = allow; 115 | } 116 | 117 | public void Warped(float yaw) { 118 | smoothedYaw = this.yaw = yaw; 119 | RotTrans.localEulerAngles = new Vector3(smoothedPitch, Mathf.Repeat(smoothedYaw + 180f, 360f) - 180f, 0f); 120 | } 121 | } 122 | 123 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Poolable.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine.Events; 5 | 6 | namespace RatKing.Base { 7 | 8 | public class Poolable : MonoBehaviour { 9 | static Transform _poolParent; 10 | static readonly Dictionary> _stackByPrefab = new Dictionary>(); 11 | 12 | protected virtual string PoolParentName { get { return "Standard"; } } 13 | protected virtual Transform PoolParent { get { return _poolParent; } set { _poolParent = value; } } 14 | protected virtual Dictionary> StackByPrefab { get { return _stackByPrefab; } set { } } 15 | 16 | [SerializeField] int startCount = 10; 17 | [SerializeField] int addCount = 1; 18 | public enum Parenting { 19 | UsePoolParent, // a generated parent will be used for the pooled object 20 | UseOriginalParent, // the parent of the original will be used for the pooled object, and it will be set inactive 21 | DontChangeParent // no parent change will happen, the pooled object will be set inactive 22 | } 23 | [SerializeField] Parenting parenting = Parenting.UsePoolParent; 24 | [SerializeField] UnityEvent onPop = null; 25 | [SerializeField] UnityEvent onPush = null; 26 | 27 | Poolable original; 28 | bool isOriginal = true; 29 | 30 | ParticleSystem ps; 31 | 32 | // 33 | 34 | [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] 35 | static void OnRuntimeInitializeOnLoad() { 36 | _stackByPrefab.Clear(); 37 | } 38 | 39 | // 40 | 41 | void Awake() { 42 | if (isOriginal && parenting == Parenting.UseOriginalParent) { gameObject.SetActive(false); } 43 | } 44 | 45 | void CreateInstanceInPool(Stack stack) { 46 | var go = (GameObject)Instantiate(original.gameObject); 47 | switch (parenting) { 48 | case Parenting.UsePoolParent: 49 | go.transform.SetParent(PoolParent); 50 | break; 51 | case Parenting.UseOriginalParent: 52 | go.transform.SetParent(original.transform.parent); 53 | go.SetActive(false); 54 | break; 55 | case Parenting.DontChangeParent: 56 | go.SetActive(false); 57 | break; 58 | } 59 | go.name = original.name; 60 | var p = go.GetComponent(); 61 | p.original = original; 62 | p.isOriginal = false; 63 | p.ps = go.GetComponent(); 64 | stack.Push(p); 65 | } 66 | 67 | /// 68 | /// Prepare the pool. 69 | /// Doesn't have to be called, but most often it's good practice. But call it ONLY ONCE! 70 | /// 71 | public void PoolPrepare(int startCount = -1) { 72 | if (!isOriginal) 73 | return; 74 | 75 | if (StackByPrefab.ContainsKey(this)) { 76 | return; 77 | // Debug.LogWarning("Trying to manually prepare the Poolable " + name + " more than once! You should fix that!"); 78 | } 79 | 80 | if (PoolParent == null) { 81 | PoolParent = new GameObject("<" + PoolParentName + " Pool>").transform; 82 | GameObject.DontDestroyOnLoad(PoolParent.gameObject); 83 | PoolParent.gameObject.SetActive(false); 84 | } 85 | original = this; 86 | 87 | if (startCount < 0) 88 | startCount = this.startCount; 89 | 90 | var stack = StackByPrefab[original] = new Stack(startCount + 1); 91 | for (int i = 0; i < startCount; ++i) { 92 | CreateInstanceInPool(stack); 93 | } 94 | } 95 | 96 | // 97 | 98 | public T PoolPop() where T : Component { 99 | return PoolPop().GetComponent(); 100 | } 101 | 102 | public T PoolPop(Vector3 pos) where T : Component { 103 | return PoolPop(pos).GetComponent(); 104 | } 105 | 106 | public T PoolPop(Vector3 pos, Quaternion rot) where T : Component { 107 | return PoolPop(pos, rot).GetComponent(); 108 | } 109 | 110 | public Poolable PoolPop() { 111 | if (original == null) 112 | return PoolPop(transform.position, transform.rotation); 113 | return PoolPop(original.transform.position, original.transform.rotation); 114 | } 115 | 116 | public Poolable PoolPop(Vector3 pos) { 117 | if (original == null) 118 | return PoolPop(pos, transform.rotation); 119 | return PoolPop(pos, original.transform.rotation); 120 | } 121 | 122 | public Poolable PoolPop(Vector3 pos, Quaternion rot) { 123 | if (original == null || !StackByPrefab.ContainsKey(original)) { 124 | PoolPrepare(); 125 | } 126 | 127 | var stack = StackByPrefab[original]; 128 | 129 | if (stack.Count == 0) 130 | for (int i = 0; i < addCount; ++i) 131 | CreateInstanceInPool(stack); 132 | var p = stack.Pop(); 133 | var t = p.transform; 134 | switch (parenting) { 135 | case Parenting.UsePoolParent: 136 | t.SetParent(null); 137 | #if UNITY_EDITOR 138 | PoolParent.name = "<" + PoolParentName + " Pool " + PoolParent.childCount + ">"; 139 | #endif 140 | break; 141 | case Parenting.UseOriginalParent: 142 | t.SetParent(original.transform.parent); 143 | p.gameObject.SetActive(true); 144 | break; 145 | case Parenting.DontChangeParent: 146 | p.gameObject.SetActive(true); 147 | break; 148 | } 149 | t.SetPositionAndRotation(pos, rot); 150 | t.localScale = original.transform.localScale; 151 | 152 | if (p.ps != null) 153 | p.ps.Play(); 154 | 155 | if (p.onPop != null) 156 | p.onPop.Invoke(); 157 | 158 | return p; 159 | } 160 | 161 | public void PoolPush() { 162 | if (isOriginal) { 163 | #if UNITY_EDITOR 164 | Debug.LogWarning("Trying to push the original prefab into the pool! You should fix that!"); 165 | #endif 166 | return; 167 | } 168 | switch (parenting) { 169 | case Parenting.UsePoolParent: 170 | transform.SetParent(PoolParent); 171 | #if UNITY_EDITOR 172 | PoolParent.name = "<" + PoolParentName + " Pool " + PoolParent.childCount + ">"; 173 | #endif 174 | break; 175 | case Parenting.UseOriginalParent: 176 | case Parenting.DontChangeParent: 177 | gameObject.SetActive(false); 178 | break; 179 | } 180 | var stack = StackByPrefab[original]; 181 | stack.Push(this); 182 | 183 | if (onPush != null) 184 | onPush.Invoke(); 185 | } 186 | 187 | public bool IsPushable() { 188 | return original != null; 189 | } 190 | 191 | // 192 | 193 | void OnValidate() { 194 | if (addCount < 1) addCount = 1; 195 | if (startCount < 0) startCount = 0; 196 | } 197 | } 198 | 199 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Range.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace RatKing.Base { 6 | 7 | [System.Serializable] 8 | public struct RangeInt { 9 | public int min; 10 | public int max; 11 | 12 | public RangeInt(int min, int max) { 13 | this.min = min; 14 | this.max = max; 15 | } 16 | 17 | public void Validate() { 18 | if (max < min) { var tmp = min; min = max; max = tmp; } 19 | } 20 | 21 | public int Random(System.Random generator = null) { 22 | int a = min, b = max; 23 | if (a > b) { a = b; b = min; } 24 | if (generator == null) { return UnityEngine.Random.Range(a, b + 1); } 25 | return generator.Next(a, b + 1); 26 | } 27 | 28 | public int Clamp(int value) { 29 | return value > max ? max : value < min ? min : value; 30 | } 31 | 32 | public int Difference { get { return Mathf.Abs(max - min); } } 33 | 34 | // 35 | 36 | public static bool operator ==(RangeInt a, RangeInt b) { return a.min == b.min && a.max == b.max; } 37 | public static bool operator !=(RangeInt a, RangeInt b) { return a.min != b.min || a.max != b.max; } 38 | public override bool Equals(object o) { var p = (RangeInt)o; return p == this; } 39 | public override int GetHashCode() { return base.GetHashCode(); } 40 | public bool Equals(RangeInt other) { return min == other.min && max == other.max; } 41 | public override string ToString() { return "[" + min + "," + max + "]"; } 42 | } 43 | 44 | [System.Serializable] 45 | public struct RangeFloat { 46 | public float min; 47 | public float max; 48 | public float SqrMin => min * min; 49 | public float SqrMax => max * max; 50 | 51 | public RangeFloat(float min, float max) { 52 | this.min = min; 53 | this.max = max; 54 | } 55 | 56 | public void Validate() { 57 | if (max < min) { var tmp = min; min = max; max = tmp; } 58 | } 59 | 60 | public float Random(System.Random generator = null) { 61 | float a = min, b = max; 62 | if (a > b) { a = b; b = min; } 63 | if (generator == null) { return UnityEngine.Random.Range(a, b); } 64 | return (float)generator.NextDouble() * (b - a) + a; 65 | } 66 | 67 | public float Lerp(float factor) { 68 | return min + (max - min) * factor; 69 | } 70 | 71 | public static RangeFloat Lerp(Base.RangeFloat a, Base.RangeFloat b, float factor) { 72 | var min = a.min + (b.min - a.min) * factor; 73 | var max = a.max + (b.max - a.max) * factor; 74 | return new RangeFloat(min, max); 75 | } 76 | 77 | public float LerpClamped(float factor) { 78 | return min + (max - min) * Mathf.Clamp01(factor); 79 | } 80 | 81 | public float InverseLerp(float value) { 82 | return (value - min) / (max - min); 83 | } 84 | 85 | public float InverseLerpClamped(float value) { 86 | return Mathf.Clamp01((value - min) / (max - min)); 87 | } 88 | 89 | public float Clamp(float value) { 90 | return value > max ? max : value < min ? min : value; 91 | } 92 | 93 | public float RemapTo(float min, float max, float value) { 94 | return ((max - min) * (value - this.min) / (this.max - this.min)) + min; 95 | } 96 | 97 | public float RemapTo(RangeFloat range, float value) { 98 | return ((range.max - range.min) * (value - this.min) / (this.max - this.min)) + range.min; 99 | } 100 | 101 | public float RemapClampedTo(float min, float max, float value) { 102 | return ((max - min) * Mathf.Clamp01((value - this.min) / (this.max - this.min))) + min; 103 | } 104 | 105 | public float RemapClampedTo(RangeFloat range, float value) { 106 | return ((range.max - range.min) * Mathf.Clamp01((value - this.min) / (this.max - this.min))) + range.min; 107 | } 108 | 109 | public float Difference { get { return Mathf.Abs(max - min); } } 110 | 111 | // 112 | 113 | public static bool operator ==(RangeFloat a, RangeFloat b) { return a.min == b.min && a.max == b.max; } 114 | public static bool operator !=(RangeFloat a, RangeFloat b) { return a.min != b.min || a.max != b.max; } 115 | public override bool Equals(object o) { var p = (RangeFloat)o; return p == this; } 116 | public override int GetHashCode() { return base.GetHashCode(); } 117 | public bool Equals(RangeFloat other) { return min == other.min && max == other.max; } 118 | public override string ToString() { return "[" + min + "," + max + "]"; } 119 | } 120 | 121 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Testing.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | namespace RatKing.Base { 5 | 6 | public class Testing : MonoBehaviour { 7 | public string screenshotPrefix = "screen"; 8 | public float screenshotTakeRate = 0.25f; 9 | bool takingScreenshots; 10 | 11 | // 12 | 13 | void Update() { 14 | if (screenshotTakeRate > 0f && Input.GetKeyDown(KeyCode.F11)) { 15 | if (!takingScreenshots) 16 | StartCoroutine("ScreenshotTakerCR"); 17 | else 18 | StopCoroutine("ScreenshotTakerCR"); 19 | takingScreenshots = !takingScreenshots; 20 | } 21 | if (Input.GetKeyDown(KeyCode.F12)) { 22 | Debugging.CreateScreenshot(screenshotPrefix); 23 | } 24 | if (Input.GetKeyDown(KeyCode.F4)) { 25 | UnityEngine.SceneManagement.SceneManager.LoadScene(UnityEngine.SceneManagement.SceneManager.GetActiveScene().buildIndex); 26 | } 27 | } 28 | 29 | IEnumerator ScreenshotTakerCR() { 30 | var wait = new WaitForSeconds(screenshotTakeRate); 31 | while (true) { 32 | Debugging.CreateScreenshot(screenshotPrefix, "screenshots/series"); 33 | yield return wait; 34 | } 35 | } 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/EventVarFloat.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace RatKing.Base { 6 | 7 | // source: https://unity3d.com/how-to/architect-with-scriptable-objects 8 | // source: https://jacksondunstan.com/articles/3547 9 | 10 | [CreateAssetMenu(fileName="New Event Float", menuName="Variables/Event Float")] 11 | public class EventVarFloat : ScriptableObject, ISerializationCallbackReceiver { 12 | // 13 | [SerializeField] float startValue = 0f; 14 | public float StartValue { get { return startValue; } } 15 | // 16 | float value; 17 | System.Action OnChanged; 18 | // 19 | public float Value { 20 | get { return value; } 21 | set { 22 | var oldValue = this.value; 23 | this.value = value; 24 | if (OnChanged != null) { 25 | OnChanged(this, oldValue, value); 26 | } 27 | } 28 | } 29 | 30 | public void Reset(bool callEvents = true) { 31 | if (callEvents) { Value = startValue; } 32 | else { value = startValue; } 33 | } 34 | 35 | // 36 | 37 | void ISerializationCallbackReceiver.OnAfterDeserialize() { value = startValue; } 38 | void ISerializationCallbackReceiver.OnBeforeSerialize() { } 39 | 40 | // 41 | 42 | public void AddListener(System.Action listener, bool callAtOnce = false) { 43 | OnChanged += listener; 44 | if (callAtOnce) { listener(this, value, value); } 45 | } 46 | 47 | public void RemoveListener(System.Action listener) { 48 | OnChanged -= listener; 49 | } 50 | 51 | public override string ToString() { 52 | return value.ToString(); 53 | } 54 | 55 | public bool Equals(EventVarFloat other) { 56 | return other.value.Equals(value); 57 | } 58 | 59 | public override bool Equals(object other) { 60 | return other != null 61 | && other is EventVarFloat 62 | && ((EventVarFloat)other).value.Equals(value); 63 | } 64 | 65 | public override int GetHashCode() { 66 | return value.GetHashCode(); 67 | } 68 | 69 | // 70 | 71 | public static implicit operator float(EventVarFloat ev) { 72 | return ev.value; 73 | } 74 | 75 | public static EventVarFloat operator ++(EventVarFloat ev) { ev.Value++; return ev; } 76 | public static EventVarFloat operator --(EventVarFloat ev) { ev.Value--; return ev; } 77 | } 78 | 79 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/EventVarInt.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace RatKing.Base { 6 | 7 | // source: https://unity3d.com/how-to/architect-with-scriptable-objects 8 | // source: https://jacksondunstan.com/articles/3547 9 | 10 | [CreateAssetMenu(fileName="New Event Int", menuName="Variables/Event Int")] 11 | public class EventVarInt : ScriptableObject, ISerializationCallbackReceiver { 12 | [SerializeField] int startValue = 0; 13 | public int StartValue { get { return startValue; } } 14 | // 15 | int value; 16 | System.Action OnChanged; 17 | // 18 | public int Value { 19 | get { return value; } 20 | set { 21 | var oldValue = this.value; 22 | this.value = value; 23 | if (OnChanged != null) { 24 | OnChanged(this, oldValue, value); 25 | } 26 | } 27 | } 28 | 29 | public void Reset(bool callEvents = true) { 30 | if (callEvents) { Value = startValue; } 31 | else { value = startValue; } 32 | } 33 | 34 | // 35 | 36 | void ISerializationCallbackReceiver.OnAfterDeserialize() { value = startValue; } 37 | void ISerializationCallbackReceiver.OnBeforeSerialize() { } 38 | 39 | // 40 | 41 | public void AddListener(System.Action listener, bool callAtOnce = false) { 42 | OnChanged += listener; 43 | if (callAtOnce) { listener(this, value, value); } 44 | } 45 | 46 | public void RemoveListener(System.Action listener) { 47 | OnChanged -= listener; 48 | } 49 | 50 | public override string ToString() { 51 | return value.ToString(); 52 | } 53 | 54 | public bool Equals(EventVarInt other) { 55 | return other.value.Equals(value); 56 | } 57 | 58 | public override bool Equals(object other) { 59 | return other != null 60 | && other is EventVarInt 61 | && ((EventVarInt)other).value.Equals(value); 62 | } 63 | 64 | public override int GetHashCode() { 65 | return value.GetHashCode(); 66 | } 67 | 68 | // 69 | 70 | public static implicit operator int(EventVarInt ev) { 71 | return ev.value; 72 | } 73 | 74 | public static EventVarInt operator ++(EventVarInt ev) { ev.Value++; return ev; } 75 | public static EventVarInt operator --(EventVarInt ev) { ev.Value--; return ev; } 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/FloatyFloats.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace RatKing { 6 | 7 | public class FloatyFloat { 8 | 9 | class FloatyFloats : MonoBehaviour { 10 | static FloatyFloats instance; 11 | static readonly List floats = new List(); 12 | 13 | // 14 | 15 | [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] 16 | static void OnRuntimeInitializeOnLoad() { 17 | instance = null; 18 | floats.Clear(); 19 | } 20 | 21 | // 22 | 23 | static void Init() { 24 | instance = new GameObject("").AddComponent(); 25 | } 26 | 27 | public static void Register(FloatyFloat floatyFloat) { 28 | if (instance == null) { Init(); } 29 | floats.Add(floatyFloat); 30 | } 31 | 32 | public static void Unregister(FloatyFloat floatyFloat) { 33 | floats.Remove(floatyFloat); 34 | } 35 | 36 | // 37 | 38 | void Update() { 39 | foreach (var f in floats) { 40 | if (f.curWait > Time.time) { continue; } 41 | f.CurValue = Mathf.SmoothDamp(f.CurValue, f.target, ref f.velocity, f.smoothTime); 42 | } 43 | } 44 | } 45 | 46 | // 47 | 48 | public float CurValue { get; private set; } = 0f; 49 | float target = 0f; 50 | public float Target { 51 | get { return target; } 52 | set { target = value; curWait = Time.time + delay; } 53 | } 54 | readonly float smoothTime = 0.5f; 55 | readonly float delay = 0f; 56 | float curWait = 0f; 57 | float velocity = 0f; 58 | 59 | 60 | public FloatyFloat() { 61 | FloatyFloats.Register(this); 62 | } 63 | public FloatyFloat(float value) { 64 | CurValue = target = value; 65 | FloatyFloats.Register(this); 66 | } 67 | public FloatyFloat(float value, float delay) { 68 | CurValue = target = value; 69 | this.delay = delay; 70 | FloatyFloats.Register(this); 71 | } 72 | public FloatyFloat(float value, float delay, float smoothTime) { 73 | CurValue = target = value; 74 | this.delay = delay; 75 | this.smoothTime = smoothTime; 76 | FloatyFloats.Register(this); 77 | } 78 | 79 | public void Destroy() { 80 | FloatyFloats.Unregister(this); 81 | } 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/InstancedVariablesContainer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public interface IInstanceVar { 8 | IInstanceVar GetCopy(); 9 | void SendOnChangeMessage(Component c, string name); 10 | string ToString(); 11 | } 12 | 13 | public class InstanceVar : IInstanceVar { 14 | public T value; 15 | public InstanceVar(T value) { this.value = value; } 16 | public void Set(T value) { this.value = value; } 17 | public virtual IInstanceVar GetCopy() { return new InstanceVar(value); } 18 | public override string ToString() { return value.ToString(); } 19 | // 20 | public void SendOnChangeMessage(Component c, string name) { c.SendMessage("OnChangeVar_" + name, value, SendMessageOptions.DontRequireReceiver); } 21 | } 22 | 23 | public class InstanceVarInt : InstanceVar { 24 | public InstanceVarInt(int value) : base(value) { } 25 | public override IInstanceVar GetCopy() { return new InstanceVarInt(value); } 26 | public override string ToString() { return value.ToString(); } 27 | } 28 | public class InstanceVarFloat : InstanceVar { 29 | public InstanceVarFloat(float value) : base(value) { } 30 | public override IInstanceVar GetCopy() { return new InstanceVarFloat(value); } 31 | public override string ToString() { return value.ToString("0.###"); } 32 | } 33 | public class InstanceVarString : InstanceVar { 34 | public InstanceVarString(string value) : base(value) { } 35 | public override IInstanceVar GetCopy() { return new InstanceVarString(value); } 36 | public override string ToString() { return '"' + StringExtras.Escape(value) + '"'; } 37 | } 38 | public class InstanceVarBool : InstanceVar { 39 | public InstanceVarBool(bool value) : base(value) { } 40 | public override IInstanceVar GetCopy() { return new InstanceVarBool(value); } 41 | public override string ToString() { return value ? "1" : "0"; } 42 | } 43 | public class InstanceVarList : InstanceVar { 44 | public InstanceVarList(ListType value) : base(value) { } 45 | public override IInstanceVar GetCopy() { return new InstanceVarList(value.GetCopy()); } 46 | public override string ToString() { return value.ToString(); } 47 | } 48 | 49 | // 50 | 51 | public class InstancedVariablesContainer { 52 | readonly int varCount = 0; 53 | readonly List templateVars = null; 54 | IInstanceVar[] instanceVars; 55 | 56 | // 57 | 58 | public InstancedVariablesContainer(TemplateVariables templateVars) : this(templateVars.List) { 59 | } 60 | 61 | public InstancedVariablesContainer(List templateVars) { 62 | if (templateVars == null) { return; } 63 | this.templateVars = templateVars; 64 | varCount = templateVars.Count; 65 | if (instanceVars == null || instanceVars.Length != varCount) { instanceVars = new IInstanceVar[varCount]; } 66 | for (int i = 0, j = 0; i < varCount; ++i) { 67 | var vt = templateVars[i]; 68 | if (vt == null) { Debug.LogError("Missing variable"); break; } 69 | instanceVars[j] = vt.GetNewVar(); 70 | ++j; 71 | } 72 | } 73 | 74 | public bool Set(string id, T value) { 75 | for (int i = 0; i < varCount; ++i) { 76 | if (templateVars[i].name == id && instanceVars[i] is InstanceVar) { 77 | (instanceVars[i] as InstanceVar).Set(value); 78 | return true; 79 | } 80 | } 81 | return false; 82 | } 83 | 84 | public T Get(string id, T standard = default) { 85 | for (int i = 0; i < varCount; ++i) { 86 | if (templateVars[i].name == id && instanceVars[i] is InstanceVar) { 87 | return (instanceVars[i] as InstanceVar).value; 88 | } 89 | } 90 | return standard; 91 | } 92 | 93 | public bool Has(string id) { 94 | for (int i = 0; i < varCount; ++i) { 95 | if (templateVars[i].name == id && instanceVars[i] is InstanceVar) { 96 | return true; 97 | } 98 | } 99 | return false; 100 | } 101 | 102 | public IInstanceVar[] GetCopyOfVars() { 103 | if (instanceVars == null) { return null; } 104 | var copy = new IInstanceVar[varCount]; 105 | for (int i = 0; i < varCount; ++i) { 106 | copy[i] = instanceVars[i].GetCopy(); 107 | } 108 | return copy; 109 | } 110 | } 111 | 112 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/ListType.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace RatKing.Base { 6 | 7 | public class ListType { 8 | public TemplateVarList names; 9 | public int index; 10 | // 11 | public ListType(TemplateVarList names) { this.names = names; this.index = 0; } 12 | public ListType(TemplateVarList names, int index) { this.names = names; this.index = index; } 13 | public ListType GetCopy() { return new ListType(names, index); } 14 | // 15 | public override string ToString() { return index.ToString() + "/" + names.GetNames().Length; } 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/TemplateVar.T.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using UnityEditor; 3 | #endif 4 | using UnityEngine; 5 | using System.Collections.Generic; 6 | 7 | namespace RatKing.Base { 8 | 9 | [System.Serializable] 10 | public class TemplateVar : TemplateVar { 11 | public virtual T GetValue() { return default; } 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/TemplateVar.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using UnityEditor; 3 | #endif 4 | using UnityEngine; 5 | using System.Collections.Generic; 6 | 7 | namespace RatKing.Base { 8 | 9 | [System.Serializable] 10 | public class TemplateVar : ScriptableObject { 11 | 12 | public enum MinMax { None = 0, HasMinValue = 1, HasMaxValue = 2, HasMinAndMaxValue = 3, HasMinAndMaxSuggestion = 4 } 13 | 14 | public virtual IInstanceVar GetNewVar() { return null; } 15 | public override string ToString() { return ""; } 16 | #if UNITY_EDITOR 17 | protected virtual string Unity3DGetButtonName() { return "NON"; } 18 | protected virtual void Unity3DSetStandardValue(Rect r) { /*nothing*/ } 19 | public bool Unity3DDrawAndCheck(Rect r) { 20 | var w = r.width; r.width = 38f; var res = GUI.Button(r, Unity3DGetButtonName()); 21 | r.x += r.width; r.width = 62f; name = GUI.TextField(r, name ?? ""); 22 | r.x += r.width; r.width = w - 100f; Unity3DSetStandardValue(r); 23 | return res; 24 | } 25 | #endif 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/TemplateVarBool.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using UnityEditor; 3 | #endif 4 | using UnityEngine; 5 | 6 | namespace RatKing.Base { 7 | 8 | [System.Serializable] 9 | public class TemplateVarBool : TemplateVar { 10 | public bool standardValue; 11 | public override IInstanceVar GetNewVar() { return new InstanceVarBool(standardValue); } 12 | public override bool GetValue() { return standardValue; } 13 | public override string ToString() { return standardValue ? "1" : "0"; } 14 | #if UNITY_EDITOR 15 | protected override string Unity3DGetButtonName() { return "Y/N"; } 16 | protected override void Unity3DSetStandardValue(Rect r) { standardValue = EditorGUI.Toggle(r, standardValue); } 17 | #endif 18 | 19 | // 20 | 21 | public static implicit operator bool(TemplateVarBool tv) { 22 | return tv.standardValue; 23 | } 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/TemplateVarFloat.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using UnityEditor; 3 | #endif 4 | using UnityEngine; 5 | 6 | namespace RatKing.Base { 7 | 8 | [System.Serializable] 9 | public class TemplateVarFloat : TemplateVar { 10 | public float standardValue; 11 | public MinMax minMax = MinMax.None; 12 | public float valueMin; 13 | public float valueMax; 14 | public override IInstanceVar GetNewVar() { return new InstanceVarFloat(standardValue); } 15 | public override float GetValue() { return standardValue; } 16 | public override string ToString() { return standardValue.ToString("0.###"); } 17 | #if UNITY_EDITOR 18 | protected override string Unity3DGetButtonName() { return "FLT"; } 19 | protected override void Unity3DSetStandardValue(Rect r) { standardValue = EditorGUI.FloatField(r, standardValue); } 20 | #endif 21 | public bool IsOutsideMinMax(InstanceVarFloat num) { 22 | return num.value < valueMin || num.value > valueMax; 23 | } 24 | 25 | // 26 | 27 | public static implicit operator float(TemplateVarFloat tv) { 28 | return tv.standardValue; 29 | } 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/TemplateVarInt.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using UnityEditor; 3 | #endif 4 | using UnityEngine; 5 | 6 | namespace RatKing.Base { 7 | 8 | [System.Serializable] 9 | public class TemplateVarInt : TemplateVar { 10 | public int standardValue; 11 | public MinMax minMax = MinMax.None; 12 | public int valueMin; 13 | public int valueMax; 14 | public override IInstanceVar GetNewVar() { return new InstanceVarInt(standardValue); } 15 | public override int GetValue() { return standardValue; } 16 | public override string ToString() { return standardValue.ToString("0.###"); } 17 | #if UNITY_EDITOR 18 | protected override string Unity3DGetButtonName() { return "INT"; } 19 | protected override void Unity3DSetStandardValue(Rect r) { standardValue = EditorGUI.IntField(r, standardValue); } 20 | #endif 21 | public bool IsOutsideMinMax(InstanceVarInt num) { 22 | return num.value < valueMin || num.value > valueMax; 23 | } 24 | 25 | // 26 | 27 | public static implicit operator int(TemplateVarInt tv) { 28 | return tv.standardValue; 29 | } 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/TemplateVarList.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using UnityEditor; 3 | #endif 4 | using UnityEngine; 5 | 6 | namespace RatKing.Base { 7 | 8 | [System.Serializable] 9 | public class TemplateVarList : TemplateVar { 10 | public int standardIndex; 11 | [SerializeField] string[] names = null; 12 | public TemplateVarList source = null; 13 | public override IInstanceVar GetNewVar() { return new InstanceVarList(new ListType(this, standardIndex)); } 14 | public override int GetValue() { return standardIndex; } 15 | public override string ToString() { return standardIndex.ToString(); } 16 | public string[] GetNames() { if (source != null) { return source.names; } return names; } 17 | public string GetName(int index) { if (source != null) { return source.names[index % source.names.Length]; } return names[index % names.Length]; } 18 | #if UNITY_EDITOR 19 | protected override string Unity3DGetButtonName() { return "LST"; } 20 | protected override void Unity3DSetStandardValue(Rect r) { standardIndex = EditorGUI.IntField(r, standardIndex); } 21 | #endif 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/TemplateVarString.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using UnityEditor; 3 | #endif 4 | using UnityEngine; 5 | 6 | namespace RatKing.Base { 7 | 8 | [System.Serializable] 9 | public class TemplateVarString : TemplateVar { 10 | public string standardValue; 11 | public bool multiLine; 12 | public override IInstanceVar GetNewVar() { return new InstanceVarString(standardValue); } 13 | public override string GetValue() { return standardValue; } 14 | public override string ToString() { return '"' + standardValue + '"'; } 15 | #if UNITY_EDITOR 16 | protected override string Unity3DGetButtonName() { return "TXT"; } 17 | protected override void Unity3DSetStandardValue(Rect r) { standardValue = EditorGUI.TextField(r, standardValue); } 18 | #endif 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/TemplateVariables.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using UnityEditor; 3 | #endif 4 | using UnityEngine; 5 | using System.Collections.Generic; 6 | 7 | namespace RatKing.Base { 8 | 9 | [System.Serializable] 10 | public class TemplateVariables { 11 | [SerializeField] List list = null; 12 | public List List { get => list; } 13 | 14 | // 15 | 16 | public T Get(string id, T standardValue = default) where T:TemplateVar { 17 | if (list == null) { return standardValue; } 18 | foreach (var v in list) { 19 | if (v is T && v.name == id) { return v as T; } 20 | } 21 | return standardValue; 22 | } 23 | 24 | public T GetByBaseType(string id, T standardValue = default) { 25 | if (list == null) { return standardValue; } 26 | foreach (var v in list) { 27 | if (v.name == id && v is TemplateVar vt) { 28 | return vt.GetValue(); 29 | } 30 | } 31 | return standardValue; 32 | } 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/VarFloat.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace RatKing.Base { 6 | 7 | // source: https://unity3d.com/how-to/architect-with-scriptable-objects 8 | 9 | [CreateAssetMenu(fileName="New Float", menuName="Variables/Float")] 10 | public class VarFloat : ScriptableObject, ISerializationCallbackReceiver { 11 | [SerializeField] float startValue = 0f; 12 | public float StartValue { get { return startValue; } } 13 | [System.NonSerialized] public float value; 14 | 15 | public void Reset() { 16 | value = startValue; 17 | } 18 | 19 | void ISerializationCallbackReceiver.OnAfterDeserialize() { value = startValue; } 20 | void ISerializationCallbackReceiver.OnBeforeSerialize() { } 21 | 22 | // 23 | 24 | public static implicit operator float(VarFloat v) { 25 | return v.value; 26 | } 27 | 28 | public static VarFloat operator ++(VarFloat v) { v.value++; return v; } 29 | public static VarFloat operator --(VarFloat v) { v.value--; return v; } 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /RatKing/Base/Scripts/Variables/VarInt.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace RatKing.Base { 6 | 7 | // source: https://unity3d.com/how-to/architect-with-scriptable-objects 8 | 9 | [CreateAssetMenu(fileName="New Int", menuName="Variables/Int")] 10 | public class VarInt : ScriptableObject, ISerializationCallbackReceiver { 11 | [SerializeField] int startValue = 0; 12 | public int StartValue { get { return startValue; } } 13 | [System.NonSerialized] public int value; 14 | 15 | public void Reset() { 16 | value = startValue; 17 | } 18 | 19 | void ISerializationCallbackReceiver.OnAfterDeserialize() { value = startValue; } 20 | void ISerializationCallbackReceiver.OnBeforeSerialize() { } 21 | 22 | // 23 | 24 | public static implicit operator float(VarInt v) { 25 | return v.value; 26 | } 27 | 28 | public static VarInt operator ++(VarInt v) { v.value++; return v; } 29 | public static VarInt operator --(VarInt v) { v.value--; return v; } 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /RatKing/Base/Shaders/BoxMappingDiffuse.shader: -------------------------------------------------------------------------------- 1 | Shader "A Rat King/BoxMappingDiffuse" { 2 | Properties { 3 | _Color ("Color", Color) = (1,1,1,1) 4 | _MainTex ("Base (RGB)", 2D) = "white" {} 5 | } 6 | SubShader { 7 | Tags { "RenderType"="Opaque" } 8 | LOD 200 9 | 10 | CGPROGRAM 11 | #pragma surface surf Lambert 12 | 13 | sampler2D _MainTex; 14 | uniform float4 _MainTex_ST; 15 | fixed4 _Color; 16 | 17 | struct Input { 18 | float3 worldPos; 19 | float3 worldNormal; 20 | }; 21 | 22 | 23 | /* 24 | float2x2 UVScaleRotation; 25 | float2 UVOffset; 26 | float2 CalculateUVs(float3 pos, float3 normal) 27 | { 28 | float diff = length(pos * normal) * 2; 29 | float2 uv = float2(diff + pos.x + (pos.z * normal.x), diff - pos.y + (pos.z * normal.y)); 30 | return mul(uv, UVScaleRotation) + UVOffset; 31 | } 32 | */ 33 | 34 | 35 | void surf (Input IN, inout SurfaceOutput o) { 36 | // taken from http://unifycommunity.com/wiki/index.php?title=3SideProjDiffuse 37 | float2 tex0 = IN.worldPos.xy * _MainTex_ST.xy + _MainTex_ST.zw; 38 | float2 tex1 = IN.worldPos.zx * _MainTex_ST.yx + _MainTex_ST.wz; 39 | float2 tex2 = IN.worldPos.zy * _MainTex_ST.xy + _MainTex_ST.zw; 40 | float4 color0_ = tex2D(_MainTex, tex0); 41 | float4 color1_ = tex2D(_MainTex, tex1); 42 | float4 color2_ = tex2D(_MainTex, tex2); 43 | 44 | float3 projnormal = saturate(pow(IN.worldNormal*1.5, 4)); 45 | half3 c = lerp(color1_, color0_, projnormal.z); 46 | c = lerp(c, color2_, projnormal.x); 47 | /* 48 | UVScaleRotation = float2x2(1, 0, 0, 1); 49 | UVOffset = float2(0, 0); 50 | c = tex2D(_MainTex, CalculateUVs(IN.worldPos, IN.worldNormal)); 51 | */ 52 | o.Albedo = c * _Color; 53 | } 54 | ENDCG 55 | } 56 | FallBack "Diffuse" 57 | } 58 | -------------------------------------------------------------------------------- /RatKing/Base/Shaders/MyFont.shader: -------------------------------------------------------------------------------- 1 | // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' 2 | 3 | Shader "A Rat King/3D Text Shader" { 4 | Properties { 5 | _MainTex ("Font Texture", 2D) = "white" {} 6 | _Color ("Text Color", Color) = (1,1,1,1) 7 | } 8 | 9 | SubShader { 10 | Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } 11 | Lighting Off Cull Back ZWrite Off Fog { Mode Off } 12 | Blend SrcAlpha OneMinusSrcAlpha 13 | 14 | Pass { 15 | ColorMask RGB 16 | 17 | CGPROGRAM 18 | #pragma vertex vert 19 | #pragma fragment frag 20 | #pragma fragmentoption ARB_precision_hint_fastest 21 | 22 | #include "UnityCG.cginc" 23 | 24 | sampler2D _MainTex; 25 | float4 _Color; 26 | 27 | struct f2v { 28 | float4 vertex : POSITION; 29 | half2 texcoord : TEXCOORD0; 30 | float4 color : COLOR; 31 | }; 32 | 33 | struct v2f { 34 | float4 pos : POSITION; 35 | half2 uv : TEXCOORD0; 36 | float4 color : COLOR; 37 | float4 projPos : TEXCOORD1; 38 | }; 39 | 40 | //float4 _MainTex_ST; 41 | 42 | v2f vert (f2v v) 43 | { 44 | v2f o; 45 | o.pos = UnityObjectToClipPos (v.vertex); 46 | o.projPos = ComputeScreenPos(o.pos); 47 | COMPUTE_EYEDEPTH(o.projPos.z); 48 | //o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); 49 | o.uv = v.texcoord; 50 | o.color = v.color; 51 | return o; 52 | } 53 | 54 | fixed4 frag( v2f i ) : COLOR 55 | { 56 | return tex2D(_MainTex, i.uv).a * i.color * _Color; 57 | } 58 | ENDCG 59 | } 60 | } 61 | 62 | //SubShader { 63 | // Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } 64 | // Lighting Off Cull Back ZWrite Off Fog { Mode Off } 65 | // Blend SrcAlpha OneMinusSrcAlpha 66 | // Pass { 67 | // ColorMask RGB 68 | // Color [_Color] 69 | // SetTexture [_MainTex] { 70 | // combine primary, texture * primary 71 | // } 72 | // } 73 | //} 74 | } -------------------------------------------------------------------------------- /RatKing/Base/Shaders/MyFontAlways.shader: -------------------------------------------------------------------------------- 1 | // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' 2 | 3 | Shader "A Rat King/3D Text Shader Always" { 4 | Properties { 5 | _MainTex ("Font Texture", 2D) = "white" {} 6 | _Color ("Text Color", Color) = (1,1,1,1) 7 | } 8 | 9 | SubShader { 10 | Tags { "Queue"="Transparent+1" "IgnoreProjector"="True" "RenderType"="Transparent" } 11 | Lighting Off Cull Off ZTest Always ZWrite Off Fog { Mode Off } 12 | Blend SrcAlpha OneMinusSrcAlpha 13 | 14 | Pass { 15 | ColorMask RGB 16 | 17 | CGPROGRAM 18 | #pragma vertex vert 19 | #pragma fragment frag 20 | #pragma fragmentoption ARB_precision_hint_fastest 21 | 22 | #include "UnityCG.cginc" 23 | 24 | sampler2D _MainTex; 25 | float4 _Color; 26 | 27 | struct f2v { 28 | float4 vertex : POSITION; 29 | half2 texcoord : TEXCOORD0; 30 | float4 color : COLOR; 31 | }; 32 | 33 | struct v2f { 34 | float4 pos : POSITION; 35 | half2 uv : TEXCOORD0; 36 | float4 color : COLOR; 37 | float4 projPos : TEXCOORD1; 38 | }; 39 | 40 | //float4 _MainTex_ST; 41 | 42 | v2f vert (f2v v) 43 | { 44 | v2f o; 45 | o.pos = UnityObjectToClipPos (v.vertex); 46 | o.projPos = ComputeScreenPos(o.pos); 47 | COMPUTE_EYEDEPTH(o.projPos.z); 48 | //o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); 49 | o.uv = v.texcoord; 50 | o.color = v.color; 51 | return o; 52 | } 53 | 54 | fixed4 frag( v2f i ) : COLOR 55 | { 56 | return tex2D(_MainTex, i.uv).a * i.color * _Color; 57 | } 58 | ENDCG 59 | } 60 | } 61 | 62 | //SubShader { 63 | // Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } 64 | // Lighting Off Cull Back ZWrite Off Fog { Mode Off } 65 | // Blend SrcAlpha OneMinusSrcAlpha 66 | // Pass { 67 | // ColorMask RGB 68 | // Color [_Color] 69 | // SetTexture [_MainTex] { 70 | // combine primary, texture * primary 71 | // } 72 | // } 73 | //} 74 | } -------------------------------------------------------------------------------- /RatKing/Base/Shaders/Rim.shader: -------------------------------------------------------------------------------- 1 | Shader "A Rat King/Rim" { 2 | Properties { 3 | _Color ("Main Color", Color) = (0.5,0.5,0.5,1) 4 | _MainTex ("Texture", 2D) = "white" {} 5 | _BumpMap ("Bumpmap", 2D) = "bump" {} 6 | _Emission ("Emission Factor", float) = 0.2 // (0.5, 0.5, 0.5, 0.5) 7 | _RimColor ("Rim Color", Color) = (0.5,0.5,0.5,0.0) 8 | _RimPower ("Rim Power", Range(0.5,8.0)) = 3.0 9 | } 10 | SubShader { 11 | Tags { "RenderType" = "Opaque" } 12 | 13 | CGPROGRAM 14 | #pragma surface surf Lambert 15 | 16 | struct Input { 17 | float2 uv_MainTex; 18 | float2 uv_BumpMap; 19 | float3 viewDir; 20 | }; 21 | 22 | fixed4 _Color; 23 | sampler2D _MainTex; 24 | sampler2D _BumpMap; 25 | float _Emission; 26 | float4 _RimColor; 27 | float _RimPower; 28 | 29 | /* 30 | void surf (Input IN, inout SurfaceOutput o) { 31 | o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb * _Color.rgb; 32 | half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal)); 33 | o.Emission = _RimColor.rgb * pow (rim, _RimPower) * _Emission; 34 | o.Alpha = _Color.a; // + _RimColor.a * o.Emission; 35 | } 36 | */ 37 | 38 | void surf (Input IN, inout SurfaceOutput o) { 39 | o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb * _Color.rgb; 40 | o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap)); 41 | half rim = 1.0 - saturate(dot (Unity_SafeNormalize(IN.viewDir), o.Normal)); 42 | o.Emission = _RimColor.rgb * pow (rim, _RimPower); 43 | o.Alpha = _Color.a; // + _RimColor.a * o.Emission; 44 | } 45 | 46 | ENDCG 47 | } 48 | 49 | Fallback "Diffuse" 50 | } -------------------------------------------------------------------------------- /RatKing/Base/Shaders/RimTransparent.shader: -------------------------------------------------------------------------------- 1 | Shader "A Rat King/RimTransparent" { 2 | Properties { 3 | _Color ("Main Color", Color) = (0.5,0.5,0.5,0.5) 4 | _MainTex ("Texture", 2D) = "white" {} 5 | _Emission ("Emission Factor", float) = 0.2 // (0.5, 0.5, 0.5, 0.5) 6 | _RimColor ("Rim Color", Color) = (0.5,0.5,0.5,0.0) 7 | _RimPower ("Rim Power", Range(0.5,8.0)) = 3.0 8 | } 9 | SubShader { 10 | Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"} 11 | LOD 200 12 | 13 | CGPROGRAM 14 | #pragma surface surf Lambert alpha 15 | 16 | struct Input { 17 | float2 uv_MainTex; 18 | float3 viewDir; 19 | }; 20 | 21 | fixed4 _Color; 22 | sampler2D _MainTex; 23 | float _Emission; 24 | float4 _RimColor; 25 | float _RimPower; 26 | 27 | void surf (Input IN, inout SurfaceOutput o) { 28 | half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; 29 | o.Albedo = c.rgb; 30 | //o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap)); 31 | half rim = 1.0 - saturate(dot (Unity_SafeNormalize(IN.viewDir), o.Normal)); 32 | o.Emission = _RimColor.rgb * pow (rim, _RimPower) * _Emission; 33 | 34 | o.Alpha = c.a; 35 | } 36 | ENDCG 37 | } 38 | 39 | Fallback "Transparent/Diffuse" 40 | } -------------------------------------------------------------------------------- /RatKing/Base/Shaders/SelfIllumDiffuse.shader: -------------------------------------------------------------------------------- 1 | Shader "A Rat King/SelfIllumDiffuse" { 2 | Properties { 3 | _Color ("Main Color", Color) = (0.5, 0.5, 0.5, 0.5) 4 | _Emission ("Emission Factor", float) = 0.2 // (0.5, 0.5, 0.5, 0.5) 5 | _MainTex ("Base (RGB)", 2D) = "white" {} 6 | } 7 | SubShader { 8 | Tags {"Queue"="Geometry" "RenderType"="Opaque"} 9 | LOD 200 10 | Lighting On 11 | 12 | CGPROGRAM 13 | #pragma surface surf Lambert 14 | 15 | sampler2D _MainTex; 16 | float4 _Color; 17 | float _Emission; 18 | 19 | struct Input { 20 | float2 uv_MainTex; 21 | }; 22 | 23 | void surf (Input IN, inout SurfaceOutput o) { 24 | half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; 25 | o.Albedo = c.rgb; 26 | o.Emission = c * _Emission; 27 | o.Alpha = _Color.a; 28 | } 29 | ENDCG 30 | } 31 | FallBack "Diffuse" 32 | } 33 | -------------------------------------------------------------------------------- /RatKing/Base/Shaders/SelfIllumDiffuseNoDepth.shader: -------------------------------------------------------------------------------- 1 | Shader "A Rat King/SelfIllumDiffuseNoDepth" { 2 | Properties { 3 | _Color ("Main Color", Color) = (0.5, 0.5, 0.5, 0.5) 4 | _Emission ("Emission Factor", float) = 0.2 // (0.5, 0.5, 0.5, 0.5) 5 | _MainTex ("Base (RGB)", 2D) = "white" {} 6 | } 7 | SubShader { 8 | Tags {"Queue"="Transparent-1" "RenderType"="Opaque"} 9 | LOD 200 10 | Lighting On 11 | 12 | 13 | CGPROGRAM 14 | #pragma surface surf Lambert 15 | 16 | sampler2D _MainTex; 17 | float4 _Color; 18 | float _Emission; 19 | 20 | struct Input { 21 | float2 uv_MainTex; 22 | }; 23 | 24 | void surf (Input IN, inout SurfaceOutput o) { 25 | half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; 26 | o.Albedo = c.rgb; 27 | o.Emission = c * _Emission; 28 | o.Alpha = _Color.a; 29 | } 30 | ENDCG 31 | } 32 | FallBack "Diffuse" 33 | } 34 | -------------------------------------------------------------------------------- /RatKing/Base/Shaders/SelfIllumTransparent.shader: -------------------------------------------------------------------------------- 1 | Shader "A Rat King/SelfIllumTransparent" { 2 | Properties { 3 | _Color ("Main Color", Color) = (0.5, 0.5, 0.5, 0.5) 4 | _Emission ("Emission Factor", float) = 0.2 // (0.5, 0.5, 0.5, 0.5) 5 | _MainTex ("Base (RGB)", 2D) = "white" {} 6 | } 7 | SubShader { 8 | Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"} 9 | LOD 200 10 | // Lighting On 11 | 12 | CGPROGRAM 13 | #pragma surface surf Lambert alpha 14 | 15 | sampler2D _MainTex; 16 | float4 _Color; 17 | float _Emission; 18 | 19 | struct Input { 20 | float2 uv_MainTex; 21 | }; 22 | 23 | void surf (Input IN, inout SurfaceOutput o) { 24 | half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; 25 | o.Albedo = c.rgb; 26 | o.Emission = c * _Emission; 27 | o.Alpha = c.a; 28 | } 29 | ENDCG 30 | } 31 | FallBack "Transparent/Diffuse" 32 | } 33 | -------------------------------------------------------------------------------- /RatKing/Base/Shaders/SelfIllumTransparentGeometry.shader: -------------------------------------------------------------------------------- 1 | Shader "A Rat King/SelfIllumTransparentGeometry" { 2 | Properties { 3 | _Color ("Main Color", Color) = (0.5, 0.5, 0.5, 0.5) 4 | _Emission ("Emission Factor", float) = 0.2 // (0.5, 0.5, 0.5, 0.5) 5 | _MainTex ("Base (RGB)", 2D) = "white" {} 6 | } 7 | SubShader { 8 | Tags {"Queue"="Geometry" "IgnoreProjector"="True" "RenderType"="Transparent"} 9 | LOD 200 10 | // Lighting On 11 | 12 | CGPROGRAM 13 | #pragma surface surf Lambert alpha 14 | 15 | sampler2D _MainTex; 16 | float4 _Color; 17 | float _Emission; 18 | 19 | struct Input { 20 | float2 uv_MainTex; 21 | }; 22 | 23 | void surf (Input IN, inout SurfaceOutput o) { 24 | half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; 25 | o.Albedo = c.rgb; 26 | o.Emission = c * _Emission; 27 | o.Alpha = c.a; 28 | } 29 | ENDCG 30 | } 31 | FallBack "Transparent/Diffuse" 32 | } 33 | -------------------------------------------------------------------------------- /RatKing/Base/Shaders/SelfIllumTransparentZwrite.shader: -------------------------------------------------------------------------------- 1 | // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' 2 | 3 | Shader "A Rat King/SelfIllumTransparentZwrite" { 4 | Properties { 5 | _Color ("Main Color", Color) = (0.5, 0.5, 0.5, 0.5) 6 | _Emission ("Emission Factor", float) = 0.2 // (0.5, 0.5, 0.5, 0.5) 7 | _MainTex ("Base (RGB)", 2D) = "white" {} 8 | } 9 | SubShader { 10 | Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"} 11 | //Tags {"Queue"="Geometry" "IgnoreProjector"="True" "RenderType"="Transparent"} 12 | LOD 200 13 | // Lighting On 14 | 15 | Pass { 16 | Zwrite on 17 | ColorMask 0 18 | 19 | CGPROGRAM 20 | #pragma vertex vert 21 | #pragma fragment frag 22 | #pragma fragmentoption ARB_precision_hint_fastest 23 | #include "UnityCG.cginc" 24 | sampler2D _MainTex; 25 | float4 _Color; 26 | struct f2v { float4 vertex : POSITION; half2 texcoord : TEXCOORD0; }; 27 | struct v2f { float4 pos : POSITION; half2 uv : TEXCOORD0; float4 projPos : TEXCOORD1; }; 28 | float4 _MainTex_ST; 29 | v2f vert (f2v v) { v2f o; o.pos = UnityObjectToClipPos (v.vertex); o.projPos = ComputeScreenPos(o.pos); COMPUTE_EYEDEPTH(o.projPos.z); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); return o; } 30 | fixed4 frag( v2f i ) : COLOR { return tex2D(_MainTex, i.uv) * _Color; } 31 | ENDCG 32 | } 33 | 34 | CGPROGRAM 35 | #pragma surface surf Lambert alpha 36 | 37 | sampler2D _MainTex; 38 | float4 _Color; 39 | float _Emission; 40 | 41 | struct Input { 42 | float2 uv_MainTex; 43 | }; 44 | 45 | void surf (Input IN, inout SurfaceOutput o) { 46 | half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; 47 | o.Albedo = c.rgb; 48 | o.Emission = c * _Emission; 49 | o.Alpha = c.a; 50 | } 51 | ENDCG 52 | } 53 | FallBack "Transparent/Diffuse" 54 | } 55 | -------------------------------------------------------------------------------- /RatKing/Base/Shaders/VertexColored.shader: -------------------------------------------------------------------------------- 1 | Shader "A Rat King/VertexColored" { 2 | Properties { 3 | _Color ("Main Color", Color) = (1,1,1,1) 4 | _Emission ("Emission Factor", float) = 0.2 5 | } 6 | SubShader { 7 | Tags { "IgnoreProjector"="True" "RenderType"="TransparentCutout"} 8 | LOD 200 9 | Cull Back 10 | 11 | CGPROGRAM 12 | #pragma surface surf Lambert 13 | 14 | fixed4 _Color; 15 | float _Emission; 16 | 17 | struct Input { 18 | float4 color : COLOR; 19 | }; 20 | 21 | void surf (Input IN, inout SurfaceOutput o) { 22 | half4 c = IN.color * _Color; 23 | o.Albedo = c.rgb; 24 | o.Alpha = c.a; 25 | o.Emission = c * _Emission; 26 | } 27 | ENDCG 28 | } 29 | 30 | Fallback "Transparent/Cutout/VertexLit" 31 | } 32 | -------------------------------------------------------------------------------- /RatKing/Base/Shaders/VertexColoredAlpha.shader: -------------------------------------------------------------------------------- 1 | Shader "A Rat King/VertexColoredAlpha" { 2 | Properties { 3 | _Color ("Main Color", Color) = (1,1,1,1) 4 | _MainTex ("Base (RGB)", 2D) = "white" {} 5 | _Emission ("Emission Factor", float) = 0.2 // (0.5, 0.5, 0.5, 0.5) 6 | } 7 | SubShader { 8 | Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"} // Cutout"} 9 | LOD 200 10 | Cull Off 11 | 12 | CGPROGRAM 13 | #pragma surface surf Lambert alpha 14 | 15 | fixed4 _Color; 16 | sampler2D _MainTex; 17 | float _Emission; 18 | 19 | struct Input { 20 | float4 color : COLOR; 21 | float2 uv_MainTex; 22 | }; 23 | 24 | void surf (Input IN, inout SurfaceOutput o) { 25 | half4 c = tex2D(_MainTex, IN.uv_MainTex) * IN.color * _Color; 26 | o.Albedo = c.rgb; 27 | o.Alpha = c.a; 28 | o.Emission = c * _Emission; 29 | } 30 | ENDCG 31 | } 32 | 33 | Fallback "Transparent/Cutout/VertexLit" 34 | } 35 | -------------------------------------------------------------------------------- /RatKing/Base/Shaders/VertexColoredCutout.shader: -------------------------------------------------------------------------------- 1 | Shader "A Rat King/VertexColoredCutout" { 2 | Properties { 3 | _Color ("Main Color", Color) = (1,1,1,1) 4 | _MainTex ("Base (RGB)", 2D) = "white" {} 5 | _Emission ("Emission Factor", float) = 0.2 // (0.5, 0.5, 0.5, 0.5) 6 | _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5 7 | } 8 | SubShader { 9 | Tags { "IgnoreProjector"="True" "RenderType"="TransparentCutout"} 10 | LOD 200 11 | 12 | CGPROGRAM 13 | #pragma surface surf Lambert alphatest:_Cutoff 14 | 15 | fixed4 _Color; 16 | sampler2D _MainTex; 17 | float _Emission; 18 | 19 | struct Input { 20 | float4 color : COLOR; 21 | float2 uv_MainTex; 22 | }; 23 | 24 | void surf (Input IN, inout SurfaceOutput o) { 25 | half4 c = tex2D(_MainTex, IN.uv_MainTex) * IN.color * _Color; 26 | o.Albedo = c.rgb; 27 | o.Alpha = c.a; 28 | o.Emission = c * _Emission; 29 | } 30 | ENDCG 31 | } 32 | 33 | Fallback "Transparent/Cutout/VertexLit" 34 | } 35 | -------------------------------------------------------------------------------- /RatKing/Base/Shaders/VertexColoredCutoutAlpha.shader: -------------------------------------------------------------------------------- 1 | Shader "A Rat King/VertexColoredCutoutAlpha" { 2 | Properties { 3 | _Color ("Main Color", Color) = (1,1,1,1) 4 | _MainTex ("Base (RGB)", 2D) = "white" {} 5 | _Emission ("Emission Factor", float) = 0.2 // (0.5, 0.5, 0.5, 0.5) 6 | _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5 7 | } 8 | SubShader { 9 | Tags { "Queue"="Transparent-1" "IgnoreProjector"="True" "RenderType"="Transparent"} // Cutout"} 10 | LOD 200 11 | 12 | CGPROGRAM 13 | #pragma surface surf Lambert alpha 14 | // alphatest:_Cutoff 15 | 16 | fixed4 _Color; 17 | sampler2D _MainTex; 18 | float _Emission; 19 | float _Cutoff; 20 | 21 | struct Input { 22 | float4 color : COLOR; 23 | float2 uv_MainTex; 24 | }; 25 | 26 | void surf (Input IN, inout SurfaceOutput o) { 27 | half4 c = tex2D(_MainTex, IN.uv_MainTex) * IN.color; 28 | o.Albedo = c.rgb * _Color.rgb; 29 | if (_Cutoff < 1.0 && c.a >= _Cutoff) 30 | o.Alpha = _Color.a; 31 | else 32 | o.Alpha = 0.0; 33 | o.Emission = c * _Emission; 34 | } 35 | ENDCG 36 | } 37 | 38 | Fallback "Transparent/Cutout/VertexLit" 39 | } 40 | -------------------------------------------------------------------------------- /RatKing/Base/Shaders/VertexLit.shader: -------------------------------------------------------------------------------- 1 | Shader "A Rat King/VertexLit Colored" { 2 | Properties{ 3 | _Color("Main Color", Color) = (1,1,1,1) 4 | //_SpecColor("Spec Color", Color) = (1,1,1,1) 5 | _Emission("Emissive Color", Color) = (0,0,0,0) 6 | //_Shininess("Shininess", Range(0.01, 1)) = 0.7 7 | _MainTex("Base (RGB)", 2D) = "white" {} 8 | } 9 | 10 | SubShader{ 11 | Tags{ "RenderType" = "Opaque" } 12 | LOD 100 13 | 14 | // Non-lightmapped 15 | Pass{ 16 | Tags{ "LightMode" = "Vertex" } 17 | 18 | Material{ 19 | Diffuse[_Color] 20 | Ambient[_Color] 21 | //Shininess[_Shininess] 22 | //Specular[_SpecColor] 23 | Emission[_Emission] 24 | } 25 | Lighting On 26 | SeparateSpecular On 27 | SetTexture[_MainTex]{ 28 | //constantColor(1,1,1,1) 29 | constantColor[_Color] 30 | Combine texture * primary DOUBLE, constant // UNITY_OPAQUE_ALPHA_FFP 31 | } 32 | } 33 | 34 | // Lightmapped, encoded as dLDR 35 | Pass{ 36 | Tags{ "LightMode" = "VertexLM" } 37 | 38 | BindChannels{ 39 | Bind "Vertex", vertex 40 | Bind "normal", normal 41 | Bind "texcoord1", texcoord0 // lightmap uses 2nd uv 42 | Bind "texcoord", texcoord1 // main uses 1st uv 43 | } 44 | 45 | SetTexture[unity_Lightmap]{ 46 | matrix[unity_LightmapMatrix] 47 | constantColor[_Color] 48 | combine texture * constant 49 | } 50 | SetTexture[_MainTex]{ 51 | //constantColor(1,1,1,1) 52 | constantColor[_Color] 53 | combine texture * previous DOUBLE, constant // UNITY_OPAQUE_ALPHA_FFP 54 | } 55 | } 56 | 57 | // Lightmapped, encoded as RGBM 58 | Pass{ 59 | Tags{ "LightMode" = "VertexLMRGBM" } 60 | 61 | BindChannels{ 62 | Bind "Vertex", vertex 63 | Bind "normal", normal 64 | Bind "texcoord1", texcoord0 // lightmap uses 2nd uv 65 | Bind "texcoord1", texcoord1 // unused 66 | Bind "texcoord", texcoord2 // main uses 1st uv 67 | } 68 | 69 | SetTexture[unity_Lightmap]{ 70 | matrix[unity_LightmapMatrix] 71 | combine texture * texture alpha DOUBLE 72 | } 73 | SetTexture[unity_Lightmap]{ 74 | constantColor[_Color] 75 | combine previous * constant 76 | } 77 | SetTexture[_MainTex]{ 78 | //constantColor(1,1,1,1) 79 | constantColor[_Color] 80 | combine texture * previous QUAD, constant // UNITY_OPAQUE_ALPHA_FFP 81 | } 82 | } 83 | 84 | // Pass to render object as a shadow caster 85 | Pass{ 86 | Name "ShadowCaster" 87 | Tags{ "LightMode" = "ShadowCaster" } 88 | 89 | CGPROGRAM 90 | #pragma vertex vert 91 | #pragma fragment frag 92 | #pragma multi_compile_shadowcaster 93 | #include "UnityCG.cginc" 94 | 95 | struct v2f { 96 | V2F_SHADOW_CASTER; 97 | }; 98 | 99 | v2f vert(appdata_base v) 100 | { 101 | v2f o; 102 | TRANSFER_SHADOW_CASTER_NORMALOFFSET(o) 103 | return o; 104 | } 105 | 106 | float4 frag(v2f i) : SV_Target 107 | { 108 | SHADOW_CASTER_FRAGMENT(i) 109 | } 110 | ENDCG 111 | 112 | } 113 | 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /RatKing/Base/_ThirdParty/Editor/NormalSolver.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * The following code was taken from: http://schemingdeveloper.com 3 | * 4 | * Visit our game studio website: http://stopthegnomes.com 5 | * 6 | * License: You may use this code however you see fit, as long as you include this notice 7 | * without any modifications. 8 | * 9 | * You may not publish a paid asset on Unity store if its main function is based on 10 | * the following code, but you may publish a paid asset that uses this code. 11 | * 12 | * If you intend to use this in a Unity store asset or a commercial project, it would 13 | * be appreciated, but not required, if you let me know with a link to the asset. If I 14 | * don't get back to you just go ahead and use it anyway! 15 | */ 16 | 17 | using System; 18 | using System.Collections.Generic; 19 | using UnityEngine; 20 | 21 | public static class NormalSolver 22 | { 23 | /// 24 | /// Recalculate the normals of a mesh based on an angle threshold. This takes 25 | /// into account distinct vertices that have the same position. 26 | /// 27 | /// 28 | /// 29 | /// The smoothing angle. Note that triangles that already share 30 | /// the same vertex will be smooth regardless of the angle! 31 | /// 32 | public static void RecalculateNormals(this Mesh mesh, float angle) { 33 | var cosineThreshold = Mathf.Cos(angle * Mathf.Deg2Rad); 34 | 35 | var vertices = mesh.vertices; 36 | var normals = new Vector3[vertices.Length]; 37 | 38 | // Holds the normal of each triangle in each sub mesh. 39 | var triNormals = new Vector3[mesh.subMeshCount][]; 40 | 41 | var dictionary = new Dictionary>(vertices.Length); 42 | 43 | for (var subMeshIndex = 0; subMeshIndex < mesh.subMeshCount; ++subMeshIndex) { 44 | 45 | var triangles = mesh.GetTriangles(subMeshIndex); 46 | 47 | triNormals[subMeshIndex] = new Vector3[triangles.Length / 3]; 48 | 49 | for (var i = 0; i < triangles.Length; i += 3) { 50 | int i1 = triangles[i]; 51 | int i2 = triangles[i + 1]; 52 | int i3 = triangles[i + 2]; 53 | 54 | // Calculate the normal of the triangle 55 | Vector3 p1 = vertices[i2] - vertices[i1]; 56 | Vector3 p2 = vertices[i3] - vertices[i1]; 57 | Vector3 normal = Vector3.Cross(p1, p2).normalized; 58 | int triIndex = i / 3; 59 | triNormals[subMeshIndex][triIndex] = normal; 60 | 61 | List entry; 62 | VertexKey key; 63 | 64 | if (!dictionary.TryGetValue(key = new VertexKey(vertices[i1]), out entry)) { 65 | entry = new List(4); 66 | dictionary.Add(key, entry); 67 | } 68 | entry.Add(new VertexEntry(subMeshIndex, triIndex, i1)); 69 | 70 | if (!dictionary.TryGetValue(key = new VertexKey(vertices[i2]), out entry)) { 71 | entry = new List(); 72 | dictionary.Add(key, entry); 73 | } 74 | entry.Add(new VertexEntry(subMeshIndex, triIndex, i2)); 75 | 76 | if (!dictionary.TryGetValue(key = new VertexKey(vertices[i3]), out entry)) { 77 | entry = new List(); 78 | dictionary.Add(key, entry); 79 | } 80 | entry.Add(new VertexEntry(subMeshIndex, triIndex, i3)); 81 | } 82 | } 83 | 84 | // Each entry in the dictionary represents a unique vertex position. 85 | 86 | foreach (var vertList in dictionary.Values) { 87 | for (var i = 0; i < vertList.Count; ++i) { 88 | 89 | var sum = new Vector3(); 90 | var lhsEntry = vertList[i]; 91 | 92 | for (var j = 0; j < vertList.Count; ++j) { 93 | var rhsEntry = vertList[j]; 94 | 95 | if (lhsEntry.VertexIndex == rhsEntry.VertexIndex) { 96 | sum += triNormals[rhsEntry.MeshIndex][rhsEntry.TriangleIndex]; 97 | } else { 98 | // The dot product is the cosine of the angle between the two triangles. 99 | // A larger cosine means a smaller angle. 100 | var dot = Vector3.Dot( 101 | triNormals[lhsEntry.MeshIndex][lhsEntry.TriangleIndex], 102 | triNormals[rhsEntry.MeshIndex][rhsEntry.TriangleIndex]); 103 | if (dot >= cosineThreshold) { 104 | sum += triNormals[rhsEntry.MeshIndex][rhsEntry.TriangleIndex]; 105 | } 106 | } 107 | } 108 | 109 | normals[lhsEntry.VertexIndex] = sum.normalized; 110 | } 111 | } 112 | 113 | mesh.normals = normals; 114 | } 115 | 116 | private struct VertexKey 117 | { 118 | private readonly long _x; 119 | private readonly long _y; 120 | private readonly long _z; 121 | 122 | // Change this if you require a different precision. 123 | private const int Tolerance = 100000; 124 | 125 | // Magic FNV values. Do not change these. 126 | private const long FNV32Init = 0x811c9dc5; 127 | private const long FNV32Prime = 0x01000193; 128 | 129 | public VertexKey(Vector3 position) { 130 | _x = (long)(Mathf.Round(position.x * Tolerance)); 131 | _y = (long)(Mathf.Round(position.y * Tolerance)); 132 | _z = (long)(Mathf.Round(position.z * Tolerance)); 133 | } 134 | 135 | public override bool Equals(object obj) { 136 | var key = (VertexKey)obj; 137 | return _x == key._x && _y == key._y && _z == key._z; 138 | } 139 | 140 | public override int GetHashCode() { 141 | long rv = FNV32Init; 142 | rv ^= _x; 143 | rv *= FNV32Prime; 144 | rv ^= _y; 145 | rv *= FNV32Prime; 146 | rv ^= _z; 147 | rv *= FNV32Prime; 148 | 149 | return rv.GetHashCode(); 150 | } 151 | } 152 | 153 | private struct VertexEntry { 154 | public int MeshIndex; 155 | public int TriangleIndex; 156 | public int VertexIndex; 157 | 158 | public VertexEntry(int meshIndex, int triIndex, int vertIndex) { 159 | MeshIndex = meshIndex; 160 | TriangleIndex = triIndex; 161 | VertexIndex = vertIndex; 162 | } 163 | } 164 | } -------------------------------------------------------------------------------- /RatKing/Base/_ThirdParty/Editor/UnityHook.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using System.Reflection; 3 | 4 | // source: https://twitter.com/PsyKola/status/874623012141768704 5 | 6 | [InitializeOnLoad] 7 | public class UnityHook { 8 | static UnityHook() { 9 | typeof(EditorGUI).GetField("kFloatFieldFormatString", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, "0.#######"); 10 | typeof(EditorGUI).GetField("kDoubleFieldFormatString", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, "0.##############"); 11 | } 12 | } -------------------------------------------------------------------------------- /RatKing/Base/_ThirdParty/SimpleJSON/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012-2017 Markus Göbel (Bunny83) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | --------------------------------------------------------------------------------