Skip to content

Commit

Permalink
Merge pull request #9 from AkiKurisu/dev_blackboard_component
Browse files Browse the repository at this point in the history
Dev blackboard component
  • Loading branch information
AkiKurisu authored Jul 7, 2024
2 parents 345f33b + 39b9ca5 commit 1644ed9
Show file tree
Hide file tree
Showing 22 changed files with 481 additions and 255 deletions.
12 changes: 10 additions & 2 deletions Editor/Core/Editor/BehaviorTreeEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ public override VisualElement CreateInspectorGUI()
myInspector.Add(field);
if (instance.SharedVariables.Count(x => x.IsExposed) != 0)
{
myInspector.Add(new SharedVariablesFoldout(instance, target, this));
myInspector.Add(new SharedVariablesFoldout(instance.BlackBoard, () =>
{
tree.SetBehaviorTreeData(instance.GetData());
EditorUtility.SetDirty(target);
}));
}
myInspector.Add(new BehaviorTreeDebugButton(tree));
return myInspector;
Expand Down Expand Up @@ -58,7 +62,11 @@ public override VisualElement CreateInspectorGUI()
myInspector.Add(description);
if (instance.SharedVariables.Count(x => x.IsExposed) != 0)
{
myInspector.Add(new SharedVariablesFoldout(instance, target, this));
myInspector.Add(new SharedVariablesFoldout(instance.BlackBoard, () =>
{
tree.SetBehaviorTreeData(instance.GetData());
EditorUtility.SetDirty(target);
}));
}
myInspector.Add(new BehaviorTreeDebugButton(tree));
return myInspector;
Expand Down
35 changes: 35 additions & 0 deletions Editor/Core/Editor/BlackBoardComponentEditor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace Kurisu.AkiBT.Editor
{
[CustomEditor(typeof(BlackBoardComponent))]
public class BlackBoardComponentEditor : UnityEditor.Editor
{
private AdvancedBlackBoardController controller;
public override VisualElement CreateInspectorGUI()
{
var source = target as BlackBoardComponent;
var bb = source.GetBlackBoard();
var myInspector = new VisualElement();
myInspector.style.flexDirection = FlexDirection.Column;
controller = new AdvancedBlackBoardController(bb,
new AdvancedBlackBoard.BlackBoardSettings()
{
showIsExposed = true,
showIsGlobalToggle = true,
},
() =>
{
// commit to component
source.SetBlackBoardVariables(controller.SharedVariables);
EditorUtility.SetDirty(source);
AssetDatabase.SaveAssets();
});
myInspector.Add(controller.GetBlackBoard());
if (Application.isPlaying) return myInspector;
myInspector.RegisterCallback<DetachFromPanelEvent>(_ => controller.UpdateIfDirty());
return myInspector;
}
}
}
11 changes: 11 additions & 0 deletions Editor/Core/Editor/BlackBoardComponentEditor.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

