Initial Commit
This commit is contained in:
commit
8f1ce37f3b
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class ActionList : RJAction
|
||||||
|
{
|
||||||
|
[Export]
|
||||||
|
public RJAction[] actions;
|
||||||
|
[Export]
|
||||||
|
public bool triggerDirectChildren = true;
|
||||||
|
|
||||||
|
protected override void _OnTrigger()
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < actions.Length; i++ )
|
||||||
|
{
|
||||||
|
Actions.Trigger( actions[ i ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class Actions
|
||||||
|
{
|
||||||
|
public static Trigger( RJAction action )
|
||||||
|
{
|
||||||
|
if ( action == null )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
action.Trigger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
|
||||||
|
public class ReadonlyEventProperty<T>: EventSlot<T>
|
||||||
|
{
|
||||||
|
protected T _value;
|
||||||
|
public T value
|
||||||
|
{
|
||||||
|
get { return _value; }
|
||||||
|
protected set { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EventProperty<T>:ReadonlyEventProperty<T>
|
||||||
|
{
|
||||||
|
public new T value
|
||||||
|
{
|
||||||
|
get { return _value; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if ( IsEqual( _value, value ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_value = value;
|
||||||
|
DispatchEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void DispatchEvent()
|
||||||
|
{
|
||||||
|
_actions.ForEach( a => { if ( a != null ){ a( _value ); } } );
|
||||||
|
|
||||||
|
_ClearOnceActions();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected bool IsEqual( T oldValue, T newValue )
|
||||||
|
{
|
||||||
|
if ( oldValue == null && newValue == null )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( oldValue == null || newValue == null )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( EqualityComparer<T>.Default.Equals( oldValue , newValue ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetSilent( T value )
|
||||||
|
{
|
||||||
|
_value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class EventSlot<T>
|
||||||
|
{
|
||||||
|
protected List<Action<T>> _actions = new List<Action<T>>();
|
||||||
|
List<Action<T>> _once = new List<Action<T>>();
|
||||||
|
|
||||||
|
public bool hasListeners => _once.Count > 0 || _actions.Count > 0;
|
||||||
|
|
||||||
|
public void AddAction( Action<T> action )
|
||||||
|
{
|
||||||
|
_actions.Add( action );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAction( Action<T> action )
|
||||||
|
{
|
||||||
|
_actions.Remove( action );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Once( Action<T> action )
|
||||||
|
{
|
||||||
|
_actions.Add( action );
|
||||||
|
_once.Add( action );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void _ClearOnceActions()
|
||||||
|
{
|
||||||
|
_once.ForEach( a => { _actions.Remove( a ); } );
|
||||||
|
_once.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DispatchEvent( T t )
|
||||||
|
{
|
||||||
|
_actions.ForEach( a => { if ( a != null ){ a( t ); } } );
|
||||||
|
|
||||||
|
_ClearOnceActions();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class Null
|
||||||
|
{
|
||||||
|
private Null(){}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
using Godot;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class HierarchyName
|
||||||
|
{
|
||||||
|
public static string Of( Node node, string seperator = "/" )
|
||||||
|
{
|
||||||
|
if ( node == null )
|
||||||
|
{
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
|
||||||
|
var list = new List<string>();
|
||||||
|
|
||||||
|
var it = node;
|
||||||
|
|
||||||
|
while ( it != null )
|
||||||
|
{
|
||||||
|
list.Add( it.Name );
|
||||||
|
it = it.GetParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Reverse();
|
||||||
|
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
for ( int i = 0; i < list.Count; i++)
|
||||||
|
{
|
||||||
|
if ( i != 0 )
|
||||||
|
{
|
||||||
|
sb.Append( seperator );
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append( list[ i ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class Nodes
|
||||||
|
{
|
||||||
|
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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NodesWalker nodesWalker = new NodesWalker();
|
||||||
|
|
||||||
|
public static T GetAnyChild<T>( Node parent ) where T:Node
|
||||||
|
{
|
||||||
|
return (T) nodesWalker.Find( parent, ( n )=> n is T, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class NodesWalker: TreeWalker<Node>
|
||||||
|
{
|
||||||
|
static NodesWalker _singleton = new NodesWalker();
|
||||||
|
public static NodesWalker Get()
|
||||||
|
{
|
||||||
|
return _singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Node Parent( Node n )
|
||||||
|
{
|
||||||
|
if ( n == null )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n.GetParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Node ChildAt( Node n, int index )
|
||||||
|
{
|
||||||
|
if ( n == null )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n.GetChild( index );
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int NumChildren( Node n )
|
||||||
|
{
|
||||||
|
if ( n == null )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n.GetChildCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public partial class Root:Node
|
||||||
|
{
|
||||||
|
private static Root _singleton;
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
_singleton = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SceneTree Tree()
|
||||||
|
{
|
||||||
|
return _singleton.GetTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Window Window()
|
||||||
|
{
|
||||||
|
return Tree().Root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Root Get()
|
||||||
|
{
|
||||||
|
var r = Window();
|
||||||
|
return _singleton;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class Unique<N> where N:Node
|
||||||
|
{
|
||||||
|
private static N _singleton;
|
||||||
|
|
||||||
|
public static N Get()
|
||||||
|
{
|
||||||
|
if ( _singleton != null )
|
||||||
|
{
|
||||||
|
return _singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
_singleton = Nodes.GetAnyChild<N>( Root.Window() );
|
||||||
|
|
||||||
|
return _singleton;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class ChildrenIterator<N>: TreeIterator<N> where N:class
|
||||||
|
{
|
||||||
|
N parent;
|
||||||
|
N current;
|
||||||
|
N end;
|
||||||
|
N next;
|
||||||
|
TreeWalker<N> walker;
|
||||||
|
|
||||||
|
public static ChildrenIterator<N> Create( TreeWalker<N> walker, N node )
|
||||||
|
{
|
||||||
|
var iterator = new ChildrenIterator<N>();
|
||||||
|
|
||||||
|
iterator.walker = walker;
|
||||||
|
iterator.current = null;
|
||||||
|
iterator.parent = node;
|
||||||
|
iterator.end = walker.IterationEndOf( node );
|
||||||
|
iterator.next = walker.NextNode( node );
|
||||||
|
|
||||||
|
if ( iterator.next == iterator.end )
|
||||||
|
{
|
||||||
|
iterator.next = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool HasNext()
|
||||||
|
{
|
||||||
|
return next != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override N Current()
|
||||||
|
{
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void _MoveToNext()
|
||||||
|
{
|
||||||
|
current = next;
|
||||||
|
|
||||||
|
next = walker.NextNode( current );
|
||||||
|
|
||||||
|
if ( next == end )
|
||||||
|
{
|
||||||
|
next = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class DirectChildrenIterator<N>: TreeIterator<N> where N:class
|
||||||
|
{
|
||||||
|
N parent;
|
||||||
|
N current;
|
||||||
|
int index = 0;
|
||||||
|
TreeWalker<N> walker;
|
||||||
|
|
||||||
|
public static DirectChildrenIterator<N> Create( TreeWalker<N> walker, N node )
|
||||||
|
{
|
||||||
|
var iterator = new DirectChildrenIterator<N>();
|
||||||
|
|
||||||
|
iterator.parent = node;
|
||||||
|
iterator.walker = walker;
|
||||||
|
iterator.current = null;
|
||||||
|
iterator.index = -1;
|
||||||
|
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool HasNext()
|
||||||
|
{
|
||||||
|
return ( index + 1 ) < walker.NumChildren( parent );
|
||||||
|
}
|
||||||
|
|
||||||
|
public override N Current()
|
||||||
|
{
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void _MoveToNext()
|
||||||
|
{
|
||||||
|
index ++;
|
||||||
|
current = walker.ChildAt( parent, index );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class NodesIterator<N>: TreeIterator<N> where N:class
|
||||||
|
{
|
||||||
|
N node;
|
||||||
|
N current;
|
||||||
|
bool isForward = true;
|
||||||
|
TreeWalker<N> walker;
|
||||||
|
|
||||||
|
public static NodesIterator<N> Create( TreeWalker<N> walker, N node, bool forward )
|
||||||
|
{
|
||||||
|
var iterator = new NodesIterator<N>();
|
||||||
|
|
||||||
|
iterator.walker = walker;
|
||||||
|
iterator.node = node;
|
||||||
|
iterator.current = null;
|
||||||
|
iterator.isForward = forward;
|
||||||
|
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool HasNext()
|
||||||
|
{
|
||||||
|
return node != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override N Current()
|
||||||
|
{
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void _MoveToNext()
|
||||||
|
{
|
||||||
|
if ( isForward )
|
||||||
|
{
|
||||||
|
node = walker.NextNode( node );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node = walker.PreviousNode( node );
|
||||||
|
}
|
||||||
|
|
||||||
|
current = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class ParentsIterator<N>: TreeIterator<N> where N:class
|
||||||
|
{
|
||||||
|
N iterator;
|
||||||
|
N current;
|
||||||
|
TreeWalker<N> walker;
|
||||||
|
|
||||||
|
public static ParentsIterator<N> Create( TreeWalker<N> walker, N start )
|
||||||
|
{
|
||||||
|
var iterator = new ParentsIterator<N>();
|
||||||
|
|
||||||
|
iterator.current = null;
|
||||||
|
iterator.iterator = start;
|
||||||
|
iterator.walker = walker;
|
||||||
|
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool HasNext()
|
||||||
|
{
|
||||||
|
return walker.HasParent( iterator );
|
||||||
|
}
|
||||||
|
|
||||||
|
public override N Current()
|
||||||
|
{
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void _MoveToNext()
|
||||||
|
{
|
||||||
|
iterator = walker.Parent( iterator );
|
||||||
|
current = iterator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class SiblingsIterator<N>: TreeIterator<N> where N:class
|
||||||
|
{
|
||||||
|
bool nextSiblings = true;
|
||||||
|
|
||||||
|
N parent;
|
||||||
|
N current;
|
||||||
|
int index = 0;
|
||||||
|
int nodeIndex = 0;
|
||||||
|
TreeWalker<N> walker;
|
||||||
|
|
||||||
|
public static SiblingsIterator<N> Create( TreeWalker<N> walker, N node, bool previous = true, bool next = true )
|
||||||
|
{
|
||||||
|
var iterator = new SiblingsIterator<N>();
|
||||||
|
|
||||||
|
iterator.parent = node;
|
||||||
|
iterator.walker = walker;
|
||||||
|
iterator.current = null;
|
||||||
|
iterator.nodeIndex = walker.ChildIndexOf( node );
|
||||||
|
iterator.index = previous ? -1 : iterator.nodeIndex;
|
||||||
|
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool HasNext()
|
||||||
|
{
|
||||||
|
if ( ! nextSiblings )
|
||||||
|
{
|
||||||
|
return ( index + 1 ) < nodeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nextIndex = index + 1;
|
||||||
|
|
||||||
|
if ( nextIndex == nodeIndex )
|
||||||
|
{
|
||||||
|
nextIndex ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nextIndex < walker.NumChildren( parent );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override N Current()
|
||||||
|
{
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void _MoveToNext()
|
||||||
|
{
|
||||||
|
index ++;
|
||||||
|
|
||||||
|
if ( index == nodeIndex )
|
||||||
|
{
|
||||||
|
index ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = walker.ChildAt( parent, index );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori.Core
|
||||||
|
{
|
||||||
|
public class SinlgeIterator<N>: TreeIterator<N> where N:class
|
||||||
|
{
|
||||||
|
N node;
|
||||||
|
N current;
|
||||||
|
|
||||||
|
public static SinlgeIterator<N> Create( N node )
|
||||||
|
{
|
||||||
|
var iterator = new SinlgeIterator<N>();
|
||||||
|
|
||||||
|
iterator.node = node;
|
||||||
|
iterator.current = null;
|
||||||
|
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool HasNext()
|
||||||
|
{
|
||||||
|
return node != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override N Current()
|
||||||
|
{
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void _MoveToNext()
|
||||||
|
{
|
||||||
|
current = node;
|
||||||
|
node = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,165 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public enum TreeIteratorType
|
||||||
|
{
|
||||||
|
Parent,
|
||||||
|
|
||||||
|
NextSibling,
|
||||||
|
PreviousSibling,
|
||||||
|
|
||||||
|
FirstChild,
|
||||||
|
LastChild,
|
||||||
|
LastGrandChild,
|
||||||
|
|
||||||
|
NextNode,
|
||||||
|
PreviousNode,
|
||||||
|
|
||||||
|
Parents,
|
||||||
|
|
||||||
|
DirectChildren,
|
||||||
|
Children,
|
||||||
|
|
||||||
|
Siblings,
|
||||||
|
PreviousSiblings,
|
||||||
|
NextSiblings,
|
||||||
|
|
||||||
|
PreviousNodes,
|
||||||
|
NextNodes
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class TreeIterator<N> where N:class
|
||||||
|
{
|
||||||
|
public abstract bool HasNext();
|
||||||
|
public abstract N Current();
|
||||||
|
protected abstract void _MoveToNext();
|
||||||
|
bool safeMoving = true;
|
||||||
|
|
||||||
|
public void MoveToNext()
|
||||||
|
{
|
||||||
|
if ( safeMoving && ! HasNext() )
|
||||||
|
{
|
||||||
|
throw new System.Exception( "Has no more elements" );
|
||||||
|
}
|
||||||
|
|
||||||
|
_MoveToNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ForEach( System.Action<N> callback )
|
||||||
|
{
|
||||||
|
while ( HasNext() )
|
||||||
|
{
|
||||||
|
_MoveToNext();
|
||||||
|
callback( Current() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public N Get( System.Func<N,bool> predicate )
|
||||||
|
{
|
||||||
|
while ( HasNext() )
|
||||||
|
{
|
||||||
|
_MoveToNext();
|
||||||
|
|
||||||
|
var current = Current();
|
||||||
|
var result = predicate( current );
|
||||||
|
|
||||||
|
if ( result )
|
||||||
|
{
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Has( System.Func<N,bool> predicate )
|
||||||
|
{
|
||||||
|
return Get( predicate ) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<N> All( System.Func<N,bool> predicate )
|
||||||
|
{
|
||||||
|
var list = new List<N>();
|
||||||
|
|
||||||
|
while ( HasNext() )
|
||||||
|
{
|
||||||
|
_MoveToNext();
|
||||||
|
|
||||||
|
var current = Current();
|
||||||
|
var result = predicate( current );
|
||||||
|
|
||||||
|
if ( result )
|
||||||
|
{
|
||||||
|
list.Add( current );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TreeIterator<N> GetIterator( TreeIteratorType type, N node, TreeWalker<N> walker )
|
||||||
|
{
|
||||||
|
|
||||||
|
switch ( type )
|
||||||
|
{
|
||||||
|
case TreeIteratorType.Parent:
|
||||||
|
return SinlgeIterator<N>.Create( walker.Parent( node ) );
|
||||||
|
|
||||||
|
case TreeIteratorType.NextSibling:
|
||||||
|
return SinlgeIterator<N>.Create( walker.NextSibling( node ) );
|
||||||
|
|
||||||
|
case TreeIteratorType.PreviousSibling:
|
||||||
|
return SinlgeIterator<N>.Create( walker.PreviousSibling( node ) );
|
||||||
|
|
||||||
|
case TreeIteratorType.FirstChild:
|
||||||
|
return SinlgeIterator<N>.Create( walker.ChildAt( node, 0 ) );
|
||||||
|
|
||||||
|
case TreeIteratorType.LastChild:
|
||||||
|
return SinlgeIterator<N>.Create( walker.ChildAt( node, walker.NumChildren( node ) - 1 ) );
|
||||||
|
|
||||||
|
case TreeIteratorType.LastGrandChild:
|
||||||
|
return SinlgeIterator<N>.Create( walker.LastGrandChild( node ) );
|
||||||
|
|
||||||
|
case TreeIteratorType.NextNode:
|
||||||
|
return SinlgeIterator<N>.Create( walker.NextNode( node ) );
|
||||||
|
|
||||||
|
case TreeIteratorType.PreviousNode:
|
||||||
|
return SinlgeIterator<N>.Create( walker.PreviousNode( node ) );
|
||||||
|
|
||||||
|
|
||||||
|
case TreeIteratorType.Parents:
|
||||||
|
return ParentsIterator<N>.Create( walker, node );
|
||||||
|
|
||||||
|
|
||||||
|
case TreeIteratorType.DirectChildren:
|
||||||
|
return DirectChildrenIterator<N>.Create( walker, node );
|
||||||
|
|
||||||
|
case TreeIteratorType.Children:
|
||||||
|
return ChildrenIterator<N>.Create( walker, node );
|
||||||
|
|
||||||
|
|
||||||
|
case TreeIteratorType.Siblings:
|
||||||
|
return SiblingsIterator<N>.Create( walker, node, true, true );
|
||||||
|
|
||||||
|
case TreeIteratorType.PreviousSiblings:
|
||||||
|
return SiblingsIterator<N>.Create( walker, node, true, false );
|
||||||
|
|
||||||
|
case TreeIteratorType.NextSiblings:
|
||||||
|
return SiblingsIterator<N>.Create( walker, node, false, true );
|
||||||
|
|
||||||
|
|
||||||
|
case TreeIteratorType.NextNodes:
|
||||||
|
return NodesIterator<N>.Create( walker, node, true );
|
||||||
|
|
||||||
|
case TreeIteratorType.PreviousNodes:
|
||||||
|
return NodesIterator<N>.Create( walker, node, false );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,322 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public abstract class TreeWalker<N> where N:class
|
||||||
|
{
|
||||||
|
public abstract N Parent( N node );
|
||||||
|
|
||||||
|
public abstract N ChildAt( N node, int index );
|
||||||
|
|
||||||
|
public abstract int NumChildren( N node );
|
||||||
|
|
||||||
|
public bool HasChildren( N node )
|
||||||
|
{
|
||||||
|
return NumChildren( node ) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasParent( N node )
|
||||||
|
{
|
||||||
|
return Parent( node ) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int ChildIndexOf( N node )
|
||||||
|
{
|
||||||
|
var p = Parent( node );
|
||||||
|
|
||||||
|
if ( p == null )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var numKids = NumChildren( p );
|
||||||
|
|
||||||
|
for ( var i = 0; i<numKids; i++ )
|
||||||
|
{
|
||||||
|
if ( ChildAt( p, i ) == node )
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public N SiblingAt( N node, int index )
|
||||||
|
{
|
||||||
|
var p = Parent( node );
|
||||||
|
|
||||||
|
if ( p == null || index<0 || index >= NumChildren( p ) )
|
||||||
|
{ return null; }
|
||||||
|
|
||||||
|
return ChildAt( p, index );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public N NextSibling( N node )
|
||||||
|
{
|
||||||
|
var index = ChildIndexOf( node );
|
||||||
|
return SiblingAt( node, index+1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public N PreviousSibling( N node )
|
||||||
|
{
|
||||||
|
var index = ChildIndexOf( node );
|
||||||
|
return SiblingAt( node, index-1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool HasSiblingAt( N node, int index )
|
||||||
|
{
|
||||||
|
var p = Parent( node );
|
||||||
|
if ( p == null || index<0 || index >= NumChildren( p ) )
|
||||||
|
{ return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public N FirstChild( N node )
|
||||||
|
{
|
||||||
|
return NumChildren( node )<=0?null:ChildAt( node, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public N LastChild( N node )
|
||||||
|
{
|
||||||
|
var num = NumChildren( node );
|
||||||
|
return num <= 0 ? null : ChildAt( node, num - 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public N NextNode( N node )
|
||||||
|
{
|
||||||
|
if ( HasChildren( node ) )
|
||||||
|
{
|
||||||
|
return FirstChild( node );
|
||||||
|
}
|
||||||
|
|
||||||
|
var next = NextSibling( node );
|
||||||
|
|
||||||
|
if ( next != null )
|
||||||
|
{
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parent = Parent( node );
|
||||||
|
|
||||||
|
while ( parent != null )
|
||||||
|
{
|
||||||
|
var n = NextSibling( parent );
|
||||||
|
|
||||||
|
if ( n != null )
|
||||||
|
{
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent = Parent( parent );
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public N PreviousNode( N node )
|
||||||
|
{
|
||||||
|
var prev = PreviousSibling( node );
|
||||||
|
|
||||||
|
if ( prev != null )
|
||||||
|
{
|
||||||
|
while ( HasChildren( prev ) )
|
||||||
|
{
|
||||||
|
prev = LastChild( prev );
|
||||||
|
}
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Parent( node );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public N RootParent( N node )
|
||||||
|
{
|
||||||
|
node = Parent( node );
|
||||||
|
|
||||||
|
if ( node == null )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( HasParent( node ) )
|
||||||
|
{
|
||||||
|
node = Parent( node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public N LastGrandChild( N node )
|
||||||
|
{
|
||||||
|
if ( HasChildren( node ) )
|
||||||
|
{
|
||||||
|
node = LastChild( node );
|
||||||
|
|
||||||
|
while ( HasChildren( node ) )
|
||||||
|
{
|
||||||
|
node = LastChild( node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool IsChildOf( N child, N parent )
|
||||||
|
{
|
||||||
|
var p = Parent( child );
|
||||||
|
|
||||||
|
while ( p != null )
|
||||||
|
{
|
||||||
|
if ( p == parent )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
p = Parent( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int NumParents( N node )
|
||||||
|
{
|
||||||
|
var num = 0;
|
||||||
|
var p = Parent( node );
|
||||||
|
|
||||||
|
while ( p != null )
|
||||||
|
{
|
||||||
|
num++;
|
||||||
|
p = Parent( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public N LastOuterNode( N node )
|
||||||
|
{
|
||||||
|
var its = 0;
|
||||||
|
var max = 10000;
|
||||||
|
|
||||||
|
while ( HasChildren( node ) )
|
||||||
|
{
|
||||||
|
its++;
|
||||||
|
|
||||||
|
if ( its > max )
|
||||||
|
{
|
||||||
|
throw new System.Exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
node = LastChild( node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public N NextNonChild( N node )
|
||||||
|
{
|
||||||
|
return NextNode( LastOuterNode( node ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public N IterationEndOf( N node )
|
||||||
|
{
|
||||||
|
return NextNonChild( node );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Iterate( N node, System.Action<N> callback, bool childrenOnly = false )
|
||||||
|
{
|
||||||
|
var end = IterationEndOf( node );
|
||||||
|
var it = node;
|
||||||
|
|
||||||
|
if ( childrenOnly )
|
||||||
|
{
|
||||||
|
it = NextNode( it );
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( it != end )
|
||||||
|
{
|
||||||
|
callback( it );
|
||||||
|
it = NextNode( it );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public N Find( N node, System.Predicate<N> predicate, bool childrenOnly )
|
||||||
|
{
|
||||||
|
var end = IterationEndOf( node );
|
||||||
|
var it = node;
|
||||||
|
|
||||||
|
if ( childrenOnly )
|
||||||
|
{
|
||||||
|
it = NextNode( it );
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( it != end )
|
||||||
|
{
|
||||||
|
if ( predicate( it ) )
|
||||||
|
{
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
it = NextNode( it );
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Filter( List<N> list, N node, System.Predicate<N> predicate, bool childrenOnly )
|
||||||
|
{
|
||||||
|
System.Action<N> addToList = ( N n ) =>
|
||||||
|
{
|
||||||
|
if ( predicate( n ) )
|
||||||
|
{
|
||||||
|
list.Add( n );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Iterate( node, addToList, childrenOnly );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FilterAndMap<U>( List<U> list, N node, System.Predicate<N> predicate, System.Func<N,U> mapper, bool childrenOnly )
|
||||||
|
{
|
||||||
|
System.Action<N> addToList = ( N n ) =>
|
||||||
|
{
|
||||||
|
if ( predicate( n ) )
|
||||||
|
{
|
||||||
|
list.Add( mapper( n ) );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Iterate( node, addToList, childrenOnly );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Map<U>( List<U> list, N node, System.Predicate<N> predicate, System.Func<N,U> mapper, bool childrenOnly )
|
||||||
|
{
|
||||||
|
System.Action<N> addToList = ( N n ) =>
|
||||||
|
{
|
||||||
|
list.Add( mapper( n ) );
|
||||||
|
};
|
||||||
|
|
||||||
|
Iterate( node, addToList, childrenOnly );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue