drawer graph collapse fix

This commit is contained in:
Pascal Serrarens 2026-05-19 09:04:43 +02:00
parent 7cbd6bafb7
commit 9d43772b79
10 changed files with 189 additions and 38 deletions

View File

@ -18,11 +18,15 @@ namespace NanoBrain.Unity {
const float elementHeight = 64f; // height reserved for the VisualElement const float elementHeight = 64f; // height reserved for the VisualElement
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
float height = EditorGUIUtility.singleLineHeight; float height = EditorGUIUtility.singleLineHeight + padding;
if (property.objectReferenceValue != null) { string key = property.propertyPath + "_" + property.serializedObject.targetObject.GetEntityId();
s_foldouts.TryGetValue(key, out bool isOpen);
if (property.objectReferenceValue != null && isOpen) {
height += padding + elementHeight; height += padding + elementHeight;
height = 500; height = 500;
} }
else
height = 36;
return height; return height;
} }
@ -42,16 +46,17 @@ namespace NanoBrain.Unity {
if (property.objectReferenceValue is ClusterPrefab prefab) { if (property.objectReferenceValue is ClusterPrefab prefab) {
// key per field instance // key per field instance
string key = property.propertyPath + "_" + property.serializedObject.targetObject.GetEntityId(); string key = property.propertyPath + "_" + property.serializedObject.targetObject.GetEntityId();
if (!s_foldouts.TryGetValue(key, out bool isOpen)) isOpen = true; if (!s_foldouts.TryGetValue(key, out bool isOpen))
isOpen = true;
// foldout header rect // foldout header rect
Rect headerRect = new Rect(fieldRect.x, fieldRect.yMax + 4f, fieldRect.width, EditorGUIUtility.singleLineHeight); Rect headerRect = new(fieldRect.x, fieldRect.yMax + 4f, fieldRect.width, EditorGUIUtility.singleLineHeight);
isOpen = EditorGUI.Foldout(headerRect, isOpen, "Graph", true); isOpen = EditorGUI.Foldout(headerRect, isOpen, "Graph", true);
s_foldouts[key] = isOpen; s_foldouts[key] = isOpen;
if (isOpen) { if (isOpen) {
// content rect below header // content rect below header
Rect drawRect = new Rect(fieldRect.x, headerRect.yMax + 2f, fieldRect.width, 450f); Rect drawRect = new(fieldRect.x, headerRect.yMax + 2f, fieldRect.width, 450f);
// IMGUIContainer should be inserted here // IMGUIContainer should be inserted here
ClusterView.Render(drawRect, prefab.cluster, property); ClusterView.Render(drawRect, prefab.cluster, property);

View File

@ -462,9 +462,12 @@ namespace NanoBrain {
/// <returns></returns> /// <returns></returns>
protected float3 Combinator(float3 bias, List<Synapse> synapses) { protected float3 Combinator(float3 bias, List<Synapse> synapses) {
switch (combinator) { switch (combinator) {
case CombinatorType.Sum: return CombinatorSum(bias, synapses); case CombinatorType.Sum:
case CombinatorType.Product: return CombinatorProduct(bias, synapses); return CombinatorSum(bias, synapses);
default: return CombinatorSum(bias, synapses); case CombinatorType.Product:
return CombinatorProduct(bias, synapses);
default:
return CombinatorSum(bias, synapses);
} }
} }
@ -559,14 +562,22 @@ namespace NanoBrain {
// This does not allocate memory and seems faster than a switch expression // This does not allocate memory and seems faster than a switch expression
protected float3 Activator(float3 inputValue) { protected float3 Activator(float3 inputValue) {
switch (activator) { switch (activator) {
case ActivationType.Linear: return ActivatorLinear(inputValue); case ActivationType.Linear:
case ActivationType.Sqrt: return ActivatorSqrt(inputValue); return ActivatorLinear(inputValue);
case ActivationType.Power: return ActivatorPower(inputValue); case ActivationType.Sqrt:
case ActivationType.Reciprocal: return ActivatorReciprocal(inputValue); return ActivatorSqrt(inputValue);
case ActivationType.Tanh: return ActivatorTanh(inputValue); case ActivationType.Power:
case ActivationType.Binary: return ActivatorBinary(inputValue); return ActivatorPower(inputValue);
case ActivationType.Normalized: return ActivatorNormalized(inputValue); case ActivationType.Reciprocal:
default: return ActivatorLinear(inputValue); return ActivatorReciprocal(inputValue);
case ActivationType.Tanh:
return ActivatorTanh(inputValue);
case ActivationType.Binary:
return ActivatorBinary(inputValue);
case ActivationType.Normalized:
return ActivatorNormalized(inputValue);
default:
return ActivatorLinear(inputValue);
} }
} }

View File

@ -31,12 +31,12 @@ MonoBehaviour:
data: data:
name: Output name: Output
parent: parent:
rid: 4201950130928877723 rid: 4201950130928878123
bias: {x: 0, y: 0, z: 1} bias: {x: 0, y: 0, z: 1}
_synapses: _synapses:
- neuron: - neuron:
rid: 4201949899492425817 rid: 4201949899492425817
weight: 2 weight: 5
combinator: 0 combinator: 0
_activator: 0 _activator: 0
curve: curve:
@ -65,15 +65,15 @@ MonoBehaviour:
m_RotationOrder: 4 m_RotationOrder: 4
curveMax: 1 curveMax: 1
persistOutput: 0 persistOutput: 0
lastUpdate: 8.396028 lastUpdate: 16.366629
_receivers: [] _receivers: []
- rid: 4201949899492425817 - rid: 4201949899492425817
type: {class: Neuron, ns: NanoBrain, asm: Assembly-CSharp} type: {class: Neuron, ns: NanoBrain, asm: Assembly-CSharp}
data: data:
name: Sensor name: Sensor
parent: parent:
rid: 4201950130928877723 rid: 4201950130928878123
bias: {x: 0.00001, y: 0.00001, z: 0.00001} bias: {x: 0.061416026, y: 0.061416026, z: 0.061416026}
_synapses: [] _synapses: []
combinator: 0 combinator: 0
_activator: 0 _activator: 0
@ -103,10 +103,10 @@ MonoBehaviour:
m_RotationOrder: 4 m_RotationOrder: 4
curveMax: 1 curveMax: 1
persistOutput: 0 persistOutput: 0
lastUpdate: 8.396028 lastUpdate: 16.366629
_receivers: _receivers:
- rid: 4201949899492425781 - rid: 4201949899492425781
- rid: 4201950130928877723 - rid: 4201950130928878123
type: {class: Cluster, ns: NanoBrain, asm: Assembly-CSharp} type: {class: Cluster, ns: NanoBrain, asm: Assembly-CSharp}
data: data:
name: Braitenberg 1 name: Braitenberg 1

View File

@ -462,6 +462,10 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Vehicle 4a value: Vehicle 4a
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 1939863784866365225, guid: 7a7a20927b765988f8e0725d41f5022c, type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4961030105565435617, guid: 7a7a20927b765988f8e0725d41f5022c, type: 3} - target: {fileID: 4961030105565435617, guid: 7a7a20927b765988f8e0725d41f5022c, type: 3}
propertyPath: m_LocalPosition.x propertyPath: m_LocalPosition.x
value: -2 value: -2
@ -863,6 +867,63 @@ MeshFilter:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 600786778} m_GameObject: {fileID: 600786778}
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
--- !u!1001 &605735531
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 1939863784866365225, guid: 83edc100c355dcd53bfb759dc07323c4, type: 3}
propertyPath: m_Name
value: Vehicle 1
objectReference: {fileID: 0}
- target: {fileID: 4961030105565435617, guid: 83edc100c355dcd53bfb759dc07323c4, type: 3}
propertyPath: m_LocalPosition.x
value: -3
objectReference: {fileID: 0}
- target: {fileID: 4961030105565435617, guid: 83edc100c355dcd53bfb759dc07323c4, type: 3}
propertyPath: m_LocalPosition.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: 4961030105565435617, guid: 83edc100c355dcd53bfb759dc07323c4, type: 3}
propertyPath: m_LocalPosition.z
value: -3
objectReference: {fileID: 0}
- target: {fileID: 4961030105565435617, guid: 83edc100c355dcd53bfb759dc07323c4, type: 3}
propertyPath: m_LocalRotation.w
value: 0.92387956
objectReference: {fileID: 0}
- target: {fileID: 4961030105565435617, guid: 83edc100c355dcd53bfb759dc07323c4, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4961030105565435617, guid: 83edc100c355dcd53bfb759dc07323c4, type: 3}
propertyPath: m_LocalRotation.y
value: 0.38268343
objectReference: {fileID: 0}
- target: {fileID: 4961030105565435617, guid: 83edc100c355dcd53bfb759dc07323c4, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4961030105565435617, guid: 83edc100c355dcd53bfb759dc07323c4, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4961030105565435617, guid: 83edc100c355dcd53bfb759dc07323c4, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 45
objectReference: {fileID: 0}
- target: {fileID: 4961030105565435617, guid: 83edc100c355dcd53bfb759dc07323c4, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 83edc100c355dcd53bfb759dc07323c4, type: 3}
--- !u!1 &655360912 --- !u!1 &655360912
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -2877,6 +2938,7 @@ SceneRoots:
- {fileID: 36325788} - {fileID: 36325788}
- {fileID: 1849732293} - {fileID: 1849732293}
- {fileID: 1604976778} - {fileID: 1604976778}
- {fileID: 605735531}
- {fileID: 1687205049} - {fileID: 1687205049}
- {fileID: 2006553073} - {fileID: 2006553073}
- {fileID: 128572670} - {fileID: 128572670}

View File

@ -48,12 +48,37 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z propertyPath: m_LocalEulerAnglesHint.z
value: 0 value: 0
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3243811853767288093, guid: c0398fc7a48853d47acb42e4e3498383, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3243811853767288093, guid: c0398fc7a48853d47acb42e4e3498383, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3243811853767288093, guid: c0398fc7a48853d47acb42e4e3498383, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3243811853767288093, guid: c0398fc7a48853d47acb42e4e3498383, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5526084556521277228, guid: c0398fc7a48853d47acb42e4e3498383, type: 3}
propertyPath: m_Name
value: Sensor
objectReference: {fileID: 0}
- target: {fileID: 6509051042471214143, guid: c0398fc7a48853d47acb42e4e3498383, type: 3} - target: {fileID: 6509051042471214143, guid: c0398fc7a48853d47acb42e4e3498383, type: 3}
propertyPath: m_Name propertyPath: m_Name
value: Vehicle 1 value: Vehicle 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 8280937452374640854, guid: c0398fc7a48853d47acb42e4e3498383, type: 3}
propertyPath: sensorRight
value:
objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_RemovedGameObjects: [] m_RemovedGameObjects:
- {fileID: 449746320909641321, guid: c0398fc7a48853d47acb42e4e3498383, type: 3}
m_AddedGameObjects: [] m_AddedGameObjects: []
m_AddedComponents: [] m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: c0398fc7a48853d47acb42e4e3498383, type: 3} m_SourcePrefab: {fileID: 100100000, guid: c0398fc7a48853d47acb42e4e3498383, type: 3}

View File

@ -72,10 +72,6 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.y propertyPath: m_LocalEulerAnglesHint.y
value: 0 value: 0
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 4375230766388568734, guid: c0398fc7a48853d47acb42e4e3498383, type: 3}
propertyPath: m_Constraints
value: 64
objectReference: {fileID: 0}
- target: {fileID: 6470252300495393990, guid: c0398fc7a48853d47acb42e4e3498383, type: 3} - target: {fileID: 6470252300495393990, guid: c0398fc7a48853d47acb42e4e3498383, type: 3}
propertyPath: sensitivityAngle propertyPath: sensitivityAngle
value: 180 value: 180

