diff --git a/Assets/EventManager/Source/Event.cs.meta b/Assets/EventManager/Source/Event.cs.meta
index 5062693..fd592c8 100644
--- a/Assets/EventManager/Source/Event.cs.meta
+++ b/Assets/EventManager/Source/Event.cs.meta
@@ -1,8 +1,9 @@
fileFormatVersion: 2
-guid: 31025e63368c145d89224258a7e0f6d7
-timeCreated: 1455836011
+guid: 9990916267d7d03478fcc638ec84d163
+timeCreated: 1518809105
licenseType: Free
MonoImporter:
+ externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
diff --git a/Assets/EventManager/Source/EventManager.cs b/Assets/EventManager/Source/EventManager.cs
index f748fdf..531aa28 100644
--- a/Assets/EventManager/Source/EventManager.cs
+++ b/Assets/EventManager/Source/EventManager.cs
@@ -1,109 +1,213 @@
+using System;
using System.Collections;
using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using UnityEngine;
-namespace SDD.Events {
-
- ///
- /// Event Manager manages publishing raised events to subscribing/listening classes.
- ///
- /// @example subscribe
- /// EventManager.Instance.AddListener(OnSomethingHappened);
- ///
- /// @example unsubscribe
- /// EventManager.Instance.RemoveListener(OnSomethingHappened);
- ///
- /// @example publish an event
- /// EventManager.Instance.Raise(new SomethingHappenedEvent());
- ///
- /// This class is a minor variation on
- ///
- public class EventManager {
-
- public static EventManager Instance {
- get {
- if (instance == null) {
- instance = new EventManager();
+namespace SDD.Events
+{
+
+ ///
+ /// Event Manager manages publishing raised events to subscribing/listening classes.
+ ///
+ /// @example subscribe
+ /// EventManager.Instance.AddListener(OnSomethingHappened);
+ ///
+ /// @example unsubscribe
+ /// EventManager.Instance.RemoveListener(OnSomethingHappened);
+ ///
+ /// @example publish an event
+ /// EventManager.Instance.Raise(new SomethingHappenedEvent());
+ ///
+ /// This class is a minor variation on
+ ///
+ public class EventManager
+ {
+
+ public static EventManager Instance
+ {
+ get
+ {
+ if (instance == null)
+ {
+ instance = new EventManager();
+ }
+
+ return instance;
+ }
}
+ private static EventManager instance = null;
- return instance;
- }
- }
- private static EventManager instance = null;
+ public List Events { get; private set; }
+ public bool EnableDebugLog { get; set; }
+ public bool EnableEventVisualization { get; set; }
- public delegate void EventDelegate(T e) where T : Event;
- private delegate void EventDelegate(Event e);
+ private EventManager()
+ {
+ Events = new List();
+ EnableEventVisualization = true;
+ EnableDebugLog = false;
+ }
- ///
- /// The actual delegate, there is one delegate per unique event. Each
- /// delegate has multiple invocation list items.
- ///
- private Dictionary delegates = new Dictionary();
+ public delegate void EventDelegate(T e) where T : Event;
+ private delegate void EventDelegate(Event e);
+
+ ///
+ /// The actual delegate, there is one delegate per unique event. Each
+ /// delegate has multiple invocation list items.
+ ///
+ private Dictionary delegates = new Dictionary();
+
+ ///
+ /// Lookups only, there is one delegate lookup per listener
+ ///
+ private Dictionary delegateLookup = new Dictionary();
+
+ ///
+ /// Add the delegate.
+ ///
+ public void AddListener(EventDelegate del) where T : Event
+ {
+ if (delegateLookup.ContainsKey(del))
+ {
+ return;
+ }
+
+ if (EnableEventVisualization) LogAddListener(del);
+
+ // Create a new non-generic delegate which calls our generic one. This
+ // is the delegate we actually invoke.
+ EventDelegate internalDelegate = (e) => del((T)e);
+ delegateLookup[del] = internalDelegate;
+
+ EventDelegate tempDel;
+ if (delegates.TryGetValue(typeof(T), out tempDel))
+ {
+ delegates[typeof(T)] = tempDel += internalDelegate;
+ }
+ else
+ {
+ delegates[typeof(T)] = internalDelegate;
+ }
+ }
- ///
- /// Lookups only, there is one delegate lookup per listener
- ///
- private Dictionary delegateLookup = new Dictionary();
+ ///
+ /// Remove the delegate. Can be called multiple times on same delegate.
+ ///
+ public void RemoveListener(EventDelegate del) where T : Event
+ {
+ if (EnableEventVisualization) LogRemoveListener(del);
+
+ EventDelegate internalDelegate;
+ if (delegateLookup.TryGetValue(del, out internalDelegate))
+ {
+ EventDelegate tempDel;
+ if (delegates.TryGetValue(typeof(T), out tempDel))
+ {
+ tempDel -= internalDelegate;
+ if (tempDel == null)
+ {
+ delegates.Remove(typeof(T));
+ }
+ else
+ {
+ delegates[typeof(T)] = tempDel;
+ }
+ }
+
+ delegateLookup.Remove(del);
+ }
+ }
- ///
- /// Add the delegate.
- ///
- public void AddListener(EventDelegate del) where T : Event {
-
- if (delegateLookup.ContainsKey(del)) {
- return;
- }
-
- // Create a new non-generic delegate which calls our generic one. This
- // is the delegate we actually invoke.
- EventDelegate internalDelegate = (e) => del((T)e);
- delegateLookup[del] = internalDelegate;
-
- EventDelegate tempDel;
- if (delegates.TryGetValue(typeof(T), out tempDel)) {
- delegates[typeof(T)] = tempDel += internalDelegate;
- }
- else {
- delegates[typeof(T)] = internalDelegate;
- }
- }
+ ///
+ /// The count of delegate lookups. The delegate lookups will increase by
+ /// one for each unique AddListener. Useful for debugging and not much else.
+ ///
+ public int DelegateLookupCount { get { return delegateLookup.Count; } }
+
+ ///
+ /// Raise the event to all the listeners
+ ///
+ public void Raise(Event e)
+ {
+ if (EnableEventVisualization) LogRaise(e);
+
+ EventDelegate del;
+ if (delegates.TryGetValue(e.GetType(), out del))
+ {
+ del.Invoke(e);
+ }
+ }
- ///
- /// Remove the delegate. Can be called multiple times on same delegate.
- ///
- public void RemoveListener(EventDelegate del) where T : Event {
-
- EventDelegate internalDelegate;
- if (delegateLookup.TryGetValue(del, out internalDelegate)) {
- EventDelegate tempDel;
- if (delegates.TryGetValue(typeof(T), out tempDel)) {
- tempDel -= internalDelegate;
- if (tempDel == null) {
- delegates.Remove(typeof(T));
- }
- else {
- delegates[typeof(T)] = tempDel;
- }
+ private string GetCaller()
+ {
+ var stacktrace = StackTraceUtility.ExtractStackTrace();
+ if (stacktrace.Length != 0)
+ {
+ var stackEntries = stacktrace.Split('\n');
+ foreach (var entry in stackEntries)
+ {
+ if(entry.StartsWith(this.GetType().ToString()))
+ {
+ continue;
+ }
+
+ //First item that is not this class is our external caller
+ return Regex.Match(entry, "([^:]*):").Groups[1].Value;
+ }
+ }
+
+ return "";
}
- delegateLookup.Remove(del);
- }
- }
+ private void LogRaise(Event e)
+ {
+ string eventName = e.GetType().ToString();
+ string sender = GetCaller();
+ if(EnableDebugLog) Debug.Log(sender + " raised " + eventName);
+
+ var newEvents = new List();
+ foreach (var eventCall in Events)
+ {
+ if(eventCall.EventName == eventName)
+ {
+ newEvents.Add(new EventVisualizer.Base.EventCall(sender, eventCall.Receiver, eventCall.EventName, eventCall.Method));
+ }
+ }
+ Events.AddRange(newEvents);
+ Events.RemoveAll(item => ((item.Sender == null) &&
+ (item.EventName == eventName)));
+ }
- ///
- /// The count of delegate lookups. The delegate lookups will increase by
- /// one for each unique AddListener. Useful for debugging and not much else.
- ///
- public int DelegateLookupCount { get { return delegateLookup.Count; }}
+ private void LogAddListener(EventDelegate del) where T : Event
+ {
+ string receiver = GetCaller();
+ string eventName = typeof(T).ToString();
+ string methodName = "";
+#if UNITY_EDITOR
+ methodName = del.Method.Name;
+#endif
+ if (EnableDebugLog) Debug.Log(receiver + " added Listener for " + eventName + ": " + methodName);
+
+ //add this as an EventCall, even though there is no sender so far (this is needed to show empty slots)
+ EventVisualizer.Base.EventCall newCall = new EventVisualizer.Base.EventCall(null, receiver, eventName, methodName);
+ Events.Add(newCall);
+ }
- ///
- /// Raise the event to all the listeners
- ///
- public void Raise(Event e) {
- EventDelegate del;
- if (delegates.TryGetValue(e.GetType(), out del)) {
- del.Invoke(e);
- }
- }
+ private void LogRemoveListener(EventDelegate del) where T : Event
+ {
+ string receiver = GetCaller();
+ string eventName = typeof(T).ToString();
+ string methodName = "";
+#if UNITY_EDITOR
+ methodName = del.Method.Name;
+#endif
+ if (EnableDebugLog) Debug.Log(receiver + " removed Listener for " + eventName + ": " + methodName);
+
+ Events.RemoveAll(item => ( (item.EventName.Equals(eventName)) &&
+ (item.Receiver.Equals(receiver)) &&
+ (item.Method.Equals(methodName))));
+ }
- }
+ }
}
diff --git a/Assets/EventManager/Source/EventManager.cs.meta b/Assets/EventManager/Source/EventManager.cs.meta
index be45d09..d86e346 100644
--- a/Assets/EventManager/Source/EventManager.cs.meta
+++ b/Assets/EventManager/Source/EventManager.cs.meta
@@ -1,8 +1,9 @@
fileFormatVersion: 2
-guid: d462efaa2139342e88d7d1a538cb89bf
-timeCreated: 1455836012
+guid: 9bdb458cfd353ee49a595870a85c4aa2
+timeCreated: 1518809105
licenseType: Free
MonoImporter:
+ externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
diff --git a/Assets/EventManager/Source/IEventHandler.cs.meta b/Assets/EventManager/Source/IEventHandler.cs.meta
index 4ede3c7..a2c5428 100644
--- a/Assets/EventManager/Source/IEventHandler.cs.meta
+++ b/Assets/EventManager/Source/IEventHandler.cs.meta
@@ -1,8 +1,9 @@
fileFormatVersion: 2
-guid: b6ba3497f1dfd4d7bb4df5a099099e4d
-timeCreated: 1455836012
+guid: a1cb9b0b0377133498a831e22f23928e
+timeCreated: 1518809105
licenseType: Free
MonoImporter:
+ externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
diff --git a/Assets/EventManager/Source/UnityEventVisualizer.meta b/Assets/EventManager/Source/UnityEventVisualizer.meta
new file mode 100644
index 0000000..330b3e6
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 37696b25b8158da4d8b73f14885324b7
+folderAsset: yes
+timeCreated: 1518871822
+licenseType: Free
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor.meta b/Assets/EventManager/Source/UnityEventVisualizer/Editor.meta
new file mode 100644
index 0000000..d233712
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 673c745b2caa2404db48f4bde78840d8
+folderAsset: yes
+timeCreated: 1499875042
+licenseType: Free
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/EdgeGUI.cs b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EdgeGUI.cs
new file mode 100644
index 0000000..26787c6
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EdgeGUI.cs
@@ -0,0 +1,211 @@
+//
+// Klak - Utilities for creative coding with Unity
+//
+// Copyright (C) 2016 Keijiro Takahashi
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+using UnityEngine;
+using UnityEditor;
+using System.Collections.Generic;
+using System;
+using System.Reflection;
+using Graphs = UnityEditor.Graphs;
+using UnityEditor.Graphs;
+
+namespace EventVisualizer.Base
+{
+ // Specialized edge drawer class
+ public class EdgeGUI : Graphs.IEdgeGUI
+ {
+ #region Public members
+
+ public Graphs.GraphGUI host { get; set; }
+ public List edgeSelection { get; set; }
+
+ public EdgeGUI()
+ {
+ edgeSelection = new List();
+ }
+
+ #endregion
+
+ #region IEdgeGUI implementation
+
+
+ public void DoEdges()
+ {
+ // Draw edges on repaint.
+ if (Event.current.type == EventType.Repaint)
+ {
+ foreach (var edge in host.graph.edges)
+ {
+ if (edge == null) continue;
+
+ float hue = HueOutputSlot(edge.fromSlot);
+ DrawEdge(edge, Color.HSVToRGB(hue, 1f, 1f));
+ }
+ }
+ }
+
+
+ private float HueOutputSlot(Slot slot)
+ {
+ int count = 0;
+ int index = 0;
+ foreach (var s in slot.node.outputSlots)
+ {
+ if (s == slot)
+ {
+ index = count;
+ }
+ count++;
+ }
+
+ return Mathf.Repeat((index % 2 == 0 ? (float)index : index + (count + 1f) * 0.5f) / count, 1f);
+
+ }
+
+ public void DoDraggedEdge()
+ {
+
+ }
+
+ public void BeginSlotDragging(Graphs.Slot slot, bool allowStartDrag, bool allowEndDrag)
+ {
+
+ }
+
+ public void SlotDragging(Graphs.Slot slot, bool allowEndDrag, bool allowMultiple)
+ {
+
+ }
+
+ public void EndSlotDragging(Graphs.Slot slot, bool allowMultiple)
+ {
+
+ }
+
+
+ public void EndDragging()
+ {
+
+ }
+
+ public Graphs.Edge FindClosestEdge()
+ {
+ return null;
+ }
+
+
+ #endregion
+
+ #region Private members
+
+ Graphs.Slot _dragSourceSlot;
+ Graphs.Slot _dropTarget;
+
+ #endregion
+
+ #region Edge drawer
+
+ const float kEdgeWidth = 4;
+ const float kEdgeSlotYOffset = 9;
+
+ static void DrawEdge(Graphs.Edge edge, Color color)
+ {
+ var p1 = GetPositionAsFromSlot(edge.fromSlot);
+ var p2 = GetPositionAsToSlot(edge.toSlot);
+ DrawEdge(p1, p2, color * edge.color, EdgeTriggersTracker.GetTimings(edge));
+ }
+
+ static void DrawEdge(Vector2 p1, Vector2 p2, Color color, List triggers)
+ {
+ Color prevColor = Handles.color;
+ Handles.color = color;
+
+ var l = Mathf.Min(Mathf.Abs(p1.y - p2.y), 50);
+ Vector2 p3 = p1 + new Vector2(l, 0);
+ Vector2 p4 = p2 - new Vector2(l, 0);
+ var texture = (Texture2D)Graphs.Styles.connectionTexture.image;
+ Handles.DrawBezier(p1, p2, p3, p4, color, texture, kEdgeWidth);
+
+
+ foreach (var trigger in triggers)
+ {
+ Vector3 pos = CalculateBezierPoint(trigger, p1, p3, p4, p2);
+ Handles.DrawSolidArc(pos, Vector3.back, pos + Vector3.up, 360, kEdgeWidth *2);
+
+ }
+
+ Handles.color = prevColor;
+ }
+
+ #endregion
+
+ #region Utilities to access private members
+
+ // Accessors for Slot.m_Position
+ static Rect GetSlotPosition(Graphs.Slot slot)
+ {
+ var flags = BindingFlags.NonPublic | BindingFlags.Instance;
+ var func = typeof(Graphs.Slot).GetField("m_Position", flags);
+ return (Rect)func.GetValue(slot);
+ }
+
+ static Vector2 GetPositionAsFromSlot(Graphs.Slot slot)
+ {
+ var rect = GetSlotPosition(slot);
+ return GUIClip(new Vector2(rect.xMax, rect.y + kEdgeSlotYOffset));
+ }
+
+ static Vector2 GetPositionAsToSlot(Graphs.Slot slot)
+ {
+ var rect = GetSlotPosition(slot);
+ return GUIClip(new Vector2(rect.x, rect.y + kEdgeSlotYOffset));
+ }
+
+ // Caller for GUIClip.Clip
+ static Vector2 GUIClip(Vector2 pos)
+ {
+ var type = Type.GetType("UnityEngine.GUIClip,UnityEngine");
+ var method = type.GetMethod("Clip", new Type[] { typeof(Vector2) });
+ return (Vector2)method.Invoke(null, new object[] { pos });
+ }
+
+ #endregion
+
+ private static Vector3 CalculateBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
+ {
+ float u = 1.0f - t;
+ float tt = t * t;
+ float uu = u * u;
+ float uuu = uu * u;
+ float ttt = tt * t;
+
+ Vector3 p = uuu * p0;
+ p += 3 * uu * t * p1;
+ p += 3 * u * tt * p2;
+ p += ttt * p3;
+
+ return p;
+ }
+ }
+
+}
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/EdgeGUI.cs.meta b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EdgeGUI.cs.meta
new file mode 100644
index 0000000..6de8124
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EdgeGUI.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 2985f4fac86ecd34eb637f29891d75d2
+timeCreated: 1500022382
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/EdgeTriggersTracker.cs b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EdgeTriggersTracker.cs
new file mode 100644
index 0000000..e63f133
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EdgeTriggersTracker.cs
@@ -0,0 +1,57 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor.Graphs;
+using UnityEngine;
+using UnityEngine.Events;
+
+namespace EventVisualizer.Base
+{
+ public static class EdgeTriggersTracker
+ {
+ public class EdgeTrigger
+ {
+ public Edge edge;
+ public float triggeredTime;
+ }
+
+ private readonly static float TimeToLive = 1f;
+ private static List triggers = new List();
+
+ public static void RegisterTrigger(Edge edge)
+ {
+ triggers.Add(new EdgeTrigger() { edge = edge, triggeredTime = Time.unscaledTime });
+ }
+
+ public static List GetTimings(Edge edge)
+ {
+ float now = Time.unscaledTime;
+ List acceptedTriggers = triggers.FindAll(t => t.edge == edge);
+
+ List timings = new List();//TODO cache
+ foreach (EdgeTrigger t in acceptedTriggers)
+ {
+ float time = Mathf.Abs(t.triggeredTime - now) / TimeToLive;
+ if (time <= 1f)
+ {
+ timings.Add(time);
+ }
+ else
+ {
+ triggers.Remove(t);
+ }
+ }
+ return timings;
+ }
+
+ public static void CleanObsolete()
+ {
+ float now = Time.unscaledTime;
+ triggers.RemoveAll(trigger => Mathf.Abs(now - trigger.triggeredTime) > TimeToLive);
+ }
+
+ public static bool HasData()
+ {
+ return triggers.Count > 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/EdgeTriggersTracker.cs.meta b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EdgeTriggersTracker.cs.meta
new file mode 100644
index 0000000..915d778
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EdgeTriggersTracker.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 2f19a182d61c68542a747db2ee20d0d5
+timeCreated: 1512134666
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/EditorZoomArea.cs b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EditorZoomArea.cs
new file mode 100644
index 0000000..284c079
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EditorZoomArea.cs
@@ -0,0 +1,33 @@
+using UnityEngine;
+
+namespace EventVisualizer.Base
+{
+ public class EditorZoomArea
+ {
+ private const float kEditorWindowTabHeight = 21.0f;
+ private static Matrix4x4 _prevGuiMatrix;
+
+ public static Rect Begin(float zoomScale, Rect screenCoordsArea)
+ {
+ GUI.EndGroup(); // End the group Unity begins automatically for an EditorWindow to clip out the window tab. This allows us to draw outside of the size of the EditorWindow.
+
+ Rect clippedArea = screenCoordsArea.ScaleSizeBy(1.0f / zoomScale, screenCoordsArea.TopLeft());
+ clippedArea.y += kEditorWindowTabHeight;
+ GUI.BeginGroup(clippedArea);
+
+ _prevGuiMatrix = GUI.matrix;
+ Matrix4x4 translation = Matrix4x4.TRS(clippedArea.TopLeft(), Quaternion.identity, Vector3.one);
+ Matrix4x4 scale = Matrix4x4.Scale(new Vector3(zoomScale, zoomScale, 1.0f));
+ GUI.matrix = translation * scale * translation.inverse * GUI.matrix;
+
+ return clippedArea;
+ }
+
+ public static void End()
+ {
+ GUI.matrix = _prevGuiMatrix;
+ GUI.EndGroup();
+ GUI.BeginGroup(new Rect(0.0f, kEditorWindowTabHeight, Screen.width, Screen.height));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/EditorZoomArea.cs.meta b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EditorZoomArea.cs.meta
new file mode 100644
index 0000000..d4d54b7
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EditorZoomArea.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: df84caadb31f9df48b22ab5d59ac9d5f
+timeCreated: 1504788847
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraph.cs b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraph.cs
new file mode 100644
index 0000000..4cb147d
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraph.cs
@@ -0,0 +1,101 @@
+using UnityEngine;
+using EventVisualizer.Base;
+using System.Collections.Generic;
+using UnityEditor.Graphs;
+using System.Linq;
+
+namespace EventVisualizer.Base
+{
+ [System.Serializable]
+ public class EventsGraph : Graph
+ {
+ static public EventsGraph Create()
+ {
+ var graph = CreateInstance();
+ graph.hideFlags = HideFlags.HideAndDontSave;
+ return graph;
+ }
+
+ public EventsGraphGUI GetEditor()
+ {
+ var gui = CreateInstance();
+ gui.graph = this;
+ gui.hideFlags = HideFlags.HideAndDontSave;
+ return gui;
+
+ }
+
+ public void BuildGraph()
+ {
+ NodeData.Clear();
+ Clear(true);
+ foreach (EventCall call in EventsFinder.FindAllEvents())
+ {
+ NodeData.RegisterEvent(call);
+ }
+ foreach (NodeData data in NodeData.Nodes)
+ {
+ AddNode(NodeGUI.Create(data));
+ }
+
+ foreach (NodeGUI node in nodes)
+ {
+ node.PopulateEdges();
+ }
+
+ SortGraph();
+ }
+
+#region sorting
+
+ [SerializeField]
+ private HashSet positionedNodes = new HashSet();
+ private const float VERTICAL_SPACING = 80f;
+ private const float HORIZONTAL_SPACING = 400f;
+ private void SortGraph()
+ {
+ positionedNodes.Clear();
+
+ List sortedNodes = new List(nodes); //cannot sort the original collection so a clone is needed
+ sortedNodes.Sort((x, y) =>
+ {
+ int xScore = x.outputEdges.Count() - x.inputEdges.Count();
+ int yScore = y.outputEdges.Count() - y.inputEdges.Count();
+ return yScore.CompareTo(xScore);
+ });
+
+ Vector2 position = Vector2.zero;
+ foreach (Node node in sortedNodes)
+ {
+ if (!positionedNodes.Contains(node))
+ {
+ positionedNodes.Add(node);
+ position.y += PositionNodeHierarchy(node, position);
+ }
+ }
+ }
+
+
+ private float PositionNodeHierarchy(Node currentNode, Vector2 masterPosition)
+ {
+ float height = VERTICAL_SPACING;
+ foreach (var outputEdge in currentNode.outputEdges)
+ {
+ Node node = outputEdge.toSlot.node;
+ if (!positionedNodes.Contains(node))
+ {
+ positionedNodes.Add(node);
+ height += PositionNodeHierarchy(node, masterPosition
+ + Vector2.right * HORIZONTAL_SPACING
+ + Vector2.up * height);
+ }
+ }
+ currentNode.position = new Rect(masterPosition + Vector2.up * height * 0.5f, currentNode.position.size);
+
+ return height;
+ }
+
+#endregion
+
+ }
+}
\ No newline at end of file
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraph.cs.meta b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraph.cs.meta
new file mode 100644
index 0000000..3233162
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraph.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b8f9efaa5424bdf4ebdd9d4af48ca877
+timeCreated: 1499875263
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraphGUI.cs b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraphGUI.cs
new file mode 100644
index 0000000..e7f58a0
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraphGUI.cs
@@ -0,0 +1,124 @@
+using UnityEngine;
+using UnityEditor;
+using EventVisualizer.Base;
+using System.Collections.Generic;
+using UnityEditor.Graphs;
+
+namespace EventVisualizer.Base
+{
+ [System.Serializable]
+ public class EventsGraphGUI : GraphGUI
+ {
+ [SerializeField]
+ public int SelectionOverride;
+
+ public override void OnGraphGUI()
+ {
+ // Show node subwindows.
+ m_Host.BeginWindows();
+
+ foreach (var node in graph.nodes)
+ {
+ // Recapture the variable for the delegate.
+ var node2 = node;
+
+ // Subwindow style (active/nonactive)
+ var isActive = selection.Contains(node);
+ var style = Styles.GetNodeStyle(node.style, node.color, isActive);
+
+ node.position = GUILayout.Window(
+ node.GetInstanceID(),
+ node.position,
+ delegate { NodeGUI(node2); },
+ node.title,
+ style,
+ GUILayout.Width(150)
+ );
+ }
+
+ if (graph.nodes.Count == 0)
+ {
+ GUILayout.Window(0, new Rect(0, 0, 1, 1), delegate {}, "", "MiniLabel");
+ }
+
+ m_Host.EndWindows();
+
+ // Graph edges
+ edgeGUI.DoEdges();
+
+ // Mouse drag
+ DragSelection();
+
+ }
+
+ public override IEdgeGUI edgeGUI
+ {
+ get
+ {
+ if (m_EdgeGUI == null)
+ m_EdgeGUI = new EdgeGUI { host = this };
+ return m_EdgeGUI;
+ }
+ }
+
+
+
+
+ public override void NodeGUI(Node node)
+ {
+ SelectNode(node);
+
+ foreach (var slot in node.inputSlots)
+ LayoutSlot(slot, slot.title, false, true, true, Styles.triggerPinIn);
+
+ node.NodeUI(this);
+
+ foreach (var slot in node.outputSlots)
+ {
+ EditorGUILayout.BeginHorizontal();
+ GUILayout.FlexibleSpace();
+ LayoutSlot(slot, slot.title, true, false, true, Styles.triggerPinOut);
+ EditorGUILayout.EndHorizontal();
+ }
+
+ DragNodes();
+
+ UpdateSelection();
+ }
+
+ private void UpdateSelection()
+ {
+ OverrideSelection();
+ if (selection.Count > 0)
+ {
+ int[] selectedIds = new int[selection.Count];
+ for (int i = 0; i < selection.Count; i++)
+ {
+ //TODO: .name contains the name of the Class (e.g. "Receiver2" as string, not parsable...) What ID did .name contain before? Added try/catch for now
+ selectedIds[i] = selection[i].GetInstanceID();
+ }
+ Selection.instanceIDs = selectedIds;
+ }
+ }
+
+ private void OverrideSelection()
+ {
+ if (SelectionOverride != 0)
+ {
+ Node selectedNode = graph[SelectionOverride.ToString()];
+ if (selectedNode != null)
+ {
+ selection.Clear();
+ selection.Add(selectedNode);
+ CenterGraph(selectedNode.position.position);
+
+ }
+ SelectionOverride = 0;
+ }
+ }
+
+
+
+
+ }
+}
\ No newline at end of file
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraphGUI.cs.meta b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraphGUI.cs.meta
new file mode 100644
index 0000000..3431142
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraphGUI.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 41d6ec2bce82c7c449da384062936274
+timeCreated: 1499875263
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraphWindow.cs b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraphWindow.cs
new file mode 100644
index 0000000..3a4b35e
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraphWindow.cs
@@ -0,0 +1,83 @@
+using UnityEditor;
+using UnityEngine;
+
+namespace EventVisualizer.Base
+{
+ public class EventsGraphWindow : EditorWindow
+ {
+ [SerializeField]
+ private EventsGraph _graph;
+ [SerializeField]
+ private EventsGraphGUI _graphGUI;
+
+ private const float kBarHeight = 17;
+
+ [MenuItem("Window/Events Graph editor")]
+ static void ShowEditor()
+ {
+ EventsGraphWindow editor = EditorWindow.GetWindow();
+ editor.hideFlags = HideFlags.HideAndDontSave;
+ editor.Initialize();
+ }
+
+ public void Initialize()
+ {
+ _graph = EventsGraph.Create();
+ _graph.BuildGraph();
+
+ _graphGUI = _graph.GetEditor();
+ _graphGUI.CenterGraph();
+
+ EditorUtility.SetDirty(_graphGUI);
+ EditorUtility.SetDirty(_graph);
+ }
+
+ void OnGUI()
+ {
+ var width = position.width;
+ var height = position.height;
+
+ if(_graphGUI != null)
+ {
+ // Main graph area
+ _graphGUI.BeginGraphGUI(this, new Rect(0, 0, width, height - kBarHeight));
+ _graphGUI.OnGraphGUI();
+ _graphGUI.EndGraphGUI();
+
+ // Clear selection on background click
+ var e = Event.current;
+ if (e.type == EventType.MouseDown && e.clickCount == 1)
+ _graphGUI.ClearSelection();
+ }
+
+
+ // Status bar
+ GUILayout.BeginArea(new Rect(0, height - kBarHeight, width, kBarHeight));
+ if (GUILayout.Button("Refresh"))
+ {
+ Refresh();
+ }
+ GUILayout.EndArea();
+ }
+
+ private void Update()
+ {
+ if (EdgeTriggersTracker.HasData())
+ {
+ Repaint();
+ }
+ }
+
+ public void OverrideSelection(int overrideIndex)
+ {
+ _graphGUI.SelectionOverride = overrideIndex;
+ }
+
+
+ void Refresh()
+ {
+ _graph.Clear();
+ _graph.BuildGraph();
+ }
+ }
+}
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraphWindow.cs.meta b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraphWindow.cs.meta
new file mode 100644
index 0000000..d80a409
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsGraphWindow.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 190ddcd99b7cc1b48af8d612a8aea744
+timeCreated: 1499938262
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsVisualizer.cs b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsVisualizer.cs
new file mode 100644
index 0000000..431ebe6
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsVisualizer.cs
@@ -0,0 +1,13 @@
+using System.Collections.Generic;
+
+namespace EventVisualizer.Base
+{
+
+ public static class EventsFinder
+ {
+ public static List FindAllEvents()
+ {
+ return SDD.Events.EventManager.Instance.Events;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsVisualizer.cs.meta b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsVisualizer.cs.meta
new file mode 100644
index 0000000..84bb3b7
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/EventsVisualizer.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 48826a5b6d060a148b50a6670ba6d2a4
+timeCreated: 1499869669
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/FindInGraphButton.cs b/Assets/EventManager/Source/UnityEventVisualizer/Editor/FindInGraphButton.cs
new file mode 100644
index 0000000..cd7f8e0
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/FindInGraphButton.cs
@@ -0,0 +1,20 @@
+using UnityEditor;
+using UnityEngine;
+
+namespace EventVisualizer.Base
+{
+ public static class FindInGraphButton
+ {
+ [MenuItem("GameObject/EventGraph/Find this", false, 0)]
+ static void FindEvents()
+ {
+ EventsGraphWindow window = EditorWindow.GetWindow();
+ if(window != null)
+ {
+ window.OverrideSelection(Selection.activeInstanceID);
+ }
+ }
+
+ }
+
+}
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/FindInGraphButton.cs.meta b/Assets/EventManager/Source/UnityEventVisualizer/Editor/FindInGraphButton.cs.meta
new file mode 100644
index 0000000..7b63604
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/FindInGraphButton.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 2dfbd442ff101084f9021be4d99f48b3
+timeCreated: 1500029743
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/NodeGUI.cs b/Assets/EventManager/Source/UnityEventVisualizer/Editor/NodeGUI.cs
new file mode 100644
index 0000000..6042a85
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/NodeGUI.cs
@@ -0,0 +1,123 @@
+using UnityEngine;
+using UnityEngine.Events;
+using UnityEditor;
+using System;
+using System.Reflection;
+using Graphs = UnityEditor.Graphs;
+using System.Linq;
+using UnityEditor.Graphs;
+using System.Collections.Generic;
+
+namespace EventVisualizer.Base
+{
+ public class NodeGUI : Graphs.Node
+ {
+ #region Public class methods
+
+ // Factory method
+ static public NodeGUI Create(NodeData dataInstance)
+ {
+ var node = CreateInstance();
+ node.Initialize(dataInstance);
+ node.name = dataInstance.Entity;
+ return node;
+ }
+
+ #endregion
+
+ #region Public member properties and methods
+
+ // Runtime instance access
+ public NodeData runtimeInstance
+ {
+ get { return _runtimeInstance; }
+ }
+
+ // Validity check
+ public bool isValid
+ {
+ get { return _runtimeInstance != null; }
+ }
+
+ #endregion
+
+ #region Overridden virtual methods
+
+ // Node display title
+ public override string title
+ {
+ get { return isValid ? _runtimeInstance.Name : ""; }
+ }
+
+ // Dirty callback
+ public override void Dirty()
+ {
+ base.Dirty();
+ }
+
+ #endregion
+
+ #region Private members
+
+ // Runtime instance of this node
+ NodeData _runtimeInstance;
+
+ // Initializer (called from the Create method)
+ void Initialize(NodeData runtimeInstance)
+ {
+ hideFlags = HideFlags.DontSave;
+
+ // Object references
+ _runtimeInstance = runtimeInstance;
+ position = new Rect(Vector2.one * UnityEngine.Random.Range(0, 500), Vector2.zero);
+
+ PopulateSlots();
+ }
+
+ void PopulateSlots()
+ {
+ foreach (EventCall call in _runtimeInstance.Outputs)
+ {
+ string name = call.EventName;
+ string title = ObjectNames.NicifyVariableName(name);
+ if (!outputSlots.Any(s => s.title == title))
+ {
+ var slot = AddOutputSlot(name);
+ slot.title = title;
+ }
+ }
+
+ foreach (EventCall call in _runtimeInstance.Inputs)
+ {
+ string name = call.MethodFullPath;
+ string title = ObjectNames.NicifyVariableName(name);
+ if (!inputSlots.Any(s => s.title == title))
+ {
+ var slot = AddInputSlot(name);
+ slot.title = title;
+ }
+ }
+ }
+
+ public void PopulateEdges()
+ {
+ foreach (var outSlot in outputSlots)
+ {
+ List outCalls = _runtimeInstance.Outputs.FindAll(call => call.EventName == outSlot.name);
+
+ foreach (EventCall call in outCalls)
+ {
+ var targetNode = graph[call.Receiver];
+ var inSlot = targetNode[call.MethodFullPath];
+
+ if (!graph.Connected(outSlot, inSlot))
+ {
+ graph.Connect(outSlot, inSlot);
+ }
+ }
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/NodeGUI.cs.meta b/Assets/EventManager/Source/UnityEventVisualizer/Editor/NodeGUI.cs.meta
new file mode 100644
index 0000000..8793b27
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/NodeGUI.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 24ae9b60aa42dfc4ba3dca7eb88a614d
+timeCreated: 1499939700
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/RectExtensions.cs b/Assets/EventManager/Source/UnityEventVisualizer/Editor/RectExtensions.cs
new file mode 100644
index 0000000..82a3dd9
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/RectExtensions.cs
@@ -0,0 +1,47 @@
+using UnityEngine;
+
+namespace EventVisualizer.Base
+{
+
+ public static class RectExtensions
+ {
+ public static Vector2 TopLeft(this Rect rect)
+ {
+ return new Vector2(rect.xMin, rect.yMin);
+ }
+ public static Rect ScaleSizeBy(this Rect rect, float scale)
+ {
+ return rect.ScaleSizeBy(scale, rect.center);
+ }
+ public static Rect ScaleSizeBy(this Rect rect, float scale, Vector2 pivotPoint)
+ {
+ Rect result = rect;
+ result.x -= pivotPoint.x;
+ result.y -= pivotPoint.y;
+ result.xMin *= scale;
+ result.xMax *= scale;
+ result.yMin *= scale;
+ result.yMax *= scale;
+ result.x += pivotPoint.x;
+ result.y += pivotPoint.y;
+ return result;
+ }
+ public static Rect ScaleSizeBy(this Rect rect, Vector2 scale)
+ {
+ return rect.ScaleSizeBy(scale, rect.center);
+ }
+ public static Rect ScaleSizeBy(this Rect rect, Vector2 scale, Vector2 pivotPoint)
+ {
+ Rect result = rect;
+ result.x -= pivotPoint.x;
+ result.y -= pivotPoint.y;
+ result.xMin *= scale.x;
+ result.xMax *= scale.x;
+ result.yMin *= scale.y;
+ result.yMax *= scale.y;
+ result.x += pivotPoint.x;
+ result.y += pivotPoint.y;
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/Editor/RectExtensions.cs.meta b/Assets/EventManager/Source/UnityEventVisualizer/Editor/RectExtensions.cs.meta
new file mode 100644
index 0000000..c59eca2
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/Editor/RectExtensions.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: d731028bb06536145af5d62304d3edcf
+timeCreated: 1504789257
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/EventCall.cs b/Assets/EventManager/Source/UnityEventVisualizer/EventCall.cs
new file mode 100644
index 0000000..dd83765
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/EventCall.cs
@@ -0,0 +1,29 @@
+
+namespace EventVisualizer.Base
+{
+ [System.Serializable]
+ public class EventCall
+ {
+ public string Sender { get; set; }
+ public string Receiver { get; private set; }
+ public string EventName { get; private set; }
+ public string Method { get; private set; }
+ public string ReceiverComponentName { get; private set; }
+
+ public string MethodFullPath
+ {
+ get
+ {
+ return ReceiverComponentName + Method;
+ }
+ }
+
+ public EventCall(string sender, string receiver, string eventName, string methodName)
+ {
+ Sender = sender;
+ Receiver = receiver;
+ EventName = eventName;
+ Method = methodName;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/EventCall.cs.meta b/Assets/EventManager/Source/UnityEventVisualizer/EventCall.cs.meta
new file mode 100644
index 0000000..1daca82
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/EventCall.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 146bf08e47e9cb646bc3fdb8a2bc2c6c
+timeCreated: 1499941586
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/NodeData.cs b/Assets/EventManager/Source/UnityEventVisualizer/NodeData.cs
new file mode 100644
index 0000000..2bd7ac0
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/NodeData.cs
@@ -0,0 +1,74 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace EventVisualizer.Base
+{
+ [System.Serializable]
+ public class NodeData
+ {
+ public string Entity { get; private set; }
+
+ public string Name
+ {
+ get
+ {
+ return Entity != null ? Entity : "";
+ }
+ }
+
+ public List Outputs { get; private set; }
+ public List Inputs { get; private set; }
+
+ [SerializeField]
+ private static Dictionary nodes = new Dictionary();
+
+ public static ICollection Nodes
+ {
+ get
+ {
+ return nodes != null ? nodes.Values : null;
+ }
+ }
+
+
+
+ public static void Clear()
+ {
+ nodes.Clear();
+ }
+
+ public static void RegisterEvent(EventCall eventCall)
+ {
+ CreateNode(eventCall.Receiver);
+ nodes[eventCall.Receiver].Inputs.Add(eventCall);
+
+ if (eventCall.Sender != null)
+ {
+ CreateNode(eventCall.Sender);
+ nodes[eventCall.Sender].Outputs.Add(eventCall);
+ }
+ }
+
+ private static void CreateNode(string entity)
+ {
+ if(entity == null)
+ {
+ return;
+ }
+
+ if(!nodes.ContainsKey(entity))
+ {
+ nodes.Add(entity, new NodeData(entity));
+ }
+
+ }
+
+ public NodeData(string entity)
+ {
+ Entity = entity;
+ Outputs = new List();
+ Inputs = new List();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Assets/EventManager/Source/UnityEventVisualizer/NodeData.cs.meta b/Assets/EventManager/Source/UnityEventVisualizer/NodeData.cs.meta
new file mode 100644
index 0000000..6d558bb
--- /dev/null
+++ b/Assets/EventManager/Source/UnityEventVisualizer/NodeData.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 70667cf59022c0a42a20bae166613703
+timeCreated: 1499875742
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/README.md b/README.md
index d722a68..57faae3 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,9 @@ Unity's own EventSystem may be more appropriate for that use case.
* Type-safe
* Avoids breaking changes when new event parameters are added
+EventManager includes a graphical EventVisualizer that shows how your classes are connected during runtime
+![EventVisualizer](https://user-images.githubusercontent.com/4217216/36345399-bbc9cf42-1429-11e8-8c3c-2bdc6362ead8.png)
+
Installation
------------
@@ -66,6 +69,28 @@ HomeBrew ```brew install mono```
cp build/SDD.EventManager.dll ~/your_unity_project/Assets/Lib/
+### Option 3: Installation via NPM
+
+To install via NPM the following is needed:
+* Install the [Node.js package manager](https://nodejs.org/en/download/)
+* In your Unity-project run `npm install --save unity3d.eventmanager`
+* Extend your `.gitignore` (or whatever else you're using)
+ * Add `node_modules`
+ * Add `package-lock.json`
+ * Add `Assets/packages/`
+ * Add `Assets/packages.meta`
+
+You can also add a `package.json` to your Unity project that contains the following content:
+```
+{
+ "dependencies": {
+ "unity3d.eventmanager": "1.1.0"
+ }
+}
+```
+This way you can define what dependencies you need in a reproducible way.
+
+
Testing
-------
diff --git a/npm/postinstall.js b/npm/postinstall.js
new file mode 100644
index 0000000..5dd3faf
--- /dev/null
+++ b/npm/postinstall.js
@@ -0,0 +1,23 @@
+var mkdirp = require('mkdirp');
+var path = require('path');
+var ncp = require('ncp');
+
+// Paths
+var srcDir = path.join(__dirname, '..', 'Assets', 'EventManager', 'Source');
+var targetDir = path.join(__dirname, '..', '..', '..', 'Assets', 'packages', 'EventManager');
+
+// Create folder if missing
+mkdirp(targetDir, function (err) {
+ if (err) {
+ console.error(err)
+ process.exit(1);
+ }
+
+ // Copy files
+ ncp(srcDir, targetDir, function (err) {
+ if (err) {
+ console.error(err);
+ process.exit(1);
+ }
+ });
+});
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..8a960c4
--- /dev/null
+++ b/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "unity3d.eventmanager",
+ "version": "1.1.1",
+ "description": "A type-safe event system for Unity3D based on the event listener pattern. More info http://saltydog.digital/usage-pattern-for-a-type-safe-unity-event-system/",
+ "main": "npm/index.js",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/UbimaxFrontline/EventManager.git"
+ },
+ "keywords": [
+ "unity3d",
+ "eventsystem",
+ "events"
+ ],
+ "author": "Robert Wahler, Nils Brinkmann",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/UbimaxFrontline/EventManager/issues"
+ },
+ "homepage": "https://github.com/UbimaxFrontline/EventManager#readme",
+
+ "files": [
+ "npm/postinstall.js",
+ "Assets/EventManager/Source/Event.cs",
+ "Assets/EventManager/Source/EventManager.cs",
+ "Assets/EventManager/Source/IEventHandler.cs",
+ "Assets/EventManager/Source/UnityEventVisualizer"
+ ],
+ "scripts": {
+ "postinstall": "node npm/postinstall.js"
+ },
+ "dependencies": {
+ "ncp": "^2.0.0",
+ "mkdirp": "^0.5.1"
+ }
+}