C# Only Update

This commit is contained in:
Josef 2025-01-08 19:46:17 +01:00
parent b852e63bf0
commit 73df307cef
157 changed files with 4274 additions and 731 deletions

View File

@ -1,5 +1,6 @@
using Godot; using Godot;
using System.Collections.Generic;
namespace Rokojori namespace Rokojori
@ -7,15 +8,154 @@ namespace Rokojori
[GlobalClass ] [GlobalClass ]
public partial class Action : NetworkNode public partial class Action : NetworkNode
{ {
public void Trigger() NetworkNodeSlot _seedSlot = new NetworkNodeSlot();
{ NetworkNodeSlot _dataSlot = new NetworkNodeSlot();
_OnTrigger(); NetworkNodeSlot _seedAndDataSlot = new NetworkNodeSlot();
}
public virtual void _OnTrigger() protected override List<NetworkNodeMember> CreateNetworkNodeMembers()
{
return new List<NetworkNodeMember>()
{
_networkNodeSlot,
_seedSlot,
_dataSlot,
_seedAndDataSlot
};
}
public Action()
{ {
} }
public void Trigger()
{
_isNetworkedTrigger = false;
_sendsSeed = false;
_sendsData = false;
_OnTrigger();
SendOverNetwork();
}
protected void SendOverNetwork()
{
// check which type
// 0 0 => vanilla
// 1 0 => with seed
// 0 1 => with data
// 1 1 => with seed + data
}
protected void _OnNetworkTrigger( int seed, BitView data )
{
_isNetworkedTrigger = true;
_receivedNetworkSeed = seed;
_receivedNetworkData = data;
_OnTrigger();
_isNetworkedTrigger = false;
}
bool _isNetworkedTrigger = false;
int _receivedNetworkSeed = -1;
int _sendingNetworkSeed = -1;
bool _sendsSeed = false;
bool _sendsData = false;
BitView _sendingNetworkData;
BitView _receivedNetworkData;
protected bool isNetworkedTrigger => _isNetworkedTrigger;
static readonly int maxNetworkSeed = Mathf.RoundToInt( Mathf.Pow( 2, 30 ) );
protected int networkSeed
{
get
{
if ( _isNetworkedTrigger )
{
return _receivedNetworkSeed;
}
if ( _sendsSeed )
{
return _sendingNetworkSeed;
}
_sendingNetworkSeed = GodotRandom.Get().IntegerExclusive( 0, maxNetworkSeed );
_sendsSeed = true;
return _sendingNetworkSeed;
}
}
protected BitView GetNetworkData( BitView view )
{
if ( _isNetworkedTrigger )
{
return _receivedNetworkData;
}
_sendingNetworkData = view;
_sendsData = true;
return _sendingNetworkData;
}
protected virtual void _OnTrigger()
{
}
public static void Trigger( Action action )
{
if ( action == null )
{
return;
}
action.Trigger();
}
public static void TriggerAll( Action[] actions, Node target, bool triggerDirectChildren )
{
if ( actions != null )
{
for ( int i = 0; i < actions.Length; i++ )
{
Action.Trigger( actions[ i ] );
}
}
if ( ! triggerDirectChildren )
{
return;
}
Nodes.ForEachDirectChild<Action>( target, a => Action.Trigger( a ) );
}
public static void TriggerAll( Action action, Node target, bool triggerDirectChildren )
{
if ( action != null )
{
Action.Trigger( action );
}
if ( ! triggerDirectChildren )
{
return;
}
Nodes.ForEachDirectChild<Action>( target, a => Action.Trigger( a ) );
}
} }
} }

View File

@ -7,33 +7,33 @@ namespace Rokojori
/** <summary for="class ActionList"> /** <summary for="class ActionList">
<title> <title>
Executes multiple actions (RJAction) at once. Executes multiple actions (Action) at once.
</title> </title>
<description> <description>
The ActionList, which is an RJAction itself, executes all actions stored in the member 'actions' and also child nodes The ActionList, which is an Action itself, executes all actions stored in the member 'actions' and also child nodes
that extend RJAction, when 'triggerDirectChildren' is checked. that extend Action, when 'triggerDirectChildren' is checked.
</description> </description>
</summary> </summary>
*/ */
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/RJActionList.svg") ] [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/ActionList.svg") ]
public partial class ActionList : RJAction public partial class ActionList : Action
{ {
/** <summary for="field actions">Actions to execute</summary>*/ /** <summary for="field actions">Actions to execute</summary>*/
[Export] [Export]
public RJAction[] actions; public Action[] actions;
/** <summary for="field triggerDirectChildren">Whether to execute RJAction child nodes</summary>*/ /** <summary for="field triggerDirectChildren">Whether to execute Action child nodes</summary>*/
[Export] [Export]
public bool triggerDirectChildren = true; public bool triggerDirectChildren = true;
public override void _OnTrigger() protected override void _OnTrigger()
{ {
Actions.TriggerAll( actions, this, triggerDirectChildren ); Action.TriggerAll( actions, this, triggerDirectChildren );
} }
} }
} }

View File

