Removed Neuron_Drawer and curves

This commit is contained in:
Pascal Serrarens 2026-05-22 17:02:34 +02:00
parent 94df545222
commit 923a5fafe3
6 changed files with 62 additions and 174 deletions

View File

@ -311,10 +311,10 @@ namespace NanoBrain.Unity {
if (this.view.currentNucleus is not MemoryCell) { if (this.view.currentNucleus is not MemoryCell) {
EditorGUILayout.BeginHorizontal(); EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Activation Curve", GUILayout.MinWidth(60)); EditorGUILayout.LabelField("Activation Curve", GUILayout.MinWidth(60));
if (neuron.curveMax > 0) // if (neuron.curveMax > 0)
EditorGUILayout.CurveField(neuron.curve, Color.cyan, new Rect(0, 0, 1, neuron.curveMax), GUILayout.Width(40)); // EditorGUILayout.CurveField(neuron.curve, Color.cyan, new Rect(0, 0, 1, neuron.curveMax), GUILayout.Width(40));
else // else
EditorGUILayout.CurveField(neuron.curve, Color.cyan, new Rect(0, neuron.curveMax, 1, -neuron.curveMax), GUILayout.Width(40)); // EditorGUILayout.CurveField(neuron.curve, Color.cyan, new Rect(0, neuron.curveMax, 1, -neuron.curveMax), GUILayout.Width(40));
Neuron.ActivationType newPreset = (Neuron.ActivationType)EditorGUILayout.EnumPopup(neuron.activator, GUILayout.MinWidth(50)); Neuron.ActivationType newPreset = (Neuron.ActivationType)EditorGUILayout.EnumPopup(neuron.activator, GUILayout.MinWidth(50));
anythingChanged |= newPreset != neuron.activator; anythingChanged |= newPreset != neuron.activator;
neuron.activator = newPreset; neuron.activator = newPreset;

View File

@ -11,41 +11,27 @@ namespace NanoBrain.Unity {
class Cluster_Drawer : PropertyDrawer { class Cluster_Drawer : PropertyDrawer {
static Cluster_Drawer() { static Cluster_Drawer() {
SceneView.duringSceneGui += OnSceneGUI; if (Application.isPlaying)
SceneView.duringSceneGui += OnSceneGUI;
Selection.selectionChanged += OnSelectionChanged; Selection.selectionChanged += OnSelectionChanged;
if (clusterView != null) if (clusterView != null)
clusterView.initialized = false; clusterView.initialized = false;
} }
//static readonly Dictionary<string, ClusterView> clusterViews = new(); private const float padding = 4f;
private const float elementHeight = 64f; // height reserved for the VisualElement
public static void Insepctor(SerializedObject serializedObject, string propertyName) {
EditorGUILayout.PropertyField(serializedObject.FindProperty(propertyName));
}
const float padding = 4f;
const float elementHeight = 64f; // height reserved for the VisualElement
private static ClusterView clusterView; private static ClusterView clusterView;
private static UnityEngine.Object selectedTarget; private static UnityEngine.Object selectedTarget;
// public ClusterView GetClusterView(SerializedProperty property) {
// string key = property.propertyPath + "_" + property.serializedObject.targetObject.GetInstanceID();//GetEntityId();
// if (clusterViews.TryGetValue(key, out ClusterView view))
// return view;
// view = new ClusterView(key);
// clusterViews[key] = view;
// return view;
// }
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
if (Cluster_Drawer.clusterView == null)
return 0;
float height = EditorGUIUtility.singleLineHeight + padding; float height = EditorGUIUtility.singleLineHeight + padding;
// string key = property.propertyPath + "_" + property.serializedObject.targetObject.GetInstanceID();//GetEntityId();
// //s_foldouts.TryGetValue(key, out bool isOpen);
// clusterViews.TryGetValue(key, out ClusterView view);
ClusterView view = ClusterView.GetClusterView(property);
SerializedProperty prefabProp = property.FindPropertyRelative(nameof(Cluster.prefab)); SerializedProperty prefabProp = property.FindPropertyRelative(nameof(Cluster.prefab));
if (prefabProp.objectReferenceValue != null && view.isOpen) { if (prefabProp.objectReferenceValue != null && Cluster_Drawer.clusterView.isOpen) {
height += padding + elementHeight; height += padding + elementHeight;
height = 500; height = 500;
} }
@ -56,7 +42,10 @@ namespace NanoBrain.Unity {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
ClusterView clusterView = ClusterView.GetClusterView(property); // Not sure if this works properly with multiple Clusters in a single gameObject
ClusterView clusterView = Cluster_Drawer.clusterView;
if (Cluster_Drawer.clusterView == null)
clusterView = ClusterView.GetClusterView(property);
label = EditorGUI.BeginProperty(position, label, property); label = EditorGUI.BeginProperty(position, label, property);
@ -88,7 +77,7 @@ namespace NanoBrain.Unity {
} }
if (prefabProp.objectReferenceValue != null) { if (prefabProp.objectReferenceValue != null) {
// // Graph is not shown when multi-editing // Graph is not shown when multi-editing
if (property.serializedObject.targetObjects.Length == 1) { if (property.serializedObject.targetObjects.Length == 1) {
UnityEngine.Object targetObject = property.serializedObject.targetObject; UnityEngine.Object targetObject = property.serializedObject.targetObject;
Cluster_Drawer.selectedTarget = targetObject; Cluster_Drawer.selectedTarget = targetObject;
@ -98,22 +87,18 @@ namespace NanoBrain.Unity {
cluster = SerializedPropertyUtility.GetManagedObjectForProperty(targetObject, property.propertyPath) as Cluster; cluster = SerializedPropertyUtility.GetManagedObjectForProperty(targetObject, property.propertyPath) as Cluster;
} }
else { else {
Debug.Log("New cluster instance");
// This does not work properly yet it seems // This does not work properly yet it seems
ClusterPrefab clusterPrefab = prefabProp.objectReferenceValue as ClusterPrefab; ClusterPrefab clusterPrefab = prefabProp.objectReferenceValue as ClusterPrefab;
cluster = new(clusterPrefab); cluster = new(clusterPrefab);
object parent = SerializedPropertyUtility.GetParentObjectAndMember(targetObject, property.propertyPath, out var memberInfo, out int outIndex); object parent = SerializedPropertyUtility.GetParentObjectAndMember(targetObject, property.propertyPath, out var memberInfo, out int outIndex);
if (parent != null && memberInfo is FieldInfo fieldInfo) { if (parent != null && memberInfo is FieldInfo fieldInfo) {
fieldInfo.SetValue(parent, cluster); fieldInfo.SetValue(parent, cluster);
EditorUtility.SetDirty(targetObject); //EditorUtility.SetDirty(targetObject);
} }
clusterView.initialized = true; clusterView.initialized = true;
} }
// key per field instance
string key = property.propertyPath + "_" + property.serializedObject.targetObject.GetInstanceID();//GetEntityId();
// if (!s_foldouts.TryGetValue(key, out bool isOpen))
// isOpen = true;
// foldout header rect // foldout header rect
Rect headerRect = new(fieldRect.x, fieldRect.yMax + 4f, fieldRect.width, EditorGUIUtility.singleLineHeight); Rect headerRect = new(fieldRect.x, fieldRect.yMax + 4f, fieldRect.width, EditorGUIUtility.singleLineHeight);
clusterView.isOpen = EditorGUI.Foldout(headerRect, clusterView.isOpen, "Graph", true); clusterView.isOpen = EditorGUI.Foldout(headerRect, clusterView.isOpen, "Graph", true);
@ -165,9 +150,12 @@ namespace NanoBrain.Unity {
} }
private static void OnSelectionChanged() { private static void OnSelectionChanged() {
foreach (ClusterView clusterView in ClusterView.clusterViews.Values) { UnityEngine.Object active = Selection.activeObject;
if (active == null)
return;
foreach (ClusterView clusterView in ClusterView.clusterViews.Values)
clusterView.initialized = false; clusterView.initialized = false;
}
} }
} }

View File

@ -1,85 +0,0 @@
using UnityEngine;
using UnityEditor;
using Unity.Mathematics;
using System;
using System.Reflection;
using System.Collections;
namespace NanoBrain.Unity {
[CustomPropertyDrawer(typeof(Neuron))]
class Neuron_Drawer : PropertyDrawer {
public static void Insepctor(SerializedObject serializedObject, string propertyName ) {
EditorGUILayout.PropertyField(serializedObject.FindProperty(propertyName));
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
// Draw foldout + properties
label = EditorGUI.BeginProperty(position, label, property);
// Begin indent block
int indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
object instance = GetTargetObjectOfProperty(property);
float lineHeight = EditorGUIUtility.singleLineHeight;
Rect r = new(position.x, position.y, position.width, lineHeight);
if (instance != null) {
FieldInfo field = typeof(Neuron).GetField("_outputValue", BindingFlags.NonPublic | BindingFlags.Instance);
if (field != null) {
float3 val = (float3)field.GetValue(instance);
EditorGUI.Vector3Field(r, $"Neuron: {label}", val);
}
}
EditorGUI.indentLevel = indent;
EditorGUI.EndProperty();
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
// height for 1 line
return (EditorGUIUtility.singleLineHeight * 1) + (EditorGUIUtility.standardVerticalSpacing * 0);
}
public static object GetTargetObjectOfProperty(SerializedProperty prop) {
var path = prop.propertyPath.Replace(".Array.data[", "[");
object obj = prop.serializedObject.targetObject;
var elements = path.Split('.');
foreach (var element in elements) {
if (element.Contains("[")) {
var elementName = element.Substring(0, element.IndexOf("["));
var index = Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", ""));
obj = GetValue_Imp(obj, elementName, index);
}
else {
obj = GetValue_Imp(obj, element);
}
}
return obj;
}
static object GetValue_Imp(object source, string name) {
if (source == null)
return null;
Type t = source.GetType();
FieldInfo f = t.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
if (f != null)
return f.GetValue(source);
PropertyInfo p = t.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
return p?.GetValue(source, null);
}
static object GetValue_Imp(object source, string name, int index) {
if (GetValue_Imp(source, name) is not IEnumerable enumerable)
return null;
IEnumerator en = enumerable.GetEnumerator();
for (int i = 0; i <= index; i++) {
if (!en.MoveNext())
return null;
}
return en.Current;
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: aa0e340763ca6299e93d514b271ae38d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -69,10 +69,6 @@ namespace NanoBrain {
[SerializeReference] [SerializeReference]
[HideInInspector] [HideInInspector]
public List<Nucleus> nuclei = new(); public List<Nucleus> nuclei = new();
// the nuclei sorted using topological sorting
// to ensure that the cluster is computer in the right order
//public List<Nucleus> sortedNuclei;
#region Init #region Init

View File

@ -141,52 +141,52 @@ namespace NanoBrain {
get { return _activator; } get { return _activator; }
set { set {
_activator = value; _activator = value;
this.curve = GenerateCurve(); //this.curve = GenerateCurve();
} }
} }
/// <summary> /// <summary>
/// The curve representing the activation function /// The curve representing the activation function
/// </summary> /// </summary>
[HideInInspector] // [HideInInspector]
public AnimationCurve curve; // public AnimationCurve curve;
/// <summary> /// <summary>
/// The maximum value of the curve /// The maximum value of the curve
/// </summary> /// </summary>
[HideInInspector] // [HideInInspector]
public float curveMax = 1.0f; // public float curveMax = 1.0f;
/// <summary> /// <summary>
/// Generate the curve for the current activation function /// Generate the curve for the current activation function
/// </summary> /// </summary>
/// <returns>The curve </returns> /// <returns>The curve </returns>
public AnimationCurve GenerateCurve() { // public AnimationCurve GenerateCurve() {
switch (this.activator) { // switch (this.activator) {
case ActivationType.Linear: // case ActivationType.Linear:
this.curveMax = 1; // this.curveMax = 1;
return Presets.Linear(1); // return Presets.Linear(1);
case ActivationType.Power: // case ActivationType.Power:
this.curveMax = 1; // this.curveMax = 1;
return Presets.Power(2.0f, 1); // return Presets.Power(2.0f, 1);
case ActivationType.Sqrt: // case ActivationType.Sqrt:
this.curveMax = 1; // this.curveMax = 1;
return Presets.Power(0.5f, 1); // return Presets.Power(0.5f, 1);
case ActivationType.Reciprocal: // case ActivationType.Reciprocal:
this.curveMax = 1 / 0.01f * 1; // this.curveMax = 1 / 0.01f * 1;
return Presets.Reciprocal(1); // return Presets.Reciprocal(1);
case ActivationType.Tanh: // case ActivationType.Tanh:
this.curveMax = 1; // this.curveMax = 1;
return Presets.Tanh(1); // return Presets.Tanh(1);
case ActivationType.Binary: // case ActivationType.Binary:
this.curveMax = 1; // this.curveMax = 1;
return Presets.Binary(); // return Presets.Binary();
case ActivationType.Normalized: // case ActivationType.Normalized:
this.curveMax = 1; // this.curveMax = 1;
return Presets.Binary(); // return Presets.Binary();
default: // default:
this.curveMax = 1; // this.curveMax = 1;
return this.curve; // return this.curve;
} // }
} // }
/// <summary> /// <summary>
/// The curve presets for the activation functions /// The curve presets for the activation functions
@ -401,9 +401,9 @@ namespace NanoBrain {
clone.bias = this.bias; clone.bias = this.bias;
clone.persistOutput = this.persistOutput; clone.persistOutput = this.persistOutput;
clone.combinator = this.combinator; clone.combinator = this.combinator;
clone.curve = this.curve; // clone.curve = this.curve;
clone.activator = this.activator; clone.activator = this.activator;
clone.curveMax = this.curveMax; // clone.curveMax = this.curveMax;
clone.breakOnUpdate = this.breakOnUpdate; clone.breakOnUpdate = this.breakOnUpdate;
} }