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