Files
tianrunCRM/Assets/CoolapeFrame/3rd/Hivemind/Editor/NodeRenderer.cs
2020-07-04 14:41:25 +08:00

282 lines
9.8 KiB
C#

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<string, Texture2D> textures = new Dictionary<string, Texture2D> ();
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<Texture2D> ("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<Texture2D> ("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<Texture2D> ("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);
}
}
}