Updates From Explorers

This commit is contained in:
Josef 2024-08-04 11:08:12 +02:00
parent 1e0ffa9761
commit c2c548ae04
29 changed files with 1087 additions and 82 deletions

View File

@ -33,37 +33,7 @@ namespace Rokojori
public override void _OnTrigger()
{
if ( actions != null )
{
for ( int i = 0; i < actions.Length; i++ )
{
Actions.Trigger( actions[ i ] );
}
}
if ( ! triggerDirectChildren )
{
return;
}
Nodes.ForEachDirectChild<RJAction>( this, a => Actions.Trigger( a ) );
/*
var childCount = GetChildCount();
for ( int i = 0; i < childCount; i++ )
{
var action = GetChild( i ) as RJAction;
if ( action == null )
{
continue;
}
Actions.Trigger( action );
}
*/
Actions.TriggerAll( actions, this, triggerDirectChildren );
}
}
}

View File

@ -15,5 +15,23 @@ namespace Rokojori
action.Trigger();
}
public static void TriggerAll( RJAction[] actions, Node target, bool triggerDirectChildren )
{
if ( actions != null )
{
for ( int i = 0; i < actions.Length; i++ )
{
Actions.Trigger( actions[ i ] );
}
}
if ( ! triggerDirectChildren )
{
return;
}
Nodes.ForEachDirectChild<RJAction>( target, a => Actions.Trigger( a ) );
}
}
}

View File

@ -1,34 +0,0 @@
class_name GDDelay
extends RJSequenceAction
@export var duration = 1
@export var message = "huhu"
var running = false
var elapsed = 0;
var id = 0;
var cachedIDs = []
func _onTrigger():
if running:
cachedIDs
running = true
elapsed = 0
id = dispatchStart()
func _process( delta ):
if ! running:
return
elapsed += delta
if elapsed > duration:
running = false
elapsed = 0
print( name + " >> " + message )
dispatchEnd( id )

View File

@ -0,0 +1,24 @@
using Godot;
namespace Rokojori
{
[GlobalClass ]
public partial class SetNodeState : RJAction
{
[Export]
public Node[] enable;
[Export]
public Node[] disable;
public override void _OnTrigger()
{
Arrays.ForEach( enable, n => NodeState.Enable( n ) );
Arrays.ForEach( disable, n => NodeState.Disable( n ) );
}
}
}

View File

@ -0,0 +1,31 @@
using Godot;
namespace Rokojori
{
[GlobalClass ]
public partial class CopyMousePosition : RJAction
{
[Export]
public Camera3D camera;
[Export]
public float depth;
[Export]
public Node3D target;
public override void _OnTrigger()
{
if ( camera == null || target == null )
{
return;
}
var mousePosition = GetViewport().GetMousePosition();
target.GlobalPosition = camera.ProjectPosition( mousePosition, depth );
}
}
}

View File

@ -0,0 +1,33 @@
using Godot;
namespace Rokojori
{
[GlobalClass, Tool ]
public partial class CopyPosition : RJAction
{
[Export]
public Node3D source;
[Export]
public Node3D target;
public override void _Process( double delta )
{
_OnTrigger();
}
public override void _OnTrigger()
{
if ( source == null || target == null )
{
return;
}
target.GlobalPosition = source.GlobalPosition;
}
}
}

View File

@ -0,0 +1,49 @@
using Godot;
namespace Rokojori
{
[GlobalClass, Tool ]
public partial class DistributeChildren : RJAction
{
[Export]
public Node3D target;
[Export]
public Node3D start;
[Export]
public Node3D end;
public override void _Process( double delta )
{
_OnTrigger();
}
public override void _OnTrigger()
{
if ( start == null || end == null || target == null )
{
return;
}
var children = Nodes.GetDirectChildren<Node3D>( target );
var startPosition = start.GlobalPosition;
var endPosition = end.GlobalPosition;
for ( int i = 0; i < children.Count; i++ )
{
var lerpState = i / ( children.Count - 1f );
var childPosition = startPosition.Lerp( endPosition, lerpState );
children[ i ].GlobalPosition = childPosition;
}
}
}
}

