Generic MVP working
This commit is contained in:
committed by
Michal Pikulski
parent
11833ba503
commit
ab579e2d21
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Core;
|
||||
using Core.Lifecycle;
|
||||
using Unity.Cinemachine;
|
||||
@@ -7,15 +8,40 @@ using UnityEngine;
|
||||
|
||||
namespace Common.Camera
|
||||
{
|
||||
/// <summary>
|
||||
/// Serializable mapping between a camera state and its Cinemachine camera.
|
||||
/// Used to assign cameras in the Inspector for each enum state.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class CameraStateMapping<TState> where TState : Enum
|
||||
{
|
||||
[Tooltip("The state this camera represents")]
|
||||
public TState state;
|
||||
|
||||
[Tooltip("The Cinemachine camera for this state")]
|
||||
public CinemachineCamera camera;
|
||||
|
||||
public CameraStateMapping(TState state)
|
||||
{
|
||||
this.state = state;
|
||||
this.camera = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generic state-based camera controller using Cinemachine.
|
||||
/// Manages camera transitions by setting priorities on virtual cameras.
|
||||
/// Type parameter TState must be an enum representing camera states.
|
||||
/// </summary>
|
||||
///
|
||||
public abstract class CameraStateManager<TState> : ManagedBehaviour where TState : Enum
|
||||
{
|
||||
#region Configuration
|
||||
|
||||
[Header("Camera Mappings")]
|
||||
[Tooltip("Assign cameras for each state - list auto-populates from enum")]
|
||||
[SerializeField] protected List<CameraStateMapping<TState>> cameraMappings = new List<CameraStateMapping<TState>>();
|
||||
|
||||
[Header("Camera Priority Settings")]
|
||||
[Tooltip("Priority for inactive cameras")]
|
||||
[SerializeField] protected int inactivePriority = 10;
|
||||
@@ -47,11 +73,66 @@ namespace Common.Camera
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
/// <summary>
|
||||
/// Initialize camera mappings and validate them.
|
||||
/// Subclasses should call base.OnManagedAwake() to get automatic initialization.
|
||||
/// If custom initialization is needed, override without calling base.
|
||||
/// </summary>
|
||||
internal override void OnManagedAwake()
|
||||
{
|
||||
base.OnManagedAwake();
|
||||
|
||||
// Initialize cameras from Inspector mappings
|
||||
InitializeCameraMap();
|
||||
|
||||
// Validate all cameras are assigned
|
||||
ValidateCameras();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Initialization
|
||||
|
||||
/// <summary>
|
||||
/// Register a camera for a specific state.
|
||||
/// Call this in subclass OnManagedAwake to set up the camera map.
|
||||
/// Initialize camera mappings from Inspector-assigned list.
|
||||
/// Call this in OnManagedAwake - no need to manually register cameras!
|
||||
/// This is the preferred method for new implementations.
|
||||
/// </summary>
|
||||
protected void InitializeCameraMap()
|
||||
{
|
||||
_cameraMap.Clear();
|
||||
|
||||
// Build dictionary from serialized mappings
|
||||
foreach (var mapping in cameraMappings)
|
||||
{
|
||||
if (mapping.camera == null)
|
||||
{
|
||||
Logging.Warning($"[{GetType().Name}] No camera assigned for state {mapping.state}");
|
||||
continue;
|
||||
}
|
||||
|
||||
_cameraMap[mapping.state] = mapping.camera;
|
||||
mapping.camera.Priority.Value = inactivePriority;
|
||||
|
||||
if (showDebugLogs)
|
||||
Logging.Debug($"[{GetType().Name}] Registered camera '{mapping.camera.gameObject.name}' for state {mapping.state}");
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
|
||||
if (_cameraMap.Count == 0)
|
||||
{
|
||||
Logging.Warning($"[{GetType().Name}] No cameras registered!");
|
||||
}
|
||||
|
||||
if (showDebugLogs) Logging.Debug($"[{GetType().Name}] Initialized with {_cameraMap.Count} cameras");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DEPRECATED: Use InitializeCameraMap() instead for cleaner code.
|
||||
/// Kept for backward compatibility with existing implementations.
|
||||
/// </summary>
|
||||
protected void RegisterCamera(TState state, CinemachineCamera pCamera)
|
||||
{
|
||||
@@ -67,16 +148,14 @@ namespace Common.Camera
|
||||
}
|
||||
|
||||
_cameraMap[state] = pCamera;
|
||||
|
||||
// Set all cameras to inactive priority initially
|
||||
pCamera.Priority.Value = inactivePriority;
|
||||
|
||||
if (showDebugLogs) Logging.Debug($"[{GetType().Name}] Registered camera '{pCamera.gameObject.name}' for state {state}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalize initialization after all cameras are registered.
|
||||
/// Call this at the end of subclass OnManagedAwake.
|
||||
/// DEPRECATED: Use InitializeCameraMap() instead.
|
||||
/// Kept for backward compatibility with existing implementations.
|
||||
/// </summary>
|
||||
protected void FinalizeInitialization()
|
||||
{
|
||||
@@ -155,15 +234,66 @@ namespace Common.Camera
|
||||
#region Validation
|
||||
|
||||
/// <summary>
|
||||
/// Validate that all required states have cameras registered.
|
||||
/// Subclasses can override to add custom validation.
|
||||
/// Validate that all enum states have cameras registered.
|
||||
/// Override to add custom validation (e.g., check for specific components).
|
||||
/// </summary>
|
||||
protected virtual void ValidateCameras()
|
||||
{
|
||||
// Subclasses should implement specific validation
|
||||
// Check that all enum values have cameras assigned
|
||||
foreach (TState state in Enum.GetValues(typeof(TState)))
|
||||
{
|
||||
if (!_cameraMap.ContainsKey(state))
|
||||
{
|
||||
Logging.Warning($"[{GetType().Name}] No camera assigned for state {state}");
|
||||
}
|
||||
else if (_cameraMap[state] == null)
|
||||
{
|
||||
Logging.Error($"[{GetType().Name}] Camera for state {state} is null!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Editor Support
|
||||
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// Auto-populate camera mappings list with all enum values.
|
||||
/// Called automatically in the Editor when the component is added or values change.
|
||||
/// </summary>
|
||||
protected virtual void OnValidate()
|
||||
{
|
||||
// Get all enum values
|
||||
TState[] allStates = (TState[])Enum.GetValues(typeof(TState));
|
||||
|
||||
// Add missing states to the list
|
||||
foreach (TState state in allStates)
|
||||
{
|
||||
bool exists = cameraMappings.Any(m => EqualityComparer<TState>.Default.Equals(m.state, state));
|
||||
if (!exists)
|
||||
{
|
||||
cameraMappings.Add(new CameraStateMapping<TState>(state));
|
||||
}
|
||||
}
|
||||
|
||||
// Remove mappings for states that no longer exist in the enum
|
||||
cameraMappings.RemoveAll(m => !System.Array.Exists(allStates, s => EqualityComparer<TState>.Default.Equals(s, m.state)));
|
||||
|
||||
// Sort by enum order for cleaner Inspector display
|
||||
cameraMappings = cameraMappings.OrderBy(m => (int)(object)m.state).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize list when component is first added
|
||||
/// </summary>
|
||||
protected virtual void Reset()
|
||||
{
|
||||
OnValidate();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user