add helpers on camera boundary

This commit is contained in:
Nilton Constantino 2026-06-08 22:13:44 +01:00
parent 775dfd8ad2
commit 052f88c46d
No known key found for this signature in database
2 changed files with 778 additions and 338 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@ using System;
using Intrepid.Core.Camera.Events; using Intrepid.Core.Camera.Events;
using Intrepid.GameManagers; using Intrepid.GameManagers;
using Intrepid.Utilities; using Intrepid.Utilities;
using Sirenix.OdinInspector;
using UnityEngine; using UnityEngine;
#if UNITY_EDITOR #if UNITY_EDITOR
using UnityEditor; using UnityEditor;
@ -9,13 +10,38 @@ using UnityEditor;
namespace Intrepid.Core.Camera namespace Intrepid.Core.Camera
{ {
[ExecuteAlways]
[DisallowMultipleComponent] [DisallowMultipleComponent]
[RequireComponent(typeof(BoxCollider))] [RequireComponent(typeof(BoxCollider))]
public sealed class CameraBoundary : MonoBehaviour public sealed class CameraBoundary : MonoBehaviour
{ {
[GroupInjections, SerializeField] private BoxCollider boxCollider; [GroupInjections, SerializeField] private BoxCollider boxCollider;
[GroupConfigurations, SerializeField, Min(0f)] private float cameraPadding = 0.5f;
[GroupConfigurations, SerializeField, Min(0.1f)] private float triggerHeight = 5f;
public Bounds WorldBounds => boxCollider.bounds; public Bounds WorldBounds => boxCollider.bounds;
private void Reset()
{
boxCollider = GetComponent<BoxCollider>();
ConfigureAsTrigger();
}
private void OnValidate()
{
if (boxCollider.IsNull())
boxCollider = GetComponent<BoxCollider>();
ConfigureAsTrigger();
}
private void ConfigureAsTrigger()
{
if (boxCollider.IsNull())
return;
boxCollider.isTrigger = true;
}
private void OnTriggerEnter(Collider other) private void OnTriggerEnter(Collider other)
{ {
@ -33,10 +59,148 @@ namespace Intrepid.Core.Camera
}); });
} }
[GroupDebug, Button(ButtonSizes.Medium)]
private void SetToCameraMinimumSize()
{
if (!TryGetCameraFootprintLocalBounds(out var localBounds))
return;
var size = boxCollider.size;
size.x = localBounds.size.x + cameraPadding * 2f;
size.y = triggerHeight;
size.z = localBounds.size.z + cameraPadding * 2f;
boxCollider.size = size;
}
[GroupDebug, Button(ButtonSizes.Medium)]
private void ClampToCameraMinimumSize()
{
if (!TryGetCameraFootprintLocalBounds(out var localBounds))
return;
var size = boxCollider.size;
size.x = Mathf.Max(size.x, localBounds.size.x + cameraPadding * 2f);
size.y = triggerHeight;
size.z = Mathf.Max(size.z, localBounds.size.z + cameraPadding * 2f);
boxCollider.size = size;
}
[GroupDebug, Button(ButtonSizes.Medium)]
private void FitToCurrentCameraView()
{
if (!TryGetCameraFootprintLocalBounds(out var localBounds))
return;
boxCollider.center = new Vector3(
localBounds.center.x,
0f,
localBounds.center.z
);
boxCollider.size = new Vector3(
localBounds.size.x + cameraPadding * 2f,
triggerHeight,
localBounds.size.z + cameraPadding * 2f
);
}
[GroupDebug, Button(ButtonSizes.Medium)]
private void ApplyTriggerHeight()
{
var size = boxCollider.size;
size.y = triggerHeight;
boxCollider.size = size;
}
[GroupDebug, Button(ButtonSizes.Medium)]
private void ResetColliderCenter()
{
boxCollider.center = Vector3.zero;
}
private bool TryGetCameraFootprintLocalBounds(out Bounds localBounds)
{
localBounds = default;
if (!TryGetReferenceCamera(out var cam))
return false;
if (!cam.orthographic)
{
Debug.LogWarning($"{nameof(CameraBoundary)} only supports orthographic cameras for boundary utilities.", this);
return false;
}
var planeY = boxCollider.transform.TransformPoint(boxCollider.center).y;
var groundPlane = new Plane(Vector3.up, new Vector3(0f, planeY, 0f));
var viewportCorners = new[]
{
new Vector3(0f, 0f, 0f),
new Vector3(0f, 1f, 0f),
new Vector3(1f, 1f, 0f),
new Vector3(1f, 0f, 0f),
};
var hasPoint = false;
foreach (var viewportCorner in viewportCorners)
{
var ray = cam.ViewportPointToRay(viewportCorner);
if (!groundPlane.Raycast(ray, out var distance))
continue;
var worldPoint = ray.GetPoint(distance);
var localPoint = boxCollider.transform.InverseTransformPoint(worldPoint);
if (!hasPoint)
{
localBounds = new Bounds(localPoint, Vector3.zero);
hasPoint = true;
}
else
{
localBounds.Encapsulate(localPoint);
}
}
return hasPoint;
}
private bool TryGetReferenceCamera(out UnityEngine.Camera cam)
{
cam = CameraSystem.Instance?.MainCamera;
if (cam.IsNotNull())
return true;
cam = UnityEngine.Camera.main;
if (cam.IsNotNull())
return true;
#if UNITY_EDITOR
if (SceneView.lastActiveSceneView.IsNotNull())
{
cam = SceneView.lastActiveSceneView.camera;
return cam.IsNotNull();
}
#endif
Debug.LogWarning($"{nameof(CameraBoundary)} could not find a reference camera.", this);
return false;
}
#if UNITY_EDITOR #if UNITY_EDITOR
private void OnDrawGizmosSelected() private void OnDrawGizmosSelected()
{ {
if (boxCollider.IsNull()) return; if (boxCollider.IsNull()) return;
DrawBoxFill(); DrawBoxFill();
DrawHatchedBoxXZ(); DrawHatchedBoxXZ();
DrawBoxWire(); DrawBoxWire();
@ -46,7 +210,7 @@ namespace Intrepid.Core.Camera
{ {
var b = boxCollider.bounds; var b = boxCollider.bounds;
Gizmos.color = new Color(1f, 0f, 1f, 0.10f); // alpha Gizmos.color = new Color(1f, 0f, 1f, 0.10f);
Gizmos.DrawCube(b.center, b.size); Gizmos.DrawCube(b.center, b.size);
} }
@ -62,7 +226,7 @@ namespace Intrepid.Core.Camera
{ {
const float hatchSpacing = .5f; const float hatchSpacing = .5f;
Handles.color = new Color(1f, 0f, 1f, 0.65f); // alpha Handles.color = new Color(1f, 0f, 1f, 0.65f);
var size = boxCollider.size; var size = boxCollider.size;
var center = boxCollider.center; var center = boxCollider.center;
@ -113,27 +277,19 @@ namespace Intrepid.Core.Camera
var xAtMinZ = c + minZ; var xAtMinZ = c + minZ;
if (xAtMinZ >= minX && xAtMinZ <= maxX) if (xAtMinZ >= minX && xAtMinZ <= maxX)
{
points[count++] = new Vector3(xAtMinZ, y, minZ); points[count++] = new Vector3(xAtMinZ, y, minZ);
}
var xAtMaxZ = c + maxZ; var xAtMaxZ = c + maxZ;
if (xAtMaxZ >= minX && xAtMaxZ <= maxX) if (xAtMaxZ >= minX && xAtMaxZ <= maxX)
{
points[count++] = new Vector3(xAtMaxZ, y, maxZ); points[count++] = new Vector3(xAtMaxZ, y, maxZ);
}
var zAtMinX = minX - c; var zAtMinX = minX - c;
if (zAtMinX >= minZ && zAtMinX <= maxZ) if (zAtMinX >= minZ && zAtMinX <= maxZ)
{
points[count++] = new Vector3(minX, y, zAtMinX); points[count++] = new Vector3(minX, y, zAtMinX);
}
var zAtMaxX = maxX - c; var zAtMaxX = maxX - c;
if (zAtMaxX >= minZ && zAtMaxX <= maxZ) if (zAtMaxX >= minZ && zAtMaxX <= maxZ)
{
points[count++] = new Vector3(maxX, y, zAtMaxX); points[count++] = new Vector3(maxX, y, zAtMaxX);
}
if (count < 2) if (count < 2)
{ {