281 lines
6.5 KiB
C#
281 lines
6.5 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
|
|
{
|
|
public enum ConstrainMode
|
|
{
|
|
Unconstrained,
|
|
Axis_Aligned_Box,
|
|
Circle_XZ_Range_Y
|
|
}
|
|
|
|
[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 ConstrainMode constrainMode = ConstrainMode.Unconstrained;
|
|
|
|
[Export]
|
|
public Node3D constrainMin;
|
|
|
|
[Export]
|
|
public Node3D constrainMax;
|
|
|
|
|
|
|
|
[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 );
|
|
|
|
ConstrainTarget();
|
|
|
|
}
|
|
|
|
void ConstrainTarget()
|
|
{
|
|
if ( ConstrainMode.Unconstrained == constrainMode )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( ConstrainMode.Axis_Aligned_Box == constrainMode )
|
|
{
|
|
target = Box3.Constrain( target, constrainMin.GlobalPosition, constrainMax.GlobalPosition );
|
|
return;
|
|
}
|
|
|
|
if ( ConstrainMode.Circle_XZ_Range_Y == constrainMode )
|
|
{
|
|
var direction = ( constrainMax.GlobalPosition - constrainMin.GlobalPosition );
|
|
var directionXZ = direction; directionXZ.Y = 0;
|
|
var distanceXZ = directionXZ.Length();
|
|
|
|
var targetDirection = target - constrainMin.GlobalPosition;
|
|
var targetDirectionXZ = targetDirection; targetDirectionXZ.Y = 0;
|
|
|
|
target.Y = Mathf.Clamp( target.Y, constrainMin.GlobalPosition.Y, constrainMax.GlobalPosition.Y );
|
|
|
|
if ( targetDirectionXZ.Length() > distanceXZ )
|
|
{
|
|
targetDirectionXZ = targetDirectionXZ.Normalized() * distanceXZ;
|
|
var constrainedPosition = constrainMin.GlobalPosition + targetDirectionXZ;
|
|
target = new Vector3( constrainedPosition.X, target.Y, constrainedPosition.Z );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
} |