420 lines
8.4 KiB
C#
420 lines
8.4 KiB
C#
using Godot;
|
|
|
|
using System.Collections.Generic;
|
|
using System;
|
|
|
|
namespace Rokojori
|
|
{
|
|
public static class Nodes
|
|
{
|
|
public static T Find<T>( Node root, NodePathLocatorType type = NodePathLocatorType.DirectChildren, int parentOffset = 0 ) where T:Node
|
|
{
|
|
var it = root;
|
|
|
|
while ( parentOffset > 0 && it != null )
|
|
{
|
|
it = it.GetParent();
|
|
parentOffset --;
|
|
}
|
|
|
|
if ( it == null )
|
|
{
|
|
return default(T);
|
|
}
|
|
|
|
switch ( type )
|
|
{
|
|
case NodePathLocatorType.DirectChildren:
|
|
{
|
|
return GetDirectChild<T>( it );
|
|
}
|
|
|
|
case NodePathLocatorType.Siblings:
|
|
{
|
|
return GetSibling<T>( it );
|
|
}
|
|
|
|
case NodePathLocatorType.DirectChildrenAndSiblings:
|
|
{
|
|
var child = GetDirectChild<T>( it );
|
|
|
|
if ( child != null )
|
|
{
|
|
return child;
|
|
}
|
|
|
|
return GetSibling<T>( it );
|
|
}
|
|
|
|
case NodePathLocatorType.AnyChildren:
|
|
{
|
|
return GetAnyChild<T>( it );
|
|
}
|
|
|
|
case NodePathLocatorType.SiblingsAndAnyChildren:
|
|
{
|
|
var sibling = GetSibling<T>( it );
|
|
|
|
if ( sibling != null )
|
|
{
|
|
return sibling;
|
|
}
|
|
|
|
return GetAnyChild<T>( it );;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
return default(T);
|
|
}
|
|
|
|
public static void ForEachInScene<T>( Action<T> callback ) where T:class
|
|
{
|
|
var root = Root.Get().GetWindow();
|
|
ForEach<T>( root, callback );
|
|
}
|
|
|
|
|
|
|
|
public static List<T> AllInScene<T>( Func<T,bool> filter = null) where T:class
|
|
{
|
|
var list = new List<T>();
|
|
ForEachInScene<T>(
|
|
t =>
|
|
{
|
|
if ( filter == null || filter( t ) )
|
|
{
|
|
list.Add( t );
|
|
}
|
|
}
|
|
);
|
|
|
|
return list;
|
|
}
|
|
|
|
public static List<T> AllIn<T>( Node root, Func<T,bool> filter = null, bool includeRoot = true) where T:class
|
|
{
|
|
var list = new List<T>();
|
|
ForEach<T>( root,
|
|
t =>
|
|
{
|
|
if ( ! includeRoot && t == root )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( filter == null || filter( t ) )
|
|
{
|
|
list.Add( t );
|
|
}
|
|
}
|
|
);
|
|
|
|
return list;
|
|
}
|
|
|
|
public static void ForEach<T>( Node root, Action<T> callback ) where T:class
|
|
{
|
|
var walker = nodesWalker;
|
|
|
|
walker.Iterate( root,
|
|
( n )=>
|
|
{
|
|
var t = n as T;
|
|
|
|
if ( t == null )
|
|
{
|
|
return;
|
|
}
|
|
|
|
callback( t );
|
|
|
|
}
|
|
,false );
|
|
}
|
|
|
|
public static T GetSibling<T>( Node node ) where T:Node
|
|
{
|
|
if ( node == null )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var parent = node.GetParent();
|
|
|
|
if ( parent == null )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return GetDirectChild<T>( parent );
|
|
}
|
|
|
|
public static T CreateChildIn<T>( Node parent, string name = null ) where T:Node,new()
|
|
{
|
|
var t = new T();
|
|
parent.AddChild( t );
|
|
|
|
t.Owner = parent.Owner;
|
|
|
|
if ( name != null )
|
|
{
|
|
t.Name = name;
|
|
}
|
|
|
|
return t;
|
|
}
|
|
|
|
public static T CreateChild<T>( this Node parent, string name = null ) where T:Node,new()
|
|
{
|
|
return CreateChildIn<T>( parent, name );
|
|
}
|
|
|
|
public static Node CopyNode( Node node, Node parent )
|
|
{
|
|
var copy = node.Duplicate();
|
|
|
|
parent.AddChild( copy );
|
|
copy.Owner = parent.Owner;
|
|
|
|
return copy;
|
|
}
|
|
|
|
public static Node DeepCopyTo( this Node node, Node parent )
|
|
{
|
|
return CopyNodeHierarchy( node, parent );
|
|
}
|
|
|
|
public static Node CopyNodeHierarchy( Node from, Node parent )
|
|
{
|
|
var copy = CopyNode( from, parent );
|
|
|
|
for ( int i = 0; i < from.GetChildCount(); i++ )
|
|
{
|
|
var child = from.GetChild( i );
|
|
CopyNodeHierarchy( child, copy );
|
|
}
|
|
|
|
return copy;
|
|
}
|
|
|
|
public static void RemoveAndDelete( Node node )
|
|
{
|
|
var parent = node.GetParent();
|
|
|
|
if ( parent != null )
|
|
{
|
|
parent.RemoveChild( node );
|
|
}
|
|
|
|
node.QueueFree();
|
|
}
|
|
|
|
public static void RemoveAndDeleteAll<N>( List<N> nodes ) where N:Node
|
|
{
|
|
nodes.ForEach( n => RemoveAndDelete( n ) );
|
|
}
|
|
|
|
public static void RemoveAndDeleteChildrenOfType<T>( Node parent, bool includeInternal = false ) where T:Node
|
|
{
|
|
if ( parent == null )
|
|
{
|
|
return;
|
|
}
|
|
|
|
var numChildren = parent.GetChildCount( includeInternal );
|
|
|
|
for ( int i = numChildren - 1; i >= 0; i-- )
|
|
{
|
|
var node = parent.GetChild( i, includeInternal );
|
|
|
|
var t = node as T;
|
|
|
|
if ( t == null )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
parent.RemoveChild( node );
|
|
node.QueueFree();
|
|
}
|
|
}
|
|
|
|
|
|
public static void RemoveAndDeleteChildren( Node parent, bool includeInternal = false )
|
|
{
|
|
if ( parent == null )
|
|
{
|
|
return;
|
|
}
|
|
|
|
var numChildren = parent.GetChildCount( includeInternal );
|
|
|
|
for ( int i = numChildren - 1; i >= 0; i-- )
|
|
{
|
|
var node = parent.GetChild( i, includeInternal );
|
|
parent.RemoveChild( node );
|
|
node.QueueFree();
|
|
}
|
|
}
|
|
|
|
public static T GetDirectChild<T>( Node parent ) where T:Node
|
|
{
|
|
if ( parent == null )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var numChildren = parent.GetChildCount();
|
|
|
|
for ( int i = 0; i < numChildren; i++ )
|
|
{
|
|
var node = parent.GetChild( i );
|
|
|
|
if ( node is T )
|
|
{
|
|
return (T) node;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public static List<T> GetDirectChildren<T>( Node parent ) where T:Node
|
|
{
|
|
if ( parent == null )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var list = new List<T>();
|
|
|
|
var numChildren = parent.GetChildCount();
|
|
|
|
for ( int i = 0; i < numChildren; i++ )
|
|
{
|
|
var node = parent.GetChild( i );
|
|
var script = node.GetScript();
|
|
|
|
// RJLog.Log( "Node is", typeof(T), node.Name, node.GetType(), script.GetType(), ">>", ( node is T ) );
|
|
|
|
|
|
if ( ! ( node is T ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
list.Add( node as T );
|
|
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
public static void ForEachDirectChild<T>( Node parent, System.Action<T> action ) where T:Node
|
|
{
|
|
if ( parent == null || action == null )
|
|
{
|
|
return;
|
|
}
|
|
|
|
var numChildren = parent.GetChildCount();
|
|
|
|
for ( int i = 0; i < numChildren; i++ )
|
|
{
|
|
var node = parent.GetChild( i );
|
|
|
|
if ( ! ( node is T ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
action( node as T );
|
|
}
|
|
}
|
|
|
|
public static List<U> MapDirectChildren<T,U>( Node parent, System.Func<T,U> mapper ) where T:Node
|
|
{
|
|
var list = new List<U>();
|
|
|
|
ForEachDirectChild<T>( parent, c => list.Add( mapper( c ) ) );
|
|
|
|
return list;
|
|
}
|
|
|
|
public static int TypeIndex<T>( Node parent, T child ) where T:Node
|
|
{
|
|
var counter = 0;
|
|
|
|
var numChildren = parent.GetChildCount();
|
|
|
|
for ( int i = 0; i < numChildren; i++ )
|
|
{
|
|
var node = parent.GetChild( i );
|
|
|
|
if ( node is T )
|
|
{
|
|
if ( node == child )
|
|
{
|
|
return counter;
|
|
}
|
|
|
|
counter++;
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static NodesWalker nodesWalker = new NodesWalker();
|
|
|
|
public static T GetAnyChild<T>( Node parent ) where T:Node
|
|
{
|
|
var result = nodesWalker.Find( parent,
|
|
( n )=>
|
|
{
|
|
|
|
|
|
var castedNode = n as T;
|
|
|
|
// RJLog.Log( "Testing", n.UniqueNameInOwner, castedNode != null, n.GetType() );
|
|
|
|
return castedNode != null;
|
|
|
|
},
|
|
|
|
|
|
true );
|
|
|
|
return (T) result;
|
|
}
|
|
|
|
/*
|
|
|
|
public static void Enable( Node n, bool affectProcess = true, bool affectPhysicsProcess = true, bool affectInput = true )
|
|
{
|
|
SetState.SetStateOfNode( NodeStateType.Enabled, n, affectProcess, affectPhysicsProcess, affectInput );
|
|
}
|
|
|
|
public static void Disable( Node n, bool affectProcess = true, bool affectPhysicsProcess = true, bool affectInput = true )
|
|
{
|
|
SetState.SetStateOfNode( NodeStateType.Disabled, n, affectProcess, affectPhysicsProcess, affectInput );
|
|
}
|
|
|
|
*/
|
|
|
|
public static void Iterate( Node[] nodes, System.Action<Node> callback )
|
|
{
|
|
for ( int i = 0; i < nodes.Length; i++ )
|
|
{
|
|
nodesWalker.Iterate( nodes[ i ], callback );
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|