Merge branch 'neg-ui' into 'main'
Neg ui See merge request negames/NegUtils!5
This commit is contained in:
		
						commit
						c106c41ca1
					
				
							
								
								
									
										30
									
								
								Editor/ComponentsAdditionalItems/CanvasScalerDefault.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								Editor/ComponentsAdditionalItems/CanvasScalerDefault.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| using UnityEditor; | ||||
| using UnityEngine; | ||||
| using UnityEngine.UI; | ||||
| 
 | ||||
| namespace NEG.Utils.Editor.ComponentsAdditionalItems | ||||
| { | ||||
|     public static class CanvasScalerDefault | ||||
|     { | ||||
|         [MenuItem("CONTEXT/CanvasScaler/Full HD horizontal", false, 2000)] | ||||
|         public static void SetFullHdHorizontal(MenuCommand command) => SetComponent(command, 1920, 1080); | ||||
|         [MenuItem("CONTEXT/CanvasScaler/Full HD vertical", false, 2000)] | ||||
|         public static void SetFullHdVertical(MenuCommand command) => SetComponent(command, 1080, 1920); | ||||
|         [MenuItem("CONTEXT/CanvasScaler/Full 2k horizontal", false, 2000)] | ||||
|         public static void Set2KHorizontal(MenuCommand command) => SetComponent(command, 2560, 1440 ); | ||||
|         [MenuItem("CONTEXT/CanvasScaler/Full 2k vertical", false, 2000)] | ||||
|         public static void Set2KVertical(MenuCommand command) => SetComponent(command, 1440, 2560); | ||||
|         [MenuItem("CONTEXT/CanvasScaler/Full 4k horizontal", false, 2000)] | ||||
|         public static void Set4KHorizontal(MenuCommand command) => SetComponent(command, 3840, 2160); | ||||
|         [MenuItem("CONTEXT/CanvasScaler/Full 4k vertical", false, 2000)] | ||||
|         public static void Set4KVertical(MenuCommand command) => SetComponent(command, 2160, 3840); | ||||
| 
 | ||||
|         private static void SetComponent(MenuCommand command, int width, int height) | ||||
|         { | ||||
|             var scaler = (CanvasScaler)command.context; | ||||
|             scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; | ||||
|             scaler.matchWidthOrHeight = width > height ? 1f : 0f; | ||||
|             scaler.referenceResolution = new Vector2(width, height); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										11
									
								
								Editor/ComponentsAdditionalItems/CanvasScalerDefault.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								Editor/ComponentsAdditionalItems/CanvasScalerDefault.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: c7ddebddb1a1c1947be05ac9e96aceb8 | ||||
| MonoImporter: | ||||
|   externalObjects: {} | ||||
|   serializedVersion: 2 | ||||
|   defaultReferences: [] | ||||
|   executionOrder: 0 | ||||
|   icon: {instanceID: 0} | ||||
|   userData:  | ||||
|   assetBundleName:  | ||||
|   assetBundleVariant:  | ||||
							
								
								
									
										18
									
								
								Editor/NEG.Utils.Editor.asmdef
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								Editor/NEG.Utils.Editor.asmdef
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| { | ||||
|     "name": "NEG.Utils.Editor", | ||||
|     "rootNamespace": "", | ||||
|     "references": [ | ||||
|         "GUID:3c4294719a93e3c4e831a9ff0c261e8a" | ||||
|     ], | ||||
|     "includePlatforms": [ | ||||
|         "Editor" | ||||
|     ], | ||||
|     "excludePlatforms": [], | ||||
|     "allowUnsafeCode": false, | ||||
|     "overrideReferences": false, | ||||
|     "precompiledReferences": [], | ||||
|     "autoReferenced": true, | ||||
|     "defineConstraints": [], | ||||
|     "versionDefines": [], | ||||
|     "noEngineReferences": false | ||||
| } | ||||
							
								
								
									
										7
									
								
								Editor/NEG.Utils.Editor.asmdef.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Editor/NEG.Utils.Editor.asmdef.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 5928dc8d9173fd348aa77d4593ca3fd8 | ||||
| AssemblyDefinitionImporter: | ||||
|   externalObjects: {} | ||||
|   userData:  | ||||
|   assetBundleName:  | ||||
|   assetBundleVariant:  | ||||
							
								
								
									
										3
									
								
								NEG.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 61eeed9106e147d8a76d7f0140d3571d | ||||
| timeCreated: 1670708950 | ||||
							
								
								
									
										3
									
								
								NEG/UI.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: bbdebf147b9a40b0bc94b6f710c7aa6b | ||||
| timeCreated: 1670690396 | ||||
							
								
								
									
										3
									
								
								NEG/UI/Area.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/Area.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 853f6a7d0f224278afbb5457d0fb8bde | ||||
| timeCreated: 1670706939 | ||||
							
								
								
									
										9
									
								
								NEG/UI/Area/IArea.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								NEG/UI/Area/IArea.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| using NEG.UI.WindowSlot; | ||||
| 
 | ||||
| namespace NEG.UI.Area | ||||
| { | ||||
|     public interface IArea : ISlotsHolder, IUiElement | ||||
|     { | ||||
|          | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/Area/IArea.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/Area/IArea.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: f7cf5ef3a347e1c4b98411f4d564b988 | ||||
| timeCreated: 1670690282 | ||||
							
								
								
									
										11
									
								
								NEG/UI/IUiElement.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								NEG/UI/IUiElement.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| namespace NEG.UI | ||||
| { | ||||
|     public interface IUiElement | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Sets only visible state of element | ||||
|         /// </summary> | ||||
|         /// <param name="setEnabled"></param> | ||||
|         void SetEnabled(bool setEnabled); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/IUiElement.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/IUiElement.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 296bf6969a6347f8aea788a7bdd086af | ||||
| timeCreated: 1670693177 | ||||
							
								
								
									
										14
									
								
								NEG/UI/NEG.UI.asmdef
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								NEG/UI/NEG.UI.asmdef
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| { | ||||
|     "name": "NEG.UI", | ||||
|     "rootNamespace": "", | ||||
|     "references": [], | ||||
|     "includePlatforms": [], | ||||
|     "excludePlatforms": [], | ||||
|     "allowUnsafeCode": false, | ||||
|     "overrideReferences": false, | ||||
|     "precompiledReferences": [], | ||||
|     "autoReferenced": true, | ||||
|     "defineConstraints": [], | ||||
|     "versionDefines": [], | ||||
|     "noEngineReferences": false | ||||
| } | ||||
							
								
								
									
										7
									
								
								NEG/UI/NEG.UI.asmdef.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								NEG/UI/NEG.UI.asmdef.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 7361f1d9c43da6649923760766194746 | ||||
| AssemblyDefinitionImporter: | ||||
|   externalObjects: {} | ||||
|   userData:  | ||||
|   assetBundleName:  | ||||
|   assetBundleVariant:  | ||||
							
								
								
									
										3
									
								
								NEG/UI/Popup.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/Popup.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 76fc21263637443ca8268859d4cb5378 | ||||
| timeCreated: 1670707809 | ||||
							
								
								
									
										28
									
								
								NEG/UI/Popup/DefaultPopupData.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								NEG/UI/Popup/DefaultPopupData.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace NEG.UI.Popup | ||||
| { | ||||
|     public class DefaultPopupData : PopupData | ||||
|     { | ||||
|         private readonly IDefaultPopup defaultPopup; | ||||
| 
 | ||||
|         private readonly string title; | ||||
|         private readonly string content; | ||||
|         private readonly List<(string, Action)> options; | ||||
| 
 | ||||
|         public DefaultPopupData(IDefaultPopup popup, string title, string content, List<(string, Action)> options) : base(popup) | ||||
|         { | ||||
|             defaultPopup = popup; | ||||
|             this.title = title; | ||||
|             this.content = content; | ||||
|             this.options = options; | ||||
|         } | ||||
| 
 | ||||
|         public override void Show() | ||||
|         { | ||||
|             defaultPopup.SetContent(title, content, options); | ||||
|             base.Show(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/Popup/DefaultPopupData.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/Popup/DefaultPopupData.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 372c6df9ec044cb3adc86c7776b2ef61 | ||||
| timeCreated: 1672432934 | ||||
							
								
								
									
										16
									
								
								NEG/UI/Popup/IDefaultPopup.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								NEG/UI/Popup/IDefaultPopup.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace NEG.UI.Popup | ||||
| { | ||||
|     public interface IDefaultPopup : IPopup | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Sets content based on provided data. | ||||
|         /// </summary> | ||||
|         /// <param name="title">popup title</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> | ||||
|         public void SetContent(string title, string content, List<(string name, Action action)> options); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/Popup/IDefaultPopup.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/Popup/IDefaultPopup.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 0a6d0871ada44d1d95bea6c8e8701769 | ||||
| timeCreated: 1672153906 | ||||
							
								
								
									
										26
									
								
								NEG/UI/Popup/IPopup.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								NEG/UI/Popup/IPopup.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| using JetBrains.Annotations; | ||||
| using System; | ||||
| 
 | ||||
| namespace NEG.UI.Popup | ||||
| { | ||||
|     [PublicAPI] | ||||
|     public interface IPopup | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Event to fire when popup is closed | ||||
|         /// </summary> | ||||
|         event Action<PopupData> OnPopupClosed; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Show popup | ||||
|         /// </summary> | ||||
|         /// <param name="data">data assigned to popup, used to give info that popup is closed</param> | ||||
|         public void Show(PopupData data); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Close popup or mark as closed if not visible | ||||
|         /// </summary> | ||||
|         /// <param name="silent">if true hide visually, without firing callbacks to properly close</param> | ||||
|         void Close(bool silent = false); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/Popup/IPopup.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/Popup/IPopup.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 79767831e4324605974f3bb0bb5026fb | ||||
| timeCreated: 1670692499 | ||||
							
								
								
									
										50
									
								
								NEG/UI/Popup/PopupData.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								NEG/UI/Popup/PopupData.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | ||||
| using JetBrains.Annotations; | ||||
| using System; | ||||
| 
 | ||||
| namespace NEG.UI.Popup | ||||
| { | ||||
|     [PublicAPI] | ||||
|     public class PopupData | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Event that is fired on closing popup. | ||||
|         /// </summary> | ||||
|         public event Action<PopupData> PopupClosedEvent | ||||
|         { | ||||
|             add => popup.OnPopupClosed += value; | ||||
|             remove => popup.OnPopupClosed -= value; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Is this data is still valid. If set to false, popup will not show. | ||||
|         /// </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> | ||||
|         public virtual void Show() => popup.Show(this); | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Hide popup. Close visuals without firing events; | ||||
|         /// </summary> | ||||
|         public virtual void Hide() => popup.Close(true); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Invalidate popup, <see cref="UiManager"/> will automatically skip this popup | ||||
|         /// </summary> | ||||
|         public virtual void Invalidate() => IsValid = false; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/Popup/PopupData.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/Popup/PopupData.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: e6e5ebb367aa4dfba5e5f853c9b31a3d | ||||
| timeCreated: 1672430446 | ||||
							
								
								
									
										999
									
								
								NEG/UI/PriorityQueue.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										999
									
								
								NEG/UI/PriorityQueue.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,999 @@ | ||||
| #nullable enable | ||||
| using System.Diagnostics; | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
| using System.Runtime.CompilerServices; | ||||
| 
 | ||||
| namespace System.Collections.Generic | ||||
| { | ||||
| // Licensed to the .NET Foundation under one or more agreements. | ||||
| // The .NET Foundation licenses this file to you under the MIT license. | ||||
| 
 | ||||
| // ported from: | ||||
| // https://github.com/dotnet/runtime/blob/main/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs | ||||
|     internal sealed class PriorityQueueDebugView<TElement, TPriority> | ||||
|     { | ||||
|         private readonly PriorityQueue<TElement, TPriority> _queue; | ||||
|         private readonly bool _sort; | ||||
| 
 | ||||
|         public PriorityQueueDebugView(PriorityQueue<TElement, TPriority> queue) | ||||
|         { | ||||
|             ArgumentNullException.ThrowIfNull(queue); | ||||
| 
 | ||||
|             _queue = queue; | ||||
|             _sort = true; | ||||
|         } | ||||
| 
 | ||||
|         public PriorityQueueDebugView(PriorityQueue<TElement, TPriority>.UnorderedItemsCollection collection) | ||||
|         { | ||||
|             _queue = collection?._queue ?? throw new System.ArgumentNullException(nameof(collection)); | ||||
|         } | ||||
| 
 | ||||
|         [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] | ||||
|         public (TElement Element, TPriority Priority)[] Items | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 List<(TElement Element, TPriority Priority)> list = new(_queue.UnorderedItems); | ||||
|                 if (_sort) list.Sort((i1, i2) => _queue.Comparer.Compare(i1.Priority, i2.Priority)); | ||||
| 
 | ||||
|                 return list.ToArray(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     [SuppressMessage("ReSharper", "InconsistentNaming")] | ||||
|     internal static class SR | ||||
|     { | ||||
|         internal const string ArgumentOutOfRange_NeedNonNegNum = "Non-negative number required."; | ||||
|         internal const string ArgumentOutOfRange_IndexMustBeLessOrEqual = "Index must be less or equal"; | ||||
|         internal const string InvalidOperation_EmptyQueue = "The queue is empty."; | ||||
|         internal const string InvalidOperation_EnumFailedVersion = "Collection modified while iterating over it."; | ||||
|         internal const string Arg_NonZeroLowerBound = "Non-zero lower bound required."; | ||||
|         internal const string Arg_RankMultiDimNotSupported = "Multi-dimensional arrays not supported."; | ||||
|         internal const string Argument_InvalidArrayType = "Invalid array type."; | ||||
|         internal const string Argument_InvalidOffLen = "Invalid offset or length."; | ||||
|     } | ||||
| 
 | ||||
|     internal static class ArgumentNullException | ||||
|     { | ||||
|         public static void ThrowIfNull(object o) | ||||
|         { | ||||
|             if (o == null) | ||||
|                 throw new System.ArgumentNullException(); // hard to do it differently without C# 10's features | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     internal static class ArrayEx | ||||
|     { | ||||
|         internal const int MaxLength = int.MaxValue; | ||||
|     } | ||||
| 
 | ||||
|     /// <summary> | ||||
|     ///     Internal helper functions for working with enumerables. | ||||
|     /// </summary> | ||||
|     internal static class EnumerableHelpers | ||||
|     { | ||||
|         /// <summary>Converts an enumerable to an array using the same logic as List{T}.</summary> | ||||
|         /// <param name="source">The enumerable to convert.</param> | ||||
|         /// <param name="length">The number of items stored in the resulting array, 0-indexed.</param> | ||||
|         /// <returns> | ||||
|         ///     The resulting array.  The length of the array may be greater than <paramref name="length" />, | ||||
|         ///     which is the actual number of elements in the array. | ||||
|         /// </returns> | ||||
|         internal static T[] ToArray<T>(IEnumerable<T> source, out int length) | ||||
|         { | ||||
|             if (source is ICollection<T> ic) | ||||
|             { | ||||
|                 int count = ic.Count; | ||||
|                 if (count != 0) | ||||
|                 { | ||||
|                     // Allocate an array of the desired size, then copy the elements into it. Note that this has the same | ||||
|                     // issue regarding concurrency as other existing collections like List<T>. If the collection size | ||||
|                     // concurrently changes between the array allocation and the CopyTo, we could end up either getting an | ||||
|                     // exception from overrunning the array (if the size went up) or we could end up not filling as many | ||||
|                     // items as 'count' suggests (if the size went down).  This is only an issue for concurrent collections | ||||
|                     // that implement ICollection<T>, which as of .NET 4.6 is just ConcurrentDictionary<TKey, TValue>. | ||||
|                     var arr = new T[count]; | ||||
|                     ic.CopyTo(arr, 0); | ||||
|                     length = count; | ||||
|                     return arr; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 using (var en = source.GetEnumerator()) | ||||
|                 { | ||||
|                     if (en.MoveNext()) | ||||
|                     { | ||||
|                         const int DefaultCapacity = 4; | ||||
|                         var arr = new T[DefaultCapacity]; | ||||
|                         arr[0] = en.Current; | ||||
|                         int count = 1; | ||||
| 
 | ||||
|                         while (en.MoveNext()) | ||||
|                         { | ||||
|                             if (count == arr.Length) | ||||
|                             { | ||||
|                                 // This is the same growth logic as in List<T>: | ||||
|                                 // If the array is currently empty, we make it a default size.  Otherwise, we attempt to | ||||
|                                 // double the size of the array.  Doubling will overflow once the size of the array reaches | ||||
|                                 // 2^30, since doubling to 2^31 is 1 larger than Int32.MaxValue.  In that case, we instead | ||||
|                                 // constrain the length to be Array.MaxLength (this overflow check works because of the | ||||
|                                 // cast to uint). | ||||
|                                 int newLength = count << 1; | ||||
|                                 if ((uint)newLength > ArrayEx.MaxLength) | ||||
|                                     newLength = ArrayEx.MaxLength <= count ? count + 1 : ArrayEx.MaxLength; | ||||
| 
 | ||||
|                                 Array.Resize(ref arr, newLength); | ||||
|                             } | ||||
| 
 | ||||
|                             arr[count++] = en.Current; | ||||
|                         } | ||||
| 
 | ||||
|                         length = count; | ||||
|                         return arr; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             length = 0; | ||||
|             return Array.Empty<T>(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// <summary> | ||||
|     ///     Represents a min priority queue. | ||||
|     /// </summary> | ||||
|     /// <typeparam name="TElement">Specifies the type of elements in the queue.</typeparam> | ||||
|     /// <typeparam name="TPriority">Specifies the type of priority associated with enqueued elements.</typeparam> | ||||
|     /// <remarks> | ||||
|     ///     Implements an array-backed quaternary min-heap. Each element is enqueued with an associated priority | ||||
|     ///     that determines the dequeue order: elements with the lowest priority get dequeued first. | ||||
|     /// </remarks> | ||||
|     [DebuggerDisplay("Count = {Count}")] | ||||
|     [DebuggerTypeProxy(typeof(PriorityQueueDebugView<,>))] | ||||
|     public class PriorityQueue<TElement, TPriority> | ||||
|     { | ||||
|         /// <summary> | ||||
|         ///     Specifies the arity of the d-ary heap, which here is quaternary. | ||||
|         ///     It is assumed that this value is a power of 2. | ||||
|         /// </summary> | ||||
|         private const int Arity = 4; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     The binary logarithm of <see cref="Arity" />. | ||||
|         /// </summary> | ||||
|         private const int Log2Arity = 2; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Custom comparer used to order the heap. | ||||
|         /// </summary> | ||||
|         private readonly IComparer<TPriority>? _comparer; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Represents an implicit heap-ordered complete d-ary tree, stored as an array. | ||||
|         /// </summary> | ||||
|         private (TElement Element, TPriority Priority)[] _nodes; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     The number of nodes in the heap. | ||||
|         /// </summary> | ||||
|         private int _size; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Lazily-initialized collection used to expose the contents of the queue. | ||||
|         /// </summary> | ||||
|         private UnorderedItemsCollection? _unorderedItems; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Version updated on mutation to help validate enumerators operate on a consistent state. | ||||
|         /// </summary> | ||||
|         private int _version; | ||||
| 
 | ||||
| #if DEBUG | ||||
|         static PriorityQueue() | ||||
|         { | ||||
|             Debug.Assert(Log2Arity > 0 && Math.Pow(2, Log2Arity) == Arity); | ||||
|         } | ||||
| #endif | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Initializes a new instance of the <see cref="PriorityQueue{TElement, TPriority}" /> class. | ||||
|         /// </summary> | ||||
|         public PriorityQueue() | ||||
|         { | ||||
|             _nodes = Array.Empty<(TElement, TPriority)>(); | ||||
|             _comparer = InitializeComparer(null); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Initializes a new instance of the <see cref="PriorityQueue{TElement, TPriority}" /> class | ||||
|         ///     with the specified initial capacity. | ||||
|         /// </summary> | ||||
|         /// <param name="initialCapacity">Initial capacity to allocate in the underlying heap array.</param> | ||||
|         /// <exception cref="ArgumentOutOfRangeException"> | ||||
|         ///     The specified <paramref name="initialCapacity" /> was negative. | ||||
|         /// </exception> | ||||
|         public PriorityQueue(int initialCapacity) | ||||
|             : this(initialCapacity, null) | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Initializes a new instance of the <see cref="PriorityQueue{TElement, TPriority}" /> class | ||||
|         ///     with the specified custom priority comparer. | ||||
|         /// </summary> | ||||
|         /// <param name="comparer"> | ||||
|         ///     Custom comparer dictating the ordering of elements. | ||||
|         ///     Uses <see cref="Comparer{T}.Default" /> if the argument is <see langword="null" />. | ||||
|         /// </param> | ||||
|         public PriorityQueue(IComparer<TPriority>? comparer) | ||||
|         { | ||||
|             _nodes = Array.Empty<(TElement, TPriority)>(); | ||||
|             _comparer = InitializeComparer(comparer); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Initializes a new instance of the <see cref="PriorityQueue{TElement, TPriority}" /> class | ||||
|         ///     with the specified initial capacity and custom priority comparer. | ||||
|         /// </summary> | ||||
|         /// <param name="initialCapacity">Initial capacity to allocate in the underlying heap array.</param> | ||||
|         /// <param name="comparer"> | ||||
|         ///     Custom comparer dictating the ordering of elements. | ||||
|         ///     Uses <see cref="Comparer{T}.Default" /> if the argument is <see langword="null" />. | ||||
|         /// </param> | ||||
|         /// <exception cref="ArgumentOutOfRangeException"> | ||||
|         ///     The specified <paramref name="initialCapacity" /> was negative. | ||||
|         /// </exception> | ||||
|         public PriorityQueue(int initialCapacity, IComparer<TPriority>? comparer) | ||||
|         { | ||||
|             if (initialCapacity < 0) | ||||
|                 throw new ArgumentOutOfRangeException( | ||||
|                     nameof(initialCapacity), initialCapacity, SR.ArgumentOutOfRange_NeedNonNegNum); | ||||
| 
 | ||||
|             _nodes = new (TElement, TPriority)[initialCapacity]; | ||||
|             _comparer = InitializeComparer(comparer); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Initializes a new instance of the <see cref="PriorityQueue{TElement, TPriority}" /> class | ||||
|         ///     that is populated with the specified elements and priorities. | ||||
|         /// </summary> | ||||
|         /// <param name="items">The pairs of elements and priorities with which to populate the queue.</param> | ||||
|         /// <exception cref="ArgumentNullException"> | ||||
|         ///     The specified <paramref name="items" /> argument was <see langword="null" />. | ||||
|         /// </exception> | ||||
|         /// <remarks> | ||||
|         ///     Constructs the heap using a heapify operation, | ||||
|         ///     which is generally faster than enqueuing individual elements sequentially. | ||||
|         /// </remarks> | ||||
|         public PriorityQueue(IEnumerable<(TElement Element, TPriority Priority)> items) | ||||
|             : this(items, null) | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Initializes a new instance of the <see cref="PriorityQueue{TElement, TPriority}" /> class | ||||
|         ///     that is populated with the specified elements and priorities, | ||||
|         ///     and with the specified custom priority comparer. | ||||
|         /// </summary> | ||||
|         /// <param name="items">The pairs of elements and priorities with which to populate the queue.</param> | ||||
|         /// <param name="comparer"> | ||||
|         ///     Custom comparer dictating the ordering of elements. | ||||
|         ///     Uses <see cref="Comparer{T}.Default" /> if the argument is <see langword="null" />. | ||||
|         /// </param> | ||||
|         /// <exception cref="ArgumentNullException"> | ||||
|         ///     The specified <paramref name="items" /> argument was <see langword="null" />. | ||||
|         /// </exception> | ||||
|         /// <remarks> | ||||
|         ///     Constructs the heap using a heapify operation, | ||||
|         ///     which is generally faster than enqueuing individual elements sequentially. | ||||
|         /// </remarks> | ||||
|         public PriorityQueue(IEnumerable<(TElement Element, TPriority Priority)> items, IComparer<TPriority>? comparer) | ||||
|         { | ||||
|             ArgumentNullException.ThrowIfNull(items); | ||||
| 
 | ||||
|             _nodes = EnumerableHelpers.ToArray(items, out _size); | ||||
|             _comparer = InitializeComparer(comparer); | ||||
| 
 | ||||
|             if (_size > 1) Heapify(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Gets the number of elements contained in the <see cref="PriorityQueue{TElement, TPriority}" />. | ||||
|         /// </summary> | ||||
|         public int Count => _size; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Gets the priority comparer used by the <see cref="PriorityQueue{TElement, TPriority}" />. | ||||
|         /// </summary> | ||||
|         public IComparer<TPriority> Comparer => _comparer ?? Comparer<TPriority>.Default; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Gets a collection that enumerates the elements of the queue in an unordered manner. | ||||
|         /// </summary> | ||||
|         /// <remarks> | ||||
|         ///     The enumeration does not order items by priority, since that would require N * log(N) time and N space. | ||||
|         ///     Items are instead enumerated following the internal array heap layout. | ||||
|         /// </remarks> | ||||
|         public UnorderedItemsCollection UnorderedItems => _unorderedItems ??= new UnorderedItemsCollection(this); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Adds the specified element with associated priority to the <see cref="PriorityQueue{TElement, TPriority}" />. | ||||
|         /// </summary> | ||||
|         /// <param name="element">The element to add to the <see cref="PriorityQueue{TElement, TPriority}" />.</param> | ||||
|         /// <param name="priority">The priority with which to associate the new element.</param> | ||||
|         public void Enqueue(TElement element, TPriority priority) | ||||
|         { | ||||
|             // Virtually add the node at the end of the underlying array. | ||||
|             // Note that the node being enqueued does not need to be physically placed | ||||
|             // there at this point, as such an assignment would be redundant. | ||||
| 
 | ||||
|             int currentSize = _size++; | ||||
|             _version++; | ||||
| 
 | ||||
|             if (_nodes.Length == currentSize) Grow(currentSize + 1); | ||||
| 
 | ||||
|             if (_comparer == null) | ||||
|                 MoveUpDefaultComparer((element, priority), currentSize); | ||||
|             else | ||||
|                 MoveUpCustomComparer((element, priority), currentSize); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Returns the minimal element from the <see cref="PriorityQueue{TElement, TPriority}" /> without removing it. | ||||
|         /// </summary> | ||||
|         /// <exception cref="InvalidOperationException">The <see cref="PriorityQueue{TElement, TPriority}" /> is empty.</exception> | ||||
|         /// <returns>The minimal element of the <see cref="PriorityQueue{TElement, TPriority}" />.</returns> | ||||
|         public TElement Peek() | ||||
|         { | ||||
|             if (_size == 0) throw new InvalidOperationException(SR.InvalidOperation_EmptyQueue); | ||||
| 
 | ||||
|             return _nodes[0].Element; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Removes and returns the minimal element from the <see cref="PriorityQueue{TElement, TPriority}" />. | ||||
|         /// </summary> | ||||
|         /// <exception cref="InvalidOperationException">The queue is empty.</exception> | ||||
|         /// <returns>The minimal element of the <see cref="PriorityQueue{TElement, TPriority}" />.</returns> | ||||
|         public TElement Dequeue() | ||||
|         { | ||||
|             if (_size == 0) throw new InvalidOperationException(SR.InvalidOperation_EmptyQueue); | ||||
| 
 | ||||
|             var element = _nodes[0].Element; | ||||
|             RemoveRootNode(); | ||||
|             return element; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Removes the minimal element from the <see cref="PriorityQueue{TElement, TPriority}" />, | ||||
|         ///     and copies it to the <paramref name="element" /> parameter, | ||||
|         ///     and its associated priority to the <paramref name="priority" /> parameter. | ||||
|         /// </summary> | ||||
|         /// <param name="element">The removed element.</param> | ||||
|         /// <param name="priority">The priority associated with the removed element.</param> | ||||
|         /// <returns> | ||||
|         ///     <see langword="true" /> if the element is successfully removed; | ||||
|         ///     <see langword="false" /> if the <see cref="PriorityQueue{TElement, TPriority}" /> is empty. | ||||
|         /// </returns> | ||||
|         public bool TryDequeue([MaybeNullWhen(false)] out TElement element, | ||||
|             [MaybeNullWhen(false)] out TPriority priority) | ||||
|         { | ||||
|             if (_size != 0) | ||||
|             { | ||||
|                 (element, priority) = _nodes[0]; | ||||
|                 RemoveRootNode(); | ||||
|                 return true; | ||||
|             } | ||||
| 
 | ||||
|             element = default; | ||||
|             priority = default; | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Returns a value that indicates whether there is a minimal element in the | ||||
|         ///     <see cref="PriorityQueue{TElement, TPriority}" />, | ||||
|         ///     and if one is present, copies it to the <paramref name="element" /> parameter, | ||||
|         ///     and its associated priority to the <paramref name="priority" /> parameter. | ||||
|         ///     The element is not removed from the <see cref="PriorityQueue{TElement, TPriority}" />. | ||||
|         /// </summary> | ||||
|         /// <param name="element">The minimal element in the queue.</param> | ||||
|         /// <param name="priority">The priority associated with the minimal element.</param> | ||||
|         /// <returns> | ||||
|         ///     <see langword="true" /> if there is a minimal element; | ||||
|         ///     <see langword="false" /> if the <see cref="PriorityQueue{TElement, TPriority}" /> is empty. | ||||
|         /// </returns> | ||||
|         public bool TryPeek([MaybeNullWhen(false)] out TElement element, | ||||
|             [MaybeNullWhen(false)] out TPriority priority) | ||||
|         { | ||||
|             if (_size != 0) | ||||
|             { | ||||
|                 (element, priority) = _nodes[0]; | ||||
|                 return true; | ||||
|             } | ||||
| 
 | ||||
|             element = default; | ||||
|             priority = default; | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Adds the specified element with associated priority to the <see cref="PriorityQueue{TElement, TPriority}" />, | ||||
|         ///     and immediately removes the minimal element, returning the result. | ||||
|         /// </summary> | ||||
|         /// <param name="element">The element to add to the <see cref="PriorityQueue{TElement, TPriority}" />.</param> | ||||
|         /// <param name="priority">The priority with which to associate the new element.</param> | ||||
|         /// <returns>The minimal element removed after the enqueue operation.</returns> | ||||
|         /// <remarks> | ||||
|         ///     Implements an insert-then-extract heap operation that is generally more efficient | ||||
|         ///     than sequencing Enqueue and Dequeue operations: in the worst case scenario only one | ||||
|         ///     shift-down operation is required. | ||||
|         /// </remarks> | ||||
|         public TElement EnqueueDequeue(TElement element, TPriority priority) | ||||
|         { | ||||
|             if (_size != 0) | ||||
|             { | ||||
|                 var root = _nodes[0]; | ||||
| 
 | ||||
|                 if (_comparer == null) | ||||
|                 { | ||||
|                     if (Comparer<TPriority>.Default.Compare(priority, root.Priority) > 0) | ||||
|                     { | ||||
|                         MoveDownDefaultComparer((element, priority), 0); | ||||
|                         _version++; | ||||
|                         return root.Element; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     if (_comparer.Compare(priority, root.Priority) > 0) | ||||
|                     { | ||||
|                         MoveDownCustomComparer((element, priority), 0); | ||||
|                         _version++; | ||||
|                         return root.Element; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             return element; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Enqueues a sequence of element/priority pairs to the <see cref="PriorityQueue{TElement, TPriority}" />. | ||||
|         /// </summary> | ||||
|         /// <param name="items">The pairs of elements and priorities to add to the queue.</param> | ||||
|         /// <exception cref="ArgumentNullException"> | ||||
|         ///     The specified <paramref name="items" /> argument was <see langword="null" />. | ||||
|         /// </exception> | ||||
|         public void EnqueueRange(IEnumerable<(TElement Element, TPriority Priority)> items) | ||||
|         { | ||||
|             ArgumentNullException.ThrowIfNull(items); | ||||
| 
 | ||||
|             int count = 0; | ||||
|             var collection = | ||||
|                 items as ICollection<(TElement Element, TPriority Priority)>; | ||||
|             if (collection is not null && (count = collection.Count) > _nodes.Length - _size) Grow(_size + count); | ||||
| 
 | ||||
|             if (_size == 0) | ||||
|             { | ||||
|                 // build using Heapify() if the queue is empty. | ||||
| 
 | ||||
|                 if (collection is not null) | ||||
|                 { | ||||
|                     collection.CopyTo(_nodes, 0); | ||||
|                     _size = count; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     int i = 0; | ||||
|                     (TElement, TPriority)[] nodes = _nodes; | ||||
|                     foreach ((var element, var priority) in items) | ||||
|                     { | ||||
|                         if (nodes.Length == i) | ||||
|                         { | ||||
|                             Grow(i + 1); | ||||
|                             nodes = _nodes; | ||||
|                         } | ||||
| 
 | ||||
|                         nodes[i++] = (element, priority); | ||||
|                     } | ||||
| 
 | ||||
|                     _size = i; | ||||
|                 } | ||||
| 
 | ||||
|                 _version++; | ||||
| 
 | ||||
|                 if (_size > 1) Heapify(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 foreach ((var element, var priority) in items) Enqueue(element, priority); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Enqueues a sequence of elements pairs to the <see cref="PriorityQueue{TElement, TPriority}" />, | ||||
|         ///     all associated with the specified priority. | ||||
|         /// </summary> | ||||
|         /// <param name="elements">The elements to add to the queue.</param> | ||||
|         /// <param name="priority">The priority to associate with the new elements.</param> | ||||
|         /// <exception cref="ArgumentNullException"> | ||||
|         ///     The specified <paramref name="elements" /> argument was <see langword="null" />. | ||||
|         /// </exception> | ||||
|         public void EnqueueRange(IEnumerable<TElement> elements, TPriority priority) | ||||
|         { | ||||
|             ArgumentNullException.ThrowIfNull(elements); | ||||
| 
 | ||||
|             int count; | ||||
|             if (elements is ICollection<(TElement Element, TPriority Priority)> collection && | ||||
|                 (count = collection.Count) > _nodes.Length - _size) | ||||
|                 Grow(_size + count); | ||||
| 
 | ||||
|             if (_size == 0) | ||||
|             { | ||||
|                 // build using Heapify() if the queue is empty. | ||||
| 
 | ||||
|                 int i = 0; | ||||
|                 (TElement, TPriority)[] nodes = _nodes; | ||||
|                 foreach (var element in elements) | ||||
|                 { | ||||
|                     if (nodes.Length == i) | ||||
|                     { | ||||
|                         Grow(i + 1); | ||||
|                         nodes = _nodes; | ||||
|                     } | ||||
| 
 | ||||
|                     nodes[i++] = (element, priority); | ||||
|                 } | ||||
| 
 | ||||
|                 _size = i; | ||||
|                 _version++; | ||||
| 
 | ||||
|                 if (i > 1) Heapify(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 foreach (var element in elements) Enqueue(element, priority); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Removes all items from the <see cref="PriorityQueue{TElement, TPriority}" />. | ||||
|         /// </summary> | ||||
|         public void Clear() | ||||
|         { | ||||
|             if (RuntimeHelpers.IsReferenceOrContainsReferences<(TElement, TPriority)>()) | ||||
|                 // Clear the elements so that the gc can reclaim the references | ||||
|                 Array.Clear(_nodes, 0, _size); | ||||
| 
 | ||||
|             _size = 0; | ||||
|             _version++; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Ensures that the <see cref="PriorityQueue{TElement, TPriority}" /> can hold up to | ||||
|         ///     <paramref name="capacity" /> items without further expansion of its backing storage. | ||||
|         /// </summary> | ||||
|         /// <param name="capacity">The minimum capacity to be used.</param> | ||||
|         /// <exception cref="ArgumentOutOfRangeException"> | ||||
|         ///     The specified <paramref name="capacity" /> is negative. | ||||
|         /// </exception> | ||||
|         /// <returns>The current capacity of the <see cref="PriorityQueue{TElement, TPriority}" />.</returns> | ||||
|         public int EnsureCapacity(int capacity) | ||||
|         { | ||||
|             if (capacity < 0) | ||||
|                 throw new ArgumentOutOfRangeException(nameof(capacity), capacity, SR.ArgumentOutOfRange_NeedNonNegNum); | ||||
| 
 | ||||
|             if (_nodes.Length < capacity) | ||||
|             { | ||||
|                 Grow(capacity); | ||||
|                 _version++; | ||||
|             } | ||||
| 
 | ||||
|             return _nodes.Length; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Sets the capacity to the actual number of items in the <see cref="PriorityQueue{TElement, TPriority}" />, | ||||
|         ///     if that is less than 90 percent of current capacity. | ||||
|         /// </summary> | ||||
|         /// <remarks> | ||||
|         ///     This method can be used to minimize a collection's memory overhead | ||||
|         ///     if no new elements will be added to the collection. | ||||
|         /// </remarks> | ||||
|         public void TrimExcess() | ||||
|         { | ||||
|             int threshold = (int)(_nodes.Length * 0.9); | ||||
|             if (_size < threshold) | ||||
|             { | ||||
|                 Array.Resize(ref _nodes, _size); | ||||
|                 _version++; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Grows the priority queue to match the specified min capacity. | ||||
|         /// </summary> | ||||
|         private void Grow(int minCapacity) | ||||
|         { | ||||
|             Debug.Assert(_nodes.Length < minCapacity); | ||||
| 
 | ||||
|             const int GrowFactor = 2; | ||||
|             const int MinimumGrow = 4; | ||||
| 
 | ||||
|             int newcapacity = GrowFactor * _nodes.Length; | ||||
| 
 | ||||
|             // Allow the queue to grow to maximum possible capacity (~2G elements) before encountering overflow. | ||||
|             // Note that this check works even when _nodes.Length overflowed thanks to the (uint) cast | ||||
|             if ((uint)newcapacity > ArrayEx.MaxLength) newcapacity = ArrayEx.MaxLength; | ||||
| 
 | ||||
|             // Ensure minimum growth is respected. | ||||
|             newcapacity = Math.Max(newcapacity, _nodes.Length + MinimumGrow); | ||||
| 
 | ||||
|             // If the computed capacity is still less than specified, set to the original argument. | ||||
|             // Capacities exceeding Array.MaxLength will be surfaced as OutOfMemoryException by Array.Resize. | ||||
|             if (newcapacity < minCapacity) newcapacity = minCapacity; | ||||
| 
 | ||||
|             Array.Resize(ref _nodes, newcapacity); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Removes the node from the root of the heap | ||||
|         /// </summary> | ||||
|         private void RemoveRootNode() | ||||
|         { | ||||
|             int lastNodeIndex = --_size; | ||||
|             _version++; | ||||
| 
 | ||||
|             if (lastNodeIndex > 0) | ||||
|             { | ||||
|                 var lastNode = _nodes[lastNodeIndex]; | ||||
|                 if (_comparer == null) | ||||
|                     MoveDownDefaultComparer(lastNode, 0); | ||||
|                 else | ||||
|                     MoveDownCustomComparer(lastNode, 0); | ||||
|             } | ||||
| 
 | ||||
|             if (RuntimeHelpers.IsReferenceOrContainsReferences<(TElement, TPriority)>()) | ||||
|                 _nodes[lastNodeIndex] = default; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Gets the index of an element's parent. | ||||
|         /// </summary> | ||||
|         private static int GetParentIndex(int index) => (index - 1) >> Log2Arity; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Gets the index of the first child of an element. | ||||
|         /// </summary> | ||||
|         private static int GetFirstChildIndex(int index) => (index << Log2Arity) + 1; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Converts an unordered list into a heap. | ||||
|         /// </summary> | ||||
|         private void Heapify() | ||||
|         { | ||||
|             // Leaves of the tree are in fact 1-element heaps, for which there | ||||
|             // is no need to correct them. The heap property needs to be restored | ||||
|             // only for higher nodes, starting from the first node that has children. | ||||
|             // It is the parent of the very last element in the array. | ||||
| 
 | ||||
|             var nodes = _nodes; | ||||
|             int lastParentWithChildren = GetParentIndex(_size - 1); | ||||
| 
 | ||||
|             if (_comparer == null) | ||||
|                 for (int index = lastParentWithChildren; index >= 0; --index) | ||||
|                     MoveDownDefaultComparer(nodes[index], index); | ||||
|             else | ||||
|                 for (int index = lastParentWithChildren; index >= 0; --index) | ||||
|                     MoveDownCustomComparer(nodes[index], index); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Moves a node up in the tree to restore heap order. | ||||
|         /// </summary> | ||||
|         private void MoveUpDefaultComparer((TElement Element, TPriority Priority) node, int nodeIndex) | ||||
|         { | ||||
|             // Instead of swapping items all the way to the root, we will perform | ||||
|             // a similar optimization as in the insertion sort. | ||||
| 
 | ||||
|             Debug.Assert(_comparer is null); | ||||
|             Debug.Assert(0 <= nodeIndex && nodeIndex < _size); | ||||
| 
 | ||||
|             var nodes = _nodes; | ||||
| 
 | ||||
|             while (nodeIndex > 0) | ||||
|             { | ||||
|                 int parentIndex = GetParentIndex(nodeIndex); | ||||
|                 var parent = nodes[parentIndex]; | ||||
| 
 | ||||
|                 if (Comparer<TPriority>.Default.Compare(node.Priority, parent.Priority) < 0) | ||||
|                 { | ||||
|                     nodes[nodeIndex] = parent; | ||||
|                     nodeIndex = parentIndex; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             nodes[nodeIndex] = node; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Moves a node up in the tree to restore heap order. | ||||
|         /// </summary> | ||||
|         private void MoveUpCustomComparer((TElement Element, TPriority Priority) node, int nodeIndex) | ||||
|         { | ||||
|             // Instead of swapping items all the way to the root, we will perform | ||||
|             // a similar optimization as in the insertion sort. | ||||
| 
 | ||||
|             Debug.Assert(_comparer is not null); | ||||
|             Debug.Assert(0 <= nodeIndex && nodeIndex < _size); | ||||
| 
 | ||||
|             var comparer = _comparer; | ||||
|             var nodes = _nodes; | ||||
| 
 | ||||
|             while (nodeIndex > 0) | ||||
|             { | ||||
|                 int parentIndex = GetParentIndex(nodeIndex); | ||||
|                 var parent = nodes[parentIndex]; | ||||
| 
 | ||||
|                 if (comparer != null && comparer.Compare(node.Priority, parent.Priority) < 0) | ||||
|                 { | ||||
|                     nodes[nodeIndex] = parent; | ||||
|                     nodeIndex = parentIndex; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             nodes[nodeIndex] = node; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Moves a node down in the tree to restore heap order. | ||||
|         /// </summary> | ||||
|         private void MoveDownDefaultComparer((TElement Element, TPriority Priority) node, int nodeIndex) | ||||
|         { | ||||
|             // The node to move down will not actually be swapped every time. | ||||
|             // Rather, values on the affected path will be moved up, thus leaving a free spot | ||||
|             // for this value to drop in. Similar optimization as in the insertion sort. | ||||
| 
 | ||||
|             Debug.Assert(_comparer is null); | ||||
|             Debug.Assert(0 <= nodeIndex && nodeIndex < _size); | ||||
| 
 | ||||
|             var nodes = _nodes; | ||||
|             int size = _size; | ||||
| 
 | ||||
|             int i; | ||||
|             while ((i = GetFirstChildIndex(nodeIndex)) < size) | ||||
|             { | ||||
|                 // Find the child node with the minimal priority | ||||
|                 var minChild = nodes[i]; | ||||
|                 int minChildIndex = i; | ||||
| 
 | ||||
|                 int childIndexUpperBound = Math.Min(i + Arity, size); | ||||
|                 while (++i < childIndexUpperBound) | ||||
|                 { | ||||
|                     var nextChild = nodes[i]; | ||||
|                     if (Comparer<TPriority>.Default.Compare(nextChild.Priority, minChild.Priority) < 0) | ||||
|                     { | ||||
|                         minChild = nextChild; | ||||
|                         minChildIndex = i; | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 // Heap property is satisfied; insert node in this location. | ||||
|                 if (Comparer<TPriority>.Default.Compare(node.Priority, minChild.Priority) <= 0) break; | ||||
| 
 | ||||
|                 // Move the minimal child up by one node and | ||||
|                 // continue recursively from its location. | ||||
|                 nodes[nodeIndex] = minChild; | ||||
|                 nodeIndex = minChildIndex; | ||||
|             } | ||||
| 
 | ||||
|             nodes[nodeIndex] = node; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Moves a node down in the tree to restore heap order. | ||||
|         /// </summary> | ||||
|         private void MoveDownCustomComparer((TElement Element, TPriority Priority) node, int nodeIndex) | ||||
|         { | ||||
|             // The node to move down will not actually be swapped every time. | ||||
|             // Rather, values on the affected path will be moved up, thus leaving a free spot | ||||
|             // for this value to drop in. Similar optimization as in the insertion sort. | ||||
| 
 | ||||
|             Debug.Assert(_comparer is not null); | ||||
|             Debug.Assert(0 <= nodeIndex && nodeIndex < _size); | ||||
| 
 | ||||
|             var comparer = _comparer; | ||||
|             var nodes = _nodes; | ||||
|             int size = _size; | ||||
| 
 | ||||
|             int i; | ||||
|             while ((i = GetFirstChildIndex(nodeIndex)) < size) | ||||
|             { | ||||
|                 // Find the child node with the minimal priority | ||||
|                 var minChild = nodes[i]; | ||||
|                 int minChildIndex = i; | ||||
| 
 | ||||
|                 int childIndexUpperBound = Math.Min(i + Arity, size); | ||||
|                 while (++i < childIndexUpperBound) | ||||
|                 { | ||||
|                     var nextChild = nodes[i]; | ||||
|                     if (comparer != null && comparer.Compare(nextChild.Priority, minChild.Priority) < 0) | ||||
|                     { | ||||
|                         minChild = nextChild; | ||||
|                         minChildIndex = i; | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 // Heap property is satisfied; insert node in this location. | ||||
|                 if (comparer != null && comparer.Compare(node.Priority, minChild.Priority) <= 0) break; | ||||
| 
 | ||||
|                 // Move the minimal child up by one node and continue recursively from its location. | ||||
|                 nodes[nodeIndex] = minChild; | ||||
|                 nodeIndex = minChildIndex; | ||||
|             } | ||||
| 
 | ||||
|             nodes[nodeIndex] = node; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Initializes the custom comparer to be used internally by the heap. | ||||
|         /// </summary> | ||||
|         private static IComparer<TPriority>? InitializeComparer(IComparer<TPriority>? comparer) | ||||
|         { | ||||
|             if (typeof(TPriority).IsValueType) | ||||
|             { | ||||
|                 if (comparer == Comparer<TPriority>.Default) | ||||
|                     // if the user manually specifies the default comparer, | ||||
|                     // revert to using the optimized path. | ||||
|                     return null; | ||||
| 
 | ||||
|                 return comparer; | ||||
|             } | ||||
| 
 | ||||
|             // Currently the JIT doesn't optimize direct Comparer<T>.Default.Compare | ||||
|             // calls for reference types, so we want to cache the comparer instance instead. | ||||
|             // TODO https://github.com/dotnet/runtime/issues/10050: Update if this changes in the future. | ||||
|             return comparer ?? Comparer<TPriority>.Default; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///     Enumerates the contents of a <see cref="PriorityQueue{TElement, TPriority}" />, without any ordering guarantees. | ||||
|         /// </summary> | ||||
|         [DebuggerDisplay("Count = {Count}")] | ||||
|         [DebuggerTypeProxy(typeof(PriorityQueueDebugView<,>))] | ||||
|         public sealed class UnorderedItemsCollection : IReadOnlyCollection<(TElement Element, TPriority Priority)>, | ||||
|             ICollection | ||||
|         { | ||||
|             internal readonly PriorityQueue<TElement, TPriority> _queue; | ||||
| 
 | ||||
|             internal UnorderedItemsCollection(PriorityQueue<TElement, TPriority> queue) | ||||
|             { | ||||
|                 _queue = queue; | ||||
|             } | ||||
| 
 | ||||
|             object ICollection.SyncRoot => this; | ||||
|             bool ICollection.IsSynchronized => false; | ||||
| 
 | ||||
|             void ICollection.CopyTo(Array array, int index) | ||||
|             { | ||||
|                 ArgumentNullException.ThrowIfNull(array); | ||||
| 
 | ||||
|                 if (array.Rank != 1) throw new ArgumentException(SR.Arg_RankMultiDimNotSupported, nameof(array)); | ||||
| 
 | ||||
|                 if (array.GetLowerBound(0) != 0) throw new ArgumentException(SR.Arg_NonZeroLowerBound, nameof(array)); | ||||
| 
 | ||||
|                 if (index < 0 || index > array.Length) | ||||
|                     throw new ArgumentOutOfRangeException(nameof(index), index, | ||||
|                         SR.ArgumentOutOfRange_IndexMustBeLessOrEqual); | ||||
| 
 | ||||
|                 if (array.Length - index < _queue._size) throw new ArgumentException(SR.Argument_InvalidOffLen); | ||||
| 
 | ||||
|                 try | ||||
|                 { | ||||
|                     Array.Copy(_queue._nodes, 0, array, index, _queue._size); | ||||
|                 } | ||||
|                 catch (ArrayTypeMismatchException) | ||||
|                 { | ||||
|                     throw new ArgumentException(SR.Argument_InvalidArrayType, nameof(array)); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             public int Count => _queue._size; | ||||
| 
 | ||||
|             IEnumerator<(TElement Element, TPriority Priority)> IEnumerable<(TElement Element, TPriority Priority)>. | ||||
|                 GetEnumerator() => GetEnumerator(); | ||||
| 
 | ||||
|             IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | ||||
| 
 | ||||
|             /// <summary> | ||||
|             ///     Returns an enumerator that iterates through the <see cref="UnorderedItems" />. | ||||
|             /// </summary> | ||||
|             /// <returns>An <see cref="Enumerator" /> for the <see cref="UnorderedItems" />.</returns> | ||||
|             public Enumerator GetEnumerator() => new(_queue); | ||||
| 
 | ||||
|             /// <summary> | ||||
|             ///     Enumerates the element and priority pairs of a <see cref="PriorityQueue{TElement, TPriority}" />, | ||||
|             ///     without any ordering guarantees. | ||||
|             /// </summary> | ||||
|             public struct Enumerator : IEnumerator<(TElement Element, TPriority Priority)> | ||||
|             { | ||||
|                 private readonly PriorityQueue<TElement, TPriority> _queue; | ||||
|                 private readonly int _version; | ||||
|                 private int _index; | ||||
| 
 | ||||
|                 internal Enumerator(PriorityQueue<TElement, TPriority> queue) | ||||
|                 { | ||||
|                     _queue = queue; | ||||
|                     _index = 0; | ||||
|                     _version = queue._version; | ||||
|                     Current = default; | ||||
|                 } | ||||
| 
 | ||||
|                 /// <summary> | ||||
|                 ///     Releases all resources used by the <see cref="Enumerator" />. | ||||
|                 /// </summary> | ||||
|                 public void Dispose() | ||||
|                 { | ||||
|                 } | ||||
| 
 | ||||
|                 /// <summary> | ||||
|                 ///     Advances the enumerator to the next element of the <see cref="UnorderedItems" />. | ||||
|                 /// </summary> | ||||
|                 /// <returns> | ||||
|                 ///     <see langword="true" /> if the enumerator was successfully advanced to the next element; | ||||
|                 ///     <see langword="false" /> if the enumerator has passed the end of the collection. | ||||
|                 /// </returns> | ||||
|                 public bool MoveNext() | ||||
|                 { | ||||
|                     var localQueue = _queue; | ||||
| 
 | ||||
|                     if (_version == localQueue._version && (uint)_index < (uint)localQueue._size) | ||||
|                     { | ||||
|                         Current = localQueue._nodes[_index]; | ||||
|                         _index++; | ||||
|                         return true; | ||||
|                     } | ||||
| 
 | ||||
|                     return MoveNextRare(); | ||||
|                 } | ||||
| 
 | ||||
|                 private bool MoveNextRare() | ||||
|                 { | ||||
|                     if (_version != _queue._version) | ||||
|                         throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); | ||||
| 
 | ||||
|                     _index = _queue._size + 1; | ||||
|                     Current = default; | ||||
|                     return false; | ||||
|                 } | ||||
| 
 | ||||
|                 /// <summary> | ||||
|                 ///     Gets the element at the current position of the enumerator. | ||||
|                 /// </summary> | ||||
|                 public (TElement Element, TPriority Priority) Current { get; private set; } | ||||
| 
 | ||||
|                 object IEnumerator.Current => Current; | ||||
| 
 | ||||
|                 void IEnumerator.Reset() | ||||
|                 { | ||||
|                     if (_version != _queue._version) | ||||
|                         throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); | ||||
| 
 | ||||
|                     _index = 0; | ||||
|                     Current = default; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										11
									
								
								NEG/UI/PriorityQueue.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								NEG/UI/PriorityQueue.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: e1b6a9a70d997fd468f30caa1e760078 | ||||
| MonoImporter: | ||||
|   externalObjects: {} | ||||
|   serializedVersion: 2 | ||||
|   defaultReferences: [] | ||||
|   executionOrder: 0 | ||||
|   icon: {instanceID: 0} | ||||
|   userData:  | ||||
|   assetBundleName:  | ||||
|   assetBundleVariant:  | ||||
							
								
								
									
										169
									
								
								NEG/UI/UiManager.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								NEG/UI/UiManager.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,169 @@ | ||||
| using JetBrains.Annotations; | ||||
| using NEG.UI.Area; | ||||
| using NEG.UI.Popup; | ||||
| using NEG.UI.Window; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using UnityEngine; | ||||
| 
 | ||||
| namespace NEG.UI | ||||
| { | ||||
|     [PublicAPI] | ||||
|     public abstract class UiManager | ||||
|     { | ||||
|         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 (PopupData data, int priority) currentShownPopup; | ||||
|         protected IDefaultPopup currentDefaultPopup; | ||||
| 
 | ||||
|         private PriorityQueue<PopupData, int> popupsToShow = new(); | ||||
| 
 | ||||
|         //TODO: localize | ||||
|         private string localizedYes = "Yes", localizedNo = "No", localizedOk = "Ok"; | ||||
| 
 | ||||
|         protected UiManager(IArea startArea) | ||||
|         { | ||||
|             if (Instance != null) | ||||
|             { | ||||
|                 Debug.LogError("Only one instance od UiManager is allowed"); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             Instance = this; | ||||
| 
 | ||||
|             CurrentArea = startArea; | ||||
|         } | ||||
| 
 | ||||
|         /// <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> | ||||
|         /// <param name="title">popup title</param> | ||||
|         /// <param name="content">popup content</param> | ||||
|         /// <param name="okText">text to show on ok button, empty for localized "Ok"</param> | ||||
|         /// <param name="okPressed">additional action on ok pressed</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> | ||||
|         /// <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) | ||||
|         { | ||||
|             var data = new DefaultPopupData(currentDefaultPopup, title, content, | ||||
|                 new List<(string, Action)>() { (okText ?? localizedOk, okPressed) }); | ||||
|             ShowPopup(data, priority, forceShow); | ||||
|             return data; | ||||
|         } | ||||
|          | ||||
|         /// <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. | ||||
|         /// </summary> | ||||
|         /// <param name="title">popup title</param> | ||||
|         /// <param name="content">popup content</param> | ||||
|         /// <param name="yesText">text to show on yes button, empty for localized "Yes"</param> | ||||
|         /// <param name="noText">text to show on no button, empty for localized "No"</param> | ||||
|         /// <param name="yesPressed">additional action on yes pressed</param> | ||||
|         /// <param name="noPressed">additional action on no pressed</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> | ||||
|         /// <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) | ||||
|         { | ||||
|             var data = new DefaultPopupData(currentDefaultPopup, title, content, | ||||
|                 new List<(string, Action)>() { (yesText ?? localizedYes, yesPressed), (noText ?? localizedNo, noPressed) }); | ||||
|             ShowPopup(data, priority, forceShow); | ||||
|             return data; | ||||
|         } | ||||
|          | ||||
|         /// <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. | ||||
|         /// </summary> | ||||
|         /// <param name="title">popup title</param> | ||||
|         /// <param name="content">popup content</param> | ||||
|         /// <param name="actions">list of actions</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> | ||||
|         /// <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) | ||||
|         { | ||||
|             var data = new DefaultPopupData(currentDefaultPopup, title, content, actions); | ||||
|             ShowPopup(data, priority, forceShow); | ||||
|             return data; | ||||
|         } | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Show popup if there is non other currently shown. Otherwise add current popup to ordered queue and show it later. | ||||
|         /// </summary> | ||||
|         /// <param name="data">popup data object</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> | ||||
|         public void ShowPopup(PopupData data, int priority = 0, bool forceShow = false) | ||||
|         { | ||||
|             popupsToShow.Enqueue(data, priority); | ||||
|             UpdatePopupsState(forceShow, priority, data); | ||||
|         } | ||||
|          | ||||
|         protected void PopupClosed(PopupData data) | ||||
|         { | ||||
|             if (currentShownPopup.data != data) | ||||
|             { | ||||
|                 Debug.LogError("Popup was not shown"); | ||||
|                 return; | ||||
|             } | ||||
|             UpdatePopupsState(false); | ||||
|         } | ||||
|          | ||||
|         protected void SetDefaultPopup(IDefaultPopup popup) => currentDefaultPopup = popup; | ||||
| 
 | ||||
|         private void UpdatePopupsState(bool forceShow, int priority = 0, PopupData data = null) | ||||
|         { | ||||
|             if (forceShow) | ||||
|             { | ||||
|                 if(currentShownPopup.priority <= priority) | ||||
|                     return; | ||||
|                  | ||||
|                 popupsToShow.Enqueue(currentShownPopup.data, currentShownPopup.priority); | ||||
|                 ShowPopup(data, priority); | ||||
|                 return; | ||||
|             } | ||||
|              | ||||
|             if(!popupsToShow.TryDequeue(out var d, out int p)) | ||||
|                return; | ||||
| 
 | ||||
|             ShowPopup(d, p); | ||||
|         } | ||||
| 
 | ||||
|         private void ShowPopup(PopupData data, int priority) | ||||
|         { | ||||
|             if (currentShownPopup.data != null) | ||||
|             { | ||||
|                 currentShownPopup.data.PopupClosedEvent -= PopupClosed; | ||||
|                 currentShownPopup.data.Hide(); | ||||
|             } | ||||
|             currentShownPopup = (data, priority); | ||||
|             data.Show(); | ||||
|             data.PopupClosedEvent += PopupClosed; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										11
									
								
								NEG/UI/UiManager.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								NEG/UI/UiManager.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: c322beedd2ec8f844903c18b1ef74b15 | ||||
| MonoImporter: | ||||
|   externalObjects: {} | ||||
|   serializedVersion: 2 | ||||
|   defaultReferences: [] | ||||
|   executionOrder: 0 | ||||
|   icon: {instanceID: 0} | ||||
|   userData:  | ||||
|   assetBundleName:  | ||||
|   assetBundleVariant:  | ||||
							
								
								
									
										8
									
								
								NEG/UI/UnityUi.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								NEG/UI/UnityUi.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: a0be272f427b40848b8aeff5b04770b4 | ||||
| folderAsset: yes | ||||
| DefaultImporter: | ||||
|   externalObjects: {} | ||||
|   userData:  | ||||
|   assetBundleName:  | ||||
|   assetBundleVariant:  | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Area.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Area.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: a99aed857b7b9e7459811b14fefdb04f | ||||
| timeCreated: 1670706939 | ||||
							
								
								
									
										15
									
								
								NEG/UI/UnityUi/Area/AutoWindowOpen.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								NEG/UI/UnityUi/Area/AutoWindowOpen.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| using NEG.UI.UnityUi.Window; | ||||
| using NEG.UI.Window; | ||||
| using System; | ||||
| using UnityEngine; | ||||
| 
 | ||||
| namespace NEG.UI.Area | ||||
| { | ||||
|     [Tooltip(tooltip: "Automatically open attached window on start")] | ||||
|     public class AutoWindowOpen : MonoBehaviour | ||||
|     { | ||||
|         [SerializeField] private MonoWindow window; | ||||
|          | ||||
|         private void Start() => window.Open(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Area/AutoWindowOpen.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Area/AutoWindowOpen.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: e439a77332dc4e3a881348c9506556c6 | ||||
| timeCreated: 1673791915 | ||||
							
								
								
									
										41
									
								
								NEG/UI/UnityUi/Area/MonoArea.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								NEG/UI/UnityUi/Area/MonoArea.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| using System.Collections.Generic; | ||||
| using UnityEngine; | ||||
| using NEG.UI.Popup; | ||||
| using NEG.UI.UnityUi.Window; | ||||
| using NEG.UI.UnityUi.WindowSlot; | ||||
| using NEG.UI.Window; | ||||
| using NEG.UI.WindowSlot; | ||||
| using System; | ||||
| 
 | ||||
| namespace NEG.UI.Area | ||||
| { | ||||
|     public class MonoArea : MonoBehaviour, IArea | ||||
|     { | ||||
|         public IEnumerable<IWindowSlot> AvailableSlots => windowSlots; | ||||
|         public IWindowSlot DefaultWindowSlot => windowSlots[0]; | ||||
|          | ||||
|         [SerializeField] private bool setAsDefaultArea; | ||||
| 
 | ||||
|         [SerializeField] private List<MonoWindowSlot> windowSlots; | ||||
| 
 | ||||
|         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() | ||||
|         { | ||||
|             if (setAsDefaultArea) | ||||
|                 UiManager.Instance.CurrentArea = this; | ||||
|         } | ||||
| 
 | ||||
|         protected virtual void OnDestroy() | ||||
|         { | ||||
|             if (ReferenceEquals(UiManager.Instance.CurrentArea, this)) | ||||
|                 UiManager.Instance.CurrentArea = null; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Area/MonoArea.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Area/MonoArea.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 39eb59ca1ef60934abb3f0c64169be65 | ||||
| timeCreated: 1670707479 | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Buttons.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Buttons.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: dcaa262d2bcd4b19aa25512a19830555 | ||||
| timeCreated: 1670777190 | ||||
							
								
								
									
										78
									
								
								NEG/UI/UnityUi/Buttons/BaseButton.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								NEG/UI/UnityUi/Buttons/BaseButton.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | ||||
| using FMOD.Studio; | ||||
| using FMODUnity; | ||||
| using System; | ||||
| using UnityEngine; | ||||
| using UnityEngine.EventSystems; | ||||
| using UnityEngine.UI; | ||||
| 
 | ||||
| namespace NEG.UI.UnityUi.Buttons | ||||
| { | ||||
|     [RequireComponent(typeof(ButtonSerializeFields))] | ||||
|     public class BaseButton : MonoBehaviour, ISelectHandler, IDeselectHandler, IPointerEnterHandler, IPointerExitHandler | ||||
|     { | ||||
|         public event Action OnButtonPressed; | ||||
|          | ||||
|         public bool Interactable { get => serializeFields.Button.interactable; set => serializeFields.Button.interactable = value; } | ||||
|          | ||||
|         [SerializeField] | ||||
|         protected ButtonSerializeFields serializeFields; | ||||
| 
 | ||||
|         private bool isHovered; | ||||
| 
 | ||||
|         public virtual void OnSelect(BaseEventData eventData) | ||||
|         { | ||||
|             if (serializeFields.Text) | ||||
|                 serializeFields.Text.color = serializeFields.SelectedTextColor; | ||||
|         } | ||||
| 
 | ||||
|         public void OnDeselect(BaseEventData eventData) | ||||
|         { | ||||
|             if (serializeFields.Text) | ||||
|                 serializeFields.Text.color = serializeFields.DeselectedTextColor; | ||||
|         } | ||||
| 
 | ||||
|         public void OnPointerEnter(PointerEventData eventData) | ||||
|         { | ||||
|             isHovered = true; | ||||
|             if (serializeFields.Text) | ||||
|                 serializeFields.Text.color = serializeFields.SelectedTextColor; | ||||
|         } | ||||
| 
 | ||||
|         public void OnPointerExit(PointerEventData eventData) | ||||
|         { | ||||
|             isHovered = false; | ||||
|             if (serializeFields.Text) | ||||
|                 serializeFields.Text.color = serializeFields.DeselectedTextColor; | ||||
|         } | ||||
| 
 | ||||
|         public void SetText(string text) | ||||
|         { | ||||
|             if(serializeFields == null) | ||||
|                 return; | ||||
|             if(serializeFields.Text == null) | ||||
|                 return; | ||||
|             serializeFields.Text.text = text; | ||||
|         } | ||||
| 
 | ||||
|         protected virtual void Awake() | ||||
|         { | ||||
|             if(serializeFields == null) | ||||
|                 serializeFields = GetComponent<ButtonSerializeFields>(); | ||||
|             serializeFields.Button.onClick.AddListener(OnClicked); | ||||
|             OnDeselect(null); | ||||
|         } | ||||
| 
 | ||||
|         private void OnValidate() | ||||
|         { | ||||
|             if(serializeFields == null) | ||||
|                 serializeFields = GetComponent<ButtonSerializeFields>(); | ||||
|         } | ||||
| 
 | ||||
|         protected virtual void OnClicked() | ||||
|         { | ||||
|             OnDeselect(null); | ||||
|             isHovered = false; | ||||
|             OnButtonPressed?.Invoke(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Buttons/BaseButton.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Buttons/BaseButton.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 3a250ef2d0c34e7396a16fc5eddbdb01 | ||||
| timeCreated: 1670777213 | ||||
							
								
								
									
										15
									
								
								NEG/UI/UnityUi/Buttons/ButtonReaction.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								NEG/UI/UnityUi/Buttons/ButtonReaction.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| using System; | ||||
| using UnityEngine; | ||||
| 
 | ||||
| namespace NEG.UI.UnityUi.Buttons | ||||
| { | ||||
|     [RequireComponent(typeof(BaseButton))] | ||||
|     public abstract class ButtonReaction : MonoBehaviour | ||||
|     { | ||||
|         private void Awake() => GetComponent<BaseButton>().OnButtonPressed += OnClicked; | ||||
| 
 | ||||
|         private void OnDestroy() => GetComponent<BaseButton>().OnButtonPressed -= OnClicked; | ||||
| 
 | ||||
|         protected abstract void OnClicked(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Buttons/ButtonReaction.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Buttons/ButtonReaction.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: a9761128a04b49c2a26eddfabe70331f | ||||
| timeCreated: 1675707257 | ||||
							
								
								
									
										33
									
								
								NEG/UI/UnityUi/Buttons/ButtonSerializeFields.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								NEG/UI/UnityUi/Buttons/ButtonSerializeFields.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| 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>(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Buttons/ButtonSerializeFields.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Buttons/ButtonSerializeFields.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 3f8c6cf4cf18463c86ec1165c61c79b2 | ||||
| timeCreated: 1670777232 | ||||
							
								
								
									
										25
									
								
								NEG/UI/UnityUi/Buttons/ChangeSceneButton.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								NEG/UI/UnityUi/Buttons/ChangeSceneButton.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| using System; | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| using UnityEngine; | ||||
| using UnityEngine.SceneManagement; | ||||
| 
 | ||||
| namespace NEG.UI.UnityUi.Buttons | ||||
| { | ||||
|     [RequireComponent(typeof(BaseButton))] | ||||
|     public class ChangeSceneButton : 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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										11
									
								
								NEG/UI/UnityUi/Buttons/ChangeSceneButton.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								NEG/UI/UnityUi/Buttons/ChangeSceneButton.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 15537f041c9c1204ebf05a5fb7ff6a3d | ||||
| MonoImporter: | ||||
|   externalObjects: {} | ||||
|   serializedVersion: 2 | ||||
|   defaultReferences: [] | ||||
|   executionOrder: 0 | ||||
|   icon: {instanceID: 0} | ||||
|   userData:  | ||||
|   assetBundleName:  | ||||
|   assetBundleVariant:  | ||||
							
								
								
									
										9
									
								
								NEG/UI/UnityUi/Buttons/CloseAllWindows.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								NEG/UI/UnityUi/Buttons/CloseAllWindows.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| using UnityEngine; | ||||
| 
 | ||||
| namespace NEG.UI.UnityUi.Buttons | ||||
| { | ||||
|     public class CloseAllWindows : ButtonReaction | ||||
|     { | ||||
|         protected override void OnClicked() => UiManager.Instance.CurrentArea.CloseAllWindows(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Buttons/CloseAllWindows.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Buttons/CloseAllWindows.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 2fa43803dc014b7694d265d48c1fc680 | ||||
| timeCreated: 1672767354 | ||||
							
								
								
									
										22
									
								
								NEG/UI/UnityUi/Buttons/CloseWindow.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								NEG/UI/UnityUi/Buttons/CloseWindow.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| using NEG.UI.UnityUi.Window; | ||||
| using NEG.UI.Window; | ||||
| using System; | ||||
| using UnityEngine; | ||||
| 
 | ||||
| namespace NEG.UI.UnityUi.Buttons | ||||
| { | ||||
|     [RequireComponent(typeof(BaseButton))] | ||||
|     public class CloseWindow : ButtonReaction | ||||
|     { | ||||
|         [SerializeField] private MonoWindow windowToClose; | ||||
| 
 | ||||
|         protected override void OnClicked() => windowToClose.Close(); | ||||
| 
 | ||||
|         private void OnValidate() | ||||
|         { | ||||
|             if(windowToClose != null) | ||||
|                 return; | ||||
|             windowToClose = GetComponentInParent<MonoWindow>(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Buttons/CloseWindow.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Buttons/CloseWindow.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 3001b971ff1e4915a29784efdf190bd6 | ||||
| timeCreated: 1670807872 | ||||
							
								
								
									
										14
									
								
								NEG/UI/UnityUi/Buttons/CloseWindowOnImageTouch.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								NEG/UI/UnityUi/Buttons/CloseWindowOnImageTouch.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| using NEG.UI.UnityUi.Window; | ||||
| using NEG.UI.Window; | ||||
| using UnityEngine; | ||||
| using UnityEngine.EventSystems; | ||||
| 
 | ||||
| namespace NEG.UI.UnityUi.Buttons | ||||
| { | ||||
|     public class CloseWindowOnImageTouch : MonoBehaviour, IPointerDownHandler | ||||
|     { | ||||
|         [SerializeField] private MonoWindow windowToClose; | ||||
|          | ||||
|         public void OnPointerDown(PointerEventData eventData) => windowToClose.Close(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Buttons/CloseWindowOnImageTouch.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Buttons/CloseWindowOnImageTouch.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: dc1aab636014456da7f768a05d0f143e | ||||
| timeCreated: 1673909580 | ||||
							
								
								
									
										19
									
								
								NEG/UI/UnityUi/Buttons/OpenWindow.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								NEG/UI/UnityUi/Buttons/OpenWindow.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| 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 : ButtonReaction | ||||
|     { | ||||
|         [SerializeField] private MonoWindow window; | ||||
|         [Header("Open on default area slot if empty")] | ||||
|         [SerializeField] private MonoWindowSlot slot; | ||||
| 
 | ||||
|         protected override void OnClicked() => window.Open(slot); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Buttons/OpenWindow.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Buttons/OpenWindow.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 66a5c05f0ba84b2a9b54f3e05a21d495 | ||||
| timeCreated: 1670806968 | ||||
							
								
								
									
										8
									
								
								NEG/UI/UnityUi/CarouselList.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								NEG/UI/UnityUi/CarouselList.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: d6bf45a37eca4dc4aa1926eb7dce5ab6 | ||||
| folderAsset: yes | ||||
| DefaultImporter: | ||||
|   externalObjects: {} | ||||
|   userData:  | ||||
|   assetBundleName:  | ||||
|   assetBundleVariant:  | ||||
							
								
								
									
										95
									
								
								NEG/UI/UnityUi/CarouselList/CarouselList.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								NEG/UI/UnityUi/CarouselList/CarouselList.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,95 @@ | ||||
| using JetBrains.Annotations; | ||||
| using NEG.UI.UnityUi.Buttons; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using TMPro; | ||||
| using UnityEngine; | ||||
| 
 | ||||
| 
 | ||||
| namespace NEG.UI.UnityUi | ||||
| { | ||||
|     [PublicAPI] | ||||
|     public class CarouselList : MonoBehaviour | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Current option | ||||
|         /// </summary> | ||||
|         public string CurrentOption { get; private set; } | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Current selected option id | ||||
|         /// </summary> | ||||
|         public int CurrentOptionId { get; private set; } | ||||
| 
 | ||||
|         [SerializeField] private BaseButton nextButton; | ||||
|         [SerializeField] private BaseButton prevButton; | ||||
|         [SerializeField] private TMP_Text currentOptionText; | ||||
| 
 | ||||
|         private List<string> options; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Sets new options list, automatically first will be selected. | ||||
|         /// </summary> | ||||
|         /// <param name="options">list of options names</param> | ||||
|         public void SetOptions(List<string> options) | ||||
|         { | ||||
|             this.options = options; | ||||
|             SelectOption(0); | ||||
|         } | ||||
| 
 | ||||
|         public void SelectNextOption() => ChangeOption(true); | ||||
|         public void SelectPrevOption() => ChangeOption(false); | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Selects option with provided id. | ||||
|         /// </summary> | ||||
|         /// <param name="option">option number</param> | ||||
|         public void SelectOption(int option) | ||||
|         { | ||||
|             if (option < 0 || option >= options.Count) | ||||
|             { | ||||
|                 Debug.LogError("Invalid option number"); | ||||
|                 return; | ||||
|             } | ||||
|             CurrentOptionId = option; | ||||
|             CurrentOption = options[option]; | ||||
|             currentOptionText.text = CurrentOption; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Select option with provided value. Use with caution, better use <see cref="SelectOption(int)"/>. | ||||
|         /// </summary> | ||||
|         /// <param name="option">option value to select</param> | ||||
|         public void SelectOption(string option) | ||||
|         { | ||||
|             if (options.Count == 0) | ||||
|             { | ||||
|                 Debug.LogError("Carousel List cannot be empty when selecting option"); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             int index = options.IndexOf(option); | ||||
|             if (index == -1) | ||||
|             { | ||||
|                 Debug.LogError($"Option {option} not found"); | ||||
|                 return; | ||||
|             } | ||||
|              | ||||
|             SelectOption(index); | ||||
|         } | ||||
| 
 | ||||
|         private void Awake() | ||||
|         { | ||||
|             nextButton.OnButtonPressed += SelectNextOption; | ||||
|             prevButton.OnButtonPressed += SelectPrevOption; | ||||
|         } | ||||
| 
 | ||||
|         private void OnDestroy() | ||||
|         { | ||||
|             nextButton.OnButtonPressed -= SelectNextOption; | ||||
|             prevButton.OnButtonPressed -= SelectPrevOption; | ||||
|         } | ||||
| 
 | ||||
|         private void ChangeOption(bool next) => SelectOption((CurrentOptionId + (next ? 1 : -1) + options.Count) % options.Count); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/CarouselList/CarouselList.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/CarouselList/CarouselList.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 9915ee4d467e47e485c4a48be295b5c2 | ||||
| timeCreated: 1672834830 | ||||
							
								
								
									
										52
									
								
								NEG/UI/UnityUi/MonoUiManager.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								NEG/UI/UnityUi/MonoUiManager.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| using NEG.UI.Area; | ||||
| using NEG.UI.Popup; | ||||
| using NEG.UI.UnityUi.Popup; | ||||
| using System.Collections.Generic; | ||||
| using UnityEngine; | ||||
| using UnityEngine.AddressableAssets; | ||||
| using UnityEngine.Assertions; | ||||
| using UnityEngine.SceneManagement; | ||||
| 
 | ||||
| namespace NEG.UI.UnityUi | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Implements ui using UnityUI and Unity Event System with New Input System. | ||||
|     /// <para>You have to provide prefabs with addresses:</para> | ||||
|     /// <para> - NEG/UI/PopupCanvas - prefab with canvas to create popups (will be created on every scene)</para> | ||||
|     /// <para> - NEG/UI/DefaultPopupPrefab - prefab of default popup with 2 options (has to have <see cref="MonoDefaultPopup"/> component)</para> | ||||
|     /// </summary> | ||||
|     public class MonoUiManager : UiManager | ||||
|     { | ||||
|         //TODO: use default unity selection | ||||
|         //TODO: window snaping to slots | ||||
|          | ||||
|         private readonly MonoDefaultPopup defaultPopupPrefab; | ||||
|         private readonly GameObject canvasPrefab; | ||||
| 
 | ||||
|         public MonoUiManager(IArea startArea) : base(startArea) | ||||
|         { | ||||
|             var prefabs = | ||||
|                 Addressables.LoadAssetsAsync<GameObject>(new List<string>() { "NEG/UI/PopupCanvas", "NEG/UI/DefaultPopupPrefab" }, (_) => { }, Addressables.MergeMode.Union).WaitForCompletion(); | ||||
|        | ||||
|             Assert.AreEqual(prefabs.Count, 2, "No prefabs was provided. Please check MonoUiManager class documentation"); | ||||
|             Assert.IsNotNull(prefabs[0].GetComponent<Canvas>()); | ||||
|             Assert.IsNotNull(prefabs[1].GetComponent<MonoDefaultPopup>()); | ||||
|              | ||||
|             canvasPrefab = prefabs[0]; | ||||
|             defaultPopupPrefab = prefabs[1].GetComponent<MonoDefaultPopup>(); | ||||
|              | ||||
|             SpawnDefaultPopup(); | ||||
| 
 | ||||
|             SceneManager.activeSceneChanged += (_, _) => SpawnDefaultPopup(); | ||||
|         } | ||||
| 
 | ||||
|         private void SpawnDefaultPopup() | ||||
|         { | ||||
|             var canvas = Object.Instantiate(canvasPrefab); | ||||
|             canvas.name = "DefaultPopupCanvas"; | ||||
|             SetDefaultPopup(Object.Instantiate(defaultPopupPrefab, canvas.transform)); | ||||
|             currentDefaultPopup.Close(true); | ||||
|         } | ||||
|          | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/MonoUiManager.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/MonoUiManager.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: db04ec3144594df1bf4739e142d1b064 | ||||
| timeCreated: 1672155707 | ||||
							
								
								
									
										24
									
								
								NEG/UI/UnityUi/NEG.UI.UnityUi.asmdef
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								NEG/UI/UnityUi/NEG.UI.UnityUi.asmdef
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| { | ||||
|     "name": "NEG.UI.UnityUi", | ||||
|     "rootNamespace": "", | ||||
|     "references": [ | ||||
|         "GUID:343deaaf83e0cee4ca978e7df0b80d21", | ||||
|         "GUID:7361f1d9c43da6649923760766194746", | ||||
|         "GUID:6055be8ebefd69e48b49212b09b47b2f", | ||||
|         "GUID:0c752da273b17c547ae705acf0f2adf2", | ||||
|         "GUID:9e24947de15b9834991c9d8411ea37cf", | ||||
|         "GUID:84651a3751eca9349aac36a66bba901b", | ||||
|         "GUID:23eed6c2401dca1419d1ebd180e58c5a" | ||||
|     ], | ||||
|     "includePlatforms": [], | ||||
|     "excludePlatforms": [], | ||||
|     "allowUnsafeCode": false, | ||||
|     "overrideReferences": false, | ||||
|     "precompiledReferences": [ | ||||
|         "" | ||||
|     ], | ||||
|     "autoReferenced": true, | ||||
|     "defineConstraints": [], | ||||
|     "versionDefines": [], | ||||
|     "noEngineReferences": false | ||||
| } | ||||
							
								
								
									
										7
									
								
								NEG/UI/UnityUi/NEG.UI.UnityUi.asmdef.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								NEG/UI/UnityUi/NEG.UI.UnityUi.asmdef.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: e2aaf8effe1c9634d87b2edda6988a6a | ||||
| AssemblyDefinitionImporter: | ||||
|   externalObjects: {} | ||||
|   userData:  | ||||
|   assetBundleName:  | ||||
|   assetBundleVariant:  | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Popup.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Popup.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 31e9b0c7a4425a248841ec2f02b92157 | ||||
| timeCreated: 1670707809 | ||||
							
								
								
									
										36
									
								
								NEG/UI/UnityUi/Popup/MonoDefaultPopup.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								NEG/UI/UnityUi/Popup/MonoDefaultPopup.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| using NEG.UI.Popup; | ||||
| using NEG.UI.UnityUi.Buttons; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using TMPro; | ||||
| using UnityEngine; | ||||
| 
 | ||||
| namespace NEG.UI.UnityUi.Popup | ||||
| { | ||||
|     public class MonoDefaultPopup : MonoPopup, IDefaultPopup | ||||
|     { | ||||
|         [SerializeField] private TMP_Text titleText; | ||||
|         [SerializeField] private TMP_Text contentText; | ||||
|         [SerializeField] private Transform buttonsParent; | ||||
|         [SerializeField] private BaseButton buttonPrefab; | ||||
| 
 | ||||
|         public void SetContent(string title, string content, List<(string, Action)> options) | ||||
|         { | ||||
|             foreach (Transform child in buttonsParent) | ||||
|             { | ||||
|                 Destroy(child.gameObject); | ||||
|             } | ||||
| 
 | ||||
|             titleText.text = title; | ||||
|             contentText.text = content; | ||||
|              | ||||
|             foreach ((string text, Action action) item in options) | ||||
|             { | ||||
|                 var button = Instantiate(buttonPrefab, buttonsParent); | ||||
|                 button.SetText(item.text); | ||||
|                 button.OnButtonPressed += item.action; | ||||
|                 button.OnButtonPressed += () => Close(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Popup/MonoDefaultPopup.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Popup/MonoDefaultPopup.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 831fb29e6c6d4997a7d471c646eec077 | ||||
| timeCreated: 1672154589 | ||||
							
								
								
									
										30
									
								
								NEG/UI/UnityUi/Popup/MonoPopup.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								NEG/UI/UnityUi/Popup/MonoPopup.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| using NEG.UI.Popup; | ||||
| using System; | ||||
| using UnityEngine; | ||||
| 
 | ||||
| namespace NEG.UI.UnityUi.Popup | ||||
| { | ||||
|     public class MonoPopup : MonoBehaviour, IPopup | ||||
|     { | ||||
|         public event Action<PopupData> OnPopupClosed; | ||||
|          | ||||
|         protected PopupData data; | ||||
| 
 | ||||
|         public void Show(PopupData data) | ||||
|         { | ||||
|             this.data = data; | ||||
|             gameObject.SetActive(true); | ||||
|         } | ||||
| 
 | ||||
|         public void Close(bool silent = false) | ||||
|         { | ||||
|             gameObject.SetActive(false); | ||||
|              | ||||
|             if(silent) | ||||
|                 return; | ||||
|              | ||||
|             OnPopupClosed?.Invoke(data); | ||||
|         } | ||||
|          | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Popup/MonoPopup.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Popup/MonoPopup.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 5d3466b2fe771184eae1ca72c1006d0c | ||||
| timeCreated: 1670707831 | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Window.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Window.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 65adacad835c2cf4b9062296be6098d2 | ||||
| timeCreated: 1670707788 | ||||
							
								
								
									
										59
									
								
								NEG/UI/UnityUi/Window/MonoWindow.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								NEG/UI/UnityUi/Window/MonoWindow.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| using NEG.UI.Area; | ||||
| using NEG.UI.UnityUi.Buttons; | ||||
| using NEG.UI.UnityUi.WindowSlot; | ||||
| using NEG.UI.Window; | ||||
| using NEG.UI.WindowSlot; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using UnityEngine; | ||||
| 
 | ||||
| namespace NEG.UI.UnityUi.Window | ||||
| { | ||||
|     public class MonoWindow : MonoBehaviour, IWindow | ||||
|     { | ||||
|         public IEnumerable<IWindowSlot> AvailableSlots => windowSlots; | ||||
|         public IWindowSlot Parent { get; private set; } | ||||
| 
 | ||||
|         public bool IsMainWindow { get; private set; } | ||||
|          | ||||
|         private IWindowSlot DefaultWindowSlot => windowSlots[0]; | ||||
|          | ||||
|         [SerializeField] private List<MonoWindowSlot> windowSlots; | ||||
|         [SerializeField] private WindowController controller; | ||||
| 
 | ||||
|         public void SetOpenedState(IWindowSlot parentSlot) | ||||
|         { | ||||
|             gameObject.SetActive(true); | ||||
|             Parent = parentSlot; | ||||
|             if (controller != null)  | ||||
|                 controller.OnOpened(); | ||||
|         } | ||||
| 
 | ||||
|         public void SetData(object data) | ||||
|         { | ||||
|             if (controller != null)  | ||||
|                 controller.SetData(data); | ||||
|         } | ||||
| 
 | ||||
|         public void SetClosedState() | ||||
|         { | ||||
|             gameObject.SetActive(false); | ||||
|             Parent = null; | ||||
|             ((ISlotsHolder)this).CloseAllWindows(); | ||||
|         } | ||||
| 
 | ||||
|         private void Awake() => ((IWindow)this).SetClosedState(); | ||||
| 
 | ||||
|         private void OnValidate() | ||||
|         { | ||||
|             if (controller == null) | ||||
|                 controller = GetComponent<WindowController>(); | ||||
|         } | ||||
| 
 | ||||
|         public void OpenWindow(IWindow window, object data = null) | ||||
|         { | ||||
|             DefaultWindowSlot.AttachWindow(window); | ||||
|             window.SetData(data); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Window/MonoWindow.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Window/MonoWindow.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 85d136d6850728d4b96c26fa286ffe3c | ||||
| timeCreated: 1670709296 | ||||
							
								
								
									
										18
									
								
								NEG/UI/UnityUi/Window/WindowController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								NEG/UI/UnityUi/Window/WindowController.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| using System; | ||||
| using UnityEngine; | ||||
| 
 | ||||
| namespace NEG.UI.UnityUi.Window | ||||
| { | ||||
|     [RequireComponent(typeof(MonoWindow))] | ||||
|     //Due to prefab variants we need this | ||||
|     public abstract class WindowController : MonoBehaviour | ||||
|     { | ||||
|         protected MonoWindow window; | ||||
|          | ||||
|         public abstract void SetData(object data); | ||||
| 
 | ||||
|         public abstract void OnOpened(); | ||||
| 
 | ||||
|         protected virtual void Awake() => window = GetComponent<MonoWindow>(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/Window/WindowController.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/Window/WindowController.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 9e3614c1d2b94294937351b640139829 | ||||
| timeCreated: 1672766736 | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/WindowSlot.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/WindowSlot.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 47e385f6fb552d74ab4cf25ef6c76595 | ||||
| timeCreated: 1670707801 | ||||
							
								
								
									
										20
									
								
								NEG/UI/UnityUi/WindowSlot/MonoWindowSlot.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								NEG/UI/UnityUi/WindowSlot/MonoWindowSlot.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| using NEG.UI.Area; | ||||
| using NEG.UI.Window; | ||||
| using NEG.UI.WindowSlot; | ||||
| using UnityEngine; | ||||
| using TNRD; | ||||
| 
 | ||||
| namespace NEG.UI.UnityUi.WindowSlot | ||||
| { | ||||
|     public abstract class MonoWindowSlot : MonoBehaviour, IWindowSlot | ||||
|     { | ||||
|         [field: SerializeField] public bool OpenWindowAsMain { get; private set; } | ||||
|          | ||||
|         public ISlotsHolder ParentHolder => slotsHolder.Value; | ||||
|         public abstract void AttachWindow(IWindow window); | ||||
|         public abstract void DetachWindow(IWindow window); | ||||
|         public abstract void CloseAllWindows(); | ||||
|          | ||||
|         [SerializeField] private SerializableInterface<ISlotsHolder> slotsHolder; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/WindowSlot/MonoWindowSlot.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/WindowSlot/MonoWindowSlot.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: e5a19b184ce9338449ad6ba899a26cda | ||||
| timeCreated: 1670709404 | ||||
							
								
								
									
										26
									
								
								NEG/UI/UnityUi/WindowSlot/SingleWindowSlot.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								NEG/UI/UnityUi/WindowSlot/SingleWindowSlot.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| using NEG.UI.UnityUi.WindowSlot; | ||||
| using NEG.UI.Window; | ||||
| using UnityEngine; | ||||
| 
 | ||||
| namespace NEG.UI.WindowSlot | ||||
| { | ||||
|     public class SingleWindowSlot : MonoWindowSlot | ||||
|     { | ||||
|         public IWindow CurrentWindow | ||||
|         { | ||||
|             get => currentWindow; | ||||
|             set | ||||
|             { | ||||
|                 currentWindow?.SetClosedState(); | ||||
|                 currentWindow = value; | ||||
|                 currentWindow?.SetOpenedState(this); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         private IWindow currentWindow; | ||||
|          | ||||
|         public override void AttachWindow(IWindow window) => CurrentWindow = window; | ||||
|         public override void DetachWindow(IWindow window) => CurrentWindow = null; | ||||
|         public override void CloseAllWindows() => CurrentWindow = null; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/UnityUi/WindowSlot/SingleWindowSlot.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/UnityUi/WindowSlot/SingleWindowSlot.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 79c0738c63b2b5c40b96acd89441f78f | ||||
| timeCreated: 1670716632 | ||||
							
								
								
									
										3
									
								
								NEG/UI/Window.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/Window.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 8e57424db9924004a7945bcbbea7bab9 | ||||
| timeCreated: 1670707788 | ||||
							
								
								
									
										106
									
								
								NEG/UI/Window/IWindow.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								NEG/UI/Window/IWindow.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,106 @@ | ||||
| using JetBrains.Annotations; | ||||
| using NEG.UI.Area; | ||||
| using NEG.UI.WindowSlot; | ||||
| using UnityEngine; | ||||
| 
 | ||||
| namespace NEG.UI.Window | ||||
| { | ||||
|     public interface IWindow : ISlotsHolder | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Parent slot of this window. | ||||
|         /// </summary> | ||||
|         IWindowSlot Parent { get; } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Called internally by slot to open window. | ||||
|         /// </summary> | ||||
|         /// <param name="parentSlot">slot that opens window</param> | ||||
|         void SetOpenedState(IWindowSlot parentSlot); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Sets data for window, usually used for dynamic content set by external logic controller. | ||||
|         /// </summary> | ||||
|         /// <param name="data">can be any type, window should cast for expected type</param> | ||||
|         void SetData(object data); | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Called internally to close window by slot. | ||||
|         /// </summary> | ||||
|         void SetClosedState(); | ||||
|     } | ||||
| 
 | ||||
|     public static class WindowInterfaceExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Opens window as slot child. If slot is null or not provided, as child of current area. | ||||
|         /// </summary> | ||||
|         /// <param name="window">window to open</param> | ||||
|         /// <param name="slot">slot to attach window</param> | ||||
|         /// <param name="data">data to send to window</param> | ||||
|         public static void Open(this IWindow window, IWindowSlot slot = null, object data = null) | ||||
|         { | ||||
|             if (slot != null) | ||||
|             { | ||||
|                 slot.AttachWindow(window); | ||||
|                 window.SetData(data); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             UiManager.Instance.CurrentArea.OpenWindow(window, data); | ||||
|         } | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Opens window as child of selected area. | ||||
|         /// </summary> | ||||
|         /// <param name="window">window to open</param> | ||||
|         /// <param name="area">area to attach window</param> | ||||
|         /// <param name="data">data to send to window</param> | ||||
|         public static void Open(this IWindow window, IArea area, object data = null) => area.OpenWindow(window, data); | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Open passed window as child of this window. | ||||
|         /// </summary> | ||||
|         /// <param name="window">parent window</param> | ||||
|         /// <param name="windowToOpen">window to open</param> | ||||
|         /// <param name="data">data to send to window</param> | ||||
|         public static void OpenChild(this IWindow window, IWindow windowToOpen, object data = null) | ||||
|         { | ||||
|             if (windowToOpen == null) | ||||
|             { | ||||
|                 Debug.LogError($"Window to open cannot be null"); | ||||
|                 return; | ||||
|             } | ||||
|             window.OpenWindow(windowToOpen, data); | ||||
|         } | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Open window as child of provided window. If <typeparamref name="parentWindow"/> is null, as child of current main window in <see cref="UiManager"/>. If there is no main window, open on current area. | ||||
|         /// </summary> | ||||
|         /// <param name="window">window to open</param> | ||||
|         /// <param name="parentWindow">parent window</param> | ||||
|         /// <param name="data">data to send to window</param> | ||||
|         public static void OpenAsChild(this IWindow window, IWindow parentWindow = null, object data = null) | ||||
|         { | ||||
|             if (parentWindow != null) | ||||
|             { | ||||
|                 parentWindow.OpenWindow(window, data); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (UiManager.Instance.CurrentMainWindow != null) | ||||
|             { | ||||
|                 UiManager.Instance.CurrentMainWindow.OpenWindow(window, data); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             UiManager.Instance.CurrentArea.OpenWindow(window, data); | ||||
|         } | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Close window. | ||||
|         /// </summary> | ||||
|         /// <param name="window">window to close</param> | ||||
|         public static void Close(this IWindow window) => window.Parent.DetachWindow(window); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/Window/IWindow.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/Window/IWindow.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: c68ab5f7e5d9440e9fbd26307211e8f1 | ||||
| timeCreated: 1670690267 | ||||
							
								
								
									
										3
									
								
								NEG/UI/WindowSlot.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/WindowSlot.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 1f54322bf2ce451dbfccb7c41e89dd62 | ||||
| timeCreated: 1670707801 | ||||
							
								
								
									
										25
									
								
								NEG/UI/WindowSlot/ISlotsHolder.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								NEG/UI/WindowSlot/ISlotsHolder.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| using NEG.UI.Window; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace NEG.UI.WindowSlot | ||||
| { | ||||
|     public interface ISlotsHolder | ||||
|     { | ||||
|         IEnumerable<IWindowSlot> AvailableSlots { get; } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Open window | ||||
|         /// </summary> | ||||
|         /// <param name="window"></param> | ||||
|         /// <param name="data"></param> | ||||
|         void OpenWindow(IWindow window, object data = null); | ||||
| 
 | ||||
|         void CloseAllWindows() | ||||
|         { | ||||
|             foreach (var slot in AvailableSlots) | ||||
|             { | ||||
|                 slot.CloseAllWindows(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/WindowSlot/ISlotsHolder.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/WindowSlot/ISlotsHolder.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: ace3899aabb0491d80f8b17bd827854b | ||||
| timeCreated: 1674408955 | ||||
							
								
								
									
										14
									
								
								NEG/UI/WindowSlot/IWindowSlot.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								NEG/UI/WindowSlot/IWindowSlot.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| using NEG.UI.Area; | ||||
| using NEG.UI.Window; | ||||
| 
 | ||||
| namespace NEG.UI.WindowSlot | ||||
| { | ||||
|     public interface IWindowSlot | ||||
|     { | ||||
|         bool OpenWindowAsMain { get; } | ||||
|         ISlotsHolder ParentHolder { get; } | ||||
|         void AttachWindow(IWindow window); | ||||
|         void DetachWindow(IWindow window); | ||||
|         void CloseAllWindows(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								NEG/UI/WindowSlot/IWindowSlot.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								NEG/UI/WindowSlot/IWindowSlot.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: f4f7edf281324a2ba86f4099eff57552 | ||||
| timeCreated: 1670694831 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user