using UnityEngine; using System.Collections; using UnityEditor; using System.Collections.Generic; namespace Hivemind { public class NodeRenderer { Texture2D nodeTexture; Texture2D nodeDebugTexture; Texture2D shadowTexture; Color edgeColor = Color.white; Color shadowColor = new Color (0f, 0f, 0f, 0.15f); // Selection Texture2D selectionTexture; Color selColor = new Color (1f, .78f, .353f); float selMargin = 2f; float selWidth = 2f; private Dictionary textures = new Dictionary (); public static float Width { get { return GridRenderer.step.x * 6; } } public static float Height { get { return GridRenderer.step.y * 6; } } public void Draw (Node node, bool selected) { float shadowOffset = 3; Vector2 offset = new Vector2 (shadowOffset, shadowOffset); // Edge for (int i = 0; i < node.parents.Count; i++) { if (node.parents [i] is NodeBranch) { Vector2 startPos = node.parents [i].editorPosition; if (((NodeBranch)(node.parents [i])).inLeft (node)) { startPos.x -= (NodeRenderer.Width / 4); // Shadow DrawEdge (startPos + offset, node.editorPosition + offset, Width, Height, shadowColor); // Line DrawEdge (startPos, node.editorPosition, Width, Height, edgeColor); } startPos = node.parents [i].editorPosition; if (((NodeBranch)(node.parents [i])).inRight (node)) { startPos.x += (NodeRenderer.Width / 4); // Shadow DrawEdge (startPos + offset, node.editorPosition + offset, Width, Height, shadowColor); // Line DrawEdge (startPos, node.editorPosition, Width, Height, edgeColor); } } else { // Shadow DrawEdge (node.parents [i].editorPosition + offset, node.editorPosition + offset, Width, Height, shadowColor); // Line DrawEdge (node.parents [i].editorPosition, node.editorPosition, Width, Height, edgeColor); } } //Kill nodes if (node is NodeBranch) { NodeBranch branch = node as NodeBranch; for (int i = 0; i < branch.KillLeftNodes.Count; i++) { Vector2 startPos = node.editorPosition; startPos.x -= (NodeRenderer.Width / 4); // Shadow DrawEdge (startPos + offset, branch.KillLeftNodes [i].editorPosition + offset, Width, Height, shadowColor); // Line DrawEdge (startPos, branch.KillLeftNodes [i].editorPosition, Width, Height, Color.red); } for (int i = 0; i < branch.KillRightNodes.Count; i++) { if (branch.KillRightNodes [i] == null) continue; Vector2 startPos = node.editorPosition; startPos.x += (NodeRenderer.Width / 4); // Shadow DrawEdge (startPos + offset, branch.KillRightNodes [i].editorPosition + offset, Width, Height, shadowColor); // Line DrawEdge (startPos, branch.KillRightNodes [i].editorPosition, Width, Height, Color.red); } } else { for (int i = 0; i < node.KillNodes.Count; i++) { // Shadow DrawEdge (node.editorPosition + offset, node.KillNodes [i].editorPosition + offset, Width, Height, shadowColor); // Line DrawEdge (node.editorPosition, node.KillNodes [i].editorPosition, Width, Height, Color.red); } } // Node Shadow Rect nodeRect = new Rect (node.editorPosition.x, node.editorPosition.y, Width, Height); Rect shadowRect = new Rect (nodeRect.x + shadowOffset, nodeRect.y + shadowOffset, nodeRect.width, nodeRect.height); if (shadowTexture == null) { shadowTexture = new Texture2D (1, 1); shadowTexture.hideFlags = HideFlags.DontSave; shadowTexture.SetPixel (0, 0, shadowColor); shadowTexture.Apply (); } GUI.DrawTexture (shadowRect, shadowTexture); // Node if (nodeTexture == null) { Color colA = new Color (0.765f, 0.765f, 0.765f); Color colB = new Color (0.886f, 0.886f, 0.886f); nodeTexture = new Texture2D (1, (int)Height); nodeTexture.hideFlags = HideFlags.DontSave; for (int y = 0; y < Height; y++) { nodeTexture.SetPixel (0, y, Color.Lerp (colA, colB, (float)y / 75)); } nodeTexture.Apply (); } // Node Debug if (nodeDebugTexture == null) { Color colA = new Color (1.000f, 0.796f, 0.357f); Color colB = new Color (0.894f, 0.443f, 0.008f); nodeDebugTexture = new Texture2D (1, (int)Height); nodeDebugTexture.hideFlags = HideFlags.DontSave; for (int y = 0; y < Height; y++) { nodeDebugTexture.SetPixel (0, y, Color.Lerp (colA, colB, (float)y / 75)); } nodeDebugTexture.Apply (); } if (node.behaviorTree.debugMode && node.behaviorTree.currentNode == node) { GUI.DrawTexture (nodeRect, nodeDebugTexture); } else { GUI.DrawTexture (nodeRect, nodeTexture); } // Icons DrawNodeIcon (nodeRect, node); GUI.color = Color.black; EditorGUI.LabelField (new Rect (nodeRect.x, nodeRect.y + 58, nodeRect.width, nodeRect.height), node.index.ToString ()); GUI.color = Color.white; DrawMuttimesIcon (nodeRect, node); // Debug status // DrawStatusIcon (nodeRect, node); // Action title if (node is NodeAction) { // Node title string title = node.desc; // if (((Action)node).methodInfo != null) // title = ((Action)node).methodName; // else // title = ""; title = title.Replace (".", ".\n"); Vector2 textSize = GUI.skin.label.CalcSize (new GUIContent (title)); float x = node.editorPosition.x + (Width / 2) - (textSize.x / 2) - 6; Rect titleRect = new Rect (x, node.editorPosition.y + Height, textSize.x + 10, textSize.y); EditorGUI.DropShadowLabel (titleRect, new GUIContent (title)); } // Selection highlight if (selected) { if (selectionTexture == null) { selectionTexture = new Texture2D (1, 1); selectionTexture.hideFlags = HideFlags.DontSave; selectionTexture.SetPixel (0, 0, selColor); selectionTexture.Apply (); } float mbOffset = selMargin + selWidth; // Margin + Border offset GUI.DrawTexture (new Rect (nodeRect.x - mbOffset, nodeRect.y - mbOffset, nodeRect.width + mbOffset * 2, selWidth), selectionTexture); // Top GUI.DrawTexture (new Rect (nodeRect.x - mbOffset, nodeRect.y - selMargin, selWidth, nodeRect.height + selMargin * 2), selectionTexture); // Left GUI.DrawTexture (new Rect (nodeRect.x + nodeRect.width + selMargin, nodeRect.y - selMargin, selWidth, nodeRect.height + selMargin * 2), selectionTexture); // Right GUI.DrawTexture (new Rect (nodeRect.x - mbOffset, nodeRect.y + nodeRect.height + selMargin, nodeRect.width + mbOffset * 2, selWidth), selectionTexture); // Top } } private void DrawMuttimesIcon (Rect nodeRect, Node node) { if (node.canMultTimes) { if (!textures.ContainsKey ("canMultTimes")) { Texture2D tex = (Texture2D)AssetDatabase.LoadAssetAtPath ("Assets/CoolapeFrame/Hivemind/EditorResources/Status/Running.png"); if (tex == null) { // Debug.LogWarning (status + ".png not found"); return; } tex.hideFlags = HideFlags.DontSave; textures.Add ("canMultTimes", tex); } Rect statusRect = new Rect (nodeRect.x, nodeRect.y, 32f, 32f); GUI.DrawTexture (statusRect, textures ["canMultTimes"]); } } private void DrawStatusIcon (Rect nodeRect, Node node) { EditorGUI.LabelField (new Rect (nodeRect.x, nodeRect.y + 58f, nodeRect.width, nodeRect.height), node.lastTick.ToString ()); if (node.lastStatus != null && BTEditorManager.Manager.behaviorTree.TotalTicks == node.lastTick) { string status = node.lastStatus.ToString (); if (!textures.ContainsKey (status)) { Texture2D tex = (Texture2D)AssetDatabase.LoadAssetAtPath ("Assets/CoolapeFrame/Hivemind/EditorResources/Status/" + status + ".png"); if (tex == null) { Debug.LogWarning (status + ".png not found"); return; } tex.hideFlags = HideFlags.DontSave; textures.Add (status, tex); } Rect statusRect = new Rect (nodeRect.x, nodeRect.y, 32f, 32f); GUI.DrawTexture (statusRect, textures [status]); } } private void DrawNodeIcon (Rect nodeRect, Node node) { int width = NearestPowerOfTwo (nodeRect.width); int height = NearestPowerOfTwo (nodeRect.height); float xOffset = (nodeRect.width - width) / 2; float yOffset = (nodeRect.height - height) / 2; Rect iconRect = new Rect (nodeRect.x + xOffset, nodeRect.y + yOffset, width, height); string nodeName = node.GetType ().Name; // if (node is Sequence && ((Sequence) node).rememberRunning) nodeName = "MemSequence"; // if (node is Selector && ((Selector) node).rememberRunning) nodeName = "MemSelector"; if (!textures.ContainsKey (nodeName)) { Texture2D tex = (Texture2D)AssetDatabase.LoadAssetAtPath ("Assets/CoolapeFrame/Hivemind/EditorResources/Nodes/" + nodeName + ".png"); if (tex == null) { Debug.LogWarning (nodeName + ".png not found"); return; } tex.hideFlags = HideFlags.DontSave; textures.Add (nodeName, tex); } GUI.DrawTexture (iconRect, textures [nodeName]); } int NearestPowerOfTwo (float value) { int result = 1; do { result = result << 1; } while (result << 1 < value); return result; } public static void DrawEdge (Vector2 start, Vector2 end, float width, float height, Color color) { float offset = width / 2; Vector3 startPos = new Vector3 (start.x + offset, start.y + height, 0); Vector3 endPos = new Vector3 (end.x + offset, end.y, 0); Vector3 startTan = startPos + Vector3.up * GridRenderer.step.x * 2; Vector3 endTan = endPos + Vector3.down * GridRenderer.step.x * 2; Handles.DrawBezier (startPos, endPos, startTan, endTan, color, null, 4); // Handles.ArrowCap(0, endPos, Quaternion.FromToRotation(new Vector3(0, 0, 1), new Vector3(0, 0, 1)), 154); Handles.color = color; Handles.DrawSolidDisc (endPos, new Vector3 (0, 0, 1), 5); Handles.color = Color.white; } public Rect rectForNode (Node node, Vector2 offset) { return new Rect (node.editorPosition.x - offset.x, node.editorPosition.y - offset.y, Width, Height); } } }