@ -5,14 +5,14 @@ using Godot;
namespace Rokojori namespace Rokojori
{ {
[GlobalClass ] [GlobalClass ]
public partial class ActionReference : RJAction public partial class ActionReference : Action
{ {
[Export] [Export]
public RJAction referencedAction; public Action referencedAction;
public override void _OnTrigger() protected override void _OnTrigger()
{ {
Actions.Trigger( referencedAction ); Action.Trigger( referencedAction );
} }
} }

View File

@ -11,15 +11,15 @@ namespace Rokojori
public class ActionSequenceRunner public class ActionSequenceRunner
{ {
public ActionSequence sequence; public ActionSequence sequence;
public List<RJAction> actions; public List<Action> actions;
public List<RJSequenceAction> sequencables; public List<SequenceAction> sequencables;
public int sequencablesIndex = 0; public int sequencablesIndex = 0;
bool cancelled = false; bool cancelled = false;
bool cancelledSequence = false; bool cancelledSequence = false;
int _runID = -1; int _runID = -1;
RJSequenceAction _runningAction; SequenceAction _runningAction;
int _runningActionID = -1; int _runningActionID = -1;
public void Cancel() public void Cancel()
@ -61,7 +61,7 @@ namespace Rokojori
if ( sequencables.Count == 0 ) if ( sequencables.Count == 0 )
{ {
actions.ForEach( a => Actions.Trigger( a ) ); actions.ForEach( a => Action.Trigger( a ) );
sequence.DispatchEnd( _runID ); sequence.DispatchEnd( _runID );
sequence.ClearRun( this ); sequence.ClearRun( this );
return; return;
@ -87,20 +87,21 @@ namespace Rokojori
StartAction( sequenceAction ); StartAction( sequenceAction );
} }
Dictionary<RJSequenceAction,RJSequenceAction.OnSequenceDoneEventHandler> callbacks = Dictionary<SequenceAction,System.Action<SequenceActionFinishedEvent>> callbacks =
new Dictionary<RJSequenceAction, RJSequenceAction.OnSequenceDoneEventHandler>(); new Dictionary<SequenceAction, System.Action<SequenceActionFinishedEvent>>();
void StartAction( RJSequenceAction action ) void StartAction( SequenceAction action )
{ {
var capturedAction = action; var capturedAction = action;
RJSequenceAction.OnSequenceDoneEventHandler callback = System.Action<SequenceActionFinishedEvent> callback =
( long id, bool success ) => ( SequenceActionFinishedEvent ev ) =>
{ {
//RJLog.Log( "On Done", id, success ); //RJLog.Log( "On Done", id, success );
if ( id != _runningActionID ) if ( ev.id != _runningActionID )
{ {
// RJLog.Error( "Invalid ID", id, "!=", _runningActionID ); // RJLog.Error( "Invalid ID", id, "!=", _runningActionID );
return; return;
@ -108,7 +109,7 @@ namespace Rokojori
_runningActionID = -1; _runningActionID = -1;
if ( success ) if ( ev.success )
{ {
sequencablesIndex ++; sequencablesIndex ++;
ProcessNext(); ProcessNext();
@ -120,7 +121,7 @@ namespace Rokojori
} }
var callbackReference = callbacks[ capturedAction ]; var callbackReference = callbacks[ capturedAction ];
capturedAction.OnSequenceDone -= callbackReference; capturedAction.onSequenceDone.RemoveAction( callbackReference );
callbacks.Remove( capturedAction ); callbacks.Remove( capturedAction );
}; };
@ -132,54 +133,54 @@ namespace Rokojori
callbacks[ _runningAction ] = callback; callbacks[ _runningAction ] = callback;
_runningAction.OnSequenceDone += callback; _runningAction.OnSequenceDone += callback;
TriggerAllBefore( _runningAction ); TriggerAllBefore( _runningAction );
Actions.Trigger( _runningAction ); Action.Trigger( _runningAction );
_runningActionID = _runningAction.GetLastSequenceActionID(); _runningActionID = _runningAction.GetLastSequenceActionID();
*/ */
} }
void RunNext( RJSequenceAction action, RJSequenceAction.OnSequenceDoneEventHandler callback ) void RunNext( SequenceAction action, System.Action<SequenceActionFinishedEvent> callback )
{ {
_runningAction = action; _runningAction = action;
callbacks[ _runningAction ] = callback; callbacks[ _runningAction ] = callback;
_runningAction.OnSequenceDone += callback; _runningAction.onSequenceDone.AddAction( callback );
TriggerAllBefore( _runningAction ); TriggerAllBefore( _runningAction );
Actions.Trigger( _runningAction ); Action.Trigger( _runningAction );
_runningActionID = _runningAction.GetLastSequenceActionID(); _runningActionID = _runningAction.GetLastSequenceActionID();
} }
void TriggerAllBefore( RJSequenceAction action ) void TriggerAllBefore( SequenceAction action )
{ {
var actionIndex = actions.IndexOf( action ); var actionIndex = actions.IndexOf( action );
for ( int i = actionIndex - 1; i >= 0; i -- ) for ( int i = actionIndex - 1; i >= 0; i -- )
{ {
if ( typeof( RJSequenceAction ).IsAssignableFrom( actions[ i ].GetType() ) ) if ( typeof( SequenceAction ).IsAssignableFrom( actions[ i ].GetType() ) )
{ {
return; return;
} }
RJLog.Log( "Triggering Action", actions[ i ].Name ); RJLog.Log( "Triggering Action", actions[ i ].Name );
Actions.Trigger( actions[ i ] ); Action.Trigger( actions[ i ] );
} }
} }
void TriggerAllAfter( RJSequenceAction action ) void TriggerAllAfter( SequenceAction action )
{ {
var actionIndex = actions.IndexOf( action ); var actionIndex = actions.IndexOf( action );
for ( int i = actionIndex + 1; i < actions.Count; i ++ ) for ( int i = actionIndex + 1; i < actions.Count; i ++ )
{ {
if ( typeof( RJSequenceAction ).IsAssignableFrom( actions[ i ].GetType() ) ) if ( typeof( SequenceAction ).IsAssignableFrom( actions[ i ].GetType() ) )
{ {
return; return;
} }
RJLog.Log( "Triggering Action", actions[ i ].Name ); RJLog.Log( "Triggering Action", actions[ i ].Name );
Actions.Trigger( actions[ i ] ); Action.Trigger( actions[ i ] );
} }
} }
@ -187,30 +188,30 @@ namespace Rokojori
} }
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/RJActionSequence.svg") ] [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/ActionSequence.svg") ]
public partial class ActionSequence:RJSequenceAction public partial class ActionSequence:SequenceAction
{ {
/** <summary for="field actions">Actions to execute</summary>*/ /** <summary for="field actions">Actions to execute</summary>*/
[Export] [Export]
public RJAction[] actions; public Action[] actions;
[Export] [Export]
public bool triggerDirectChildren = true; public bool triggerDirectChildren = true;
List<ActionSequenceRunner> running = new List<ActionSequenceRunner>(); List<ActionSequenceRunner> running = new List<ActionSequenceRunner>();
public override void _OnTrigger() protected override void _OnTrigger()
{ {
var run = new ActionSequenceRunner(); var run = new ActionSequenceRunner();
run.sequence = this; run.sequence = this;
run.actions = new List<RJAction>( actions ); run.actions = new List<Action>( actions );
if ( triggerDirectChildren ) if ( triggerDirectChildren )
{ {
Nodes.ForEachDirectChild<RJAction>( this, a => run.actions.Add( a ) ); Nodes.ForEachDirectChild<Action>( this, a => run.actions.Add( a ) );
} }
run.sequencables = Lists.FilterType<RJAction,RJSequenceAction>( run.actions ); run.sequencables = Lists.FilterType<Action,SequenceAction>( run.actions );

View File

@ -1,53 +0,0 @@
using Godot;
namespace Rokojori
{
public class Actions
{
public static void Trigger( RJAction action )
{
if ( action == null )
{
return;
}
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 ) );
}
public static void TriggerAll( RJAction action, Node target, bool triggerDirectChildren )
{
if ( action != null )
{
Actions.Trigger( action );
}
if ( ! triggerDirectChildren )
{
return;
}
Nodes.ForEachDirectChild<RJAction>( target, a => Actions.Trigger( a ) );
}
}
}

View File

@ -5,7 +5,7 @@ using Godot;
namespace Rokojori namespace Rokojori
{ {
[GlobalClass] [GlobalClass]
public partial class Delay : RJSequenceAction public partial class Delay : SequenceAction
{ {
[Export] [Export]
public float duration; public float duration;
@ -14,10 +14,10 @@ namespace Rokojori
public string message; public string message;
[Export] [Export]
public RJTimeLine timeLine; public TimeLine timeLine;
public override void _OnTrigger() protected override void _OnTrigger()
{ {
var sequenceID = DispatchStart(); var sequenceID = DispatchStart();

View File

@ -5,15 +5,15 @@ using Godot;
namespace Rokojori namespace Rokojori
{ {
[GlobalClass ] [GlobalClass ]
public partial class IterateActions : RJAction public partial class IterateActions : Action
{ {
[ExportGroup( "Read Only")] [ExportGroup( "Read Only")]
[Export] [Export]
public int iterationIndex = 0; public int iterationIndex = 0;
public override void _OnTrigger() protected override void _OnTrigger()
{ {
var num = this.NumDirectChildrenOf<RJAction>(); var num = this.NumDirectChildrenOf<Action>();
if ( num == 0 ) if ( num == 0 )
{ {
@ -23,7 +23,7 @@ namespace Rokojori
iterationIndex = MathX.Repeat( iterationIndex, num ); iterationIndex = MathX.Repeat( iterationIndex, num );
Actions.Trigger( this.GetNthDirectChild<RJAction>( iterationIndex ) ); Action.Trigger( this.GetNthDirectChild<Action>( iterationIndex ) );
iterationIndex++; iterationIndex++;
} }

View File

@ -5,7 +5,7 @@ using System.Collections.Generic;
namespace Rokojori namespace Rokojori
{ {
[GlobalClass] [GlobalClass]
public partial class LoadScene : RJSequenceAction public partial class LoadScene : SequenceAction
{ {
[Export] [Export]
public string scenePath; public string scenePath;
@ -14,13 +14,13 @@ namespace Rokojori
public Node target; public Node target;
[Export] [Export]
public RJAction onLoaded; public Action onLoaded;
bool _loading = false; bool _loading = false;
int _id = -1; int _id = -1;
List<int> _cached = new List<int>(); List<int> _cached = new List<int>();
public override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( _loading ) if ( _loading )
{ {
@ -59,7 +59,7 @@ namespace Rokojori
var packedScene = (PackedScene) ResourceLoader.LoadThreadedGet( scenePath ); var packedScene = (PackedScene) ResourceLoader.LoadThreadedGet( scenePath );
var node = packedScene.Instantiate(); var node = packedScene.Instantiate();
target.AddChild( node ); target.AddChild( node );
Actions.Trigger( onLoaded ); Action.Trigger( onLoaded );
DispatchEnd( _id ); DispatchEnd( _id );
_id = -1; _id = -1;
@ -67,7 +67,7 @@ namespace Rokojori
( c )=> ( c )=>
{ {
target.AddChild( packedScene.Instantiate() ); target.AddChild( packedScene.Instantiate() );
Actions.Trigger( onLoaded ); Action.Trigger( onLoaded );
DispatchEnd( c ); DispatchEnd( c );
} }
); );

View File

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

View File

@ -5,7 +5,7 @@ using Godot;
namespace Rokojori namespace Rokojori
{ {
[GlobalClass ] [GlobalClass ]
public partial class CopyMousePosition : RJAction public partial class CopyMousePosition : Action
{ {
[Export] [Export]
public Camera3D camera; public Camera3D camera;
@ -17,7 +17,7 @@ namespace Rokojori
public Node3D target; public Node3D target;
public override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( camera == null || target == null ) if ( camera == null || target == null )
{ {

View File

@ -5,7 +5,7 @@ using Godot;
namespace Rokojori namespace Rokojori
{ {
[GlobalClass, Tool ] [GlobalClass, Tool ]
public partial class CopyPose : RJAction public partial class CopyPose : Action
{ {
[Export] [Export]
public Node3D source; public Node3D source;
@ -20,7 +20,7 @@ namespace Rokojori
} }
public override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( source == null || target == null ) if ( source == null || target == null )
{ {

View File

@ -5,7 +5,7 @@ using Godot;
namespace Rokojori namespace Rokojori
{ {
[GlobalClass, Tool ] [GlobalClass, Tool ]
public partial class CopyPosition : RJAction public partial class CopyPosition : Action
{ {
[Export] [Export]
public Node3D source; public Node3D source;
@ -20,7 +20,7 @@ namespace Rokojori
} }
public override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( source == null || target == null ) if ( source == null || target == null )
{ {

View File

@ -5,7 +5,7 @@ using Godot;
namespace Rokojori namespace Rokojori
{ {
[GlobalClass, Tool ] [GlobalClass, Tool ]
public partial class DistributeChildren : RJAction public partial class DistributeChildren : Action
{ {
[Export] [Export]
public Node3D target; public Node3D target;
@ -23,7 +23,7 @@ namespace Rokojori
} }
public override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( start == null || end == null || target == null ) if ( start == null || end == null || target == null )
{ {

View File

@ -4,7 +4,7 @@ using Godot;
namespace Rokojori namespace Rokojori
{ {
[GlobalClass ] [GlobalClass ]
public partial class LerpPosition : RJAction public partial class LerpPosition : Action
{ {
[Export] [Export]
public Node3D sourceA; public Node3D sourceA;
@ -18,7 +18,7 @@ namespace Rokojori
[Export] [Export]
public Node3D target; public Node3D target;
public override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( sourceA == null || sourceB == null || target == null ) if ( sourceA == null || sourceB == null || target == null )
{ {

View File

@ -4,7 +4,7 @@ using Godot;
namespace Rokojori namespace Rokojori
{ {
[GlobalClass, Tool ] [GlobalClass, Tool ]
public partial class LookAt : RJAction public partial class LookAt : Action
{ {
[Export] [Export]
public Node3D lookTarget; public Node3D lookTarget;
@ -17,7 +17,7 @@ namespace Rokojori
_OnTrigger(); _OnTrigger();
} }
public override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( lookFrom == null || lookTarget == null ) if ( lookFrom == null || lookTarget == null )
{ {

View File

@ -9,15 +9,15 @@ namespace Rokojori
{ {
/** <summary for="field actions">Actions to execute</summary>*/ /** <summary for="field actions">Actions to execute</summary>*/
[Export] [Export]
public RJAction[] actions; public Action[] actions;
/** <summary for="field triggerDirectChildren">Whether to execute RJAction child nodes</summary>*/ /** <summary for="field triggerDirectChildren">Whether to execute Action child nodes</summary>*/
[Export] [Export]
public bool triggerDirectChildren = true; public bool triggerDirectChildren = true;
public override void _PhysicsProcess( double delta ) public override void _PhysicsProcess( double delta )
{ {
Actions.TriggerAll( actions, this, triggerDirectChildren ); Action.TriggerAll( actions, this, triggerDirectChildren );
} }
} }
} }

View File

@ -9,9 +9,9 @@ namespace Rokojori
{ {
/** <summary for="field actions">Actions to execute</summary>*/ /** <summary for="field actions">Actions to execute</summary>*/
[Export] [Export]
public RJAction[] actions; public Action[] actions;
/** <summary for="field triggerDirectChildren">Whether to execute RJAction child nodes</summary>*/ /** <summary for="field triggerDirectChildren">Whether to execute Action child nodes</summary>*/
[Export] [Export]
public bool triggerDirectChildren = true; public bool triggerDirectChildren = true;
@ -25,7 +25,7 @@ namespace Rokojori
return; return;
} }
Actions.TriggerAll( actions, this, triggerDirectChildren ); Action.TriggerAll( actions, this, triggerDirectChildren );
} }
} }
} }

View File

@ -9,15 +9,15 @@ namespace Rokojori
{ {
/** <summary for="field actions">Actions to execute</summary>*/ /** <summary for="field actions">Actions to execute</summary>*/
[Export] [Export]
public RJAction[] actions; public Action[] actions;
/** <summary for="field triggerDirectChildren">Whether to execute RJAction child nodes</summary>*/ /** <summary for="field triggerDirectChildren">Whether to execute Action child nodes</summary>*/
[Export] [Export]
public bool triggerDirectChildren = true; public bool triggerDirectChildren = true;
public override void _Ready() public override void _Ready()
{ {
Actions.TriggerAll( actions, this, triggerDirectChildren ); Action.TriggerAll( actions, this, triggerDirectChildren );
} }
} }
} }

View File

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

View File

@ -0,0 +1,68 @@
using Godot;
namespace Rokojori
{
public class SequenceActionFinishedEvent
{
public int id;
public bool success;
}
[GlobalClass ]
public partial class SequenceAction : Action
{
/*
int dispatchStart();
void dispatchCancelled( int id );
void dispatchEnd( int id );
int getLastSequenceActionID();
GDVIRTUAL1( cancelAction, int );
/* signal onSequenceDone * /
*/
int _dispatchCounter = 0;
public int GetLastSequenceActionID()
{
return _dispatchCounter;
}
public readonly EventSlot<SequenceActionFinishedEvent> onSequenceDone = new EventSlot<SequenceActionFinishedEvent>();
public int DispatchStart()
{
_dispatchCounter ++;
return _dispatchCounter;
}
public void DispatchEnd( int id )
{
onSequenceDone.DispatchEvent( new SequenceActionFinishedEvent{ id = id, success = true } );
}
public void DispatchCancelled( int id )
{
onSequenceDone.DispatchEvent( new SequenceActionFinishedEvent{ id = id, success = false } );
}
public virtual void CancelAction( int id )
{
}
}
}

View File

@ -9,7 +9,7 @@ namespace Rokojori
public partial class TriggerActionInEditor : Node public partial class TriggerActionInEditor : Node
{ {
[Export] [Export]
public RJAction action; public Action action;
[Export] [Export]
public bool execute; public bool execute;

View File

@ -21,6 +21,15 @@ namespace Rokojori
public class AnimationMember public class AnimationMember
{ {
public static readonly AnimationMember Position = new AnimationMember( "position" );
public static readonly AnimationMember Rotation = new AnimationMember( "rotation" );
public static readonly AnimationMember Scale = new AnimationMember( "scale" );
public static readonly AnimationMember[] Transform = new AnimationMember[]
{
AnimationMember.Position, AnimationMember.Rotation, AnimationMember.Scale
};
string _name; string _name;
public string name => _name; public string name => _name;
@ -34,18 +43,42 @@ namespace Rokojori
{ {
static MultiMap<Node,string,Animator> _animating = new MultiMap<Node,string,Animator>(); static MultiMap<Node,string,Animator> _animating = new MultiMap<Node,string,Animator>();
public static AnimationMember position = new AnimationMember( "position" );
public static AnimationMember rotation = new AnimationMember( "rotation" );
public static AnimationMember scale = new AnimationMember( "scale" );
public static Animator GetAnimator( Node node, AnimationMember member ) public static Animator GetAnimator( Node node, AnimationMember member )
{ {
return _animating[ node ][ member.name ]; return _animating.Get( node, member.name );
} }
public static bool IsAnimating( Animator animator, Node node, AnimationMember member ) public static bool IsAnimating( Animator animator, Node node, AnimationMember member )
{ {
return GetAnimator( node, member ) == animator; return GetAnimator( node, member ) == animator;
}
public static bool IsAnimating( Animator animator, Node node, params AnimationMember[] members )
{
for ( int i = 0; i < members.Length; i++ )
{
if ( ! IsAnimating( animator, node, members[ i ] ) )
{
return false;
}
}
return members.Length > 0;
}
public static bool IsAnimating( Animator animator, Node[] nodes, params AnimationMember[] members )
{
for ( int i = 0; i < nodes.Length; i++ )
{
if ( ! IsAnimating( animator, nodes[ i ], members ) )
{
return false;
}
}
return nodes.Length > 0;
} }
public static void StartAnimation( Animator animator, Node node, AnimationMember member ) public static void StartAnimation( Animator animator, Node node, AnimationMember member )
@ -61,6 +94,22 @@ namespace Rokojori
} }
public static void StartAnimation( Animator animator, Node node, params AnimationMember[] members )
{
for ( int i = 0; i < members.Length; i++ )
{
StartAnimation( animator, node, members[ i ] );
}
}
public static void StartAnimation( Animator animator, Node[] nodes, params AnimationMember[] members )
{
for ( int i = 0; i < nodes.Length; i++ )
{
StartAnimation( animator, nodes[ i ], members );
}
}
public static void EndAnimation( Animator animator, Node node, AnimationMember member ) public static void EndAnimation( Animator animator, Node node, AnimationMember member )
{ {
var activeAnimator = GetAnimator( node, member ); var activeAnimator = GetAnimator( node, member );
@ -70,5 +119,21 @@ namespace Rokojori
activeAnimator.OnAnimatorCancel(); activeAnimator.OnAnimatorCancel();
} }
} }
public static void EndAnimation( Animator animator, Node node, params AnimationMember[] members )
{
for ( int i = 0; i < members.Length; i++ )
{
EndAnimation( animator, node, members[ i ] );
}
}
public static void EndAnimation( Animator animator, Node[] nodes, params AnimationMember[] members )
{
for ( int i = 0; i < nodes.Length; i++ )
{
EndAnimation( animator, nodes[ i ], members );
}
}
} }
} }

View File

@ -8,7 +8,7 @@ namespace Rokojori
{ {
[Tool] [Tool]
[GlobalClass] [GlobalClass]
public partial class Flash:RJSequenceAction public partial class Flash:SequenceAction
{ {
[Export] [Export]
public FlashEffect flashEffect; public FlashEffect flashEffect;
@ -41,22 +41,27 @@ namespace Rokojori
return color; return color;
} }
public override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( actionID != -1 ) if ( actionID != -1 )
{ {
CancelAction( actionID ); CancelAction( actionID );
} }
actionID = DispatchStart(); actionID = DispatchStart();
// RJLog.Log( "Setting actionID id", actionID, GetLastSequenceActionID() ); var random = LCG.Randomized();
var networkSeed = random.GetSeed();
RJLog.Log( "Setting actionID id", actionID, GetLastSequenceActionID() );
var flashCurve = flashEffect.flashCurve; var flashCurve = flashEffect.flashCurve;
var color = flashEffect.color.GetHDRColor(); var color = flashEffect.color.GetHDRColor();
var timeline = flashEffect.timeline; var timeline = flashEffect.timeline;
randomization = flashCurve.Randomize(); randomization = flashCurve.Randomize( random );
var duration = flashCurve.GetRandomizedDuration( randomization ); var duration = flashCurve.GetRandomizedDuration( randomization );
@ -139,7 +144,7 @@ namespace Rokojori
var end = start + duration; var end = start + duration;
animationID = TimeLineScheduler.ScheduleSpanIn( timeline, 0, duration, animationID = TimeLineScheduler.ScheduleSpanIn( timeline, 0, duration,
( int id, int type )=> ( int id, TimeLineSpanUpdateType type )=>
{ {
if ( animationID != id ) if ( animationID != id )
@ -196,7 +201,7 @@ namespace Rokojori
); );
if ( type == TimeLineSpan.End ) if ( type == TimeLineSpanUpdateType.End )
{ {
if ( light != null ) if ( light != null )
{ {

View File

@ -15,6 +15,10 @@ namespace Rokojori
[Export] [Export]
public AnimationCurve flashCurve; public AnimationCurve flashCurve;
[Export]
public TimeLine timeline;
[Export] [Export]
public HDRColor color; public HDRColor color;
@ -61,8 +65,7 @@ namespace Rokojori
[Export] [Export]
public ColorPropertyName customFlashColorProperty; public ColorPropertyName customFlashColorProperty;
[Export]
public RJTimeLine timeline;

View File

@ -2,8 +2,8 @@
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/HDRColor.cs" id="1_ejko8"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/HDRColor.cs" id="1_ejko8"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/AnimationCurve.cs" id="2_3i2og"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/AnimationCurve.cs" id="2_3i2og"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/FlashEffect.cs" id="3_65ipm"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/Flash/FlashEffect.cs" id="3_65ipm"]
[ext_resource type="RJTimeLine" uid="uid://frruktikky46" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/GameTime.tres" id="4_urqjo"] [ext_resource type="Resource" uid="uid://ch5nsa6yafs5l" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/GameTime.tres" id="4_nyaof"]
[sub_resource type="Resource" id="Resource_54hj8"] [sub_resource type="Resource" id="Resource_54hj8"]
script = ExtResource("1_ejko8") script = ExtResource("1_ejko8")
@ -29,10 +29,10 @@ scaleRandomRange = 0.0
[resource] [resource]
script = ExtResource("3_65ipm") script = ExtResource("3_65ipm")
flashCurve = SubResource("Resource_pwp07") flashCurve = SubResource("Resource_pwp07")
timeline = ExtResource("4_nyaof")
color = SubResource("Resource_54hj8") color = SubResource("Resource_54hj8")
lightMode = 1 lightMode = 1
lightRange = 5.0 lightRange = 5.0
lightFlashCurveScale = 5.0 lightFlashCurveScale = 5.0
lightHasShadows = true lightHasShadows = true
materialMode = 3 materialMode = 3
timeline = ExtResource("4_urqjo")

View File

@ -2,8 +2,8 @@
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/HDRColor.cs" id="1_yrhv1"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/HDRColor.cs" id="1_yrhv1"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/AnimationCurve.cs" id="2_cdv3p"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/AnimationCurve.cs" id="2_cdv3p"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/FlashEffect.cs" id="3_87ql1"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/Flash/FlashEffect.cs" id="3_87ql1"]
[ext_resource type="RJTimeLine" uid="uid://frruktikky46" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/GameTime.tres" id="4_t20yf"] [ext_resource type="Resource" uid="uid://ch5nsa6yafs5l" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/GameTime.tres" id="4_2na64"]
[sub_resource type="Resource" id="Resource_54hj8"] [sub_resource type="Resource" id="Resource_54hj8"]
script = ExtResource("1_yrhv1") script = ExtResource("1_yrhv1")
@ -29,10 +29,10 @@ scaleRandomRange = 0.0
[resource] [resource]
script = ExtResource("3_87ql1") script = ExtResource("3_87ql1")
flashCurve = SubResource("Resource_pwp07") flashCurve = SubResource("Resource_pwp07")
timeline = ExtResource("4_2na64")
color = SubResource("Resource_54hj8") color = SubResource("Resource_54hj8")
lightMode = 1 lightMode = 1
lightRange = 5.0 lightRange = 5.0
lightFlashCurveScale = 2.0 lightFlashCurveScale = 2.0
lightHasShadows = true lightHasShadows = true
materialMode = 2 materialMode = 2
timeline = ExtResource("4_t20yf")

View File

@ -2,8 +2,8 @@
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/HDRColor.cs" id="1_c8lnw"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/HDRColor.cs" id="1_c8lnw"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/AnimationCurve.cs" id="2_w323b"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/AnimationCurve.cs" id="2_w323b"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/FlashEffect.cs" id="3_eqd4c"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/Flash/FlashEffect.cs" id="3_eqd4c"]
[ext_resource type="RJTimeLine" uid="uid://frruktikky46" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/GameTime.tres" id="4_03b60"] [ext_resource type="Resource" uid="uid://ch5nsa6yafs5l" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/GameTime.tres" id="4_cs6ks"]
[sub_resource type="Resource" id="Resource_ny3sx"] [sub_resource type="Resource" id="Resource_ny3sx"]
script = ExtResource("1_c8lnw") script = ExtResource("1_c8lnw")
@ -29,10 +29,10 @@ scaleRandomRange = 0.0
[resource] [resource]
script = ExtResource("3_eqd4c") script = ExtResource("3_eqd4c")
flashCurve = SubResource("Resource_pwp07") flashCurve = SubResource("Resource_pwp07")
timeline = ExtResource("4_cs6ks")
color = SubResource("Resource_ny3sx") color = SubResource("Resource_ny3sx")
lightMode = 1 lightMode = 1
lightRange = 4.0 lightRange = 4.0
lightFlashCurveScale = 1.0 lightFlashCurveScale = 1.0
lightHasShadows = false lightHasShadows = false
materialMode = 1 materialMode = 1
timeline = ExtResource("4_03b60")

View File

@ -2,8 +2,8 @@
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/HDRColor.cs" id="1_nmdum"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/HDRColor.cs" id="1_nmdum"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/AnimationCurve.cs" id="2_0sgd7"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/AnimationCurve.cs" id="2_0sgd7"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/FlashEffect.cs" id="3_7qcuh"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/Flash/FlashEffect.cs" id="3_7qcuh"]
[ext_resource type="RJTimeLine" uid="uid://frruktikky46" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/GameTime.tres" id="4_8oykd"] [ext_resource type="Resource" uid="uid://ch5nsa6yafs5l" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/GameTime.tres" id="4_rkq1j"]
[sub_resource type="Resource" id="Resource_54hj8"] [sub_resource type="Resource" id="Resource_54hj8"]
script = ExtResource("1_nmdum") script = ExtResource("1_nmdum")
@ -29,6 +29,10 @@ scaleRandomRange = 0.0
[resource] [resource]
script = ExtResource("3_7qcuh") script = ExtResource("3_7qcuh")
flashCurve = SubResource("Resource_pwp07") flashCurve = SubResource("Resource_pwp07")
timeline = ExtResource("4_rkq1j")
color = SubResource("Resource_54hj8") color = SubResource("Resource_54hj8")
lightMode = 0
lightRange = 2.0
lightFlashCurveScale = 2.0
lightHasShadows = false
materialMode = 0 materialMode = 0
timeline = ExtResource("4_8oykd")

View File

@ -2,8 +2,8 @@
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/HDRColor.cs" id="1_pp4qy"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/HDRColor.cs" id="1_pp4qy"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/AnimationCurve.cs" id="2_f6f0o"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/AnimationCurve.cs" id="2_f6f0o"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/FlashEffect.cs" id="3_dq1j1"] [ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/Flash/FlashEffect.cs" id="3_dq1j1"]
[ext_resource type="RJTimeLine" uid="uid://frruktikky46" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/GameTime.tres" id="4_v17wj"] [ext_resource type="Resource" uid="uid://ch5nsa6yafs5l" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/GameTime.tres" id="4_d6hj6"]
[sub_resource type="Resource" id="Resource_ny3sx"] [sub_resource type="Resource" id="Resource_ny3sx"]
script = ExtResource("1_pp4qy") script = ExtResource("1_pp4qy")
@ -29,10 +29,10 @@ scaleRandomRange = 0.0
[resource] [resource]
script = ExtResource("3_dq1j1") script = ExtResource("3_dq1j1")
flashCurve = SubResource("Resource_pwp07") flashCurve = SubResource("Resource_pwp07")
timeline = ExtResource("4_d6hj6")
color = SubResource("Resource_ny3sx") color = SubResource("Resource_ny3sx")
lightMode = 0 lightMode = 0
lightRange = 2.0 lightRange = 2.0
lightFlashCurveScale = 2.0 lightFlashCurveScale = 2.0
lightHasShadows = false lightHasShadows = false
materialMode = 0 materialMode = 0
timeline = ExtResource("4_v17wj")

View File

@ -0,0 +1,14 @@
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using Godot;
namespace Rokojori
{
public class KeyFrame<T>
{
public float time;
public T data;
}
}

View File

@ -0,0 +1,131 @@
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using Godot;
namespace Rokojori
{
public class KeyFrameAnimation<T>
{
public List<KeyFrame<T>> keyFrames = new List<KeyFrame<T>>();
int _currentIndex = -1;
bool _sorted = false;
public void FlagUnsorted()
{
_sorted = false;
}
public void FlagSorted()
{
_sorted = true;
}
public void Sort()
{
if ( _sorted )
{
return;
}
keyFrames.Sort( ( a, b ) => Mathf.Sign( a.time - b.time ) );
_sorted = true;
}
public KeyFrame<T> GetKeyFrameAt( float time )
{
var index = GetKeyFrameIndexAt( time );
return index == -1 ? null : keyFrames[ index ];
}
public int GetKeyFrameIndexAt( float time )
{
if ( keyFrames.Count == 0 )
{
return -1;
}
Sort();
for ( int i = 0; i < keyFrames.Count; i++ )
{
if ( keyFrames[ i ].time > time )
{
return Mathf.Max( 0, i - 1 );
}
}
if ( _sorted )
{
return keyFrames.Count - 1;
}
if ( IsKeyFrameAt( time, _currentIndex ) )
{
return _currentIndex;
}
_currentIndex = MathX.SafeIndex( _currentIndex, keyFrames );
var kf = keyFrames[ _currentIndex ];
if ( kf.time < time )
{
_currentIndex ++;
while ( _currentIndex < keyFrames.Count )
{
if ( IsKeyFrameAt( time, _currentIndex ) )
{
return _currentIndex;
}
_currentIndex ++;
}
}
else
{
_currentIndex --;
while ( _currentIndex > -1 )
{
if ( IsKeyFrameAt( time, _currentIndex ) )
{
return _currentIndex;
}
_currentIndex --;
}
}
return -1;
}
bool IsKeyFrameAt( float time, int index )
{
if ( index < 0 || index >= keyFrames.Count -1 )
{
return false;
}
var i = keyFrames[ index ];
if ( i.time < time && index == keyFrames.Count - 1 )
{
return true;
}
var n = keyFrames[ index + 1 ];
return i.time < time && time < n.time;
}
}
}

View File

@ -0,0 +1,49 @@
[gd_resource type="Resource" script_class="ShakeEffect" load_steps=8 format=3 uid="uid://c2wbn25rxynk8"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/Shake/ShakeEffect.cs" id="1_41sot"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/AnimationCurve.cs" id="2_rwbu4"]
[ext_resource type="Resource" uid="uid://h6oi6vkj4c2m" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/RealTime.tres" id="3_rqeiy"]
[sub_resource type="Curve" id="Curve_j2uji"]
min_value = -1.0
_data = [Vector2(0, 1), 0.0, -0.608916, 0, 0, Vector2(1, -1), -3.46819, 0.0, 0, 0]
point_count = 2
[sub_resource type="Resource" id="Resource_jwnpm"]
script = ExtResource("2_rwbu4")
duration = 0.4
durationRandomRange = 0.0
delay = 0.0
delayRandomRange = 0.0
curve = SubResource("Curve_j2uji")
scaleY = 1.0
scaleRandomRange = 0.0
[sub_resource type="Curve" id="Curve_b6b7u"]
_data = [Vector2(0, 0.368339), 0.0, 3.25035, 0, 0, Vector2(0.264591, 0.73511), 0.0, 0.0, 0, 0, Vector2(1, 0.266458), -0.637268, 0.0, 1, 0]
point_count = 3
[sub_resource type="Resource" id="Resource_1s2e6"]
script = ExtResource("2_rwbu4")
duration = 0.5
durationRandomRange = 0.0
delay = 0.0
delayRandomRange = 0.0
curve = SubResource("Curve_b6b7u")
scaleY = 30.0
scaleRandomRange = 0.0
[resource]
script = ExtResource("1_41sot")
shakeAmountCurve = SubResource("Resource_jwnpm")
shakeChangeFPSCurve = SubResource("Resource_1s2e6")
timeline = ExtResource("3_rqeiy")
smooth = true
smoothingStrength = 0.291
positionShake = Vector3(0.075, 0, 0.075)
globalPosition = true
repeatAndFlipFirstPosition = true
rotationShake = Vector3(2, 2, 40)
globalRotation = false
scaleShake = Vector3(0.5, 0.5, 0.1)
scaleShakeIsRelative = true

View File

@ -8,7 +8,7 @@ namespace Rokojori
{ {
[Tool] [Tool]
[GlobalClass] [GlobalClass]
public partial class Shake:RJSequenceAction public partial class Shake:SequenceAction, Animator
{ {
[Export] [Export]
public ShakeEffect shakeEffect; public ShakeEffect shakeEffect;
@ -16,45 +16,159 @@ namespace Rokojori
[Export] [Export]
public Node3D[] targets; public Node3D[] targets;
List<Transform3D> _targetValues; List<TransformData> _targetValues;
int actionID = -1; int _actionID = -1;
int animationID = -1; int _currentSpanAnimationID = -1;
public override void _OnTrigger() public void OnAnimatorStart(){}
public void OnAnimatorEnd(){}
public void OnAnimatorCancel(){}
protected override void _OnTrigger()
{ {
if ( actionID != -1 ) if ( _actionID != -1 )
{ {
CancelAction( actionID ); CancelAction( _actionID );
} }
actionID = DispatchStart(); _actionID = DispatchStart();
var random = shakeEffect.shakeCurve.Randomize(); var random = LCG.Randomized();
var networkSeed = random.GetSeed();
var randomization = shakeEffect.shakeAmountCurve.Randomize( random );
var timeline = shakeEffect.timeline; var timeline = shakeEffect.timeline;
var duration = shakeEffect.shakeCurve.GetRandomizedEndTime( random ); var duration = shakeEffect.shakeAmountCurve.GetRandomizedEndTime( randomization );
var curve = shakeEffect;
var start = TimeLineManager.GetPosition( shakeEffect.timeline ); var start = TimeLineManager.GetPosition( shakeEffect.timeline );
var end = start + duration;
var keyFrames = new List<KeyFrame<TransformData>>();
var elapsed = 0f;
while ( elapsed < duration )
{
var key = new KeyFrame<TransformData>();
key.data = shakeEffect.GetShakeData( elapsed, randomization, random );
key.time = elapsed;
keyFrames.Add( key );
elapsed += 1f / shakeEffect.GetShakeChangeFPSRandomized( elapsed, random );
}
var kfAnimation = new KeyFrameAnimation<TransformData>();
kfAnimation.keyFrames = keyFrames;
kfAnimation.FlagSorted();
KeyFrame<TransformData> lastKeyFrame = null;
AnimationManager.StartAnimation( this, targets, AnimationMember.Transform );
if ( _targetValues == null || _targetValues.Count == 0 )
{
_targetValues = Lists.Map( targets, t => TransformData.From( t, shakeEffect.globalPosition, shakeEffect.globalRotation ) );
}
animationID = TimeLineScheduler.ScheduleSpanIn( timeline, 0, duration,
( int id, int type )=> _currentSpanAnimationID = TimeLineScheduler.ScheduleSpanIn( timeline, 0, duration,
{ ( int spanAnimationID, TimeLineSpanUpdateType type )=>
if ( animationID != id ) {
if ( spanAnimationID != _currentSpanAnimationID )
{ {
return; return;
} }
if ( ! AnimationManager.IsAnimating( this, targets, AnimationMember.Transform ) )
{
return;
}
if ( TimeLineSpanUpdateType.End == type )
{
AnimationManager.EndAnimation( this, targets, AnimationMember.Transform );
for ( int i = 0; i < targets.Length; i++ )
{
var o = _targetValues[ i ];
o.Set( targets[ i ], shakeEffect.globalPosition, shakeEffect.globalRotation );
}
_targetValues.Clear();
_actionID = -1;
_currentSpanAnimationID = -1;
return;
}
var offset = TimeLineManager.GetPosition( shakeEffect.timeline ) - start;
var keyFrame = kfAnimation.GetKeyFrameAt( offset );
if ( keyFrame == lastKeyFrame && ! shakeEffect.smooth )
{
return;
}
var offsetData = keyFrame.data;
var delta = shakeEffect.timeline.delta;
for ( int i = 0; i < targets.Length; i++ )
{
var combined = offsetData.Clone();
var o = _targetValues[ i ];
if ( shakeEffect.scaleShakeIsRelative )
{
combined.scale *= _targetValues[ i ].scale;
}
combined.rotation *= MathX.DegreesToRadians;
var beforeAdd = combined.Clone();
combined.Add( o );
// this.LogInfo( "Applying:", beforeAdd, " + ", o, "=", combined );
if ( shakeEffect.smooth )
{
var rawSmooth = Mathf.Clamp( shakeEffect.smoothingStrength, 0, 1 );
rawSmooth = Mathf.Pow( 1f - rawSmooth, 3 );
var smoothStrength = rawSmooth * 250f;
var current = TransformData.From( targets[ i ], shakeEffect.globalPosition, shakeEffect.globalRotation );
combined.position = Smoother.SmoothTimeInvariant( current.position, combined.position, delta, smoothStrength );
combined.rotation = Smoother.SmoothTimeInvariant( current.rotation, combined.rotation, delta, smoothStrength );
combined.scale = Smoother.SmoothTimeInvariant( current.scale, combined.scale, delta, smoothStrength );
}
combined.Set( targets[ i ], shakeEffect.globalPosition, shakeEffect.globalRotation );
}
lastKeyFrame = keyFrame;
} }
); );
} }
public override void CancelAction( int id ) public override void CancelAction( int actionID )
{ {
if ( actionID != _actionID )
{
return;
}
AnimationManager.EndAnimation( this, targets, AnimationMember.Transform );
_actionID = -1;
_currentSpanAnimationID = -1;
} }
} }
} }

View File

@ -12,27 +12,63 @@ namespace Rokojori
{ {
[Export] [Export]
public AnimationCurve shakeCurve; public AnimationCurve shakeAmountCurve;
[Export]
public AnimationCurve shakeChangeFPSCurve;
[Export]
public AnimationCurve shakeChangeFPSRandomCurve;
[Export]
public TimeLine timeline;
[Export]
public bool smooth = true;
[Export( PropertyHint.Range, "0,1" )]
public float smoothingStrength = 0;
public float GetShakeChangeFPSRandomized( float time, RandomEngine random = null )
{
random = RandomEngine.CreateIfNull( random );
var staticChange = shakeChangeFPSCurve == null ? 10 : shakeChangeFPSCurve.Sample( time );
var randomChange = shakeChangeFPSRandomCurve == null ? 0 : shakeChangeFPSRandomCurve.Sample( time );
return staticChange + random.Polar( randomChange );
}
[Export] [Export]
public Vector3 positionShake = Vector3.Zero; public Vector3 positionShake = Vector3.Zero;
[Export] [Export]
public Vector3 positionShakeRandom = Vector3.Zero; public bool globalPosition = true;
[Export]
public bool repeatAndFlipFirstPosition = true;
[Export] [Export]
public Vector3 rotationShake = Vector3.Zero; public Vector3 rotationShake = Vector3.Zero;
[Export] [Export]
public Vector3 rotationShakeRandom = Vector3.Zero; public bool globalRotation = true;
[Export] [Export]
public Vector3 scaleShake = Vector3.Zero; public Vector3 scaleShake = Vector3.Zero;
[Export]
public Vector3 scaleShakeRandom = Vector3.Zero;
[Export]
public bool scaleIsPercentage = true;
[Export] [Export]
public RJTimeLine timeline; public bool scaleShakeIsRelative = true;
public TransformData GetShakeData( float time, Vector3 curveRandomization, RandomEngine random = null )
{
random = RandomEngine.CreateIfNull( random );
var shakeAmount = shakeAmountCurve.Sample( time, curveRandomization );
var transformData = new TransformData();
transformData.position = random.IndividualBetween( -positionShake, positionShake ) * shakeAmount;
transformData.rotation = random.IndividualBetween( -rotationShake, rotationShake ) * shakeAmount;
transformData.scale = random.IndividualBetween( -scaleShake, scaleShake ) * shakeAmount;
return transformData;
}

View File

@ -8,7 +8,7 @@ namespace Rokojori
{ {
[Tool] [Tool]
[GlobalClass] [GlobalClass]
public partial class AnimateTransform:RJSequenceAction, Animator public partial class AnimateTransform:SequenceAction, Animator
{ {
[Export] [Export]
@ -25,7 +25,7 @@ namespace Rokojori
public void OnAnimatorCancel(){} public void OnAnimatorCancel(){}
public override void _OnTrigger() protected override void _OnTrigger()
{ {
_frameValues = new List<Vector3>(); _frameValues = new List<Vector3>();
_randomizations = new List<Vector3>(); _randomizations = new List<Vector3>();
@ -50,7 +50,7 @@ namespace Rokojori
} }
TimeLineScheduler.ScheduleSpanIn( timeline, 0, duration, TimeLineScheduler.ScheduleSpanIn( timeline, 0, duration,
( int id, int type )=> ( int id, TimeLineSpanUpdateType type )=>
{ {
var timeNow = TimeLineManager.GetPosition( timeline ); var timeNow = TimeLineManager.GetPosition( timeline );
var elapsed = timeNow - start; var elapsed = timeNow - start;
@ -67,7 +67,7 @@ namespace Rokojori
index ++; index ++;
} }
if ( type == TimeLineSpan.End ) if ( type == TimeLineSpanUpdateType.End )
{ {
foreach ( var c in animations.curves ) foreach ( var c in animations.curves )
{ {

View File

@ -14,7 +14,7 @@ namespace Rokojori
public TransformCurve[] curves; public TransformCurve[] curves;
[Export] [Export]
public RJTimeLine timeline; public TimeLine timeline;
public float GetMaxDuration( List<Vector3> randomizations ) public float GetMaxDuration( List<Vector3> randomizations )
{ {

View File

@ -0,0 +1,61 @@
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using Godot;
namespace Rokojori
{
public class TransformData
{
public Vector3 position;
public Vector3 rotation;
public Vector3 scale;
public TransformData Clone()
{
var data = new TransformData();
data.position = position;
data.rotation = rotation;
data.scale = scale;
return data;
}
public void Add( TransformData other )
{
position += other.position;
rotation += other.rotation;
scale += other.scale;
}
public override string ToString()
{
return RJLog.Stringify( position ) + ", " + RJLog.Stringify( rotation ) + ", " + RJLog.Stringify( scale );
}
public void Set( Node3D node, bool globalPosition = true, bool globalRotation = true )
{
TransformTargets.Set( position, node, TransformTargets.Position( globalPosition ) );
TransformTargets.Set( rotation, node, TransformTargets.Rotation( globalRotation ) );
TransformTargets.Set( scale, node, TransformTargets.Scale() );
}
public void Get( Node3D node, bool globalPosition = true, bool globalRotation = true )
{
position = TransformTargets.Get( node, TransformTargets.Position( globalPosition ) );
rotation = TransformTargets.Get( node, TransformTargets.Rotation( globalRotation ) );
scale = TransformTargets.Get( node, TransformTargets.Scale() );
}
public static TransformData From( Node3D n, bool globalPosition = true, bool globalRotation = true )
{
var td = new TransformData();
td.Get( n, globalPosition, globalRotation );
return td;
}
}
}

View File

@ -15,23 +15,40 @@ namespace Rokojori
Local_Scale Local_Scale
} }
public class TransformTargets public class TransformTargets
{ {
public static TransformTarget Position( bool global = true )
{
return global ? TransformTarget.Global_Position : TransformTarget.Local_Position;
}
public static TransformTarget Rotation( bool global = true )
{
return global ? TransformTarget.Global_Rotation : TransformTarget.Local_Rotation;
}
public static TransformTarget Scale()
{
return TransformTarget.Local_Scale;
}
public static AnimationMember ToAnimationMember( TransformTarget target ) public static AnimationMember ToAnimationMember( TransformTarget target )
{ {
if ( TransformTarget.Local_Position == target || TransformTarget.Global_Position == target ) if ( TransformTarget.Local_Position == target || TransformTarget.Global_Position == target )
{ {
return AnimationManager.position; return AnimationMember.Position;
} }
if ( TransformTarget.Local_Rotation == target || TransformTarget.Global_Rotation == target ) if ( TransformTarget.Local_Rotation == target || TransformTarget.Global_Rotation == target )
{ {
return AnimationManager.rotation; return AnimationMember.Rotation;
} }
if ( TransformTarget.Local_Scale == target ) if ( TransformTarget.Local_Scale == target )
{ {
return AnimationManager.scale; return AnimationMember.Scale;
} }
return null; return null;
@ -45,6 +62,7 @@ namespace Rokojori
} }
else if ( TransformTarget.Global_Rotation == transformTarget ) else if ( TransformTarget.Global_Rotation == transformTarget )
{ {
// RJLog.Log( "GlobalRotation => ", target.GlobalRotation );
return target.GlobalRotation; return target.GlobalRotation;
} }
else if ( TransformTarget.Local_Position == transformTarget ) else if ( TransformTarget.Local_Position == transformTarget )
@ -53,6 +71,7 @@ namespace Rokojori
} }
else if ( TransformTarget.Local_Rotation == transformTarget ) else if ( TransformTarget.Local_Rotation == transformTarget )
{ {
// RJLog.Log( "Rotation => ", target.Rotation );
return target.Rotation; return target.Rotation;
} }
else if ( TransformTarget.Local_Scale == transformTarget ) else if ( TransformTarget.Local_Scale == transformTarget )
@ -71,7 +90,9 @@ namespace Rokojori
} }
else if ( TransformTarget.Global_Rotation == transformTarget ) else if ( TransformTarget.Global_Rotation == transformTarget )
{ {
var rotation = target.GlobalRotation;
target.GlobalRotation = value; target.GlobalRotation = value;
// RJLog.Log( "GlobalRotation = ", rotation, ">>", value, target.GlobalRotation );
} }
else if ( TransformTarget.Local_Position == transformTarget ) else if ( TransformTarget.Local_Position == transformTarget )
{ {
@ -79,7 +100,9 @@ namespace Rokojori
} }
else if ( TransformTarget.Local_Rotation == transformTarget ) else if ( TransformTarget.Local_Rotation == transformTarget )
{ {
var rotation = target.Rotation;
target.Rotation = value; target.Rotation = value;
// RJLog.Log( "Rotation = ", rotation, ">>", value, target.Rotation );
} }
else if ( TransformTarget.Local_Scale == transformTarget ) else if ( TransformTarget.Local_Scale == transformTarget )
{ {

View File

@ -0,0 +1,22 @@
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using Godot;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class FadeWipeEffect:TextureWipeEffect
{
public override void Assign( ColorRect colorRect )
{
var material = new FadeWipeMaterial();
colorRect.Material = material;
base.Assign( colorRect );
}
}
}

View File

@ -0,0 +1,94 @@
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using Godot;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class TextureWipeEffect:WipeEffect
{
[ExportGroup("Texture")]
[Export]
public Texture2D texture;
[Export]
public Gradient tint;
[ExportGroup("Texture Transform")]
[Export]
public Curve rotation = MathX.Curve( 0, 0 );
[Export]
public Curve scale = MathX.Curve( 1, 1 );
[Export]
public Curve translationX = MathX.Curve( 0, 0 );
[Export]
public Curve translationY = MathX.Curve( 0, 0 );
[ExportGroup("Texture Transform Centers")]
[Export]
public Vector2 rotationCenter = new Vector2( 0.5f, 0.5f );
[Export]
public Vector2 scaleCenter = new Vector2( 0.5f, 0.5f );
public static readonly Texture2DPropertyName _wipeTextureProperty = Texture2DPropertyName.Create( "wipeTexture" );
public static readonly Vector2PropertyName _outputViewSizeProperty = Vector2PropertyName.Create( "outputViewSize" );
public static readonly Vector2PropertyName _wipeTextureSizeProperty = Vector2PropertyName.Create( "wipeTextureSize" );
public static readonly Vector2PropertyName _uvRotationCenterProperty = Vector2PropertyName.Create( "uvRotationCenter" );
public static readonly Vector2PropertyName _uvScaleCenterPropery = Vector2PropertyName.Create( "uvScaleCenter" );
public static readonly ColorPropertyName _wipeTextureTintProperty = ColorPropertyName.Create( "wipeTextureTint" );
public static readonly FloatPropertyName _uvRotationProperty = FloatPropertyName.Create( "uvRotation" );
public static readonly FloatPropertyName _uvScaleProperty = FloatPropertyName.Create( "uvScale" );
public static readonly Vector2PropertyName _uvTranslationProperty = Vector2PropertyName.Create( "uvTranslation" );
public override void Assign( ColorRect colorRect )
{
if ( colorRect == null )
{
return;
}
var material = GetMaterial( colorRect );
if ( texture != null )
{
_wipeTextureProperty.Set( material, texture );
_wipeTextureSizeProperty.Set( material, texture.GetSize() );
_uvRotationCenterProperty.Set( material, rotationCenter );
_uvScaleCenterPropery.Set( material, scaleCenter );
}
_outputViewSizeProperty.Set( material, colorRect.GetViewportRect().Size );
}
public override void SetWipeState( float state, ColorRect target )
{
if ( target == null )
{
return;
}
var material = GetMaterial( target );
_wipeTextureTintProperty.Set( material, tint.Sample( state ) );
_uvRotationProperty.Set( material, rotation.Sample( state ) );
_uvScaleProperty.Set( material, rotation.Sample( state ) );
_uvTranslationProperty.Set( material, new Vector2( translationX.Sample( state ), translationY.Sample( state ) ) );
}
}
}

View File

@ -0,0 +1,59 @@
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using Godot;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class Wipe:SequenceAction
{
public enum Direction
{
In,
Out,
Custom
}
[Export]
public Direction direction;
[Export]
public float duration;
[Export]
public TimeLine timeLine;
[Export]
public WipeEffect wipeEffect;
[ExportGroup("Target Overwrite")]
[Export]
public ColorRect targetOverwriteColorRect;
[Export]
public Selector targetOverwriteSelector;
[Export]
public Node targetOverwriteRoot;
int _actionID = -1;
int _animationID = -1;
protected override void _OnTrigger()
{
if ( _actionID != -1 )
{
CancelAction( _actionID );
}
}
public override void CancelAction( int id )
{
}
}
}

View File

@ -0,0 +1,34 @@
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using Godot;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class WipeEffect:Resource
{
public static readonly FloatPropertyName wipeState = FloatPropertyName.Create( "wipeState" );
[ExportGroup("Target")]
[Export]
public Selector selector;
public ShaderMaterial GetMaterial( ColorRect rect )
{
return rect.Material as ShaderMaterial;
}
public virtual void Assign( ColorRect colorRect )
{
}
public virtual void SetWipeState( float state, ColorRect target )
{}
}
}

31
Runtime/Bits/BitMath.cs Normal file
View File

@ -0,0 +1,31 @@
using Godot;
namespace Rokojori
{
public class BitMath
{
public static int GetInt32BitMask( int bit )
{
return ( 1 << bit );
}
public static int SetBit( int value, int bitPosition )
{
return value | GetInt32BitMask( bitPosition );
}
public static int UnsetBit( int value, int bitPosition )
{
return value & ~GetInt32BitMask( bitPosition );
}
public static bool IsBitSet( int value, int bitPosition )
{
var mask = GetInt32BitMask( bitPosition );
return ( value & mask ) == mask;
}
}
}

148
Runtime/Bits/BitViewTest.cs Normal file
View File

@ -0,0 +1,148 @@
using Godot;
namespace Rokojori
{
public class NetTransform: NetClassDefinition
{
public readonly NetVector3 position = new NetVector3( Vector3.Zero );
public readonly NetQuaternion rotation = new NetQuaternion( Quaternion.Identity );
public readonly NetVector3 scale = new NetVector3( Vector3.One );
public NetTransform()
{
SetMembers( position, rotation, scale );
}
}
public class NetMovementData: NetClassDefinition
{
public readonly NetClass<NetTransform> transform = new NetClass<NetTransform>(
new NetTransform()
);
public readonly NetInt id = new NetInt( -1 );
public NetMovementData()
{
SetMembers( transform, id );
}
}
[GlobalClass]
public partial class BitViewTest : Action
{
protected override void _OnTrigger()
{
TestSingleBitWriting();
TestByteWriting();
TestIntVL8Writing();
TestClassWriting();
}
public void TestSingleBitWriting()
{
RJLog.Log( "----- TestSingleBitWriting -------" );
var bitView = BitView.CreateEmpty();
var numBits = 21;
for ( int i = 0; i < numBits; i++ )
{
bitView.WriteBit( i % 2 == 0 );
}
LogAndTestReversal( bitView );
}
public void TestClassWriting()
{
RJLog.Log( "----- TestClassWriting -------" );
var bitView = BitView.CreateEmpty();
bitView.WriteBit( true );
bitView.WriteFloat( -1234.567f );
var trsf = new NetTransform();
trsf.position.value = new Vector3( 1, 2, 3 );
trsf.rotation.value = Quaternion.FromEuler( new Vector3( 0, 90, 0 ) );
trsf.scale.value = new Vector3( 10,5,-1 );
//var md = new NetMovementData();
trsf.WriteMembers( bitView );
LogAndTestReversal( bitView );
var copy = bitView.Clone();
copy.SetPointer( 0 );
var bit = copy.ReadBit();
var data = copy.ReadFloat();
var copyTrsf = Singleton<NetClassDataType<NetTransform>>.Get().ReadData( copy );
RJLog.Log( bit, data, trsf.position.value, trsf.rotation.value, trsf.scale.value );
}
public void TestByteWriting()
{
RJLog.Log( "----- TestByteWriting -------" );
var bitView = BitView.CreateEmpty();
bitView.WriteByte( 1 );
bitView.WriteByte( 0 );
bitView.WriteByte( 0 );
bitView.WriteByte( 0 );
bitView.WriteBit( true );
bitView.WriteBit( false );
bitView.WriteBit( true );
bitView.WriteByte( 19 );
bitView.WriteByte( 84 );
LogAndTestReversal( bitView );
}
public void TestIntVL8Writing()
{
RJLog.Log( "----- TestIntVL8Writing -------" );
var bitView = BitView.CreateEmpty();
bitView.WriteUIntVL8( 127 );
bitView.WriteUIntVL8( 128 );
bitView.WriteUIntVL8( 70000 );
bitView.WriteUIntVL8( 17121984 );
LogAndTestReversal( bitView );
var copy = BitView.From( bitView.GetBytes(), bitView.numBits );
copy.SetPointer( 0 );
RJLog.Log( "----- Reading -------" );
for ( int i = 0; i < 4; i++ )
{
copy.ReadUIntVL8();
}
}
void LogAndTestReversal( BitView bitView )
{
Log( bitView );
var fromBytes = BitView.From( bitView.GetBytes(), bitView.numBits );
Log( fromBytes );
}
void Log( BitView view )
{
RJLog.Log( view.GetBitString(), "|", ByteView.Stringify( view.GetBytes() ) );
}
}
}

View File

@ -0,0 +1,60 @@
using Godot;
using System.Collections.Generic;
using System.Text;
namespace Rokojori
{
public partial class BitView
{
public void WriteByte( byte value )
{
for ( int i = 0; i < 8; i++ )
{
WriteBit( BitMath.IsBitSet( value, i ) );
}
}
public void WriteBytes( byte[] values )
{
for ( int i = 0; i < values.Length; i++ )
{
WriteByte( values[ i ] );
}
}
public byte ReadByte()
{
var byteValue = 0;
for ( int i = 0; i < 8; i++ )
{
var bitValue = ReadBit();
if ( ! bitValue )
{
continue;
}
byteValue = byteValue | ( 1 << i );
}
return (byte) byteValue;
}
public void ReadBytes( byte[] output, int size )
{
for ( int i = 0; i < size; i++ )
{
output[ i ] = ReadByte();
}
}
public byte[] ReadByteArray( int size )
{
var data = new byte[ size ];
ReadBytes( data, size );
return data;
}
}
}

View File

@ -0,0 +1,20 @@
using Godot;
using System.Collections.Generic;
using System.Text;
using System;
namespace Rokojori
{
public partial class BitView
{
public void WriteFloat( float value )
{
WriteBytes( BitConverter.GetBytes( value ) );
}
public float ReadFloat()
{
return BitConverter.ToSingle( ReadByteArray( 4 ) );
}
}
}

View File

@ -0,0 +1,20 @@
using Godot;
using System.Collections.Generic;
using System.Text;
using System;
namespace Rokojori
{
public partial class BitView
{
public void WriteInt( int value )
{
WriteBytes( BitConverter.GetBytes( value ) );
}
public int ReadInt()
{
return BitConverter.ToInt32( ReadByteArray( 4 ) );
}
}
}

View File

@ -0,0 +1,85 @@
using Godot;
using System.Collections.Generic;
using System.Text;
namespace Rokojori
{
public partial class BitView
{
public static int numBitsForIntVL8( int value )
{
return numBytesForUIntVL8( value ) * 8;
}
public static int numBytesForUIntVL8( int value )
{
var numBits = Mathf.CeilToInt( MathX.Exponent( 2, value + 1 ) );
var numBytes = ( numBits - 1 )/ 7 + 1;
return numBytes;
}
public void WriteUIntVL8( int value )
{
if ( value < 0 )
{
throw new System.Exception( "Value is negative, writing only positive value:" + value );
}
var numBits = Mathf.CeilToInt( MathX.Exponent( 2, value + 1 ) );
var numBytes = ( numBits - 1 )/ 7 + 1;
var position = 0;
RJLog.Log( "WriteIntVL8", value, "bits:", numBits," >> bytes:", numBytes );
for ( int b = 0; b < numBytes; b++ )
{
for ( int i = 0; i < 7; i++ )
{
WriteBit( BitMath.IsBitSet( value, position ) );
position++;
}
WriteBit( b != ( numBytes - 1 ) );
}
}
public int ReadUIntVL8()
{
var byteValue = ReadByte();
var intValue = byteValue & 127;
var numShifts = 1;
while ( byteValue > 127 )
{
byteValue = ReadByte();
var nextIntValue = ( byteValue & 127 ) << ( 7 * numShifts );
numShifts ++;
intValue = intValue | nextIntValue;
}
RJLog.Log( "ReadIntVL8 >> ", intValue );
return intValue;
}
public void WriteIntVL8( int value )
{
var isNegative = value < 0;
var absValue = Mathf.Abs( value );
WriteBit( isNegative );
WriteUIntVL8( absValue );
}
public int ReadIntVL8()
{
var isNegative = ReadBit();
var absValue = ReadUIntVL8();
return isNegative ? ( -absValue ) : absValue;
}
}
}

View File

@ -0,0 +1,59 @@
using Godot;
using System.Collections.Generic;
using System.Text;
using System;
namespace Rokojori
{
public partial class BitView
{
public void WriteVector2( Vector2 value )
{
WriteFloat( value.X );
WriteFloat( value.Y );
}
public Vector2 ReadVector2()
{
return new Vector2( ReadFloat(), ReadFloat() );
}
public void WriteVector3( Vector3 value )
{
WriteFloat( value.X );
WriteFloat( value.Y );
WriteFloat( value.Z );
}
public Vector3 ReadVector3()
{
return new Vector3( ReadFloat(), ReadFloat(), ReadFloat() );
}
public void WriteVector4( Vector4 value )
{
WriteFloat( value.X );
WriteFloat( value.Y );
WriteFloat( value.Z );
WriteFloat( value.W );
}
public Vector4 ReadVector4()
{
return new Vector4( ReadFloat(), ReadFloat(), ReadFloat(), ReadFloat() );
}
public void WriteQuaternion( Quaternion value )
{
WriteFloat( value.X );
WriteFloat( value.Y );
WriteFloat( value.Z );
WriteFloat( value.W );
}
public Quaternion ReadQuaternion()
{
return new Quaternion( ReadFloat(), ReadFloat(), ReadFloat(), ReadFloat() );
}
}
}

266
Runtime/Bits/BitView__.cs Normal file
View File

@ -0,0 +1,266 @@
using Godot;
using System.Collections.Generic;
using System.Text;
namespace Rokojori
{
public partial class BitView
{
byte[] _data;
int _internalViewOffset = 0;
public int bitOffset => _internalViewOffset;
int _internalViewSize = 0;
public int numBits => _internalViewSize;
public int numBytes => Mathf.CeilToInt( _internalViewSize / 8f );
int _externalPointer = 0;
public int pointerPosition => _externalPointer;
public void SetPointer( int bitPosition )
{
_externalPointer = bitPosition;
}
public byte[] GetBytes()
{
var numBytes = this.numBytes;
var data = new byte[ numBytes ];
System.Array.Fill( data, (byte)0 );
for ( int i = 0; i < _internalViewSize; i++ )
{
var isSet = GetValueInternal( i + _internalViewOffset );
if ( ! isSet )
{
continue;
}
var shift = i % 8;
var index = i / 8;
var value = 1 << shift;
data[ index ] = (byte) ( data[ index ] | value );
}
return data;
}
public BitView Clone()
{
var clone = new BitView();
clone._data = _data;
clone._internalViewOffset = _internalViewOffset;
clone._internalViewSize = _internalViewSize;
clone._externalPointer = _externalPointer;
return clone;
}
public string GetBitString()
{
var output = new StringBuilder();
for ( int i = 0; i < _internalViewSize; i++ )
{
var mod = i % 8;
if ( i != 0 && mod == 0 )
{
output.Append( " " );
}
var reverseIndex = 7 - mod * 2;
var value = GetValueInternal( reverseIndex + i + _internalViewOffset ) ? "1" : "0";
output.Append( value );
}
return output.ToString();
}
void SetValueInternal( int position, bool value )
{
var byteIndex = position / 8;
var bitOffset = position - byteIndex * 8;
if ( value )
{
_data[ byteIndex ] = Bytes.SetBit( _data[ byteIndex ], bitOffset );
}
else
{
_data[ byteIndex ] = Bytes.UnsetBit( _data[ byteIndex ], bitOffset );
}
}
bool GetValueInternal( int bitPosition )
{
var byteIndex = bitPosition / 8;
var bitOffset = bitPosition - byteIndex * 8;
return Bytes.IsBitSet( _data[ byteIndex ], bitOffset );
}
int GetShiftedValueInternal( int bitPosition, int shift )
{
if ( ! GetValueInternal( bitPosition ) )
{
return 0;
}
return 1 << shift;
}
void EnsureInternalSize( int bitPosition )
{
var byteIndex = bitPosition / 8;
if ( byteIndex >= _data.Length )
{
var newData = new byte[ _data.Length + 1 ];
System.Array.Fill( newData, (byte) 0 );
System.Array.Copy( _data, 0, newData, 0, _data.Length );
_data = newData;
}
}
public void Clear()
{
_externalPointer = 0;
for ( int i = 0; i < _internalViewSize; i++ )
{
SetValueInternal( i + _internalViewOffset, false );
}
}
public void ResetPointerAndSize()
{
_externalPointer = 0;
_internalViewSize = 0;
}
public void WriteBit( bool value )
{
var position = _externalPointer + _internalViewOffset;
EnsureInternalSize( position );
SetValueInternal( position, value );
_externalPointer ++;
_internalViewSize = Mathf.Max( _externalPointer, _internalViewSize );
}
public bool GetBitAt( int bitPosition )
{
var internalBitPosition = bitPosition + _internalViewOffset;
return GetValueInternal( bitPosition );
}
public bool ReadBit()
{
var bitPosition = _externalPointer + _internalViewOffset;
if ( bitPosition < 0 || bitPosition >= numBits )
{
RJLog.Log( "Can't read: >> ", bitPosition, "in", numBits, "p:", _externalPointer, "o:", _internalViewOffset );
return false;
}
var value = GetValueInternal( bitPosition );
_externalPointer ++;
return value;
}
public void SetPointerPosition( int position )
{
_externalPointer = Mathf.Clamp( position, 0, _internalViewSize );
}
public static BitView CreateEmpty()
{
var view = new BitView();
view._data = new byte[]{};
view._internalViewOffset = 0;
view._internalViewSize = 0;
view._externalPointer = 0;
return view;
}
public static BitView From( byte[] data)
{
var view = new BitView();
view._data = data;
view._internalViewOffset = 0;
view._internalViewSize = data.Length * 8;
view._externalPointer = 0;
return view;
}
public static BitView From( byte[] data, int bitSize = -1 )
{
var view = new BitView();
view._data = data;
view._internalViewOffset = 0;
view._internalViewSize = bitSize == -1 ? data.Length * 8 : bitSize;
view._externalPointer = 0;
return view;
}
public static BitView PrependBytes( byte[] before, BitView after )
{
var data = new byte[ before.Length + after.numBytes ];
System.Array.Copy( before, 0, data, 0, before.Length );
var view = BitView.From( data, before.Length * 8 + after.numBits );
if ( after.bitOffset == 0 )
{
System.Array.Copy( after._data, 0, data, 0, after.numBytes );
view.SetPointer( after.pointerPosition + before.Length * 8 );
return view;
}
view.SetPointer( before.Length * 8 );
for ( int i = 0; i < after.numBits; i++ )
{
view.WriteBit( after.GetBitAt( i ) );
}
view.SetPointer( after.pointerPosition + before.Length * 8 );
return view;
}
public static BitView PrependID( int id, BitView after )
{
var idView = BitView.CreateEmpty();
idView.WriteUIntVL8( id );
return BitView.PrependBytes( idView.GetBytes(), after );
}
}
}

76
Runtime/Bits/ByteView.cs Normal file
View File

@ -0,0 +1,76 @@
using Godot;
using System;
using System.Text;
namespace Rokojori
{
public class ByteView
{
byte[] _data;
int _start;
int _size;
public ByteView From( byte[] bytes )
{
var view = new ByteView();
view._start = 0;
view._size = bytes.Length;
view._data = bytes;
return view;
}
public byte[] GetBytes()
{
if ( _start == 0 && _size == _data.Length )
{
return _data;
}
var bytes = new byte[ _size ];
Array.Copy( _data, _start, bytes, 0, _size );
return bytes;
}
public string Stringify()
{
return Stringify( _data, _start, _size );
}
public static string Stringify( byte[] _data, int _start = 0, int _size = -1)
{
if ( _size < 0 )
{
_size = _data.Length - _start;
}
var sb = new StringBuilder();
for ( int i = 0; i < _size; i++ )
{
if ( i != 0 )
{
sb.Append( " " );
}
var value = _data[ i + _start ] + "";
while ( value.Length < 3 )
{
value = "0" + value;
}
sb.Append( value );
}
return sb.ToString();
}
}
}

30
Runtime/Bits/Bytes.cs Normal file
View File

@ -0,0 +1,30 @@
using Godot;
using System;
using System.Text;
namespace Rokojori
{
public class Bytes
{
public static byte SetBit( byte value, int position )
{
return (byte) ( ( 1 << position ) | value );
}
public static byte UnsetBit( byte value, int position )
{
var mask = 1 << position;
var invertedMask = ~mask;
return (byte)( value & invertedMask );
}
public static bool IsBitSet( byte value, int position )
{
var mask = 1 << position;
return ( mask & value ) == mask ;
}
}
}

View File

@ -37,10 +37,13 @@ namespace Rokojori
public virtual void DispatchEvent() public virtual void DispatchEvent()
{ {
_canModify = false;
_actions.ForEach( a => { if ( a != null ){ a( _value ); } } ); _actions.ForEach( a => { if ( a != null ){ a( _value ); } } );
_ClearOnceActions(); _UpdateLists();
_canModify = true;
} }

View File

@ -12,35 +12,88 @@ namespace Rokojori
protected List<Action<T>> _actions = new List<Action<T>>(); protected List<Action<T>> _actions = new List<Action<T>>();
List<Action<T>> _once = new List<Action<T>>(); List<Action<T>> _once = new List<Action<T>>();
protected bool _canModify = true;
List<Action<T>> _additions = new List<Action<T>>();
List<Action<T>> _onceAdditions = new List<Action<T>>();
List<Action<T>> _removals = new List<Action<T>>();
public bool hasListeners => _once.Count > 0 || _actions.Count > 0; public bool hasListeners => _once.Count > 0 || _actions.Count > 0;
public void AddAction( Action<T> action ) public void AddAction( Action<T> action )
{ {
_actions.Add( action ); if ( _canModify )
{
_actions.Add( action );
}
else
{
_additions.Add( action );
}
} }
public void RemoveAction( Action<T> action ) public void RemoveAction( Action<T> action )
{ {
_actions.Remove( action ); if ( _canModify )
{
_actions.Remove( action );
}
else
{
_removals.Add( action );
}
} }
public void Once( Action<T> action ) public void Once( Action<T> action )
{ {
_actions.Add( action ); if ( _canModify )
_once.Add( action ); {
_actions.Add( action );
_once.Add( action );
}
else
{
_onceAdditions.Add( action );
}
} }
protected void _ClearOnceActions() protected void _UpdateLists()
{ {
_once.ForEach( a => { _actions.Remove( a ); } ); _once.ForEach( a => { _actions.Remove( a ); } );
_once.Clear(); _once.Clear();
if ( _removals.Count > 0 )
{
Lists.RemoveRange( _actions, _removals );
_removals.Clear();
}
if ( _additions.Count > 0 )
{
_actions.AddRange( _additions );
_additions.Clear();
}
if ( _onceAdditions.Count > 0 )
{
_once.AddRange( _onceAdditions );
_actions.AddRange( _onceAdditions );
}
} }
public void DispatchEvent( T t ) public void DispatchEvent( T t )
{ {
_canModify = false;
_actions.ForEach( a => { if ( a != null ){ a( t ); } } ); _actions.ForEach( a => { if ( a != null ){ a( t ); } } );
_UpdateLists();
_ClearOnceActions(); _canModify = true;
} }
} }

View File

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

View File

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

View File

@ -72,7 +72,7 @@ namespace Rokojori
output.Append( " \n" ); output.Append( " \n" );
output.Append( " [Export]\n" ); output.Append( " [Export]\n" );
output.Append( " public RJAction On" + eventName + ";\n" ); output.Append( " public Action On" + eventName + ";\n" );
} }
output.Append( " \n" ); output.Append( " \n" );
@ -100,7 +100,7 @@ namespace Rokojori
p += " )"; p += " )";
output.Append( " " + eventName + " += " + p + " => { Actions.Trigger( On" + eventName +" ); }; \n" ); output.Append( " " + eventName + " += " + p + " => { Action.Trigger( On" + eventName +" ); }; \n" );
} }
output.Append( " }\n" ); output.Append( " }\n" );

View File

@ -0,0 +1,52 @@
using Godot;
using System.Collections;
using System.Collections.Generic;
using Godot.Collections;
namespace Rokojori
{
[GlobalClass]
public partial class Caster:Node3D
{
[Export]
public Action beforeProcess;
[Export]
public Action afterProcess;
[Export]
public Selector includeSelector;
[Export]
public Selector excludeSelector;
public virtual int NumColliders()
{
return 0;
}
public virtual Node GetCollider( int index )
{
return null;
}
public virtual Vector3 GetCollisionPosition( int index )
{
return Vector3.Zero;
}
public virtual Vector3 GetCollisionNormal( int index )
{
return Vector3.Zero;
}
public virtual Shape3D GetCollisionShape( int index )
{
return null;
}
}
}

View File

@ -50,7 +50,7 @@ namespace Rokojori
if ( CharacterUpdateMode.Process == characterUpdateMode ) if ( CharacterUpdateMode.Process == characterUpdateMode )
{ {
this.delta = (float)delta; this.delta = (float)delta;
Nodes.ForEachDirectChild<CharacterControllerAction>( actionsContainer, a => Actions.Trigger( a ) ); Nodes.ForEachDirectChild<CharacterControllerAction>( actionsContainer, a => Action.Trigger( a ) );
} }
// positionSmoother.CopyPosition( graphics, body, rotationSmoothingDuration, delta ); // positionSmoother.CopyPosition( graphics, body, rotationSmoothingDuration, delta );
@ -64,7 +64,7 @@ namespace Rokojori
if ( CharacterUpdateMode.Physics_Process == characterUpdateMode ) if ( CharacterUpdateMode.Physics_Process == characterUpdateMode )
{ {
this.delta = (float)delta; this.delta = (float)delta;
Nodes.ForEach<RJAction>( actionsContainer, a => Actions.Trigger( a ) ); Nodes.ForEach<Action>( actionsContainer, a => Action.Trigger( a ) );
} }
} }
} }

View File

@ -6,7 +6,7 @@ using Godot.Collections;
namespace Rokojori namespace Rokojori
{ {
[GlobalClass] [GlobalClass]
public partial class CharacterControllerAction:RJAction public partial class CharacterControllerAction:Action
{ {
[Export] [Export]
public CharacterController controller; public CharacterController controller;

View File

@ -16,18 +16,18 @@ namespace Rokojori
[ExportGroup( "Actions" )] [ExportGroup( "Actions" )]
[Export] [Export]
public RJAction onMoving; public Action onMoving;
[Export] [Export]
public RJAction onIdle; public Action onIdle;
[Export] [Export]
public RJAction onForward; public Action onForward;
[Export] [Export]
public RJAction onBackwards; public Action onBackwards;
[Export] [Export]
public RJAction onStrafeLeft; public Action onStrafeLeft;
[Export] [Export]
public RJAction onStrafeRight; public Action onStrafeRight;
[ExportGroup( "Direction Source" )] [ExportGroup( "Direction Source" )]
@ -50,20 +50,20 @@ namespace Rokojori
public float moveSpeed; public float moveSpeed;
[Export] [Export]
public RJSensor forward; public Sensor forward;
[Export] [Export]
public RJSensor backwards; public Sensor backwards;
[ExportGroup( "Strafing" )] [ExportGroup( "Strafing" )]
[Export] [Export]
public float strafeSpeed; public float strafeSpeed;
[Export] [Export]
public RJSensor strafeLeft; public Sensor strafeLeft;
[Export] [Export]
public RJSensor strafeRight; public Sensor strafeRight;
[Export] [Export]
public bool useBodyDirection = true; public bool useBodyDirection = true;
@ -81,7 +81,7 @@ namespace Rokojori
Smoother rotationSmoother = new Smoother(); Smoother rotationSmoother = new Smoother();
public override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( ! body.IsOnFloor() ) if ( ! body.IsOnFloor() )
{ {

View File

@ -11,7 +11,7 @@ namespace Rokojori
[Export] [Export]
public float strength = 10; public float strength = 10;
public override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( body.IsOnFloor() ) if ( body.IsOnFloor() )
{ {

View File

@ -8,7 +8,7 @@ namespace Rokojori
[GlobalClass] [GlobalClass]
public partial class GroundReset:CharacterControllerAction public partial class GroundReset:CharacterControllerAction
{ {
public override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( ! body.IsOnFloor() ) if ( ! body.IsOnFloor() )
{ {

View File

@ -9,7 +9,7 @@ namespace Rokojori
public partial class Jump:CharacterControllerAction public partial class Jump:CharacterControllerAction
{ {
[Export] [Export]
public RJSensor button; public Sensor button;
[Export] [Export]
public float jumpStrength; public float jumpStrength;
@ -31,7 +31,7 @@ namespace Rokojori
public override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( body.IsOnFloor() ) if ( body.IsOnFloor() )
{ {
@ -43,7 +43,7 @@ namespace Rokojori
return; return;
} }
if ( ! button.IsActive() ) if ( ! button.isActive )
{ {
jumping = false; jumping = false;
return; return;

View File

@ -8,7 +8,7 @@ namespace Rokojori
[GlobalClass] [GlobalClass]
public partial class MoveAndSlide:CharacterControllerAction public partial class MoveAndSlide:CharacterControllerAction
{ {
public override void _OnTrigger() protected override void _OnTrigger()
{ {
// RJLog.Log( controller.body.Velocity ); // RJLog.Log( controller.body.Velocity );
controller.body.MoveAndSlide(); controller.body.MoveAndSlide();

View File

@ -7,7 +7,7 @@ namespace Rokojori
{ {
[GlobalClass] [GlobalClass]
public partial class MultiRayCaster:RJCaster public partial class MultiRayCaster:Caster
{ {
[Export] [Export]
public float rayLength = 10; public float rayLength = 10;
@ -54,13 +54,13 @@ namespace Rokojori
public override void _Process( double delta ) public override void _Process( double delta )
{ {
Actions.Trigger( BeforeProcess ); Action.Trigger( beforeProcess );
ResolveCollisions(); ResolveCollisions();
SortCollisions(); SortCollisions();
Actions.Trigger( AfterProcess ); Action.Trigger( afterProcess );
} }
@ -119,9 +119,6 @@ namespace Rokojori
bool IsSelected( CollisionData cd ) bool IsSelected( CollisionData cd )
{ {
var includeSelector = IncludeSelector;
var excludeSelector = ExcludeSelector;
if ( includeSelector != null && ! includeSelector.Selects( cd.collider ) ) if ( includeSelector != null && ! includeSelector.Selects( cd.collider ) )
{ {
return false; return false;
@ -164,11 +161,11 @@ namespace Rokojori
{ {
float priority = 0; float priority = 0;
var pointable = Nodes.Find<RJPointable>( cd.collider ); var pointable = Nodes.Find<Pointable>( cd.collider );
if ( pointable != null ) if ( pointable != null )
{ {
priority = pointable.PointingPriority; priority = pointable.pointingPriority;
} }
return priority; return priority;

View File

@ -7,21 +7,33 @@ namespace Rokojori
{ {
[GlobalClass] [GlobalClass]
public partial class Pointable:RJPointable public partial class Pointable:Node3D
{ {
List<RJPointer> _pointers = new List<RJPointer>(); [Export]
public int pointingPriority;
public override int NumPointing() [Export]
{ public Action onPointed;
return _pointers.Count;
}
public bool IsPointedBy( RJPointer pointer ) [Export]
public Action onUnpointed;
[Export]
public Action onPointerAdded;
[Export]
public Action onPointerRemoved;
List<Pointer> _pointers = new List<Pointer>();
public int numPointing => _pointers.Count;
public bool IsPointedBy( Pointer pointer )
{ {
return _pointers.Contains( pointer ); return _pointers.Contains( pointer );
} }
public override void UpdatePointerState( RJPointer pointer, bool pointed ) public void UpdatePointerState( Pointer pointer, bool pointed )
{ {
var isCurrentlyPointed = IsPointedBy( pointer ); var isCurrentlyPointed = IsPointedBy( pointer );
@ -34,11 +46,11 @@ namespace Rokojori
if ( pointed ) if ( pointed )
{ {
_pointers.Add( pointer ); _pointers.Add( pointer );
Actions.Trigger( OnPointerAdded ); Action.Trigger( onPointerAdded );
if ( _pointers.Count == 1 ) if ( _pointers.Count == 1 )
{ {
Actions.Trigger( OnPointed ); Action.Trigger( onPointed );
} }
} }
@ -46,11 +58,11 @@ namespace Rokojori
{ {
_pointers.Remove( pointer ); _pointers.Remove( pointer );
Actions.Trigger( OnPointerRemoved ); Action.Trigger( onPointerRemoved );
if ( _pointers.Count == 0 ) if ( _pointers.Count == 0 )
{ {
Actions.Trigger( OnUnpointed ); Action.Trigger( onUnpointed );
} }
} }

View File

@ -7,22 +7,25 @@ namespace Rokojori
{ {
[GlobalClass] [GlobalClass]
public partial class Pointer:RJPointer public partial class Pointer:Node3D
{ {
[Export] [Export]
public RJPointable pointable; public Pointable pointable;
[Export]
public Caster caster;
public override void _Process( double delta ) public override void _Process( double delta )
{ {
if ( Caster == null ) if ( caster == null )
{ {
return; return;
} }
var currentCollider = Caster.NumColliders() == 0 ? null : Caster.GetCollider( 0 ); var currentCollider = caster.NumColliders() == 0 ? null : caster.GetCollider( 0 );
var currentPointable = currentCollider == null ? null : Nodes.Find<RJPointable>( currentCollider ); var currentPointable = currentCollider == null ? null : Nodes.Find<Pointable>( currentCollider );
// RJLog.Log( currentCollider, currentPointable ); // RJLog.Log( currentCollider, currentPointable );

View File

@ -18,6 +18,11 @@ namespace Rokojori
return LookingAtEachOtherAngle( lookDirectionA, lookDirectionB ) > 0; return LookingAtEachOtherAngle( lookDirectionA, lookDirectionB ) > 0;
} }
public static Vector2 Lerp( Vector2 a, Vector2 b, float lerpAmount )
{
return a.Lerp( b, lerpAmount );
}
public static bool LookingTowards( Vector2 from, Vector2 fromDirection, Vector2 to ) public static bool LookingTowards( Vector2 from, Vector2 fromDirection, Vector2 to )
{ {
return LookingAtEachOther( fromDirection.Normalized(), ( to - from ).Normalized() ); return LookingAtEachOther( fromDirection.Normalized(), ( to - from ).Normalized() );

View File

@ -118,6 +118,9 @@ namespace Rokojori
return Mathf.Floor( value / snappingDistance ) * snappingDistance; return Mathf.Floor( value / snappingDistance ) * snappingDistance;
} }
public const float DegreesToRadians = Mathf.Pi / 180f;
public const float RadiansToDegreens = 180f / Mathf.Pi;
public static float AngleDelta( float degreesA, float degreesB) public static float AngleDelta( float degreesA, float degreesB)
{ {
var angleDelta = degreesB - degreesA; var angleDelta = degreesB - degreesA;
@ -279,6 +282,11 @@ namespace Rokojori
return ( phase - phaseStart ) / ( phaseStart - phaseEnd ); return ( phase - phaseStart ) / ( phaseStart - phaseEnd );
} }
public static int SafeIndex<T>( int index, List<T> elements, bool wrap = false )
{
return SafeIndex( index, elements.Count, wrap );
}
public static int SafeIndex( int index, int maxElements, bool wrap = false ) public static int SafeIndex( int index, int maxElements, bool wrap = false )
{ {
if ( wrap ) if ( wrap )

View File

@ -8,6 +8,24 @@ namespace Rokojori
{ {
float overflowDelta = 0; float overflowDelta = 0;
public static float SmoothTimeInvariant( float value, float nextValue, float delta, float coefficient )
{
var lerpAmount = Mathf.Exp( -coefficient * delta );
return Mathf.Lerp( nextValue, value, lerpAmount );
}
public static Vector2 SmoothTimeInvariant( Vector2 value, Vector2 nextValue, float delta, float coefficient )
{
var lerpAmount = Mathf.Exp( -coefficient * delta );
return Math2D.Lerp( nextValue, value, lerpAmount );
}
public static Vector3 SmoothTimeInvariant( Vector3 value, Vector3 nextValue, float delta, float coefficient )
{
var lerpAmount = Mathf.Exp( -coefficient * delta );
return Math3D.Lerp( nextValue, value, lerpAmount );
}
public float SmoothForDuration( float value, float nextValue, float duration, float delta, float processDelta = MathX.fps120Delta ) public float SmoothForDuration( float value, float nextValue, float duration, float delta, float processDelta = MathX.fps120Delta )
{ {
var coefficient = MathX.SmoothingCoefficient( duration * 1000f, processDelta ); var coefficient = MathX.SmoothingCoefficient( duration * 1000f, processDelta );

View File

@ -0,0 +1,174 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
[GlobalClass]
public partial class LANNetworkBackend:NetworkBackend
{
SceneMultiplayer multiplayer;
ENetMultiplayerPeer peer;
public override void StartSession( NetworkSessionRequest request )
{
if ( _state != NetworkSessionConnectionState.Not_Connected )
{
return;
}
AssignSessionRequestVariables( request );
RJLog.Log( "Starting Session:", request );
_state = NetworkSessionConnectionState.Connecting_As_Server;
multiplayer = new SceneMultiplayer();
ConnectListeners();
peer = new ENetMultiplayerPeer();
var result = peer.CreateServer( port, maxMembers );
if ( Error.Ok != result )
{
_state = NetworkSessionConnectionState.Not_Connected;
RJLog.Log( "Session Creation Failed >>", result );
return;
}
_state = NetworkSessionConnectionState.Connected_As_Server;
_sessionManager.SetInSessionState();
Action.Trigger( _manager.onStartedSession );
AssignMultiplyer();
}
public override void JoinSession( NetworkSessionRequest request )
{
if ( _state != NetworkSessionConnectionState.Not_Connected )
{
if ( NetworkSessionConnectionState.Connected_As_Client == _state )
{
SendData();
}
return;
}
AssignSessionRequestVariables( request );
RJLog.Log( "Joining Session:", request );
_state = NetworkSessionConnectionState.Connecting_As_Client;
multiplayer = new SceneMultiplayer();
ConnectListeners();
peer = new ENetMultiplayerPeer();
var result = peer.CreateClient( serverIP, port, maxMembers );
if ( Error.Ok != result )
{
RJLog.Log( "Joining Session Failed >>", result );
_state = NetworkSessionConnectionState.Not_Connected;
return;
}
AssignMultiplyer();
}
void SendData()
{
var data = new byte[]{ 0, 1, 2, 3 };
var resultSending = multiplayer.SendBytes( data, 0, MultiplayerPeer.TransferModeEnum.Reliable );
RJLog.Log( "Sending Data", resultSending, ByteView.Stringify( data ) );
}
void AssignMultiplyer()
{
RJLog.Log( "AssignMultiplyer" );
multiplayer.MultiplayerPeer = peer;
GetTree().SetMultiplayer( multiplayer );
}
void ConnectListeners()
{
multiplayer.PeerPacket += ( id, data )=>
{
RJLog.Log( "Received Data:", id, ByteView.Stringify( data ) );
_transport.HandleIncomingMessage( id, data );
};
multiplayer.ConnectionFailed += ()=>
{
RJLog.Log( "ConnectionFailed" );
_state = NetworkSessionConnectionState.Not_Connected;
};
multiplayer.ServerDisconnected += ()=>
{
RJLog.Log( "ServerDisconnected" );
_state = NetworkSessionConnectionState.Not_Connected;
_sessionManager.SetInSessionState( false );
};
multiplayer.ConnectedToServer += ()=>
{
RJLog.Log( "Connecting_As_Client" );
_state = NetworkSessionConnectionState.Connected_As_Client;
_sessionManager.SetInSessionState();
Action.Trigger( _manager.onStartedSession );
};
multiplayer.PeerConnected += ( id )=>
{
RJLog.Log( "PeerConnected:", id );
var networkSessionMember = NetworkSessionMember.Create( id );
_sessionManager.AddMember( networkSessionMember );
};
multiplayer.PeerDisconnected += ( id )=>
{
RJLog.Log( "PeerDisconnected:", id );
_sessionManager.RemoveMember( id );
};
}
public override void SendMessage( byte[] bytes, List<int> targetMembers, bool reliable = true )
{
var mode = reliable ? MultiplayerPeer.TransferModeEnum.Reliable : MultiplayerPeer.TransferModeEnum.Unreliable;
if ( targetMembers.Count == 0 )
{
var resultSending = multiplayer.SendBytes( bytes, 0, mode );
RJLog.Log( "Sending Data", resultSending, ByteView.Stringify( bytes ) );
}
else
{
targetMembers.ForEach(
( id )=>
{
var resultSending = multiplayer.SendBytes( bytes, id, mode );
RJLog.Log( "Sending Data", resultSending, ByteView.Stringify( bytes ) );
}
);
}
}
}
}

View File

@ -0,0 +1,78 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public abstract class NetClassDefinition
{
protected NetMember[] _members;
public void SetMembers( params NetMember[] members )
{
_members = members;
}
public void ReadMembers( BitView view )
{
System.Array.ForEach( _members, m => m.ReadMember( view ) );
}
public void WriteMembers( BitView view )
{
System.Array.ForEach( _members, m => m.WriteMember( view ) );
}
}
public class NetClassDataType<T> where T:NetClassDefinition, new()
{
public T ReadData( BitView view )
{
var n = new T();
n.ReadMembers( view );
return n;
}
public void WriteData( BitView view, T t )
{
t.WriteMembers( view );
}
}
public class NetClass<T>:NetMember where T:NetClassDefinition, new()
{
public T value;
public NetClass( T value )
{
this.value = value;
}
public NetClassDataType<T> dataType => Singleton<NetClassDataType<T>>.Get();
public override void ReadMember( BitView view )
{
var isNull = ! view.ReadBit();
if ( isNull )
{
value = null;
return;
}
value = dataType.ReadData( view );
}
public override void WriteMember( BitView view )
{
view.WriteBit( value != null );
if ( value == null )
{
return;
}
dataType.WriteData( view, value );
}
}
}

View File

@ -0,0 +1,45 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class NetMember
{
public virtual void ReadMember( BitView view )
{
}
public virtual void WriteMember( BitView view )
{
}
}
public class TypedNetMember<T>:NetMember
{
NetworkDataType<T> dataType;
public T value;
public TypedNetMember( NetworkDataType<T> dataType, T value )
{
this.dataType = dataType;
this.value = value;
}
public override void ReadMember( BitView view )
{
value = dataType.ReadData( view );
}
public override void WriteMember( BitView view )
{
dataType.WriteData( view, value );
}
}
}

View File

@ -0,0 +1,12 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public interface NetworkDataType<T>
{
T ReadData( BitView view );
void WriteData( BitView view, T value );
}
}

View File

@ -0,0 +1,26 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class NetBoolType:NetworkDataType<bool>
{
public bool ReadData( BitView view )
{
return view.ReadBit();
}
public void WriteData( BitView view, bool value )
{
view.WriteBit( value );
}
}
public class NetBool:TypedNetMember<bool>
{
public NetBool( bool value ):base( Singleton<NetBoolType>.Get(), value ){}
}
}

View File

@ -0,0 +1,26 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class NetByteType:NetworkDataType<byte>
{
public byte ReadData( BitView view )
{
return view.ReadByte();
}
public void WriteData( BitView view, byte value )
{
view.WriteByte( value );
}
}
public class NetByte:TypedNetMember<byte>
{
public NetByte( byte value ):base( Singleton<NetByteType>.Get(), value ){}
}
}

View File

@ -0,0 +1,25 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class NetFloatType:NetworkDataType<float>
{
public float ReadData( BitView view )
{
return view.ReadFloat();
}
public void WriteData( BitView view, float value )
{
view.WriteFloat( value );
}
}
public class NetFloat:TypedNetMember<float>
{
public NetFloat( float value ):base( Singleton<NetFloatType>.Get(), value ){}
}
}

View File

@ -0,0 +1,24 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class NetIntType:NetworkDataType<int>
{
public int ReadData( BitView view )
{
return view.ReadInt();
}
public void WriteData( BitView view, int value )
{
view.WriteInt( value );
}
}
public class NetInt:TypedNetMember<int>
{
public NetInt( int value ):base( Singleton<NetIntType>.Get(), value ){}
}
}

View File

@ -0,0 +1,24 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class NetIntVL8Type:NetworkDataType<int>
{
public int ReadData( BitView view )
{
return view.ReadUIntVL8();
}
public void WriteData( BitView view, int value )
{
view.WriteUIntVL8( value );
}
}
public class NetIntVL8:TypedNetMember<int>
{
public NetIntVL8( int value ):base( Singleton<NetIntVL8Type>.Get(), value ){}
}
}

View File

@ -0,0 +1,39 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class NetListType<T>:NetworkDataType<List<T>>
{
public NetworkDataType<T> dataType;
public List<T> ReadData( BitView view )
{
var num = view.ReadUIntVL8();
var list = new List<T>( num );
for ( int i = 0; i < num; i++ )
{
list.Add( dataType.ReadData( view ) );
}
return list;
}
public void WriteData( BitView view, List<T> list )
{
view.WriteUIntVL8( list.Count );
for ( int i = 0; i < list.Count; i++ )
{
dataType.WriteData( view, list[ i ] );
}
}
}
public class NetList<T>:TypedNetMember<List<T>>
{
public NetList( List<T> value ):base( Singleton<NetListType<T>>.Get(), value ){}
}
}

View File

@ -0,0 +1,24 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class NetQuaternionType:NetworkDataType<Quaternion>
{
public Quaternion ReadData( BitView view )
{
return view.ReadQuaternion();
}
public void WriteData( BitView view, Quaternion value )
{
view.WriteQuaternion( value );
}
}
public class NetQuaternion:TypedNetMember<Quaternion>
{
public NetQuaternion( Quaternion value ):base( Singleton<NetQuaternionType>.Get(), value ){}
}
}

View File

@ -0,0 +1,24 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class NetVector3Type:NetworkDataType<Vector3>
{
public Vector3 ReadData( BitView view )
{
return view.ReadVector3();
}
public void WriteData( BitView view, Vector3 value )
{
view.WriteVector3( value );
}
}
public class NetVector3:TypedNetMember<Vector3>
{
public NetVector3( Vector3 value ):base( Singleton<NetVector3Type>.Get(), value ){}
}
}

View File

@ -0,0 +1,73 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public partial class NetworkBackend:Node
{
protected NetworkSessionConnectionState _state;
protected string serverIP = "127.0.0.1";
protected int port = 1984;
protected int maxMembers = 32;
protected NetworkManager _manager;
protected ExtendedNetworkSessionManager _sessionManager;
protected ExtendedNetworkTransport _transport;
public void InitializeBackend(
NetworkManager manager,
ExtendedNetworkSessionManager sessionManager,
ExtendedNetworkTransport transport
)
{
_manager = manager;
_sessionManager = sessionManager;
_transport = transport;
}
protected void AssignSessionRequestVariables( NetworkSessionRequest request )
{
if ( request == null )
{
return;
}
if ( request.serverIP != null )
{
serverIP = request.serverIP;
}
if ( request.port > 0 )
{
port = request.port;
}
if ( request.maxMembers > 0 )
{
maxMembers = request.maxMembers;
}
}
public virtual void StartSession( NetworkSessionRequest sessionRequest )
{
}
public virtual void JoinSession( NetworkSessionRequest sessionRequest )
{
}
public virtual void LeaveSession()
{
}
public virtual void SendMessage( byte[] bytes, List<int> targetMembers, bool reliable = true )
{
}
}
}

View File

@ -0,0 +1,65 @@
using Godot;
namespace Rokojori
{
[GlobalClass]
public partial class NetworkManager:Node
{
[Export]
public NetworkBackend backend;
NetworkNodeMemberReferences _references = new NetworkNodeMemberReferences();
public NetworkNodeMemberReferences references => _references;
ExtendedNetworkTransport _transport = new ExtendedNetworkTransport();
public NetworkTransport transport => _transport;
ExtendedNetworkSessionManager _sessionManager = new ExtendedNetworkSessionManager();
public NetworkSessionManager sessionManager => _sessionManager;
bool _initialized = false;
[Export]
public Action onStartedSession;
[Export]
public Action onSessionMemberJoined;
[Export]
public Action onSessionMemberLeft;
public static NetworkManager Get()
{
return Unique<NetworkManager>.Get();
}
public static bool IsInSession => Get().sessionManager.isInSession;
public static int ownSessionMemberIndex => Get().sessionManager.ownMemberIndex;
public static int serverSessionMemberIndex =>Get().sessionManager.serverMemberIndex;
public void Initialize()
{
if ( _initialized )
{
return;
}
RJLog.Log( "InitializeBackend:" );
backend.InitializeBackend( this, _sessionManager, _transport );
_initialized = true;
}
public override void _Process( double delta )
{
if ( ! IsInSession )
{
return;
}
_transport.ProcessQueuedMessages();
}
}
}

View File

@ -0,0 +1,47 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
[GlobalClass]
public partial class AddNetworkNodes:Action
{
[Export]
public Node[] nodes;
protected override void _OnTrigger()
{
RJLog.Log( "AddNetworkNodes" );
for ( int i = 0; i < nodes.Length; i++ )
{
AddNodeAndChildren( nodes[ i ] );
}
}
void AddNodeAndChildren( Node root )
{
var walker = new NodesWalker();
var nm = Unique<NetworkManager>.Get();
var rf = nm.references;
walker.Iterate( root,
n =>
{
var isNetworkNode = typeof( INetworkNode ).IsAssignableFrom( n.GetType() );
if ( ! isNetworkNode )
{
return;
}
var inn = (INetworkNode) n;
rf.AddMembersOf( inn );
}
);
}
}
}

View File

@ -0,0 +1,16 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public interface INetworkNode
{
List<NetworkNodeMember> GetNetworkNodeMembers();
NetworkTransportType GetNetworkType();
int GetNetworkOwner();
}
}

View File

@ -0,0 +1,56 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public partial class NetworkNode : Node, INetworkNode
{
[ExportGroup("Network Settings")]
[Export]
public NetworkTransportType networkType = NetworkTransportType.Never_Networked;
public NetworkTransportType GetNetworkType(){ return networkType; }
[Export]
public int networkOwner;
public int GetNetworkOwner(){ return networkOwner; }
protected List<NetworkNodeMember> _networkNodeMembers = null;
protected NetworkNodeSlot _networkNodeSlot = new NetworkNodeSlot();
public virtual List<NetworkNodeMember> GetNetworkNodeMembers()
{
if ( _networkNodeMembers != null )
{
return _networkNodeMembers;
}
_networkNodeMembers = CreateNetworkNodeMembers();
_networkNodeSlot.onMessage.AddAction( _OnNetworkMessageReceived );
InitializeNetworkMembers();
return _networkNodeMembers;
}
protected virtual List<NetworkNodeMember> CreateNetworkNodeMembers()
{
return new List<NetworkNodeMember>(){ _networkNodeSlot };
}
protected virtual void InitializeNetworkMembers()
{
for ( int i = 0; i < _networkNodeMembers.Count; i++ )
{
_networkNodeMembers[ i ]._SetNode( this );
}
}
protected virtual void _OnNetworkMessageReceived( NetworkMessageEvent m )
{
}
}
}

View File

@ -0,0 +1,95 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class NetworkNodeMember
{
protected int _networkID = -1;
public int networkID => _networkID;
public bool hasNetworkID => _networkID != -1;
public void _SetNetworkID ( int netID )
{
_networkID = netID;
}
protected INetworkNode _networkNode;
public INetworkNode networkNode => _networkNode;
protected NetworkTransportType customNetworkType = NetworkTransportType.Never_Networked;
protected bool hasCustomNetworkType = false;
public NetworkTransportType networkType => hasCustomNetworkType ? customNetworkType : networkNode.GetNetworkType();
public bool hasOwnedTransportType => NetworkTransportType.Owned_By_One == networkType;
public bool IsOwnedBy( int sessionMember )
{
return hasOwnedTransportType && networkNode.GetNetworkOwner() == sessionMember;
}
public bool isOwnedLocally
{
get
{
return IsOwnedBy( NetworkManager.ownSessionMemberIndex );
}
}
public bool CanReceive()
{
return NetworkTransportSettings.CanReceive( networkType, networkNode.GetNetworkOwner() );
}
public bool CanSend()
{
return NetworkTransportSettings.CanSend( networkType, networkNode.GetNetworkOwner() );
}
public void _SetNode( NetworkNode node )
{
_networkNode = node;
}
public void ReceiveNetworkMessage( NetworkMessageEvent messageEvent )
{
if ( ! CanReceive() )
{
return;
}
OnNetworkMessageReceived( messageEvent );
}
protected virtual void OnNetworkMessageReceived( NetworkMessageEvent messageEvent )
{
}
public void Send( BitView view, List<int> targets = null, bool reliable = true )
{
if ( ! CanSend() )
{
return;
}
var nm = Unique<NetworkManager>.Get();
var viewWithID = BitView.PrependID( networkID, view );
nm.transport.SendMessage( viewWithID, targets, reliable );
}
public void SendWithID( BitView viewWithID, List<int> targets = null, bool reliable = true )
{
if ( ! CanSend() )
{
return;
}
var nm = Unique<NetworkManager>.Get();
nm.transport.SendMessage( viewWithID, targets, reliable );
}
}
}

View File

@ -0,0 +1,50 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class NetworkNodeMemberReferences
{
Dictionary<int,NetworkNodeMember> referencesMap = new Dictionary<int, NetworkNodeMember>();
int counter = 1;
public NetworkNodeMember GetMember( int id )
{
if ( ! referencesMap.ContainsKey( id ) )
{
return null;
}
return referencesMap[ id ];
}
public void AddMembersOf( INetworkNode node )
{
var members = node.GetNetworkNodeMembers();
for ( int i = 0; i < members.Count; i++ )
{
if ( members[ i ].networkType == NetworkTransportType.Never_Networked )
{
continue;
}
if ( members[ i ].hasNetworkID )
{
continue;
}
RJLog.Log( "Networked member", HierarchyName.Of( (Node)node ), i );
var id = counter;
referencesMap[ id ] = members[ i ];
members[ i ]._SetNetworkID( id );
counter ++;
}
}
}
}

View File

@ -0,0 +1,16 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class NetworkNodeSlot:NetworkNodeMember
{
public EventSlot<NetworkMessageEvent> onMessage = new EventSlot<NetworkMessageEvent>();
protected override void OnNetworkMessageReceived( NetworkMessageEvent nme )
{
onMessage.DispatchEvent( nme );
}
}
}

View File

@ -0,0 +1,22 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
[GlobalClass]
public partial class JoinSession:Action
{
[Export]
public NetworkManager networkingManager;
[Export]
public NetworkSessionRequest sessionRequest;
protected override void _OnTrigger()
{
networkingManager.Initialize();
networkingManager.sessionManager.JoinSession( sessionRequest );
}
}
}

View File

@ -0,0 +1,11 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class NetworkSessionEvent
{
public long memberIndex;
}
}

View File

@ -0,0 +1,104 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class NetworkSessionManager
{
protected bool _isInSession = false;
public bool isInSession => _isInSession;
protected string _sessionName = null;
public string sessionName => _sessionName;
protected int _serverMemberIndex = 0;
public int serverMemberIndex => _serverMemberIndex;
protected int _ownMemberIndex = -1;
public int ownMemberIndex => _ownMemberIndex;
public bool isServer => ownMemberIndex == serverMemberIndex;
protected List<NetworkSessionMember> _sessionMembers = new List<NetworkSessionMember>();
public EventSlot<NetworkSessionEvent> onSessionEntered = new EventSlot<NetworkSessionEvent>();
public EventSlot<NetworkSessionEvent> onSessionLeft = new EventSlot<NetworkSessionEvent>();
public void StartSession( NetworkSessionRequest sessionRequest )
{
var nm = Unique<NetworkManager>.Get();
if ( nm.backend == null )
{
return;
}
RJLog.Log( "StartSession" );
nm.backend.StartSession( sessionRequest );
}
public void JoinSession( NetworkSessionRequest sessionRequest )
{
var nm = Unique<NetworkManager>.Get();
if ( nm.backend == null )
{
return;
}
RJLog.Log( "JoinSession" );
nm.backend.JoinSession( sessionRequest );
}
public void LeaveSession()
{
var nm = Unique<NetworkManager>.Get();
if ( nm.backend == null )
{
return;
}
nm.backend.LeaveSession();
}
}
public class ExtendedNetworkSessionManager:NetworkSessionManager
{
public void SetInSessionState( bool state = true )
{
_isInSession = state;
}
public void AddMember( NetworkSessionMember member )
{
_sessionMembers.Add( member );
var nse = new NetworkSessionEvent();
nse.memberIndex = member.index;
onSessionEntered.DispatchEvent( nse );
}
public void RemoveMember( long id )
{
var index = _sessionMembers.FindIndex( m => m.index == id );
if ( index == -1 )
{
return;
}
_sessionMembers.RemoveAt( index );
var nse = new NetworkSessionEvent();
nse.memberIndex = id;
onSessionLeft.DispatchEvent( nse );
}
}
}

View File

@ -0,0 +1,22 @@
using Godot;
namespace Rokojori
{
public class NetworkSessionMember
{
long _index;
public long index => _index;
public string name;
public static NetworkSessionMember Create( long index )
{
var member = new NetworkSessionMember();
member._index = index;
return member;
}
}
}

View File

@ -0,0 +1,19 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
[GlobalClass]
public partial class NetworkSessionRequest:Resource
{
[Export]
public string sessionName = null;
[Export]
public int maxMembers = -1;
[Export]
public int port = 1984;
[Export]
public string serverIP = null;
}
}

View File

@ -0,0 +1,15 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public enum NetworkSessionConnectionState
{
Not_Connected,
Connecting_As_Server,
Connecting_As_Client,
Connected_As_Server,
Connected_As_Client
}
}

View File

@ -0,0 +1,24 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
[GlobalClass]
public partial class StartSession:Action
{
[Export]
public NetworkManager networkingManager;
[Export]
public NetworkSessionRequest sessionRequest;
protected override void _OnTrigger()
{
RJLog.Log( "StartSession:" );
networkingManager.Initialize();
networkingManager.sessionManager.StartSession( sessionRequest );
}
}
}

View File

@ -0,0 +1,57 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
[GlobalClass]
public partial class NetworkTransform3D:NetworkNode
{
[Export]
public NetworkTransform3DType type;
NetworkNodeSlot _positionSlot = new NetworkNodeSlot();
NetworkNodeSlot _rotationSlot = new NetworkNodeSlot();
NetworkNodeSlot _scaleSlot = new NetworkNodeSlot();
protected override List<NetworkNodeMember> CreateNetworkNodeMembers()
{
return new List<NetworkNodeMember>()
{
_networkNodeSlot,
_positionSlot,
_rotationSlot,
_scaleSlot
};
}
Vector3 _sendPosition = Vector3.Zero;
Vector3 _sendRotation = Vector3.Zero;
Vector3 _sendScale = Vector3.One;
float _sendTime = 0;
bool _idle = true;
public override void _Process( double delta )
{
if ( ! NetworkManager.IsInSession )
{
return;
}
if ( ! _networkNodeSlot.hasOwnedTransportType )
{
return;
}
if ( _networkNodeSlot.isOwnedLocally )
{
}
else
{
}
}
}
}

View File

@ -0,0 +1,30 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
[GlobalClass]
public partial class NetworkTransform3DType:Resource
{
[ExportCategory("Position")]
[Export]
public bool positionX;
[Export]
public bool positionY;
[Export]
public bool positionZ;
[ExportCategory("Rotation")]
[Export]
public bool rotationX;
[Export]
public bool rotationY;
[Export]
public bool rotationZ;
}
}

Some files were not shown because too many files have changed in this diff Show More