89 changes: 22 additions & 67 deletions Editor/Core/Editor/GameVariableScopeEditor.cs
Original file line number Diff line number Diff line change
@@ -1,100 +1,55 @@
using UnityEditor;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using System.Collections.Generic;
namespace Kurisu.AkiBT.Editor
{
internal class VirtualGraphView : GraphView { }
internal class VariableSourceProxy : IVariableSource
{
public List<SharedVariable> SharedVariables { get; } = new();
private readonly IVariableSource source;
private readonly Object dirtyObject;
public VariableSourceProxy(IVariableSource source, Object dirtyObject)
{
this.source = source;
this.dirtyObject = dirtyObject;
}
public void Update()
{
source.SharedVariables.Clear();
source.SharedVariables.AddRange(SharedVariables);
EditorUtility.SetDirty(dirtyObject);
AssetDatabase.SaveAssets();
}
}
[CustomEditor(typeof(GameVariableScope))]
public class GameVariableScopeEditor : UnityEditor.Editor
{
private bool isDirty;
public override VisualElement CreateInspectorGUI()
{
var source = target as GameVariableScope;
var myInspector = new VisualElement();
myInspector.style.flexDirection = FlexDirection.Column;
var proxy = new VariableSourceProxy(source, source);
//Need attached to a virtual graphView to send event
//It's an interesting hack so that you can use blackBoard outside of graphView
var blackBoard = new AdvancedBlackBoard(proxy, new VirtualGraphView()) { AlwaysExposed = true };
foreach (var variable in source.SharedVariables)
var controller = new AdvancedBlackBoardController(source,
new AdvancedBlackBoard.BlackBoardSettings()
{
//In play mode, use original variable to observe value change
if (Application.isPlaying)
{
blackBoard.AddSharedVariable(variable);
}
else
{
blackBoard.AddSharedVariable(variable.Clone());
}
}
blackBoard.style.position = Position.Relative;
blackBoard.style.width = Length.Percent(100f);
myInspector.Add(blackBoard);

autoExposed = true
},
() =>
{
EditorUtility.SetDirty(source);
AssetDatabase.SaveAssets();
});
myInspector.Add(controller.GetBlackBoard());
if (Application.isPlaying) return myInspector;

myInspector.RegisterCallback<DetachFromPanelEvent>(_ => { if (isDirty) proxy.Update(); });
blackBoard.RegisterCallback<VariableChangeEvent>(_ => isDirty = true);
myInspector.RegisterCallback<DetachFromPanelEvent>(_ => controller.UpdateIfDirty());
myInspector.Add(new PropertyField(serializedObject.FindProperty("parentScope"), "Parent Scope"));
return myInspector;
}
}
[CustomEditor(typeof(SceneVariableScope))]
public class SceneVariableScopeEditor : UnityEditor.Editor
{
private bool isDirty;
public override VisualElement CreateInspectorGUI()
{
var source = target as SceneVariableScope;
var myInspector = new VisualElement();
myInspector.style.flexDirection = FlexDirection.Column;
var proxy = new VariableSourceProxy(source, source);
//Need attached to a virtual graphView to send event
//It's an interesting hack so that you can use blackBoard outside of graphView
var blackBoard = new AdvancedBlackBoard(proxy, new VirtualGraphView()) { AlwaysExposed = true };
foreach (var variable in source.SharedVariables)
var controller = new AdvancedBlackBoardController(source,
new AdvancedBlackBoard.BlackBoardSettings()
{
autoExposed = true
},
() =>
{
//In play mode, use original variable to observe value change
if (Application.isPlaying)
{
blackBoard.AddSharedVariable(variable);
}
else
{
blackBoard.AddSharedVariable(variable.Clone());
}
}
blackBoard.style.position = Position.Relative;
blackBoard.style.width = Length.Percent(100f);
myInspector.Add(blackBoard);

EditorUtility.SetDirty(source);
AssetDatabase.SaveAssets();
});
myInspector.Add(controller.GetBlackBoard());
if (Application.isPlaying) return myInspector;

myInspector.RegisterCallback<DetachFromPanelEvent>(_ => { if (isDirty) proxy.Update(); });
blackBoard.RegisterCallback<VariableChangeEvent>(_ => isDirty = true);
myInspector.RegisterCallback<DetachFromPanelEvent>(_ => controller.UpdateIfDirty());
myInspector.Add(new PropertyField(serializedObject.FindProperty("parentScope"), "Parent Scope"));
return myInspector;
}
Expand Down
47 changes: 42 additions & 5 deletions Editor/Core/GraphView/AdvancedBlackBoard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,31 @@ namespace Kurisu.AkiBT.Editor
{
public class AdvancedBlackBoard : Blackboard, IBlackBoard
{
public struct BlackBoardSettings
{
/// <summary>
/// Show IsExposed toggle for shared variable
/// </summary>
public bool showIsExposed;
/// <summary>
/// Automatically set IsExposed for variables
/// </summary>
public bool autoExposed;
/// <summary>
/// Show IsGlobal toggle for shared variable
/// </summary>
public bool showIsGlobalToggle;
}
public Blackboard View => this;
public bool AlwaysExposed { get; set; }
public BlackBoardSettings settings;
private readonly FieldResolverFactory fieldResolverFactory = FieldResolverFactory.Instance;
private readonly ScrollView scrollView;
public VisualElement RawContainer => scrollView;
private readonly List<SharedVariable> sharedVariables;
private readonly HashSet<ObserveProxyVariable> observeProxies = new();
public AdvancedBlackBoard(IVariableSource variableSource, GraphView graphView) : base(graphView)
private readonly HashSet<ObservableVariable> observeProxies = new();
public AdvancedBlackBoard(IVariableSource variableSource, GraphView graphView, BlackBoardSettings settings = default) : base(graphView)
{
this.settings = settings;
var header = this.Q("header");
header.style.height = new StyleLength(50);
Add(scrollView = new());
Expand Down Expand Up @@ -94,7 +110,7 @@ public void AddSharedVariable(SharedVariable variable)
localPropertyName = $"{variable.Name}{index++}";
}
variable.Name = localPropertyName;
if (AlwaysExposed) variable.IsExposed = true;
if (settings.autoExposed) variable.IsExposed = true;
sharedVariables.Add(variable);
var container = new VisualElement();
var field = new BlackboardField { text = localPropertyName, typeText = variable.GetType().Name };
Expand Down Expand Up @@ -128,7 +144,7 @@ public void AddSharedVariable(SharedVariable variable)
}
}
var placeHolder = new VisualElement();
if (!AlwaysExposed)
if (settings.showIsExposed)
{
var toggle = new Toggle("Exposed")
{
Expand All @@ -149,6 +165,27 @@ public void AddSharedVariable(SharedVariable variable)
}
placeHolder.Add(toggle);
}
if (settings.showIsGlobalToggle)
{
var toggle = new Toggle("Global")
{
value = variable.IsGlobal
};
if (Application.isPlaying)
{
toggle.SetEnabled(false);
}
else
{
toggle.RegisterValueChangedCallback(x =>
{
var index = sharedVariables.FindIndex(x => x.Name == variable.Name);
sharedVariables[index].IsGlobal = x.newValue;
NotifyVariableChanged(variable, VariableChangeType.ValueChange);
});
}
placeHolder.Add(toggle);
}
placeHolder.Add(valueField);
if (variable is SharedObject sharedObject)
{
Expand Down
53 changes: 53 additions & 0 deletions Editor/Core/GraphView/AdvancedBlackBoardController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using UnityEngine.UIElements;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using System.Collections.Generic;
namespace Kurisu.AkiBT.Editor
{
internal class AdvancedBlackBoardController : IVariableSource
{
private class VirtualGraphView : GraphView { }
private readonly AdvancedBlackBoard blackBoard;
public List<SharedVariable> SharedVariables { get; } = new();
private readonly IVariableSource source;
private bool isDirty;
private readonly System.Action onUpdate;
public AdvancedBlackBoardController(IVariableSource source, AdvancedBlackBoard.BlackBoardSettings settings = default, System.Action onUpdate = null)
{
this.source = source;
this.onUpdate = onUpdate;
//Need attached to a virtual graphView to send event
//It's an interesting hack so that you can use blackBoard outside of graphView
blackBoard = new AdvancedBlackBoard(this, new VirtualGraphView(), settings);
blackBoard.style.position = Position.Relative;
blackBoard.style.width = Length.Percent(100f);
foreach (var variable in source.SharedVariables)
{
if (Application.isPlaying)
{
blackBoard.AddSharedVariable(variable);
}
else
{
blackBoard.AddSharedVariable(variable.Clone());
}
}
blackBoard.RegisterCallback<VariableChangeEvent>(_ => isDirty = true);
}
public AdvancedBlackBoard GetBlackBoard() => blackBoard;
public void Update()
{
source.SharedVariables.Clear();
source.SharedVariables.AddRange(SharedVariables);
onUpdate?.Invoke();
}
public void UpdateIfDirty()
{
if (isDirty)
{
Update();
isDirty = false;
}
}
}
}
11 changes: 11 additions & 0 deletions Editor/Core/GraphView/AdvancedBlackBoardController.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion Editor/Core/GraphView/BehaviorTreeView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ private void RegisterSerializationCallBack()
}
private void AddBlackBoard()
{
var blackboard = new AdvancedBlackBoard(this, View);
var blackboard = new AdvancedBlackBoard(this, View, new AdvancedBlackBoard.BlackBoardSettings()
{
showIsExposed = true,
showIsGlobalToggle = true,
});
blackboard.SetPosition(new Rect(10, 100, 300, 400));
Add(blackboard);
BlackBoard = blackboard;
Expand Down
Loading

0 comments on commit 1644ed9

Please sign in to comment.