Files
chameleon/Assets/Scripts/GameModeManager.cs
T
adminandClaude Opus 4.8 04c22f0ac1 Add in-game paint HUD bound to the mesh painter
Add a code-driven HUD that appears in paint mode and binds live to the
active MeshPainter: four channel toggles, HSV pickers for albedo and
emission, sliders for metallic/smoothness/occlusion, emission intensity
and brush size. The HUD self-assembles its own overlay canvas and event
system at runtime.

Add a ModeChanged event to GameModeManager so the HUD can follow the
active mode, and guard MeshPainter against painting through the UI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 08:26:56 +02:00

124 lines
4.0 KiB
C#

using System.Collections.Generic;
using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
/// <summary>
/// Switches the game between high-level modes (Player Control, Paint). The switch
/// key (Tab) cycles to the next registered mode. Register additional modes in
/// <see cref="BuildModes"/>. Attach to a single, persistent scene GameObject.
/// </summary>
[DisallowMultipleComponent]
public class GameModeManager : MonoBehaviour
{
[Header("Controlled Systems")]
[Tooltip("Player movement controller. Empty = found automatically.")]
public PlayerCharacterController player;
[Tooltip("Third-person orbit camera input. Empty = found automatically.")]
public ThirdPersonOrbitInput cameraInput;
[Tooltip("Mesh painter. Empty = found automatically.")]
public MeshPainter painter;
[Tooltip("Insect / surface-walk controller. Empty = found automatically.")]
public InsectController insect;
[Header("Switching")]
[Tooltip("Key that cycles to the next mode.")]
#if ENABLE_INPUT_SYSTEM
public Key switchKey = Key.Tab;
#else
public KeyCode switchKey = KeyCode.Tab;
#endif
[Tooltip("Mode active at startup (0 = Player Control).")]
public int startModeIndex = 0;
public PlayerCharacterController Player => player;
public ThirdPersonOrbitInput CameraInput => cameraInput;
public MeshPainter Painter => painter;
public InsectController Insect => insect;
/// <summary>Raised after a mode switch finishes (the new mode's Enter has already run).
/// Argument = the now-active mode. Used by UI (e.g. the paint HUD) to follow the mode.</summary>
public event System.Action<GameMode> ModeChanged;
private readonly List<GameMode> _modes = new List<GameMode>();
private int _activeIndex = -1;
/// <summary>The currently active mode (null before startup).</summary>
public GameMode ActiveMode =>
(_activeIndex >= 0 && _activeIndex < _modes.Count) ? _modes[_activeIndex] : null;
private void Awake()
{
if (!player) player = FindFirstObjectByType<PlayerCharacterController>();
if (!cameraInput) cameraInput = FindFirstObjectByType<ThirdPersonOrbitInput>();
if (!painter) painter = FindFirstObjectByType<MeshPainter>();
if (!insect) insect = FindFirstObjectByType<InsectController>();
BuildModes();
}
private void Start()
{
if (_modes.Count > 0)
SwitchTo(Mathf.Clamp(startModeIndex, 0, _modes.Count - 1));
}
/// <summary>Registers all available modes. Add new modes here.</summary>
private void BuildModes()
{
_modes.Clear();
// Player Control only joins the Tab cycle when a gravity player is present, so a scene
// running only the insect walker doesn't trap input in a dead, player-freezing mode.
if (player)
_modes.Add(new PlayerControlMode());
_modes.Add(new PaintMode());
// Insect mode only joins the Tab cycle when a surface walker is present, so a scene
// without one behaves exactly as before (no dead, player-freezing mode in the cycle).
if (insect)
_modes.Add(new InsectMode());
foreach (var m in _modes)
m.Bind(this);
}
private void Update()
{
if (_modes.Count == 0) return;
if (WasSwitchPressed())
SwitchTo((_activeIndex + 1) % _modes.Count);
ActiveMode?.Tick();
}
/// <summary>Activates the mode at <paramref name="index"/> (Exit old, Enter new).</summary>
public void SwitchTo(int index)
{
if (index < 0 || index >= _modes.Count || index == _activeIndex) return;
ActiveMode?.Exit();
_activeIndex = index;
ActiveMode.Enter();
Debug.Log($"[GameModeManager] Mode -> {ActiveMode.DisplayName}", this);
ModeChanged?.Invoke(ActiveMode);
}
private bool WasSwitchPressed()
{
#if ENABLE_INPUT_SYSTEM
return Keyboard.current != null && Keyboard.current[switchKey].wasPressedThisFrame;
#else
return Input.GetKeyDown(switchKey);
#endif
}
}