diff --git a/AutoSceneChanger.cs b/AutoSceneChanger.cs
new file mode 100644
index 0000000..c7b60ea
--- /dev/null
+++ b/AutoSceneChanger.cs
@@ -0,0 +1,13 @@
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+namespace NEG.Utils
+{
+ public class AutoSceneChanger : MonoBehaviour
+ {
+#if !UNITY_EDITOR
+ private void Start() => SceneManager.LoadScene(1);
+#endif
+ }
+}
+
diff --git a/AutoSceneChanger.cs.meta b/AutoSceneChanger.cs.meta
new file mode 100644
index 0000000..c7db448
--- /dev/null
+++ b/AutoSceneChanger.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: eac2f9a681087504998bbeb40cd8516a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Collections.meta b/Collections.meta
new file mode 100644
index 0000000..d087cf9
--- /dev/null
+++ b/Collections.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 9b25b74f42726e94585fe6ae4b9dd947
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Collections/DictionaryExtensions.cs b/Collections/DictionaryExtensions.cs
new file mode 100644
index 0000000..aae8985
--- /dev/null
+++ b/Collections/DictionaryExtensions.cs
@@ -0,0 +1,41 @@
+using System.Collections.Generic;
+
+namespace NEG.Utils.Collections
+{
+ public static class DictionaryExtensions
+ {
+ ///
+ /// Adds given value to a dictionary if there was no element at given , replaces element with otherwise.
+ ///
+ /// true if element was added, false if it was replaced
+ public static bool AddOrUpdate(this Dictionary dict, K key, V value)
+ {
+ if (dict.ContainsKey(key))
+ {
+ dict[key] = value;
+ return false;
+ }
+ else
+ {
+ dict.Add(key, value);
+ return true;
+ }
+ }
+
+
+ ///
+ /// Gets a value from the dictionary under a specified key or adds it if did not exist and returns .
+ ///
+ /// value under a given if it exists, otherwise
+ public static V GetOrSetToDefault(this Dictionary dict, K key, V defaultValue)
+ {
+ if (dict.TryGetValue(key, out V value))
+ {
+ return value;
+ }
+ dict.Add(key, defaultValue);
+
+ return defaultValue;
+ }
+ }
+}
diff --git a/Collections/DictionaryExtensions.cs.meta b/Collections/DictionaryExtensions.cs.meta
new file mode 100644
index 0000000..d6cb872
--- /dev/null
+++ b/Collections/DictionaryExtensions.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a2c99d7a9a2f8184f8b8e94c01723ec6
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/BuildingUtils.cs b/Editor/BuildingUtils.cs
new file mode 100644
index 0000000..7dca265
--- /dev/null
+++ b/Editor/BuildingUtils.cs
@@ -0,0 +1,84 @@
+using System.Diagnostics;
+using UnityEngine;
+using UnityEditor;
+using Debug = UnityEngine.Debug;
+
+public static class BuildingUtils
+{
+ [MenuItem("Tools/Build/Steam/Release")]
+ public static void SteamRelease()
+ {
+ IncreaseBuildNumber();
+ BuildRelease();
+ UploadSteam();
+ }
+
+ [MenuItem("Tools/Build/Steam/Development")]
+ public static void SteamDevelopment()
+ {
+ IncreaseBuildNumber();
+ BuildDevelopment();
+ UploadSteam();
+ }
+
+
+ [MenuItem("Tools/Build/All Release")]
+ public static void BuildRelease()
+ {
+ BuildWindowsRelease();
+ }
+
+ [MenuItem("Tools/Build/All Development")]
+ public static void BuildDevelopment()
+ {
+ BuildWindowsDevelopment();
+ }
+
+ [MenuItem("Tools/Build/Platform/Windows/x64-Development")]
+ public static void BuildWindowsDevelopment() => BuildWindows(false);
+
+ [MenuItem("Tools/Build/Platform/Windows/x64-Release")]
+ public static void BuildWindowsRelease() => BuildWindows(true);
+
+
+ private static void BuildWindows(bool release)
+ {
+ var buildPlayerOptions = new BuildPlayerOptions { scenes = new string[EditorBuildSettings.scenes.Length] };
+ for (int i = 0; i < EditorBuildSettings.scenes.Length; i++)
+ {
+ buildPlayerOptions.scenes[i] = EditorBuildSettings.scenes[i].path;
+ }
+
+ buildPlayerOptions.target = BuildTarget.StandaloneWindows64;
+ buildPlayerOptions.options = release ? BuildOptions.None : BuildOptions.Development;
+ buildPlayerOptions.locationPathName = Application.dataPath +
+ $"/../../{Application.productName}-Steam/ContentBuilder/content/windows/{Application.productName}.exe";
+ BuildPipeline.BuildPlayer(buildPlayerOptions);
+ }
+
+ private static void IncreaseBuildNumber()
+ {
+ string[] versionParts = PlayerSettings.bundleVersion.Split('.');
+ if (versionParts.Length != 3 || !int.TryParse(versionParts[2], out int version)) {
+ Debug.LogError("IncreaseBuildNumber failed to update version " + PlayerSettings.bundleVersion);
+ return;
+ }
+ versionParts[2] = (version + 1).ToString();
+ PlayerSettings.bundleVersion = string.Join(".", versionParts);
+ }
+
+ private static void UploadSteam()
+ {
+ string command = $"cd {Application.dataPath}/../../{Application.productName}-Steam/ContentBuilder && run_build.bat";
+
+ var processInfo = new ProcessStartInfo("cmd.exe", $"/c {command}")
+ {
+ CreateNoWindow = true,
+ UseShellExecute = false
+ };
+ var process = Process.Start(processInfo);
+ process.WaitForExit();
+ Debug.Log(process.ExitCode);
+ process.Close();
+ }
+}
\ No newline at end of file
diff --git a/Editor/BuildingUtils.cs.meta b/Editor/BuildingUtils.cs.meta
new file mode 100644
index 0000000..5458af4
--- /dev/null
+++ b/Editor/BuildingUtils.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 1e90ce49e16b4cecb77bf258651f6209
+timeCreated: 1669642124
\ No newline at end of file
diff --git a/Editor/ComponentsAdditionalItems.meta b/Editor/ComponentsAdditionalItems.meta
new file mode 100644
index 0000000..3129799
--- /dev/null
+++ b/Editor/ComponentsAdditionalItems.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d683d64cc04efcf479b41c84b51cf7fe
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/ComponentsAdditionalItems/RectTransformSetBasedOnImage.cs b/Editor/ComponentsAdditionalItems/RectTransformSetBasedOnImage.cs
new file mode 100644
index 0000000..f1f1691
--- /dev/null
+++ b/Editor/ComponentsAdditionalItems/RectTransformSetBasedOnImage.cs
@@ -0,0 +1,22 @@
+using UnityEditor;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace NEG.Utils.Editor.ComponentsAdditionalItems
+{
+ public static class RectTransformSetBasedOnImage
+ {
+ [MenuItem("CONTEXT/RectTransform/Set as inside of Image", false, 2000)]
+ public static void SetFillBasedOnImage(MenuCommand command)
+ {
+ var transform = (RectTransform)command.context;
+ if (!transform.TryGetComponent(out Image image))
+ return;
+
+ transform.anchorMin = Vector2.zero;
+ transform.anchorMax = Vector2.one;
+ transform.offsetMin = new Vector2(-image.sprite.border.x, -image.sprite.border.y);
+ transform.offsetMax = new Vector2(image.sprite.border.z, image.sprite.border.w);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/ComponentsAdditionalItems/RectTransformSetBasedOnImage.cs.meta b/Editor/ComponentsAdditionalItems/RectTransformSetBasedOnImage.cs.meta
new file mode 100644
index 0000000..b1a832b
--- /dev/null
+++ b/Editor/ComponentsAdditionalItems/RectTransformSetBasedOnImage.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 614a58a9665e7cf4182834f1fb3c0096
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/EditorMultipleInstances.meta b/Editor/EditorMultipleInstances.meta
similarity index 100%
rename from EditorMultipleInstances.meta
rename to Editor/EditorMultipleInstances.meta
diff --git a/EditorMultipleInstances/Editor.meta b/Editor/EditorMultipleInstances/Editor.meta
similarity index 100%
rename from EditorMultipleInstances/Editor.meta
rename to Editor/EditorMultipleInstances/Editor.meta
diff --git a/EditorMultipleInstances/Editor/EditorInstanceCreator.cs b/Editor/EditorMultipleInstances/Editor/EditorInstanceCreator.cs
similarity index 100%
rename from EditorMultipleInstances/Editor/EditorInstanceCreator.cs
rename to Editor/EditorMultipleInstances/Editor/EditorInstanceCreator.cs
diff --git a/EditorMultipleInstances/Editor/EditorInstanceCreator.cs.meta b/Editor/EditorMultipleInstances/Editor/EditorInstanceCreator.cs.meta
similarity index 100%
rename from EditorMultipleInstances/Editor/EditorInstanceCreator.cs.meta
rename to Editor/EditorMultipleInstances/Editor/EditorInstanceCreator.cs.meta
diff --git a/EditorMultipleInstances/LICENSE b/Editor/EditorMultipleInstances/LICENSE
similarity index 100%
rename from EditorMultipleInstances/LICENSE
rename to Editor/EditorMultipleInstances/LICENSE
diff --git a/EditorMultipleInstances/LICENSE.meta b/Editor/EditorMultipleInstances/LICENSE.meta
similarity index 100%
rename from EditorMultipleInstances/LICENSE.meta
rename to Editor/EditorMultipleInstances/LICENSE.meta
diff --git a/Editor/GUIDToAssetPath.cs b/Editor/GUIDToAssetPath.cs
new file mode 100644
index 0000000..f4e5aae
--- /dev/null
+++ b/Editor/GUIDToAssetPath.cs
@@ -0,0 +1,41 @@
+using UnityEditor;
+using UnityEngine;
+
+public class GUIDToAssetPath : EditorWindow
+{
+ string guid = "";
+ string path = "";
+ [MenuItem("Tools/GUIDToAssetPath")]
+ static void CreateWindow()
+ {
+ GUIDToAssetPath window = (GUIDToAssetPath)EditorWindow.GetWindowWithRect(typeof(GUIDToAssetPath), new Rect(0, 0, 400, 120));
+ }
+
+ void OnGUI()
+ {
+ GUILayout.Label("Enter guid");
+ guid = GUILayout.TextField(guid);
+ GUILayout.BeginHorizontal();
+ GUILayout.FlexibleSpace();
+ if (GUILayout.Button("Get Asset Path",GUILayout.Width(120)))
+ path = GetAssetPath(guid);
+ GUILayout.FlexibleSpace();
+ GUILayout.EndHorizontal();
+ GUILayout.BeginHorizontal();
+ GUILayout.FlexibleSpace();
+ if (GUILayout.Button("Abort", GUILayout.Width(120)))
+ Close();
+ GUILayout.FlexibleSpace();
+ GUILayout.EndHorizontal();
+ GUILayout.Label(path);
+ }
+ static string GetAssetPath(string guid)
+ {
+ guid = guid.Replace("-", "");
+
+ string p = AssetDatabase.GUIDToAssetPath(guid);
+ Debug.Log(p);
+ if (p.Length == 0) p = "not found";
+ return p;
+ }
+}
\ No newline at end of file
diff --git a/Editor/GUIDToAssetPath.cs.meta b/Editor/GUIDToAssetPath.cs.meta
new file mode 100644
index 0000000..693beae
--- /dev/null
+++ b/Editor/GUIDToAssetPath.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: ee5c0a00075140f28ac5e6ff46e9a6b3
+timeCreated: 1669777021
\ No newline at end of file
diff --git a/RequireInterface/Editor/RequireInterfaceDrawer.cs b/Editor/RequireInterfaceDrawer.cs
similarity index 100%
rename from RequireInterface/Editor/RequireInterfaceDrawer.cs
rename to Editor/RequireInterfaceDrawer.cs
diff --git a/RequireInterface/Editor/RequireInterfaceDrawer.cs.meta b/Editor/RequireInterfaceDrawer.cs.meta
similarity index 100%
rename from RequireInterface/Editor/RequireInterfaceDrawer.cs.meta
rename to Editor/RequireInterfaceDrawer.cs.meta
diff --git a/Editor/ToolsWindowBase.cs b/Editor/ToolsWindowBase.cs
new file mode 100644
index 0000000..d200732
--- /dev/null
+++ b/Editor/ToolsWindowBase.cs
@@ -0,0 +1,108 @@
+using System;
+using System.IO;
+using UnityEditor;
+using UnityEditor.SceneManagement;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+namespace NegUtils.Editor
+{
+ [InitializeOnLoad]
+ public class ToolsWindowBase : EditorWindow
+ {
+ static ToolsWindowBase()
+ {
+ EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
+ }
+
+ [MenuItem("Tools/Show Tools Window")]
+ private static void ShowWindow()
+ {
+ var window = GetWindow();
+ window.Show();
+ }
+
+ protected virtual void OnGUI()
+ {
+ if (GUILayout.Button("Select Scene"))
+ ShowScenesList(GUILayoutUtility.GetLastRect());
+
+ bool startFromSceneIndex0 = EditorPrefs.GetBool("StartFromSceneIndex0");
+ bool newVal = GUILayout.Toggle(startFromSceneIndex0, "Start from scene with index 0 on start");
+ if (newVal != startFromSceneIndex0)
+ {
+ EditorPrefs.SetBool("StartFromSceneIndex0", newVal);
+ }
+
+ if (startFromSceneIndex0)
+ {
+ bool goToCurrentScene = EditorPrefs.GetBool("GoToCurrentSceneAfterPlay");
+ newVal = GUILayout.Toggle(goToCurrentScene, "Go to current scene after play");
+ if (newVal != goToCurrentScene)
+ {
+ EditorPrefs.SetBool("GoToCurrentSceneAfterPlay", newVal);
+ }
+ }
+ }
+
+ private static void ShowScenesList(Rect position)
+ {
+ var menu = new GenericMenu();
+
+ string path = Application.dataPath + "/Scenes/Production";
+ string[] fileInfo = Directory.GetFiles(path, "*.unity");
+
+ foreach (string item in fileInfo)
+ {
+ string s = item;
+ menu.AddItem(new GUIContent(s.Remove(0, path.Length + 1).Remove(s.Length - path.Length - 7 ,6)), false, () => {
+ LoadScene(s);
+ });
+ menu.AddSeparator("");
+ }
+ menu.DropDown(position);
+ }
+
+ private static void LoadScene(string path)
+ {
+ EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
+ EditorSceneManager.OpenScene(path, OpenSceneMode.Single);
+ }
+
+ private static void OnPlayModeStateChanged(PlayModeStateChange state)
+ {
+ switch(state)
+ {
+ case PlayModeStateChange.ExitingEditMode:
+ {
+ if(!EditorPrefs.GetBool("StartFromSceneIndex0"))
+ return;
+ EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
+ EditorPrefs.SetString("LastOpenedScenePath", EditorSceneManager.GetSceneManagerSetup()[0].path);
+ EditorSceneManager.OpenScene(EditorBuildSettings.scenes[0].path);
+ }
+ break;
+ case PlayModeStateChange.EnteredPlayMode:
+ {
+ if(!EditorPrefs.GetBool("StartFromSceneIndex0"))
+ return;
+
+ if (EditorPrefs.GetBool("GoToCurrentSceneAfterPlay"))
+ EditorSceneManager.LoadSceneInPlayMode(EditorPrefs.GetString("LastOpenedScenePath"),
+ new LoadSceneParameters(LoadSceneMode.Single));
+ else
+ SceneManager.LoadScene(1);
+ }
+ break;
+ case PlayModeStateChange.EnteredEditMode:
+ {
+ if(!EditorPrefs.GetBool("StartFromSceneIndex0"))
+ return;
+ EditorSceneManager.OpenScene(EditorPrefs.GetString("LastOpenedScenePath"));
+ }
+ break;
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/ToolsWindowBase.cs.meta b/Editor/ToolsWindowBase.cs.meta
new file mode 100644
index 0000000..407b91d
--- /dev/null
+++ b/Editor/ToolsWindowBase.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 76faf7fadf7c40d88dec1a8ee4da5cb6
+timeCreated: 1671500708
\ No newline at end of file
diff --git a/NEG.Utils.asmdef b/NEG.Utils.asmdef
new file mode 100644
index 0000000..1f68761
--- /dev/null
+++ b/NEG.Utils.asmdef
@@ -0,0 +1,16 @@
+{
+ "name": "NEG.Utils",
+ "rootNamespace": "",
+ "references": [
+ "GUID:6055be8ebefd69e48b49212b09b47b2f"
+ ],
+ "includePlatforms": [],
+ "excludePlatforms": [],
+ "allowUnsafeCode": false,
+ "overrideReferences": false,
+ "precompiledReferences": [],
+ "autoReferenced": true,
+ "defineConstraints": [],
+ "versionDefines": [],
+ "noEngineReferences": false
+}
\ No newline at end of file
diff --git a/NEG.Utils.asmdef.meta b/NEG.Utils.asmdef.meta
new file mode 100644
index 0000000..cfd68b0
--- /dev/null
+++ b/NEG.Utils.asmdef.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 3c4294719a93e3c4e831a9ff0c261e8a
+AssemblyDefinitionImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/RequireInterface/RequireInterfaceAttribute.cs b/RequireInterfaceAttribute.cs
similarity index 100%
rename from RequireInterface/RequireInterfaceAttribute.cs
rename to RequireInterfaceAttribute.cs
diff --git a/RequireInterface/RequireInterfaceAttribute.cs.meta b/RequireInterfaceAttribute.cs.meta
similarity index 100%
rename from RequireInterface/RequireInterfaceAttribute.cs.meta
rename to RequireInterfaceAttribute.cs.meta
diff --git a/Timing.meta b/Timing.meta
new file mode 100644
index 0000000..aa993a9
--- /dev/null
+++ b/Timing.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d3f27225e5dd00546b927b1a8bd253ee
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Timing/AutoTimeMachine.cs b/Timing/AutoTimeMachine.cs
new file mode 100644
index 0000000..6bcf59f
--- /dev/null
+++ b/Timing/AutoTimeMachine.cs
@@ -0,0 +1,33 @@
+using System;
+
+namespace NEG.Utils.Timing
+{
+ public class AutoTimeMachine
+ {
+ public double Interval { get; set; }
+ public Action Action { get; set; }
+
+ private readonly TimeMachine machine;
+
+ public AutoTimeMachine(Action action, double interval)
+ {
+ Action = action;
+ Interval = interval;
+ machine = new TimeMachine();
+ }
+
+ ///
+ /// Forwards the time by given amount, triggers assigned action relevant amount of times
+ ///
+ /// Amount of time to forward by
+ public void Forward(double time)
+ {
+ machine.Accumulate(time);
+ int rolls = machine.RetrieveAll(Interval);
+ for (int i = 0; i < rolls; i++)
+ {
+ Action();
+ }
+ }
+ }
+}
diff --git a/Timing/AutoTimeMachine.cs.meta b/Timing/AutoTimeMachine.cs.meta
new file mode 100644
index 0000000..3c13533
--- /dev/null
+++ b/Timing/AutoTimeMachine.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: cf2d68c5a76882f4ead172644f643fd5
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Timing/TimeMachine.cs b/Timing/TimeMachine.cs
new file mode 100644
index 0000000..02cc9bf
--- /dev/null
+++ b/Timing/TimeMachine.cs
@@ -0,0 +1,70 @@
+using System;
+
+namespace NEG.Utils.Timing
+{
+ public class TimeMachine
+ {
+ private double time;
+
+ public TimeMachine()
+ {
+ time = 0;
+ }
+
+ ///
+ /// Adds time into the TimeMachine
+ ///
+ /// Amount of time to be added
+ public void Accumulate(double time)
+ {
+ this.time += time;
+ }
+
+ ///
+ /// Retrieves given amount of time from the TimeMachine
+ ///
+ ///
+ /// Amount of time retrievend
+ public double Retrieve(double maxTime)
+ {
+ if(!Double.IsFinite(maxTime))
+ {
+ double timeRetrieved = time;
+ time = 0;
+ return timeRetrieved;
+ }
+ double timeLeft = time - maxTime;
+ time = Math.Max(timeLeft, 0);
+ return Math.Min(maxTime + timeLeft, maxTime);
+ }
+
+ ///
+ /// Attempts to retrieves given amount of time from the TimeMachine
+ /// If there is enough accumulated in this machine subtructs that amount and returns true, otherwise returns false
+ ///
+ ///
+ public bool TryRetrieve(double time)
+ {
+ if (this.time >= time)
+ {
+ this.time -= time;
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// Result is equivalent to calling as many times as possible, but is faster for larger values
+ ///
+ /// Single unit of warp time, must be positive/param>
+ /// Maximum amount of warps, must be positive
+ /// Amount of warps
+ public int RetrieveAll(double interval, int limit = int.MaxValue)
+ {
+ int result = Mathf.FloorToInt(time / interval);
+ result = Math.Clamp(result, 0, limit);
+ time -= result * interval;
+ return result;
+ }
+ }
+}
diff --git a/Timing/TimeMachine.cs.meta b/Timing/TimeMachine.cs.meta
new file mode 100644
index 0000000..5b85c31
--- /dev/null
+++ b/Timing/TimeMachine.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2f4db23cbb7389a41bf48808a3d5696f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: