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

159 lines
3.6 KiB
C#

using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System;
using Godot;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class VirtualCamera3DManager:RJVirtualCamera3DManager
{
[Export]
public Camera3D camera;
[Export]
public bool refreshSlots = false;
[Export]
public bool active = false;
public override void _Process( double delta )
{
if ( ! active )
{
return;
}
LerpCameras( delta );
}
public float smoothStepDelta => 1f / CameraPrioritySmoothingStepFPS;
public float safeSmoothing => Mathf.Max( 0, CameraPrioritySmoothingCoefficient );
List<VirtualCamera3DSlot> _cameraSlots = new List<VirtualCamera3DSlot>();
public void SetActiveSlot( VirtualCamera3DSlot slot )
{
_cameraSlots.ForEach( c => c.priority = c == slot ? 1 : 0 );
}
void LerpCameras( double delta )
{
if ( refreshSlots || _cameraSlots == null || _cameraSlots.Count == 0 )
{
refreshSlots = false;
_cameraSlots = Nodes.GetDirectChildren<VirtualCamera3DSlot>( this );
//RJLog.Log( "GRABBED SLOTs" , _cameraSlots.Count );
}
var sumPriority = 0f;
_cameraSlots.ForEach(
c =>
{
c.Update( delta, this );
sumPriority += MathF.Max( 0, c.smoothedPriority );
}
);
if ( sumPriority == 0 )
{
return;
}
var position = new Vector3();
var up = new Vector3();
var forward = new Vector3();
var fov = 0f;
_cameraSlots.ForEach(
c =>
{
var priority = MathF.Max( 0, c.smoothedPriority );
var rotation = c.camera.GetCameraRotation();
if ( ! rotation.IsFinite() || rotation.Length() == 0 )
{
rotation = new Quaternion();
rotation.X = 0;
rotation.Y = 0;
rotation.Z = 0;
rotation.W = 1;
rotation = rotation.Normalized();
//RJLog.Log( "Rotation was weird" );
}
else
{
//RJLog.Log( "Rotation is fine" );
}
//RJLog.Log( rotation.X, rotation.Y, rotation.Z, rotation.W );
var vUp = rotation * Vector3.Up;
var vForward = rotation * Vector3.Forward;
position += priority * c.camera.GetCameraPosition();
up += priority * vUp;
forward += priority * vForward;
fov += priority * c.camera.GetCameraFOV();
}
);
position /= sumPriority;
fov /= sumPriority;
if ( forward.LengthSquared() == 0 )
{
forward = camera.Basis.Z;
}
else
{
forward = forward.Normalized();
}
if ( up.LengthSquared() == 0 )
{
up = camera.Basis.Y;
}
else
{
up = up.Normalized();
}
camera.GlobalPosition = position;
camera.LookAt( position - forward, up );
camera.Fov = fov;
}
public override RJVirtualCamera3D GetCamera( int index )
{
return _cameraSlots[ index ].camera;
}
public override int GetCameraIndex( RJVirtualCamera3D camera3D )
{
return _cameraSlots.FindIndex( c => c.camera == camera3D );
}
public override float GetCameraPriority( int index )
{
return _cameraSlots[ index ].priority;
}
public override void SetCameraPriority( int index, float priority )
{
_cameraSlots[ index ].priority = priority;
}
}
}