// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using FlaxEditor.Gizmo;
using FlaxEditor.GUI.Tree;
using FlaxEditor.SceneGraph;
using FlaxEditor.SceneGraph.GUI;
using FlaxEditor.Viewport.Cameras;
using FlaxEngine;
namespace FlaxEditor.Windows.Assets
{
public sealed partial class PrefabWindow
{
///
/// The current selection (readonly).
///
public readonly List Selection = new List();
///
/// Occurs when selection gets changed.
///
public event Action SelectionChanged;
private void OnTreeSelectedChanged(List before, List after)
{
// Check if lock events
if (_isUpdatingSelection)
return;
if (after.Count > 0)
{
// Get actors from nodes
var actors = new List(after.Count);
for (int i = 0; i < after.Count; i++)
{
if (after[i] is ActorTreeNode node && node.Actor)
actors.Add(node.ActorNode);
}
// Select
Select(actors);
}
else
{
// Deselect
Deselect();
}
}
///
/// Called when selection gets changed.
///
/// The selection before the change.
public void OnSelectionChanged(SceneGraphNode[] before)
{
Undo.AddAction(new SelectionChangeAction(before, Selection.ToArray(), OnSelectionUndo));
OnSelectionChanges();
}
private void OnSelectionUndo(SceneGraphNode[] toSelect)
{
Selection.Clear();
Selection.AddRange(toSelect);
OnSelectionChanges();
}
private void OnSelectionChanges()
{
_isUpdatingSelection = true;
// Update tree
var selection = Selection;
if (selection.Count == 0)
{
_tree.Deselect();
}
else
{
// Find nodes to select
var nodes = new List(selection.Count);
for (int i = 0; i < selection.Count; i++)
{
if (selection[i] is ActorNode node)
{
nodes.Add(node.TreeNode);
}
}
// Select nodes
_tree.Select(nodes);
// For single node selected scroll view so user can see it
if (nodes.Count == 1)
{
nodes[0].ExpandAllParents(true);
ScrollViewTo(nodes[0]);
}
}
// Update properties editor
var objects = Selection.ConvertAll(x => x.EditableObject).Distinct();
_propertiesEditor.Select(objects);
_isUpdatingSelection = false;
// Send event
SelectionChanged?.Invoke();
}
///
/// Selects the specified nodes collection.
///
/// The nodes.
public void Select(List nodes)
{
if (nodes == null || nodes.Count == 0)
{
Deselect();
return;
}
if (Utils.ArraysEqual(Selection, nodes))
return;
var before = Selection.ToArray();
Selection.Clear();
Selection.AddRange(nodes);
OnSelectionChanged(before);
}
///
/// Selects the specified node.
///
/// The node.
/// if set to true will use additive mode, otherwise will clear previous selection.
public void Select(SceneGraphNode node, bool additive = false)
{
if (node == null)
{
Deselect();
return;
}
// Check if won't change
if (!additive && Selection.Count == 1 && Selection[0] == node)
return;
if (additive && Selection.Contains(node))
return;
var before = Selection.ToArray();
if (!additive)
Selection.Clear();
Selection.Add(node);
OnSelectionChanged(before);
}
///
/// Deselects the specified node.
///
public void Deselect(SceneGraphNode node)
{
if (!Selection.Contains(node))
return;
var before = Selection.ToArray();
Selection.Remove(node);
OnSelectionChanged(before);
}
///
/// Clears the selection.
///
public void Deselect()
{
if (Selection.Count == 0)
return;
var before = Selection.ToArray();
Selection.Clear();
OnSelectionChanged(before);
}
}
}