128 lines
4.1 KiB
C#
128 lines
4.1 KiB
C#
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using FlaxEngine;
|
|
|
|
namespace FlaxEditor.Surface.Elements
|
|
{
|
|
/// <summary>
|
|
/// The Visject surface node element used to pick a skeleton node name with a combo box.
|
|
/// </summary>
|
|
[HideInEditor]
|
|
public class SkeletonNodeNameSelectElement : ComboBoxElement
|
|
{
|
|
private readonly Dictionary<string, int> _nodeNameToIndex = new Dictionary<string, int>();
|
|
|
|
/// <summary>
|
|
/// Gets or sets the name of the selected node.
|
|
/// </summary>
|
|
public string SelectedNodeName
|
|
{
|
|
get
|
|
{
|
|
var selectedIndex = SelectedIndex;
|
|
foreach (var e in _nodeNameToIndex)
|
|
{
|
|
if (e.Value == selectedIndex)
|
|
return e.Key;
|
|
}
|
|
return string.Empty;
|
|
}
|
|
set
|
|
{
|
|
if (!string.IsNullOrEmpty(value) && _nodeNameToIndex.TryGetValue(value, out var index))
|
|
SelectedIndex = index;
|
|
else
|
|
SelectedIndex = -1;
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public SkeletonNodeNameSelectElement(SurfaceNode parentNode, NodeElementArchetype archetype)
|
|
: base(parentNode, archetype)
|
|
{
|
|
_isAutoSelect = true;
|
|
|
|
if (Surface == null)
|
|
return;
|
|
UpdateComboBox();
|
|
|
|
// Select saved value
|
|
_selectedIndices.Clear();
|
|
if (Archetype.ValueIndex != -1)
|
|
{
|
|
SelectedNodeName = (string)ParentNode.Values[Archetype.ValueIndex];
|
|
ParentNode.ValuesChanged += OnNodeValuesChanged;
|
|
}
|
|
}
|
|
|
|
private void OnNodeValuesChanged()
|
|
{
|
|
_selectedIndices.Clear();
|
|
var selectedNode = (string)ParentNode.Values[Archetype.ValueIndex];
|
|
if (!string.IsNullOrEmpty(selectedNode) && _nodeNameToIndex.TryGetValue(selectedNode, out var index))
|
|
_selectedIndices.Add(index);
|
|
OnSelectedIndexChanged();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the Combo Box items list from the current skeleton nodes hierarchy.
|
|
/// </summary>
|
|
protected void UpdateComboBox()
|
|
{
|
|
// Prepare
|
|
var selectedNode = SelectedNodeName;
|
|
_items.Clear();
|
|
_nodeNameToIndex.Clear();
|
|
|
|
// Get the skeleton
|
|
var surfaceParam = Surface.GetParameter(Windows.Assets.AnimationGraphWindow.BaseModelId);
|
|
var skeleton = surfaceParam != null ? FlaxEngine.Content.LoadAsync<SkinnedModel>((Guid)surfaceParam.Value) : null;
|
|
if (skeleton == null || skeleton.WaitForLoaded())
|
|
{
|
|
SelectedIndex = -1;
|
|
return;
|
|
}
|
|
|
|
// Update the items
|
|
var nodes = skeleton.Nodes;
|
|
_items.Capacity = Mathf.Max(_items.Capacity, nodes.Length);
|
|
var sb = new StringBuilder(64);
|
|
for (int nodeIndex = 0; nodeIndex < nodes.Length; nodeIndex++)
|
|
{
|
|
sb.Clear();
|
|
var node = nodes[nodeIndex];
|
|
_nodeNameToIndex[node.Name] = nodeIndex;
|
|
int parent = node.ParentIndex;
|
|
while (parent != -1)
|
|
{
|
|
sb.Append(" ");
|
|
parent = nodes[parent].ParentIndex;
|
|
}
|
|
|
|
sb.Append("> ");
|
|
sb.Append(node.Name);
|
|
|
|
_items.Add(sb.ToString());
|
|
}
|
|
|
|
// Restore the selected node
|
|
SelectedNodeName = selectedNode;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override void OnSelectedIndexChanged()
|
|
{
|
|
if ((string)ParentNode.Values[Archetype.ValueIndex] != SelectedNodeName)
|
|
{
|
|
// Edit value
|
|
ParentNode.SetValue(Archetype.ValueIndex, SelectedNodeName);
|
|
}
|
|
|
|
//base.OnSelectedIndexChanged();
|
|
}
|
|
}
|
|
}
|