├── Core
├── AUILayer.cs
├── AUIScreenController.cs
├── ScreenControllerInterfaces.cs
└── ScreenPropertyInterfaces.cs
├── Editor
└── UIFrameworkTools.cs
├── LICENSE
├── MANUAL.md
├── Panel
├── APanelController.cs
├── PanelPriority.cs
├── PanelProperties.cs
└── PanelUILayer.cs
├── README.md
├── ScreenTransitions
├── ATransitionComponent.cs
├── LegacyAnimationScreenTransition.cs
└── SimpleFadeTransition.cs
├── UIFrame.cs
├── UISettings.cs
└── Window
├── AWindowController.cs
├── WindowHistoryEntry.cs
├── WindowParaLayer.cs
├── WindowPriority.cs
├── WindowProperties.cs
└── WindowUILayer.cs
/Core/AUILayer.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections.Generic;
3 |
4 | namespace deVoid.UIFramework {
5 | ///
6 | /// Base class for UI Layers. Layers implement custom logic
7 | /// for Screen types when opening, closing etc.
8 | ///
9 | public abstract class AUILayer : MonoBehaviour where TScreen : IUIScreenController {
10 | protected Dictionary registeredScreens;
11 |
12 | ///
13 | /// Shows a screen
14 | ///
15 | /// The ScreenController to show
16 | public abstract void ShowScreen(TScreen screen);
17 |
18 | ///
19 | /// Shows a screen passing in properties
20 | ///
21 | /// The ScreenController to show
22 | /// The data payload
23 | /// The type of the data payload
24 | public abstract void ShowScreen(TScreen screen, TProps properties) where TProps : IScreenProperties;
25 |
26 | ///
27 | /// Hides a screen
28 | ///
29 | /// The ScreenController to be hidden
30 | public abstract void HideScreen(TScreen screen);
31 |
32 | ///
33 | /// Initialize this layer
34 | ///
35 | public virtual void Initialize() {
36 | registeredScreens = new Dictionary();
37 | }
38 |
39 | ///
40 | /// Reparents the screen to this Layer's transform
41 | ///
42 | /// The screen controller
43 | /// The Screen Transform
44 | public virtual void ReparentScreen(IUIScreenController controller, Transform screenTransform) {
45 | screenTransform.SetParent(transform, false);
46 | }
47 |
48 | ///
49 | /// Register a ScreenController to a specific ScreenId
50 | ///
51 | /// Target ScreenId
52 | /// Screen Controller to be registered
53 | public void RegisterScreen(string screenId, TScreen controller) {
54 | if (!registeredScreens.ContainsKey(screenId)) {
55 | ProcessScreenRegister(screenId, controller);
56 | }
57 | else {
58 | Debug.LogError("[AUILayerController] Screen controller already registered for id: " + screenId);
59 | }
60 | }
61 |
62 | ///
63 | /// Unregisters a given controller from a ScreenId
64 | ///
65 | /// The ScreenId
66 | /// The controller to be unregistered
67 | public void UnregisterScreen(string screenId, TScreen controller) {
68 | if (registeredScreens.ContainsKey(screenId)) {
69 | ProcessScreenUnregister(screenId, controller);
70 | }
71 | else {
72 | Debug.LogError("[AUILayerController] Screen controller not registered for id: " + screenId);
73 | }
74 | }
75 |
76 | ///
77 | /// Attempts to find a registered screen that matches the id
78 | /// and shows it.
79 | ///
80 | /// The desired ScreenId
81 | public void ShowScreenById(string screenId) {
82 | TScreen ctl;
83 | if (registeredScreens.TryGetValue(screenId, out ctl)) {
84 | ShowScreen(ctl);
85 | }
86 | else {
87 | Debug.LogError("[AUILayerController] Screen ID " + screenId + " not registered to this layer!");
88 | }
89 | }
90 |
91 | ///
92 | /// Attempts to find a registered screen that matches the id
93 | /// and shows it, passing a data payload.
94 | ///
95 | /// The Screen Id (by default, it's the name of the Prefab)
96 | /// The data payload for this screen to use
97 | /// The type of the Properties class this screen uses
98 | public void ShowScreenById(string screenId, TProps properties) where TProps : IScreenProperties {
99 | TScreen ctl;
100 | if (registeredScreens.TryGetValue(screenId, out ctl)) {
101 | ShowScreen(ctl, properties);
102 | }
103 | else {
104 | Debug.LogError("[AUILayerController] Screen ID " + screenId + " not registered!");
105 | }
106 | }
107 |
108 | ///
109 | /// Attempts to find a registered screen that matches the id
110 | /// and hides it
111 | ///
112 | /// The id for this screen (by default, it's the name of the Prefab)
113 | public void HideScreenById(string screenId) {
114 | TScreen ctl;
115 | if (registeredScreens.TryGetValue(screenId, out ctl)) {
116 | HideScreen(ctl);
117 | }
118 | else {
119 | Debug.LogError("[AUILayerController] Could not hide Screen ID " + screenId + " as it is not registered to this layer!");
120 | }
121 | }
122 |
123 | ///
124 | /// Checks if a screen is registered to this UI Layer
125 | ///
126 | /// The Screen Id (by default, it's the name of the Prefab)
127 | /// True if screen is registered, false if not
128 | public bool IsScreenRegistered(string screenId) {
129 | return registeredScreens.ContainsKey(screenId);
130 | }
131 |
132 | ///
133 | /// Hides all screens registered to this layer
134 | ///
135 | /// Should the screen animate while hiding?
136 | public virtual void HideAll(bool shouldAnimateWhenHiding = true) {
137 | foreach (var screen in registeredScreens) {
138 | screen.Value.Hide(shouldAnimateWhenHiding);
139 | }
140 | }
141 |
142 | protected virtual void ProcessScreenRegister(string screenId, TScreen controller) {
143 | controller.ScreenId = screenId;
144 | registeredScreens.Add(screenId, controller);
145 | controller.ScreenDestroyed += OnScreenDestroyed;
146 | }
147 |
148 | protected virtual void ProcessScreenUnregister(string screenId, TScreen controller) {
149 | controller.ScreenDestroyed -= OnScreenDestroyed;
150 | registeredScreens.Remove(screenId);
151 | }
152 |
153 | private void OnScreenDestroyed(IUIScreenController screen) {
154 | if (!string.IsNullOrEmpty(screen.ScreenId)
155 | && registeredScreens.ContainsKey(screen.ScreenId)) {
156 | UnregisterScreen(screen.ScreenId, (TScreen) screen);
157 | }
158 | }
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/Core/AUIScreenController.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System;
3 |
4 | namespace deVoid.UIFramework
5 | {
6 | ///
7 | /// Base implementation for UI Screens. You'll probably want to inherit
8 | /// from one of its child classes: AWindowController or APanelController, not this.
9 | ///
10 | ///
11 | ///
12 | public abstract class AUIScreenController : MonoBehaviour, IUIScreenController
13 | where TProps : IScreenProperties
14 | {
15 | [Header("Screen Animations")]
16 | [Tooltip("Animation that shows the screen")]
17 | [SerializeField]
18 | private ATransitionComponent animIn;
19 |
20 | [Tooltip("Animation that hides the screen")]
21 | [SerializeField]
22 | private ATransitionComponent animOut;
23 |
24 | [Header("Screen properties")]
25 | [Tooltip(
26 | "This is the data payload and settings for this screen. You can rig this directly in a prefab and/or pass it when you show this screen")]
27 | [SerializeField]
28 | private TProps properties;
29 |
30 | ///
31 | /// Unique identifier for this ID. If using the default system, it should be the same name as the screen's Prefab.
32 | ///
33 | public string ScreenId { get; set; }
34 |
35 | ///
36 | /// Transition component for the showing up animation
37 | ///
38 | public ATransitionComponent AnimIn
39 | {
40 | get { return animIn; }
41 | set { animIn = value; }
42 | }
43 |
44 | ///
45 | /// Transition component for the hiding animation
46 | ///
47 | public ATransitionComponent AnimOut
48 | {
49 | get { return animOut; }
50 | set { animOut = value; }
51 | }
52 |
53 | ///
54 | /// Occurs when "in" transition is finished.
55 | ///
56 | public Action InTransitionFinished { get; set; }
57 |
58 | ///
59 | /// Occurs when "out" transition is finished.
60 | ///
61 | public Action OutTransitionFinished { get; set; }
62 |
63 | ///
64 | /// Screen can fire this event to request its responsible layer to close it
65 | ///
66 | /// The close request.
67 | public Action CloseRequest { get; set; }
68 |
69 | ///
70 | /// If this screen is destroyed for some reason, it must warn its layer
71 | ///
72 | /// The destruction action.
73 | public Action ScreenDestroyed { get; set; }
74 |
75 | ///
76 | /// Is this screen currently visible?
77 | ///
78 | /// true if visible; otherwise, false.
79 | public bool IsVisible { get; private set; }
80 |
81 | ///
82 | /// The properties of this screen. Can contain
83 | /// serialized values, or passed in private values.
84 | ///
85 | /// The properties.
86 | protected TProps Properties
87 | {
88 | get { return properties; }
89 | set { properties = value; }
90 | }
91 |
92 | protected virtual void Awake()
93 | {
94 | AddListeners();
95 | }
96 |
97 | protected virtual void OnDestroy()
98 | {
99 | if (ScreenDestroyed != null)
100 | {
101 | ScreenDestroyed(this);
102 | }
103 |
104 | InTransitionFinished = null;
105 | OutTransitionFinished = null;
106 | CloseRequest = null;
107 | ScreenDestroyed = null;
108 | RemoveListeners();
109 | }
110 |
111 | ///
112 | /// For setting up all the listeners for events/messages. By default, called on Awake()
113 | ///
114 | protected virtual void AddListeners()
115 | {
116 | }
117 |
118 | ///
119 | /// For removing all the listeners for events/messages. By default, called on OnDestroy()
120 | ///
121 | protected virtual void RemoveListeners()
122 | {
123 | }
124 |
125 | ///
126 | /// When Properties are set for this screen, this method is called.
127 | /// At this point, you can safely access Properties.
128 | ///
129 | protected virtual void OnPropertiesSet()
130 | {
131 | }
132 |
133 | ///
134 | /// When the screen animates out, this is called
135 | /// immediately
136 | ///
137 | protected virtual void WhileHiding()
138 | {
139 | }
140 |
141 | ///
142 | /// When setting the properties, this method is called.
143 | /// This way, you can extend the usage of your properties by
144 | /// certain conditions.
145 | ///
146 | /// Properties.
147 | protected virtual void SetProperties(TProps props)
148 | {
149 | properties = props;
150 | }
151 |
152 | ///
153 | /// In case your screen has any special behaviour to be called
154 | /// when the hierarchy is adjusted
155 | ///
156 | protected virtual void HierarchyFixOnShow()
157 | {
158 | }
159 |
160 | ///
161 | /// Hides the screen
162 | ///
163 | /// Should animation be played? (defaults to true)
164 | public void Hide(bool animate = true)
165 | {
166 | DoAnimation(animate ? animOut : null, OnTransitionOutFinished, false);
167 | WhileHiding();
168 | }
169 |
170 | ///
171 | /// Show this screen with the specified properties.
172 | ///
173 | /// The data for the screen.
174 | public void Show(IScreenProperties props = null)
175 | {
176 | if (props != null)
177 | {
178 | if (props is TProps)
179 | {
180 | SetProperties((TProps) props);
181 | }
182 | else
183 | {
184 | Debug.LogError("Properties passed have wrong type! (" + props.GetType() + " instead of " +
185 | typeof(TProps) + ")");
186 | return;
187 | }
188 | }
189 |
190 | HierarchyFixOnShow();
191 | OnPropertiesSet();
192 |
193 | if (!gameObject.activeSelf)
194 | {
195 | DoAnimation(animIn, OnTransitionInFinished, true);
196 | }
197 | else
198 | {
199 | if (InTransitionFinished != null)
200 | {
201 | InTransitionFinished(this);
202 | }
203 | }
204 | }
205 |
206 | private void DoAnimation(ATransitionComponent caller, Action callWhenFinished, bool isVisible)
207 | {
208 | if (caller == null)
209 | {
210 | gameObject.SetActive(isVisible);
211 | if (callWhenFinished != null)
212 | {
213 | callWhenFinished();
214 | }
215 | }
216 | else
217 | {
218 | if (isVisible && !gameObject.activeSelf)
219 | {
220 | gameObject.SetActive(true);
221 | }
222 |
223 | caller.Animate(transform, callWhenFinished);
224 | }
225 | }
226 |
227 | private void OnTransitionInFinished()
228 | {
229 | IsVisible = true;
230 |
231 | if (InTransitionFinished != null)
232 | {
233 | InTransitionFinished(this);
234 | }
235 | }
236 |
237 | private void OnTransitionOutFinished()
238 | {
239 | IsVisible = false;
240 | gameObject.SetActive(false);
241 |
242 | if (OutTransitionFinished != null)
243 | {
244 | OutTransitionFinished(this);
245 | }
246 | }
247 | }
248 | }
249 |
--------------------------------------------------------------------------------
/Core/ScreenControllerInterfaces.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace deVoid.UIFramework {
4 | ///
5 | /// Interface that all UI Screens must implement directly or indirectly
6 | ///
7 | public interface IUIScreenController {
8 | string ScreenId { get; set; }
9 | bool IsVisible { get; }
10 |
11 | void Show(IScreenProperties props = null);
12 | void Hide(bool animate = true);
13 |
14 | Action InTransitionFinished { get; set; }
15 | Action OutTransitionFinished { get; set; }
16 | Action CloseRequest { get; set; }
17 | Action ScreenDestroyed { get; set; }
18 | }
19 |
20 | ///
21 | /// Interface that all Windows must implement
22 | ///
23 | public interface IWindowController : IUIScreenController {
24 | bool HideOnForegroundLost { get; }
25 | bool IsPopup { get; }
26 | WindowPriority WindowPriority { get; }
27 | }
28 |
29 | ///
30 | /// Interface that all Panels must implement
31 | ///
32 | public interface IPanelController : IUIScreenController {
33 | PanelPriority Priority { get; }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Core/ScreenPropertyInterfaces.cs:
--------------------------------------------------------------------------------
1 | namespace deVoid.UIFramework
2 | {
3 | ///
4 | /// Base interface for all the screen properties
5 | ///
6 | public interface IScreenProperties { }
7 |
8 | ///
9 | /// Base interface for all Panel properties
10 | ///
11 | public interface IPanelProperties : IScreenProperties
12 | {
13 | PanelPriority Priority { get; set; }
14 | }
15 |
16 | ///
17 | /// Base interface for Window properties.
18 | ///
19 | public interface IWindowProperties : IScreenProperties
20 | {
21 | WindowPriority WindowQueuePriority { get; set; }
22 | bool HideOnForegroundLost { get; set; }
23 | bool IsPopup { get; set; }
24 | bool SuppressPrefabProperties { get; set; }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Editor/UIFrameworkTools.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using UnityEditor;
5 | using UnityEngine;
6 | using UnityEngine.EventSystems;
7 | using UnityEngine.UI;
8 |
9 | namespace deVoid.UIFramework.Editor
10 | {
11 | public static class UIFrameworkTools
12 | {
13 | [MenuItem("Assets/Create/deVoid UI/UI Frame in Scene", priority = 2)]
14 | public static void CreateUIFrameInScene() {
15 | CreateUIFrame();
16 | }
17 |
18 | [MenuItem("Assets/Create/deVoid UI/UI Frame Prefab", priority = 1)]
19 | public static void CreateUIFramePrefab() {
20 | var frame = CreateUIFrame();
21 |
22 | string prefabPath = GetCurrentPath();
23 | prefabPath = EditorUtility.SaveFilePanel("UI Frame Prefab", prefabPath,"UIFrame", "prefab");
24 |
25 | if (prefabPath.StartsWith(Application.dataPath)) {
26 | prefabPath = "Assets" + prefabPath.Substring(Application.dataPath.Length);
27 | }
28 |
29 | if (!string.IsNullOrEmpty(prefabPath)) {
30 | CreateNewPrefab(frame, prefabPath);
31 | }
32 |
33 | Object.DestroyImmediate(frame);
34 | }
35 |
36 | private static GameObject CreateUIFrame() {
37 | var uiLayer = LayerMask.NameToLayer("UI");
38 | var root = new GameObject("UIFrame");
39 | var camera = new GameObject("UICamera");
40 |
41 | var cam = camera.AddComponent();
42 | cam.clearFlags = CameraClearFlags.Depth;
43 | cam.cullingMask = LayerMask.GetMask("UI");
44 | cam.orthographic = true;
45 | cam.farClipPlane = 25;
46 |
47 | root.AddComponent();
48 | var canvas = root.AddComponent