multicluster visualization
This commit is contained in:
parent
a87118fc23
commit
92bfb29ed0
@ -76,8 +76,15 @@ namespace NanoBrain.Unity {
|
|||||||
margin = new RectOffset(10, 0, 4, 4)
|
margin = new RectOffset(10, 0, 4, 4)
|
||||||
};
|
};
|
||||||
// Nucleus type
|
// Nucleus type
|
||||||
string nucleusType = this.view.currentNucleus.GetType().Name;
|
System.Type nucleusType = this.view.currentNucleus.GetType();
|
||||||
GUILayout.Label(nucleusType, headerStyle);
|
if (nucleusType == typeof(Cluster)) {
|
||||||
|
Cluster cluster = this.view.currentNucleus as Cluster;
|
||||||
|
GUILayout.Label($"{cluster.prefab.name} {nucleusType.Name}", headerStyle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
GUILayout.Label(nucleusType.Name, headerStyle);
|
||||||
|
// string nucleusType = this.view.currentNucleus.GetType().Name;
|
||||||
|
// GUILayout.Label(nucleusType, headerStyle);
|
||||||
|
|
||||||
// Nucleus name
|
// Nucleus name
|
||||||
string newName = EditorGUILayout.TextField(this.view.currentNucleus.name, boldTextFieldStyle);
|
string newName = EditorGUILayout.TextField(this.view.currentNucleus.name, boldTextFieldStyle);
|
||||||
|
|||||||
@ -7,6 +7,8 @@ namespace NanoBrain.Unity {
|
|||||||
|
|
||||||
public class ClusterView {
|
public class ClusterView {
|
||||||
|
|
||||||
|
public static ClusterPrefab previousPrefab;
|
||||||
|
|
||||||
private static readonly float discRadius = 20;
|
private static readonly float discRadius = 20;
|
||||||
private float viewWidth;
|
private float viewWidth;
|
||||||
private float contentWidth = 1000;
|
private float contentWidth = 1000;
|
||||||
@ -199,7 +201,7 @@ namespace NanoBrain.Unity {
|
|||||||
DrawOutputs(position);
|
DrawOutputs(position);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dag dag = GenerateGraph(this.selectedOutput);
|
Dag dag = GenerateGraph(this.selectedOutput);
|
||||||
Dag.ComputeLayout(dag);
|
Dag.ComputeLayout(dag);
|
||||||
|
|
||||||
@ -269,7 +271,7 @@ namespace NanoBrain.Unity {
|
|||||||
Neuron receiverNeuron = receiver.nucleus as Neuron;
|
Neuron receiverNeuron = receiver.nucleus as Neuron;
|
||||||
if (receiverNeuron == null)
|
if (receiverNeuron == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (Synapse synapse in receiverNeuron.synapses) {
|
foreach (Synapse synapse in receiverNeuron.synapses) {
|
||||||
Nucleus nucleus = synapse.neuron;
|
Nucleus nucleus = synapse.neuron;
|
||||||
if (nucleus.parent != null && nucleus.parent != currentNucleus.parent) {
|
if (nucleus.parent != null && nucleus.parent != currentNucleus.parent) {
|
||||||
@ -310,7 +312,7 @@ namespace NanoBrain.Unity {
|
|||||||
if (nucleus == this.selectedOutput) {
|
if (nucleus == this.selectedOutput) {
|
||||||
// Add link to 'Outpus'
|
// Add link to 'Outpus'
|
||||||
nodeCount++;
|
nodeCount++;
|
||||||
if (ClusterViewer.previousPrefab != null)
|
if (ClusterView.previousPrefab != null && ClusterView.previousPrefab != nucleus.parent.prefab)
|
||||||
// Add link to previous editor
|
// Add link to previous editor
|
||||||
nodeCount++;
|
nodeCount++;
|
||||||
}
|
}
|
||||||
@ -344,9 +346,9 @@ namespace NanoBrain.Unity {
|
|||||||
}
|
}
|
||||||
if (nucleus == this.selectedOutput) {
|
if (nucleus == this.selectedOutput) {
|
||||||
Vector3 pos = new(50, margin + row * spacing, 0);
|
Vector3 pos = new(50, margin + row * spacing, 0);
|
||||||
if (ClusterViewer.previousPrefab != null) {
|
if (ClusterView.previousPrefab != null && ClusterView.previousPrefab != nucleus.parent.prefab) {
|
||||||
DrawEdge(parentPos, pos);
|
DrawEdge(parentPos, pos);
|
||||||
DrawClusterPrefab(ClusterViewer.previousPrefab, pos);
|
DrawClusterPrefab(ClusterView.previousPrefab, pos);
|
||||||
row++;
|
row++;
|
||||||
}
|
}
|
||||||
pos = new(50, margin + row * spacing, 0);
|
pos = new(50, margin + row * spacing, 0);
|
||||||
@ -447,9 +449,10 @@ namespace NanoBrain.Unity {
|
|||||||
float margin = 10 + spacing / 2;
|
float margin = 10 + spacing / 2;
|
||||||
|
|
||||||
int row = 0;
|
int row = 0;
|
||||||
|
Vector3 position = Vector3.zero;
|
||||||
foreach (Cluster sibling in nucleus.parent.instances) {
|
foreach (Cluster sibling in nucleus.parent.instances) {
|
||||||
Neuron siblingNeuron = sibling.GetNucleus(nucleus.name) as Neuron;
|
Neuron siblingNeuron = sibling.GetNucleus(nucleus.name) as Neuron;
|
||||||
Vector3 position = new(250, margin + row * spacing, 0.0f);
|
position = new(250, margin + row * spacing, 0.0f);
|
||||||
DrawEdge(parentPos, position);
|
DrawEdge(parentPos, position);
|
||||||
Color color = Color.black;
|
Color color = Color.black;
|
||||||
if (Application.isPlaying) {
|
if (Application.isPlaying) {
|
||||||
@ -459,16 +462,16 @@ namespace NanoBrain.Unity {
|
|||||||
color = new Color(brightness, brightness, brightness, 1f);
|
color = new Color(brightness, brightness, brightness, 1f);
|
||||||
}
|
}
|
||||||
DrawNucleus(siblingNeuron, position, color);
|
DrawNucleus(siblingNeuron, position, color);
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
Vector3 labelPos = position - Vector3.down * (discRadius + 5); // below neuron
|
||||||
|
string name = $"{nucleus.parent.instances[0].baseName}\n{nucleus.name}";
|
||||||
GUIStyle style = new(EditorStyles.label) {
|
GUIStyle style = new(EditorStyles.label) {
|
||||||
alignment = TextAnchor.UpperCenter,
|
alignment = TextAnchor.UpperCenter,
|
||||||
normal = { textColor = Color.white },
|
normal = { textColor = Color.white },
|
||||||
fontStyle = FontStyle.Bold,
|
fontStyle = FontStyle.Bold,
|
||||||
};
|
};
|
||||||
Vector3 labelPos = position - Vector3.down * (discRadius + 5); // below neuron
|
Handles.Label(labelPos, name, style);
|
||||||
string name = $"{sibling.baseName}\n{nucleus.name}";
|
|
||||||
Handles.Label(labelPos, name, style);
|
|
||||||
row++;
|
|
||||||
}
|
|
||||||
expandArray = false;
|
expandArray = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,7 +529,6 @@ namespace NanoBrain.Unity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void DrawNucleus(Nucleus nucleus, Vector3 position, float maxValue) {
|
protected void DrawNucleus(Nucleus nucleus, Vector3 position, float maxValue) {
|
||||||
maxValue = 1;
|
maxValue = 1;
|
||||||
Color color;
|
Color color;
|
||||||
@ -541,7 +543,6 @@ namespace NanoBrain.Unity {
|
|||||||
DrawNucleus(nucleus, position, color);
|
DrawNucleus(nucleus, position, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void DrawNucleus(Nucleus nucleus, Vector2 position, Color color) {
|
protected void DrawNucleus(Nucleus nucleus, Vector2 position, Color color) {
|
||||||
if (nucleus == null)
|
if (nucleus == null)
|
||||||
return;
|
return;
|
||||||
@ -699,7 +700,7 @@ namespace NanoBrain.Unity {
|
|||||||
e.Use();
|
e.Use();
|
||||||
Selection.activeObject = prefab;
|
Selection.activeObject = prefab;
|
||||||
EditorGUIUtility.PingObject(prefab);
|
EditorGUIUtility.PingObject(prefab);
|
||||||
ClusterViewer.previousPrefab = null;
|
ClusterView.previousPrefab = null;
|
||||||
Editor.CreateEditor(prefab);
|
Editor.CreateEditor(prefab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -765,16 +766,16 @@ namespace NanoBrain.Unity {
|
|||||||
protected void OnNeuronClick(Nucleus nucleus) {
|
protected void OnNeuronClick(Nucleus nucleus) {
|
||||||
if (nucleus == this.currentNucleus) {
|
if (nucleus == this.currentNucleus) {
|
||||||
this.selectedSynapseNeuron = null;
|
this.selectedSynapseNeuron = null;
|
||||||
// if (Application.isPlaying) {
|
if (Application.isPlaying) {
|
||||||
// if (nucleus is Cluster)
|
if (nucleus is Cluster)
|
||||||
// expandArray = !expandArray;
|
expandArray = !expandArray;
|
||||||
// else
|
else
|
||||||
// expandArray = false;
|
expandArray = false;
|
||||||
// }
|
}
|
||||||
// else {
|
else {
|
||||||
if (nucleus is Cluster cluster)
|
if (nucleus is Cluster cluster)
|
||||||
OnClusterClick(cluster);
|
OnClusterClick(cluster);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
else if (nucleus.parent != null && this.currentNucleus != null && nucleus.parent != this.currentNucleus.parent) {
|
else if (nucleus.parent != null && this.currentNucleus != null && nucleus.parent != this.currentNucleus.parent) {
|
||||||
// We go to a different cluster
|
// We go to a different cluster
|
||||||
@ -795,6 +796,7 @@ namespace NanoBrain.Unity {
|
|||||||
else {
|
else {
|
||||||
// select the cluster, not the neuron in the cluster
|
// select the cluster, not the neuron in the cluster
|
||||||
this.currentNucleus = nucleus.parent;
|
this.currentNucleus = nucleus.parent;
|
||||||
|
this.selectedSynapseNeuron = null;
|
||||||
this.expandArray = false;
|
this.expandArray = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -802,6 +804,7 @@ namespace NanoBrain.Unity {
|
|||||||
this.currentNucleus = nucleus;
|
this.currentNucleus = nucleus;
|
||||||
if (this.currentNucleus is Neuron neuron && neuron.receivers.Count == 0)
|
if (this.currentNucleus is Neuron neuron && neuron.receivers.Count == 0)
|
||||||
this.selectedOutput = this.currentNucleus;
|
this.selectedOutput = this.currentNucleus;
|
||||||
|
this.selectedSynapseNeuron = null;
|
||||||
this.expandArray = false;
|
this.expandArray = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -810,7 +813,7 @@ namespace NanoBrain.Unity {
|
|||||||
// May be used with storedPrefab...
|
// May be used with storedPrefab...
|
||||||
Selection.activeObject = subCluster.prefab;
|
Selection.activeObject = subCluster.prefab;
|
||||||
EditorGUIUtility.PingObject(subCluster.prefab);
|
EditorGUIUtility.PingObject(subCluster.prefab);
|
||||||
ClusterViewer.previousPrefab = this.currentCluster.prefab;
|
ClusterView.previousPrefab = this.currentCluster.prefab;
|
||||||
Editor.CreateEditor(subCluster.prefab);
|
Editor.CreateEditor(subCluster.prefab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ namespace NanoBrain.Unity {
|
|||||||
|
|
||||||
public class ClusterViewer : Editor {
|
public class ClusterViewer : Editor {
|
||||||
|
|
||||||
public static ClusterPrefab previousPrefab;
|
//public static ClusterPrefab previousPrefab;
|
||||||
|
|
||||||
public class GraphView : VisualElement {
|
public class GraphView : VisualElement {
|
||||||
protected Cluster currentCluster;
|
protected Cluster currentCluster;
|
||||||
|
|||||||
@ -12,12 +12,19 @@ namespace NanoBrain.Unity {
|
|||||||
|
|
||||||
[CustomPropertyDrawer(typeof(Cluster))]
|
[CustomPropertyDrawer(typeof(Cluster))]
|
||||||
class Cluster_Drawer : PropertyDrawer {
|
class Cluster_Drawer : PropertyDrawer {
|
||||||
|
|
||||||
|
static Cluster_Drawer() {
|
||||||
|
SceneView.duringSceneGui += OnSceneGUI;
|
||||||
|
}
|
||||||
|
|
||||||
public static void Insepctor(SerializedObject serializedObject, string propertyName) {
|
public static void Insepctor(SerializedObject serializedObject, string propertyName) {
|
||||||
EditorGUILayout.PropertyField(serializedObject.FindProperty(propertyName));
|
EditorGUILayout.PropertyField(serializedObject.FindProperty(propertyName));
|
||||||
}
|
}
|
||||||
|
|
||||||
const float padding = 4f;
|
const float padding = 4f;
|
||||||
const float elementHeight = 64f; // height reserved for the VisualElement
|
const float elementHeight = 64f; // height reserved for the VisualElement
|
||||||
|
private static ClusterView clusterView;
|
||||||
|
private static UnityEngine.Object selectedTarget;
|
||||||
|
|
||||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
|
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
|
||||||
float height = EditorGUIUtility.singleLineHeight + padding;
|
float height = EditorGUIUtility.singleLineHeight + padding;
|
||||||
@ -69,7 +76,8 @@ namespace NanoBrain.Unity {
|
|||||||
if (property.serializedObject.targetObjects.Length == 1) {
|
if (property.serializedObject.targetObjects.Length == 1) {
|
||||||
// Graph is not shown when multi-editing
|
// Graph is not shown when multi-editing
|
||||||
UnityEngine.Object targetObject = property.serializedObject.targetObject;
|
UnityEngine.Object targetObject = property.serializedObject.targetObject;
|
||||||
Cluster cluster = SerializedPropertyUtility.GetManagedObjectForProperty(targetObject, property.propertyPath) as Cluster;
|
Cluster_Drawer.selectedTarget = targetObject;
|
||||||
|
Cluster cluster = SerializedPropertyUtility.GetManagedObjectForProperty(targetObject, property.propertyPath) as Cluster;
|
||||||
|
|
||||||
// key per field instance
|
// key per field instance
|
||||||
string key = property.propertyPath + "_" + property.serializedObject.targetObject.GetInstanceID();//GetEntityId();
|
string key = property.propertyPath + "_" + property.serializedObject.targetObject.GetInstanceID();//GetEntityId();
|
||||||
@ -85,18 +93,40 @@ namespace NanoBrain.Unity {
|
|||||||
// content rect below header
|
// content rect below header
|
||||||
Rect drawRect = new(fieldRect.x, headerRect.yMax + 2f, fieldRect.width, 450f);
|
Rect drawRect = new(fieldRect.x, headerRect.yMax + 2f, fieldRect.width, 450f);
|
||||||
|
|
||||||
|
Cluster_Drawer.clusterView = ClusterView.GetClusterView(property);
|
||||||
ClusterView.Render(drawRect, cluster, property);
|
ClusterView.Render(drawRect, cluster, property);
|
||||||
//Debug.Log(prefab.cluster.defaultOutput.outputMagnitude);
|
//Debug.Log(prefab.cluster.defaultOutput.outputMagnitude);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUI.indentLevel = indent;
|
EditorGUI.indentLevel = indent;
|
||||||
EditorGUI.EndProperty();
|
EditorGUI.EndProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void OnSceneGUI(SceneView sceneView) {
|
||||||
|
GameObject gameObject = null;
|
||||||
|
if (selectedTarget is Component c)
|
||||||
|
gameObject = c.gameObject;
|
||||||
|
else if (selectedTarget is GameObject g)
|
||||||
|
gameObject = g;
|
||||||
|
|
||||||
|
Handles.color = Color.yellow;
|
||||||
|
if (clusterView.selectedSynapseNeuron != null) {
|
||||||
|
foreach (Cluster sibling in clusterView.selectedSynapseNeuron.parent.instances) {
|
||||||
|
Neuron siblingNeuron = sibling.GetNucleus(clusterView.selectedSynapseNeuron.name) as Neuron;
|
||||||
|
Vector3 worldVector = gameObject.transform.TransformVector(siblingNeuron.outputValue);
|
||||||
|
Handles.DrawLine(gameObject.transform.position, gameObject.transform.position + worldVector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (clusterView.currentNucleus is Neuron currentNeuron) {
|
||||||
|
Vector3 worldVector = gameObject.transform.TransformVector(currentNeuron.outputValue);
|
||||||
|
Handles.DrawLine(gameObject.transform.position, gameObject.transform.position + worldVector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SerializedPropertyUtility {
|
public static class SerializedPropertyUtility {
|
||||||
|
|||||||
@ -42,7 +42,8 @@ namespace NanoBrain {
|
|||||||
/// A cluster is a multi-cluster when there is more than one instance.
|
/// A cluster is a multi-cluster when there is more than one instance.
|
||||||
/// The actual instances are only created at runtime.
|
/// The actual instances are only created at runtime.
|
||||||
/// The value instanceCount determines how many instances will be present at runtime.
|
/// The value instanceCount determines how many instances will be present at runtime.
|
||||||
[NonSerialized]
|
//[NonSerialized]
|
||||||
|
[SerializeReference]
|
||||||
public Cluster[] instances;
|
public Cluster[] instances;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -164,7 +165,7 @@ namespace NanoBrain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Application.isPlaying) {
|
//if (Application.isPlaying) {
|
||||||
// Only create cluster siblings at runtime
|
// Only create cluster siblings at runtime
|
||||||
foreach (Nucleus clonedNucleus in clonedNuclei) {
|
foreach (Nucleus clonedNucleus in clonedNuclei) {
|
||||||
if (clonedNucleus is not Cluster clonedCluster)
|
if (clonedNucleus is not Cluster clonedCluster)
|
||||||
@ -194,7 +195,7 @@ namespace NanoBrain {
|
|||||||
if (clonedNucleus is not Cluster)
|
if (clonedNucleus is not Cluster)
|
||||||
clonedNucleus.UpdateStateIsolated();
|
clonedNucleus.UpdateStateIsolated();
|
||||||
}
|
}
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \copydoc NanoBrain::Nucleus::ShallowCloneTo
|
/// \copydoc NanoBrain::Nucleus::ShallowCloneTo
|
||||||
@ -503,6 +504,8 @@ namespace NanoBrain {
|
|||||||
foreach (Nucleus receptor in this.nuclei) {
|
foreach (Nucleus receptor in this.nuclei) {
|
||||||
if (receptor is Nucleus nucleus)
|
if (receptor is Nucleus nucleus)
|
||||||
if (nucleus.name == nucleusName) {
|
if (nucleus.name == nucleusName) {
|
||||||
|
// if (nucleus is Cluster cluster)
|
||||||
|
// cluster.CheckInstances();
|
||||||
foundNucleus = nucleus;
|
foundNucleus = nucleus;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -524,6 +527,7 @@ namespace NanoBrain {
|
|||||||
foreach (Nucleus nucleus in this.nuclei) {
|
foreach (Nucleus nucleus in this.nuclei) {
|
||||||
if (nucleus is Cluster cluster) {
|
if (nucleus is Cluster cluster) {
|
||||||
if (cluster.name == clusterName || cluster.name == clusterName0) {
|
if (cluster.name == clusterName || cluster.name == clusterName0) {
|
||||||
|
// cluster.CheckInstances();
|
||||||
string subNucleusName = nucleusName[(dotPosition + 1)..];
|
string subNucleusName = nucleusName[(dotPosition + 1)..];
|
||||||
return cluster.GetNucleus(subNucleusName);
|
return cluster.GetNucleus(subNucleusName);
|
||||||
}
|
}
|
||||||
@ -534,9 +538,11 @@ namespace NanoBrain {
|
|||||||
else {
|
else {
|
||||||
string nucleusName0 = nucleusName + ": 0";
|
string nucleusName0 = nucleusName + ": 0";
|
||||||
foreach (Nucleus nucleus in this.nuclei) {
|
foreach (Nucleus nucleus in this.nuclei) {
|
||||||
if (nucleus is Cluster) {
|
if (nucleus is Cluster cluster) {
|
||||||
if (nucleus.name == nucleusName || nucleus.name == nucleusName0)
|
if (nucleus.name == nucleusName || nucleus.name == nucleusName0) {
|
||||||
|
// cluster.CheckInstances();
|
||||||
return nucleus;
|
return nucleus;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (nucleus.name == nucleusName)
|
else if (nucleus.name == nucleusName)
|
||||||
return nucleus;
|
return nucleus;
|
||||||
@ -574,6 +580,7 @@ namespace NanoBrain {
|
|||||||
return this.GetNeuron(neuronName);
|
return this.GetNeuron(neuronName);
|
||||||
|
|
||||||
// See if we are already using a cluster for thingId
|
// See if we are already using a cluster for thingId
|
||||||
|
thingClusters ??= new();
|
||||||
if (thingClusters.TryGetValue(thingId, out Cluster cluster))
|
if (thingClusters.TryGetValue(thingId, out Cluster cluster))
|
||||||
return cluster.GetNeuron(neuronName);
|
return cluster.GetNeuron(neuronName);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user