rj-action-library/Runtime/VirtualCameras/ThirdPersonCamera.cs

243 lines
5.4 KiB
C#

using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System;
using Godot;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class ThirdPersonCamera:VirtualCamera3D
{
[Export]
public Node3D target;
[Export]
public Smoothing targetFollowSmoothing = new FrameSmoothing();
[ExportGroup("Yaw")]
[Export]
public float yawSpeed;
[Export]
public Sensor yawPositiveAxis;
[Export]
public Sensor yawNegativeAxis;
[Export]
public bool roundYaw = false;
[Export]
public int roundedYawResolution = 64;
[Export]
public float yaw = 0;
[Export]
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;
[ExportGroup("Pitch")]
[Export]
public float pitchSpeed;
[Export]
public Sensor pitchPositiveAxis;
[Export]
public Sensor pitchNegativeAxis;
[Export]
public bool pitchIsRelative = false;
[Export]
public float pitch = 0;
[Export]
public float minPitch = -10;
[Export]
public float maxPitch = 80;
public float normalizedPitch => MathX.NormalizeClamped( pitch, minPitch, maxPitch );
[Export]
public Smoothing pitchSmoothing = new FrameSmoothing();
[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("Camera Offset")]
[Export]
public Vector3 offset;
float smoothedYaw = 0;
float smoothedPitch = 0;
float smoothedDistance = 0;
float _centerPitchActivation = 0;
float _yawBehindActivation = 0;
public override void _Process( double delta )
{
if ( target == null )
{
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
{
pitch = Mathf.Remap( pitchAxis, -1, 1, minPitch, maxPitch );
}
// 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 );
// smoothedYaw = yaw;
// smoothedPitch = pitch;
var distance = distanceForPitch.Sample( MathX.NormalizeClamped( pitch, minPitch, maxPitch ) ) * distanceScale;
GlobalPosition = targetPosition + Math3D.YawPitchRotation( smoothedYaw, smoothedPitch ) * Vector3.Forward * distance;
LookAt( targetPosition, Vector3.Up, true );
GlobalPosition += this.GetOrientationBasedGlobalOffset( offset );
}
}
}