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

226 lines
5.0 KiB
C#

using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System;
using Godot;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class StrategyTopDownCamera:VirtualCamera3D
{
[Export]
public Vector3 target;
[Export]
public float yaw = 0;
[Export]
public float pitch = 0;
[Export]
public float distance = 10;
float smoothDistance = 10;
[ExportCategory("Move")]
[Export]
public RJSensor moveUpButton;
[Export]
public RJSensor moveDownButton;
[Export]
public RJSensor moveRightButton;
[Export]
public RJSensor moveLeftButton;
[Export]
public float buttonMoveSpeed = 1f;
[Export]
public RJSensor mouseMoveButton;
[Export]
public float mouseMoveSpeed = 0.001f;
[Export]
public bool flipHorizontal = false;
[Export]
public bool flipVertical = false;
[Export]
public bool moveAtBorders = true;
[Export]
public float moveAtBorderSpeed = 0.001f;
[Export]
public float borderSizePercentage = 5;
[ExportCategory("Orbit")]
[Export]
public RJSensor orbitRightButton;
[Export]
public RJSensor orbitLeftButton;
[Export]
public RJSensor orbitMouseButton;
[Export]
public float mouseOrbitSpeedScale = -0.5f;
[Export]
public float orbitSpeed = 0.001f;
[ExportCategory("Zoom")]
[Export]
public float zoomStepInPercentage = 10;
[Export]
public float minDistance = 0.001f;
[Export]
public float maxDistance = 200f;
[Export]
public RJSensor zoomInButton;
[Export]
public RJSensor[] zoomInModifierButtons;
[Export]
public RJSensor zoomOutButton;
[Export]
public RJSensor[] zoomOutModifierButtons;
[Export]
public float zoomSmoothingCoefficient = 0.1f;
Smoother smoother = new Smoother();
public override void _Process( double delta )
{
Move();
Orbit( (float) delta );
Zoom();
Apply( (float) delta );
if ( ! hasMotionDelta )
{
motionDelta.X = 0;
motionDelta.Y = 0;
}
hasMotionDelta = false;
}
bool hasMotionDelta = false;
Vector2 motionDelta = Vector2.Zero;
float borderMoveHorizontal = 0;
float borderMoveVertical = 0;
float GetBorderSize()
{
var size = GetViewport().GetVisibleRect().Size;
var borderX = ( size.X * borderSizePercentage ) / 100f;
var borderY = ( size.Y * borderSizePercentage ) / 100f;
return Mathf.Min( borderX, borderY );
}
public override void _Input( InputEvent inputEvent )
{
if ( inputEvent is InputEventMouseMotion )
{
var eventMouseMotion = inputEvent as InputEventMouseMotion;
motionDelta = eventMouseMotion.ScreenRelative;
if ( moveAtBorders )
{
var position = eventMouseMotion.Position;
var screenSize = GetViewport().GetVisibleRect().Size;
var borderSize = GetBorderSize();
borderMoveHorizontal = - MathX.PolarAxis( position.X < borderSize, position.X > screenSize.X - borderSize );
borderMoveVertical = - MathX.PolarAxis( position.Y < borderSize, position.Y > screenSize.Y - borderSize );
}
hasMotionDelta = true;
}
}
void Move()
{
var deltaX = 0f;
var deltaY = 0f;
if ( Sensors.IsActive( mouseMoveButton ) )
{
deltaX = motionDelta.X * mouseMoveSpeed;
deltaY = motionDelta.Y * mouseMoveSpeed;
}
else
{
deltaX = Sensors.PolarAxis( moveLeftButton, moveRightButton ) + borderMoveHorizontal * moveAtBorderSpeed;
deltaY = Sensors.PolarAxis( moveUpButton, moveDownButton ) + borderMoveVertical * moveAtBorderSpeed;
}
var forward = Math3D.GetYPlaneForward( this );
var right = Math3D.GetYPlaneRight( this );
var flipH = flipHorizontal ? -1 : 1;
var flipV = flipVertical ? -1 : 1;
var xAmount = deltaX * smoothDistance * right * flipH;
var zAmount = deltaY * smoothDistance * forward * flipV;
target += ( xAmount + zAmount );
}
void Orbit( float delta )
{
var direction = Sensors.PolarAxis( orbitLeftButton, orbitRightButton );
if ( Sensors.IsActive( orbitMouseButton ) )
{
yaw += motionDelta.X * mouseOrbitSpeedScale;
}
yaw += direction * orbitSpeed * delta;
}
void Zoom()
{
var zoomButtonAxis = Sensors.PolarAxis( zoomOutButton, zoomInButton );
distance *= Mathf.Pow( 1 + zoomStepInPercentage / 100f, zoomButtonAxis );
distance = Mathf.Clamp( distance, minDistance, maxDistance );
}
void Apply( float delta )
{
smoothDistance = smoother.SmoothWithCoefficient( smoothDistance, distance, zoomSmoothingCoefficient, delta );
GlobalRotation = new Vector3( Mathf.DegToRad( pitch ), Mathf.DegToRad( yaw ), 0 );
var forward = Math3D.GetGlobalForward( this ) * smoothDistance;
GlobalPosition = target - forward;
}
}
}