148 lines
6.4 KiB
C#
148 lines
6.4 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEditor;
|
|
|
|
namespace NanoBrain.Unity {
|
|
|
|
public class ClusterView {
|
|
|
|
private static readonly float size = 20;
|
|
|
|
protected class ViewState {
|
|
public string key = null;
|
|
public Vector2 scrollPos = Vector2.zero;
|
|
public bool expandArray = false;
|
|
public Nucleus currentNucleus = null;
|
|
}
|
|
|
|
static Dictionary<string, ViewState> viewStates = new();
|
|
private static ViewState GetViewState(SerializedProperty property) {
|
|
string key = property.propertyPath + "_" + property.serializedObject.targetObject.GetEntityId();
|
|
if (!viewStates.TryGetValue(key, out ViewState state))
|
|
state = new() { key = key };
|
|
return state;
|
|
}
|
|
|
|
private static void UpdateViewState(ViewState viewState) {
|
|
viewStates[viewState.key] = viewState;
|
|
}
|
|
|
|
public static void Render(Rect drawRect, Cluster cluster, SerializedProperty property) {
|
|
ViewState state = GetViewState(property);
|
|
|
|
// background
|
|
EditorGUI.DrawRect(drawRect, Color.black);
|
|
|
|
const float contentWidth = 1000f;
|
|
Rect contentRect = new Rect(0f, 0f, contentWidth, drawRect.height);
|
|
|
|
// Begin horizontal-only scroll view
|
|
state.scrollPos = GUI.BeginScrollView(drawRect, state.scrollPos, contentRect, true, false);
|
|
|
|
// Local content group: draw GUI content using content-local coords (0..contentWidth)
|
|
GUI.BeginGroup(new Rect(-state.scrollPos.x, 0f, contentWidth, drawRect.height));
|
|
EditorGUI.DrawRect(new Rect(0f, 0f, contentWidth, drawRect.height), new Color(0.08f, 0.08f, 0.08f, 1f));
|
|
GUI.EndGroup();
|
|
GUI.EndScrollView();
|
|
|
|
// Clip to drawRect so Handles are not drawn outside the black area
|
|
GUI.BeginGroup(drawRect);
|
|
|
|
// Inner group positions content origin so local coords match content space and respect scroll
|
|
GUI.BeginGroup(new Rect(-state.scrollPos.x, 0f, contentWidth, drawRect.height));
|
|
|
|
Handles.BeginGUI();
|
|
DrawNucleus(state, cluster, new Vector2(100, 100), Color.black);
|
|
Handles.EndGUI();
|
|
|
|
GUI.EndGroup(); // end inner group
|
|
GUI.EndGroup(); // end clipping group
|
|
|
|
UpdateViewState(state);
|
|
}
|
|
|
|
protected static void DrawNucleus(ViewState state, Nucleus nucleus, Vector2 position, Color color) {
|
|
if (nucleus == null)
|
|
return;
|
|
|
|
if (nucleus == state.currentNucleus) {
|
|
// The selected nucleus highlight ring
|
|
Handles.color = Color.white;
|
|
Handles.DrawSolidDisc(position, Vector3.forward, size + 2);
|
|
}
|
|
|
|
if (nucleus is MemoryCell) {
|
|
Handles.color = Color.white;
|
|
Handles.DrawWireDisc(position + Vector2.right * 10, Vector3.forward, size);
|
|
}
|
|
|
|
Handles.color = color;
|
|
Handles.DrawSolidDisc(position, Vector3.forward, size);
|
|
|
|
Handles.color = Color.white;
|
|
// Position the label in front of the disc
|
|
//Vector3 labelPosition = position; // + (Vector2.forward * 0.1f);
|
|
|
|
GUIStyle style = new(EditorStyles.label) {
|
|
alignment = TextAnchor.MiddleCenter,
|
|
normal = { textColor = Color.white },
|
|
fontStyle = FontStyle.Bold,
|
|
};
|
|
|
|
// if (nucleus.parent is Cluster parentCluster && currentNucleus != null && parentCluster != currentNucleus.parent)
|
|
// DrawCluster(parentCluster, position, color, size);
|
|
// else if (nucleus is Cluster cluster)
|
|
// DrawCluster(cluster, position, color, size);
|
|
|
|
if (state.expandArray == false) {// || nucleus != currentNucleus) {
|
|
// put name below nucleus
|
|
Vector3 labelPos = position - Vector2.down * (size + 5); // below neuron
|
|
style.alignment = TextAnchor.UpperCenter;
|
|
|
|
if (nucleus.parent != null && state.currentNucleus != null && nucleus.parent != state.currentNucleus.parent && nucleus.parent is Cluster parentCluster1) {
|
|
// This neuron is part of another cluster
|
|
parentCluster1.name ??= "";
|
|
int colonPos = parentCluster1.name.IndexOf(":");
|
|
string baseName;
|
|
if (colonPos > 0 && colonPos < parentCluster1.name.Length - 2)
|
|
baseName = parentCluster1.name[..colonPos] + "\n";
|
|
else
|
|
baseName = parentCluster1.name + "\n";
|
|
Handles.Label(labelPos, baseName + nucleus.name, style);
|
|
}
|
|
else {
|
|
nucleus.name ??= "";
|
|
int colonPos = nucleus.name.IndexOf(":");
|
|
if (colonPos > 0 && colonPos < nucleus.name.Length - 2) {
|
|
// if it is an array, we should not show the :0 of the first element
|
|
string baseName = nucleus.name[..colonPos];
|
|
Handles.Label(labelPos, baseName, style);
|
|
}
|
|
else
|
|
Handles.Label(labelPos, nucleus.name, style);
|
|
}
|
|
}
|
|
|
|
// Tooltip
|
|
// Rect neuronRect = new(position.x - size, position.y - size, size * 2, size * 2);
|
|
|
|
// int id = GUIUtility.GetControlID(FocusType.Passive);
|
|
// Event e = Event.current;
|
|
// EventType et = e.GetTypeForControl(id);
|
|
// if (e != null && neuronRect.Contains(e.mousePosition)) {
|
|
// // Process Hover
|
|
// HandleMouseHover(nucleus, neuronRect);
|
|
// // Process click
|
|
// if (e.type == EventType.MouseDown && e.button == 0) {
|
|
// // Consume the event so the scene doesn't also handle it
|
|
// e.Use();
|
|
// if (nucleus is Cluster parentCluster2)
|
|
// OnNeuronClick(parentCluster2);
|
|
// else
|
|
// OnNeuronClick(nucleus);
|
|
// }
|
|
// }
|
|
}
|
|
}
|
|
|
|
} |