Player/Camera Updates
This commit is contained in:
parent
3b74292b2c
commit
af3786e6b4
|
@ -99,6 +99,7 @@ namespace Rokojori
|
|||
|
||||
public void Highlight( HighlightActionType type, Node3D[] targets )
|
||||
{
|
||||
|
||||
if ( HighlightActionType.Start == type )
|
||||
{
|
||||
StartHighlight( targets );
|
||||
|
@ -131,6 +132,7 @@ namespace Rokojori
|
|||
var outlineMaterial = new OutlineMaterial();
|
||||
outlineMaterial.albedo.Set( colorTransparent );
|
||||
material = outlineMaterial;
|
||||
outlineMaterial.size.Set( 2 );
|
||||
|
||||
outlineMaterial.opacityModulationDuration.Set( opacityModulationDuration );
|
||||
outlineMaterial.opacityModulationStrength.Set( opacityModulationStrength );
|
||||
|
|
|
@ -31,5 +31,5 @@ opacityModulationStrength = 0.75
|
|||
opacityModulationDuration = 1.0
|
||||
opacityModulationTransition = 1.0
|
||||
outlineMaterialMode = 0
|
||||
overlayOpacity = 0.01
|
||||
overlayOpacity = 0.1
|
||||
overlayMaterialMode = 0
|
||||
|
|
|
@ -24,6 +24,16 @@ namespace Rokojori
|
|||
}
|
||||
|
||||
|
||||
public static float ComputeCoefficientForFramesAdaptiveTreshold( int numFrames )
|
||||
{
|
||||
var fps60 = 1f/60f;
|
||||
var treshold = MathX.MapClamped( numFrames, 400, 600, fps60/50, fps60/2 );
|
||||
|
||||
return ComputeCoefficientForFrames( numFrames, treshold );
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static float ComputeCoefficientForFrames( int numFrames, float treshold = 1f/60f * 0.02f )
|
||||
{
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@ namespace Rokojori
|
|||
[GlobalClass]
|
||||
public partial class FrameSmoothing: Smoothing
|
||||
{
|
||||
[Export( PropertyHint.Range, "0,600")]
|
||||
[Export( PropertyHint.Range, "0,1800")]
|
||||
public float frames = 10;
|
||||
|
||||
protected override float _ComputeInterpolationAmount( float delta )
|
||||
{
|
||||
frames = Mathf.Clamp( frames, 0, 600 );
|
||||
frames = Mathf.Clamp( frames, 0, 1800 );
|
||||
|
||||
if ( frames <= 0 )
|
||||
{
|
||||
|
@ -36,7 +36,7 @@ namespace Rokojori
|
|||
|
||||
public static float ComputeCoefficientInt( float delta, int frames )
|
||||
{
|
||||
frames = Mathf.Clamp( frames, 0, 600 );
|
||||
frames = Mathf.Clamp( frames, 0, 1800 );
|
||||
|
||||
if ( frames <= 0 )
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -11,19 +11,12 @@ namespace Rokojori
|
|||
[Export]
|
||||
public string path;
|
||||
|
||||
[Export]
|
||||
public bool compute
|
||||
{
|
||||
get { return false; }
|
||||
set
|
||||
{
|
||||
if ( ! value )
|
||||
{
|
||||
return;
|
||||
}
|
||||
[ExportToolButton( "Compute")]
|
||||
public Callable ComputeButton => Callable.From( Compute );
|
||||
|
||||
FrameSmoothingTable.ComputeAndSaveTable( path );
|
||||
}
|
||||
async void Compute()
|
||||
{
|
||||
await FrameSmoothingTable.ComputeAndSaveTable( this, path );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,12 +9,44 @@ namespace Rokojori
|
|||
public partial class Smoothing: Resource
|
||||
{
|
||||
float _currentFloat = 0;
|
||||
public void SetCurrent( float value )
|
||||
{
|
||||
_currentFloat = value;
|
||||
}
|
||||
|
||||
Vector2 _currentVector2 = Vector2.Zero;
|
||||
Vector3 _currentVector3 = Vector3.Zero;
|
||||
Vector4 _currentVector4 = Vector4.Zero;
|
||||
|
||||
public void SetCurrent( Vector2 value )
|
||||
{
|
||||
_currentVector2 = value;
|
||||
}
|
||||
|
||||
public void SetCurrent( Vector3 value )
|
||||
{
|
||||
_currentVector3 = value;
|
||||
}
|
||||
|
||||
public void SetCurrent( Vector4 value )
|
||||
{
|
||||
_currentVector4 = value;
|
||||
}
|
||||
|
||||
|
||||
Quaternion _currentQuaternion = Quaternion.Identity;
|
||||
|
||||
public void SetCurrent( Quaternion quaternion )
|
||||
{
|
||||
_currentQuaternion = quaternion;
|
||||
}
|
||||
|
||||
Color _currentColor = Colors.Black;
|
||||
|
||||
public void SetCurrent( Color color )
|
||||
{
|
||||
_currentColor = color;
|
||||
}
|
||||
|
||||
public float Smooth( float nextValue, float delta )
|
||||
{
|
||||
|
@ -29,7 +61,16 @@ namespace Rokojori
|
|||
return sm.Smooth( value, delta );
|
||||
}
|
||||
|
||||
public Vector2 Smooth( Vector2 nextValue, float delta )
|
||||
public static float ApplyWith( Smoothing sm, float oldValue, float nextValue, float delta )
|
||||
{
|
||||
if ( sm == null ){ return nextValue; }
|
||||
|
||||
sm._currentFloat = oldValue;
|
||||
|
||||
return sm.Smooth( nextValue, delta );
|
||||
}
|
||||
|
||||
public Vector2 Smooth( Vector2 nextValue, float delta )
|
||||
{
|
||||
_currentVector2 = _currentVector2.Lerp( nextValue, _ComputeInterpolationAmount( delta ) );
|
||||
|
||||
|
@ -42,6 +83,30 @@ namespace Rokojori
|
|||
return sm.Smooth( value, delta );
|
||||
}
|
||||
|
||||
public static float ApplyDegrees( Smoothing sm, float value, float delta )
|
||||
{
|
||||
var newV = MathX.RadiansToVector2( MathX.DegreesToRadians * value );
|
||||
|
||||
return MathX.RadiansToDegrees * MathX.Vector2ToRadians( Apply( sm, newV, delta ) );
|
||||
}
|
||||
|
||||
public static float ApplyDegreesWith( Smoothing sm, float oldValue, float nextValue, float delta )
|
||||
{
|
||||
var oldV = MathX.RadiansToVector2( MathX.DegreesToRadians * oldValue );
|
||||
var newV = MathX.RadiansToVector2( MathX.DegreesToRadians * nextValue );
|
||||
|
||||
return MathX.RadiansToDegrees * MathX.Vector2ToRadians( ApplyWith( sm, oldV, newV, delta ) );
|
||||
}
|
||||
|
||||
public static Vector2 ApplyWith( Smoothing sm, Vector2 oldValue, Vector2 nextValue, float delta )
|
||||
{
|
||||
if ( sm == null ){ return nextValue; }
|
||||
|
||||
sm._currentVector2 = oldValue;
|
||||
|
||||
return sm.Smooth( nextValue, delta );
|
||||
}
|
||||
|
||||
public Vector3 Smooth( Vector3 nextValue, float delta )
|
||||
{
|
||||
_currentVector3 = _currentVector3.Lerp( nextValue, _ComputeInterpolationAmount( delta ) );
|
||||
|
@ -70,7 +135,8 @@ namespace Rokojori
|
|||
|
||||
public Quaternion Smooth( Quaternion nextValue, float delta )
|
||||
{
|
||||
_currentQuaternion = _currentQuaternion.Slerp( nextValue, _ComputeInterpolationAmount( delta ) );
|
||||
_currentQuaternion = _currentQuaternion.GetNormalized();
|
||||
_currentQuaternion = _currentQuaternion.Slerp( nextValue.GetNormalized(), _ComputeInterpolationAmount( delta ) );
|
||||
|
||||
return _currentQuaternion;
|
||||
}
|
||||
|
@ -109,16 +175,18 @@ namespace Rokojori
|
|||
var duration = 0f;
|
||||
var lastValue = value;
|
||||
|
||||
var maxDuration = 30;
|
||||
var maxDuration = 120;
|
||||
|
||||
while ( value > tresholdValue && duration < maxDuration )
|
||||
{
|
||||
lastValue = value;
|
||||
value = Smooth( 0, delta );
|
||||
Safe.While(
|
||||
()=> value > tresholdValue && duration < maxDuration,
|
||||
()=>
|
||||
{
|
||||
lastValue = value;
|
||||
value = Smooth( 0, delta );
|
||||
|
||||
duration += delta;
|
||||
|
||||
}
|
||||
duration += delta;
|
||||
}
|
||||
);
|
||||
|
||||
_currentFloat = cached;
|
||||
|
||||
|
|
|
@ -76,8 +76,22 @@ namespace Rokojori
|
|||
);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void InitializeCamera()
|
||||
{
|
||||
var cameraManager = this.Get<VirtualCamera3DManager>();
|
||||
var camera = this.Get<Camera3D>();
|
||||
|
||||
cameraManager.camera = camera;
|
||||
var slot = cameraManager.CreateChild<VirtualCamera3DSlot>();
|
||||
slot.camera = this.Get<MouseEditorCamera>();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -13,6 +13,11 @@ namespace Rokojori
|
|||
return Directory.Exists( path );
|
||||
}
|
||||
|
||||
public static bool FileExists( string path )
|
||||
{
|
||||
return File.Exists( path );
|
||||
}
|
||||
|
||||
public static void CreateDirectory( string path )
|
||||
{
|
||||
Directory.CreateDirectory( path );
|
||||
|
|
|
@ -9,6 +9,16 @@ namespace Rokojori
|
|||
{
|
||||
public static class Nodes
|
||||
{
|
||||
public static T Get<T>( this Node node ) where T:Node
|
||||
{
|
||||
return GetAnyChild<T>( node );
|
||||
}
|
||||
|
||||
public static T GetChild<T>( this Node node ) where T:Node
|
||||
{
|
||||
return GetDirectChild<T>( node );
|
||||
}
|
||||
|
||||
public static void CopyData<T>( T from, T to ) where T:Node
|
||||
{
|
||||
var memberInfos = ReflectionHelper.GetDataMemberInfos<T>( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly );
|
||||
|
|
|
@ -5,7 +5,7 @@ using Godot.Collections;
|
|||
|
||||
namespace Rokojori
|
||||
{
|
||||
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class Caster:Node3D
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@ using Godot.Collections;
|
|||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class CharacterController:Node
|
||||
{
|
||||
|
@ -28,14 +29,10 @@ namespace Rokojori
|
|||
|
||||
|
||||
[Export]
|
||||
public float rotationSmoothingDuration = 0;
|
||||
|
||||
Smoother rotationSmoother = new Smoother();
|
||||
public Smoothing rotationSmoothing;
|
||||
|
||||
[Export]
|
||||
public float positionSmoothingDuration = 0;
|
||||
|
||||
Smoother positionSmoother = new Smoother();
|
||||
public Smoothing positionSmoothing;
|
||||
|
||||
public float delta = 0;
|
||||
|
||||
|
@ -49,22 +46,24 @@ namespace Rokojori
|
|||
|
||||
if ( CharacterUpdateMode.Process == characterUpdateMode )
|
||||
{
|
||||
this.delta = (float)delta;
|
||||
Nodes.ForEachDirectChild<CharacterControllerAction>( actionsContainer, a => Action.Trigger( a ) );
|
||||
this.delta = (float) delta;
|
||||
Nodes.ForEachDirectChild<CharacterControllerAction>( actionsContainer, Action.Trigger );
|
||||
}
|
||||
|
||||
// positionSmoother.CopyPosition( graphics, body, rotationSmoothingDuration, delta );
|
||||
// rotationSmoother.CopyRotation( graphics, body, positionSmoothingDuration, delta );
|
||||
|
||||
Pose.CopyTo( body, graphics );
|
||||
graphics.GlobalPosition = Smoothing.Apply( positionSmoothing, body.GlobalPosition, this.delta );
|
||||
graphics.SetGlobalQuaternion( Smoothing.Apply( rotationSmoothing, body.GetGlobalQuaternion(), this.delta ) );
|
||||
// Pose.CopyTo( body, graphics );
|
||||
}
|
||||
|
||||
public override void _PhysicsProcess( double delta )
|
||||
{
|
||||
if ( CharacterUpdateMode.Physics_Process == characterUpdateMode )
|
||||
{
|
||||
this.delta = (float)delta;
|
||||
Nodes.ForEachDirectChild<CharacterControllerAction>( actionsContainer, a => Action.Trigger( a ) );
|
||||
this.delta = (float) delta;
|
||||
Nodes.ForEachDirectChild<CharacterControllerAction>( actionsContainer, Action.Trigger );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ using Godot.Collections;
|
|||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class CharacterControllerAction:Action
|
||||
{
|
||||
|
|
|
@ -5,30 +5,18 @@ using Godot.Collections;
|
|||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class CharacterMovement:CharacterControllerAction
|
||||
{
|
||||
[Export]
|
||||
public float onFloorMultiply = 0f;
|
||||
public float onFloorMultiply = 1f;
|
||||
|
||||
[Export]
|
||||
public bool overwriteVelocity = true;
|
||||
|
||||
[ExportGroup( "Actions" )]
|
||||
[Export]
|
||||
public Action onMoving;
|
||||
[Export]
|
||||
public Action onIdle;
|
||||
public float inAirMultiply = 0.01f;
|
||||
|
||||
[Export]
|
||||
public Action onForward;
|
||||
[Export]
|
||||
public Action onBackwards;
|
||||
[Export]
|
||||
public Action onStrafeLeft;
|
||||
[Export]
|
||||
public Action onStrafeRight;
|
||||
|
||||
public CameraTargetOffset cameraTargetOffset;
|
||||
|
||||
[ExportGroup( "Direction Source" )]
|
||||
[Export]
|
||||
|
@ -41,32 +29,26 @@ namespace Rokojori
|
|||
Project_On_TransformPlane
|
||||
}
|
||||
|
||||
[Export]
|
||||
public DirectionProcessing directionProcessing;
|
||||
|
||||
[ExportGroup( "Moving" )]
|
||||
[ExportGroup("Movement")]
|
||||
|
||||
[Export]
|
||||
public float moveSpeed;
|
||||
|
||||
[Export]
|
||||
public Sensor forward;
|
||||
public CharacterMovementType controllerMovementType;
|
||||
|
||||
[Export]
|
||||
public Sensor backwards;
|
||||
|
||||
[ExportGroup( "Strafing" )]
|
||||
[Export]
|
||||
public float strafeSpeed;
|
||||
public CharacterMovementType mouseKeyboardMovementType;
|
||||
|
||||
[Export]
|
||||
public Sensor strafeLeft;
|
||||
public CharacterMovementType currentMovementType;
|
||||
|
||||
[Export]
|
||||
public Sensor strafeRight;
|
||||
public Smoothing onFloorMovementSmoothing = new FrameSmoothing();
|
||||
|
||||
[Export]
|
||||
public bool useBodyDirection = true;
|
||||
public Smoothing inAirMovementSmoothing = new FrameSmoothing();
|
||||
|
||||
|
||||
[ExportGroup( "Rotation" )]
|
||||
|
||||
|
@ -74,74 +56,73 @@ namespace Rokojori
|
|||
public bool adjustRotation = true;
|
||||
|
||||
[Export]
|
||||
public Curve forwardToRotation = MathX.Curve( 0, 1 );
|
||||
public Curve forwardToRotationSmoothingFrames = MathX.Curve( 0, 1 );
|
||||
|
||||
[Export( PropertyHint.Range, "0,1")]
|
||||
public float rotationSmoothingCoefficient = 0.1f;
|
||||
Smoother rotationSmoother = new Smoother();
|
||||
[Export(PropertyHint.Range, "0,600")]
|
||||
public int airRotationSmoothingFrames = 120;
|
||||
|
||||
FrameSmoothing rotationSmoothing = new FrameSmoothing();
|
||||
|
||||
protected CharacterMovementData characterMovementData = new CharacterMovementData();
|
||||
|
||||
protected override void _OnTrigger()
|
||||
{
|
||||
if ( ! body.IsOnFloor() )
|
||||
var onFloor = body.IsOnFloor();
|
||||
|
||||
characterMovementData.Reset( this );
|
||||
|
||||
if ( currentMovementType == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var movement = Vector3.Zero;
|
||||
currentMovementType.ProcessMovement( characterMovementData );
|
||||
|
||||
var fw = Sensors.GetValue( forward );
|
||||
var bw = Sensors.GetValue( backwards );
|
||||
|
||||
var fbAxis = Sensors.PolarAxis( backwards, forward );
|
||||
|
||||
var dir = directionSource != null ? directionSource : body;
|
||||
var forwardDirection = dir.GlobalForward();
|
||||
var rightDirection = useBodyDirection ? body.GlobalRight() : dir.GlobalRight();
|
||||
|
||||
if ( DirectionProcessing.Zero_Y_And_Normalize == directionProcessing )
|
||||
if ( cameraTargetOffset != null )
|
||||
{
|
||||
forwardDirection.Y = 0;
|
||||
rightDirection.Y = 0;
|
||||
}
|
||||
else if ( DirectionProcessing.Project_On_TransformPlane == directionProcessing )
|
||||
{
|
||||
var bodyPlane = Plane3.CreateFromNode3D( body );
|
||||
forwardDirection = bodyPlane.ConstrainToPlane( forwardDirection + body.GlobalPosition ) - body.GlobalPosition;
|
||||
rightDirection = bodyPlane.ConstrainToPlane( rightDirection + body.GlobalPosition ) - body.GlobalPosition;
|
||||
cameraTargetOffset.SetMovingForward( characterMovementData.isMovingForward ? 1f : 0f );
|
||||
}
|
||||
|
||||
forwardDirection = forwardDirection.Normalized();
|
||||
rightDirection = rightDirection.Normalized();
|
||||
var movementMultiply = onFloor ? onFloorMultiply : inAirMultiply;
|
||||
|
||||
movement += forwardDirection * Sensors.PolarAxis( backwards, forward ) * moveSpeed;
|
||||
characterMovementData.movement *= movementMultiply;
|
||||
|
||||
movement += rightDirection * Sensors.PolarAxis( strafeLeft, strafeRight ) * strafeSpeed ;
|
||||
|
||||
|
||||
|
||||
if ( body.IsOnFloor() )
|
||||
{
|
||||
movement *= onFloorMultiply;
|
||||
}
|
||||
|
||||
if ( adjustRotation )
|
||||
{
|
||||
var currentRotation = body.GetGlobalQuaternion();
|
||||
var nextRotation = Math3D.LookRotation( forwardDirection );
|
||||
var nextRotation = Math3D.LookRotation( characterMovementData.forwardDirection );
|
||||
var speed = MathX.Clamp01( characterMovementData.movement.Length() / moveSpeed );
|
||||
|
||||
var sm = 1f - rotationSmoothingCoefficient;
|
||||
sm = sm * sm;
|
||||
if ( speed > 0 )
|
||||
{
|
||||
Quaternion rotation;
|
||||
|
||||
var speed = MathX.Clamp01( movement.Length() / moveSpeed ) * Mathf.Max( fw, bw );
|
||||
if ( onFloor )
|
||||
{
|
||||
rotationSmoothing.frames = Mathf.Round( forwardToRotationSmoothingFrames.Sample( speed ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
rotationSmoothing.frames = airRotationSmoothingFrames;
|
||||
}
|
||||
|
||||
sm *= forwardToRotation.Sample( speed );
|
||||
|
||||
var rotation = rotationSmoother.SmoothWithCoefficient( currentRotation, nextRotation, sm, controller.delta );
|
||||
body.SetGlobalQuaternion( rotation );
|
||||
rotation = rotationSmoothing.Smooth( nextRotation, controller.delta );
|
||||
body.SetGlobalQuaternion( rotation );
|
||||
}
|
||||
}
|
||||
|
||||
Velocity( movement, overwriteVelocity );
|
||||
var smoothedMovement = Vector3.Zero;
|
||||
|
||||
if ( onFloor )
|
||||
{
|
||||
smoothedMovement = onFloorMovementSmoothing.Smooth( characterMovementData.movement, controller.delta );
|
||||
}
|
||||
else
|
||||
{
|
||||
smoothedMovement = inAirMovementSmoothing.Smooth( characterMovementData.movement, controller.delta );
|
||||
}
|
||||
|
||||
Velocity( smoothedMovement, onFloor );
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
using Godot;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot.Collections;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
public enum CharacterDirectionProcessing
|
||||
{
|
||||
None,
|
||||
Zero_Y_And_Normalize,
|
||||
Project_On_TransformPlane
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://823d4vtyx5d3
|
|
@ -0,0 +1,23 @@
|
|||
using Godot;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot.Collections;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
public class CharacterMovementData
|
||||
{
|
||||
public CharacterMovement characterMovement;
|
||||
public Vector3 movement;
|
||||
public Vector3 forwardDirection;
|
||||
public bool isMovingForward;
|
||||
|
||||
public void Reset( CharacterMovement characterMovement )
|
||||
{
|
||||
this.characterMovement = characterMovement;
|
||||
movement = Vector3.Zero;
|
||||
forwardDirection = Vector3.Forward;
|
||||
isMovingForward = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://bh7oo1wqi4cau
|
|
@ -0,0 +1,17 @@
|
|||
using Godot;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot.Collections;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class CharacterMovementType:Resource
|
||||
{
|
||||
public virtual void ProcessMovement( CharacterMovementData characterMovementData )
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://dco3ngscxqjf5
|
|
@ -0,0 +1,78 @@
|
|||
using Godot;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot.Collections;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class StrafeMovementType:CharacterMovementType
|
||||
{
|
||||
public enum StrafeDirectionSource
|
||||
{
|
||||
Character_Movement_Direction_Source,
|
||||
Character_Controller_Body
|
||||
}
|
||||
|
||||
[ExportGroup( "Movement" )]
|
||||
[Export]
|
||||
public Sensor forward;
|
||||
|
||||
[Export]
|
||||
public Sensor backwards;
|
||||
|
||||
[Export]
|
||||
public CharacterDirectionProcessing directionProcessing;
|
||||
|
||||
[ExportGroup( "Strafing" )]
|
||||
[Export]
|
||||
public float strafeSpeedMultiply = 1.0f;
|
||||
|
||||
[Export]
|
||||
public Sensor strafeLeft;
|
||||
|
||||
[Export]
|
||||
public Sensor strafeRight;
|
||||
|
||||
[Export]
|
||||
public StrafeDirectionSource strafeDirectionSource = StrafeDirectionSource.Character_Controller_Body;
|
||||
|
||||
public override void ProcessMovement( CharacterMovementData characterMovementData )
|
||||
{
|
||||
var characterMovement = characterMovementData.characterMovement;
|
||||
var directionSource = characterMovement.directionSource;
|
||||
var body = characterMovement.body;
|
||||
|
||||
var dir = directionSource != null ? directionSource : body;
|
||||
var forwardDirection = dir.GlobalForward();
|
||||
var rightDirection = StrafeDirectionSource.Character_Controller_Body == strafeDirectionSource ?
|
||||
body.GlobalRight() : dir.GlobalRight();
|
||||
|
||||
if ( CharacterDirectionProcessing.Zero_Y_And_Normalize == directionProcessing )
|
||||
{
|
||||
forwardDirection.Y = 0;
|
||||
rightDirection.Y = 0;
|
||||
}
|
||||
else if ( CharacterDirectionProcessing.Project_On_TransformPlane == directionProcessing )
|
||||
{
|
||||
var bodyPlane = Plane3.CreateFromNode3D( body );
|
||||
forwardDirection = bodyPlane.ConstrainToPlane( forwardDirection + body.GlobalPosition ) - body.GlobalPosition;
|
||||
rightDirection = bodyPlane.ConstrainToPlane( rightDirection + body.GlobalPosition ) - body.GlobalPosition;
|
||||
}
|
||||
|
||||
forwardDirection = forwardDirection.Normalized();
|
||||
rightDirection = rightDirection.Normalized();
|
||||
|
||||
var movement = forwardDirection * Sensors.PolarAxis( backwards, forward ) * characterMovement.moveSpeed;
|
||||
|
||||
movement += rightDirection * Sensors.PolarAxis( strafeLeft, strafeRight ) * characterMovement.moveSpeed * strafeSpeedMultiply ;
|
||||
|
||||
characterMovementData.movement = movement;
|
||||
characterMovementData.isMovingForward = forward.isActive;
|
||||
characterMovementData.forwardDirection = forwardDirection;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://b37sjsfvphc8b
|
|
@ -0,0 +1,105 @@
|
|||
using Godot;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot.Collections;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class TurnMovementType:CharacterMovementType
|
||||
{
|
||||
[Export]
|
||||
public CharacterDirectionProcessing directionProcessing;
|
||||
|
||||
[ExportGroup( "Movement" )]
|
||||
[Export]
|
||||
public Sensor up;
|
||||
|
||||
[Export]
|
||||
public Sensor down;
|
||||
|
||||
[Export]
|
||||
public Sensor left;
|
||||
|
||||
[Export]
|
||||
public Sensor right;
|
||||
|
||||
[ExportGroup( "Strafing" )]
|
||||
[Export]
|
||||
public bool useBodyDirection = true;
|
||||
|
||||
[Export]
|
||||
public Sensor strafeBack;
|
||||
|
||||
[Export]
|
||||
public Sensor strafeLeft;
|
||||
|
||||
[Export]
|
||||
public Sensor strafeRight;
|
||||
|
||||
[Export]
|
||||
public float strafeBackSpeedMultiply = 1.0f;
|
||||
|
||||
[Export]
|
||||
public float strafeSidewardsSpeedMultiply = 1.0f;
|
||||
|
||||
public override void ProcessMovement( CharacterMovementData characterMovementData )
|
||||
{
|
||||
var characterMovement = characterMovementData.characterMovement;
|
||||
var directionSource = characterMovement.directionSource;
|
||||
var body = characterMovement.body;
|
||||
|
||||
var dir = directionSource != null ? directionSource : body;
|
||||
var forwardDirection = dir.GlobalForward();
|
||||
var rightDirection = dir.GlobalRight();
|
||||
var forwardStrafe = useBodyDirection ? body.GlobalForward() : dir.GlobalForward();
|
||||
var rightStrafe = useBodyDirection ? body.GlobalRight() : dir.GlobalRight();
|
||||
|
||||
if ( CharacterDirectionProcessing.Zero_Y_And_Normalize == directionProcessing )
|
||||
{
|
||||
forwardDirection.Y = 0;
|
||||
rightDirection.Y = 0;
|
||||
}
|
||||
else if ( CharacterDirectionProcessing.Project_On_TransformPlane == directionProcessing )
|
||||
{
|
||||
var bodyPlane = Plane3.CreateFromNode3D( body );
|
||||
forwardDirection = bodyPlane.ConstrainToPlane( forwardDirection + body.GlobalPosition ) - body.GlobalPosition;
|
||||
rightDirection = bodyPlane.ConstrainToPlane( rightDirection + body.GlobalPosition ) - body.GlobalPosition;
|
||||
}
|
||||
|
||||
forwardDirection = forwardDirection.Normalized();
|
||||
rightDirection = rightDirection.Normalized();
|
||||
|
||||
|
||||
var direction = Sensors.FourDirectional( left, right, up, down );
|
||||
|
||||
var movement = forwardDirection * - direction.Y * characterMovement.moveSpeed;
|
||||
|
||||
movement += rightDirection * direction.X * characterMovement.moveSpeed;
|
||||
|
||||
var turningForwardDirection = movement.Normalized();
|
||||
|
||||
if ( Sensors.IsActive( strafeBack ) )
|
||||
{
|
||||
movement += -Sensors.GetValue( strafeBack ) * forwardStrafe * characterMovement.moveSpeed * strafeBackSpeedMultiply;
|
||||
turningForwardDirection = forwardDirection;
|
||||
}
|
||||
|
||||
if ( Sensors.IsActive( strafeLeft ) || Sensors.IsActive( strafeRight ) )
|
||||
{
|
||||
var strafeStrength = Sensors.PolarAxis( strafeLeft, strafeRight );
|
||||
movement += strafeStrength * rightStrafe * characterMovement.moveSpeed * strafeSidewardsSpeedMultiply;
|
||||
turningForwardDirection = forwardDirection;
|
||||
}
|
||||
|
||||
movement = movement.ConstrainLength( characterMovement.moveSpeed );
|
||||
|
||||
characterMovementData.movement = movement;
|
||||
characterMovementData.isMovingForward = ! Math3D.FacingSameDirection( turningForwardDirection, forwardDirection );
|
||||
characterMovementData.forwardDirection = turningForwardDirection;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://kodskdb1mcd4
|
|
@ -5,6 +5,7 @@ using Godot.Collections;
|
|||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class Gravity:CharacterControllerAction
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@ using Godot.Collections;
|
|||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class GroundReset:CharacterControllerAction
|
||||
{
|
||||
|
|
|
@ -5,29 +5,43 @@ using Godot.Collections;
|
|||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class Jump:CharacterControllerAction
|
||||
{
|
||||
[Export]
|
||||
public Sensor button;
|
||||
|
||||
[Export]
|
||||
public float jumpStrength;
|
||||
[ExportGroup( "Jump Impulse")]
|
||||
|
||||
[Export]
|
||||
public float maxJumpDuration;
|
||||
public float jumpImpulseStrength;
|
||||
|
||||
[Export( PropertyHint.Range, "0,100" )]
|
||||
public float velocityToJumpDirection = 0.5f;
|
||||
|
||||
[Export]
|
||||
public Curve jumpCurveStrength = MathX.Curve( 1, 0 );
|
||||
public float velocityTresholdForJumpDirection = 1f;
|
||||
|
||||
|
||||
[ExportGroup( "Air Control")]
|
||||
|
||||
[Export]
|
||||
public float jumpedDuration;
|
||||
public Curve airControlCurveStrength = MathX.Curve( 1, 0 );
|
||||
|
||||
[Export]
|
||||
public bool canJump = false;
|
||||
public float airMaxControlStrength;
|
||||
|
||||
[Export]
|
||||
public bool jumping = false;
|
||||
public float maxAirControlDuration;
|
||||
|
||||
float jumpedDuration;
|
||||
|
||||
bool canJump = false;
|
||||
|
||||
bool jumping = false;
|
||||
|
||||
bool needsToRelease = false;
|
||||
|
||||
|
||||
|
||||
|
@ -35,7 +49,11 @@ namespace Rokojori
|
|||
{
|
||||
if ( body.IsOnFloor() )
|
||||
{
|
||||
jumping = false;
|
||||
if ( jumping )
|
||||
{
|
||||
jumping = false;
|
||||
needsToRelease = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! ( jumping || body.IsOnFloor() ) )
|
||||
|
@ -46,6 +64,12 @@ namespace Rokojori
|
|||
if ( ! button.isActive )
|
||||
{
|
||||
jumping = false;
|
||||
needsToRelease = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( needsToRelease )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -53,17 +77,33 @@ namespace Rokojori
|
|||
{
|
||||
jumping = true;
|
||||
jumpedDuration = 0;
|
||||
|
||||
var jumpDirection = Vector3.Up * jumpImpulseStrength;
|
||||
|
||||
if ( body.Velocity.Length() > velocityTresholdForJumpDirection )
|
||||
{
|
||||
var xz = body.Velocity;
|
||||
xz.Y = 0;
|
||||
// xz = xz.Normalized();
|
||||
|
||||
jumpDirection += xz * velocityToJumpDirection;
|
||||
}
|
||||
|
||||
SetVelocity( jumpDirection );
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
jumpedDuration += controller.delta;
|
||||
|
||||
canJump = jumpedDuration < maxJumpDuration;
|
||||
canJump = jumpedDuration < maxAirControlDuration;
|
||||
|
||||
|
||||
if ( jumpedDuration < maxJumpDuration )
|
||||
if ( canJump )
|
||||
{
|
||||
var jumpStrengthMultiply = jumpCurveStrength.Sample( jumpedDuration / maxJumpDuration );
|
||||
AddVelocity( Vector3.Up * jumpStrength );
|
||||
var jumpStrengthMultiply = airControlCurveStrength.Sample( jumpedDuration / maxAirControlDuration );
|
||||
AddVelocity( Vector3.Up * airMaxControlStrength * jumpStrengthMultiply );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ using Godot.Collections;
|
|||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class MoveAndSlide:CharacterControllerAction
|
||||
{
|
||||
|
|
|
@ -21,11 +21,18 @@ namespace Rokojori
|
|||
[Export]
|
||||
public Node3D grabOffset;
|
||||
|
||||
[Export]
|
||||
public Smoothing positionSmoothing;
|
||||
|
||||
[Export]
|
||||
public Smoothing rotationSmoothing;
|
||||
|
||||
[ExportGroup("Read Only")]
|
||||
[Export]
|
||||
public Grabbable grabbable;
|
||||
|
||||
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
SensorManager.Register( this, button );
|
||||
|
@ -59,7 +66,7 @@ namespace Rokojori
|
|||
return;
|
||||
}
|
||||
|
||||
var grabbable = Nodes.Find<Grabbable>( pointable.GetParent() );
|
||||
grabbable = Nodes.Find<Grabbable>( pointable.GetParent() );
|
||||
|
||||
if ( grabbable == null )
|
||||
{
|
||||
|
@ -76,6 +83,8 @@ namespace Rokojori
|
|||
return;
|
||||
}
|
||||
|
||||
positionSmoothing.SetCurrent( grabbable.grabTarget.GlobalPosition );
|
||||
rotationSmoothing.SetCurrent( grabbable.grabTarget.GetGlobalQuaternion() );
|
||||
UpdateGrabbable();
|
||||
}
|
||||
);
|
||||
|
@ -89,7 +98,9 @@ namespace Rokojori
|
|||
|
||||
void UpdateGrabbable()
|
||||
{
|
||||
|
||||
// this.LogInfo( "Grabbing", HierarchyName.Of( grabbable ) );
|
||||
grabbable.grabTarget.GlobalPosition = Smoothing.Apply( positionSmoothing, grabOffset.GlobalPosition, timeLine.delta );
|
||||
grabbable.grabTarget.SetGlobalQuaternion( Smoothing.Apply( rotationSmoothing, grabOffset.GetGlobalQuaternion(), timeLine.delta ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ using Godot.Collections;
|
|||
|
||||
namespace Rokojori
|
||||
{
|
||||
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class MultiRayCaster:Caster
|
||||
{
|
||||
|
@ -24,6 +24,9 @@ namespace Rokojori
|
|||
[Export]
|
||||
public Vector3 to;
|
||||
|
||||
[Export]
|
||||
public Node collider;
|
||||
|
||||
public override int NumColliders()
|
||||
{
|
||||
return numCollisions;
|
||||
|
@ -59,6 +62,14 @@ namespace Rokojori
|
|||
ResolveCollisions();
|
||||
SortCollisions();
|
||||
|
||||
var nextCollider = NumColliders() == 0 ? null : GetCollider( 0 );
|
||||
|
||||
if ( nextCollider != collider )
|
||||
{
|
||||
collider = nextCollider;
|
||||
|
||||
// this.LogInfo( "New Collider:", HierarchyName.Of( collider ) );
|
||||
}
|
||||
|
||||
Action.Trigger( afterProcess );
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ using Godot.Collections;
|
|||
|
||||
namespace Rokojori
|
||||
{
|
||||
|
||||
[Tool]
|
||||
[GlobalClass,Icon("res://addons/rokojori_action_library/Icons/Pointer.svg")]
|
||||
public partial class Pointer:Node3D
|
||||
{
|
||||
|
|
|
@ -18,6 +18,11 @@ namespace Rokojori
|
|||
return LookingAtEachOtherAngle( lookDirectionA, lookDirectionB ) > 0;
|
||||
}
|
||||
|
||||
public static bool FacingSameDirection( Vector3 lookDirectionA, Vector3 lookDirectionB )
|
||||
{
|
||||
return ! LookingAtEachOther( lookDirectionA, lookDirectionB );
|
||||
}
|
||||
|
||||
public static bool LookingTowards( Vector3 from, Vector3 fromDirection, Vector3 to )
|
||||
{
|
||||
return LookingAtEachOther( fromDirection, to - from );
|
||||
|
@ -103,11 +108,26 @@ namespace Rokojori
|
|||
return v.X == 0 && v.Y == 0 && v.Z == 0;
|
||||
}
|
||||
|
||||
|
||||
public static Vector3 ConstrainLength( this Vector3 v, float maxLength )
|
||||
{
|
||||
var length = v.Length();
|
||||
|
||||
if ( length <= maxLength )
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
return v.Normalized() * maxLength;
|
||||
}
|
||||
|
||||
public static Vector3 ComputeNormalFast( Vector3 a, Vector3 b, Vector3 c )
|
||||
{
|
||||
return Math3D.Cross( c - b , a - b ).Normalized();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Vector3 ComputeNormal( Vector3 a, Vector3 b, Vector3 c )
|
||||
{
|
||||
var cross = Math3D.Cross( c - b , a - b );
|
||||
|
@ -440,7 +460,12 @@ namespace Rokojori
|
|||
|
||||
public static float GlobalYaw( Vector3 direction )
|
||||
{
|
||||
return Mathf.Atan2( direction.Z, direction.X );
|
||||
return ( Mathf.Pi * 2.0f - Mathf.Atan2( direction.Z, direction.X ) ) - Mathf.Pi / 2.0f;
|
||||
}
|
||||
|
||||
public static float GlobalYawDegrees( Vector3 direction )
|
||||
{
|
||||
return Mathf.RadToDeg( GlobalYaw( direction ) );
|
||||
}
|
||||
|
||||
public static float GlobalPitch( Vector3 direction )
|
||||
|
@ -451,6 +476,11 @@ namespace Rokojori
|
|||
return Mathf.Atan2( y, xz );
|
||||
}
|
||||
|
||||
public static float GlobalPitchDegrees( Vector3 direction )
|
||||
{
|
||||
return Mathf.RadToDeg( GlobalPitch( direction ) );
|
||||
}
|
||||
|
||||
public static void SetGlobalQuaternion( this Node3D node, Quaternion quaternion )
|
||||
{
|
||||
var localScale = node.Scale;
|
||||
|
@ -620,6 +650,38 @@ namespace Rokojori
|
|||
node.GlobalPosition = gp;
|
||||
}
|
||||
|
||||
public static void SetLocalX( this Node3D node, float x )
|
||||
{
|
||||
var gp = node.Position;
|
||||
|
||||
gp.X = x;
|
||||
|
||||
node.Position = gp;
|
||||
}
|
||||
|
||||
public static void SetLocalY( this Node3D node, float y )
|
||||
{
|
||||
var gp = node.Position;
|
||||
|
||||
gp.Y = y;
|
||||
|
||||
node.Position = gp;
|
||||
}
|
||||
|
||||
public static void SetLocalZ( this Node3D node, float z )
|
||||
{
|
||||
var gp = node.Position;
|
||||
|
||||
gp.Z = z;
|
||||
|
||||
node.Position = gp;
|
||||
}
|
||||
|
||||
public static Vector3 GetOrientationBasedGlobalOffset( this Node3D node, Vector3 offset )
|
||||
{
|
||||
return offset.X * node.GlobalRight() + offset.Y * node.GlobalUp() + offset.Z * node.GlobalForward();
|
||||
}
|
||||
|
||||
public static Vector3 Average( List<Vector3> vectors )
|
||||
{
|
||||
var average = Vector3.Zero;
|
||||
|
|
|
@ -96,6 +96,21 @@ namespace Rokojori
|
|||
return Mathf.Abs( AngleDelta( degreesA, degreesB ) );
|
||||
}
|
||||
|
||||
public static float NormalizeAngle( float degrees )
|
||||
{
|
||||
while ( degrees > 180 )
|
||||
{
|
||||
degrees -= 360;
|
||||
}
|
||||
|
||||
while ( degrees < -180 )
|
||||
{
|
||||
degrees += 360;
|
||||
}
|
||||
|
||||
return degrees;
|
||||
}
|
||||
|
||||
public static float Smoothstep ( float edge0, float edge1, float x )
|
||||
{
|
||||
x = MathX.Clamp01( ( x - edge0 ) / ( edge1 - edge0 ) );
|
||||
|
@ -118,6 +133,17 @@ namespace Rokojori
|
|||
return Mathf.Floor( value / snappingDistance ) * snappingDistance;
|
||||
}
|
||||
|
||||
public static Vector2 RadiansToVector2( float angle )
|
||||
{
|
||||
return new Vector2( Mathf.Cos( angle ), Mathf.Sin( angle ) );
|
||||
}
|
||||
|
||||
public static float Vector2ToRadians( Vector2 circle )
|
||||
{
|
||||
return Mathf.Atan2( circle.Y, circle.X );
|
||||
}
|
||||
|
||||
|
||||
public const float DegreesToRadians = Mathf.Pi / 180f;
|
||||
public const float RadiansToDegrees = 180f / Mathf.Pi;
|
||||
|
||||
|
|
|
@ -27,23 +27,9 @@ namespace Rokojori
|
|||
[Export]
|
||||
public MeshInstance3D output;
|
||||
|
||||
[Export]
|
||||
public bool update = false;
|
||||
|
||||
[Export]
|
||||
public bool updateAlways = false;
|
||||
|
||||
public override void _Process( double delta )
|
||||
{
|
||||
if ( ! ( update || updateAlways ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
update = false;
|
||||
|
||||
Create();
|
||||
}
|
||||
[ExportToolButton( "Update")]
|
||||
public Callable UpdateButton => Callable.From( () => Create() );
|
||||
|
||||
|
||||
public float X()
|
||||
|
@ -148,6 +134,11 @@ namespace Rokojori
|
|||
|
||||
mg.AddQuad( 20, 21, 22, 23, true );
|
||||
|
||||
if ( output == null )
|
||||
{
|
||||
output = this.CreateChild<MeshInstance3D>();
|
||||
}
|
||||
|
||||
output.Mesh = mg.GenerateMesh();
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
[gd_resource type="Resource" script_class="GamePadAxisSensor" load_steps=2 format=3 uid="uid://dbha8dmhxgm05"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Sensors/GamePadAxisSensor.cs" id="1_yy4wi"]
|
||||
[ext_resource type="Script" uid="uid://cb81s7ud1de7h" path="res://addons/rokojori_action_library/Runtime/Sensors/GamePadAxisSensor.cs" id="1_yy4wi"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_yy4wi")
|
||||
axis = 0
|
||||
axis = 1
|
||||
type = 1
|
||||
continous = true
|
||||
_value = 0.0
|
|
@ -0,0 +1,9 @@
|
|||
[gd_resource type="Resource" script_class="GamePadAxisSensor" load_steps=2 format=3 uid="uid://ck7woerh7mhp"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://cb81s7ud1de7h" path="res://addons/rokojori_action_library/Runtime/Sensors/GamePadAxisSensor.cs" id="1_nrdau"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_nrdau")
|
||||
axis = 3
|
||||
type = 1
|
||||
continous = true
|
|
@ -1,13 +0,0 @@
|
|||
[gd_resource type="Resource" script_class="GamePadAxisSensor" load_steps=2 format=3 uid="uid://ck7woerh7mhp"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Sensors/GamePadAxisSensor.cs" id="1_nrdau"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_nrdau")
|
||||
axis = 3
|
||||
type = 1
|
||||
continous = true
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
|
@ -1,12 +1,8 @@
|
|||
[gd_resource type="Resource" script_class="GamePadButtonSensor" load_steps=2 format=3 uid="uid://jvwwq6guhl77"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Sensors/GamePadButtonSensor.cs" id="1_4da72"]
|
||||
[ext_resource type="Script" uid="uid://0ji11kv86cpk" path="res://addons/rokojori_action_library/Runtime/Sensors/GamePadButtonSensor.cs" id="1_4da72"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_4da72")
|
||||
button = 1
|
||||
button = 2
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
[gd_resource type="Resource" script_class="GamePadButtonSensor" load_steps=2 format=3 uid="uid://dpwq5eyla8rob"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Sensors/GamePadButtonSensor.cs" id="1_yv1r0"]
|
||||
[ext_resource type="Script" uid="uid://0ji11kv86cpk" path="res://addons/rokojori_action_library/Runtime/Sensors/GamePadButtonSensor.cs" id="1_yv1r0"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_yv1r0")
|
||||
button = 2
|
||||
button = 3
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
[gd_resource type="Resource" script_class="SensorGroup" load_steps=28 format=3 uid="uid://bv40lrpi3831d"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Sensors/SensorGroup.cs" id="1_k6ypa"]
|
||||
[ext_resource type="Resource" uid="uid://5gnh5dmv1p21" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Left-Joystick X-Negative.tres" id="2_1ywmr"]
|
||||
[ext_resource type="Resource" uid="uid://dsrf03g6mgu5t" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Left-Joystick X-Positive.tres" id="3_1yuu5"]
|
||||
[ext_resource type="Resource" uid="uid://dbha8dmhxgm05" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Left-Joystick Y-Negative.tres" id="4_ehig4"]
|
||||
[ext_resource type="Resource" uid="uid://cyyy0ycusgil3" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Left-Joystick Y-Positive.tres" id="5_adyq7"]
|
||||
[ext_resource type="Resource" uid="uid://b16mtcrpm1f6i" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Right-Joystick X-Negative.tres" id="6_g7fxo"]
|
||||
[ext_resource type="Resource" uid="uid://d05w143o644d3" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Right-Joystick X-Positive.tres" id="7_b0v3q"]
|
||||
[ext_resource type="Resource" uid="uid://ck7woerh7mhp" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Right-Joystick Y-Negative.tres" id="8_ljqng"]
|
||||
[ext_resource type="Resource" uid="uid://6emg8n3qxhlv" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Right-Joystick Y-Positive.tres" id="9_qkgw5"]
|
||||
[ext_resource type="Script" uid="uid://da4bhmvkury2" path="res://addons/rokojori_action_library/Runtime/Sensors/SensorGroup.cs" id="1_k6ypa"]
|
||||
[ext_resource type="Resource" uid="uid://5gnh5dmv1p21" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Left-Joystick Left -X.tres" id="2_1ywmr"]
|
||||
[ext_resource type="Resource" uid="uid://dsrf03g6mgu5t" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Left-Joystick Right +X.tres" id="3_1yuu5"]
|
||||
[ext_resource type="Resource" uid="uid://dbha8dmhxgm05" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Left-Joystick Up -Y.tres" id="4_ehig4"]
|
||||
[ext_resource type="Resource" uid="uid://cyyy0ycusgil3" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Left-Joystick Down +Y.tres" id="5_adyq7"]
|
||||
[ext_resource type="Resource" uid="uid://b16mtcrpm1f6i" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Right-Joystick Left -X.tres" id="6_g7fxo"]
|
||||
[ext_resource type="Resource" uid="uid://d05w143o644d3" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Right-Joystick Right +X.tres" id="7_b0v3q"]
|
||||
[ext_resource type="Resource" uid="uid://ck7woerh7mhp" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Right-Joystick Up -Y.tres" id="8_ljqng"]
|
||||
[ext_resource type="Resource" uid="uid://6emg8n3qxhlv" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Right-Joystick Down +Y.tres" id="9_qkgw5"]
|
||||
[ext_resource type="Resource" uid="uid://cs12bjge707ri" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Trigger Left, LT, PS L2, Nin ZL.tres" id="10_t2i3f"]
|
||||
[ext_resource type="Resource" uid="uid://cy3ja8squnin6" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Axis/Trigger Right, RT, PS R2, Nin ZR.tres" id="11_u6ig2"]
|
||||
[ext_resource type="Resource" uid="uid://dffkdky8iowro" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Buttons/Button A, PS Cross, Nin B.tres" id="12_0r6yt"]
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass,Icon("res://addons/rokojori_action_library/Icons/SensorGroup.svg")]
|
||||
public partial class HoldSensor : Sensor
|
||||
{
|
||||
[Export]
|
||||
public Sensor holdButton;
|
||||
|
||||
[Export]
|
||||
public bool negateHoldButton;
|
||||
|
||||
[Export]
|
||||
public Sensor triggerButton;
|
||||
|
||||
protected override void UpdateValue()
|
||||
{
|
||||
if ( holdButton == null || triggerButton == null )
|
||||
{
|
||||
SetFloatValue( 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
var holdButtonValue = holdButton.isActive;
|
||||
|
||||
if ( negateHoldButton )
|
||||
{
|
||||
holdButtonValue = ! holdButtonValue;
|
||||
}
|
||||
|
||||
if ( ! holdButtonValue )
|
||||
{
|
||||
SetFloatValue( 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
SetFloatValue( triggerButton.value );
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return RJLog.GetInfo( this, holdButton, triggerButton );
|
||||
}
|
||||
|
||||
[Export]
|
||||
public InputIcon[] inputIcons = [];
|
||||
|
||||
[Export]
|
||||
public bool useInputIconsFromSensors = true;
|
||||
|
||||
public override List<InputIcon> GetInputIcons()
|
||||
{
|
||||
var list = Lists.From( inputIcons );
|
||||
|
||||
if ( useInputIconsFromSensors )
|
||||
{
|
||||
if ( holdButton != null )
|
||||
{
|
||||
list.AddRange( holdButton.GetInputIcons() );
|
||||
}
|
||||
|
||||
if ( triggerButton != null )
|
||||
{
|
||||
list.AddRange( triggerButton.GetInputIcons() );
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://b3c1sl7uhvqu8
|
|
@ -17,18 +17,13 @@ namespace Rokojori
|
|||
[Export]
|
||||
public bool continous = false;
|
||||
|
||||
[ExportGroup("Read Only")]
|
||||
[Export]
|
||||
public float _value = 0;
|
||||
protected float _value = 0;
|
||||
|
||||
[Export]
|
||||
public bool _wasActive = false;
|
||||
protected bool _wasActive = false;
|
||||
|
||||
[Export]
|
||||
public bool _active = false;
|
||||
protected bool _active = false;
|
||||
|
||||
[Export]
|
||||
public float _activeTreshold = 0.5f;
|
||||
protected float _activeTreshold = 0.5f;
|
||||
|
||||
public void ProcessSensor( SensorRunner runner, float delta )
|
||||
{
|
||||
|
|
|
@ -35,16 +35,22 @@ namespace Rokojori
|
|||
|
||||
[ExportGroup("Read Only")]
|
||||
[Export]
|
||||
public SensorDevice[] deviceList = new SensorDevice[]{};
|
||||
public SensorDevice[] deviceList =[];
|
||||
|
||||
[Export]
|
||||
public float[] deviceLastInputTimeStamp = new float[]{};
|
||||
public float[] deviceLastInputTimeStamp = [];
|
||||
|
||||
[ExportGroup("Testing")]
|
||||
|
||||
[Export]
|
||||
public SensorDevice testingLastActiveDevice;
|
||||
|
||||
[Export]
|
||||
public bool showRegistratedSensors = true;
|
||||
|
||||
[Export]
|
||||
public Sensor[] registratedSensors = [];
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -61,6 +67,12 @@ namespace Rokojori
|
|||
DateTime _startTime;
|
||||
|
||||
|
||||
public bool isMouseKeyboardLastActive => lastActiveDevice == mouseKeyboardDevice ||
|
||||
lastActiveDevice == mouseDevice ||
|
||||
lastActiveDevice == keyboardDevice;
|
||||
|
||||
public bool isControllerLastActive => lastActiveDevice == gamePadDevice;
|
||||
|
||||
public SensorDevice lastActiveDevice
|
||||
{
|
||||
get
|
||||
|
@ -175,8 +187,11 @@ namespace Rokojori
|
|||
runners.ForEach( r => r.Update( (float) delta ) );
|
||||
}
|
||||
|
||||
|
||||
public void Register( Sensor s, SensorInputHandler sih )
|
||||
{
|
||||
this.LogInfo( "Registrating", s );
|
||||
|
||||
var sensorRunner = sensorToRunner[ s ];
|
||||
|
||||
if ( sensorRunner.listeners.Contains( sih ) )
|
||||
|
@ -185,6 +200,8 @@ namespace Rokojori
|
|||
}
|
||||
|
||||
sensorRunner.listeners.Add( sih );
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void Unregister( Sensor s, SensorInputHandler sih )
|
||||
|
@ -197,6 +214,11 @@ namespace Rokojori
|
|||
{
|
||||
var sm = Unique<SensorManager>.Get();
|
||||
|
||||
if ( sm == null )
|
||||
{
|
||||
Nodes.ForEachInScene<Node>( n => n.LogInfo() );
|
||||
}
|
||||
|
||||
foreach ( var s in sensors )
|
||||
{
|
||||
if ( s == null )
|
||||
|
@ -241,6 +263,11 @@ namespace Rokojori
|
|||
|
||||
sensorsSet.Add( s );
|
||||
runners.Add( new SensorRunner( s ) );
|
||||
|
||||
if ( showRegistratedSensors )
|
||||
{
|
||||
registratedSensors = Arrays.Add( registratedSensors, s );
|
||||
}
|
||||
}
|
||||
|
||||
HashSet<object> _scannedObjects = new HashSet<object>();
|
||||
|
@ -257,6 +284,19 @@ namespace Rokojori
|
|||
|
||||
var sensors = ReflectionHelper.GetDataMemberValues<Sensor>( obj );
|
||||
|
||||
if ( sensors.Count > 0 )
|
||||
{
|
||||
if ( obj is Node n )
|
||||
{
|
||||
n.LogInfo( sensors );
|
||||
}
|
||||
else if ( obj is Resource r )
|
||||
{
|
||||
r.LogInfo( sensors );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sensors.ForEach(
|
||||
s =>
|
||||
{
|
||||
|
@ -309,12 +349,12 @@ namespace Rokojori
|
|||
|
||||
foreach ( var n in autoScanForSensors )
|
||||
{
|
||||
Nodes.ForEach<Node>( n, cn=> AddSensorsFrom( cn ) );
|
||||
Nodes.ForEach<Node>( n, AddSensorsFrom );
|
||||
}
|
||||
|
||||
if ( autoScanParent )
|
||||
{
|
||||
Nodes.ForEach<Node>( GetParent(), cn=> AddSensorsFrom( cn ) );
|
||||
Nodes.ForEach<Node>( GetParent(), AddSensorsFrom );
|
||||
}
|
||||
|
||||
runners.ForEach(
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass,Icon("res://addons/rokojori_action_library/Icons/SensorManager.svg")]
|
||||
public partial class SensorViewer: Node
|
||||
{
|
||||
[Export]
|
||||
public Sensor sensor;
|
||||
|
||||
[Export]
|
||||
public float value;
|
||||
|
||||
[Export]
|
||||
public bool active;
|
||||
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if ( sensor == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
value = sensor.value;
|
||||
active = sensor.isActive;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://bodk4mqlebnwi
|
|
@ -34,5 +34,23 @@ namespace Rokojori
|
|||
{
|
||||
return GetValue( negative, -scale, deadZone ) + GetValue( positive, scale, deadZone );
|
||||
}
|
||||
|
||||
public static Vector2 FourDirectional( Sensor left, Sensor right, Sensor up, Sensor down, bool normalize = true, float deadZone = 0.3f )
|
||||
{
|
||||
var x = PolarAxis( left, right, 1, deadZone );
|
||||
var y = PolarAxis( up, down, 1, deadZone );
|
||||
|
||||
|
||||
var v = new Vector2( x, y );
|
||||
|
||||
if ( normalize && v.Length() > 1 )
|
||||
{
|
||||
v = v.Normalized();
|
||||
}
|
||||
|
||||
return v;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,8 @@ namespace Rokojori
|
|||
|
||||
public override void _Ready()
|
||||
{
|
||||
this.LogInfo( "Root" );
|
||||
|
||||
SensorManager.Register( this, sensor );
|
||||
}
|
||||
|
||||
|
|
|
@ -73,3 +73,18 @@ float angleDelta( float degreesA, float degreesB )
|
|||
angleDelta = mod( angleDelta + 180.0, 360.0 ) - 180.0;
|
||||
return angleDelta;
|
||||
}
|
||||
|
||||
float snapRounded( float value, float snappingDistance )
|
||||
{
|
||||
return round( value / snappingDistance ) * snappingDistance;
|
||||
}
|
||||
|
||||
float snapCeiled( float value, float snappingDistance )
|
||||
{
|
||||
return ceil( value / snappingDistance ) * snappingDistance;
|
||||
}
|
||||
|
||||
float snapFloored( float value, float snappingDistance )
|
||||
{
|
||||
return floor( value / snappingDistance ) * snappingDistance;
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
// #include "res://addons/rokojori_action_library/Runtime/Shading/Library/Noise.gdshaderinc"
|
||||
|
||||
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Math.gdshaderinc"
|
||||
|
||||
float random( vec2 uv )
|
||||
{
|
||||
return fract( sin( dot( uv.xy, vec2( 12.9898, 78.233 ) ) ) * 43758.5453123 );
|
||||
|
@ -7,9 +9,16 @@ float random( vec2 uv )
|
|||
|
||||
vec2 random_v2( vec2 uv )
|
||||
{
|
||||
return vec2( fract( sin( dot( uv.xy, vec2( 12.9898,78.233 ) ) ) * 43758.5453123 ) );
|
||||
uv = vec2
|
||||
(
|
||||
dot(uv, vec2( 127.1,311.7 ) ),
|
||||
dot(uv, vec2( 269.5,183.3 ) )
|
||||
);
|
||||
|
||||
return -1.0 + 2.0 * fract( sin( uv ) * 43758.5453123 );
|
||||
}
|
||||
|
||||
|
||||
vec3 random_v3( vec3 uvw )
|
||||
{
|
||||
|
||||
|
@ -20,7 +29,20 @@ vec3 random_v3( vec3 uvw )
|
|||
return -1.0 + 2.0 * fract(sin(uvw) * 43758.5453123);
|
||||
}
|
||||
|
||||
float perlin( vec2 uv )
|
||||
// float perlin( vec2 uv )
|
||||
// {
|
||||
// vec2 uv_index = floor(uv);
|
||||
// vec2 uv_fract = fract(uv);
|
||||
|
||||
// vec2 blur = smoothstep(0.0, 1.0, uv_fract);
|
||||
|
||||
// return mix( mix( dot( random_v2(uv_index + vec2(0.0,0.0) ), uv_fract - vec2(0.0,0.0) ),
|
||||
// dot( random_v2(uv_index + vec2(1.0,0.0) ), uv_fract - vec2(1.0,0.0) ), blur.x),
|
||||
// mix( dot( random_v2(uv_index + vec2(0.0,1.0) ), uv_fract - vec2(0.0,1.0) ),
|
||||
// dot( random_v2(uv_index + vec2(1.0,1.0) ), uv_fract - vec2(1.0,1.0) ), blur.x), blur.y) + 0.5;
|
||||
// }
|
||||
|
||||
float perlin(vec2 uv)
|
||||
{
|
||||
vec2 uv_index = floor(uv);
|
||||
vec2 uv_fract = fract(uv);
|
||||
|
@ -33,6 +55,61 @@ float perlin( vec2 uv )
|
|||
dot( random_v2(uv_index + vec2(1.0,1.0) ), uv_fract - vec2(1.0,1.0) ), blur.x), blur.y) + 0.5;
|
||||
}
|
||||
|
||||
float perlinOctaves( vec2 uv, int octaves, float scale, float gain )
|
||||
{
|
||||
float s = 1.0;
|
||||
float g = 1.0;
|
||||
|
||||
float v = perlin( uv * s ) * g;
|
||||
float n = 1.0;
|
||||
|
||||
for ( int i = 0; i < octaves; i++ )
|
||||
{
|
||||
s *= scale;
|
||||
g *= gain;
|
||||
|
||||
v += perlin( uv * s ) * g;
|
||||
n += g;
|
||||
}
|
||||
|
||||
return v / n;
|
||||
}
|
||||
|
||||
vec2 seamLessCoordinate( vec2 uv, vec2 seamRange, vec2 seamFade, vec2 type )
|
||||
{
|
||||
return mod( uv - seamFade * type, seamRange );
|
||||
}
|
||||
|
||||
float perlinOctavesSeamless( vec2 uv, int octaves, float scale, float gain, vec2 seamRange, vec2 seamFade )
|
||||
{
|
||||
// uv = mod( uv , seamRange );
|
||||
seamFade *= seamRange;
|
||||
vec2 fading = mod( uv, seamRange ) ;
|
||||
fading.x = normalizeToRange01( fading.x, seamRange.x - seamFade.x, seamRange.x );
|
||||
fading.y = normalizeToRange01( fading.y, seamRange.y - seamFade.y, seamRange.y );
|
||||
|
||||
|
||||
// 0, seamRange - seamFade, seamRange
|
||||
//
|
||||
|
||||
vec2 p00 = seamLessCoordinate( uv, seamRange, seamFade, vec2( 0.0, 0.0 ) );
|
||||
vec2 p10 = seamLessCoordinate( uv, seamRange, seamFade, vec2( 1.0, 0.0 ) );
|
||||
vec2 p01 = seamLessCoordinate( uv, seamRange, seamFade, vec2( 0.0, 1.0 ) );
|
||||
vec2 p11 = seamLessCoordinate( uv, seamRange, seamFade, vec2( 1.0, 1.0 ) );
|
||||
|
||||
float n00 = perlinOctaves( p00, octaves, scale, gain );
|
||||
float n10 = perlinOctaves( p10, octaves, scale, gain );
|
||||
float n01 = perlinOctaves( p01, octaves, scale, gain );
|
||||
float n11 = perlinOctaves( p11, octaves, scale, gain );
|
||||
|
||||
float n0 = mix( n00, n10, fading.x );
|
||||
float n1 = mix( n01, n11, fading.x );
|
||||
|
||||
return mix( n0, n1, fading.y );
|
||||
}
|
||||
|
||||
|
||||
|
||||
float perlin3D( vec3 uvw )
|
||||
{
|
||||
vec3 gridIndex = floor( uvw );
|
||||
|
|
|
@ -48,6 +48,7 @@ namespace Rokojori
|
|||
high = tweened;
|
||||
}
|
||||
|
||||
|
||||
if ( validateLimits != null && ! validateLimits( low, high ) )
|
||||
{
|
||||
throw new Exception( "Limit validation failed" );
|
||||
|
|
|
@ -39,6 +39,20 @@ namespace Rokojori
|
|||
return last;
|
||||
}
|
||||
|
||||
public static async Task<double> WaitIfExceeded( double last, Node node, double waitTime = Async.waitTime )
|
||||
{
|
||||
var now = Time.GetTicksMsec() / 1000.0;
|
||||
|
||||
if ( ( now - last ) > waitTime )
|
||||
{
|
||||
await node.RequestNextFrame();
|
||||
|
||||
return Time.GetTicksMsec() / 1000.0;;
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
public static double DoIfExceeded( double last, System.Action action, double waitTime = Async.waitTime )
|
||||
{
|
||||
var now = Time.GetTicksMsec() / 1000.0;
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace Rokojori
|
|||
{
|
||||
public class Safe
|
||||
{
|
||||
static readonly int maxWhileIterations = 2000 * 1000;
|
||||
static readonly int maxWhileIterations = 1000 * 1000;
|
||||
|
||||
public static void While( Func<bool> condition, System.Action action, System.Action onTooManyIterations = null )
|
||||
{
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using Godot;
|
||||
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class CameraTargetOffset:Node3D
|
||||
{
|
||||
[Export]
|
||||
public float cameraTargetMinOffsetZ = 0;
|
||||
|
||||
[Export]
|
||||
public float cameraTargetMaxOffsetZ = 10;
|
||||
|
||||
[Export]
|
||||
public Smoothing cameraTargetOffsetZSmoothing = new FrameSmoothing();
|
||||
|
||||
|
||||
[Export]
|
||||
public float cameraTargetMinOffsetY = 1.7f;
|
||||
|
||||
[Export]
|
||||
public float cameraTargetMaxOffsetY = 2f;
|
||||
|
||||
[Export]
|
||||
public Smoothing cameraTargetOffsetYSmoothing = new FrameSmoothing();
|
||||
|
||||
protected float nextZ = 0;
|
||||
protected float nextY = 0;
|
||||
|
||||
public virtual void SetMovingForward( float movingForward )
|
||||
{
|
||||
nextZ = Mathf.Lerp( cameraTargetMinOffsetZ, cameraTargetMaxOffsetZ, movingForward );
|
||||
nextY = Mathf.Lerp( cameraTargetMinOffsetY, cameraTargetMaxOffsetY, movingForward );
|
||||
}
|
||||
|
||||
public override void _Process( double delta )
|
||||
{
|
||||
var smoothedOffsetZ = cameraTargetOffsetZSmoothing.Smooth( nextZ, (float)delta );
|
||||
this.SetLocalZ( smoothedOffsetZ );
|
||||
|
||||
|
||||
var smoothedOffsetY = cameraTargetOffsetYSmoothing.Smooth( nextY, (float)delta );
|
||||
this.SetLocalY( smoothedOffsetY );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://bk5eoi53m08jh
|
|
@ -15,6 +15,9 @@ namespace Rokojori
|
|||
[Export]
|
||||
public Node3D target;
|
||||
|
||||
[Export]
|
||||
public Smoothing targetFollowSmoothing = new FrameSmoothing();
|
||||
|
||||
[ExportGroup("Yaw")]
|
||||
|
||||
[Export]
|
||||
|
@ -26,14 +29,39 @@ namespace Rokojori
|
|||
[Export]
|
||||
public Sensor yawNegativeAxis;
|
||||
|
||||
[Export]
|
||||
public bool roundYaw = false;
|
||||
|
||||
[Export]
|
||||
public int roundedYawResolution = 64;
|
||||
|
||||
[Export]
|
||||
public float yaw = 0;
|
||||
|
||||
[Export]
|
||||
public float yawSmoothingDuration = 0.1f;
|
||||
public Smoothing yawSmoothing = new FrameSmoothing();
|
||||
|
||||
[Export]
|
||||
public bool yawGoesBehindPlayer = true;
|
||||
|
||||
[Export]
|
||||
public Smoothing yawToBehingSmoothing = new FrameSmoothing();
|
||||
|
||||
[Export]
|
||||
public float yawBehindDelayDuration = 5;
|
||||
|
||||
[Export]
|
||||
public float yawGoesBehindActivation = 0.1f;
|
||||
|
||||
[Export]
|
||||
public float behindYaw = 0;
|
||||
|
||||
[Export]
|
||||
public float currentYaw = 0;
|
||||
|
||||
[Export]
|
||||
public float bcDelta = 0;
|
||||
|
||||
Smoother yawSmoother = new Smoother();
|
||||
|
||||
[ExportGroup("Pitch")]
|
||||
|
||||
|
@ -58,27 +86,44 @@ namespace Rokojori
|
|||
[Export]
|
||||
public float maxPitch = 80;
|
||||
|
||||
public float normalizedPitch => MathX.NormalizeClamped( pitch, minPitch, maxPitch );
|
||||
|
||||
[Export]
|
||||
public float pitchSmoothingDuration = 0.1f;
|
||||
public Smoothing pitchSmoothing = new FrameSmoothing();
|
||||
|
||||
Smoother pitchSmoother = new Smoother();
|
||||
[Export]
|
||||
public bool pitchGoesBackToCenter = true;
|
||||
|
||||
[Export]
|
||||
public Smoothing toCenterPitchSmoothing = new FrameSmoothing();
|
||||
|
||||
[Export]
|
||||
public float centerPitchDelayDuration = 5;
|
||||
|
||||
[Export]
|
||||
public float centerPitch = 30;
|
||||
|
||||
[Export]
|
||||
public float centerPitchActivation = 0.1f;
|
||||
|
||||
[ExportGroup("Distance")]
|
||||
[Export]
|
||||
public Curve distanceForPitch = MathX.Curve( 1, 1 );
|
||||
|
||||
[Export]
|
||||
public float distanceScale = 1;
|
||||
|
||||
[ExportGroup("Offset")]
|
||||
[ExportGroup("Camera Offset")]
|
||||
[Export]
|
||||
public Vector3 offset;
|
||||
|
||||
Smoother distanceSmoother = new Smoother();
|
||||
|
||||
float smoothedYaw = 0;
|
||||
float smoothedPitch = 0;
|
||||
float smoothedDistance = 0;
|
||||
|
||||
float _centerPitchActivation = 0;
|
||||
float _yawBehindActivation = 0;
|
||||
|
||||
public override void _Process( double delta )
|
||||
{
|
||||
|
@ -87,17 +132,60 @@ namespace Rokojori
|
|||
return;
|
||||
}
|
||||
|
||||
behindYaw = Math3D.GlobalYawDegrees( target.GlobalForward() * -1 );
|
||||
behindYaw = MathX.NormalizeAngle( behindYaw );
|
||||
|
||||
currentYaw = MathX.NormalizeAngle( yaw );
|
||||
|
||||
bcDelta = MathX.NormalizeAngle( MathX.AngleDelta( behindYaw, currentYaw ) );
|
||||
|
||||
var targetPosition = Smoothing.Apply( targetFollowSmoothing, target.GlobalPosition, (float) delta );
|
||||
|
||||
|
||||
var yawAxis = Sensors.PolarAxis( yawNegativeAxis, yawPositiveAxis );
|
||||
var pitchAxis = Sensors.PolarAxis( pitchNegativeAxis, pitchPositiveAxis );
|
||||
|
||||
|
||||
yaw += yawAxis * yawSpeed * (float)delta;
|
||||
|
||||
if ( yawGoesBehindPlayer )
|
||||
{
|
||||
if ( Mathf.Abs( yawAxis ) < yawGoesBehindActivation )
|
||||
{
|
||||
_yawBehindActivation += (float)delta;
|
||||
|
||||
if ( yawGoesBehindPlayer && _yawBehindActivation > yawBehindDelayDuration )
|
||||
{
|
||||
yaw = Smoothing.ApplyDegreesWith( yawToBehingSmoothing, yaw, behindYaw, (float) delta );
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
_yawBehindActivation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// yaw = MathX.Repeat( yaw, 360f );
|
||||
|
||||
if ( pitchIsRelative )
|
||||
{
|
||||
pitch += pitchAxis * pitchSpeed * (float)delta;
|
||||
pitch = Mathf.Clamp( pitch, minPitch, maxPitch );
|
||||
|
||||
if ( Mathf.Abs( pitchAxis ) < centerPitchActivation )
|
||||
{
|
||||
_centerPitchActivation += (float)delta;
|
||||
|
||||
if ( _centerPitchActivation > centerPitchDelayDuration )
|
||||
{
|
||||
pitch = Smoothing.ApplyWith( toCenterPitchSmoothing, pitch, centerPitch, (float) delta );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_centerPitchActivation = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -105,20 +193,36 @@ namespace Rokojori
|
|||
}
|
||||
|
||||
|
||||
if ( Mathf.Abs( yaw - smoothedYaw ) > 180 )
|
||||
{
|
||||
if ( yaw > smoothedYaw )
|
||||
{
|
||||
smoothedYaw += 360;
|
||||
}
|
||||
else if ( yaw < smoothedYaw )
|
||||
{
|
||||
smoothedYaw -= 360;
|
||||
}
|
||||
}
|
||||
|
||||
smoothedYaw = yaw;
|
||||
smoothedPitch = pitchSmoother.SmoothForDuration( smoothedPitch, pitch, pitchSmoothingDuration, (float) delta );
|
||||
// if ( Mathf.Abs( yaw - smoothedYaw ) > 180 )
|
||||
// {
|
||||
// if ( yaw > smoothedYaw )
|
||||
// {
|
||||
// smoothedYaw += 360;
|
||||
// }
|
||||
// else if ( yaw < smoothedYaw )
|
||||
// {
|
||||
// smoothedYaw -= 360;
|
||||
// }
|
||||
// }
|
||||
|
||||
var appliedYaw = yaw;
|
||||
|
||||
// if ( roundYaw )
|
||||
// {
|
||||
// appliedYaw = MathX.SnapRounded( yaw, 360f/roundedYawResolution );
|
||||
// }
|
||||
|
||||
smoothedYaw = Smoothing.ApplyDegrees( yawSmoothing, appliedYaw, (float) delta );
|
||||
|
||||
|
||||
smoothedPitch = Smoothing.Apply( pitchSmoothing, pitch, (float) delta );
|
||||
|
||||
// if ( pitchGoesBackToCenter )
|
||||
// {
|
||||
// pitch = toCenterPitchSmoothing.Smooth( centerPitch, (float) delta );
|
||||
// }
|
||||
|
||||
|
||||
// RJLog.Log( "Pitch", smoothedPitch );
|
||||
|
||||
|
@ -126,11 +230,11 @@ namespace Rokojori
|
|||
// smoothedPitch = pitch;
|
||||
var distance = distanceForPitch.Sample( MathX.NormalizeClamped( pitch, minPitch, maxPitch ) ) * distanceScale;
|
||||
|
||||
GlobalPosition = target.GlobalPosition + Math3D.YawPitchRotation( smoothedYaw, smoothedPitch ) * Vector3.Forward * distance + offset;
|
||||
|
||||
LookAt( target.GlobalPosition + offset, Vector3.Up, true );
|
||||
GlobalPosition = targetPosition + Math3D.YawPitchRotation( smoothedYaw, smoothedPitch ) * Vector3.Forward * distance;
|
||||
|
||||
LookAt( targetPosition, Vector3.Up, true );
|
||||
|
||||
GlobalPosition += this.GetOrientationBasedGlobalOffset( offset );
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using Godot;
|
||||
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class ThirdPersonCameraTargetOffset:CameraTargetOffset
|
||||
{
|
||||
|
||||
[Export]
|
||||
public ThirdPersonCamera thirdPersonCamera;
|
||||
|
||||
[Export]
|
||||
public Curve pitchMultiply;
|
||||
|
||||
|
||||
public override void SetMovingForward( float movingForward )
|
||||
{
|
||||
if ( pitchMultiply != null && thirdPersonCamera != null )
|
||||
{
|
||||
var normalizedPitch = thirdPersonCamera.normalizedPitch;
|
||||
var sampledPitchMultiply = pitchMultiply.Sample( normalizedPitch );
|
||||
movingForward *= sampledPitchMultiply;
|
||||
}
|
||||
|
||||
|
||||
|
||||
nextZ = Mathf.Lerp( cameraTargetMinOffsetZ, cameraTargetMaxOffsetZ, movingForward );
|
||||
nextY = Mathf.Lerp( cameraTargetMinOffsetY, cameraTargetMaxOffsetY, movingForward );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://s7mi8hpmma3e
|
|
@ -21,6 +21,7 @@ namespace Rokojori
|
|||
[Export]
|
||||
public bool active = false;
|
||||
|
||||
|
||||
public static VirtualCamera3DManager Get()
|
||||
{
|
||||
return Unique<VirtualCamera3DManager>.Get();
|
||||
|
|
Loading…
Reference in New Issue