Migrated ClusterEditor to ClusterView

This commit is contained in:
Pascal Serrarens 2026-05-19 12:45:11 +02:00
parent 9d43772b79
commit ebef711981
6 changed files with 1399 additions and 1232 deletions

View File

@ -1,3 +1,4 @@
/*
using UnityEditor;
using UnityEditor.UIElements;
@ -71,3 +72,4 @@ namespace NanoBrain.Unity {
}
}
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,10 @@
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor;
using System;
using System.Reflection;
namespace NanoBrain.Unity {
@ -58,7 +61,6 @@ namespace NanoBrain.Unity {
// content rect below header
Rect drawRect = new(fieldRect.x, headerRect.yMax + 2f, fieldRect.width, 450f);
// IMGUIContainer should be inserted here
ClusterView.Render(drawRect, prefab.cluster, property);
}
}
@ -86,4 +88,62 @@ namespace NanoBrain.Unity {
// }
}
/*
[InitializeOnLoad]
static class ClusterPrefabInspectorRepaints {
static ClusterPrefabInspectorRepaints() {
EditorApplication.update += OnEditorUpdate;
}
static double lastRepaint = 0;
const double repaintInterval = 1.0 / 15.0; // up to 15 FPS in inspector
static void OnEditorUpdate() {
if (!Application.isPlaying) return;
// throttle repaint frequency
if (EditorApplication.timeSinceStartup - lastRepaint < repaintInterval) return;
lastRepaint = EditorApplication.timeSinceStartup;
// Find all open inspectors (Editors) that target objects containing ClusterPrefab fields
var editors = Resources.FindObjectsOfTypeAll<Editor>();
foreach (var ed in editors) {
var targets = ed.targets;
if (targets == null)
continue;
bool shouldRepaint = targets.Any(t => ObjectHasClusterPrefabField(t));
if (shouldRepaint) {
try {
ed.Repaint();
}
catch {
// ignore
}
}
}
}
static bool ObjectHasClusterPrefabField(UnityEngine.Object obj) {
if (obj == null)
return false;
Type type = obj.GetType();
// search fields (instance, non-public/public)
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo f in fields) {
if (f.FieldType == typeof(ClusterPrefab))
return true;
// also handle arrays/lists of ClusterPrefab or serializable wrappers:
if (f.FieldType.IsArray && f.FieldType.GetElementType() == typeof(ClusterPrefab))
return true;
if (f.FieldType.IsGenericType) {
Type[] gen = f.FieldType.GetGenericArguments();
if (gen.Length == 1 && gen[0] == typeof(ClusterPrefab))
return true;
}
}
return false;
}
}
*/
}

View File

@ -9,32 +9,46 @@ namespace NanoBrain.Unity {
private static readonly float discRadius = 20;
static readonly Dictionary<string, ClusterView> viewStates = new();
private static ClusterView GetClusterView(SerializedProperty property) {
public static ClusterView GetClusterView(SerializedProperty property) {
string key = property.propertyPath + "_" + property.serializedObject.targetObject.GetEntityId();
if (!viewStates.TryGetValue(key, out ClusterView state))
state = new() { key = key };
return state;
}
public static ClusterView GetClusterView(SerializedObject serializedObject) {
string key = serializedObject.targetObject.GetEntityId().ToString();
if (!viewStates.TryGetValue(key, out ClusterView state))
state = new() { key = key };
return state;
}
private static void UpdateViewState(ClusterView viewState) {
viewStates[viewState.key] = viewState;
private void UpdateViewState() {
viewStates[this.key] = this;
}
public static void Render(Rect drawRect, Cluster cluster, SerializedProperty property) {
ClusterView clusterView = GetClusterView(property);
clusterView.currentCluster ??= cluster;
clusterView.Render(drawRect);
}
public static void Render(Rect drawRect, Cluster cluster, SerializedObject obj) {
ClusterView clusterView = GetClusterView(obj);
clusterView.currentCluster ??= cluster;
clusterView.Render(drawRect);
}
public void Render(Rect drawRect) {
// background
EditorGUI.DrawRect(drawRect, Color.black);
const float contentWidth = 1000f;
Rect contentRect = new Rect(0f, 0f, contentWidth, drawRect.height);
Rect contentRect = new(0f, 0f, contentWidth, drawRect.height - 20);
// Begin horizontal-only scroll view
clusterView.scrollPos = GUI.BeginScrollView(drawRect, clusterView.scrollPos, contentRect, true, false);
this.scrollPos = GUI.BeginScrollView(drawRect, this.scrollPos, contentRect, false, false);
// Local content group: draw GUI content using content-local coords (0..contentWidth)
GUI.BeginGroup(new Rect(-clusterView.scrollPos.x, 0f, contentWidth, drawRect.height));
GUI.BeginGroup(new Rect(-this.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();
@ -43,16 +57,16 @@ namespace NanoBrain.Unity {
GUI.BeginGroup(drawRect);
// Inner group positions content origin so local coords match content space and respect scroll
GUI.BeginGroup(new Rect(-clusterView.scrollPos.x, 0f, contentWidth, drawRect.height));
GUI.BeginGroup(new Rect(-this.scrollPos.x, 0f, contentWidth, drawRect.height));
Handles.BeginGUI();
clusterView.DrawFocusGraph();
this.DrawFocusGraph();
Handles.EndGUI();
GUI.EndGroup(); // end inner group
GUI.EndGroup(); // end clipping group
UpdateViewState(clusterView);
UpdateViewState();
}
public string key = null;

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
using System;
using UnityEngine;
/*
namespace NanoBrain.Unity {
/// <summary>
@ -66,3 +66,4 @@ namespace NanoBrain.Unity {
}
}
*/