View File

@ -0,0 +1,31 @@
using Godot;
namespace Rokojori
{
[GlobalClass ]
public partial class LerpPosition : RJAction
{
[Export]
public Node3D sourceA;
[Export]
public Node3D sourceB;
[Export]
public float lerp;
[Export]
public Node3D target;
public override void _OnTrigger()
{
if ( sourceA == null || sourceB == null || target == null )
{
return;
}
target.GlobalPosition = sourceA.GlobalPosition.Lerp( sourceB.GlobalPosition, lerp );
}
}
}

View File

@ -0,0 +1,30 @@
using Godot;
namespace Rokojori
{
[GlobalClass, Tool ]
public partial class LookAt : RJAction
{
[Export]
public Node3D lookTarget;
[Export]
public Node3D lookFrom;
public override void _Process( double delta )
{
_OnTrigger();
}
public override void _OnTrigger()
{
if ( lookFrom == null || lookTarget == null )
{
return;
}
lookFrom.LookAt( lookTarget.GlobalPosition );
}
}
}

View File

@ -0,0 +1,19 @@
using Godot;
namespace Rokojori
{
[GlobalClass, Icon("res://Scripts/Rokojori/Rokojori-Action-Library/Icons/RJOnEvent.svg") ]
public partial class OnPhysicsProcess : Node
{
[Export]
public RJAction action;
public override void _PhysicsProcess( double delta )
{
// RJLog.Log( "OnReady" );
Actions.Trigger( action );
}
}
}

View File

@ -0,0 +1,31 @@
using Godot;
namespace Rokojori
{
[GlobalClass, Tool, Icon("res://Scripts/Rokojori/Rokojori-Action-Library/Icons/RJOnEvent.svg") ]
public partial class OnProcess : Node
{
/** <summary for="field actions">Actions to execute</summary>*/
[Export]
public RJAction[] actions;
/** <summary for="field triggerDirectChildren">Whether to execute RJAction child nodes</summary>*/
[Export]
public bool triggerDirectChildren = true;
[Export]
public bool executeInEditor = false;
public override void _Process( double delta )
{
if ( Engine.IsEditorHint() && ! executeInEditor )
{
return;
}
Actions.TriggerAll( actions, this, triggerDirectChildren );
}
}
}

View File

