From 52b46024cc1983362f07375f3fdc7e35dea389ec Mon Sep 17 00:00:00 2001 From: Josef Date: Mon, 5 Aug 2024 09:14:00 +0200 Subject: [PATCH] Constrains On StrategyTopDownCamera --- Runtime/Godot/Nodes.cs | 32 +++++++ Runtime/Math/Geometry/Box3.cs | 87 +++++++++++++++++++ Runtime/Tools/Arrays.cs | 15 ++++ .../VirtualCameras/StrategyTopDownCamera.cs | 55 ++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 Runtime/Math/Geometry/Box3.cs diff --git a/Runtime/Godot/Nodes.cs b/Runtime/Godot/Nodes.cs index db2caed..ac8db9e 100644 --- a/Runtime/Godot/Nodes.cs +++ b/Runtime/Godot/Nodes.cs @@ -75,6 +75,38 @@ namespace Rokojori ForEach( root, callback ); } + public static List AllInScene( Func filter = null) where T:class + { + var list = new List(); + ForEachInScene( + t => + { + if ( filter == null || filter( t ) ) + { + list.Add( t ); + } + } + ); + + return list; + } + + public static List AllIn( Node root, Func filter = null) where T:class + { + var list = new List(); + ForEach( root, + t => + { + if ( filter == null || filter( t ) ) + { + list.Add( t ); + } + } + ); + + return list; + } + public static void ForEach( Node root, Action callback ) where T:class { var walker = nodesWalker; diff --git a/Runtime/Math/Geometry/Box3.cs b/Runtime/Math/Geometry/Box3.cs new file mode 100644 index 0000000..eb24af5 --- /dev/null +++ b/Runtime/Math/Geometry/Box3.cs @@ -0,0 +1,87 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; + +namespace Rokojori +{ + public class Box3 + { + public Vector3 min = Vector3.Zero; + public Vector3 max = Vector3.Zero; + + public static Box3 FromPositionAndScale( Vector3 position, Vector3 scale ) + { + var max = scale * 0.5f; + var min = -max; + + return Box3.Create( min + position, max + position ); + } + + public static Box3 Create( Vector3 min, Vector3 max ) + { + var b = new Box3(); + b.min = min; + b.max = max; + + return b; + } + + public Vector3 Constrain( Vector3 point ) + { + point = min.Max( point ); + point = max.Min( point ); + + return point; + } + + public static Vector3 Constrain( Vector3 point, Vector3 min, Vector3 max ) + { + point = min.Max( point ); + point = max.Min( point ); + + return point; + } + + public bool ContainsPoint( Vector3 point ) + { + if ( ! Range.Contains( min.X, max.X, point.X ) ) + { + return false; + } + + if ( ! Range.Contains( min.Z, max.Z, point.Z ) ) + { + return false; + } + + if ( ! Range.Contains( min.Y, max.Y, point.Y ) ) + { + return false; + } + + return true; + } + + + public void EnsureCorrectness() + { + if ( max.X < min.X ) + { + var b = max.X; max.X = min.X; min.X = b; + } + + if ( max.Y < min.Y ) + { + var b = max.Y; max.Y = min.Y; min.Y = b; + } + + if ( max.Z < min.Z ) + { + var b = max.Z; max.Z = min.Z; min.Z = b; + } + + } + + } + +} \ No newline at end of file diff --git a/Runtime/Tools/Arrays.cs b/Runtime/Tools/Arrays.cs index 4c25e74..45c360b 100644 --- a/Runtime/Tools/Arrays.cs +++ b/Runtime/Tools/Arrays.cs @@ -7,6 +7,21 @@ namespace Rokojori { public class Arrays { + public static bool Contains ( T[] values, T other ) + { + return Array.IndexOf( values, other ) != -1; + } + + public static T[] Add( T[] values, T other ) + { + var newValues = new T[ values.Length + 1 ]; + + Array.Copy( values, newValues, values.Length ); + newValues[ values.Length ] = other; + + return newValues; + } + public static void ForEach( T[] values, Action callback ) { foreach ( var it in values ) diff --git a/Runtime/VirtualCameras/StrategyTopDownCamera.cs b/Runtime/VirtualCameras/StrategyTopDownCamera.cs index f5b3f9a..2cdc755 100644 --- a/Runtime/VirtualCameras/StrategyTopDownCamera.cs +++ b/Runtime/VirtualCameras/StrategyTopDownCamera.cs @@ -12,6 +12,13 @@ namespace Rokojori [GlobalClass] public partial class StrategyTopDownCamera:VirtualCamera3D { + public enum ConstrainMode + { + Unconstrained, + Axis_Aligned_Box, + Circle_XZ_Range_Y + } + [Export] public Vector3 target; @@ -27,6 +34,17 @@ namespace Rokojori [ExportCategory("Move")] + [Export] + public ConstrainMode constrainMode = ConstrainMode.Unconstrained; + + [Export] + public Node3D constrainMin; + + [Export] + public Node3D constrainMax; + + + [Export] public RJSensor moveUpButton; [Export] @@ -190,6 +208,43 @@ namespace Rokojori 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 )