Compare commits

..

76 Commits

Author SHA1 Message Date
d14e2ca055 Merge pull request 'add serializable guid' (#5) from serializable-guid into main
Reviewed-on: https://internal.negames.live/gitea/negames/Neg_Utils/pulls/5
2025-03-20 16:39:35 +01:00
d0d7134b68 delete unused usings 2025-03-20 16:39:15 +01:00
987c7b1be2 add serializable guid 2025-03-20 16:35:34 +01:00
f7a7427610 clean up 2025-03-03 19:17:05 +01:00
b3c1d2fd14 revert stupid change 2024-03-05 23:13:30 +01:00
5dd6a3b0de null check 2024-03-04 11:46:39 +01:00
e6af704f30 more cleanup 2024-03-03 15:39:03 +01:00
85dee79cc8 Cleanup 2024-03-03 15:38:40 +01:00
20e281f9dd Fix for error on close 2024-03-02 23:58:55 +01:00
f8d8b9fd12 fix build error 2024-03-02 21:45:06 +01:00
a9d35a5447 Read only attribute - build fix 2024-03-02 11:47:21 +01:00
bcb239587b Update path 2024-02-14 18:40:28 +01:00
e819020474 Code cleanup 2024-02-12 21:26:24 +01:00
ae89122e42 Merge pull request 'ui-system-fix' (#4) from ui-system-fix into main
Reviewed-on: http://newexceptiongames.dynamic-dns.net:3000/NewExceptionGames/Neg_Utils/pulls/4
2024-02-12 18:06:53 +00:00
46d192ea27 Merge pull request 'Update tools window' (#3) from ToolsWindowUpdate into main
Reviewed-on: http://newexceptiongames.dynamic-dns.net:3000/NewExceptionGames/Neg_Utils/pulls/3
2024-02-12 18:04:37 +00:00
1818d99caf null fix 2024-02-06 18:07:28 +01:00
8d5b903b1a working on city 2023-12-16 22:22:25 +01:00
d9fc097783 login screen done 2023-11-21 16:34:45 +01:00
da89d7a7fc Category item view button list 2023-11-09 12:04:53 +01:00
cd8c819585 working on dialogs system 2023-10-25 20:52:17 +02:00
566430650f moa fixes 2023-10-10 20:25:34 +02:00
164fd2f794 ui update 2023-10-03 15:55:02 +02:00
0148de0db7 Moa nullchecks 2023-10-02 21:52:09 +02:00
610179c21d Add linux builds 2023-09-19 21:41:39 +02:00
ebfeb14515 Add new auto window open 2023-09-19 12:42:51 +02:00
1abfcc0042 null check 2023-09-15 16:53:41 +02:00
6b01de0095 fix 2023-09-15 14:03:55 +02:00
8835f620e9 null check 2023-09-15 14:01:24 +02:00
ab5a33742a Mono ui input manager 2023-09-14 19:24:38 +02:00
b7dfa7bffa Apply pr changes 2023-09-08 21:57:20 +02:00
b7aa670e70 Merge branch 'VectorSwizzleUpdate' 2023-09-02 14:34:44 +02:00
d06350da06 Merge pull request 'better-ui-manager' (#2) from better-ui-manager into main
Reviewed-on: http://newexceptiongames.dynamic-dns.net:3000/NewExceptionGames/Neg_Utils/pulls/2
2023-09-02 12:34:16 +00:00
15ea7f7328 event rename 2023-09-02 14:34:01 +02:00
aafd5dbc75 Apply pr comments 2023-09-02 01:12:42 +02:00
fb90337a3f final update befor pr 2023-09-01 21:42:37 +02:00
0007e30aca switch to swizzle form Michal 2023-09-01 20:22:35 +02:00
33d0a9078f Fixed for avoiding scripts execution order 2023-08-26 01:03:34 +02:00
63d3d908e8 Naming update 2023-08-20 14:07:45 +02:00
a83c4cfb3b Cleanup 2023-08-17 10:47:21 +02:00
85daf89041 Merge branch 'better-ui-manager' of newexceptiongames.dynamic-dns.net:NewExceptionGames/Neg_Utils into better-ui-manager 2023-08-12 11:15:06 +02:00
9c91269a9e New componnets 2023-08-12 11:14:57 +02:00
f3f386d4c0 Update tools window 2023-08-11 19:44:44 +02:00
9e60fdf32d fix popup show 2023-07-31 11:05:57 +02:00
17f48f7eb2 update 2023-06-30 13:41:43 +02:00
34807988d8 add define 2023-06-12 19:33:57 +02:00
f837aec845 add features 2023-06-09 01:01:46 +02:00
611f417d5e Merge remote-tracking branch 'origin/main' into better-ui-manager 2023-06-05 20:56:41 +02:00
1f2c251d0c popups fix 2023-06-01 00:25:38 +02:00
8fe292818e Add custom editor 2023-05-27 21:39:28 +02:00
c0dd3dfdc5 add define 2023-05-22 20:33:17 +02:00
1e66136bfc Cleanup 2023-05-20 20:03:25 +02:00
e30470d27a update window 2023-05-19 22:52:09 +02:00
4239816cd8 Merge remote-tracking branch 'origin/main' into better-ui-manager 2023-05-19 21:05:52 +02:00
7bf4512c43 Working on selection 2023-05-19 20:58:53 +02:00
7aecbeb240 ui system improved 2023-05-14 01:04:34 +02:00
42dbfc8827 popups + android build utils 2023-05-14 01:00:03 +02:00
359b616be9 Vector int add to swizzle
Upgrade Building utils
2023-04-12 00:40:44 +02:00
ad760f57b0 Vectror swizzle, carousel list update 2023-04-08 11:47:55 +02:00
482e70b21a add asmdef for uinty ui editor 2023-03-20 19:57:08 +01:00
989a21a2c5 Update ui manager 2023-02-23 20:32:21 +01:00
c0923cc884 Merge branch 'main' into MultiSelectChip 2023-02-16 22:44:41 +01:00
eba429022b fix compile error
(cherry picked from commit 055df4e42719fa348140575f79fa9415716ce681)
2023-02-06 20:00:14 +01:00
c106c41ca1 Merge branch 'neg-ui' into 'main'
Neg ui

See merge request negames/NegUtils!5
2023-02-06 18:20:28 +00:00
2fe84c5c0b pr coments implementation 2023-02-06 19:20:01 +01:00
055df4e427 fix compile error 2023-01-09 17:08:54 +01:00
32b208d1b6 Merge remote-tracking branch 'origin/main' into MultiSelectChip 2023-01-09 17:04:52 +01:00
58ef8a0268 Merge branch 'time-machines' into 'main'
time machines

See merge request negames/NegUtils!1
2023-01-05 12:07:56 +00:00
f728f30920 Merge branch 'dictionary-extensions' into 'main'
dictionary extensions

See merge request negames/NegUtils!2
2023-01-05 12:06:33 +00:00
57bc81065e Apply 1 suggestion(s) to 1 file(s) 2023-01-03 12:09:37 +00:00
LubieKakao1212
df046e3303 Fixed AutoTimeMachine 2022-12-19 19:35:14 +01:00
LubieKakao1212
927d835d2e Improved naming and documentation 2022-12-19 15:23:50 +01:00
LubieKakao1212
90caf11c6c Applied suggestions 2022-12-19 13:54:07 +00:00
LubieKakao1212
c60b15dc51 time machines 2022-12-16 21:30:23 +01:00
LubieKakao1212
11cbaac33d dictionary extensions 2022-12-16 21:29:30 +01:00
9647327168 multi chip update 2022-12-12 19:22:13 +01:00
6c19b566d0 test of assembly definition 2022-11-26 19:24:00 +01:00
163 changed files with 10321 additions and 1062 deletions

View File

@ -1,5 +1,4 @@
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement;
namespace NEG.Utils namespace NEG.Utils
{ {
@ -9,5 +8,4 @@ namespace NEG.Utils
private void Start() => SceneManager.LoadScene(1); private void Start() => SceneManager.LoadScene(1);
#endif #endif
} }
} }

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: ae6126b91ed6cf14d98898d4e2cbce75 guid: 9b25b74f42726e94585fe6ae4b9dd947
folderAsset: yes folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} externalObjects: {}

View File

@ -0,0 +1,38 @@
using System.Collections.Generic;
namespace NEG.Utils.Collections
{
public static class DictionaryExtensions
{
/// <summary>
/// Adds given value to a dictionary if there was no element at given <paramref name="key" />, replaces element with
/// <paramref name="value"> otherwise.
/// </summary>
/// <returns>true if element was added, false if it was replaced</returns>
public static bool AddOrUpdate<K, V>(this Dictionary<K, V> dict, K key, V value)
{
if (dict.ContainsKey(key))
{
dict[key] = value;
return false;
}
dict.Add(key, value);
return true;
}
/// <summary>
/// Gets a value from the dictionary under a specified key or adds it if did not exist and returns
/// <paramref name="defaultValue" />.
/// </summary>
/// <returns>value under a given <paramref name="key" /> if it exists, <paramref name="defaultValue" /> otherwise</returns>
public static V GetOrSetToDefault<K, V>(this Dictionary<K, V> dict, K key, V defaultValue)
{
if (dict.TryGetValue(key, out var value)) return value;
dict.Add(key, defaultValue);
return defaultValue;
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: b4d51a82fa182b64db93b7057762f8a2 guid: a2c99d7a9a2f8184f8b8e94c01723ec6
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -6,40 +6,42 @@ namespace NEG.Utils
{ {
public static class CoroutineUtils public static class CoroutineUtils
{ {
private static readonly WaitForEndOfFrame WaitForEndOfFrame = new WaitForEndOfFrame(); private static readonly WaitForEndOfFrame WaitForEndOfFrame = new();
public static IEnumerator WaitForFrames(int count) public static IEnumerator WaitForFrames(int count)
{ {
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++) yield return null;
{
yield return null;
}
} }
public static void ActionAfterFrames(this MonoBehaviour mono, int count, Action action) public static void ActionAfterFrames(this MonoBehaviour mono, int count, Action action) =>
{
mono.StartCoroutine(ActionAfterFrames(count, action)); mono.StartCoroutine(ActionAfterFrames(count, action));
}
public static IEnumerator ActionAfterFrames(int count, Action action) public static IEnumerator ActionAfterFrames(int count, Action action)
{ {
yield return WaitForFrames(count); yield return WaitForFrames(count);
action?.Invoke(); action?.Invoke();
} }
public static void ActionAfterEndOfFrame(this MonoBehaviour mono, Action action) =>
mono.StartCoroutine(ActionAtNextFrame(action));
public static IEnumerator ActionAfterEndOfFrame(Action action) public static IEnumerator ActionAfterEndOfFrame(Action action)
{ {
yield return WaitForEndOfFrame; yield return WaitForEndOfFrame;
action?.Invoke(); action?.Invoke();
} }
public static void ActionAtNextFrame(this MonoBehaviour mono, Action action) => mono.StartCoroutine(ActionAtNextFrame(action));
public static void ActionAtNextFrame(this MonoBehaviour mono, Action action) =>
mono.StartCoroutine(ActionAtNextFrame(action));
public static IEnumerator ActionAtNextFrame(Action action) public static IEnumerator ActionAtNextFrame(Action action)
{ {
yield return null; yield return null;
action?.Invoke(); action?.Invoke();
} }
public static void ActionAfterTime(this MonoBehaviour mono, float time, Action action) => mono.StartCoroutine(ActionAfterTime(time, action)); public static void ActionAfterTime(this MonoBehaviour mono, float time, Action action) =>
mono.StartCoroutine(ActionAfterTime(time, action));
public static IEnumerator ActionAfterTime(float time, Action action) public static IEnumerator ActionAfterTime(float time, Action action)
{ {

View File

@ -1,13 +1,45 @@
using System.Diagnostics; using System.Diagnostics;
using UnityEngine; using System.Linq;
using UnityEditor; using UnityEditor;
using UnityEditor.Build;
using UnityEngine;
using Debug = UnityEngine.Debug; using Debug = UnityEngine.Debug;
public static class BuildingUtils public static class BuildingUtils
{ {
private const string SteamBuildDefine = "STEAM_BUILD";
[MenuItem("Tools/PrepareForBuild", priority = -10)]
public static void PrepareForBuild()
{
var namedBuildTarget = NamedBuildTarget.FromBuildTargetGroup(
BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget));
string[] args = PlayerSettings.GetAdditionalCompilerArguments(namedBuildTarget);
var argsList = args.ToList();
argsList.Remove(SteamBuildDefine);
PlayerSettings.SetScriptingDefineSymbols(namedBuildTarget, argsList.ToArray());
}
[MenuItem("Tools/PlatformDefines/Steam", priority = -1)]
public static void SetDefinesForSteam()
{
PrepareForBuild();
var namedBuildTarget = NamedBuildTarget.FromBuildTargetGroup(
BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget));
string[] args = PlayerSettings.GetAdditionalCompilerArguments(namedBuildTarget);
var argsList = args.ToList();
argsList.Add(SteamBuildDefine);
PlayerSettings.SetScriptingDefineSymbols(namedBuildTarget, argsList.ToArray());
}
[MenuItem("Tools/Build/Steam/Release")] [MenuItem("Tools/Build/Steam/Release")]
public static void SteamRelease() public static void SteamRelease()
{ {
if (!CanBuild())
return;
IncreaseBuildNumber(); IncreaseBuildNumber();
BuildRelease(); BuildRelease();
UploadSteam(); UploadSteam();
@ -16,38 +48,102 @@ public static class BuildingUtils
[MenuItem("Tools/Build/Steam/Development")] [MenuItem("Tools/Build/Steam/Development")]
public static void SteamDevelopment() public static void SteamDevelopment()
{ {
if (!CanBuild())
return;
IncreaseBuildNumber(); IncreaseBuildNumber();
BuildDevelopment(); BuildDevelopment();
UploadSteam(); UploadSteam();
} }
[MenuItem("Tools/Build/Steam/Demo")]
public static void SteamDemo()
{
if (!CanBuild())
return;
IncreaseBuildNumber();
BuildDemo();
UploadSteam(true);
}
[MenuItem("Tools/Build/All Release")] [MenuItem("Tools/Build/All Release")]
public static void BuildRelease() public static void BuildRelease()
{ {
if (!CanBuild())
return;
BuildWindowsRelease(); BuildWindowsRelease();
BuildLinuxRelease();
} }
[MenuItem("Tools/Build/All Development")] [MenuItem("Tools/Build/All Development")]
public static void BuildDevelopment() public static void BuildDevelopment()
{ {
if (!CanBuild())
return;
BuildWindowsDevelopment(); BuildWindowsDevelopment();
} }
[MenuItem("Tools/Build/All Demo")]
public static void BuildDemo()
{
if (!CanBuild())
return;
BuildWindows(true, new[] { "DEMO" });
BuildLinux(true, new[] { "DEMO" });
}
[MenuItem("Tools/Build/Platform/Windows/x64-Development")] [MenuItem("Tools/Build/Platform/Windows/x64-Development")]
public static void BuildWindowsDevelopment() => BuildWindows(false); public static void BuildWindowsDevelopment()
{
if (!CanBuild())
return;
BuildWindows(false);
}
[MenuItem("Tools/Build/Platform/Windows/x64-Release")] [MenuItem("Tools/Build/Platform/Windows/x64-Release")]
public static void BuildWindowsRelease() => BuildWindows(true); public static void BuildWindowsRelease()
{
if (!CanBuild())
return;
BuildWindows(true);
}
[MenuItem("Tools/Build/Platform/Linux/x64-Release")]
public static void BuildLinuxRelease()
{
if (!CanBuild())
return;
BuildLinux(true);
}
private static void BuildWindows(bool release) [MenuItem("Tools/Build/Platform/Android/GooglePlay")]
public static void BuildGooglePlay()
{
IncreaseBuildNumber();
PlayerSettings.Android.bundleVersionCode++;
EditorUserBuildSettings.buildAppBundle = true;
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.Android;
buildPlayerOptions.options = BuildOptions.None;
buildPlayerOptions.locationPathName = Application.dataPath +
$"/../../{Application.productName}-GooglePlay/{Application.productName}.aab";
BuildPipeline.BuildPlayer(buildPlayerOptions);
}
private static void BuildWindows(bool release, string[] additionalDefines = default)
{ {
var buildPlayerOptions = new BuildPlayerOptions { scenes = new string[EditorBuildSettings.scenes.Length] }; var buildPlayerOptions = new BuildPlayerOptions { scenes = new string[EditorBuildSettings.scenes.Length] };
for (int i = 0; i < EditorBuildSettings.scenes.Length; i++) for (int i = 0; i < EditorBuildSettings.scenes.Length; i++)
{
buildPlayerOptions.scenes[i] = EditorBuildSettings.scenes[i].path; buildPlayerOptions.scenes[i] = EditorBuildSettings.scenes[i].path;
}
buildPlayerOptions.extraScriptingDefines = additionalDefines;
buildPlayerOptions.target = BuildTarget.StandaloneWindows64; buildPlayerOptions.target = BuildTarget.StandaloneWindows64;
buildPlayerOptions.options = release ? BuildOptions.None : BuildOptions.Development; buildPlayerOptions.options = release ? BuildOptions.None : BuildOptions.Development;
@ -56,29 +152,73 @@ public static class BuildingUtils
BuildPipeline.BuildPlayer(buildPlayerOptions); BuildPipeline.BuildPlayer(buildPlayerOptions);
} }
private static void BuildLinux(bool release, string[] additionalDefines = default)
{
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.extraScriptingDefines = additionalDefines;
buildPlayerOptions.target = BuildTarget.StandaloneLinux64;
buildPlayerOptions.options = release ? BuildOptions.None : BuildOptions.Development;
buildPlayerOptions.locationPathName = Application.dataPath +
$"/../../{Application.productName}-Steam/ContentBuilder/content/linux/{Application.productName}.x86_64";
BuildPipeline.BuildPlayer(buildPlayerOptions);
}
private static void IncreaseBuildNumber() private static void IncreaseBuildNumber()
{ {
string[] versionParts = PlayerSettings.bundleVersion.Split('.'); string[] versionParts = PlayerSettings.bundleVersion.Split('.');
if (versionParts.Length != 3 || !int.TryParse(versionParts[2], out int version)) { if (versionParts.Length != 3 || !int.TryParse(versionParts[2], out int version))
{
Debug.LogError("IncreaseBuildNumber failed to update version " + PlayerSettings.bundleVersion); Debug.LogError("IncreaseBuildNumber failed to update version " + PlayerSettings.bundleVersion);
return; return;
} }
versionParts[2] = (version + 1).ToString(); versionParts[2] = (version + 1).ToString();
PlayerSettings.bundleVersion = string.Join(".", versionParts); PlayerSettings.bundleVersion = string.Join(".", versionParts);
} }
private static void UploadSteam() private static void UploadSteam(bool demo = false)
{ {
string command = $"cd {Application.dataPath}/../../{Application.productName}-Steam/ContentBuilder && run_build.bat"; string command =
$"cd {Application.dataPath}/../../{Application.productName}-Steam/ContentBuilder && push_build.bat";
if (demo)
{
command =
$"cd {Application.dataPath}/../../{Application.productName}-Steam/ContentBuilder && push_demo.bat";
}
var processInfo = new ProcessStartInfo("cmd.exe", $"/c {command}") var processInfo = new ProcessStartInfo("cmd.exe", $"/c {command}")
{ {
CreateNoWindow = true, CreateNoWindow = true, UseShellExecute = false
UseShellExecute = false };
};
var process = Process.Start(processInfo); var process = Process.Start(processInfo);
process.WaitForExit(); process.WaitForExit();
Debug.Log(process.ExitCode); Debug.Log(process.ExitCode);
process.Close(); process.Close();
} }
private static bool CanBuild()
{
if (CanBuildUtil())
return true;
Debug.LogError(
"Cannot build with defines set in project, please use PrepareForBuild and wait for scripts recompilation");
return false;
}
private static bool CanBuildUtil()
{
var namedBuildTarget = NamedBuildTarget.FromBuildTargetGroup(
BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget));
string[] args = PlayerSettings.GetAdditionalCompilerArguments(namedBuildTarget);
var argsList = args.ToList();
if (argsList.Contains(SteamBuildDefine))
return false;
return true;
}
} }

View File

@ -8,14 +8,19 @@ namespace NEG.Utils.Editor.ComponentsAdditionalItems
{ {
[MenuItem("CONTEXT/CanvasScaler/Full HD horizontal", false, 2000)] [MenuItem("CONTEXT/CanvasScaler/Full HD horizontal", false, 2000)]
public static void SetFullHdHorizontal(MenuCommand command) => SetComponent(command, 1920, 1080); public static void SetFullHdHorizontal(MenuCommand command) => SetComponent(command, 1920, 1080);
[MenuItem("CONTEXT/CanvasScaler/Full HD vertical", false, 2000)] [MenuItem("CONTEXT/CanvasScaler/Full HD vertical", false, 2000)]
public static void SetFullHdVertical(MenuCommand command) => SetComponent(command, 1080, 1920); public static void SetFullHdVertical(MenuCommand command) => SetComponent(command, 1080, 1920);
[MenuItem("CONTEXT/CanvasScaler/Full 2k horizontal", false, 2000)] [MenuItem("CONTEXT/CanvasScaler/Full 2k horizontal", false, 2000)]
public static void Set2KHorizontal(MenuCommand command) => SetComponent(command, 2560, 1440 ); public static void Set2KHorizontal(MenuCommand command) => SetComponent(command, 2560, 1440);
[MenuItem("CONTEXT/CanvasScaler/Full 2k vertical", false, 2000)] [MenuItem("CONTEXT/CanvasScaler/Full 2k vertical", false, 2000)]
public static void Set2KVertical(MenuCommand command) => SetComponent(command, 1440, 2560); public static void Set2KVertical(MenuCommand command) => SetComponent(command, 1440, 2560);
[MenuItem("CONTEXT/CanvasScaler/Full 4k horizontal", false, 2000)] [MenuItem("CONTEXT/CanvasScaler/Full 4k horizontal", false, 2000)]
public static void Set4KHorizontal(MenuCommand command) => SetComponent(command, 3840, 2160); public static void Set4KHorizontal(MenuCommand command) => SetComponent(command, 3840, 2160);
[MenuItem("CONTEXT/CanvasScaler/Full 4k vertical", false, 2000)] [MenuItem("CONTEXT/CanvasScaler/Full 4k vertical", false, 2000)]
public static void Set4KVertical(MenuCommand command) => SetComponent(command, 2160, 3840); public static void Set4KVertical(MenuCommand command) => SetComponent(command, 2160, 3840);

View File

@ -11,61 +11,57 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using UnityEngine;
using UnityEditor; using UnityEditor;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace TheGamedevGuru namespace TheGamedevGuru
{ {
public class EditorInstanceCreator : EditorWindow public class EditorInstanceCreator : EditorWindow
{ {
string _projectInstanceName; private string _extraSubdirectories;
string _extraSubdirectories; private bool _includeProjectSettings = true;
bool _includeProjectSettings = true; private string _projectInstanceName;
[MenuItem("Window/The Gamedev Guru/Editor Instance Creator")] private void OnGUI()
static void Init()
{
((EditorInstanceCreator)EditorWindow.GetWindow(typeof(EditorInstanceCreator))).Show();
}
void OnGUI()
{ {
if (string.IsNullOrEmpty(_projectInstanceName)) if (string.IsNullOrEmpty(_projectInstanceName))
{
_projectInstanceName = PlayerSettings.productName + "_Slave_1"; _projectInstanceName = PlayerSettings.productName + "_Slave_1";
}
EditorGUILayout.Separator(); EditorGUILayout.Separator();
EditorGUILayout.LabelField("The Gamedev Guru - Project Instance Creator"); EditorGUILayout.LabelField("The Gamedev Guru - Project Instance Creator");
EditorGUILayout.Separator(); EditorGUILayout.Separator();
EditorGUILayout.LabelField("Slave Project Name"); EditorGUILayout.LabelField("Slave Project Name");
_projectInstanceName = EditorGUILayout.TextField("", _projectInstanceName); _projectInstanceName = EditorGUILayout.TextField("", _projectInstanceName);
EditorGUILayout.Separator(); EditorGUILayout.Separator();
EditorGUILayout.LabelField("Include Project Settings? (Recommended)"); EditorGUILayout.LabelField("Include Project Settings? (Recommended)");
_includeProjectSettings = EditorGUILayout.Toggle("", _includeProjectSettings); _includeProjectSettings = EditorGUILayout.Toggle("", _includeProjectSettings);
EditorGUILayout.Separator(); EditorGUILayout.Separator();
EditorGUILayout.LabelField("Extra Subdirectories? (Separate by comma)"); EditorGUILayout.LabelField("Extra Subdirectories? (Separate by comma)");
_extraSubdirectories = EditorGUILayout.TextField("", _extraSubdirectories); _extraSubdirectories = EditorGUILayout.TextField("", _extraSubdirectories);
EditorGUILayout.Separator(); EditorGUILayout.Separator();
if (GUILayout.Button("Create")) if (GUILayout.Button("Create"))
{
CreateProjectInstance(_projectInstanceName, _includeProjectSettings, _extraSubdirectories); CreateProjectInstance(_projectInstanceName, _includeProjectSettings, _extraSubdirectories);
}
if (GUILayout.Button("Help")) if (GUILayout.Button("Help"))
{
Application.OpenURL("https://thegamedev.guru/multiple-unity-editor-instances-within-a-single-project/"); Application.OpenURL("https://thegamedev.guru/multiple-unity-editor-instances-within-a-single-project/");
}
} }
static void CreateProjectInstance(string projectInstanceName, bool includeProjectSettings, string extraSubdirectories) [MenuItem("Window/The Gamedev Guru/Editor Instance Creator")]
private static void Init() => ((EditorInstanceCreator)GetWindow(typeof(EditorInstanceCreator))).Show();
private static void CreateProjectInstance(string projectInstanceName, bool includeProjectSettings,
string extraSubdirectories)
{ {
var targetDirectory = Path.Combine(Directory.GetCurrentDirectory(), ".." + Path.DirectorySeparatorChar, projectInstanceName); string targetDirectory = Path.Combine(Directory.GetCurrentDirectory(), ".." + Path.DirectorySeparatorChar,
projectInstanceName);
Debug.Log(targetDirectory); Debug.Log(targetDirectory);
if (Directory.Exists(targetDirectory)) if (Directory.Exists(targetDirectory))
{ {
@ -75,29 +71,21 @@ namespace TheGamedevGuru
Directory.CreateDirectory(targetDirectory); Directory.CreateDirectory(targetDirectory);
List<string> subdirectories = new List<string>{"Assets", "Packages"}; var subdirectories = new List<string> { "Assets", "Packages" };
if (includeProjectSettings) if (includeProjectSettings) subdirectories.Add("ProjectSettings");
{
subdirectories.Add("ProjectSettings");
}
foreach (var extraSubdirectory in extraSubdirectories.Split(',')) foreach (string extraSubdirectory in extraSubdirectories.Split(','))
{
subdirectories.Add(extraSubdirectory.Trim()); subdirectories.Add(extraSubdirectory.Trim());
}
foreach (var subdirectory in subdirectories) foreach (string subdirectory in subdirectories)
{ Process.Start("CMD.exe", GetLinkCommand(subdirectory, targetDirectory));
System.Diagnostics.Process.Start("CMD.exe",GetLinkCommand(subdirectory, targetDirectory));
}
EditorUtility.RevealInFinder(targetDirectory + Path.DirectorySeparatorChar + "Assets"); EditorUtility.RevealInFinder(targetDirectory + Path.DirectorySeparatorChar + "Assets");
EditorUtility.DisplayDialog("Done!", $"Done! Feel free to add it as an existing project at: {targetDirectory}", "Ok :)"); EditorUtility.DisplayDialog("Done!",
$"Done! Feel free to add it as an existing project at: {targetDirectory}", "Ok :)");
} }
static string GetLinkCommand(string subdirectory, string targetDirectory) private static string GetLinkCommand(string subdirectory, string targetDirectory) =>
{ $"/c mklink /J \"{targetDirectory}{Path.DirectorySeparatorChar}{subdirectory}\" \"{Directory.GetCurrentDirectory()}{Path.DirectorySeparatorChar}{subdirectory}\"";
return $"/c mklink /J \"{targetDirectory}{Path.DirectorySeparatorChar}{subdirectory}\" \"{Directory.GetCurrentDirectory()}{Path.DirectorySeparatorChar}{subdirectory}\"";
}
} }
} }

42
Editor/EditorUtils.cs Normal file
View File

@ -0,0 +1,42 @@
using System;
using UnityEditor;
namespace NegUtils.Editor
{
public class EditorUtils
{
}
public class AssetPath
{
private readonly string filter;
private string path;
public AssetPath(string filter)
{
this.filter = filter;
TryFindPath();
}
public string Path
{
get
{
if (path != null)
return path;
TryFindPath();
return path;
}
}
private void TryFindPath()
{
string[] candidates = AssetDatabase.FindAssets(filter);
if (candidates.Length == 0)
throw new Exception("Missing layout asset!");
path = AssetDatabase.GUIDToAssetPath(candidates[0]);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a4848b69c1024df8ad6f76cfd4415d01
timeCreated: 1698258811

View File

@ -1,23 +1,18 @@
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
public class GUIDToAssetPath : EditorWindow public class GUIDToAssetPath : EditorWindow
{ {
string guid = ""; private string guid = "";
string path = ""; private string path = "";
[MenuItem("Tools/GUIDToAssetPath")]
static void CreateWindow() private void OnGUI()
{
GUIDToAssetPath window = (GUIDToAssetPath)EditorWindow.GetWindowWithRect(typeof(GUIDToAssetPath), new Rect(0, 0, 400, 120));
}
void OnGUI()
{ {
GUILayout.Label("Enter guid"); GUILayout.Label("Enter guid");
guid = GUILayout.TextField(guid); guid = GUILayout.TextField(guid);
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
if (GUILayout.Button("Get Asset Path",GUILayout.Width(120))) if (GUILayout.Button("Get Asset Path", GUILayout.Width(120)))
path = GetAssetPath(guid); path = GetAssetPath(guid);
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
@ -29,10 +24,17 @@ public class GUIDToAssetPath : EditorWindow
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUILayout.Label(path); GUILayout.Label(path);
} }
static string GetAssetPath(string guid)
[MenuItem("Tools/GUIDToAssetPath")]
private static void CreateWindow()
{
var window = (GUIDToAssetPath)GetWindowWithRect(typeof(GUIDToAssetPath), new Rect(0, 0, 400, 120));
}
private static string GetAssetPath(string guid)
{ {
guid = guid.Replace("-", ""); guid = guid.Replace("-", "");
string p = AssetDatabase.GUIDToAssetPath(guid); string p = AssetDatabase.GUIDToAssetPath(guid);
Debug.Log(p); Debug.Log(p);
if (p.Length == 0) p = "not found"; if (p.Length == 0) p = "not found";

View File

@ -0,0 +1,46 @@
using System.IO;
using UnityEditor;
using UnityEngine;
namespace NEG.Utils.Editor
{
public static class MonoBehaviourExtensions
{
[MenuItem("CONTEXT/MonoBehaviour/Change Script")]
public static void ChangeScript(MenuCommand command)
{
if (command.context == null)
return;
var monoBehaviour = command.context as MonoBehaviour;
var monoScript = MonoScript.FromMonoBehaviour(monoBehaviour);
string scriptPath = AssetDatabase.GetAssetPath(monoScript);
string directoryPath = new FileInfo(scriptPath).Directory?.FullName;
// Allow the user to select which script to replace with
string newScriptPath = EditorUtility.OpenFilePanel("Select replacement script", directoryPath, "cs");
// Don't log anything if they cancelled the window
if (string.IsNullOrEmpty(newScriptPath)) return;
// Load the selected asset
string relativePath = "Assets\\" + Path.GetRelativePath(Application.dataPath, newScriptPath);
var chosenTextAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(relativePath);
if (chosenTextAsset == null)
{
Debug.LogWarning($"Selected script couldn't be loaded ({relativePath})");
return;
}
Undo.RegisterCompleteObjectUndo(command.context, "Changing component script");
var so = new SerializedObject(monoBehaviour);
var scriptProperty = so.FindProperty("m_Script");
so.Update();
scriptProperty.objectReferenceValue = chosenTextAsset;
so.ApplyModifiedProperties();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0501eedeaf1d4dcf8c4d0f1b7a0c1761
timeCreated: 1684519404

View File

@ -1,18 +1,18 @@
{ {
"name": "NEG.Utils.Editor", "name": "NEG.Utils.Editor",
"rootNamespace": "", "rootNamespace": "",
"references": [ "references": [
"GUID:3c4294719a93e3c4e831a9ff0c261e8a" "GUID:3c4294719a93e3c4e831a9ff0c261e8a"
], ],
"includePlatforms": [ "includePlatforms": [
"Editor" "Editor"
], ],
"excludePlatforms": [], "excludePlatforms": [],
"allowUnsafeCode": false, "allowUnsafeCode": false,
"overrideReferences": false, "overrideReferences": false,
"precompiledReferences": [], "precompiledReferences": [],
"autoReferenced": true, "autoReferenced": true,
"defineConstraints": [], "defineConstraints": [],
"versionDefines": [], "versionDefines": [],
"noEngineReferences": false "noEngineReferences": false
} }

View File

@ -0,0 +1,19 @@
using UnityEditor;
using UnityEngine;
namespace NEG.Utils.Editor
{
[CustomPropertyDrawer(typeof(ReadOnlyAttribute))]
public class ReadOnlyPropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
GUI.enabled = false;
EditorGUI.PropertyField(position, property, label, true);
GUI.enabled = true;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) =>
EditorGUI.GetPropertyHeight(property, label, true);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1f837bac3a7b40528454a9fb9a46d0be
timeCreated: 1699371332

View File

@ -1,5 +1,6 @@
using UnityEngine;
using UnityEditor; using UnityEditor;
using UnityEngine;
/// <summary> /// <summary>
/// Drawer for the RequireInterface attribute. /// Drawer for the RequireInterface attribute.
/// </summary> /// </summary>
@ -10,7 +11,7 @@ namespace NEG.Utils
public class RequireInterfaceDrawer : PropertyDrawer public class RequireInterfaceDrawer : PropertyDrawer
{ {
/// <summary> /// <summary>
/// Overrides GUI drawing for the attribute. /// Overrides GUI drawing for the attribute.
/// </summary> /// </summary>
/// <param name="position">Position.</param> /// <param name="position">Position.</param>
/// <param name="property">Property.</param> /// <param name="property">Property.</param>
@ -21,11 +22,12 @@ namespace NEG.Utils
if (property.propertyType == SerializedPropertyType.ObjectReference) if (property.propertyType == SerializedPropertyType.ObjectReference)
{ {
// Get attribute parameters. // Get attribute parameters.
var requiredAttribute = this.attribute as RequireInterfaceAttribute; var requiredAttribute = attribute as RequireInterfaceAttribute;
// Begin drawing property field. // Begin drawing property field.
EditorGUI.BeginProperty(position, label, property); EditorGUI.BeginProperty(position, label, property);
// Draw property field. // Draw property field.
property.objectReferenceValue = EditorGUI.ObjectField(position, label, property.objectReferenceValue, requiredAttribute.requiredType, true); property.objectReferenceValue = EditorGUI.ObjectField(position, label, property.objectReferenceValue,
requiredAttribute.requiredType, true);
// Finish drawing property field. // Finish drawing property field.
EditorGUI.EndProperty(); EditorGUI.EndProperty();
} }

18
Editor/ScreenshotMaker.cs Normal file
View File

@ -0,0 +1,18 @@
using UnityEditor;
using UnityEngine;
namespace NEG.Editor
{
public static class ScreenshotMaker
{
[MenuItem("CONTEXT/Camera/Save view")]
public static void Capture(MenuCommand command)
{
string path = EditorUtility.SaveFilePanel("Save screenshot", "", "screen.png", "png");
if (path.Length == 0)
return;
ScreenCapture.CaptureScreenshot(path);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7dba407e8e8740a1bed3ee5fa833b13c
timeCreated: 1687881092

View File

@ -1,21 +1,16 @@
using System;
using UnityEditor; using UnityEditor;
namespace NEG.Utils.Serialization namespace NEG.Utils.Serialization
{ {
public static class SerializationExtentions public static class SerializationExtentions
{ {
public static SerializedProperty FindAutoProperty(this SerializedObject @this, string name) public static SerializedProperty FindAutoProperty(this SerializedObject @this, string name) =>
{ @this.FindProperty(GetBackingFieldName(name));
return @this.FindProperty(GetBackingFieldName(name));
}
public static SerializedProperty FindAutoPropertyRelative(this SerializedProperty @this, string name) public static SerializedProperty FindAutoPropertyRelative(this SerializedProperty @this, string name) =>
{ @this.FindPropertyRelative(GetBackingFieldName(name));
return @this.FindPropertyRelative(GetBackingFieldName(name));
}
private static string GetBackingFieldName(string name) public static string GetBackingFieldName(string name)
{ {
#if NET_STANDARD || NET_STANDARD_2_1 #if NET_STANDARD || NET_STANDARD_2_1
return string.Create(1/*<*/ + name.Length + 16/*>k__BackingField*/, name, static (span, name) => return string.Create(1/*<*/ + name.Length + 16/*>k__BackingField*/, name, static (span, name) =>
@ -29,4 +24,4 @@ namespace NEG.Utils.Serialization
#endif #endif
} }
} }
} }

View File

@ -1,5 +1,4 @@
using System; using System.IO;
using System.IO;
using UnityEditor; using UnityEditor;
using UnityEditor.SceneManagement; using UnityEditor.SceneManagement;
using UnityEngine; using UnityEngine;
@ -10,11 +9,34 @@ namespace NegUtils.Editor
[InitializeOnLoad] [InitializeOnLoad]
public class ToolsWindowBase : EditorWindow public class ToolsWindowBase : EditorWindow
{ {
private const int UnitySceneExtensionLength = 6;
static ToolsWindowBase() static ToolsWindowBase()
{ {
EditorApplication.playModeStateChanged += OnPlayModeStateChanged; EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
} }
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)
return;
bool goToCurrentScene = EditorPrefs.GetBool("GoToCurrentSceneAfterPlay");
newVal = GUILayout.Toggle(goToCurrentScene, "Go to current scene after play");
if (newVal != goToCurrentScene) EditorPrefs.SetBool("GoToCurrentSceneAfterPlay", newVal);
bool goToFirstScene = EditorPrefs.GetBool("GoToFirstSceneAfterPlay");
newVal = GUILayout.Toggle(goToFirstScene, "Go to scene with index 1 after play");
if (newVal != goToFirstScene) EditorPrefs.SetBool("GoToFirstSceneAfterPlay", newVal);
}
[MenuItem("Tools/Show Tools Window")] [MenuItem("Tools/Show Tools Window")]
private static void ShowWindow() private static void ShowWindow()
{ {
@ -22,47 +44,39 @@ namespace NegUtils.Editor
window.Show(); 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) private static void ShowScenesList(Rect position)
{ {
var menu = new GenericMenu(); var menu = new GenericMenu();
string path = Application.dataPath + "/Scenes/Production"; string path = Application.dataPath + "/Scenes";
string[] fileInfo = Directory.GetFiles(path, "*.unity");
AddFiles(path, path, menu);
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); menu.DropDown(position);
} }
private static void AddFiles(string path, string basePath, GenericMenu menu)
{
string[] fileInfo = Directory.GetFiles(path, "*.unity");
for (int i = 0; i < fileInfo.Length; i++)
{
string s = fileInfo[i];
menu.AddItem(
new GUIContent(s.Remove(0, basePath.Length + 1)
.Remove(s.Length - basePath.Length - UnitySceneExtensionLength - 1, UnitySceneExtensionLength)
.Replace('\\', '/')), false, () =>
{
LoadScene(s);
});
if (i == fileInfo.Length) continue;
menu.AddSeparator("");
}
string[] dirInfo = Directory.GetDirectories(path);
foreach (string dir in dirInfo) AddFiles(dir, basePath, menu);
}
private static void LoadScene(string path) private static void LoadScene(string path)
{ {
EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo(); EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
@ -71,11 +85,11 @@ namespace NegUtils.Editor
private static void OnPlayModeStateChanged(PlayModeStateChange state) private static void OnPlayModeStateChanged(PlayModeStateChange state)
{ {
switch(state) switch (state)
{ {
case PlayModeStateChange.ExitingEditMode: case PlayModeStateChange.ExitingEditMode:
{ {
if(!EditorPrefs.GetBool("StartFromSceneIndex0")) if (!EditorPrefs.GetBool("StartFromSceneIndex0"))
return; return;
EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo(); EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
EditorPrefs.SetString("LastOpenedScenePath", EditorSceneManager.GetSceneManagerSetup()[0].path); EditorPrefs.SetString("LastOpenedScenePath", EditorSceneManager.GetSceneManagerSetup()[0].path);
@ -84,25 +98,26 @@ namespace NegUtils.Editor
break; break;
case PlayModeStateChange.EnteredPlayMode: case PlayModeStateChange.EnteredPlayMode:
{ {
if(!EditorPrefs.GetBool("StartFromSceneIndex0")) if (!EditorPrefs.GetBool("StartFromSceneIndex0"))
return; return;
if (EditorPrefs.GetBool("GoToCurrentSceneAfterPlay")) if (EditorPrefs.GetBool("GoToCurrentSceneAfterPlay"))
{
EditorSceneManager.LoadSceneInPlayMode(EditorPrefs.GetString("LastOpenedScenePath"), EditorSceneManager.LoadSceneInPlayMode(EditorPrefs.GetString("LastOpenedScenePath"),
new LoadSceneParameters(LoadSceneMode.Single)); new LoadSceneParameters(LoadSceneMode.Single));
else }
else if (EditorPrefs.GetBool("GoToFirstSceneAfterPlay"))
SceneManager.LoadScene(1); SceneManager.LoadScene(1);
} }
break; break;
case PlayModeStateChange.EnteredEditMode: case PlayModeStateChange.EnteredEditMode:
{ {
if(!EditorPrefs.GetBool("StartFromSceneIndex0")) if (!EditorPrefs.GetBool("StartFromSceneIndex0"))
return; return;
EditorSceneManager.OpenScene(EditorPrefs.GetString("LastOpenedScenePath")); EditorSceneManager.OpenScene(EditorPrefs.GetString("LastOpenedScenePath"));
} }
break; break;
} }
} }
} }
} }

14
Editor/TsvImporter.cs Normal file
View File

@ -0,0 +1,14 @@
using System.IO;
using UnityEditor.AssetImporters;
using UnityEngine;
[ScriptedImporter(1, "tsv")]
public class TsvImporter : ScriptedImporter
{
public override void OnImportAsset(AssetImportContext ctx)
{
var textAsset = new TextAsset(File.ReadAllText(ctx.assetPath));
ctx.AddObjectToAsset(Path.GetFileNameWithoutExtension(ctx.assetPath), textAsset);
ctx.SetMainObject(textAsset);
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 307c41c8e2487e3488480dd4696efaf6 guid: b3f8438db4084014bab0a063e4675d3f
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

50
KeyBasedFactory.cs Normal file
View File

@ -0,0 +1,50 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Reflection;
namespace NEG.Utils
{
public class KeyBasedFactory<T1, T2>
{
[PublicAPI] protected Dictionary<T1, Type> data;
public KeyBasedFactory()
{
data = new Dictionary<T1, Type>();
}
public void FireRegistration()
{
ScanAssembly(typeof(T2).Assembly);
if (typeof(T2).Assembly.GetType().Assembly == typeof(T2).Assembly)
return;
ScanAssembly(typeof(T2).Assembly.GetType().Assembly);
}
private static void ScanAssembly(Assembly assembly)
{
foreach (var type in assembly.GetTypes())
{
var methodFields =
type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
for (int i = 0; i < methodFields.Length; i++)
{
if (Attribute.GetCustomAttribute(methodFields[i], typeof(FactoryRegistration)) != null)
methodFields[i].Invoke(null, Array.Empty<object>());
}
}
}
public void Register(T1 key, Type type) => data.Add(key, type);
public T2 CreateInstance(T1 key, params object[] args) => (T2)Activator.CreateInstance(data[key], args);
}
[AttributeUsage(AttributeTargets.Method)]
public class FactoryRegistration : Attribute
{
}
}

3
KeyBasedFactory.cs.meta Normal file
View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2e0d3df1ddd34209bfb7262b4e51abfe
timeCreated: 1683917310

View File

@ -1,16 +1,16 @@
{ {
"name": "NEG.Utils", "name": "NEG.Utils",
"rootNamespace": "", "rootNamespace": "",
"references": [ "references": [
"GUID:6055be8ebefd69e48b49212b09b47b2f" "GUID:6055be8ebefd69e48b49212b09b47b2f"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],
"allowUnsafeCode": false, "allowUnsafeCode": false,
"overrideReferences": false, "overrideReferences": false,
"precompiledReferences": [], "precompiledReferences": [],
"autoReferenced": true, "autoReferenced": true,
"defineConstraints": [], "defineConstraints": [],
"versionDefines": [], "versionDefines": [],
"noEngineReferences": false "noEngineReferences": false
} }

View File

@ -1,22 +0,0 @@
using System.IO;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
namespace NEG.Localization.Editor
{
public class LocalizationPreBuild : IPreprocessBuildWithReport
{
public int callbackOrder => 0;
public void OnPreprocessBuild(BuildReport report)
{
if(!Directory.Exists($"{Application.dataPath}/{LocalizationManager.ResourcesFolderPath}/{LocalizationManager.LanguageResourcePath}"))
{
Debug.LogWarning("No folder for localization, creating");
}
Debug.Log("test");
}
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 7a787e11f9704339b362f95e333b2daf
timeCreated: 1675691755

View File

@ -1,19 +0,0 @@
{
"name": "NEG.Localization.Editor",
"rootNamespace": "",
"references": [
"GUID:6055be8ebefd69e48b49212b09b47b2f",
"GUID:9fb3d516715e5574db1dd1f3d557a8ab"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -1,7 +0,0 @@
namespace NEG.Localization
{
public class LocalizationContext
{
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: ce1c159bd9384adea90c1a2103a3fb12
timeCreated: 1675688372

View File

@ -1,75 +0,0 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace NEG.Localization
{
[PublicAPI]
public class LocalizationManager
{
private class AvailableLanguages
{
public List<string> Languages { get; set; }
}
public const string LanguageResourcePath = "Localization";
public const string ResourcesFolderPath = "Data/Resources";
public const string AvailableLanguagesFile = "Languages";
public static LocalizationManager Instance => instance ??= new LocalizationManager();
public IEnumerable<string> Languages => languages;
private static LocalizationManager instance;
private List<string> languages;
private HashSet<Action<LocalizationProvider>> actions = new();
private LocalizationProvider provider;
public LocalizationManager()
{
var file = Resources.Load<TextAsset>($"{LanguageResourcePath}/{AvailableLanguagesFile}");
var available = JsonConvert.DeserializeObject<AvailableLanguages>(file.text);
languages = available.Languages;
}
public void SelectLanguage(string languageCode)
{
if (!languages.Contains(languageCode))
{
Debug.LogError($"Localization {languageCode} not found in files");
return;
}
provider = new LocalizationProvider($"{LanguageResourcePath}/{languageCode}");
foreach (var item in actions)
{
item?.Invoke(provider);
}
}
/// <summary>
/// Register action for localization. Always fire provided action
/// </summary>
/// <param name="action">action to call on localization change</param>
public static void Register(Action<LocalizationProvider> action)
{
if (!Instance.actions.Contains(action))
{
Instance.actions.Add(action);
}
action.Invoke(Instance.provider);
}
/// <summary>
/// Unregister action from localization.
/// </summary>
/// <param name="action">action to unregister</param>
public static void Unregister(Action<LocalizationProvider> action) => Instance.actions.Remove(action);
}
}

View File

@ -1,57 +0,0 @@
using Newtonsoft.Json.Linq;
using System.IO;
using System.Collections.Generic;
using UnityEngine;
namespace NEG.Localization
{
public class LocalizationProvider
{
private readonly Dictionary<string, string> texts = new();
private readonly Dictionary<int, string> posToString = new();
public LocalizationProvider(string path)
{
}
public string GetText(string key)
{
if (texts.TryGetValue(key, out string val))
{
return val;
}
return "BAD_" + key;
}
public string GetText(string key, params LocalizationContext[] contexts)
{
return "BAD_" + key;
}
internal void RegisterKeys(BinaryReader keysReader)
{
int i = 0;
while (keysReader.BaseStream.Position < keysReader.BaseStream.Length)
{
string read = keysReader.ReadString();
if (texts.ContainsKey(read))
Debug.LogWarning($"{read} is already added to localization");
else
texts.Add(read, "");
posToString.Add(++i, read);
}
}
internal void ChangeLanguage(BinaryReader reader)
{
int i = 0;
while (reader.BaseStream.Position < reader.BaseStream.Length)
{
texts[posToString[++i]] = reader.ReadString();
}
}
}
}

View File

@ -1,46 +0,0 @@
using System;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
namespace NEG.Localization
{
public class LocalizedText : MonoBehaviour
{
[SerializeField] private string key = "";
[SerializeField] private TMP_Text tmpText;
[SerializeField] private Text text;
private void Awake() => LocalizationManager.Register(SetText);
private void OnDestroy() => LocalizationManager.Unregister(SetText);
private void OnValidate()
{
if (tmpText != null || text != null)
return;
tmpText = GetComponent<TMP_Text>();
if (tmpText != null)
return;
text = GetComponent<Text>();
}
private void SetText(LocalizationProvider ctx)
{
if (text != null)
text.text = ctx.GetText(key);
if (tmpText != null)
tmpText.text = ctx.GetText(key);
}
#if UNITY_EDITOR
public void SetTextForEditor()
{
if (text != null)
text.text = "_" + key;
if (tmpText != null)
tmpText.text = "_" + key;
}
#endif
}
}

View File

@ -1,16 +0,0 @@
{
"name": "NEG.Localization",
"rootNamespace": "",
"references": [
"GUID:6055be8ebefd69e48b49212b09b47b2f"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -1,27 +0,0 @@
using System.Collections.Generic;
namespace NEG.Localization
{
public static class SteamLocalizationHelper
{
private static readonly Dictionary<string, string> steamLangMapping = new()
{
{ "english", "en" },
{ "polish", "pl" },
{ "spanish", "es" },
{ "german", "de" },
{ "schinese", "zh" },
{ "japanese", "ja" },
{ "french", "fr" },
{ "russian", "ru" },
{ "koreana", "ko" },
{ "italian", "it" },
{ "portuguese", "pt" },
{ "ukrainian", "uk" },
{ "norwegian", "no" },
{ "czech", "cs" }
};
public static string MapLanguageFromSteam(string lang) => steamLangMapping.TryGetValue(lang, out string mapped) ? mapped : "en";
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 3640a0fcfb0c4ea89159e0c64e5135b0
timeCreated: 1675474100

View File

@ -1,9 +1,11 @@
using NEG.UI.WindowSlot; using NEG.UI.WindowSlot;
using NegUtils.NEG.UI;
namespace NEG.UI.Area namespace NEG.UI.Area
{ {
public interface IArea : ISlotsHolder, IUiElement public interface IArea : ISlotsHolder, IControllable
{ {
void Open();
void Close();
} }
} }

18
NEG/UI/IControllable.cs Normal file
View File

@ -0,0 +1,18 @@
using System;
namespace NegUtils.NEG.UI
{
public interface IControllable
{
event Action<object> OnOpened;
event Action OnClosed;
event Action<BackUsed> OnBackUsed;
public void TryUseBack(ref BackUsed backUsed);
public class BackUsed
{
public bool Used { get; set; }
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 175798310e4048eda768cf40e6ee6de3
timeCreated: 1686596400

7
NEG/UI/IController.cs Normal file
View File

@ -0,0 +1,7 @@
namespace NegUtils.NEG.UI
{
public interface IController
{
IControllable Controllable { get; }
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b88f4a93020a4bc6bde40e0438d296a9
timeCreated: 1686595825

View File

@ -1,11 +0,0 @@
namespace NEG.UI
{
public interface IUiElement
{
/// <summary>
/// Sets only visible state of element
/// </summary>
/// <param name="setEnabled"></param>
void SetEnabled(bool setEnabled);
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 296bf6969a6347f8aea788a7bdd086af
timeCreated: 1670693177

View File

@ -1,14 +1,16 @@
{ {
"name": "NEG.UI", "name": "NEG.UI",
"rootNamespace": "", "rootNamespace": "",
"references": [], "references": [
"includePlatforms": [], "GUID:3c4294719a93e3c4e831a9ff0c261e8a"
"excludePlatforms": [], ],
"allowUnsafeCode": false, "includePlatforms": [],
"overrideReferences": false, "excludePlatforms": [],
"precompiledReferences": [], "allowUnsafeCode": false,
"autoReferenced": true, "overrideReferences": false,
"defineConstraints": [], "precompiledReferences": [],
"versionDefines": [], "autoReferenced": true,
"noEngineReferences": false "defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
} }

View File

@ -5,13 +5,14 @@ namespace NEG.UI.Popup
{ {
public class DefaultPopupData : PopupData public class DefaultPopupData : PopupData
{ {
private readonly IDefaultPopup defaultPopup;
private readonly string title;
private readonly string content; private readonly string content;
private readonly IDefaultPopup defaultPopup;
private readonly List<(string, Action)> options; private readonly List<(string, Action)> options;
public DefaultPopupData(IDefaultPopup popup, string title, string content, List<(string, Action)> options) : base(popup) private readonly string title;
public DefaultPopupData(IDefaultPopup popup, string title, string content, List<(string, Action)> options) :
base(popup)
{ {
defaultPopup = popup; defaultPopup = popup;
this.title = title; this.title = title;

View File

@ -6,11 +6,14 @@ namespace NEG.UI.Popup
public interface IDefaultPopup : IPopup public interface IDefaultPopup : IPopup
{ {
/// <summary> /// <summary>
/// Sets content based on provided data. /// Sets content based on provided data.
/// </summary> /// </summary>
/// <param name="title">popup title</param> /// <param name="title">popup title</param>
/// <param name="content">popup content</param> /// <param name="content">popup content</param>
/// <param name="options">list of tuples (name, action on click), to set buttons. Do not pass here popup closing logic, implementing class should do it</param> /// <param name="options">
/// list of tuples (name, action on click), to set buttons. Do not pass here popup closing logic,
/// implementing class should do it
/// </param>
public void SetContent(string title, string content, List<(string name, Action action)> options); public void SetContent(string title, string content, List<(string name, Action action)> options);
} }
} }

View File

@ -7,20 +7,20 @@ namespace NEG.UI.Popup
public interface IPopup public interface IPopup
{ {
/// <summary> /// <summary>
/// Event to fire when popup is closed /// Event to fire when popup is closed
/// </summary> /// </summary>
event Action<PopupData> OnPopupClosed; event Action<PopupData> OnPopupClosed;
/// <summary> /// <summary>
/// Show popup /// Show popup
/// </summary> /// </summary>
/// <param name="data">data assigned to popup, used to give info that popup is closed</param> /// <param name="data">data assigned to popup, used to give info that popup is closed</param>
public void Show(PopupData data); public void Show(PopupData data);
/// <summary> /// <summary>
/// Close popup or mark as closed if not visible /// Close popup or mark as closed if not visible
/// </summary> /// </summary>
/// <param name="silence">if true hide visually, without firing callbacks to properly close</param> /// <param name="silent">if true hide visually, without firing callbacks to properly close</param>
void Close(bool silence = false); void Close(bool silent = false);
} }
} }

View File

@ -6,8 +6,25 @@ namespace NEG.UI.Popup
[PublicAPI] [PublicAPI]
public class PopupData public class PopupData
{ {
private readonly IPopup popup;
/// <summary> /// <summary>
/// Event that is fired on closing popup. /// PopupData constructor.
/// </summary>
/// <param name="popup">attached to this data, can be used by different data instances</param>
public PopupData(IPopup popup)
{
this.popup = popup;
IsValid = true;
}
/// <summary>
/// Is this data is still valid. If set to false, popup will not show.
/// </summary>
public bool IsValid { get; protected set; }
/// <summary>
/// Event that is fired on closing popup.
/// </summary> /// </summary>
public event Action<PopupData> PopupClosedEvent public event Action<PopupData> PopupClosedEvent
{ {
@ -16,35 +33,22 @@ namespace NEG.UI.Popup
} }
/// <summary> /// <summary>
/// Is this data is still valid. If set to false, popup will not show. /// Show popup and pass needed data.
/// </summary>
public bool IsValid { get; protected set; }
private readonly IPopup popup;
/// <summary>
/// PopupData constructor.
/// </summary>
/// <param name="popup">attached to this data, can be used by different data instances</param>
public PopupData(IPopup popup)
{
this.popup = popup;
IsValid = true;
}
/// <summary>
/// Show popup and pass needed data.
/// </summary> /// </summary>
public virtual void Show() => popup.Show(this); public virtual void Show() => popup.Show(this);
/// <summary> /// <summary>
/// Hide popup. Close visuals without firing events; /// Hide popup. Close visuals without firing events;
/// </summary> /// </summary>
public virtual void Hide() => popup.Close(true); public virtual void Hide() => popup.Close(true);
/// <summary> /// <summary>
/// Invalidate popup, <see cref="UiManager"/> will automatically skip this popup /// Invalidate popup, <see cref="UiManager" /> will automatically skip this popup
/// </summary> /// </summary>
public virtual void Invalidate() => IsValid = false; public virtual void Invalidate()
{
IsValid = false;
UiManager.Instance.RefreshPopups();
}
} }
} }

View File

@ -248,8 +248,10 @@ namespace System.Collections.Generic
public PriorityQueue(int initialCapacity, IComparer<TPriority>? comparer) public PriorityQueue(int initialCapacity, IComparer<TPriority>? comparer)
{ {
if (initialCapacity < 0) if (initialCapacity < 0)
{
throw new ArgumentOutOfRangeException( throw new ArgumentOutOfRangeException(
nameof(initialCapacity), initialCapacity, SR.ArgumentOutOfRange_NeedNonNegNum); nameof(initialCapacity), initialCapacity, SR.ArgumentOutOfRange_NeedNonNegNum);
}
_nodes = new (TElement, TPriority)[initialCapacity]; _nodes = new (TElement, TPriority)[initialCapacity];
_comparer = InitializeComparer(comparer); _comparer = InitializeComparer(comparer);
@ -489,7 +491,7 @@ namespace System.Collections.Generic
{ {
int i = 0; int i = 0;
(TElement, TPriority)[] nodes = _nodes; (TElement, TPriority)[] nodes = _nodes;
foreach ((var element, var priority) in items) foreach (var (element, priority) in items)
{ {
if (nodes.Length == i) if (nodes.Length == i)
{ {
@ -508,9 +510,8 @@ namespace System.Collections.Generic
if (_size > 1) Heapify(); if (_size > 1) Heapify();
} }
else else
{ foreach (var (element, priority) in items)
foreach ((var element, var priority) in items) Enqueue(element, priority); Enqueue(element, priority);
}
} }
/// <summary> /// <summary>
@ -554,9 +555,8 @@ namespace System.Collections.Generic
if (i > 1) Heapify(); if (i > 1) Heapify();
} }
else else
{ foreach (var element in elements)
foreach (var element in elements) Enqueue(element, priority); Enqueue(element, priority);
}
} }
/// <summary> /// <summary>
@ -684,11 +684,15 @@ namespace System.Collections.Generic
int lastParentWithChildren = GetParentIndex(_size - 1); int lastParentWithChildren = GetParentIndex(_size - 1);
if (_comparer == null) if (_comparer == null)
{
for (int index = lastParentWithChildren; index >= 0; --index) for (int index = lastParentWithChildren; index >= 0; --index)
MoveDownDefaultComparer(nodes[index], index); MoveDownDefaultComparer(nodes[index], index);
}
else else
{
for (int index = lastParentWithChildren; index >= 0; --index) for (int index = lastParentWithChildren; index >= 0; --index)
MoveDownCustomComparer(nodes[index], index); MoveDownCustomComparer(nodes[index], index);
}
} }
/// <summary> /// <summary>
@ -715,9 +719,7 @@ namespace System.Collections.Generic
nodeIndex = parentIndex; nodeIndex = parentIndex;
} }
else else
{
break; break;
}
} }
nodes[nodeIndex] = node; nodes[nodeIndex] = node;
@ -748,9 +750,7 @@ namespace System.Collections.Generic
nodeIndex = parentIndex; nodeIndex = parentIndex;
} }
else else
{
break; break;
}
} }
nodes[nodeIndex] = node; nodes[nodeIndex] = node;
@ -894,8 +894,10 @@ namespace System.Collections.Generic
if (array.GetLowerBound(0) != 0) throw new ArgumentException(SR.Arg_NonZeroLowerBound, nameof(array)); if (array.GetLowerBound(0) != 0) throw new ArgumentException(SR.Arg_NonZeroLowerBound, nameof(array));
if (index < 0 || index > array.Length) if (index < 0 || index > array.Length)
{
throw new ArgumentOutOfRangeException(nameof(index), index, throw new ArgumentOutOfRangeException(nameof(index), index,
SR.ArgumentOutOfRange_IndexMustBeLessOrEqual); SR.ArgumentOutOfRange_IndexMustBeLessOrEqual);
}
if (array.Length - index < _queue._size) throw new ArgumentException(SR.Argument_InvalidOffLen); if (array.Length - index < _queue._size) throw new ArgumentException(SR.Argument_InvalidOffLen);

View File

@ -2,47 +2,28 @@ using JetBrains.Annotations;
using NEG.UI.Area; using NEG.UI.Area;
using NEG.UI.Popup; using NEG.UI.Popup;
using NEG.UI.Window; using NEG.UI.Window;
using NegUtils.NEG.UI;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using UnityEngine; using UnityEngine;
namespace NEG.UI namespace NEG.UI
{ {
[PublicAPI] [PublicAPI]
public abstract class UiManager public abstract class UiManager : IDisposable
{ {
public static UiManager Instance { get; private set; }
/// <summary>
/// Current area shown on screen.
/// </summary>
public IArea CurrentArea
{
get => currentArea;
set
{
currentArea?.SetEnabled(false);
currentArea = value;
currentArea?.SetEnabled(true);
}
}
/// <summary>
/// Current window that is considered main (focused, lastly opened). Can be null.
/// </summary>
public IWindow CurrentMainWindow { get; protected set; }
private IArea currentArea; private IArea currentArea;
private (PopupData data, int priority) currentShownPopup;
protected IDefaultPopup currentDefaultPopup; protected IDefaultPopup currentDefaultPopup;
private (PopupData data, int priority) currentShownPopup;
private PriorityQueue<PopupData, int> popupsToShow = new();
//TODO: localize //TODO: localize
private string localizedYes = "Yes", localizedNo = "No", localizedOk = "Ok"; private string localizedYes = "Yes", localizedNo = "No", localizedOk = "Ok";
private List<IWindow> mainWindows;
private PriorityQueue<PopupData, int> popupsToShow = new();
protected UiManager(IArea startArea) protected UiManager(IArea startArea)
{ {
if (Instance != null) if (Instance != null)
@ -54,10 +35,39 @@ namespace NEG.UI
Instance = this; Instance = this;
CurrentArea = startArea; CurrentArea = startArea;
mainWindows = new List<IWindow>();
}
public static UiManager Instance { get; protected set; }
/// <summary>
/// Current area shown on screen.
/// </summary>
public IArea CurrentArea
{
get => currentArea;
set
{
currentArea?.Close();
currentArea = value;
currentArea?.Open();
}
} }
/// <summary> /// <summary>
/// Show popup if there is non other currently shown. Otherwise add current popup to ordered queue and show it later. It will be closed after pressing ok button. /// Current window that is considered main (focused, lastly opened). Can be null.
/// </summary>
public IWindow CurrentMainWindow => mainWindows.LastOrDefault();
public PopupData CurrentPopup => currentShownPopup.data;
public virtual void Dispose() => Instance = null;
/// <summary>
/// Show popup if there is non other currently shown. Otherwise add current popup to ordered queue and show it later.
/// It will be closed after pressing ok button.
/// </summary> /// </summary>
/// <param name="title">popup title</param> /// <param name="title">popup title</param>
/// <param name="content">popup content</param> /// <param name="content">popup content</param>
@ -66,16 +76,18 @@ namespace NEG.UI
/// <param name="priority">priority of popup (lower number -> show first)</param> /// <param name="priority">priority of popup (lower number -> show first)</param>
/// <param name="forceShow">force show current popup only if currently shown has lower priority</param> /// <param name="forceShow">force show current popup only if currently shown has lower priority</param>
/// <returns>data for created popup, can be used to invalidate popup (will not show)</returns> /// <returns>data for created popup, can be used to invalidate popup (will not show)</returns>
public PopupData ShowOkPopup(string title, string content, string okText = null, Action okPressed = null, int priority = 0, bool forceShow = false) public PopupData ShowOkPopup(string title, string content, string okText = null, Action okPressed = null,
int priority = 0, bool forceShow = false)
{ {
var data = new DefaultPopupData(currentDefaultPopup, title, content, var data = new DefaultPopupData(currentDefaultPopup, title, content,
new List<(string, Action)>() { (okText ?? localizedOk, okPressed) }); new List<(string, Action)> { (okText ?? localizedOk, okPressed) });
ShowPopup(data, priority, forceShow); ShowPopup(data, priority, forceShow);
return data; return data;
} }
/// <summary> /// <summary>
/// Show popup if there is non other currently shown. Otherwise add current popup to ordered queue and show it later. It will be closed after pressing yes or no button. /// Show popup if there is non other currently shown. Otherwise add current popup to ordered queue and show it later.
/// It will be closed after pressing yes or no button.
/// </summary> /// </summary>
/// <param name="title">popup title</param> /// <param name="title">popup title</param>
/// <param name="content">popup content</param> /// <param name="content">popup content</param>
@ -86,16 +98,21 @@ namespace NEG.UI
/// <param name="priority">priority of popup (lower number -> show first)</param> /// <param name="priority">priority of popup (lower number -> show first)</param>
/// <param name="forceShow">force show current popup only if currently shown has lower priority</param> /// <param name="forceShow">force show current popup only if currently shown has lower priority</param>
/// <returns>data for created popup, can be used to invalidate popup (will not show)</returns> /// <returns>data for created popup, can be used to invalidate popup (will not show)</returns>
public PopupData ShowYesNoPopup(string title, string content, string yesText = null, string noText = null, Action yesPressed = null, Action noPressed = null, int priority = 0, bool forceShow = false) public PopupData ShowYesNoPopup(string title, string content, string yesText = null, string noText = null,
Action yesPressed = null, Action noPressed = null, int priority = 0, bool forceShow = false)
{ {
var data = new DefaultPopupData(currentDefaultPopup, title, content, var data = new DefaultPopupData(currentDefaultPopup, title, content,
new List<(string, Action)>() { (yesText ?? localizedYes, yesPressed), (noText ?? localizedNo, noPressed) }); new List<(string, Action)>
{
(yesText ?? localizedYes, yesPressed), (noText ?? localizedNo, noPressed)
});
ShowPopup(data, priority, forceShow); ShowPopup(data, priority, forceShow);
return data; return data;
} }
/// <summary> /// <summary>
/// Show popup if there is non other currently shown. Otherwise add current popup to ordered queue and show it later. It will be closed after pressing any button. /// Show popup if there is non other currently shown. Otherwise add current popup to ordered queue and show it later.
/// It will be closed after pressing any button.
/// </summary> /// </summary>
/// <param name="title">popup title</param> /// <param name="title">popup title</param>
/// <param name="content">popup content</param> /// <param name="content">popup content</param>
@ -103,15 +120,16 @@ namespace NEG.UI
/// <param name="priority">priority of popup (lower number -> show first)</param> /// <param name="priority">priority of popup (lower number -> show first)</param>
/// <param name="forceShow">force show current popup only if currently shown has lower priority</param> /// <param name="forceShow">force show current popup only if currently shown has lower priority</param>
/// <returns>data for created popup, can be used to invalidate popup (will not show)</returns> /// <returns>data for created popup, can be used to invalidate popup (will not show)</returns>
public PopupData ShowPopup(string title, string content, List<(string, Action)> actions, int priority = 0, bool forceShow = false) public PopupData ShowPopup(string title, string content, List<(string, Action)> actions, int priority = 0,
bool forceShow = false)
{ {
var data = new DefaultPopupData(currentDefaultPopup, title, content, actions); var data = new DefaultPopupData(currentDefaultPopup, title, content, actions);
ShowPopup(data, priority, forceShow); ShowPopup(data, priority, forceShow);
return data; return data;
} }
/// <summary> /// <summary>
/// Show popup if there is non other currently shown. Otherwise add current popup to ordered queue and show it later. /// Show popup if there is non other currently shown. Otherwise add current popup to ordered queue and show it later.
/// </summary> /// </summary>
/// <param name="data">popup data object</param> /// <param name="data">popup data object</param>
/// <param name="priority">priority of popup (lower number -> show first)</param> /// <param name="priority">priority of popup (lower number -> show first)</param>
@ -121,35 +139,72 @@ namespace NEG.UI
popupsToShow.Enqueue(data, priority); popupsToShow.Enqueue(data, priority);
UpdatePopupsState(forceShow, priority, data); UpdatePopupsState(forceShow, priority, data);
} }
public void UseBack()
{
IControllable.BackUsed backUsed = new();
CurrentMainWindow?.TryUseBack(ref backUsed);
if (backUsed.Used)
return;
CurrentArea.TryUseBack(ref backUsed);
}
public void RefreshPopups()
{
if (currentShownPopup.data is { IsValid: true })
return;
UpdatePopupsState(false);
}
public void SetMainWindow(IWindow window) => mainWindows.Add(window);
public void MainWindowClosed(IWindow window) => mainWindows.Remove(window);
public void OnWindowClosed(IWindow window) => MainWindowClosed(window);
//TODO: select new main window
protected void PopupClosed(PopupData data) protected void PopupClosed(PopupData data)
{ {
if (currentShownPopup.data != data) if (currentShownPopup.data != data)
{ //Debug.LogError("Popup was not shown");
Debug.LogError("Popup was not shown");
return; return;
}
UpdatePopupsState(false); UpdatePopupsState(false);
} }
protected void SetDefaultPopup(IDefaultPopup popup) => currentDefaultPopup = popup; protected void SetDefaultPopup(IDefaultPopup popup) => currentDefaultPopup = popup;
private void UpdatePopupsState(bool forceShow, int priority = 0, PopupData data = null)
protected virtual void UpdatePopupsState(bool forceShow, int priority = 0, PopupData data = null)
{ {
if (forceShow) if (forceShow)
{ {
if(currentShownPopup.priority <= priority) if (currentShownPopup.data != null && currentShownPopup.priority >= priority)
return; return;
popupsToShow.Enqueue(currentShownPopup.data, currentShownPopup.priority); popupsToShow.Enqueue(currentShownPopup.data, currentShownPopup.priority);
ShowPopup(data, priority); ShowPopup(data, priority);
return; return;
} }
if(!popupsToShow.TryDequeue(out var d, out int p))
return;
ShowPopup(d, p); while (popupsToShow.TryDequeue(out var d, out int p))
{
if (d == null)
continue;
if (!d.IsValid)
continue;
if (d == currentShownPopup.data)
continue;
ShowPopup(d, p);
return;
}
if (currentShownPopup.data == null)
return;
currentShownPopup.data.PopupClosedEvent -= PopupClosed;
currentShownPopup.data.Hide();
currentShownPopup.data = null;
} }
private void ShowPopup(PopupData data, int priority) private void ShowPopup(PopupData data, int priority)
@ -159,11 +214,10 @@ namespace NEG.UI
currentShownPopup.data.PopupClosedEvent -= PopupClosed; currentShownPopup.data.PopupClosedEvent -= PopupClosed;
currentShownPopup.data.Hide(); currentShownPopup.data.Hide();
} }
currentShownPopup = (data, priority); currentShownPopup = (data, priority);
data.Show(); data.Show();
data.PopupClosedEvent += PopupClosed; data.PopupClosedEvent += PopupClosed;
} }
} }
} }

View File

@ -0,0 +1,17 @@
using NEG.UI.UnityUi.Window;
using NEG.UI.Window;
using UnityEngine;
namespace NEG.UI.Area
{
public class AutoOpenWindowWhenNoOther : MonoBehaviour
{
[SerializeField] private MonoWindow window;
private void Start()
{
if (UiManager.Instance.CurrentMainWindow == null)
window.Open();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 473c065573984067a824ebf3b605c3ab
timeCreated: 1695048071

View File

@ -1,15 +1,14 @@
using NEG.UI.UnityUi.Window; using NEG.UI.UnityUi.Window;
using NEG.UI.Window; using NEG.UI.Window;
using System;
using UnityEngine; using UnityEngine;
namespace NEG.UI.Area namespace NEG.UI.Area
{ {
[Tooltip(tooltip: "Automatically open attached window on start")] [Tooltip("Automatically open attached window on start")]
public class AutoWindowOpen : MonoBehaviour public class AutoWindowOpen : MonoBehaviour
{ {
[SerializeField] private MonoWindow window; [SerializeField] private MonoWindow window;
private void Start() => window.Open(); private void Start() => window.Open();
} }
} }

View File

@ -0,0 +1,16 @@
using NEG.UI.UnityUi;
using NEG.UI.Window;
using NegUtils.NEG.UI;
namespace NEG.UI.Area
{
public class CloseMainWindowOnBack : MonoController
{
protected override void OnBackUsed(IControllable.BackUsed backUsed)
{
base.OnBackUsed(backUsed);
UiManager.Instance.CurrentMainWindow?.Close();
backUsed.Used = true;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6ec2bf64cda740a1849d024d4f163a01
timeCreated: 1686598066

View File

@ -1,30 +1,19 @@
using System.Collections.Generic; using NEG.UI.UnityUi.WindowSlot;
using UnityEngine;
using NEG.UI.Popup;
using NEG.UI.UnityUi.Window;
using NEG.UI.UnityUi.WindowSlot;
using NEG.UI.Window; using NEG.UI.Window;
using NEG.UI.WindowSlot; using NEG.UI.WindowSlot;
using NegUtils.NEG.UI;
using System; using System;
using System.Collections.Generic;
using UnityEngine;
namespace NEG.UI.Area namespace NEG.UI.Area
{ {
public class MonoArea : MonoBehaviour, IArea public class MonoArea : MonoBehaviour, IArea
{ {
public IEnumerable<IWindowSlot> AvailableSlots => windowSlots;
public IWindowSlot DefaultWindowSlot => windowSlots[0];
[SerializeField] private bool setAsDefaultArea; [SerializeField] private bool setAsDefaultArea;
[SerializeField] private List<MonoWindowSlot> windowSlots; [SerializeField] private List<MonoWindowSlot> windowSlots;
public IWindowSlot DefaultWindowSlot => windowSlots[0];
public virtual void SetEnabled(bool setEnabled) => gameObject.SetActive(setEnabled);
public virtual void OpenWindow(IWindow window, object data = null)
{
DefaultWindowSlot.AttachWindow(window);
window.SetData(data);
}
protected virtual void Awake() protected virtual void Awake()
{ {
@ -32,10 +21,40 @@ namespace NEG.UI.Area
UiManager.Instance.CurrentArea = this; UiManager.Instance.CurrentArea = this;
} }
protected virtual void OnDestroy() private void Start()
{ {
if (!setAsDefaultArea)
Close();
}
private void OnDestroy()
{
if (UiManager.Instance == null)
return;
if (ReferenceEquals(UiManager.Instance.CurrentArea, this)) if (ReferenceEquals(UiManager.Instance.CurrentArea, this))
UiManager.Instance.CurrentArea = null; UiManager.Instance.CurrentArea = null;
} }
public event Action<object> OnOpened;
public event Action OnClosed;
public event Action<IControllable.BackUsed> OnBackUsed;
public IEnumerable<IWindowSlot> AvailableSlots => windowSlots;
public void Open()
{
gameObject.SetActive(true);
OnOpened?.Invoke(null);
}
public void Close()
{
gameObject.SetActive(false);
OnClosed?.Invoke();
}
public void OpenWindow(IWindow window, object data = null) => DefaultWindowSlot.AttachWindow(window, data);
public void TryUseBack(ref IControllable.BackUsed backUsed) => OnBackUsed?.Invoke(backUsed);
} }
} }

View File

@ -1,3 +1,11 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 39eb59ca1ef60934abb3f0c64169be65 guid: 39eb59ca1ef60934abb3f0c64169be65
timeCreated: 1670707479 MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 10
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,78 +1,104 @@
using FMOD.Studio; using KBCore.Refs;
using FMODUnity; using NEG.UI.UnityUi.Buttons.Behaviours;
using NEG.UI.UnityUi.Buttons.Settings;
using System; using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems; using UnityEngine.EventSystems;
using UnityEngine.UI; using UnityEngine.UI;
namespace NEG.UI.UnityUi.Buttons namespace NEG.UI.UnityUi.Buttons
{ {
[RequireComponent(typeof(ButtonSerializeFields))] [DefaultExecutionOrder(-1)]
[RequireComponent(typeof(Button))]
public class BaseButton : MonoBehaviour, ISelectHandler, IDeselectHandler, IPointerEnterHandler, IPointerExitHandler public class BaseButton : MonoBehaviour, ISelectHandler, IDeselectHandler, IPointerEnterHandler, IPointerExitHandler
{ {
public event Action OnButtonPressed; public delegate void SelectionHandler(bool isSilent);
public bool Interactable { get => serializeFields.Button.interactable; set => serializeFields.Button.interactable = value; }
[SerializeField]
protected ButtonSerializeFields serializeFields;
private bool isHovered; [SerializeField] [Self(Flag.Optional)] private Button button;
public virtual void OnSelect(BaseEventData eventData) [SerializeField] [Child(Flag.Optional)]
{ private TMP_Text text;
if (serializeFields.Text)
serializeFields.Text.color = serializeFields.SelectedTextColor;
}
public void OnDeselect(BaseEventData eventData) [SerializeField] [Child(Flag.Optional)]
{ private Image icon;
if (serializeFields.Text)
serializeFields.Text.color = serializeFields.DeselectedTextColor;
}
public void OnPointerEnter(PointerEventData eventData) [SerializeField] private ButtonSettings groupButtonSettings;
{
isHovered = true;
if (serializeFields.Text)
serializeFields.Text.color = serializeFields.SelectedTextColor;
}
public void OnPointerExit(PointerEventData eventData) private readonly Dictionary<string, ButtonElementBehaviour> behaviours = new();
{
isHovered = false;
if (serializeFields.Text)
serializeFields.Text.color = serializeFields.DeselectedTextColor;
}
public void SetText(string text) public bool Interactable { get => button.interactable; set => button.interactable = value; }
{
if(serializeFields == null) public TMP_Text Text => text;
return;
if(serializeFields.Text == null)
return;
serializeFields.Text.text = text;
}
protected virtual void Awake() protected virtual void Awake()
{ {
if(serializeFields == null) button.onClick.AddListener(OnClicked);
serializeFields = GetComponent<ButtonSerializeFields>(); if (groupButtonSettings == null)
serializeFields.Button.onClick.AddListener(OnClicked); MonoUiManager.Instance.DefaultUiSettings.Apply(this);
OnDeselect(null); else
groupButtonSettings.Apply(this);
} }
private void OnValidate() private void Start() => OnDeselect(null);
private void OnValidate() => this.ValidateRefs();
public void OnDeselect(BaseEventData eventData) => OnDeselected?.Invoke(eventData is SilentEventData);
public void OnPointerEnter(PointerEventData eventData) => EventSystem.current.SetSelectedGameObject(gameObject);
public void OnPointerExit(PointerEventData eventData)
{ {
if(serializeFields == null) if (EventSystem.current.currentSelectedGameObject == gameObject)
serializeFields = GetComponent<ButtonSerializeFields>(); EventSystem.current.SetSelectedGameObject(null);
}
public virtual void OnSelect(BaseEventData eventData) => OnSelected?.Invoke(eventData is SilentEventData);
/// <summary>
/// is silent
/// </summary>
public event SelectionHandler OnSelected;
public event SelectionHandler OnDeselected;
public event Action OnButtonPressed;
public void SetText(string txt)
{
if (text == null)
return;
text.text = txt;
}
public void AddOrOverrideSetting(SettingData data)
{
if (behaviours.TryGetValue(data.Key, out var setting))
{
setting.ChangeData(data);
return;
}
behaviours.Add(data.Key, MonoUiManager.Instance.BehavioursFactory.CreateInstance(data.Key, this, data));
}
public void RemoveSetting(string key)
{
if (!behaviours.TryGetValue(key, out var setting))
{
Debug.LogError($"Behaviour with key {key} was not found");
return;
}
setting.Dispose();
behaviours.Remove(key);
} }
protected virtual void OnClicked() protected virtual void OnClicked()
{ {
OnDeselect(null); OnDeselect(null);
isHovered = false;
OnButtonPressed?.Invoke(); OnButtonPressed?.Invoke();
} }
} }
} }

View File

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

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 953c3353e3af44258625fe607ede632b
timeCreated: 1683915598

View File

@ -0,0 +1,21 @@
using NEG.UI.UnityUi.Buttons.Settings;
using System;
namespace NEG.UI.UnityUi.Buttons.Behaviours
{
public abstract class ButtonElementBehaviour : IDisposable
{
protected readonly BaseButton button;
protected SettingData baseData;
public ButtonElementBehaviour(BaseButton baseButton, SettingData settingData)
{
button = baseButton;
baseData = settingData;
}
public abstract void Dispose();
public virtual void ChangeData(SettingData newData) => baseData = newData;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a5e3decad6424cb288eff3e6f7e0d28e
timeCreated: 1683919740

View File

@ -0,0 +1,41 @@
using NEG.UI.UnityUi.Buttons.Settings;
using NEG.Utils;
using UnityEngine;
namespace NEG.UI.UnityUi.Buttons.Behaviours
{
public class ChangeTextColorBehaviour : ButtonElementBehaviour
{
private ColorData data;
public ChangeTextColorBehaviour(BaseButton baseButton, ColorData data) : base(baseButton, data)
{
if (baseButton.Text == null)
return;
baseButton.OnSelected += OnButtonSelected;
baseButton.OnDeselected += OnButtonDeselected;
ChangeData(data);
}
public override void ChangeData(SettingData newData)
{
base.ChangeData(newData);
Debug.Assert(newData is ColorData, "newData is not ColorData");
data = (ColorData)newData;
}
public override void Dispose()
{
button.OnSelected -= OnButtonSelected;
button.OnDeselected -= OnButtonDeselected;
}
[FactoryRegistration]
private static void RegisterInFactory() =>
MonoUiManager.Instance.BehavioursFactory.Register("ChangeTextColor", typeof(ChangeTextColorBehaviour));
private void OnButtonSelected(bool _) => button.Text.color = data.SelectedColor;
private void OnButtonDeselected(bool _) => button.Text.color = data.DeselectedColor;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f2079225d6e34001ae85f74a0a418d68
timeCreated: 1683919878

View File

@ -0,0 +1,21 @@
#if FMOD
namespace NEG.UI.UnityUi.Buttons.Behaviours
{
public class SimpleSoundBehaviour : ButtonElementBehaviour
{
public SimpleSoundBehaviour(BaseButton baseButton, FmodSoundData data) : base(baseButton, data)
{
//TODO: use silnet to not play sound
}
[FactoryRegistration]
private static void RegisterInFactory() =>
MonoUiManager.Instance.BehavioursFactory.Register("SimpleSound", typeof(SimpleSoundBehaviour));
public override void ChangeData(SettingData newData) => throw new System.NotImplementedException();
public override void Dispose() => throw new System.NotImplementedException();
}
}
#endif

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d75c0d86eeab47a1a6340f0b03b83de0
timeCreated: 1684002680

View File

@ -1,33 +0,0 @@
using FMODUnity;
using System;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace NEG.UI.UnityUi.Buttons
{
public class ButtonSerializeFields : MonoBehaviour
{
[field: SerializeField]
public Button Button { get; private set; }
[field: SerializeField]
public TMP_Text Text { get; private set; }
[field: SerializeField]
public Color SelectedTextColor { get; private set; }
[field: SerializeField]
public Color DeselectedTextColor { get; private set; }
[field: SerializeField]
public EventReference HoverEventRef { get; private set; }
[field: SerializeField]
public EventReference ClickEventRef { get; private set; }
private void OnValidate()
{
if(Button == null)
Button = GetComponent<Button>();
if (Text == null)
Text = GetComponentInChildren<TMP_Text>();
}
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 3f8c6cf4cf18463c86ec1165c61c79b2
timeCreated: 1670777232

View File

@ -1,26 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace NEG.UI.UnityUi.Buttons
{
[RequireComponent(typeof(BaseButton))]
public class ChangeSceneButton : MonoBehaviour
{
[Header("Leave empty to use int value")]
[SerializeField] private string sceneName;
[SerializeField] private int sceneIndex;
private void Awake() => GetComponent<BaseButton>().OnButtonPressed += OnClicked;
private void OnClicked()
{
if (string.IsNullOrEmpty(sceneName))
SceneManager.LoadScene(sceneIndex);
else
SceneManager.LoadScene(sceneName);
}
}
}

View File

@ -1,11 +0,0 @@
using UnityEngine;
namespace NEG.UI.UnityUi.Buttons
{
[RequireComponent(typeof(BaseButton))]
public class CloseAllWindows : MonoBehaviour
{
private void Awake() => GetComponent<BaseButton>().OnButtonPressed += OnClicked;
private void OnClicked() => UiManager.Instance.CurrentArea.CloseAllWindows();
}
}

View File

@ -8,7 +8,7 @@ namespace NEG.UI.UnityUi.Buttons
public class CloseWindowOnImageTouch : MonoBehaviour, IPointerDownHandler public class CloseWindowOnImageTouch : MonoBehaviour, IPointerDownHandler
{ {
[SerializeField] private MonoWindow windowToClose; [SerializeField] private MonoWindow windowToClose;
public void OnPointerDown(PointerEventData eventData) => windowToClose.Close(); public void OnPointerDown(PointerEventData eventData) => windowToClose.Close();
} }
} }

View File

@ -0,0 +1,64 @@
using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace NEG.UI.UnityUi.Buttons
{
public class CustomNavigationButton : Button
{
[SerializeField] [HideInInspector] private OverridableNavigation upOverride;
[SerializeField] private OverridableNavigation downOverride;
[SerializeField] private OverridableNavigation leftOverride;
[SerializeField] private OverridableNavigation rightOverride;
public override void OnMove(AxisEventData eventData)
{
switch (eventData.moveDir)
{
case MoveDirection.Left:
if (TryNavigate(eventData, leftOverride))
return;
break;
case MoveDirection.Up:
if (TryNavigate(eventData, upOverride))
return;
break;
case MoveDirection.Right:
if (TryNavigate(eventData, rightOverride))
return;
break;
case MoveDirection.Down:
if (TryNavigate(eventData, downOverride))
return;
break;
case MoveDirection.None:
break;
default:
throw new ArgumentOutOfRangeException();
}
base.OnMove(eventData);
}
public static bool TryNavigate(BaseEventData eventData, OverridableNavigation overrideNavigation)
{
if (!overrideNavigation.Override)
return false;
if (overrideNavigation.Selectable == null || !overrideNavigation.Selectable.IsActive())
return true;
eventData.selectedObject = overrideNavigation.Selectable.gameObject;
return true;
}
}
[Serializable]
public class OverridableNavigation
{
[field: SerializeField] public bool Override { get; private set; }
[field: SerializeField] public Selectable Selectable { get; private set; }
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d9b5ca8863c240f792232d6e276d8d56
timeCreated: 1684520970

View File

@ -1,21 +0,0 @@
using NEG.UI.UnityUi.Window;
using NEG.UI.UnityUi.WindowSlot;
using System;
using UnityEngine;
using NEG.UI.Window;
using NEG.UI.WindowSlot;
namespace NEG.UI.UnityUi.Buttons
{
[RequireComponent(typeof(BaseButton))]
public class OpenWindow : MonoBehaviour
{
[SerializeField] private MonoWindow window;
[Header("Open on default area slot if empty")]
[SerializeField] private MonoWindowSlot slot;
private void Awake() => GetComponent<BaseButton>().OnButtonPressed += OnClicked;
private void OnClicked() => window.Open(slot);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ccaf0d2f63be41f6956471dcd9c210d9
timeCreated: 1709465582

View File

@ -0,0 +1,19 @@
using KBCore.Refs;
using UnityEngine;
namespace NEG.UI.UnityUi.Buttons
{
[RequireComponent(typeof(BaseButton))]
public abstract class ButtonReaction : MonoBehaviour
{
[SerializeField] [Self(Flag.Optional)] protected BaseButton button;
protected virtual void Awake() => button.OnButtonPressed += OnClicked;
protected virtual void OnDestroy() => button.OnButtonPressed -= OnClicked;
private void OnValidate() => this.ValidateRefs();
protected abstract void OnClicked();
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a9761128a04b49c2a26eddfabe70331f
timeCreated: 1675707257

View File

@ -0,0 +1,22 @@
using UnityEngine;
using UnityEngine.SceneManagement;
namespace NEG.UI.UnityUi.Buttons.Reactions
{
[RequireComponent(typeof(BaseButton))]
public class ChangeScene : ButtonReaction
{
[Header("Leave empty to use int value")] [SerializeField]
private string sceneName;
[SerializeField] private int sceneIndex;
protected override void OnClicked()
{
if (string.IsNullOrEmpty(sceneName))
SceneManager.LoadScene(sceneIndex);
else
SceneManager.LoadScene(sceneName);
}
}
}

View File

@ -0,0 +1,7 @@
namespace NEG.UI.UnityUi.Buttons.Reactions
{
public class CloseAllWindows : ButtonReaction
{
protected override void OnClicked() => UiManager.Instance.CurrentArea.CloseAllWindows();
}
}

View File

@ -1,23 +1,21 @@
using NEG.UI.UnityUi.Window; using NEG.UI.UnityUi.Window;
using NEG.UI.Window; using NEG.UI.Window;
using System;
using UnityEngine; using UnityEngine;
namespace NEG.UI.UnityUi.Buttons namespace NEG.UI.UnityUi.Buttons.Reactions
{ {
[RequireComponent(typeof(BaseButton))] [RequireComponent(typeof(BaseButton))]
public class CloseWindow : MonoBehaviour public class CloseWindow : ButtonReaction
{ {
[SerializeField] private MonoWindow windowToClose; [SerializeField] private MonoWindow windowToClose;
private void Awake() => GetComponent<BaseButton>().OnButtonPressed += OnClicked;
private void OnClicked() => windowToClose.Close();
private void OnValidate() private void OnValidate()
{ {
if(windowToClose != null) if (windowToClose != null)
return; return;
windowToClose = GetComponentInParent<MonoWindow>(); windowToClose = GetComponentInParent<MonoWindow>();
} }
protected override void OnClicked() => windowToClose.Close();
} }
} }

View File

@ -0,0 +1,16 @@
using UnityEditor;
using UnityEngine;
namespace NEG.UI.UnityUi.Buttons.Reactions
{
public class ExitGame : ButtonReaction
{
protected override void OnClicked()
{
#if UNITY_EDITOR
EditorApplication.isPlaying = false;
#endif
Application.Quit();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 185f765a5bf7487ab85a7d95fc0ef2c7
timeCreated: 1709473462

View File

@ -0,0 +1,13 @@
using NEG.UI.UnityUi.Window;
using NEG.UI.Window;
using UnityEngine;
namespace NEG.UI.UnityUi.Buttons.Reactions
{
public class OpenAsCurrentMainChild : ButtonReaction
{
[SerializeField] private MonoWindow windowToOpen;
protected override void OnClicked() => UiManager.Instance.CurrentMainWindow.OpenAsChild(windowToOpen);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 049e222140c94fc28fb36bca4aaddba4
timeCreated: 1686595194

View File

@ -0,0 +1,18 @@
using NEG.UI.UnityUi.Window;
using NEG.UI.UnityUi.WindowSlot;
using NEG.UI.Window;
using UnityEngine;
namespace NEG.UI.UnityUi.Buttons.Reactions
{
[RequireComponent(typeof(BaseButton))]
public class OpenWindow : ButtonReaction
{
[SerializeField] private MonoWindow window;
[Header("Open on default area slot if empty")] [SerializeField]
private MonoWindowSlot slot;
protected override void OnClicked() => window.Open(slot);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d25aba738e174616bcab9bf2d52a3ed1
timeCreated: 1683398272

View File

@ -0,0 +1,23 @@
using System.Collections.Generic;
using UnityEngine;
namespace NEG.UI.UnityUi.Buttons.Settings
{
public class ButtonSettings : MonoBehaviour
{
[SerializeField] private List<SettingData> settingDatas = new();
public void Apply(BaseButton button)
{
foreach (var setting in settingDatas) setting.Apply(button);
}
[ContextMenu("Refresh")]
public void Refresh()
{
settingDatas.Clear();
var components = GetComponents<SettingData>();
foreach (var data in components) settingDatas.Add(data);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b5292008faae496ab9028ad1faa0a3ba
timeCreated: 1683398713

View File

@ -0,0 +1,10 @@
using UnityEngine;
namespace NEG.UI.UnityUi.Buttons.Settings
{
public class ColorData : SettingData
{
[field: SerializeField] public Color SelectedColor { get; private set; } = Color.black;
[field: SerializeField] public Color DeselectedColor { get; private set; } = Color.black;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cec5286cd31b4819981e244b1adb977e
timeCreated: 1684001181

View File

@ -0,0 +1,14 @@
#if FMOD
using FMODUnity;
using UnityEngine;
namespace NEG.UI.UnityUi.Buttons.Settings
{
public class FmodSoundData : SettingData
{
[field: SerializeField] public EventReference SelectedSound { get; private set; }
[field: SerializeField] public EventReference ClickedSound { get; private set; }
}
}
#endif

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8e6a7b10c07d40408ee9492c931e3ec9
timeCreated: 1684001979

View File

@ -0,0 +1,7 @@
namespace NEG.UI.UnityUi.Buttons.Settings
{
public class RemoveFeature : SettingData
{
public override void Apply(BaseButton button) => button.RemoveSetting(Key);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3b44cdc2e0164ebdb8f6da348d653e77
timeCreated: 1684001264

View File

@ -0,0 +1,26 @@
using KBCore.Refs;
using UnityEngine;
namespace NEG.UI.UnityUi.Buttons.Settings
{
public abstract class SettingData : MonoBehaviour
{
[field: SerializeField] public string Key { get; private set; }
[SerializeField] [Self(Flag.Optional)] private BaseButton attachedButton;
private void Awake()
{
if (attachedButton != null)
Apply(attachedButton);
}
private void OnValidate()
{
this.ValidateRefs();
if (attachedButton == null && TryGetComponent(out ButtonSettings settings))
settings.Refresh();
}
public virtual void Apply(BaseButton button) => button.AddOrOverrideSetting(this);
}
}

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