@ -4,14 +4,14 @@ using Godot;
namespace Rokojori
{
[GlobalClass]
public partial class GDPrint : RJAction
[GlobalClass ]
public partial class RJLogMessage : RJAction
{
[Export]
public string message;
public override void _OnTrigger()
{
{
RJLog.Log( message );
}
}

View File

@ -0,0 +1,79 @@
using Godot;
namespace Rokojori
{
[GlobalClass]
public partial class RJAnimatableBody3D:AnimatableBody3D
{
[Export]
public RJAction OnInputEvent;
[Export]
public RJAction OnMouseEntered;
[Export]
public RJAction OnMouseExited;
[Export]
public RJAction OnVisibilityChanged;
[Export]
public RJAction OnReady;
[Export]
public RJAction OnRenamed;
[Export]
public RJAction OnTreeEntered;
[Export]
public RJAction OnTreeExiting;
[Export]
public RJAction OnTreeExited;
[Export]
public RJAction OnChildEnteredTree;
[Export]
public RJAction OnChildExitingTree;
[Export]
public RJAction OnChildOrderChanged;
[Export]
public RJAction OnReplacingBy;
[Export]
public RJAction OnEditorDescriptionChanged;
[Export]
public RJAction OnScriptChanged;
[Export]
public RJAction OnPropertyListChanged;
public override void _Ready()
{
InputEvent += ( p0, p1, p2, p3, p4 ) => { Actions.Trigger( OnInputEvent ); };
MouseEntered += ( ) => { Actions.Trigger( OnMouseEntered ); };
MouseExited += ( ) => { Actions.Trigger( OnMouseExited ); };
VisibilityChanged += ( ) => { Actions.Trigger( OnVisibilityChanged ); };
Ready += ( ) => { Actions.Trigger( OnReady ); };
Renamed += ( ) => { Actions.Trigger( OnRenamed ); };
TreeEntered += ( ) => { Actions.Trigger( OnTreeEntered ); };
TreeExiting += ( ) => { Actions.Trigger( OnTreeExiting ); };
TreeExited += ( ) => { Actions.Trigger( OnTreeExited ); };
ChildEnteredTree += ( p0 ) => { Actions.Trigger( OnChildEnteredTree ); };
ChildExitingTree += ( p0 ) => { Actions.Trigger( OnChildExitingTree ); };
ChildOrderChanged += ( ) => { Actions.Trigger( OnChildOrderChanged ); };
ReplacingBy += ( p0 ) => { Actions.Trigger( OnReplacingBy ); };
EditorDescriptionChanged += ( p0 ) => { Actions.Trigger( OnEditorDescriptionChanged ); };
ScriptChanged += ( ) => { Actions.Trigger( OnScriptChanged ); };
PropertyListChanged += ( ) => { Actions.Trigger( OnPropertyListChanged ); };
}
}
}

View File

@ -0,0 +1,79 @@
using Godot;
namespace Rokojori
{
[GlobalClass]
public partial class RJCharacterBody3D:CharacterBody3D
{
[Export]
public RJAction OnInputEvent;
[Export]
public RJAction OnMouseEntered;
[Export]
public RJAction OnMouseExited;
[Export]
public RJAction OnVisibilityChanged;
[Export]
public RJAction OnReady;
[Export]
public RJAction OnRenamed;
[Export]
public RJAction OnTreeEntered;
[Export]
public RJAction OnTreeExiting;
[Export]
public RJAction OnTreeExited;
[Export]
public RJAction OnChildEnteredTree;
[Export]
public RJAction OnChildExitingTree;
[Export]
public RJAction OnChildOrderChanged;
[Export]
public RJAction OnReplacingBy;
[Export]
public RJAction OnEditorDescriptionChanged;
[Export]
public RJAction OnScriptChanged;
[Export]
public RJAction OnPropertyListChanged;
public override void _Ready()
{
InputEvent += ( p0, p1, p2, p3, p4 ) => { Actions.Trigger( OnInputEvent ); };
MouseEntered += ( ) => { Actions.Trigger( OnMouseEntered ); };
MouseExited += ( ) => { Actions.Trigger( OnMouseExited ); };
VisibilityChanged += ( ) => { Actions.Trigger( OnVisibilityChanged ); };
Ready += ( ) => { Actions.Trigger( OnReady ); };
Renamed += ( ) => { Actions.Trigger( OnRenamed ); };
TreeEntered += ( ) => { Actions.Trigger( OnTreeEntered ); };
TreeExiting += ( ) => { Actions.Trigger( OnTreeExiting ); };
TreeExited += ( ) => { Actions.Trigger( OnTreeExited ); };
ChildEnteredTree += ( p0 ) => { Actions.Trigger( OnChildEnteredTree ); };
ChildExitingTree += ( p0 ) => { Actions.Trigger( OnChildExitingTree ); };
ChildOrderChanged += ( ) => { Actions.Trigger( OnChildOrderChanged ); };
ReplacingBy += ( p0 ) => { Actions.Trigger( OnReplacingBy ); };
EditorDescriptionChanged += ( p0 ) => { Actions.Trigger( OnEditorDescriptionChanged ); };
ScriptChanged += ( ) => { Actions.Trigger( OnScriptChanged ); };
PropertyListChanged += ( ) => { Actions.Trigger( OnPropertyListChanged ); };
}
}
}

View File

@ -17,16 +17,27 @@ namespace Rokojori
[Export]
public string testClass;
public override void _Ready()
{
ExportFiles();
}
public override void _Process( double delta )
{
if ( exportFlag )
{
exportFlag = false;
var result = CreateClass( testClass );
FilesSync.SaveUTF8( outputPath + testClass + ".cs", result );
ExportFiles();
}
}
void ExportFiles()
{
RJLog.Log( "Exporting:", testClass );
var result = CreateClass( testClass );
FilesSync.SaveUTF8( outputPath + "RJ" + testClass + ".cs", result );
}
public string CreateClass( string name )
{
var output = new StringBuilder();
@ -41,7 +52,8 @@ namespace Rokojori
output.Append( " public partial class RJ" + name + ":" + name + "\n");
output.Append( " {\n" );
var classType = ReflectionHelper.GetTypeByName( name );
var classType = ReflectionHelper.GetTypeByNameFromAssembly( "Godot." + name, typeof( Node ).Assembly );
if ( classType == null )
{
@ -58,6 +70,7 @@ namespace Rokojori
var ev = events[ i ];
var eventName = ev.Name;
output.Append( " \n" );
output.Append( " [Export]\n" );
output.Append( " public RJAction On" + eventName + ";\n" );
}
@ -71,16 +84,23 @@ namespace Rokojori
{
var ev = events[ i ];
var eventName = ev.Name;
var parameters = ev.GetRaiseMethod().GetParameters();
var p = "(";
var parameters = classType.GetEvent( eventName ).EventHandlerType.GetMethod( "Invoke" ).GetParameters();
var p = "( ";
for ( int pn = 0; pn < parameters.Length; pn ++ )
{
if ( pn != 0 )
{
p += ", ";
}
p += "p" + pn;
}
p += ")";
p += " )";
output.Append( " " + eventName + " += " + p + " { Actions.Trigger( On" + eventName +" ); }; \n" );
output.Append( " " + eventName + " += " + p + " => { Actions.Trigger( On" + eventName +" ); }; \n" );
}
output.Append( " }\n" );
@ -89,6 +109,8 @@ namespace Rokojori
output.Append( "}\n" );
RJLog.Log( output.ToString() );
return output.ToString();
}

View File

@ -0,0 +1,19 @@
using Godot;
namespace Rokojori
{
public enum NodePathLocatorType
{
DirectChildrenAndSiblings,
DirectChildren,
Siblings,
AnyChildren,
SiblingsAndAnyChildren
}
public class NodePathLocator
{
public NodePathLocatorType type = NodePathLocatorType.DirectChildrenAndSiblings;
public int parentOffset = 0;
}
}

View File

@ -0,0 +1,47 @@
using Godot;
using System.Collections.Generic;
using System;
namespace Rokojori
{
public class NodeState
{
public static void Configure( Node n, bool processEnabled, bool inputEnabled, bool physicsEnabled, bool signalsEnabled,
Node.ProcessModeEnum processMode )
{
n.SetProcess( processEnabled );
n.SetProcessInput( inputEnabled );
n.SetPhysicsProcess( physicsEnabled );
n.SetBlockSignals( ! signalsEnabled );
n.ProcessMode = processMode;
}
public static void Set( Node n, bool enabled )
{
Configure( n, enabled, enabled, enabled, enabled, enabled ? Node.ProcessModeEnum.Inherit : Node.ProcessModeEnum.Disabled );
}
public static void Set( Node[] nodes, bool enabled )
{
Arrays.ForEach( nodes, n => Set( n, enabled ) );
}
public static void Enable( Node n )
{
Set( n, true );
}
public static void Enable( Node[] n )
{
Set( n, true );
}
public static void Disable( Node n )
{
Set( n, true );
}
}
}

View File

@ -7,6 +7,68 @@ namespace Rokojori
{
public 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 ForEach<T>( Node root, Action<T> callback ) where T:class
{
var walker = nodesWalker;
@ -82,7 +144,7 @@ namespace Rokojori
var node = parent.GetChild( i );
var script = node.GetScript();
RJLog.Log( "Node is", typeof(T), node.Name, node.GetType(), script.GetType(), ">>", ( node is T ) );
// RJLog.Log( "Node is", typeof(T), node.Name, node.GetType(), script.GetType(), ">>", ( node is T ) );
if ( ! ( node is T ) )
@ -130,7 +192,7 @@ namespace Rokojori
var castedNode = n as T;
RJLog.Log( "Testing", n.UniqueNameInOwner, castedNode != null, n.GetType() );
// RJLog.Log( "Testing", n.UniqueNameInOwner, castedNode != null, n.GetType() );
return castedNode != null;

View File

@ -18,7 +18,7 @@ namespace Rokojori
var rootWindow = n == null ? Root.Window() : n.Owner;
RJLog.Log( "ROOT", rootWindow );
// RJLog.Log( "ROOT", rootWindow );
if ( rootWindow == null )
{
@ -27,7 +27,7 @@ namespace Rokojori
_singleton = Nodes.GetAnyChild<N>( rootWindow );
RJLog.Log( "_singleton", _singleton );
// RJLog.Log( "_singleton", _singleton );
return _singleton;
}

View File

@ -0,0 +1,184 @@
using Godot;
using System.Collections;
using System.Collections.Generic;
using Godot.Collections;
namespace Rokojori
{
[GlobalClass]
public partial class MultiRayCaster:RJCaster
{
[Export]
public float rayLength = 10;
[Export]
public int maxHits = 100;
[Export]
public bool sortByPointerPriority;
List<CollisionData> collisions = new List<CollisionData>();
int numCollisions = 0;
[Export]
public Vector3 to;
public override int NumColliders()
{
return numCollisions;
}
public override Node GetCollider( int index )
{
return collisions[ index ].collider;
}
public override Vector3 GetCollisionNormal( int index )
{
return collisions[ index ].normal;
}
public override Vector3 GetCollisionPosition( int index )
{
return collisions[ index ].position;
}
public override Shape3D GetCollisionShape( int index )
{
return collisions[ index ].shape;
}
PhysicsRayQueryParameters3D rayParameters = new PhysicsRayQueryParameters3D();
public override void _Process( double delta )
{
Actions.Trigger( BeforeProcess );
ResolveCollisions();
SortCollisions();
Actions.Trigger( AfterProcess );
}
ValueSorter<CollisionData> singleSorter;
MultiValueSorter<CollisionData> multiSorter;
CollisionData GetCollisionData( int i )
{
while ( collisions.Count <= i )
{
collisions.Add( new CollisionData() );
}
return collisions[ i ];
}
void ResolveCollisions()
{
var physics = GetWorld3D().DirectSpaceState;
var excludes = new Array<Rid>();
var from = GlobalPosition;
var to = from + Math3D.GetGlobalForward( this ) * rayLength;
this.to = to;
rayParameters.From = from;
rayParameters.To = to;
numCollisions = 0;
for ( int i = 0; i < maxHits; i++ )
{
rayParameters.Exclude = excludes;
var collisionData = GetCollisionData( numCollisions );
collisionData.Get( rayParameters, physics );
if ( ! collisionData.hasCollision )
{
return;
}
excludes.Add( collisionData.rid );
if ( IsSelected( collisionData ) )
{
numCollisions ++;
}
}
}
bool IsSelected( CollisionData cd )
{
var includeSelector = IncludeSelector;
var excludeSelector = ExcludeSelector;
if ( includeSelector != null && ! includeSelector.Selects( cd.collider ) )
{
return false;
}
if ( excludeSelector != null && excludeSelector.Selects( cd.collider ) )
{
return false;
}
return true;
}
void SortCollisions()
{
if ( ! sortByPointerPriority )
{
if ( singleSorter == null )
{
singleSorter = ValueSorter<CollisionData>.Create( cd => GetDistance( cd ) );
}
singleSorter.Sort( 0, numCollisions, collisions );
}
else
{
if ( multiSorter == null )
{
multiSorter = MultiValueSorter<CollisionData>.Create(
cd => GetPointablePriority( cd ),
cd => GetDistance( cd )
);
}
multiSorter.Sort( 0, numCollisions, collisions );
}
}
float GetPointablePriority( CollisionData cd )
{
float priority = 0;
var pointable = Nodes.Find<RJPointable>( cd.collider );
if ( pointable != null )
{
priority = pointable.PointingPriority;
}
return priority;
}
float GetDistance( CollisionData cd )
{
return ( cd.position - GlobalPosition ).Length();
}
}
}

View File

@ -0,0 +1,61 @@
using Godot;
using System.Collections;
using System.Collections.Generic;
using Godot.Collections;
namespace Rokojori
{
[GlobalClass]
public partial class Pointable:RJPointable
{
List<RJPointer> _pointers = new List<RJPointer>();
public override int NumPointing()
{
return _pointers.Count;
}
public bool IsPointedBy( RJPointer pointer )
{
return _pointers.Contains( pointer );
}
public override void UpdatePointerState( RJPointer pointer, bool pointed )
{
var isCurrentlyPointed = IsPointedBy( pointer );
if ( isCurrentlyPointed == pointed )
{
return;
}
if ( pointed )
{
_pointers.Add( pointer );
Actions.Trigger( OnPointerAdded );
if ( _pointers.Count == 1 )
{
Actions.Trigger( OnPointed );
}
}
else
{
_pointers.Remove( pointer );
Actions.Trigger( OnPointerRemoved );
if ( _pointers.Count == 0 )
{
Actions.Trigger( OnUnpointed );
}
}
}
}
}

View File

@ -0,0 +1,48 @@
using Godot;
using System.Collections;
using System.Collections.Generic;
using Godot.Collections;
namespace Rokojori
{
[GlobalClass]
public partial class Pointer:RJPointer
{
[Export]
public RJPointable pointable;
public override void _Process( double delta )
{
if ( Caster == null )
{
return;
}
var currentCollider = Caster.NumColliders() == 0 ? null : Caster.GetCollider( 0 );
var currentPointable = currentCollider == null ? null : Nodes.Find<RJPointable>( currentCollider );
// RJLog.Log( currentCollider, currentPointable );
if ( currentPointable == pointable )
{
return;
}
if ( pointable != null )
{
pointable.UpdatePointerState( this, false );
}
pointable = currentPointable;
if ( pointable != null )
{
pointable.UpdatePointerState( this, true );
}
}
}
}

View File

@ -23,7 +23,7 @@ namespace Rokojori
public static Vector3 GetGlobalForward( Node3D node )
{
return node.GlobalBasis.Z;
return -node.GlobalBasis.Z;
}
public static Vector3 GetGlobalUp( Node3D node )

View File

@ -0,0 +1,44 @@
using Godot;
using System.Collections;
using System.Collections.Generic;
namespace Rokojori
{
public class CollisionData
{
public bool hasCollision = false;
public Node collider;
public Vector3 normal;
public Vector3 position;
public Shape3D shape;
public Rid rid;
public void Get( PhysicsRayQueryParameters3D ray, PhysicsDirectSpaceState3D physicsState )
{
var result = physicsState.IntersectRay( ray );
if ( ! result.ContainsKey( "collider" ) )
{
hasCollision = false;
return;
}
hasCollision = true;
collider = result[ "collider" ].As<Node>();
normal = result[ "normal" ].AsVector3();
position = result[ "position" ].AsVector3();
shape = result[ "shape" ].As<Shape3D>();
rid = result[ "rid" ].AsRid();
// RJLog.Log( "Has Collision:", HierarchyName.Of( collider ), ">> at position:", position, "with normal:", normal );
}
}
}

View File

@ -0,0 +1,67 @@
using System.Collections;
using System.Collections.Generic;
using System;
using System.Reflection;
using System.Text.RegularExpressions;
namespace Rokojori
{
public class MultiValueSorter<T>
{
List<ValueSorter<T>> valueSorters = new List<ValueSorter<T>>();
public void AddValueSorter( Func<T,float> getFloatValue, bool reverse = false )
{
var valueSorter = ValueSorter<T>.Create( getFloatValue, reverse );
valueSorters.Add( valueSorter );
}
public void Sort( List<T> data )
{
valueSorters.ForEach( v => v.ClearCache() );
data.Sort( ( a, b ) => Compare( a, b ) );
}
public void Sort( int index, int count, List<T> data )
{
valueSorters.ForEach( v => v.ClearCache() );
data.Sort( index, count, Comparer<T>.Create( ( a, b ) => Compare( a, b ) ) );
}
public int Compare( T a, T b )
{
for ( int i = 0; i < valueSorters.Count; i++ )
{
var valueProvider = valueSorters[ 0 ];
var result = valueProvider.Compare( a, b );
if ( result != 0 )
{
return result;
}
}
return 0;
}
public static MultiValueSorter<T> Create( params Func<T,float>[] valueSorterFunctions )
{
var multiSorter = new MultiValueSorter<T>();
for ( int i = 0; i < valueSorterFunctions.Length; i++ )
{
multiSorter.AddValueSorter( valueSorterFunctions[ i ] );
}
return multiSorter;
}
public static void SortBy( List<T> data, params Func<T,float>[] valueSorterFunctions )
{
Create( valueSorterFunctions ).Sort( data );
}
}
}

View File

@ -0,0 +1,73 @@
using System.Collections;
using System.Collections.Generic;
using System;
using System.Reflection;
using System.Text.RegularExpressions;
namespace Rokojori
{
public class ValueSorter<T>
{
Func<T,float> getFloatValue;
bool reverse_highestFirst = false;
Dictionary<T,float> cachedValues = new Dictionary<T, float>();
public static ValueSorter<T> Create( Func<T,float> getFloatValue, bool reverse_highestFirst = false )
{
var vs = new ValueSorter<T>();
vs.getFloatValue = getFloatValue;
vs.reverse_highestFirst = reverse_highestFirst;
return vs;
}
public void ClearCache()
{
cachedValues.Clear();
}
public float GetValue( T t )
{
if ( ! cachedValues.ContainsKey( t ) )
{
cachedValues[ t ] = getFloatValue( t );;
}
return cachedValues[ t ];
}
public int Compare( T a, T b )
{
var valueA = GetValue( a );
var valueB = GetValue( b );
if ( valueA != valueB )
{
var difference = valueA - valueB;
if ( reverse_highestFirst )
{
difference = - difference;
}
return MathF.Sign( difference );
}
return 0;
}
public void Sort( List<T> data )
{
ClearCache();
data.Sort( ( a, b ) => Compare( a, b ) );
}
public void Sort( int index, int count, List<T> data )
{
ClearCache();
data.Sort( index, count, Comparer<T>.Create( ( a, b ) => Compare( a, b ) ) );
}
}
}

18
Runtime/Tools/Arrays.cs Normal file
View File

@ -0,0 +1,18 @@
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System;
namespace Rokojori
{
public class Arrays
{
public static void ForEach<T>( T[] values, Action<T> callback )
{
foreach ( var it in values )
{
callback( it );
}
}
}
}

View File

@ -168,7 +168,7 @@ namespace Rokojori
GlobalRotation = new Vector3( Mathf.DegToRad( pitch ), Mathf.DegToRad( yaw ), 0 );
var forward = Math3D.GetGlobalForward( this ) * smoothDistance;
GlobalPosition = target - forward;
GlobalPosition = target + forward;
}
}
}

View File

@ -220,7 +220,7 @@ namespace Rokojori
GlobalRotation = new Vector3( Mathf.DegToRad( pitch ), Mathf.DegToRad( yaw ), 0 );
var forward = Math3D.GetGlobalForward( this ) * smoothDistance;
GlobalPosition = target - forward;
GlobalPosition = target + forward;
}
}
}