Skip to content

Commit

Permalink
feat: Several
Browse files Browse the repository at this point in the history
- Window now has virtual methods corresponding to each event
- StatefulView now updates view on start using an explicit flag
- PictureEditor cleaned up
- Texture2DDownloader.Download method downloads using UniTask
- Initializer has more features
- ViewList.SubscscribeToChildren is now ViewList.InvokeAllChildViews
- StatefulView abstract method on state set is now OnStateSet
- StatefulView event on state set is StateSet

Break: Renamed properties, fields and methods. Some kept intact with
Obsolete attribute
  • Loading branch information
adrenak committed Apr 30, 2021
1 parent 71977b2 commit 150db89
Show file tree
Hide file tree
Showing 27 changed files with 636 additions and 288 deletions.
14 changes: 6 additions & 8 deletions Assets/Adrenak.UGX/Editor/PictureEditor.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using UnityEditor;
using UnityEditor.UI;

using UnityEngine;

namespace Adrenak.UGX {
Expand All @@ -17,11 +18,11 @@ public override void OnInspectorGUI() {
EditorGUI.EndDisabledGroup();

showEvents = EditorGUILayout.Foldout(showEvents, new GUIContent("Events"));
if (showEvents) {
if (showEvents) {
EditorGUILayout.PropertyField(serializedObject.FindProperty("onLoadStart"), new GUIContent("On Load Start"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("onLoadSuccess"), new GUIContent("On Load Success"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("onLoadFailure"), new GUIContent("On Load Failure"));
}
EditorGUILayout.PropertyField(serializedObject.FindProperty("onLoadFailure"), new GUIContent("On Load Failure"));
}

image.refreshOnStart = EditorGUILayout.Toggle("Refresh On Start", image.refreshOnStart);
image.updateWhenOffScreen = EditorGUILayout.Toggle("Update When Off Screen", image.updateWhenOffScreen);
Expand All @@ -31,15 +32,12 @@ public override void OnInspectorGUI() {
image.compression = (Texture2DCompression)EditorGUILayout.EnumPopup("Texture Compression", image.compression);
EditorGUILayout.Space();

image.source = (Picture.Source)EditorGUILayout.EnumPopup("Source Type", image.source);

if(image.source != Picture.Source.Asset)
image.path = EditorGUILayout.TextField("Source Path", image.path);
image.path = EditorGUILayout.TextField("Source Path", image.path);

serializedObject.ApplyModifiedProperties();

if (GUILayout.Button("Refresh Picture"))
image.Refresh();
image.Refresh();
}
}
}
2 changes: 0 additions & 2 deletions Assets/Adrenak.UGX/Editor/WindowEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ public override void OnInspectorGUI() {
EditorGUILayout.EnumPopup("Status", window.Status);
EditorGUI.EndDisabledGroup();

window.autoPopOnBack = EditorGUILayout.Toggle("Auto-Pop on back", window.autoPopOnBack);

showEvents = EditorGUILayout.Foldout(showEvents, new GUIContent("Events"));
if (showEvents) {
EditorGUILayout.PropertyField(serializedObject.FindProperty("onWindowStartOpening"), new GUIContent("On Window Start Opening"));
Expand Down
4 changes: 3 additions & 1 deletion Assets/Adrenak.UGX/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## UGX

Unity GUI Extended
UGX (**U**nity u**G**UI E**x**tended) is a library over uGUI for creating UI in Unity.

UGX provides high-level features such as windows, state management, animations, navigation over the inbuilt uGUI components.

### Docs coming soon
In the meantime, checkout the [samples](https://www.github.com/adrenak/ugx-samples)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public override void Get(string location, Texture2DCompression compression, Pict
}

var request = new Request(onSuccess, onFailure);
requests.EnsureContains(key, new List<Request>() { });
requests.EnsureKey(key, new List<Request>() { });
requests[key].Add(request);
if (requests[key].Count > 1)
return;
Expand All @@ -85,8 +85,8 @@ public override void Get(string location, Texture2DCompression compression, Pict
var resultSprite = result.ToSprite();

freed.EnsureDoesntContain(key);
resources.EnsureContains(key, resultSprite);
instances.EnsureContains(key, new List<Picture>());
resources.EnsureKey(key, resultSprite);
instances.EnsureKey(key, new List<Picture>());
instances[key].Add(instance);

foreach (var req in requests[key])
Expand Down
22 changes: 12 additions & 10 deletions Assets/Adrenak.UGX/Runtime/Navigation/DefaultUGXNavigator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ protected override void PushImpl(Window window) {
// First push
if (History.Count == 0) {
History.Add(window);
SetAsActive(window);
SetAsCurrent(window);
return;
}

Expand All @@ -22,28 +22,30 @@ protected override void PushImpl(Window window) {
// Alternate repeat push
if (History.Count > 1 && History.FromLast(1).gameObject == window.gameObject) {
History.RemoveAt(History.Count - 1);
SetAsActive(History.Last());
SetAsCurrent(History.Last());
return;
}

// All other cases
History.Add(window);
SetAsActive(window);
SetAsCurrent(window);

onPush.Invoke();
onPush.Invoke(window);
}

protected override void PopImpl() {
if (History.Count > 1) {
History.RemoveAt(History.Count - 1);
SetAsActive(History.Last());
onPop.Invoke();
var last = History.Last();
History.RemoveLast();
SetAsCurrent(History.Last());
onPop.Invoke(last);
}
else if(History.Count == 1){
History.Last().CloseWindow();
History.RemoveAt(0);
active = null;
onPop.Invoke();
var first = History[0];
History.Remove(first);
current = null;
onPop.Invoke(first);
}
}
}
Expand Down
66 changes: 47 additions & 19 deletions Assets/Adrenak.UGX/Runtime/Navigation/Navigator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,29 @@

namespace Adrenak.UGX {
public abstract class Navigator : MonoBehaviour {
[System.Serializable]
public class WindowUnityEvent : UnityEvent<Window> { }

static Dictionary<string, Navigator> map = new Dictionary<string, Navigator>();
public static Navigator Get(string browserID = null) {
if (map.ContainsKey(browserID))
return map[browserID];
return null;
}

public WindowUnityEvent onPush = new WindowUnityEvent();
public WindowUnityEvent onPop = new WindowUnityEvent();

#pragma warning disable 0649
[SerializeField] string browserID;
[SerializeField] bool canPopAll;

[ReadOnly] [SerializeField] protected Window active = null;
public Window Current => active;
[ReadOnly] [SerializeField] protected Window current = null;
public Window Current => current;

[ReadOnly] [ReorderableList] [SerializeField] protected List<Window> history = new List<Window>();
public List<Window> History => history;

public UnityEvent onPush;
public UnityEvent onPop;

[SerializeField] protected bool useInitialWindow;
[ShowIf("useInitialWindow")] [SerializeField] protected Window initialWindow;
#pragma warning restore 0649
Expand All @@ -52,41 +55,66 @@ void UnregisterInstance() {

void CheckBackPress() {
if (!Input.GetKeyUp(KeyCode.Escape)) return;
if (!active.autoPopOnBack) return;
Pop();
}

protected void SetAsActive(Window window) {
window.OpenWindow();
if (active != null)
active.CloseWindow();
active = window;
}

// ================================================
// API / PUBLIC
// ================================================
/// <summary>
/// Push a Window to the navigation and open it.
/// </summary>
public void Push(Window window) {
PushImpl(window);
}

/// <summary>
/// Pops a Window from the navigation and closes it
/// </summary>
public void Pop() {
if (History.Count == 1 && !canPopAll)
return;
PopImpl();
}

/// <summary>
/// Pops all Windows
/// </summary>
public void Clear() {
while (History.Count > 0)
PopImpl();
}

protected abstract void PushImpl(Window window);

protected abstract void PopImpl();

/// <summary>
/// Pops a Window if it's active, Push it if it's not.
/// </summary>
public void Toggle(Window window) {
if (History.Count > 0 && History.Last() == window)
Pop();
else
Push(window);
}
Push(window);
}

// ================================================
// CONTRACT
// ================================================
/// <summary>
/// Actual Push logic to be implemented by subclass
/// </summary>
/// <param name="window"></param>
protected abstract void PushImpl(Window window);

/// <summary>
/// Actual Pop logic to be implemented by subclass
/// </summary>
protected abstract void PopImpl();

// ================================================
protected void SetAsCurrent(Window window) {
window.OpenWindow();
if (current != null)
current.CloseWindow();
current = window;
}
}
}
4 changes: 3 additions & 1 deletion Assets/Adrenak.UGX/Runtime/Popup/AlertPopup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ async protected override UniTask<PopupResponse> GetResponse() {
return new PopupResponse();
}

protected override void HandlePopupStateSet() {
protected override void OnStateSet() {
headerDisplay.text = State.header;
bodyDisplay.text = State.description;
ackDisplay.text = State.ack;
Expand All @@ -35,5 +35,7 @@ protected override void HandlePopupStateSet() {
public void Acknowledge() {
OnAcknowledge?.Invoke();
}

protected override void OnStart() { }
}
}
4 changes: 3 additions & 1 deletion Assets/Adrenak.UGX/Runtime/Popup/AskPopup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ async protected override UniTask<AskPopupResponse> GetResponse() {
return new AskPopupResponse { positive = response.Value };
}

protected override void HandlePopupStateSet() {
protected override void OnStateSet() {
headerDisplay.text = State.header;
bodyDisplay.text = State.body;
positiveDisplay.text = State.positive;
Expand All @@ -47,5 +47,7 @@ protected override void HandlePopupStateSet() {

Action OnDeny;
public void Deny() => OnDeny?.Invoke();

protected override void OnStart() { }
}
}
4 changes: 3 additions & 1 deletion Assets/Adrenak.UGX/Runtime/Popup/AskWithFlagPopup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ async protected override UniTask<AskWithFlagPopupResponse> GetResponse() {
};
}

protected override void HandlePopupStateSet() {
protected override void OnStateSet() {
headerDisplay.text = State.header;
bodyDisplay.text = State.body;
positiveDisplay.text = State.positive;
Expand All @@ -52,5 +52,7 @@ protected override void HandlePopupStateSet() {

Action OnDeny;
public void Deny() => OnDeny?.Invoke();

protected override void OnStart() { }
}
}
4 changes: 3 additions & 1 deletion Assets/Adrenak.UGX/Runtime/Popup/NotificationPopup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ async protected override UniTask<PopupResponse> GetResponse() {
return new PopupResponse();
}

protected override void HandlePopupStateSet() {
protected override void OnStateSet() {
title.text = State.title;
description.text = State.description;
}

protected override void OnStart() { }
}
}
22 changes: 16 additions & 6 deletions Assets/Adrenak.UGX/Runtime/Popup/Popup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,23 @@
using Cysharp.Threading.Tasks;

namespace Adrenak.UGX {
/// <summary>
/// Base class for states of popup implementations
/// </summary>
[SerializeField]
public class PopupState : ViewState { }

/// <summary>
/// Base class for response of popup implementation
/// </summary>
[Serializable]
public class PopupResponse { }

/// <summary>
/// Base class for popups. Inherit from this class to implement different kinds of popups
/// </summary>
/// <typeparam name="TState"></typeparam>
/// <typeparam name="Response"></typeparam>
[RequireComponent(typeof(Window))]
public abstract class Popup<TState, Response> : StatefulView<TState> where TState : PopupState where Response : PopupResponse {
/// <summary>
Expand Down Expand Up @@ -44,23 +55,22 @@ async public void SetStateAndDisplay(TState state, Action<Response> responseCall
responseCallback?.Invoke(await SetStateAndDisplay(state));

/// <summary>
/// Displays the popup with a given state modifier and returns the response as a task
/// Displays the popup with a given state modifier action and returns the response as a task
/// </summary>
async public UniTask<Response> ModifyStateAndDisplay(Action<TState> stateModifier) {
stateModifier?.Invoke(State);
return await Display();
}

/// <summary>
/// Displays the popup with a given state modifier and returns the response as a callback
/// Displays the popup with a given state modifier action and returns the response as a callback
/// </summary>
async public void ModifyStateAndDisplay(Action<TState> stateModifier, Action<Response> responseCallback) =>
responseCallback?.Invoke(await ModifyStateAndDisplay(stateModifier));

protected override void HandleStateSet() => HandlePopupStateSet();

protected abstract void HandlePopupStateSet();

protected abstract UniTask<Response> GetResponse();

[Obsolete(".HandleStateSet instead")]
protected virtual void HandlePopupStateSet() => OnStateSet();
}
}
Loading

0 comments on commit 150db89

Please sign in to comment.