View File

@ -51,9 +51,32 @@ MonoBehaviour:
serializedVersion: 2 serializedVersion: 2
m_Bits: 4294967295 m_Bits: 4294967295
_output: 0 _output: 0
sensoryNeuron:
name:
parent:
rid: -2
bias: {x: 0, y: 0, z: 0}
_synapses: []
combinator: 0
_activator: 0
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
curveMax: 0
persistOutput: 0
lastUpdate: 0
_receivers: []
useOcclusion: 1 useOcclusion: 1
sensitivityAngle: 90 sensitivityAngle: 90
multiplier: 1 multiplier: 1
references:
version: 2
RefIds:
- rid: -2
type: {class: , ns: , asm: }
--- !u!1 &1960572894750316796 --- !u!1 &1960572894750316796
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -192,7 +215,8 @@ MonoBehaviour:
m_EditorClassIdentifier: Assembly-CSharp::Motor m_EditorClassIdentifier: Assembly-CSharp::Motor
outputNeuronName: Output outputNeuronName: Output
speed: 0 speed: 0
maxTorque: 1 maxTorque: 10
wheelCollider: {fileID: 0}
motorNeuron: motorNeuron:
name: name:
parent: parent:
@ -393,7 +417,8 @@ MonoBehaviour:
m_EditorClassIdentifier: Assembly-CSharp::Motor m_EditorClassIdentifier: Assembly-CSharp::Motor
outputNeuronName: Output outputNeuronName: Output
speed: 0 speed: 0
maxTorque: 1 maxTorque: 10
wheelCollider: {fileID: 0}
motorNeuron: motorNeuron:
name: name:
parent: parent:
@ -507,9 +532,32 @@ MonoBehaviour:
serializedVersion: 2 serializedVersion: 2
m_Bits: 4294967295 m_Bits: 4294967295
_output: 0 _output: 0
sensoryNeuron:
name:
parent:
rid: -2
bias: {x: 0, y: 0, z: 0}
_synapses: []
combinator: 0
_activator: 0
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
curveMax: 0
persistOutput: 0
lastUpdate: 0
_receivers: []
useOcclusion: 1 useOcclusion: 1
sensitivityAngle: 90 sensitivityAngle: 90
multiplier: 1 multiplier: 1
references:
version: 2
RefIds:
- rid: -2
type: {class: , ns: , asm: }
--- !u!1 &6345114338044386603 --- !u!1 &6345114338044386603
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -687,7 +735,7 @@ Rigidbody:
m_UseGravity: 1 m_UseGravity: 1
m_IsKinematic: 0 m_IsKinematic: 0
m_Interpolate: 0 m_Interpolate: 0
m_Constraints: 0 m_Constraints: 64
m_CollisionDetection: 0 m_CollisionDetection: 0
--- !u!114 &8280937452374640854 --- !u!114 &8280937452374640854
MonoBehaviour: MonoBehaviour:

