-
-
Save MattRix/bfeb6f23b5cd6edfe93cee66f163993f to your computer and use it in GitHub Desktop.
Example of using EditorZoomer.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.IO; | |
using System.Collections; | |
using UnityEngine; | |
using UnityEditor; | |
using UnityEditor.Callbacks; | |
using System.Collections.Generic; | |
using System; | |
using NS = System.NonSerializedAttribute; | |
using System.Linq; | |
public class VizWindow : EditorWindow | |
{ | |
[NS] bool hasInited = false; | |
List<VizNode> nodes = new List<VizNode>(); | |
Vector2 scrollPos = Vector2.zero; | |
public Demand selectedDemand = null; | |
[NS] float ratioY = 1f; | |
[NS] float wireLength = 125; | |
EditorZoomer zoomer = new EditorZoomer(); | |
public void Update() | |
{ | |
if (!hasInited) Init(); | |
if (!Application.isPlaying) hasInited = false; | |
DoMovement(); | |
this.Repaint(); //always redraw | |
} | |
private void DoMovement() | |
{ | |
if (nodes.Count == 0) return; | |
ratioY = Mathf.Clamp(ratioY, 0.5f, 3f); | |
wireLength = Mathf.Clamp(wireLength, 50f, 1000f); | |
Vector2 midPoint = Vector2.zero; | |
foreach (var nodeA in nodes) | |
{ | |
midPoint += nodeA.pos; | |
foreach (var nodeB in nodes) | |
{ | |
if (nodeA != nodeB) | |
{ | |
bool isConnected = nodeA.connectedNodes.Contains(nodeB) || nodeB.connectedNodes.Contains(nodeA); | |
var delta = nodeA.pos - nodeB.pos; | |
delta.y /= ratioY; | |
delta.x *= ratioY; | |
float dist = delta.magnitude + 0.1f; //add 0.1 to prevent divide by zero | |
float force = 100000f / delta.sqrMagnitude * 100f; | |
if (isConnected) | |
{ | |
float distFromWire = (delta.magnitude - wireLength) / wireLength; | |
force = -1000f * distFromWire; | |
} | |
force = Mathf.Clamp(force, -1000f, 1000f); | |
var dir = delta.normalized; | |
//dir.y *= 0.5f; | |
nodeA.velocity += 0.01f * force * new Vector2(dir.x, dir.y); | |
} | |
} | |
nodeA.pos += nodeA.velocity; | |
nodeA.velocity *= 0.8f; | |
} | |
//move nodes back to the midpoint being at 0,0,0; | |
midPoint = midPoint / nodes.Count; | |
midPoint += zoomer.GetContentOffset(); | |
foreach (var nodeA in nodes) | |
{ | |
nodeA.pos -= midPoint; | |
} | |
} | |
public void Init() | |
{ | |
hasInited = true; | |
nodes.Clear(); | |
if (!Application.isPlaying) return; | |
} | |
public void OnGUI() | |
{ | |
if (!hasInited || !Application.isPlaying) | |
{ | |
GUILayout.Label("Only works while game is running..."); | |
return; | |
} | |
float leftPanelWidth = 100f; | |
EditorGUILayout.BeginHorizontal(); | |
//GUI.backgroundColor = Color.blue; | |
EditorGUILayout.BeginVertical(GUILayout.Width(leftPanelWidth)); | |
GUILayout.Label("Demands:"); | |
var demands = SimCore.instance.graph.spots.SelectMany(s=>s.demands).ToList(); | |
foreach(var demand in demands) | |
{ | |
if(GUILayout.Button(new GUIContent(demand.spot.name + ": " + demand.name))) | |
{ | |
SelectDemand(demand); | |
} | |
} | |
EditorGUILayout.EndVertical(); | |
//GUI.backgroundColor = Color.white; | |
//get the size of the rect | |
zoomer.Begin(); | |
BeginWindows(); | |
for(int n = 0; n<nodes.Count; n++) | |
{ | |
nodes[n].Draw(n); | |
} | |
//draw wires | |
foreach (var nodeA in nodes) | |
{ | |
foreach (var nodeB in nodeA.connectedNodes) | |
{ | |
Handles.DrawLine(nodeA.pos, nodeB.pos); | |
//draw the arrow | |
var size = 5; | |
var center = (nodeA.pos + nodeB.pos)/ 2f; | |
var forward = (nodeB.pos - nodeA.pos).normalized; | |
var ortho = new Vector2(-forward.y, forward.x); | |
Handles.DrawLine(center + forward*size, center - forward*size + ortho*size); | |
Handles.DrawLine(center + forward*size, center - forward*size - ortho*size); | |
Handles.DrawLine(center - forward*size + ortho*size, center - forward*size - ortho*size); | |
} | |
} | |
EndWindows(); | |
zoomer.End(); | |
//EditorGUILayout.EndScrollView(); | |
EditorGUILayout.EndHorizontal(); | |
} | |
private void SelectDemand(Demand demand) | |
{ | |
selectedDemand = demand; | |
nodes.Clear(); | |
VisualizeActs(); | |
} | |
private void VisualizeActs() | |
{ | |
SimCore.instance.agentManager.Update(); | |
var demandsToAdd = new List<Demand>(); | |
demandsToAdd.Add(selectedDemand); | |
while (demandsToAdd.Count > 0) | |
{ | |
var demand = demandsToAdd.Pop(); | |
for (int a = 0; a < demand.acts.Count; a++) | |
{ | |
var act = demand.acts[a]; | |
var node = new VizNode(demand.name, act.GetDesc()); | |
nodes.Add(node); | |
node.updater = (n) => | |
{ | |
GUI.backgroundColor = act.hasStarted ? (act.isComplete ? new Color(0.0f, 0.8f, 0f) : new Color(1f, 1f, 0f)) : new Color(0.8f, 0f, 0f); | |
n.title = act.hasStarted ? (act.isComplete ? "COMPLETE" : "IN PROGRESS") : "UNSTARTED"; | |
n.message = act.GetDesc(); | |
}; | |
node.source = act; | |
if (a == demand.acts.Count - 1) | |
{ | |
if (demand.parentDemand != null) | |
{ | |
//last act of previous demand | |
node.sourceParent = demand.parentDemand.acts[0]; | |
} | |
} | |
else | |
{ | |
//previous act | |
node.sourceParent = demand.acts[a + 1]; | |
} | |
} | |
foreach (var childDemand in demand.childDemands) | |
{ | |
demandsToAdd.Add(childDemand); | |
} | |
} | |
ConnectSourceParents(); | |
} | |
private void ConnectSourceParents() | |
{ | |
foreach (var nodeA in nodes) | |
{ | |
foreach (var nodeB in nodes) | |
{ | |
if (nodeA == nodeB) continue; | |
if (nodeA.sourceChildren.Contains(nodeB.source)) | |
{ | |
nodeB.Connect(nodeA); | |
} | |
if (nodeA.sourceParent == nodeB.source) | |
{ | |
nodeA.Connect(nodeB); | |
} | |
} | |
} | |
} | |
[MenuItem("Worktown/Open Window")] | |
static void OpenWindow() | |
{ | |
// Get existing open window or if none, make a new one: | |
VizWindow window = (VizWindow)EditorWindow.GetWindow(typeof(VizWindow)); | |
window.position = new Rect(100, 100, 300, 500); | |
window.titleContent = new GUIContent("VizWindow"); | |
window.Show(); | |
} | |
} | |
public class VizNode | |
{ | |
public Vector2 pos; | |
public float width = 120; | |
public float height = 120; | |
public string title; | |
public string message; | |
public List<VizNode> connectedNodes = new List<VizNode>(); | |
public object source = null; | |
public object sourceParent = null; | |
public List<object> sourceChildren = new List<object>(); | |
public Vector2 velocity = new Vector2(0, 0); | |
public Action<VizNode> updater = null; | |
public VizNode(string title, string message = "") | |
{ | |
this.title = title; | |
this.message = message; | |
pos = new Vector2(200f, 200f) + RXRandom.Vector2Normalized() * 100f; | |
} | |
public Rect GetRect() | |
{ | |
return new Rect(pos.x-width/2, pos.y-height/2, width, height); | |
} | |
public void Draw(int id) | |
{ | |
updater?.Invoke(this); | |
var resultRect = GUI.Window(id, GetRect(), DrawGUI, title); | |
pos = resultRect.center; | |
} | |
private void DrawGUI(int id) | |
{ | |
EditorStyles.label.wordWrap = true; | |
EditorGUILayout.LabelField(message); | |
//disable this soon | |
GUI.DragWindow(); //this MUST be at the end (for them to be draggable) | |
} | |
public void Connect(VizNode otherNode) | |
{ | |
connectedNodes.Add(otherNode); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment