BS 0.2.0 Visual

This commit is contained in:
2025-07-21 15:58:52 +08:00
parent f6750189d0
commit d0e5420f95
142 changed files with 11176 additions and 11 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e2f2a62dfceb71643a8a2cd7cbdf42b4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BaseBeginDragBehaviour : MonoBehaviour, IBeginDragHandler, IBehaviourOperator
{
public UnityEvent<PointerEventData> OnBeginDragEvent;
public void OnBeginDrag(PointerEventData eventData)
{
OnBeginDragEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BaseCancelBehaviour : MonoBehaviour, ICancelHandler, IBehaviourOperator
{
public UnityEvent<BaseEventData> OnCancelEvent;
public void OnCancel(BaseEventData eventData)
{
OnCancelEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BaseDeselectBehaviour : MonoBehaviour, IDeselectHandler, IBehaviourOperator
{
public UnityEvent<BaseEventData> OnDeselectEvent;
public void OnDeselect(BaseEventData eventData)
{
OnDeselectEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BaseDragBehaviour : MonoBehaviour, IDragHandler, IBehaviourOperator
{
public UnityEvent<PointerEventData> OnDragEvent;
public void OnDrag(PointerEventData eventData)
{
OnDragEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BaseDropBehaviour : MonoBehaviour, IDropHandler, IBehaviourOperator
{
public UnityEvent<PointerEventData> OnDropEvent;
public void OnDrop(PointerEventData eventData)
{
OnDropEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BaseEndDragBehaviour : MonoBehaviour, IEndDragHandler, IBehaviourOperator
{
public UnityEvent<PointerEventData> OnEndDragEvent;
public void OnEndDrag(PointerEventData eventData)
{
OnEndDragEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BaseInitializePotentialDragBehaviour : MonoBehaviour, IInitializePotentialDragHandler, IBehaviourOperator
{
public UnityEvent<PointerEventData> OnInitializePotentialDragEvent;
public void OnInitializePotentialDrag(PointerEventData eventData)
{
OnInitializePotentialDragEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BaseMoveBehaviour : MonoBehaviour, IMoveHandler, IBehaviourOperator
{
public UnityEvent<AxisEventData> OnMoveEvent;
public void OnMove(AxisEventData eventData)
{
OnMoveEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BasePointerClickBehaviour : MonoBehaviour, IPointerClickHandler, IBehaviourOperator
{
public UnityEvent<PointerEventData> OnPointerClickEvent;
public void OnPointerClick(PointerEventData eventData)
{
OnPointerClickEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BasePointerDownBehaviour : MonoBehaviour, IPointerDownHandler, IBehaviourOperator
{
public UnityEvent<PointerEventData> OnPointerDownEvent;
public void OnPointerDown(PointerEventData eventData)
{
OnPointerDownEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BasePointerEnterBehaviour : MonoBehaviour, IPointerEnterHandler, IBehaviourOperator
{
public UnityEvent<PointerEventData> OnPointerEnterEvent;
public void OnPointerEnter(PointerEventData eventData)
{
OnPointerEnterEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BasePointerExitBehaviour : MonoBehaviour, IPointerExitHandler, IBehaviourOperator
{
public UnityEvent<PointerEventData> OnPointerExitEvent;
public void OnPointerExit(PointerEventData eventData)
{
OnPointerExitEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BasePointerUpBehaviour : MonoBehaviour, IPointerUpHandler, IBehaviourOperator
{
public UnityEvent<PointerEventData> OnPointerUpEvent;
public void OnPointerUp(PointerEventData eventData)
{
OnPointerUpEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BaseScrollBehaviour : MonoBehaviour, IScrollHandler, IBehaviourOperator
{
public UnityEvent<PointerEventData> OnScrollEvent;
public void OnScroll(PointerEventData eventData)
{
OnScrollEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BaseSelectBehaviour : MonoBehaviour, ISelectHandler, IBehaviourOperator
{
public UnityEvent<BaseEventData> OnSelectEvent;
public void OnSelect(BaseEventData eventData)
{
OnSelectEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BaseSubmitBehaviour : MonoBehaviour, ISubmitHandler, IBehaviourOperator
{
public UnityEvent<BaseEventData> OnSubmitEvent;
public void OnSubmit(BaseEventData eventData)
{
OnSubmitEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class BaseUpdateSelectedBehaviour : MonoBehaviour, IUpdateSelectedHandler, IBehaviourOperator
{
public UnityEvent<BaseEventData> OnUpdateSelectedEvent;
public void OnUpdateSelected(BaseEventData eventData)
{
OnUpdateSelectedEvent?.Invoke(eventData);
}
}
}

View File

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

View File

@@ -0,0 +1,117 @@
using UnityEngine;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
public class DragBehaviour : WindowsComponent
{
[SerializeField, Resources] private BehaviourContextManager Context = null;
public BehaviourContextManager GetBehaviourContext()
{
if (Context == null)
Context = this.GetOrAddComponent<BehaviourContextManager>();
return Context;
}
public BehaviourContextManager DragBehaviourContext
{
get
{
if (Context == null)
Context = this.GetOrAddComponent<BehaviourContextManager>();
return Context;
}
}
[Setting] public bool isCanDrag = true;
public void SetDragAble(bool isCanDrag)
{
this.isCanDrag = isCanDrag;
}
public void Init([In, Opt] RectTransform DragObjectInternal, [In, Opt] RectTransform DragAreaInternal)
{
if (DragObjectInternal != null)
this.DragObjectInternal = DragObjectInternal;
else if (this.DragObjectInternal == null)
this.DragObjectInternal = rectTransform;
if (DragAreaInternal != null)
this.DragAreaInternal = DragAreaInternal;
else if (this.DragAreaInternal == null)
this.DragAreaInternal = rectTransform.parent as RectTransform;
DragBehaviourContext.OnBeginDragEvent ??= new();
DragBehaviourContext.OnDragEvent ??= new();
DragBehaviourContext.OnBeginDragEvent.RemoveListener(this.OnBeginDrag);
DragBehaviourContext.OnBeginDragEvent.AddListener(this.OnBeginDrag);
DragBehaviourContext.OnDragEvent.RemoveListener(this.OnDrag);
DragBehaviourContext.OnDragEvent.AddListener(this.OnDrag);
DragBehaviourContext.locationValid = IsRaycastLocationValid;
}
[Setting] public bool IsAutoInit = true;
private void Start()
{
Init(null, null);
}
private void Reset()
{
isCanDrag = true;
DragObjectInternal = rectTransform;
}
[Setting] public bool topOnClick = true;
[Content, Ignore, OnlyPlayMode, SerializeField] private Vector2 originalLocalPointerPosition;
[Content, Ignore, OnlyPlayMode, SerializeField] private Vector3 originalPanelLocalPosition;
[Resources, SerializeField] private RectTransform DragObjectInternal;
[Resources, SerializeField, WhenAttribute.Not(nameof(DragObjectInternal), null)] private RectTransform DragAreaInternal;
public void OnBeginDrag(PointerEventData data)
{
if (!isCanDrag) return;
originalPanelLocalPosition = DragObjectInternal.localPosition;
RectTransformUtility.ScreenPointToLocalPointInRectangle(DragAreaInternal, data.position, data.pressEventCamera, out originalLocalPointerPosition);
gameObject.transform.SetAsLastSibling();
if (topOnClick == true)
DragObjectInternal.SetAsLastSibling();
}
public void OnDrag(PointerEventData data)
{
if (!isCanDrag) return;
Vector2 localPointerPosition;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(DragAreaInternal, data.position, data.pressEventCamera, out localPointerPosition))
{
Vector3 offsetToOriginal = localPointerPosition - originalLocalPointerPosition;
DragObjectInternal.localPosition = originalPanelLocalPosition + offsetToOriginal;
}
ClampToArea();
}
private void ClampToArea()
{
Vector3 pos = DragObjectInternal.localPosition;
Vector3 minPosition = DragAreaInternal.rect.min - DragObjectInternal.rect.min;
Vector3 maxPosition = DragAreaInternal.rect.max - DragObjectInternal.rect.max;
pos.x = Mathf.Clamp(DragObjectInternal.localPosition.x, minPosition.x, maxPosition.x);
pos.y = Mathf.Clamp(DragObjectInternal.localPosition.y, minPosition.y, maxPosition.y);
DragObjectInternal.localPosition = pos;
}
public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
{
return isCanDrag || transform.childCount != 0;
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 84a533f8e4805914580808722555eb7a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,276 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
namespace Convention.WindowsUI
{
public class BaseWindowBar : WindowsComponent
{
// -----------------
private bool use_VerticalLayoutGroup => layoutGroupType == LayoutGroupType.VerticalLayoutGroup && verticalLayoutGroup;
private bool use_HorizontalLayoutGroup => layoutGroupType == LayoutGroupType.HorizontalLayoutGroup && horizontalLayoutGroup;
private bool use_GridLayoutGroup => layoutGroupType == LayoutGroupType.GridLayoutGroup && gridLayoutGroup;
// -----------------
[Setting] public bool IsMaxInTop = true;
[Setting] public bool IsMinInButtm = true;
public bool hasLayoutGroup => layoutGroupType != LayoutGroupType.None;
[Resources, Setting, HopeNotNull] public SO.Windows WindowConfig;
[Resources, SerializeField, HopeNotNull] private RectTransform BarPlane;
[Resources, SerializeField, HopeNotNull] private WindowManager m_WindowManager;
[Resources, HopeNotNull] public WindowUIModule ButtonPrefab;
[Content, OnlyPlayMode]
public void MinimizeWindow()
{
if (m_WindowManager)
{
if (IsMinInButtm)
m_WindowManager.transform.SetAsFirstSibling();
m_WindowManager.WindowPlane.ExitMaximizeWindowMode();
}
}
[Content, OnlyPlayMode]
public void MaximizeWindow()
{
if (m_WindowManager)
{
m_WindowManager.WindowPlane.MaximizeWindow();
if (IsMaxInTop)
m_WindowManager.transform.SetAsLastSibling();
}
}
[Content, OnlyPlayMode]
public void CloseWindow()
{
if (m_WindowManager)
{
m_WindowManager.CloseWindow();
}
}
public enum LayoutGroupType
{
VerticalLayoutGroup,
HorizontalLayoutGroup,
GridLayoutGroup,
None
}
[Setting] public LayoutGroupType layoutGroupType = LayoutGroupType.VerticalLayoutGroup;
[Resources, Setting, SerializeField, Header("Vertical Layout Group Setting")]
[HopeNotNull, WhenAttribute.Is(nameof(layoutGroupType), LayoutGroupType.VerticalLayoutGroup)]
private VerticalLayoutGroup verticalLayoutGroup;
[Resources, Setting, SerializeField, Header("Horizontal Layout Group Setting")]
[HopeNotNull, WhenAttribute.Is(nameof(layoutGroupType), LayoutGroupType.HorizontalLayoutGroup)]
private HorizontalLayoutGroup horizontalLayoutGroup;
[Resources, Setting, SerializeField, Header("Grid Layout Group")]
[HopeNotNull, WhenAttribute.Is(nameof(layoutGroupType), LayoutGroupType.GridLayoutGroup)]
private GridLayoutGroup gridLayoutGroup;
public void Reset()
{
WindowConfig = Resources.Load<SO.Windows>(SO.Windows.GlobalWindowsConfig);
BarPlane = rectTransform;
ResetWindowManager();
ButtonPrefab = WindowConfig.GetWindowsUI<IButton>(nameof(ModernUIButton)) as WindowUIModule;
layoutGroupType = LayoutGroupType.HorizontalLayoutGroup;
ResetLayoutGroups(false);
}
private void ResetLayoutGroups(bool isDestroy)
{
if (verticalLayoutGroup == null)
verticalLayoutGroup = BarPlane.GetComponent<VerticalLayoutGroup>();
if (horizontalLayoutGroup == null)
horizontalLayoutGroup = BarPlane.GetComponent<HorizontalLayoutGroup>();
if (gridLayoutGroup == null)
gridLayoutGroup = BarPlane.GetComponent<GridLayoutGroup>();
if (!isDestroy)
return;
if (verticalLayoutGroup && layoutGroupType != LayoutGroupType.VerticalLayoutGroup)
Destroy(verticalLayoutGroup);
if (horizontalLayoutGroup && layoutGroupType != LayoutGroupType.HorizontalLayoutGroup)
Destroy(horizontalLayoutGroup);
if (gridLayoutGroup && layoutGroupType != LayoutGroupType.GridLayoutGroup)
Destroy(gridLayoutGroup);
}
private void ResetWindowManager()
{
m_WindowManager = null;
for (Transform item = transform; m_WindowManager == null && item != null; item = item.parent)
{
m_WindowManager = item.gameObject.GetComponent<WindowManager>();
}
}
private void Start()
{
if (BarPlane == null)
BarPlane = rectTransform;
if (m_WindowManager == null)
{
ResetWindowManager();
}
ResetLayoutGroups(true);
}
private IButton InstantiateButton()
{
return Instantiate(ButtonPrefab, BarPlane.transform).GetComponents<IButton>()[0];
}
[Serializable]
public class RegisteredButtonWrapper
{
public readonly BaseWindowBar WindowBar;
public IButton button;
public WindowUIModule buttonModule;
public RegisteredButtonWrapper([In] BaseWindowBar parentBar, [In] IButton button)
{
WindowBar = parentBar;
this.button = button;
buttonModule = button as WindowUIModule;
}
public virtual void Disable()
{
if (buttonModule)
{
buttonModule.gameObject.SetActive(false);
if (WindowBar.useGUILayout)
{
LayoutRebuilder.ForceRebuildLayoutImmediate(WindowBar.BarPlane);
}
}
}
public virtual void Enable()
{
if (buttonModule)
{
buttonModule.gameObject.SetActive(true);
if (WindowBar.useGUILayout)
{
LayoutRebuilder.ForceRebuildLayoutImmediate(WindowBar.BarPlane);
}
}
}
public virtual void Release()
{
if (button == null)
{
throw new InvalidOperationException("wrapper was released");
}
if (buttonModule)
{
Disable();
Destroy(buttonModule.gameObject);
if (WindowBar.useGUILayout)
{
LayoutRebuilder.ForceRebuildLayoutImmediate(WindowBar.BarPlane);
}
}
button = null;
}
~RegisteredButtonWrapper()
{
Release();
}
}
[return: ReturnNotNull, ReturnVirtual]
public virtual RegisteredButtonWrapper RegisterButton()
{
return new RegisteredButtonWrapper(this, InstantiateButton());
}
[Serializable]
public class RegisteredPageWrapper : RegisteredButtonWrapper
{
[SerializeField]private int PageIndex = -1;
[SerializeField]private RectTransform plane, root;
public RegisteredPageWrapper(RectTransform plane, RectTransform root, [In] BaseWindowBar parentBar, [In] IButton button) : base(parentBar, button)
{
button.AddListener(() => WindowBar.m_WindowManager.SelectContextPlane(PageIndex));
PageIndex = parentBar.m_WindowManager.AddContextPlane(plane, root);
this.plane = plane;
this.root = root;
}
public RegisteredPageWrapper(RectTransform plane, [In] BaseWindowBar parentBar, [In] IButton button) : base(parentBar, button)
{
button.AddListener(() => WindowBar.m_WindowManager.SelectContextPlane(PageIndex));
PageIndex = parentBar.m_WindowManager.AddContextPlane(plane);
this.plane = plane;
}
public override void Disable()
{
if (PageIndex < 0)
{
return;
}
WindowBar.m_WindowManager.RemoveContextPlane(PageIndex);
PageIndex = -1;
base.Disable();
}
public override void Enable()
{
if (PageIndex < 0)
{
WindowBar.m_WindowManager.AddContextPlane(plane, root);
base.Enable();
}
}
public override void Release()
{
if (Application.isPlaying)
{
if (!plane)
throw new InvalidOperationException("page was released");
else
return;
}
if (root)
{
root.gameObject.SetActive(false);
Destroy(root);
}
else
{
plane.gameObject.SetActive(false);
Destroy(plane);
}
base.Release();
plane = null;
root = null;
}
public virtual void Select()
{
if (PageIndex < 0)
return;
WindowBar.m_WindowManager.SelectContextPlane(PageIndex);
}
}
[return: ReturnNotNull, ReturnVirtual]
public virtual RegisteredPageWrapper RegisterPage([In] RectTransform plane, [In] RectTransform root)
{
return new RegisteredPageWrapper(plane, root, this, InstantiateButton());
}
[return: ReturnNotNull, ReturnVirtual]
public virtual RegisteredPageWrapper RegisterPage([In] RectTransform plane)
{
return new RegisteredPageWrapper(plane, this, InstantiateButton());
}
public virtual IEnumerable<IButton> GetAllButton()
{
List<IButton> result = new();
foreach(IButton button in BarPlane.transform)
{
result.Add(button);
}
return result;
}
}
}

View File

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

View File

@@ -0,0 +1,124 @@
using System;
using UnityEngine;
using UnityEngine.UI;
namespace Convention.WindowsUI
{
public class BaseWindowPlane : WindowsComponent
{
[Resources, SerializeField, OnlyNotNullMode] private RectTransform m_Plane;
[Resources, SerializeField, HopeNotNull, Tooltip("This animational plane should has the same parent transform")]
private RectTransform m_AnimationPlane;
[Setting, OnlyNotNullMode(nameof(m_AnimationPlane)), SerializeField, Header("Animation Setting")]
private bool IsEnableAnimation = true;
[Setting, OnlyNotNullMode(nameof(m_AnimationPlane)), Percentage(0, 1), Range(0, 1), WhenAttribute.Is(nameof(IsEnableAnimation), true)]
public float AnimationSpeed = 0.5f;
public RectTransform Plane => m_Plane;
[Content, OnlyPlayMode, Ignore] public RectTransformInfo BeforeMaximizeWindow = null;
[Content, OnlyPlayMode, Ignore] public float BeforeMaximizeWindowBackgroundColorA = 1f;
private bool IsMaximizeWindowMode = false;
[Content, OnlyPlayMode]
public void MaximizeWindow()
{
if (IsMaximizeWindowMode)
return;
BeforeMaximizeWindow = new(m_Plane);
var prect = m_Plane.transform.parent.GetComponent<RectTransform>();
m_Plane.SetPositionAndRotation(prect.position, prect.rotation);
m_Plane.anchoredPosition = Vector3.zero;
m_Plane.anchorMax = Vector2.one;
m_Plane.anchorMin = Vector2.zero;
m_Plane.sizeDelta = Vector2.zero;
var backgroundPlane = m_AnimationPlane == null ? m_Plane : m_AnimationPlane;
if (backgroundPlane.TryGetComponent<Image>(out var image))
{
BeforeMaximizeWindowBackgroundColorA = image.color.a;
var color = image.color;
color.a = 1;
image.color = color;
}
IsMaximizeWindowMode = true;
}
[Content, OnlyPlayMode]
public void ExitMaximizeWindowMode()
{
if (!IsMaximizeWindowMode)
return;
BeforeMaximizeWindow.Setup(m_Plane);
var backgroundPlane = m_AnimationPlane == null ? m_Plane : m_AnimationPlane;
if (backgroundPlane.TryGetComponent<Image>(out var image))
{
var color = image.color;
color.a = BeforeMaximizeWindowBackgroundColorA;
image.color = color;
}
IsMaximizeWindowMode = false;
}
private void OnEnable()
{
if (m_AnimationPlane != null)
{
new RectTransformInfo(m_Plane).Setup(m_AnimationPlane);
}
}
[Content]
public void SynchronizedAnimationPlane()
{
new RectTransformInfo(m_Plane).Setup(m_AnimationPlane);
}
private void LateUpdate()
{
if (IsEnableAnimation && m_Plane && m_AnimationPlane)
{
RectTransformInfo.UpdateAnimationPlane(m_Plane, m_AnimationPlane, AnimationSpeed, IsMaximizeWindowMode ? 1 : -1, false);
}
}
public virtual void AddChild(RectTransform target, Rect rect, bool isAdjustSizeToContainsChilds = false)
{
RectTransformExtension.SetParentAndResizeWithoutNotifyBaseWindowPlane(m_Plane, target, rect, isAdjustSizeToContainsChilds);
}
public virtual void AddChild(RectTransform target, bool isAdjustSizeToContainsChilds = false)
{
RectTransformExtension.SetParentAndResizeWithoutNotifyBaseWindowPlane(m_Plane, target, isAdjustSizeToContainsChilds);
}
[Content]
public void ForceRebuildLayoutImmediate()
{
LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform);
}
[Resources, Tooltip("before AdjustSizeToContainsChilds, will compute it first")] public RectTransform AdjustSizeToContainsRect;
[Content]
public void AdjustSizeToContainsChilds()
{
if (AdjustSizeToContainsRect == null)
RectTransformExtension.AdjustSizeToContainsChilds(rectTransform);
else
{
var corners = new Vector3[4];
Vector2 min = new Vector2(float.MaxValue, float.MaxValue);
Vector2 max = new Vector2(float.MinValue, float.MinValue);
AdjustSizeToContainsRect.GetWorldCorners(corners);
foreach (var corner in corners)
{
Vector2 localCorner = rectTransform.InverseTransformPoint(corner);
if (float.IsNaN(localCorner.x) || float.IsNaN(localCorner.y))
break;
min.x = Mathf.Min(min.x, localCorner.x);
min.y = Mathf.Min(min.y, localCorner.y);
max.x = Mathf.Max(max.x, localCorner.x);
max.y = Mathf.Max(max.y, localCorner.y);
}
RectTransformExtension.AdjustSizeToContainsChilds(rectTransform, min, max, null);
}
}
}
}

View File

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

View File

@@ -0,0 +1,252 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1102 &-8092253087371084152
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: ExitFocusInspector
m_Speed: -1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: 9525128e21aed17438d2688e99e7e20d, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-6082174505553466741
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: ExitFullMainWindow
m_Speed: -1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: 3c2a3f60d986c0149bf92b6d3983302e, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-3932555576849271677
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: New State
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 0}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-2403780335683535720
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: FullMainWindow
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: 3c2a3f60d986c0149bf92b6d3983302e, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Canvas
serializedVersion: 5
m_AnimatorParameters:
- m_Name: IsFocus
m_Type: 4
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 9100000}
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: 1296624602851365648}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!1107 &1296624602851365648
AnimatorStateMachine:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: 6070089197181197078}
m_Position: {x: 450, y: -10, z: 0}
- serializedVersion: 1
m_State: {fileID: -3932555576849271677}
m_Position: {x: 10, y: 70, z: 0}
- serializedVersion: 1
m_State: {fileID: 1675010782392993655}
m_Position: {x: 450, y: 50, z: 0}
- serializedVersion: 1
m_State: {fileID: -2403780335683535720}
m_Position: {x: 670, y: -10, z: 0}
- serializedVersion: 1
m_State: {fileID: -6082174505553466741}
m_Position: {x: 670, y: 50, z: 0}
- serializedVersion: 1
m_State: {fileID: 1810835025064308519}
m_Position: {x: 450, y: 110, z: 0}
- serializedVersion: 1
m_State: {fileID: -8092253087371084152}
m_Position: {x: 450, y: 160, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 50, y: 120, z: 0}
m_ExitPosition: {x: 50, y: -20, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: -3932555576849271677}
--- !u!1102 &1675010782392993655
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: ExitFocusMainWindow
m_Speed: -1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: ca95e26c36202a54fb6f43ca904d2bcf, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &1810835025064308519
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: FocusInspector
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: 9525128e21aed17438d2688e99e7e20d, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &6070089197181197078
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: FocusMainWindow
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: ca95e26c36202a54fb6f43ca904d2bcf, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e407ea59aaf27714e830a008e8f5f2f3
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
namespace Convention.WindowsUI
{
public class ClickBoard : WindowUIModule
{
[Resources] public BehaviourContextManager Context;
[Setting] public UnityEvent<PointerEventData> LeftButtonClick = new();
[Setting] public UnityEvent<PointerEventData> RightButtonClick = new();
private void Start()
{
if (Context == null)
Context = this.GetOrAddComponent<BehaviourContextManager>();
Context.OnPointerClickEvent = BehaviourContextManager.InitializeContextSingleEvent(Context.OnPointerClickEvent, point =>
{
if (point.button == PointerEventData.InputButton.Left)
{
LeftButtonClick.Invoke(point);
}
if (point.button == PointerEventData.InputButton.Right)
{
RightButtonClick.Invoke(point);
}
});
}
}
}

View File

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

View File

@@ -0,0 +1,49 @@
using System.Collections.Generic;
using Convention.WindowsUI;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace Convention
{
public class CustomMenu : WindowsComponent
{
[Setting, SerializeField] private bool IsDestroy = true;
[Resources, SerializeField, OnlyNotNullMode] private Button ButtonPrefab;
[Resources, SerializeField, OnlyNotNullMode] private RectTransform Plane;
[Content] public List<GameObject> childs = new();
[Content, OnlyPlayMode]
[return: IsInstantiated(true)]
public virtual Button CreateItem()
{
var item = GameObject.Instantiate(ButtonPrefab, Plane).GetComponent<Button>();
item.gameObject.SetActive(true);
childs.Add(item.gameObject);
return item;
}
[return: IsInstantiated(true)]
public virtual Button CreateItem(UnityAction callback, string title)
{
var item = CreateItem();
item.onClick.AddListener(callback);
item.GetComponents<IText>()[0].text = title;
return item;
}
public virtual void ClearAllItem()
{
foreach (var child in childs)
{
GameObject.Destroy(child);
}
childs.Clear();
}
public virtual void ReleaseMenu()
{
if (IsDestroy)
Destroy(this.gameObject);
else
gameObject.SetActive(false);
}
}
}

View File

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

View File

@@ -0,0 +1,746 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: FocusInspector
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves:
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: -500
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_AnchoredPosition.x
path: Hierarchy
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: -500
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_AnchoredPosition.x
path: Tools
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: -400
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: -400
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_SizeDelta.x
path: Assets
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: -200
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: -700
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_AnchoredPosition.x
path: Assets
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 200
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: 700
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_SizeDelta.x
path: Inspector
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: -500
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_AnchoredPosition.x
path: Main
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: -400
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: -400
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_SizeDelta.x
path: Main
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 100
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.083333336
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.25
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_AnchoredPosition.x
path: EditorBar
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: -200
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.083333336
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.25
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_SizeDelta.x
path: EditorBar
classID: 224
script: {fileID: 0}
flags: 0
m_PPtrCurves: []
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 2022418957
attribute: 1460864421
script: {fileID: 0}
typeID: 224
customType: 28
isPPtrCurve: 0
isIntCurve: 0
isSerializeReferenceCurve: 0
- serializedVersion: 2
path: 725348723
attribute: 1460864421
script: {fileID: 0}
typeID: 224
customType: 28
isPPtrCurve: 0
isIntCurve: 0
isSerializeReferenceCurve: 0
- serializedVersion: 2
path: 2122152120
attribute: 1460864421
script: {fileID: 0}
typeID: 224
customType: 28
isPPtrCurve: 0
isIntCurve: 0
isSerializeReferenceCurve: 0
- serializedVersion: 2
path: 4029469480
attribute: 1967290853
script: {fileID: 0}
typeID: 224
customType: 28
isPPtrCurve: 0
isIntCurve: 0
isSerializeReferenceCurve: 0
- serializedVersion: 2
path: 521822810
attribute: 1460864421
script: {fileID: 0}
typeID: 224
customType: 28
isPPtrCurve: 0
isIntCurve: 0
isSerializeReferenceCurve: 0
- serializedVersion: 2
path: 3281461653
attribute: 1460864421
script: {fileID: 0}
typeID: 224
customType: 28
isPPtrCurve: 0
isIntCurve: 0
isSerializeReferenceCurve: 0
- serializedVersion: 2
path: 3281461653
attribute: 1967290853
script: {fileID: 0}
typeID: 224
customType: 28
isPPtrCurve: 0
isIntCurve: 0
isSerializeReferenceCurve: 0
- serializedVersion: 2
path: 2122152120
attribute: 1967290853
script: {fileID: 0}
typeID: 224
customType: 28
isPPtrCurve: 0
isIntCurve: 0
isSerializeReferenceCurve: 0
- serializedVersion: 2
path: 521822810
attribute: 1967290853
script: {fileID: 0}
typeID: 224
customType: 28
isPPtrCurve: 0
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping: []
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.5
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 0
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves:
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: -500
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_AnchoredPosition.x
path: Hierarchy
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: -500
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_AnchoredPosition.x
path: Tools
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: -400
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: -400
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_SizeDelta.x
path: Assets
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: -200
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: -700
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_AnchoredPosition.x
path: Assets
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 200
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: 700
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_SizeDelta.x
path: Inspector
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: -500
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_AnchoredPosition.x
path: Main
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: -400
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: -400
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_SizeDelta.x
path: Main
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 100
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.083333336
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.25
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_AnchoredPosition.x
path: EditorBar
classID: 224
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: -200
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.083333336
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.25
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_SizeDelta.x
path: EditorBar
classID: 224
script: {fileID: 0}
flags: 0
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9525128e21aed17438d2688e99e7e20d
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ca95e26c36202a54fb6f43ca904d2bcf
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3c2a3f60d986c0149bf92b6d3983302e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,490 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace Convention
{
public class GradientEffect : BaseMeshEffect
{
[return: ReturnNotNull]
public string SymbolName()
{
return GetType().Name;
}
[SerializeField]
Type _gradientType;
[Setting, SerializeField]
private Blend _blendMode = Blend.Multiply;
[Setting, SerializeField]
private bool _modifyVertices = true;
[Setting, SerializeField, Range(-1, 1)]
private float m_offset = 0f;
[Setting, SerializeField, Range(0.1f, 10)]
private float m_zoom = 1f;
[Setting]
public Gradient m_effectGradient = new Gradient()
{
colorKeys = new GradientColorKey[]
{
new GradientColorKey(Color.white, 1),
new GradientColorKey(Color.white, 1)
}
};
public Blend BlendMode
{
get { return _blendMode; }
set
{
_blendMode = value;
graphic.SetVerticesDirty();
}
}
public Gradient EffectGradient
{
get { return m_effectGradient; }
set
{
m_effectGradient = value;
graphic.SetVerticesDirty();
}
}
public Type GradientType
{
get { return _gradientType; }
set
{
_gradientType = value;
graphic.SetVerticesDirty();
}
}
public bool ModifyVertices
{
get { return _modifyVertices; }
set
{
_modifyVertices = value;
graphic.SetVerticesDirty();
}
}
public float Offset
{
get { return m_offset; }
set
{
m_offset = Mathf.Clamp(value, -1f, 1f);
graphic.SetVerticesDirty();
}
}
public float Zoom
{
get { return m_zoom; }
set
{
m_zoom = Mathf.Clamp(value, 0.1f, 10f);
graphic.SetVerticesDirty();
}
}
public enum Type
{
Horizontal,
Vertical,
Diamond
}
public enum Blend
{
Override,
Add,
Multiply
}
#region Gradient
public override void ModifyMesh(VertexHelper helper)
{
if (!IsActive() || helper.currentVertCount == 0)
return;
List<UIVertex> _vertexList = new List<UIVertex>();
helper.GetUIVertexStream(_vertexList);
int nCount = _vertexList.Count;
switch (GradientType)
{
case Type.Horizontal:
case Type.Vertical:
{
Rect bounds = GetBounds(_vertexList);
float min = bounds.xMin;
float w = bounds.width;
Func<UIVertex, float> GetPosition = v => v.position.x;
if (GradientType == Type.Vertical)
{
min = bounds.yMin;
w = bounds.height;
GetPosition = v => v.position.y;
}
float width = w == 0f ? 0f : 1f / w / Zoom;
float zoomOffset = (1 - (1 / Zoom)) * 0.5f;
float offset = (Offset * (1 - zoomOffset)) - zoomOffset;
if (ModifyVertices)
SplitTrianglesAtGradientStops(_vertexList, bounds, zoomOffset, helper);
UIVertex vertex = new UIVertex();
for (int i = 0; i < helper.currentVertCount; i++)
{
helper.PopulateUIVertex(ref vertex, i);
vertex.color = BlendColor(vertex.color, EffectGradient.Evaluate((GetPosition(vertex) - min) * width - offset));
helper.SetUIVertex(vertex, i);
}
}
break;
case Type.Diamond:
{
Rect bounds = GetBounds(_vertexList);
float height = bounds.height == 0f ? 0f : 1f / bounds.height / Zoom;
float radius = bounds.center.y / 2f;
Vector3 center = (Vector3.right + Vector3.up) * radius + Vector3.forward * _vertexList[0].position.z;
if (ModifyVertices)
{
helper.Clear();
for (int i = 0; i < nCount; i++) helper.AddVert(_vertexList[i]);
UIVertex centralVertex = new UIVertex();
centralVertex.position = center;
centralVertex.normal = _vertexList[0].normal;
centralVertex.uv0 = new Vector2(0.5f, 0.5f);
centralVertex.color = Color.white;
helper.AddVert(centralVertex);
for (int i = 1; i < nCount; i++) helper.AddTriangle(i - 1, i, nCount);
helper.AddTriangle(0, nCount - 1, nCount);
}
UIVertex vertex = new UIVertex();
for (int i = 0; i < helper.currentVertCount; i++)
{
helper.PopulateUIVertex(ref vertex, i);
vertex.color = BlendColor(vertex.color, EffectGradient.Evaluate(
Vector3.Distance(vertex.position, center) * height - Offset));
helper.SetUIVertex(vertex, i);
}
}
break;
}
}
private Rect GetBounds(List<UIVertex> vertices)
{
float left = vertices[0].position.x;
float right = left;
float bottom = vertices[0].position.y;
float top = bottom;
for (int i = vertices.Count - 1; i >= 1; --i)
{
float x = vertices[i].position.x;
float y = vertices[i].position.y;
if (x > right)
right = x;
else if (x < left)
left = x;
if (y > top)
top = y;
else if (y < bottom)
bottom = y;
}
return new Rect(left, bottom, right - left, top - bottom);
}
private void SplitTrianglesAtGradientStops(List<UIVertex> _vertexList, Rect bounds, float zoomOffset, VertexHelper helper)
{
List<float> stops = FindStops(zoomOffset, bounds);
if (stops.Count > 0)
{
helper.Clear();
int nCount = _vertexList.Count;
for (int i = 0; i < nCount; i += 3)
{
float[] positions = GetPositions(_vertexList, i);
List<int> originIndices = new List<int>(3);
List<UIVertex> starts = new List<UIVertex>(3);
List<UIVertex> ends = new List<UIVertex>(2);
for (int s = 0; s < stops.Count; s++)
{
int initialCount = helper.currentVertCount;
bool hadEnds = ends.Count > 0;
bool earlyStart = false;
for (int p = 0; p < 3; p++)
{
if (!originIndices.Contains(p) && positions[p] < stops[s])
{
int p1 = (p + 1) % 3;
var start = _vertexList[p + i];
if (positions[p1] > stops[s])
{
originIndices.Insert(0, p);
starts.Insert(0, start);
earlyStart = true;
}
else
{
originIndices.Add(p);
starts.Add(start);
}
}
}
if (originIndices.Count == 0)
continue;
if (originIndices.Count == 3)
break;
foreach (var start in starts)
helper.AddVert(start);
ends.Clear();
foreach (int index in originIndices)
{
int oppositeIndex = (index + 1) % 3;
if (positions[oppositeIndex] < stops[s])
oppositeIndex = (oppositeIndex + 1) % 3;
ends.Add(CreateSplitVertex(_vertexList[index + i], _vertexList[oppositeIndex + i], stops[s]));
}
if (ends.Count == 1)
{
int oppositeIndex = (originIndices[0] + 2) % 3;
ends.Add(CreateSplitVertex(_vertexList[originIndices[0] + i], _vertexList[oppositeIndex + i], stops[s]));
}
foreach (var end in ends)
helper.AddVert(end);
if (hadEnds)
{
helper.AddTriangle(initialCount - 2, initialCount, initialCount + 1);
helper.AddTriangle(initialCount - 2, initialCount + 1, initialCount - 1);
if (starts.Count > 0)
{
if (earlyStart)
helper.AddTriangle(initialCount - 2, initialCount + 3, initialCount);
else
helper.AddTriangle(initialCount + 1, initialCount + 3, initialCount - 1);
}
}
else
{
int vertexCount = helper.currentVertCount;
helper.AddTriangle(initialCount, vertexCount - 2, vertexCount - 1);
if (starts.Count > 1)
helper.AddTriangle(initialCount, vertexCount - 1, initialCount + 1);
}
starts.Clear();
}
if (ends.Count > 0)
{
if (starts.Count == 0)
{
for (int p = 0; p < 3; p++)
{
if (!originIndices.Contains(p) && positions[p] > stops[stops.Count - 1])
{
int p1 = (p + 1) % 3;
UIVertex end = _vertexList[p + i];
if (positions[p1] > stops[stops.Count - 1])
starts.Insert(0, end);
else
starts.Add(end);
}
}
}
foreach (var start in starts)
helper.AddVert(start);
int vertexCount = helper.currentVertCount;
if (starts.Count > 1)
{
helper.AddTriangle(vertexCount - 4, vertexCount - 2, vertexCount - 1);
helper.AddTriangle(vertexCount - 4, vertexCount - 1, vertexCount - 3);
}
else if (starts.Count > 0)
helper.AddTriangle(vertexCount - 3, vertexCount - 1, vertexCount - 2);
}
else
{
helper.AddVert(_vertexList[i]);
helper.AddVert(_vertexList[i + 1]);
helper.AddVert(_vertexList[i + 2]);
int vertexCount = helper.currentVertCount;
helper.AddTriangle(vertexCount - 3, vertexCount - 2, vertexCount - 1);
}
}
}
}
private float[] GetPositions(List<UIVertex> _vertexList, int index)
{
float[] positions = new float[3];
if (GradientType == Type.Horizontal)
{
positions[0] = _vertexList[index].position.x;
positions[1] = _vertexList[index + 1].position.x;
positions[2] = _vertexList[index + 2].position.x;
}
else
{
positions[0] = _vertexList[index].position.y;
positions[1] = _vertexList[index + 1].position.y;
positions[2] = _vertexList[index + 2].position.y;
}
return positions;
}
private List<float> FindStops(float zoomOffset, Rect bounds)
{
List<float> stops = new List<float>();
var offset = Offset * (1 - zoomOffset);
var startBoundary = zoomOffset - offset;
var endBoundary = (1 - zoomOffset) - offset;
foreach (var color in EffectGradient.colorKeys)
{
if (color.time >= endBoundary)
break;
if (color.time > startBoundary)
stops.Add((color.time - startBoundary) * Zoom);
}
foreach (var alpha in EffectGradient.alphaKeys)
{
if (alpha.time >= endBoundary)
break;
if (alpha.time > startBoundary)
stops.Add((alpha.time - startBoundary) * Zoom);
}
float min = bounds.xMin;
float size = bounds.width;
if (GradientType == Type.Vertical)
{
min = bounds.yMin;
size = bounds.height;
}
stops.Sort();
for (int i = 0; i < stops.Count; i++)
{
stops[i] = (stops[i] * size) + min;
if (i > 0 && Mathf.Abs(stops[i] - stops[i - 1]) < 2)
{
stops.RemoveAt(i);
--i;
}
}
return stops;
}
private UIVertex CreateSplitVertex(UIVertex vertex1, UIVertex vertex2, float stop)
{
if (GradientType == Type.Horizontal)
{
float sx = vertex1.position.x - stop;
float dx = vertex1.position.x - vertex2.position.x;
float dy = vertex1.position.y - vertex2.position.y;
float uvx = vertex1.uv0.x - vertex2.uv0.x;
float uvy = vertex1.uv0.y - vertex2.uv0.y;
float ratio = sx / dx;
float splitY = vertex1.position.y - (dy * ratio);
UIVertex splitVertex = new UIVertex();
splitVertex.position = new Vector3(stop, splitY, vertex1.position.z);
splitVertex.normal = vertex1.normal;
splitVertex.uv0 = new Vector2(vertex1.uv0.x - (uvx * ratio), vertex1.uv0.y - (uvy * ratio));
splitVertex.color = Color.white;
return splitVertex;
}
else
{
float sy = vertex1.position.y - stop;
float dy = vertex1.position.y - vertex2.position.y;
float dx = vertex1.position.x - vertex2.position.x;
float uvx = vertex1.uv0.x - vertex2.uv0.x;
float uvy = vertex1.uv0.y - vertex2.uv0.y;
float ratio = sy / dy;
float splitX = vertex1.position.x - (dx * ratio);
UIVertex splitVertex = new UIVertex();
splitVertex.position = new Vector3(splitX, stop, vertex1.position.z);
splitVertex.normal = vertex1.normal;
splitVertex.uv0 = new Vector2(vertex1.uv0.x - (uvx * ratio), vertex1.uv0.y - (uvy * ratio));
splitVertex.color = Color.white;
return splitVertex;
}
}
private Color BlendColor(Color colorA, Color colorB)
{
switch (BlendMode)
{
default: return colorB;
case Blend.Add: return colorA + colorB;
case Blend.Multiply: return colorA * colorB;
}
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,67 @@
using TMPro;
using UnityEngine;
using UnityEngine.Events;
namespace Convention.WindowsUI
{
public partial class InputField : WindowUIModule, IInputField
{
[Resources, HopeNotNull] public TMP_InputField Source;
[Resources] public TMP_Text placeholder;
private void Start()
{
if (Source == null)
Source = this.GetComponent<TMP_InputField>();
if (placeholder == null)
placeholder = Source.placeholder.GetComponent<TMP_Text>();
}
private void OnValidate()
{
if (Source == null)
Source = this.GetComponent<TMP_InputField>();
if (placeholder == null)
placeholder = Source.placeholder.GetComponent<TMP_Text>();
}
public virtual string text
{
get { return Source.text; }
set { Source.text = value; }
}
public bool interactable { get => Source.interactable; set => Source.interactable = value; }
public void SetPlaceholderText(string text)
{
placeholder.text = text;
}
public InputField SetTextWithoutNotify(string text)
{
Source.SetTextWithoutNotify(text);
return this;
}
public IActionInvoke<string> AddListener(params UnityAction<string>[] action)
{
foreach (var actionItem in action)
Source.onEndEdit.AddListener(actionItem);
return this;
}
public IActionInvoke<string> RemoveListener(params UnityAction<string>[] action)
{
foreach (var actionItem in action)
Source.onEndEdit.RemoveListener(actionItem);
return this;
}
public IActionInvoke<string> RemoveAllListeners()
{
Source.onEndEdit.RemoveAllListeners();
return this;
}
}
}

View File

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

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
namespace Convention.WindowsUI
{
public class KeyboardStatsBar : WindowUIModule
{
[Serializable]
public class KeyboardStatsData
{
public Key key;
public CanvasGroup iconCanvasGroup;
public float notPress = 0.3f;
public float press = 1f;
}
[Setting] public List<KeyboardStatsData> bindings = new();
private void Update()
{
foreach (var bind in bindings)
{
bind.iconCanvasGroup.alpha = Keyboard.current[bind.key].isPressed ? bind.press : bind.notPress;
}
}
}
}

View File

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

View File

@@ -0,0 +1,366 @@
using System;
using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using Convention.WindowsUI.Internal;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
namespace Convention.WindowsUI
{
namespace Internal
{
public class Ripple : MonoBehaviour
{
public bool unscaledTime = false;
public float speed;
public float maxSize;
public Color startColor;
public Color transitionColor;
UnityEngine.UI.Image colorImg;
void Start()
{
transform.localScale = new Vector3(0f, 0f, 0f);
colorImg = GetComponent<UnityEngine.UI.Image>();
colorImg.color = new Color(startColor.r, startColor.g, startColor.b, startColor.a);
colorImg.raycastTarget = false;
}
void Update()
{
if (unscaledTime == false)
{
transform.localScale = Vector3.Lerp(transform.localScale, new Vector3(maxSize, maxSize, maxSize), Time.deltaTime * speed);
colorImg.color = Color.Lerp(colorImg.color, new Color(transitionColor.r, transitionColor.g, transitionColor.b, transitionColor.a), Time.deltaTime * speed);
if (transform.localScale.x >= maxSize * 0.998)
{
if (transform.parent.childCount == 1)
transform.parent.gameObject.SetActive(false);
Destroy(gameObject);
}
}
else
{
transform.localScale = Vector3.Lerp(transform.localScale, new Vector3(maxSize, maxSize, maxSize), Time.unscaledDeltaTime * speed);
colorImg.color = Color.Lerp(colorImg.color, new Color(transitionColor.r, transitionColor.g, transitionColor.b, transitionColor.a), Time.unscaledDeltaTime * speed);
if (transform.localScale.x >= maxSize * 0.998)
{
if (transform.parent.childCount == 1)
transform.parent.gameObject.SetActive(false);
Destroy(gameObject);
}
}
}
}
}
public partial class ModernUIButton : WindowUIModule, IButton, ITitle
{
// ---------------------------------------------------------------- stats
private bool useRipple => animationSolution == AnimationSolution.SCRIPT && m_useRipple;
// ----------------------------------------------------------------
public enum RippleUpdateMode
{
NORMAL,
UNSCALED_TIME
}
public enum AnimationSolution
{
ANIMATOR,
SCRIPT
}
[Content, SerializeField] private string m_title = "";
public string title
{
get => m_title;
set
{
m_title = value;
UpdateUI();
}
}
[Content] public UnityEvent clickEvent = new();
[Content] public UnityEvent hoverEvent = new();
[Resources, OnlyNotNullMode] public TextMeshProUGUI normalText;
[Resources, HopeNotNull] public CanvasGroup normalCanvasGroup;
[Resources, OnlyNotNullMode] public TextMeshProUGUI highlightedText;
[Resources, HopeNotNull] public CanvasGroup highlightedCanvasGroup;
[Resources, Setting, HopeNotNull, Header("Sound Setting")] public AudioSource soundSource;
[Resources, Setting, OnlyNotNullMode(nameof(soundSource))] public bool enableButtonSounds = false;
[Resources, Setting, OnlyNotNullMode(nameof(soundSource))] public bool useHoverSound = true;
[Resources, Setting, OnlyNotNullMode(nameof(soundSource))] public bool useClickSound = true;
[Resources, WhenAttribute.Is(nameof(useHoverSound), true), OnlyNotNullMode(nameof(soundSource))] public AudioClip hoverSound;
[Resources, WhenAttribute.Is(nameof(useClickSound), true), OnlyNotNullMode(nameof(soundSource))] public AudioClip clickSound;
[Resources, Setting, SerializeField, Header("Animation Setting")]
private AnimationSolution animationSolution = AnimationSolution.SCRIPT;
[Resources, WhenAttribute.Is(nameof(animationSolution), AnimationSolution.SCRIPT), OnlyNotNullMode]
public GameObject rippleParent;
[Resources, WhenAttribute.Is(nameof(animationSolution), AnimationSolution.SCRIPT), Setting, SerializeField]
private bool m_useRipple = true;
[WhenAttribute.Is(nameof(useRipple), true), Setting] public bool renderOnTop = false;
[WhenAttribute.Is(nameof(useRipple), true), Setting] public bool centered = false;
[WhenAttribute.Is(nameof(useRipple), true), Setting] public RippleUpdateMode rippleUpdateMode = RippleUpdateMode.UNSCALED_TIME;
[WhenAttribute.Is(nameof(useRipple), true), Setting, Range(0.25f, 15)] public float fadingMultiplier = 8;
[WhenAttribute.Is(nameof(useRipple), true), Setting, Range(0.1f, 5)] public float speed = 1f;
[WhenAttribute.Is(nameof(useRipple), true), Setting, Range(0.5f, 25)] public float maxSize = 4f;
[WhenAttribute.Is(nameof(useRipple), true), Setting] public Color startColor = new Color(1f, 1f, 1f, 1f);
[WhenAttribute.Is(nameof(useRipple), true), Setting] public Color transitionColor = new Color(1f, 1f, 1f, 1f);
[WhenAttribute.Is(nameof(useRipple), true), Resources, HopeNotNull] public Sprite rippleShape;
[WhenAttribute.Is(nameof(useRipple), true), Setting] public bool hoverCreateRipple = false;
[WhenAttribute.Is(nameof(useRipple), true), Setting] public bool exitCreateRipple = false;
//[Header("Others")]
[Content, Ignore] private bool isPointerNotExit;
[Content, Ignore] private float currentNormalValue;
[Content, Ignore] private float currenthighlightedValue;
[Setting, SerializeField] private bool m_interactable = true;
public bool interactable
{
get => m_interactable;
set => m_interactable = value;
}
private void Start()
{
ResetContext();
if (animationSolution == AnimationSolution.SCRIPT)
{
if (normalCanvasGroup == null)
normalCanvasGroup = transform.Find("Normal").GetComponent<CanvasGroup>();
if (highlightedCanvasGroup == null)
highlightedCanvasGroup = transform.Find("Highlighted").GetComponent<CanvasGroup>();
Animator tempAnimator = this.GetComponent<Animator>();
Destroy(tempAnimator);
}
if (rippleParent)
{
if (useRipple)
rippleParent.SetActive(false);
else
Destroy(rippleParent);
}
}
private void OnValidate()
{
UpdateUI();
}
public void ResetContext()
{
var Context = this.GetOrAddComponent<BehaviourContextManager>();
Context.OnPointerDownEvent = BehaviourContextManager.InitializeContextSingleEvent(Context.OnPointerDownEvent, OnPointerDown);
Context.OnPointerEnterEvent = BehaviourContextManager.InitializeContextSingleEvent(Context.OnPointerEnterEvent, OnPointerEnter);
Context.OnPointerExitEvent = BehaviourContextManager.InitializeContextSingleEvent(Context.OnPointerExitEvent, OnPointerExit);
}
public void Reset()
{
ResetContext();
if (normalCanvasGroup == null)
normalCanvasGroup = transform.Find("Normal").GetComponent<CanvasGroup>();
if (highlightedCanvasGroup == null)
highlightedCanvasGroup = transform.Find("Highlighted").GetComponent<CanvasGroup>();
}
void OnEnable()
{
UpdateUI();
normalCanvasGroup.alpha = 1;
highlightedCanvasGroup.alpha = 0;
}
[Setting, Header("Is Auto Rename"), SerializeField] private bool m_IsAutoRename = true;
public void UpdateUI()
{
normalText.text = m_title;
highlightedText.text = m_title;
if (m_IsAutoRename)
{
this.name = $"{this.GetType().Name}<{m_title}>";
}
}
public void CreateRipple(Vector2 pos)
{
if (rippleParent != null)
{
GameObject rippleObj = new GameObject();
rippleObj.AddComponent<UnityEngine.UI.Image>();
rippleObj.GetComponent<UnityEngine.UI.Image>().sprite = rippleShape;
rippleObj.name = "Ripple";
rippleParent.SetActive(true);
rippleObj.transform.SetParent(rippleParent.transform);
if (renderOnTop == true)
rippleParent.transform.SetAsLastSibling();
else
rippleParent.transform.SetAsFirstSibling();
if (centered == true)
rippleObj.transform.localPosition = new Vector2(0f, 0f);
else
rippleObj.transform.position = pos;
rippleObj.AddComponent<Ripple>();
Ripple tempRipple = rippleObj.GetComponent<Ripple>();
tempRipple.speed = speed;
tempRipple.maxSize = maxSize;
tempRipple.startColor = startColor;
tempRipple.transitionColor = transitionColor;
if (rippleUpdateMode == RippleUpdateMode.NORMAL)
tempRipple.unscaledTime = false;
else
tempRipple.unscaledTime = true;
}
}
public void OnPointerCreateRipple(PointerEventData eventData)
{
if (useRipple == true && isPointerNotExit == true)
#if ENABLE_LEGACY_INPUT_MANAGER
CreateRipple(Input.mousePosition);
#elif ENABLE_INPUT_SYSTEM && ENABLE_LEGACY_INPUT_MANAGER
CreateRipple(Input.mousePosition);
#elif ENABLE_INPUT_SYSTEM
CreateRipple(Mouse.current.position.ReadValue());
#endif
else if (useRipple == false)
this.enabled = false;
}
public void OnPointerDown(PointerEventData eventData)
{
if (interactable == false)
return;
if (enableButtonSounds == true && useClickSound == true)
soundSource.PlayOneShot(clickSound);
clickEvent.Invoke();
OnPointerCreateRipple(eventData);
}
private void OnPointerEnter(PointerEventData eventData)
{
if (interactable == false)
return;
if (enableButtonSounds == true && useHoverSound == true)
soundSource.PlayOneShot(hoverSound);
hoverEvent.Invoke();
isPointerNotExit = true;
if (animationSolution == AnimationSolution.SCRIPT)
StartCoroutine(nameof(FadeIn));
if (hoverCreateRipple)
OnPointerCreateRipple(eventData);
}
private void OnPointerExit(PointerEventData eventData)
{
if (interactable == false)
return;
if (exitCreateRipple)
OnPointerCreateRipple(eventData);
isPointerNotExit = false;
if (animationSolution == AnimationSolution.SCRIPT)
StartCoroutine(nameof(FadeOut));
}
IEnumerator FadeIn()
{
StopCoroutine("FadeOut");
currentNormalValue = normalCanvasGroup.alpha;
currenthighlightedValue = highlightedCanvasGroup.alpha;
while (currenthighlightedValue <= 1)
{
currentNormalValue -= Time.deltaTime * fadingMultiplier;
normalCanvasGroup.alpha = currentNormalValue;
currenthighlightedValue += Time.deltaTime * fadingMultiplier;
highlightedCanvasGroup.alpha = currenthighlightedValue;
if (normalCanvasGroup.alpha >= 1)
StopCoroutine("FadeIn");
yield return null;
}
}
IEnumerator FadeOut()
{
StopCoroutine("FadeIn");
currentNormalValue = normalCanvasGroup.alpha;
currenthighlightedValue = highlightedCanvasGroup.alpha;
while (currentNormalValue >= 0)
{
currentNormalValue += Time.deltaTime * fadingMultiplier;
normalCanvasGroup.alpha = currentNormalValue;
currenthighlightedValue -= Time.deltaTime * fadingMultiplier;
highlightedCanvasGroup.alpha = currenthighlightedValue;
if (highlightedCanvasGroup.alpha <= 0)
StopCoroutine("FadeOut");
yield return null;
}
}
public IActionInvoke AddListener(params UnityAction[] action)
{
foreach (var actionItem in action)
clickEvent.AddListener(actionItem);
return this;
}
public IActionInvoke RemoveListener(params UnityAction[] action)
{
foreach (var actionItem in action)
clickEvent.RemoveListener(actionItem);
return this;
}
public IActionInvoke RemoveAllListeners()
{
clickEvent.RemoveAllListeners();
return this;
}
public Color NormalColor
{
get => normalCanvasGroup.GetComponentInChildren<Image>().color;
set
{
normalCanvasGroup.GetComponentInChildren<Image>().color = value;
normalCanvasGroup.GetComponentInChildren<TMP_Text>().color = value;
}
}
}
}

View File

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

View File

@@ -0,0 +1,412 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using static Convention.ProjectContextLabelAttribute;
namespace Convention.WindowsUI
{
public class ModernUIDropdown : WindowUIModule, IActionInvoke<string>, ITitle
{
// Resources
[Resources, OnlyNotNullMode] public GameObject triggerObject;
[Resources, OnlyNotNullMode] public Transform itemParent;
[Resources, OnlyNotNullMode] public GameObject itemPrefab;
[Resources, OnlyNotNullMode] public GameObject scrollbar;
private VerticalLayoutGroup itemList;
private Transform currentListParent;
[Resources, WhenAttribute.Is(nameof(isListItem), true)] public Transform listParent;
private Animator dropdownAnimator;
[Resources, OnlyNotNullMode] public TextMeshProUGUI m_Title;
private Button m_RawButton;
// Settings
[Setting] public bool enableTrigger = true;
[Setting] public bool enableScrollbar = true;
[Setting] public bool setHighPriorty = true;
[Setting] public bool outOnPointerExit = false;
[Setting] public bool isListItem = false;
[Setting] public AnimationType animationType = AnimationType.FADING;
[Setting] public UnityEvent<string> OnSelect = new();
[Setting] public bool isMutiSelect = false;
// Items
[Content] public List<Item> dropdownItems = new();
// Other variables
bool isOn;
[Content] public int siblingIndex = 0;
private bool m_interactable = true;
public bool interactable
{
get => m_interactable;
set
{
if (m_interactable != value)
{
m_interactable = value;
RefreshImmediate();
}
}
}
public string title { get => m_Title.text; set => m_Title.text = value; }
public enum AnimationType
{
None,
FADING,
SLIDING,
STYLISH
}
[System.Serializable]
public class Item
{
public string itemName = "Dropdown Item";
[HideInInspector] private Toggle m_ToggleItem;
public Toggle ToggleItem
{
get => m_ToggleItem;
set
{
if (m_ToggleItem != value)
{
m_ToggleItem = value;
if (m_ToggleItem != null)
m_ToggleItem.isOn = lazy_isOn;
lazy_isOn = false;
}
}
}
public UnityEvent<bool> toggleEvents = new();
private bool lazy_isOn = false;
public bool isOn
{
get => ToggleItem == null ? lazy_isOn : ToggleItem.isOn;
set
{
if (ToggleItem == null)
lazy_isOn = value;
else
ToggleItem.SetIsOnWithoutNotify(value);
}
}
}
private void Reset()
{
triggerObject = transform.Find("Trigger").gameObject;
}
[Resources] public RectTransform ResizeBroadcastRect;
public IEnumerator ResizeBroadcast()
{
if (ResizeBroadcastRect == null)
yield break;
for (int i = 0; i < 60; i++)
{
RectTransformExtension.AdjustSizeToContainsChilds(ResizeBroadcastRect);
yield return null;
}
}
private void Start()
{
m_RawButton = GetComponent<Button>();
try
{
dropdownAnimator = this.GetComponent<Animator>();
itemList = itemParent.GetComponent<VerticalLayoutGroup>();
RefreshImmediate();
currentListParent = transform.parent;
}
catch
{
DebugError("Dropdown", "Cannot initalize the object", ContextLabelType.Resources, this);
}
if (enableScrollbar == true)
{
itemList.padding.right = 25;
scrollbar.SetActive(true);
}
else
{
itemList.padding.right = 8;
Destroy(scrollbar);
}
if (setHighPriorty == true)
transform.SetAsLastSibling();
}
[Content, OnlyPlayMode]
public void RefreshImmediate()
{
foreach (Transform child in itemParent)
if (child.gameObject != itemPrefab)
GameObject.Destroy(child.gameObject);
for (int i = 0; i < dropdownItems.Count; ++i)
{
Item current = dropdownItems[i];
GameObject go = Instantiate(itemPrefab, itemParent);
go.SetActive(true);
go.GetComponentInChildren<TMP_Text>().text = current.itemName;
Toggle itemToggle = go.GetComponent<Toggle>();
current.ToggleItem = itemToggle;
itemToggle.isOn = false;
itemToggle.interactable = interactable;
}
foreach (var current in dropdownItems)
{
var itemToggle = current.ToggleItem;
itemToggle.onValueChanged.AddListener(GenerateCallback(current));
}
currentListParent = transform.parent;
UnityAction<bool> GenerateCallback(Item current)
{
void Callback(bool T)
{
if (isMutiSelect)
{
int selectCount = 0;
Item selectedLast = null;
foreach (var item in dropdownItems)
{
if (item.isOn)
{
selectCount++;
selectedLast = item;
}
}
if (selectCount == 0)
this.title = "Empty";
else if (selectCount == 1)
this.title = selectedLast.itemName;
else if (selectCount == dropdownItems.Count)
this.title = "Every";
else
this.title = "Muti";
}
else
{
if (T)
{
foreach (var item in dropdownItems)
{
if (current != item)
item.isOn = false;
}
this.title = current.itemName;
}
else
{
dropdownItems[0].isOn = true;
this.title = dropdownItems[0].itemName;
}
}
current.toggleEvents.Invoke(T);
OnSelect.Invoke(current.itemName);
}
return Callback;
}
}
public void Animate()
{
if (isOn == false && animationType == AnimationType.FADING)
{
dropdownAnimator.Play("Fading In");
isOn = true;
if (isListItem == true)
{
siblingIndex = transform.GetSiblingIndex();
gameObject.transform.SetParent(listParent, true);
}
}
else if (isOn == true && animationType == AnimationType.FADING)
{
dropdownAnimator.Play("Fading Out");
isOn = false;
if (isListItem == true)
{
gameObject.transform.SetParent(currentListParent, true);
gameObject.transform.SetSiblingIndex(siblingIndex);
}
}
else if (isOn == false && animationType == AnimationType.SLIDING)
{
dropdownAnimator.Play("Sliding In");
isOn = true;
if (isListItem == true)
{
siblingIndex = transform.GetSiblingIndex();
gameObject.transform.SetParent(listParent, true);
}
}
else if (isOn == true && animationType == AnimationType.SLIDING)
{
dropdownAnimator.Play("Sliding Out");
isOn = false;
if (isListItem == true)
{
gameObject.transform.SetParent(currentListParent, true);
gameObject.transform.SetSiblingIndex(siblingIndex);
}
}
else if (isOn == false && animationType == AnimationType.STYLISH)
{
dropdownAnimator.Play("Stylish In");
isOn = true;
if (isListItem == true)
{
siblingIndex = transform.GetSiblingIndex();
gameObject.transform.SetParent(listParent, true);
}
}
else if (isOn == true && animationType == AnimationType.STYLISH)
{
dropdownAnimator.Play("Stylish Out");
isOn = false;
if (isListItem == true)
{
gameObject.transform.SetParent(currentListParent, true);
gameObject.transform.SetSiblingIndex(siblingIndex);
}
}
StopCoroutine(nameof(ResizeBroadcast));
StartCoroutine(nameof(ResizeBroadcast));
if (enableTrigger == true && isOn == false)
triggerObject.SetActive(false);
else if (enableTrigger == true && isOn == true)
triggerObject.SetActive(true);
if (outOnPointerExit == true)
triggerObject.SetActive(false);
if (setHighPriorty == true)
transform.SetAsLastSibling();
}
public void OnPointerExit(PointerEventData eventData)
{
if (outOnPointerExit == true)
{
if (isOn == true)
{
Animate();
isOn = false;
}
if (isListItem == true)
gameObject.transform.SetParent(currentListParent, true);
}
}
public void UpdateValues()
{
if (enableScrollbar == true)
{
itemList.padding.right = 25;
scrollbar.SetActive(true);
}
else
{
itemList.padding.right = 8;
scrollbar.SetActive(false);
}
}
public Item CreateOption(string name, params UnityAction<bool>[] actions)
{
Item item = new()
{
itemName = name,
toggleEvents = ConventionUtility.WrapperAction2Event(actions)
};
dropdownItems.Add(item);
return item;
}
public void RemoveOption(params Item[] items)
{
foreach (var item in items)
{
dropdownItems.RemoveAll(T => T == item);
}
RefreshImmediate();
}
[Content, OnlyPlayMode]
public void ClearOptions()
{
dropdownItems.Clear();
RefreshImmediate();
}
public void Select(string option)
{
var target = dropdownItems.FirstOrDefault(T => T.itemName == option);
if (target != default)
{
target.ToggleItem.isOn = true;
title = option;
}
}
public IActionInvoke<string> AddListener(params UnityAction<string>[] action)
{
foreach (var item in action)
{
OnSelect.AddListener(item);
}
return this;
}
public IActionInvoke<string> RemoveListener(params UnityAction<string>[] action)
{
foreach (var item in action)
{
OnSelect.RemoveListener(item);
}
return this;
}
public IActionInvoke<string> RemoveAllListeners()
{
OnSelect.RemoveAllListeners();
return this;
}
}
}

View File

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

View File

@@ -0,0 +1,150 @@
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace Convention.WindowsUI
{
public class ModernUIFillBar : WindowUIModule
{
// Content
private float lastPercent;
[Range(0, 1)] public float currentPercent;
public float minValue = 0;
public float maxValue = 100;
public UnityEvent<float> OnValueChange = new();
public UnityEvent<float> OnEndChange = new();
public UnityEvent<float> OnTransValueChange = new();
public UnityEvent<float> OnEndTransChange = new();
public float value => (maxValue - minValue) * currentPercent + minValue;
public float Value => (maxValue - minValue) * currentPercent + minValue;
// Resources
public Image loadingBar;
public TextMeshProUGUI textPercent;
public TextMeshProUGUI textValue;
public bool IsLockByScript = true;
// Settings
public bool IsPercent = true;
public bool IsInt = false;
public float DragChangeSpeed = 0.5f;
public void Start()
{
var Context = this.GetOrAddComponent<BehaviourContextManager>();
Context.OnDragEvent = BehaviourContextManager.InitializeContextSingleEvent(Context.OnDragEvent, OnDrag);
this.currentPercent = loadingBar.fillAmount = this.lastPercent = value;
textPercent.text = (IsPercent ? currentPercent * 100 : currentPercent).ToString("F2") + (IsPercent ? "%" : "");
textValue.text = GetValue().ToString("F2");
}
public void SetValue(float t)
{
SetPerecent((t - minValue) / (maxValue - minValue));
}
public void SetPerecent(float t)
{
if (IsLockByScript) currentPercent = Mathf.Clamp(t, 0, 1);
else loadingBar.fillAmount = t;
}
public void SetPerecent(float t, float a, float b)
{
if (IsLockByScript) currentPercent = Mathf.Clamp(t, 0, 1);
else loadingBar.fillAmount = t;
minValue = a;
maxValue = b;
IsInt = false;
}
public void SetPerecent(float t, int a, int b)
{
if (IsLockByScript) currentPercent = Mathf.Clamp(t, 0, 1);
else loadingBar.fillAmount = t;
minValue = a;
maxValue = b;
IsInt = true;
}
public void OnDrag(PointerEventData data)
{
if (!IsLockByScript) loadingBar.fillAmount += data.delta.x * Time.deltaTime * DragChangeSpeed;
}
private bool IsUpdateAndInvoke = true;
public void LateUpdate()
{
if (IsLockByScript) loadingBar.fillAmount = Mathf.Clamp(currentPercent, 0, 1);
else currentPercent = loadingBar.fillAmount;
if (currentPercent == lastPercent)
{
if (!IsUpdateAndInvoke)
{
IsUpdateAndInvoke = true;
OnEndChange.Invoke(currentPercent);
OnEndTransChange.Invoke(Value);
}
return;
}
IsUpdateAndInvoke = false;
lastPercent = currentPercent;
OnValueChange.Invoke(currentPercent);
OnTransValueChange.Invoke(Value);
textPercent.text = (IsPercent ? currentPercent * 100 : currentPercent).ToString("F2") + (IsPercent ? "%" : "");
textValue.text = GetValue().ToString("F2");
}
public void UpdateWithInvoke()
{
if (IsLockByScript) loadingBar.fillAmount = Mathf.Clamp(currentPercent, 0, 1);
else currentPercent = loadingBar.fillAmount;
if (currentPercent == lastPercent)
{
if (!IsUpdateAndInvoke)
{
IsUpdateAndInvoke = true;
}
return;
}
IsUpdateAndInvoke = false;
lastPercent = currentPercent;
textPercent.text = currentPercent.ToString("F2") + (IsPercent ? "%" : "");
textValue.text = GetValue().ToString("F2");
}
public float GetValue()
{
return IsInt ? (int)value : value;
}
public int GetIntValue()
{
return (int)value;
}
public void Set(float min, float max)
{
currentPercent = 0;
minValue = min;
maxValue = max;
}
public void Set(float percent, float min, float max)
{
currentPercent = percent;
minValue = min;
maxValue = max;
}
}
}

View File

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

View File

@@ -0,0 +1,22 @@
using UnityEngine;
using UnityEngine.UI;
namespace Convention.WindowsUI
{
public class ModernUIImage : WindowUIModule
{
[Resources, SerializeField, HopeNotNull] private RawImage m_RawImage;
[Resources, SerializeField] private GradientEffect m_GradientEffect;
private void Reset()
{
m_RawImage = GetComponent<RawImage>();
}
private void Start()
{
if (m_RawImage == null)
m_RawImage = GetComponent<RawImage>();
}
}
}

View File

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

View File

@@ -0,0 +1,37 @@
using UnityEngine.Events;
namespace Convention.WindowsUI
{
public partial class ModernUIInputField : WindowUIModule, ITitle, IInputField
{
[Resources, HopeNotNull] public Text TitleSource;
[Resources, HopeNotNull] public InputField InputFieldSource;
public virtual string text { get => InputFieldSource.text; set => InputFieldSource.text = value; }
public virtual string title { get => TitleSource.title; set => TitleSource.title = value; }
public bool interactable { get => InputFieldSource.Source.interactable; set => InputFieldSource.Source.interactable = value; }
public IActionInvoke<string> AddListener(params UnityAction<string>[] action)
{
return ((IActionInvoke<string>)this.InputFieldSource).AddListener(action);
}
public IActionInvoke<string> RemoveAllListeners()
{
return ((IActionInvoke<string>)this.InputFieldSource).RemoveAllListeners();
}
public IActionInvoke<string> RemoveListener(params UnityAction<string>[] action)
{
return ((IActionInvoke<string>)this.InputFieldSource).RemoveListener(action);
}
private void Reset()
{
TitleSource = GetComponentInChildren<Text>();
InputFieldSource = GetComponentInChildren<InputField>();
}
}
}

View File

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

View File

@@ -0,0 +1,126 @@
using System;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Convention.WindowsUI
{
[Serializable]
public class ModernUIToggle : WindowUIModule, IToggle, ITitle
{
[Content] public UnityEvent m_SwitchOnEvent = new();
[Content] public UnityEvent m_SwitchOffEvent = new();
[Content] public UnityEvent<bool> m_ToggleEvent = new();
[Resources, OnlyNotNullMode] public TextMeshProUGUI normalText;
[Resources, HopeNotNull] public CanvasGroup normalCanvasGroup;
[Resources, OnlyNotNullMode] public TextMeshProUGUI selectedText;
[Resources, HopeNotNull] public CanvasGroup selectedCanvasGroup;
[Resources, Setting, HopeNotNull, Header("Sound Setting")] public AudioSource soundSource;
[Resources, Setting, OnlyNotNullMode(nameof(soundSource))] public bool enableButtonSounds = false;
[Resources, WhenAttribute.Is(nameof(enableButtonSounds), true), OnlyNotNullMode(nameof(soundSource))] public AudioClip m_SwitchOnSound;
[Resources, WhenAttribute.Is(nameof(enableButtonSounds), true), OnlyNotNullMode(nameof(soundSource))] public AudioClip m_SwitchOffSound;
[Content, SerializeField] private string m_title = "";
[Content, SerializeField] private bool m_value = false;
public bool ref_value
{
get => m_value;
set
{
if (m_value != value)
{
m_value = value;
normalCanvasGroup.alpha = m_value ? 0 : 1;
selectedCanvasGroup.alpha = m_value ? 1 : 0;
}
}
}
public string title
{
get => m_title;
set
{
m_title = value;
UpdateUI();
}
}
[Setting, SerializeField] private bool m_interactable = true;
public bool interactable { get => m_interactable; set => m_interactable = value; }
private void Start()
{
ResetContext();
}
private void OnValidate()
{
UpdateUI();
}
public void Reset()
{
ResetContext();
if (normalCanvasGroup == null)
normalCanvasGroup = transform.Find("Normal").GetComponent<CanvasGroup>();
if (selectedCanvasGroup == null)
selectedCanvasGroup = transform.Find("Selected").GetComponent<CanvasGroup>();
interactable = true;
}
void OnEnable()
{
UpdateUI();
}
public void ResetContext()
{
var Context = this.GetOrAddComponent<BehaviourContextManager>();
Context.OnPointerDownEvent = BehaviourContextManager.InitializeContextSingleEvent(Context.OnPointerDownEvent, OnPointerDown);
}
public void UpdateUI()
{
normalText.text = m_title;
selectedText.text = m_title;
normalCanvasGroup.alpha = m_value ? 0 : 1;
selectedCanvasGroup.alpha = m_value ? 1 : 0;
}
public void OnPointerDown(PointerEventData eventData)
{
if (interactable == false)
return;
ref_value = !ref_value;
if (enableButtonSounds == true)
soundSource.PlayOneShot(ref_value ? m_SwitchOnSound : m_SwitchOffSound);
(ref_value ? m_SwitchOnEvent : m_SwitchOffEvent).Invoke();
m_ToggleEvent.Invoke(ref_value);
}
public IActionInvoke<bool> AddListener(params UnityAction<bool>[] action)
{
foreach (var item in action)
{
m_ToggleEvent.AddListener(item);
}
return this;
}
public IActionInvoke<bool> RemoveListener(params UnityAction<bool>[] action)
{
foreach (var item in action)
{
m_ToggleEvent.RemoveListener(item);
}
return this;
}
public IActionInvoke<bool> RemoveAllListeners()
{
m_ToggleEvent.RemoveAllListeners();
return this;
}
}
}

View File

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

View File

@@ -0,0 +1,95 @@
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.Events;
namespace Convention.WindowsUI
{
public interface IWindowUIModule { }
public class WindowUIModule : MonoBehaviour, IWindowUIModule { }
public static partial class UIInterfaceExtension
{
public static void AutoTransform(GameObject @object)
{
if (@object == null) return;
foreach (var text in @object.GetComponentsInChildren<IText>(true))
{
text.Transform();
}
foreach (var title in @object.GetComponentsInChildren<ITitle>(true))
{
title.Transform();
}
foreach (Transform child in @object.transform)
{
AutoTransform(child.gameObject);
}
}
private const string ExpressionPattern = @"\$\$.*?\$\$";
public static void Transform(this IText self)
{
try
{
string result = self.text;
foreach (Match match in Regex.Matches(self.text, ExpressionPattern))
{
result = result.Replace(match.Value, StringExtension.Transform(match.Value[2..^2]));
}
self.text = result;
}
catch (System.Exception) { }
}
public static void Transform(this ITitle self)
{
try
{
string result = self.title;
foreach (Match match in Regex.Matches(self.title, ExpressionPattern))
{
result = result.Replace(match.Value, StringExtension.Transform(match.Value[2..^2]));
}
self.title = result;
}
catch (System.Exception) { }
}
}
public interface IText : IAnyClass
{
string text { get; set; }
}
public interface ITitle : IAnyClass
{
string title { get; set; }
}
public interface IInteractable : IAnyClass
{
bool interactable { get; set; }
}
public interface IActionInvoke : IInteractable
{
IActionInvoke AddListener(params UnityAction[] action);
IActionInvoke RemoveListener(params UnityAction[] action);
IActionInvoke RemoveAllListeners();
}
public interface IActionInvoke<Args> : IInteractable
{
IActionInvoke<Args> AddListener(params UnityAction<Args>[] action);
IActionInvoke<Args> RemoveListener(params UnityAction<Args>[] action);
IActionInvoke<Args> RemoveAllListeners();
}
public interface IButton : IWindowUIModule, IActionInvoke { }
public interface IToggle : IWindowUIModule, IActionInvoke<bool> { }
public interface IInputField : IWindowUIModule, IActionInvoke<string>, IText { }
}

View File

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

View File

@@ -0,0 +1,13 @@
using UnityEngine;
namespace Convention.WindowsUI
{
public partial class ScrollView : WindowUIModule
{
[Resources, HopeNotNull] public UnityEngine.UI.ScrollRect scrollRect;
private void Reset()
{
scrollRect = GetComponent<UnityEngine.UI.ScrollRect>();
}
}
}

View File

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

View File

@@ -0,0 +1,32 @@
using TMPro;
using UnityEngine;
namespace Convention.WindowsUI
{
public partial class Text : WindowUIModule, IText, ITitle
{
[Resources, HopeNotNull] public TextMeshProUGUI source;
public virtual string text
{
get => source.text;
set => source.text = value;
}
public virtual string title
{
get => source.text;
set => source.text = value;
}
private void Start()
{
if (source == null)
source = this.GetComponent<TextMeshProUGUI>();
}
private void Reset()
{
if (source == null)
source = this.GetComponent<TextMeshProUGUI>();
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ff1a65153fc10c04ba56684597bfa8d6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fcda8b09e5a240d4ca0e140a4691a7bf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using static Convention.WindowsUI.Variant.PropertiesWindow;
namespace Convention.WindowsUI.Variant
{
public class AssetsItem : WindowUIModule, IText, ITitle, IItemEntry
{
public static int TextStringLimit = 16;
public static AssetsItem FocusItem;
public interface IAssetsItemInvoke
{
void OnAssetsItemInvoke(AssetsItem item);
void OnAssetsItemFocus(AssetsItem item);
}
[Resources, SerializeField, OnlyNotNullMode] private Button m_RawButton;
[Resources, SerializeField, OnlyNotNullMode] private Text m_Text;
[Content, SerializeField] private string m_TextString;
[Content, SerializeField] private List<ItemEntry> m_ChildEntries = new();
[Content, SerializeField] private ItemEntry m_entry;
[Setting] public bool HasChildLayer = true;
public ItemEntry Entry
{
get => m_entry;
set
{
if (this.gameObject.activeInHierarchy && m_entry != null)
{
throw new InvalidOperationException();
}
m_entry = value;
m_entry.ref_value = this;
}
}
public Sprite ButtonSprite
{
get => m_RawButton.GetComponent<Image>().sprite;
set => m_RawButton.GetComponent<Image>().sprite = value;
}
public List<ItemEntry> AddChilds(int count)
{
var entries = Entry.rootWindow.CreateRootItemEntries(false, count);
m_ChildEntries.AddRange(entries);
return entries;
}
public ItemEntry AddChild()
{
var entry = Entry.rootWindow.CreateRootItemEntries(false, 1)[0];
m_ChildEntries.Add(entry);
return entry;
}
public void RemoveChild([In] ItemEntry entry)
{
if (m_ChildEntries.Remove(entry))
entry.Disable(true);
}
public void RemoveAllChilds()
{
foreach (var entry in m_ChildEntries)
{
entry.Disable(true);
}
m_ChildEntries.Clear();
}
public int ChildCount()
{
return m_ChildEntries.Count;
}
public ItemEntry GetChild(int index)
{
return m_ChildEntries[index];
}
public string title
{
get => m_TextString;
set
{
m_TextString = value;
if (value.Length > TextStringLimit)
this.m_Text.title = value[..(TextStringLimit - 3)] + "...";
else
this.m_Text.title = value;
}
}
public string text
{
get => title; set => title = value;
}
private void Start()
{
m_RawButton.onClick.AddListener(() =>
{
Invoke();
});
}
public virtual void Invoke()
{
AssetsWindow.instance.CurrentTargetName = m_TextString;
if (FocusItem != this)
{
FocusItem = this;
if (FocusWindowIndictaor.instance != null)
FocusWindowIndictaor.instance.SetTargetRectTransform(this.transform as RectTransform);
foreach (var component in this.GetComponents<IAssetsItemInvoke>())
{
component.OnAssetsItemFocus(this);
}
}
else
{
FocusItem = null;
if (FocusWindowIndictaor.instance != null)
FocusWindowIndictaor.instance.SetTargetRectTransform(null);
if (HasChildLayer)
Entry.rootWindow.GetComponent<AssetsWindow>().Push(title, m_ChildEntries, true);
foreach (var component in this.GetComponents<IAssetsItemInvoke>())
{
component.OnAssetsItemInvoke(this);
}
}
AssetsWindow.instance.UpdatePathText();
}
}
}

View File

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

View File

@@ -0,0 +1,95 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
namespace Convention.WindowsUI.Variant
{
[RequireComponent(typeof(PropertiesWindow))]
public class AssetsWindow : MonoSingleton<AssetsWindow>
{
[Content, OnlyPlayMode, SerializeField, Header("Assets Stack")] private Stack<List<PropertiesWindow.ItemEntry>> m_EntriesStack = new();
[Resources, OnlyNotNullMode, SerializeField] private PropertiesWindow m_PropertiesWindow;
[Resources, OnlyNotNullMode, SerializeField, Tooltip("Back Button")] private Button m_BackButton;
[Resources, OnlyNotNullMode, SerializeField, Tooltip("Path Text")] private Text m_PathTitle;
[Content, OnlyPlayMode] public string CurrentTargetName;
[Content, OnlyPlayMode, SerializeField] public List<string> pathContainer = new();
private RegisterWrapper<AssetsWindow> m_RegisterWrapper;
private void OnDestroy()
{
m_RegisterWrapper.Release();
}
public PropertiesWindow MainPropertiesWindow => m_PropertiesWindow;
public void UpdatePathText()
{
m_PathTitle.text = string.Join('/', pathContainer.ToArray()) +
(string.IsNullOrEmpty(CurrentTargetName) ? "" : $":<color=blue>{CurrentTargetName}</color>");
}
protected virtual void Start()
{
m_BackButton.onClick.AddListener(() => Pop(true));
UpdatePathText();
m_RegisterWrapper = new(() => { });
}
protected virtual void Reset()
{
m_PropertiesWindow.m_PerformanceMode = PerformanceIndicator.PerformanceMode.L1;
m_PropertiesWindow = GetComponent<PropertiesWindow>();
}
public void Push([In] string label, [In] List<PropertiesWindow.ItemEntry> entries, bool isRefreshTop)
{
var top = Peek();
if (top != null)
foreach (var entry in top)
{
entry.Disable(false);
}
m_EntriesStack.Push(entries);
foreach (var entry in entries)
{
entry.Enable(false);
}
if (isRefreshTop)
RectTransformExtension.AdjustSizeToContainsChilds(m_PropertiesWindow.TargetWindowContent);
pathContainer.Add(label);
UpdatePathText();
}
[return: ReturnMayNull, When("m_EntriesStack is empty")]
public List<PropertiesWindow.ItemEntry> Peek()
{
if (m_EntriesStack.Count == 0)
return null;
return m_EntriesStack.Peek();
}
[return: ReturnMayNull, When("m_EntriesStack is empty")]
public List<PropertiesWindow.ItemEntry> Pop(bool isRefreshTop)
{
if (m_EntriesStack.Count <= 1)
return null;
var top = m_EntriesStack.Pop();
if (top != null)
foreach (var entry in top)
{
entry.Disable(false);
}
var entries = Peek();
if (entries != null)
foreach (var entry in entries)
{
entry.Enable(false);
}
if (isRefreshTop)
RectTransformExtension.AdjustSizeToContainsChilds(m_PropertiesWindow.TargetWindowContent);
if (pathContainer.Count != 0)
pathContainer.RemoveAt(pathContainer.Count - 1);
UpdatePathText();
return top;
}
}
}

View File

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

View File

@@ -0,0 +1,75 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Convention.WindowsUI.Variant
{
public class FileSystemAssets : MonoSingleton<FileSystemAssets>
{
public static void InitLoadedRoots(ref List<string> LoadedInRoot)
{
LoadedInRoot = new List<string>();
if (PlatformIndicator.is_platform_windows)
{
LoadedInRoot.Add(Application.persistentDataPath);
LoadedInRoot.Add(Application.streamingAssetsPath);
}
else
{
LoadedInRoot.Add(Application.persistentDataPath);
}
}
[Resources, SerializeField, OnlyNotNullMode] private AssetsWindow m_AssetsWindow;
[Resources, OnlyNotNullMode] public Text CurrentSelectFilename;
[Setting] public long LoadedFileAutoLoadMaxFileSize = 1024 * 50;
[Setting] public List<string> LoadedInRoot = null;
[Setting] public List<string> LoadedFileIconsExtension = new() { "skys", "scenes", "gameobjects" };
[Setting] public string RootName = "Root";
protected override void Awake()
{
base.Awake();
// Starter
FileSystemAssetsItem.LoadedFiles.Clear();
if (LoadedInRoot == null || LoadedInRoot.Count == 0)
InitLoadedRoots(ref LoadedInRoot);
// Update extensions
var extensions = ToolFile.AssetBundleExtension.ToList();
extensions.AddRange(LoadedFileIconsExtension);
ToolFile.AssetBundleExtension = extensions.ToArray();
// Read Config
if (LoadedFileAutoLoadMaxFileSize != 0)
FileSystemAssetsItem.LoadedFileAutoLoadMaxFileSize = LoadedFileAutoLoadMaxFileSize;
}
private void Start()
{
var entries = m_AssetsWindow.MainPropertiesWindow.CreateRootItemEntries(false, LoadedInRoot.Count);
for (int i = 0, e = LoadedInRoot.Count; i != e; i++)
{
entries[i].ref_value.GetComponent<FileSystemAssetsItem>().RebuildFileInfo(LoadedInRoot[i]);
}
m_AssetsWindow.Push(RootName, entries, true);
CurrentSelectFilename.title = "";
}
private void Reset()
{
m_AssetsWindow = GetComponent<AssetsWindow>();
InitLoadedRoots(ref LoadedInRoot);
LoadedFileIconsExtension = new() { "skys", "scenes", "gameobjects" };
}
public void RefreshImmediate()
{
if (FocusWindowIndictaor.instance.Target == m_AssetsWindow.transform as RectTransform)
{
foreach (var entry in m_AssetsWindow.Peek())
{
entry.ref_value.GetComponent<FileSystemAssetsItem>().SetDirty();
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,383 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace Convention.WindowsUI.Variant
{
public class FileSystemAssetsItem : MonoAnyBehaviour, AssetsItem.IAssetsItemInvoke
{
public static Dictionary<string, ToolFile> LoadedFiles = new();
public static long LoadedFileAutoLoadMaxFileSize = 1024 * 50;
[Setting] public ToolFile m_File;
[Setting, InspectorDraw(InspectorDrawType.Text), Ignore] public string ItemPathName;
[Setting] public ScriptableObject m_Icons;
[Content, OnlyPlayMode, SerializeField] private bool m_Dirty = false;
[Content, OnlyNotNullMode, SerializeField, InspectorDraw(InspectorDrawType.Toggle), Ignore]
private bool m_IsLoading = false;
private void OnDestroy()
{
if (m_File.data is AssetBundle)
{
return;
}
m_File.data = null;
}
public void RebuildFileInfo([In] string path)
{
if (LoadedFiles.ContainsKey(path))
m_File = LoadedFiles[path];
else
{
LoadedFiles.Add(path, new ToolFile(path));
m_File = new(path);
}
m_Dirty = true;
ItemPathName = m_File.GetFilename(false);
OnAssetsItemFocusWithFileMode(GetComponent<AssetsItem>(), m_File.GetFilename(true));
}
public void RebuildButNotFileInfo([In] string title)
{
var temp = new ToolFile(title);
ItemPathName = temp.GetFilename(false);
if (title.Contains("."))
UpdateSpriteAndTitle(GetComponent<AssetsItem>(), title, title.Split('.')[^1]);
else
UpdateSpriteAndTitle(GetComponent<AssetsItem>(), title, "ab.data");
}
private void UpdateSprite([In] AssetsItem item, [In] string sprite)
{
item.ButtonSprite = m_Icons.FindItem<Sprite>(sprite);
}
private void UpdateSpriteAndTitle([In] AssetsItem item, [In] string name, [In] string extension)
{
item.title = name;
UpdateSprite(item, extension);
}
/// <summary>
/// Some extensions see <see cref="FileSystemAssets.Awake"/>
/// </summary>
/// <param name="item"></param>
private void OnAssetsItemFocusWithFileMode([In] AssetsItem item, [In] string name)
{
item.title = name;
FileSystemAssets.instance.CurrentSelectFilename.title = m_File.FullPath;
if (m_File.IsExist == false)
return;
else if (m_File.IsDir())
UpdateSprite(item, "folder");
else if (m_File.Extension.Length != 0 && m_Icons.uobjects.ContainsKey(m_File.Extension))
UpdateSprite(item, m_File.Extension);
else if (m_File.Extension.Length != 0 && m_Icons.uobjects.ContainsKey(m_File.Extension[1..]))
UpdateSprite(item, m_File.Extension[1..]);
else if (m_File.IsImage)
UpdateSprite(item, "image");
else if (m_File.IsText)
UpdateSprite(item, "text");
else if (m_File.IsJson)
UpdateSprite(item, "json");
else if (m_File.IsAssetBundle)
UpdateSprite(item, "ab");
else
UpdateSprite(item, "default");
}
// --------------------
private abstract class AssetBundleItem : WindowUIModule, AssetsItem.IAssetsItemInvoke
{
[Resources] public AssetBundle ab;
[Resources] public string targetName;
public abstract void OnAssetsItemFocus(AssetsItem item);
public abstract void OnAssetsItemInvoke(AssetsItem item);
}
private class SkyItem : AssetBundleItem
{
[Resources, SerializeField] private Material SkyBox;
public class SkyItemInstanceWrapper : Singleton<SkyItemInstanceWrapper>
{
public static void InitInstance()
{
if (instance == null)
{
instance = new SkyItemInstanceWrapper();
}
}
[InspectorDraw(InspectorDrawType.Reference), Ignore] public Material SkyBox;
[InspectorDraw(InspectorDrawType.Text), Ignore] public string SkyBoxName;
}
private void OnEnable()
{
SkyItemInstanceWrapper.InitInstance();
}
private void OnDisable()
{
SkyBox = null;
}
public override void OnAssetsItemFocus(AssetsItem item)
{
if (SkyBox == null)
{
SkyBox = ab.LoadAsset<Material>(targetName);
}
}
public override void OnAssetsItemInvoke(AssetsItem item)
{
SkyExtension.Load(SkyBox);
if (!HierarchyWindow.instance.ContainsReference(SkyItemInstanceWrapper.instance))
{
var skyItem = HierarchyWindow.instance.CreateRootItemEntryWithBinders(SkyItemInstanceWrapper.instance)[0].ref_value.GetComponent<HierarchyItem>();
skyItem.title = "Global Skybox";
}
SkyItemInstanceWrapper.instance.SkyBox = SkyBox;
SkyItemInstanceWrapper.instance.SkyBoxName = targetName;
InspectorWindow.instance.ClearWindow();
}
}
private class SceneItem : AssetBundleItem
{
[Resources, SerializeField] private bool isLoad = false;
[Content, SerializeField, Ignore] private Scene m_Scene;
private PropertiesWindow.ItemEntry m_entry;
public override void OnAssetsItemFocus(AssetsItem item)
{
}
public override void OnAssetsItemInvoke(AssetsItem item)
{
if (isLoad = !isLoad)
{
SceneExtension.Load(targetName);
item.GetComponent<Image>().color = Color.green;
// init scene item
m_Scene = SceneExtension.GetScene(targetName);
m_entry = HierarchyWindow.instance.CreateRootItemEntryWithBinders(item)[0];
var hierarchyItem = m_entry.ref_value.GetComponent<HierarchyItem>();
hierarchyItem.title = m_Scene.name;
}
else
{
SceneExtension.Unload(targetName);
item.GetComponent<Image>().color = Color.white;
// unload scene item
m_entry.Release();
}
}
}
private class GameObjectItem : AssetBundleItem, IOnlyFocusThisOnInspector
{
[Content, IsInstantiated(true)] public GameObject target;
[Content, IsInstantiated(true)] public GameObject last;
private Image image;
[InspectorDraw(InspectorDrawType.Button), Content]
public void ReleaseGameObjectToScene()
{
if (target != null)
{
HierarchyWindow.instance.CreateRootItemEntryWithGameObject(target);
target = null;
}
}
[InspectorDraw(InspectorDrawType.Button), Content]
public void DestroyCurrentSelect()
{
if (target != null)
{
if (HierarchyWindow.instance.ContainsReference(target))
{
HierarchyWindow.instance.GetReferenceItem(target).Entry.Release();
HierarchyWindow.instance.RemoveReference(target);
}
GameObject.Destroy(target);
target = null;
}
}
private void OnEnable()
{
image = GetComponent<Image>();
}
private void OnDisable()
{
if (target != null)
{
GameObject.Destroy(target);
}
}
private void FixedUpdate()
{
image.color = target == null ? Color.white : Color.green;
}
public override void OnAssetsItemFocus(AssetsItem item)
{
}
public override void OnAssetsItemInvoke(AssetsItem item)
{
if (target == null)
{
last = target;
target = GameObject.Instantiate(ab.LoadAsset<GameObject>(targetName));
try
{
target.BroadcastMessage($"On{nameof(GameObjectItem)}", this, SendMessageOptions.DontRequireReceiver);
}
catch (InvalidOperationException)
{
target = null;
}
}
else
{
ReleaseGameObjectToScene();
}
}
}
// --------------------
private void OnAssetsItemFocusWithFileLoading([In] AssetsItem item)
{
if (m_File.IsAssetBundle)
{
if (m_File.data == null)
{
StartLoad();
StartCoroutine(this.m_File.LoadAsAssetBundle(LoadAssetBundle));
}
}
else
{
if (m_File.data == null && m_File.FileSize < 1024 * 50)
m_File.Load();
}
void StartLoad()
{
m_IsLoading = true;
item.GetComponent<Image>().color = Color.red;
}
void EndLoad()
{
m_IsLoading = false;
item.GetComponent<Image>().color = Color.white;
}
void LoadAssetBundle()
{
EndLoad();
AssetBundle ab = m_File.data as AssetBundle;
var assets = ab.GetAllAssetNames().ToList();
assets.AddRange(ab.GetAllScenePaths());
var entries = item.AddChilds(assets.Count);
for (int i = 0, e = assets.Count; i < e; i++)
{
entries[i].ref_value.GetComponent<FileSystemAssetsItem>().RebuildButNotFileInfo(assets[i]);
AssetBundleItem abitem = null;
var objectName = new ToolFile(assets[i]).GetFilename(false);
if (objectName.Contains("is sky") || m_File.ExtensionIs("skys"))
{
abitem = entries[i].ref_value.gameObject.AddComponent<SkyItem>();
}
else if (m_File.ExtensionIs("scenes"))
{
abitem = entries[i].ref_value.gameObject.AddComponent<SceneItem>();
UpdateSpriteAndTitle(entries[i].ref_value.gameObject.GetComponent<AssetsItem>(), new ToolFile(assets[i]).GetFilename(true), "scene");
abitem.targetName = assets[i];
}
else if (objectName.Contains("is gameobject") || m_File.ExtensionIs("gameobjects"))
{
abitem = entries[i].ref_value.gameObject.AddComponent<GameObjectItem>();
}
if (abitem != null)
{
if (abitem.ab == null)
abitem.ab = ab;
if (abitem.targetName == null || abitem.targetName.Length == 0)
abitem.targetName = objectName;
}
}
}
}
private void RefreshWithToolFile([In] AssetsItem item)
{
ReleaseAllChilds(item);
if (m_File.IsDir())
{
var files = m_File.DirToolFileIter();
var paths = (from file in files
where !file.ExtensionIs("meta")
where !file.Filename.ToLower().Contains("<ignore file>")
select file).ToList().ConvertAll(x => x.FullPath);
AddChils(item, paths);
}
else
{
OnAssetsItemFocusWithFileLoading(item);
}
ItemPathName = m_File.GetFilename(false);
OnAssetsItemFocusWithFileMode(item, m_File.GetFilename(true));
}
private void ReleaseAllChilds(AssetsItem item)
{
item.RemoveAllChilds();
}
private List<PropertiesWindow.ItemEntry> AddChils([In] AssetsItem item, [In] List<string> paths)
{
var entries = item.AddChilds(paths.Count);
for (int i = 0, e = paths.Count; i < e; i++)
{
entries[i].ref_value.GetComponent<FileSystemAssetsItem>().RebuildFileInfo(paths[i]);
}
return entries;
}
public void OnAssetsItemFocus([In] AssetsItem item)
{
if (m_Dirty)
{
if (m_File != null)
{
RefreshWithToolFile(item);
}
m_Dirty = false;
}
item.HasChildLayer = item.ChildCount() != 0 ||
((m_File != null && m_File.IsExist) && (m_File.IsDir() || m_File.IsAssetBundle));
FileSystemAssets.instance.CurrentSelectFilename.title = ItemPathName;
InspectorWindow.instance.SetTarget(this, null);
}
public void OnAssetsItemInvoke([In] AssetsItem item)
{
//while (m_IsLoading)
{
#if UNITY_EDITOR
// Debug.Log("file loading", this);
#endif
}
}
[Content, OnlyPlayMode]
public void SetDirty()
{
m_Dirty = true;
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 164be0dc96141c54f83118ba1fcc3d6f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,42 @@
using UnityEngine;
using UnityEngine.UI;
namespace Convention.WindowsUI.Variant
{
public class ConsoleListItem : WindowUIModule,IText,ITitle
{
[Resources, SerializeField, OnlyNotNullMode] private Text MyTitleText;
[Resources, SerializeField, OnlyNotNullMode] private Button RawButton;
public string stackTrace;
public bool IsEnableFocusWindow;
public LogType logType;
public string text { get => ((IText)this.MyTitleText).text; set => ((IText)this.MyTitleText).text = value; }
public string title { get => ((ITitle)this.MyTitleText).title; set => ((ITitle)this.MyTitleText).title = value; }
public void SetupMessage(string message, string stackTrace, string color, LogType logType, string format = "<color={color}>{message}</color>")
{
format = format.Replace("{color}", color);
format = format.Replace("{message}", message);
this.title = format;
this.stackTrace = stackTrace;
this.logType = logType;
}
protected void Start()
{
RawButton.onClick.AddListener(OnFocusConsoleItem);
}
[Content]
public void OnFocusConsoleItem()
{
ConsoleWindow.instance.SetStackTrace(this.title + "\n\n" + this.stackTrace);
if (!IsEnableFocusWindow)
return;
if (FocusWindowIndictaor.instance != null)
FocusWindowIndictaor.instance.SetTargetRectTransform(MyTitleText.transform as RectTransform);
}
}
}

View File

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

View File

@@ -0,0 +1,153 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace Convention.WindowsUI.Variant
{
[RequireComponent(typeof(PropertiesWindow))]
public class ConsoleWindow : MonoSingleton<ConsoleWindow>
{
[Resources, SerializeField, OnlyNotNullMode, Header("Bar Button Setting")] private WindowManager m_WindowManager;
[Resources, SerializeField, OnlyNotNullMode(nameof(m_WindowManager))] private RectTransform m_root;
[Resources, SerializeField, OnlyNotNullMode(nameof(m_WindowManager))] private RectTransform m_plane;
public int ConsoleWindowIndex { get; private set; }
[Header("Property Window - ListView"), Resources, SerializeField, OnlyNotNullMode] private PropertiesWindow m_ListView;
private List<PropertiesWindow.ItemEntry> m_entries = new();
[Resources, SerializeField, OnlyNotNullMode] private ModernUIInputField StackTrace;
[Header("Message Switch"), Resources, SerializeField, OnlyNotNullMode] private ModernUIToggle m_MessageSwitch;
[Resources, SerializeField, OnlyNotNullMode] private ModernUIToggle m_WarningSwitch;
[Resources, SerializeField, OnlyNotNullMode] private ModernUIToggle m_VitalSwitch;
[Resources, SerializeField, OnlyNotNullMode] private Button m_ClearLogs;
[Setting] public string ConsoleButtonName = "Console";
public void ClearLog()
{
foreach (var entry in m_entries)
{
entry.Release();
}
m_entries.Clear();
}
public void Log(string condition, string stackTrace, LogType type = LogType.Log)
{
ConsoleListItem item;
string color;
GenerateLogItem(type, out item, out color);
item.SetupMessage(condition, stackTrace, color, type);
}
private void GenerateLogItem(LogType type, out ConsoleListItem item, out string color)
{
bool isActive = type switch
{
LogType.Log => m_MessageSwitch.ref_value,
LogType.Warning => m_WarningSwitch.ref_value,
_ => m_VitalSwitch.ref_value
};
PropertiesWindow.ItemEntry entry = m_ListView.CreateRootItemEntries(isActive, 1)[0];
m_entries.Add(entry);
item = entry.ref_value.GetComponent<ConsoleListItem>();
color = type switch
{
LogType.Log => "white",
LogType.Warning => "yellow",
_ => "red"
};
}
public void Log(string condition, string stackTrace, LogType type, string format)
{
ConsoleListItem item;
string color;
GenerateLogItem(type, out item, out color);
item.SetupMessage(condition, stackTrace, color, type, format);
}
public void SetStackTrace(string str)
{
StackTrace.text = str;
}
private void Start()
{
Application.logMessageReceived -= Log;
Application.logMessageReceived += Log;
ConsoleWindowIndex = m_WindowManager.AddContextPlane(m_plane, m_root);
var buttonWrapper = m_WindowManager.CreateWindowBarButton(() =>
{
m_WindowManager.SelectContextPlane(ConsoleWindowIndex);
});
(buttonWrapper.button as ITitle).title = ConsoleButtonName;
//StackTrace.interactable = false;
StackTrace.InputFieldSource.Source.readOnly = true;
m_MessageSwitch.ref_value = true;
m_WarningSwitch.ref_value = true;
m_VitalSwitch.ref_value = true;
m_MessageSwitch.AddListener(x =>
{
foreach (var entry in m_entries)
{
var item = entry.ref_value.GetComponent<ConsoleListItem>();
if (item.logType == LogType.Log)
{
item.gameObject.SetActive(x);
}
}
});
m_WarningSwitch.AddListener(x =>
{
foreach (var entry in m_entries)
{
var item = entry.ref_value.GetComponent<ConsoleListItem>();
if (item.logType == LogType.Warning)
{
item.gameObject.SetActive(x);
}
}
});
m_VitalSwitch.AddListener(x =>
{
foreach (var entry in m_entries)
{
var item = entry.ref_value.GetComponent<ConsoleListItem>();
if (item.logType != LogType.Log && item.logType != LogType.Warning)
{
item.gameObject.SetActive(x);
}
}
});
m_ClearLogs.onClick.AddListener(() =>
{
foreach (var entry in m_entries)
{
entry.Release();
}
m_entries.Clear();
});
m_WindowManager.SelectContextPlane(0);
}
[Setting, OnlyPlayMode]
public void TestLog()
{
Debug.Log("Test");
}
[Setting, OnlyPlayMode]
public void TestWarning()
{
Debug.LogWarning("Test");
}
[Setting, OnlyPlayMode]
public void TestError()
{
Debug.LogError("Test");
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2e7463b7af27b97469b0411d420abc2c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
using System.Collections.Generic;
using System;
using static Convention.WindowsUI.Variant.PropertiesWindow;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
namespace Convention.WindowsUI.Variant
{
public class ConversationItem : PropertyListItem
{
[Resources, SerializeField] private Image m_Icon;
[Resources, SerializeField] private Text m_Role;
[Resources, SerializeField] private Text m_Text;
[Setting] public float LineHeight = 25;
public void Setup([In] string text, [In] string role, int lineSize)
{
m_Icon.sprite = ConversationWindow.instance.GetRoleIconSprite(role);
m_Role.text = text;
m_Text.text = text;
var rect = this.transform as RectTransform;
rect.sizeDelta = new(rect.sizeDelta.x, LineHeight * lineSize);
}
}
}

View File

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

View File

@@ -0,0 +1,76 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace Convention.WindowsUI.Variant
{
public class ConversationWindow : MonoSingleton<ConversationWindow>
{
[Resources, OnlyNotNullMode] public WindowManager m_WindowManager;
[Resources, SerializeField, OnlyNotNullMode] private PropertiesWindow m_PropertiesWindow;
private RegisterWrapper<ConversationWindow> m_RegisterWrapper;
[Resources, Header("HeadLine"), OnlyNotNullMode] public Image HeadIcon;
[Resources, OnlyNotNullMode] public ModernUIInputField HeadText = new();
[Resources] public List<Text> HeadTitles = new();
private List<PropertiesWindow.ItemEntry> m_entries = new();
[Resources, Header("Roles Icon"), SerializeField, HopeNotNull] private ScriptableObject m_RolesIcon;
[Resources, SerializeField, OnlyNotNullMode] private Sprite m_DefaultRoleIcon;
public Sprite GetRoleIconSprite([In] string role)
{
if (m_RolesIcon == null)
return m_DefaultRoleIcon;
if (m_RolesIcon.uobjects.TryGetValue(role, out var roleIcon_) && roleIcon_ is Sprite roleIcon)
return roleIcon;
return m_DefaultRoleIcon;
}
private void Reset()
{
m_WindowManager = GetComponent<WindowManager>();
m_PropertiesWindow = GetComponent<PropertiesWindow>();
}
private void Start()
{
m_RegisterWrapper = new(() =>
{
});
}
private void OnDestroy()
{
m_RegisterWrapper.Release();
}
public void SetHeadText(string text)
{
HeadText.text = text;
}
public void SetHeadTitle(int index, string text)
{
HeadTitles[index].text = text;
}
[Resources, Header("InputField")] private ModernUIInputField m_InputField;
public delegate void MessageListener([In] string message);
public event MessageListener messageListener;
public void SendMessage()
{
messageListener?.Invoke(m_InputField.text);
m_InputField.text = "";
}
public void CreateNewMessageListItem()
{
PropertiesWindow.ItemEntry entry = m_PropertiesWindow.CreateRootItemEntries(1)[0];
m_entries.Add(entry);
var item = entry.ref_value.GetComponent<ConversationItem>();
}
}
}

View File

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

View File

@@ -0,0 +1,34 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Convention.WindowsUI.Variant
{
public class FocusWindowIndictaor : MonoSingleton<FocusWindowIndictaor>
{
[Setting, Range(0, 1), Percentage(0, 1)] public float Speed = 0.36f;
[Resources, OnlyNotNullMode] public RectTransform RectBox;
[Resources, OnlyNotNullMode] public RectTransform RopParent;
[Resources] public List<RectTransform> Targets = new();
[Content] public int TargetIndex;
[Content, OnlyPlayMode] public RectTransform Target;
public void SetTargetRectTransform(RectTransform target)
{
Target = target;
}
public void SelectNextTarget()
{
Debug.Log(TargetIndex);
Target = Targets[TargetIndex = (TargetIndex + 1) % Targets.Count];
}
private void LateUpdate()
{
if (Target != null)
RectTransformInfo.UpdateAnimationPlane(Target, RectBox, Speed, 0, true);
else
RectTransformInfo.UpdateAnimationPlane(RopParent, RectBox, Speed, 0, true);
}
}
}

View File

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

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