// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using System.Xml;
using FlaxEditor.Content;
using FlaxEditor.CustomEditors;
using FlaxEditor.GUI;
using FlaxEditor.SceneGraph;
using FlaxEditor.Scripting;
using FlaxEditor.Surface;
using FlaxEditor.Viewport;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Utilities;
namespace FlaxEditor.Windows.Assets
{
///
/// Behavior Tree window allows to view and edit asset.
///
///
///
public sealed class BehaviorTreeWindow : AssetEditorWindowBase, IVisjectSurfaceWindow, IPresenterOwner
{
private readonly SplitPanel _split1;
private readonly SplitPanel _split2;
private CustomEditorPresenter _nodePropertiesEditor;
private CustomEditorPresenter _knowledgePropertiesEditor;
private BehaviorTreeSurface _surface;
private Undo _undo;
private readonly ToolStripButton _saveButton;
private readonly ToolStripButton _undoButton;
private readonly ToolStripButton _redoButton;
private bool _showWholeGraphOnLoad = true;
private bool _isWaitingForSurfaceLoad;
private bool _canEdit = true;
///
/// Gets the Visject Surface.
///
public BehaviorTreeSurface Surface => _surface;
///
/// Gets the undo history context for this window.
///
public Undo Undo => _undo;
///
/// Current instance of the Behavior Knowledge's blackboard type or null.
///
public object Blackboard => _knowledgePropertiesEditor.Selection.Count != 0 ? _knowledgePropertiesEditor.Selection[0] : null;
///
public BehaviorTreeWindow(Editor editor, BinaryAssetItem item)
: base(editor, item)
{
var isPlayMode = Editor.IsPlayMode;
// Undo
_undo = new Undo();
_undo.UndoDone += OnUndoRedo;
_undo.RedoDone += OnUndoRedo;
_undo.ActionDone += OnUndoAction;
// Split Panels
_split1 = new SplitPanel(Orientation.Horizontal, ScrollBars.None, ScrollBars.None)
{
AnchorPreset = AnchorPresets.StretchAll,
Offsets = new Margin(0, 0, _toolstrip.Bottom, 0),
SplitterValue = 0.7f,
Parent = this
};
_split2 = new SplitPanel(Orientation.Vertical, ScrollBars.Vertical, ScrollBars.Vertical)
{
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
SplitterValue = 0.5f,
Parent = _split1.Panel2
};
// Surface
_surface = new BehaviorTreeSurface(this, Save, _undo)
{
Parent = _split1.Panel1,
Enabled = false
};
_surface.SelectionChanged += OnNodeSelectionChanged;
// Properties editors
_nodePropertiesEditor = new CustomEditorPresenter(null, null, this); // Surface handles undo for nodes editing
_nodePropertiesEditor.Features = FeatureFlags.UseDefault;
_nodePropertiesEditor.Panel.Parent = _split2.Panel1;
_nodePropertiesEditor.Modified += OnNodePropertyEdited;
_knowledgePropertiesEditor = new CustomEditorPresenter(null, "No blackboard type assigned", this); // No undo for knowledge editing
_knowledgePropertiesEditor.Features = FeatureFlags.None;
_knowledgePropertiesEditor.Panel.Parent = _split2.Panel2;
// Toolstrip
_saveButton = (ToolStripButton)_toolstrip.AddButton(Editor.Icons.Save64, Save).LinkTooltip("Save");
_toolstrip.AddSeparator();
_undoButton = (ToolStripButton)_toolstrip.AddButton(Editor.Icons.Undo64, _undo.PerformUndo).LinkTooltip("Undo (Ctrl+Z)");
_redoButton = (ToolStripButton)_toolstrip.AddButton(Editor.Icons.Redo64, _undo.PerformRedo).LinkTooltip("Redo (Ctrl+Y)");
_toolstrip.AddSeparator();
_toolstrip.AddButton(Editor.Icons.Search64, Editor.ContentFinding.ShowSearch).LinkTooltip("Open content search tool (Ctrl+F)");
_toolstrip.AddButton(editor.Icons.CenterView64, _surface.ShowWholeGraph).LinkTooltip("Show whole graph");
// Setup input actions
InputActions.Add(options => options.Undo, _undo.PerformUndo);
InputActions.Add(options => options.Redo, _undo.PerformRedo);
InputActions.Add(options => options.Search, Editor.ContentFinding.ShowSearch);
SetCanEdit(!isPlayMode);
}
private void OnUndoRedo(IUndoAction action)
{
MarkAsEdited();
UpdateToolstrip();
_nodePropertiesEditor.BuildLayoutOnUpdate();
}
private void OnUndoAction(IUndoAction action)
{
MarkAsEdited();
UpdateToolstrip();
}
private void OnNodeSelectionChanged()
{
// Select node instances to view/edit
var selection = new List