Cover seeking(-ish) behaviour

This commit is contained in:
Pascal Serrarens 2026-04-15 12:23:52 +02:00
parent 1c7b8e7940
commit 0023920ffa
4 changed files with 58 additions and 31 deletions

View File

@ -14,13 +14,11 @@ namespace NanoBrain {
protected Brain component; protected Brain component;
private SerializedProperty brainProp; private SerializedProperty brainProp;
//ClusterInspector.GraphView board;
public void OnEnable() { public void OnEnable() {
component = target as Brain; component = target as Brain;
if (Application.isPlaying == false && serializedObject != null) { if (Application.isPlaying == false && serializedObject != null) {
string propertyName = nameof(Brain.defaultBrain); string propertyName = nameof(Brain.brainPrefab);
brainProp = serializedObject.FindProperty(propertyName); brainProp = serializedObject.FindProperty(propertyName);
} }
} }
@ -32,13 +30,22 @@ namespace NanoBrain {
serializedObject.Update(); serializedObject.Update();
VisualElement root = new(); VisualElement root = new() {
if (Application.isPlaying == false) { style = {
paddingLeft = 0,
paddingRight = 0,
paddingTop = 0,
paddingBottom = 0
}
};
root.styleSheets.Add(Resources.Load<StyleSheet>("GraphStyles"));
//if (Application.isPlaying == false) {
PropertyField brainField = new(brainProp) { PropertyField brainField = new(brainProp) {
label = "Cluster Prefab" label = "Cluster Prefab"
}; };
root.Add(brainField); root.Add(brainField);
} //}
if (brain != null) if (brain != null)
CreateViewer(root, brain.prefab, brain.defaultOutput, component.gameObject); CreateViewer(root, brain.prefab, brain.defaultOutput, component.gameObject);
@ -49,13 +56,6 @@ namespace NanoBrain {
} }
public static ClusterViewer.GraphView CreateViewer(VisualElement root, ClusterPrefab cluster, Nucleus output, GameObject gameObject) { public static ClusterViewer.GraphView CreateViewer(VisualElement root, ClusterPrefab cluster, Nucleus output, GameObject gameObject) {
root.style.paddingLeft = 0;
root.style.paddingRight = 0;
root.style.paddingTop = 0;
root.style.paddingBottom = 0;
root.styleSheets.Add(Resources.Load<StyleSheet>("GraphStyles"));
VisualElement mainContainer = new() { VisualElement mainContainer = new() {
style = { style = {
flexDirection = FlexDirection.Row, flexDirection = FlexDirection.Row,

View File

@ -316,7 +316,7 @@ namespace NanoBrain {
EditorGUILayout.CurveField(neuron.curve, Color.cyan, new Rect(0, 0, 1, neuron.curveMax)); EditorGUILayout.CurveField(neuron.curve, Color.cyan, new Rect(0, 0, 1, neuron.curveMax));
else else
EditorGUILayout.CurveField(neuron.curve, Color.cyan, new Rect(0, neuron.curveMax, 1, -neuron.curveMax)); EditorGUILayout.CurveField(neuron.curve, Color.cyan, new Rect(0, neuron.curveMax, 1, -neuron.curveMax));
Neuron.ActivationFunction newPreset = (Neuron.ActivationFunction)EditorGUILayout.EnumPopup(neuron.curvePreset, GUILayout.Width(100)); Neuron.ActivationType newPreset = (Neuron.ActivationType)EditorGUILayout.EnumPopup(neuron.curvePreset, GUILayout.Width(100));
anythingChanged |= newPreset != neuron.curvePreset; anythingChanged |= newPreset != neuron.curvePreset;
neuron.curvePreset = newPreset; neuron.curvePreset = newPreset;
EditorGUILayout.EndHorizontal(); EditorGUILayout.EndHorizontal();

View File

@ -11,7 +11,7 @@ namespace NanoBrain {
/// <summary> /// <summary>
/// The Cluster prefab from which the cluster is created /// The Cluster prefab from which the cluster is created
/// </summary> /// </summary>
public ClusterPrefab defaultBrain; public ClusterPrefab brainPrefab;
[NonSerialized] [NonSerialized]
private Cluster brainInstance; private Cluster brainInstance;
@ -20,10 +20,12 @@ namespace NanoBrain {
/// </summary> /// </summary>
public Cluster brain { public Cluster brain {
get { get {
if (brainInstance == null && defaultBrain != null) { if (brainInstance == null && brainPrefab != null) {
brainInstance = new Cluster(defaultBrain) { brainInstance = new Cluster(brainPrefab) {
name = defaultBrain.name + " (Instance)" name = brainPrefab.name + " (Instance)"
}; };
} else if (brainInstance != null && brainPrefab == null) {
brainInstance = null;
} }
return brainInstance; return brainInstance;
} }

View File

@ -61,17 +61,19 @@ namespace NanoBrain {
/// <summary> /// <summary>
/// The type of /// The type of
/// </summary> /// </summary>
public enum ActivationFunction { public enum ActivationType {
Linear, Linear,
Power, Power,
Sqrt, Sqrt,
Reciprocal, Reciprocal,
Tanh, Tanh,
Binary,
Normalized,
Custom Custom
} }
[SerializeField] [SerializeField]
public ActivationFunction _curvePreset; public ActivationType _curvePreset;
public ActivationFunction curvePreset { public ActivationType curvePreset {
get { return _curvePreset; } get { return _curvePreset; }
set { set {
_curvePreset = value; _curvePreset = value;
@ -83,21 +85,27 @@ namespace NanoBrain {
public AnimationCurve GenerateCurve() { public AnimationCurve GenerateCurve() {
switch (this.curvePreset) { switch (this.curvePreset) {
case ActivationFunction.Linear: case ActivationType.Linear:
this.curveMax = 1; this.curveMax = 1;
return Presets.Linear(1); return Presets.Linear(1);
case ActivationFunction.Power: case ActivationType.Power:
this.curveMax = 1; this.curveMax = 1;
return Presets.Power(2.0f, 1); return Presets.Power(2.0f, 1);
case ActivationFunction.Sqrt: case ActivationType.Sqrt:
this.curveMax = 1; this.curveMax = 1;
return Presets.Power(0.5f, 1); return Presets.Power(0.5f, 1);
case ActivationFunction.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 ActivationFunction.Tanh: case ActivationType.Tanh:
this.curveMax = 1; this.curveMax = 1;
return Presets.Tanh(1); return Presets.Tanh(1);
case ActivationType.Binary:
this.curveMax = 1;
return Presets.Binary();
case ActivationType.Normalized:
this.curveMax = 1;
return Presets.Binary();
default: default:
this.curveMax = 1; this.curveMax = 1;
return this.curve; return this.curve;
@ -165,6 +173,9 @@ namespace NanoBrain {
return curve; return curve;
} }
public static AnimationCurve Binary() {
return AnimationCurve.Linear(0, 0, 1, 1);
}
} }
#endregion Serialization #endregion Serialization
@ -371,11 +382,13 @@ namespace NanoBrain {
#if UNITY_MATHEMATICS #if UNITY_MATHEMATICS
public Func<float3, float3> Activator => this.curvePreset switch { public Func<float3, float3> Activator => this.curvePreset switch {
ActivationFunction.Linear => ActivatorLinear, ActivationType.Linear => ActivatorLinear,
ActivationFunction.Sqrt => ActivatorSqrt, ActivationType.Sqrt => ActivatorSqrt,
ActivationFunction.Power => ActivatorPower, ActivationType.Power => ActivatorPower,
ActivationFunction.Reciprocal => ActivatorReciprocal, ActivationType.Reciprocal => ActivatorReciprocal,
ActivationFunction.Tanh => ActivatorTanh, ActivationType.Tanh => ActivatorTanh,
ActivationType.Binary => ActivatorBinary,
ActivationType.Normalized => ActivatorNormalized,
_ => ActivatorCustom _ => ActivatorCustom
}; };
@ -407,6 +420,18 @@ namespace NanoBrain {
float3 result = normalize(input) * MathF.Tanh(magnitude); float3 result = normalize(input) * MathF.Tanh(magnitude);
return result; return result;
} }
protected float3 ActivatorBinary(float3 input) {
float magnitude = length(input);
float value = Mathf.Clamp01(magnitude);
return float3(value, value, value);
}
protected float3 ActivatorNormalized(float3 input) {
if (lengthsq(input) == 0)
return input;
float3 result = normalize(input);
return result;
}
protected float3 ActivatorCustom(float3 input) { protected float3 ActivatorCustom(float3 input) {
float activatedValue = this.curve.Evaluate(length(input)); float activatedValue = this.curve.Evaluate(length(input));