rokojori_action_library/Runtime/Actions/Node3D/SelectNode3D.cs

141 lines
2.8 KiB
C#

using Godot;
using System.Collections.Generic;
using System.Reflection;
using Rokojori.Extensions;
namespace Rokojori
{
[GlobalClass, Tool ]
public partial class SelectNode3D : Action
{
[Export]
public Selector selector;
bool _enteredTree = false;
public override void _EnterTree()
{
base._EnterTree();
_enteredTree = true;
}
Node _target;
[Export]
public Node target
{
get => _target;
set
{
if ( _target == value )
{
return;
}
_target = value;
// Deserialization sets exported properties before _EnterTree fires, so this
// only triggers for genuine interactive edits in the editor, never for a scene
// being loaded (regardless of property order) or for runtime reassignment.
if ( _enteredTree && Engine.IsEditorHint() )
{
targetMember = "";
#if TOOLS
NotifyPropertyListChanged();
#endif
}
}
}
[Export]
public string targetMember;
protected override void _OnTrigger()
{
if ( target == null )
{
return;
}
Node3D node3D = null;
if ( selector == null )
{
ReflectionHelper.SetValue<Node3D>( target, targetMember, node3D );
this.LogInfo( "Set Null:", HierarchyName.Of( target ), targetMember );
return;
}
var selectedNode = Unique<SelectManager>.Get().Select( selector );
if ( selectedNode is Selectable )
{
var go = selectedNode.GetParent<GameObject3D>();
if ( go != null )
{
node3D = go.body;
}
}
ReflectionHelper.SetValue<Node3D>( target, targetMember, node3D );
}
#if TOOLS
public override void _ValidateProperty( Godot.Collections.Dictionary property )
{
if ( property[ "name" ].AsString() != nameof( targetMember ) )
{
return;
}
var members = GetTargetNode3DMemberNames();
property[ "hint" ] = (long) PropertyHint.Enum;
property[ "hint_string" ] = members.Count == 0
? "(Invalid Target)"
: "None," + string.Join( ",", members );
}
List<string> GetTargetNode3DMemberNames()
{
var names = new List<string>();
if ( target == null )
{
return names;
}
var infos = ReflectionHelper.GetDataMemberInfos( target, BindingFlags.Public | BindingFlags.Instance );
foreach ( var info in infos )
{
if ( ! info.IsDefined( typeof( ExportAttribute ) ) )
{
continue;
}
var memberType = info.GetMemberType();
if ( memberType == null || ! memberType.IsAssignableFrom( typeof( Node3D ) ) )
{
continue;
}
names.Add( info.Name );
}
return names;
}
#endif
}
}