View File

@ -67,7 +67,10 @@ namespace NanoBrain.Braitenberg {
lightCount++; lightCount++;
} }
return (sum / lightCount) * multiplier; if (lightCount == 0)
return 0;
else
return (sum / lightCount) * multiplier;
} }
static float RGBToLuminance(Color c) { static float RGBToLuminance(Color c) {

View File

@ -35,7 +35,8 @@ namespace NanoBrain.Braitenberg {
float kp = 0.02f; // proportional gain — tune float kp = 0.02f; // proportional gain — tune
float torque = kp * rpmError; float torque = kp * rpmError;
wheelCollider.motorTorque = Mathf.Clamp(torque, -maxTorque, maxTorque); wheelCollider.motorTorque = Mathf.Clamp(torque, -maxTorque, maxTorque);
// Debug.Log($"{speed} {currentRpm / 60} {torque}"); if (float.IsNaN(wheelCollider.rpm))
Debug.Log($"{speed} {currentRpm / 60} {torque}");
} }
} }

View File

@ -14,12 +14,12 @@ namespace NanoBrain.Braitenberg {
public Sensor sensorLeft; public Sensor sensorLeft;
public Sensor sensorRight; public Sensor sensorRight;
// void FixedUpdate() { void FixedUpdate() {
// //Debug.Log($"L: {sensorLeft.output} R: {sensorRight.output}"); //Debug.Log($"L: {sensorLeft.output} R: {sensorRight.output}");
// //Debug.Log($"L: {motorLeft.speed} R: {motorRight.speed}"); //Debug.Log($"L: {motorLeft.speed} R: {motorRight.speed}");
// Debug.Log($"L: {motorLeft.wheelCollider.rpm} R: {motorRight.wheelCollider.rpm}"); Debug.Log($"L: {motorLeft.wheelCollider.rpm} R: {motorRight.wheelCollider.rpm}");
// } }
} }
} }