Add backbone for card creation and implement Camera minigame mechanics

This commit is contained in:
Michal Pikulski
2025-10-10 14:31:51 +02:00
parent d9039ce655
commit 0c5546efd2
107 changed files with 10490 additions and 280 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic; // Added for List<ITouchInputConsumer>
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
@@ -27,6 +28,9 @@ namespace Input
private static InputManager _instance;
private static bool _isQuitting = false;
// Override consumer stack - using a list to support multiple overrides that can be removed in LIFO order
private readonly List<ITouchInputConsumer> _overrideConsumers = new List<ITouchInputConsumer>();
public static InputManager Instance
{
get
@@ -38,7 +42,6 @@ namespace Input
{
var go = new GameObject("InputManager");
_instance = go.AddComponent<InputManager>();
// DontDestroyOnLoad(go);
}
}
return _instance;
@@ -58,7 +61,6 @@ namespace Input
void Awake()
{
_instance = this;
// DontDestroyOnLoad(gameObject);
// Initialize settings reference
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
@@ -157,23 +159,27 @@ namespace Input
/// </summary>
private void OnTapMovePerformed(InputAction.CallbackContext ctx)
{
if (EventSystem.current.IsPointerOverGameObject())
{
return;
}
Vector2 screenPos = positionAction.ReadValue<Vector2>();
Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos);
Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y);
Debug.Log($"[InputManager] TapMove performed at {worldPos2D}");
if (!TryDelegateToInteractable(worldPos2D))
// First try to delegate to an override consumer if available
if (TryDelegateToOverrideConsumer(screenPos, worldPos2D))
{
Debug.Log("[InputManager] No interactable found, forwarding tap to default consumer");
Debug.Log("[InputManager] Tap delegated to override consumer");
return;
}
// Then try to delegate to any ITouchInputConsumer (UI or world interactable)
if (!TryDelegateToAnyInputConsumer(screenPos, worldPos2D))
{
Debug.Log("[InputManager] No input consumer found, forwarding tap to default consumer");
defaultConsumer?.OnTap(worldPos2D);
}
else
{
Debug.Log("[InputManager] Tap delegated to interactable");
Debug.Log("[InputManager] Tap delegated to input consumer");
}
}
@@ -219,14 +225,84 @@ namespace Input
}
}
/// <summary>
/// Attempts to delegate a tap to any ITouchInputConsumer at the given position.
/// Checks both UI elements and world interactables.
/// </summary>
private bool TryDelegateToAnyInputConsumer(Vector2 screenPos, Vector2 worldPos)
{
// First check if we hit a UI element implementing ITouchInputConsumer
if (TryDelegateToUIInputConsumer(screenPos))
{
return true;
}
// If no UI element with ITouchInputConsumer, try world interactables
return TryDelegateToInteractable(worldPos);
}
/// <summary>
/// Attempts to delegate a tap to a UI element implementing ITouchInputConsumer.
/// </summary>
private bool TryDelegateToUIInputConsumer(Vector2 screenPos)
{
// Check for UI elements under the pointer
var eventData = new PointerEventData(EventSystem.current)
{
position = screenPos
};
var results = new System.Collections.Generic.List<RaycastResult>();
EventSystem.current.RaycastAll(eventData, results);
foreach (var result in results)
{
// Try to get ITouchInputConsumer component
var consumer = result.gameObject.GetComponent<ITouchInputConsumer>();
if (consumer == null)
{
consumer = result.gameObject.GetComponentInParent<ITouchInputConsumer>();
}
if (consumer != null)
{
Debug.unityLogger.Log("Interactable", $"[InputManager] Delegating tap to UI consumer at {screenPos} (GameObject: {result.gameObject.name})");
consumer.OnTap(screenPos);
return true;
}
}
return false;
}
/// <summary>
/// Attempts to delegate a tap to an interactable at the given world position.
/// Traces on the "Interactable" channel and logs detailed info.
/// </summary>
private bool TryDelegateToInteractable(Vector2 worldPos)
{
LayerMask mask = _interactionSettings != null ? _interactionSettings.InteractableLayerMask : -1;
Collider2D hit = Physics2D.OverlapPoint(worldPos, mask);
// First try with the interaction layer mask if available
if (_interactionSettings != null)
{
LayerMask mask = _interactionSettings.InteractableLayerMask;
Collider2D hitWithMask = Physics2D.OverlapPoint(worldPos, mask);
if (hitWithMask != null)
{
var consumer = hitWithMask.GetComponent<ITouchInputConsumer>();
if (consumer == null)
{
consumer = hitWithMask.GetComponentInParent<ITouchInputConsumer>();
}
if (consumer != null)
{
Debug.unityLogger.Log("Interactable", $"[InputManager] Delegating tap to consumer at {worldPos} (GameObject: {hitWithMask.gameObject.name})");
consumer.OnTap(worldPos);
return true;
}
}
}
// If no hit with the mask or no settings available, try with all colliders
Collider2D hit = Physics2D.OverlapPoint(worldPos);
if (hit != null)
{
var consumer = hit.GetComponent<ITouchInputConsumer>();
@@ -244,5 +320,54 @@ namespace Input
}
return false;
}
/// <summary>
/// Registers an override consumer to receive input events.
/// The most recently registered consumer will receive input first.
/// </summary>
public void RegisterOverrideConsumer(ITouchInputConsumer consumer)
{
if (consumer == null || _overrideConsumers.Contains(consumer))
return;
_overrideConsumers.Add(consumer);
Debug.Log($"[InputManager] Override consumer registered: {consumer}");
}
/// <summary>
/// Unregisters an override consumer, removing it from the input event delegation.
/// </summary>
public void UnregisterOverrideConsumer(ITouchInputConsumer consumer)
{
if (consumer == null || !_overrideConsumers.Contains(consumer))
return;
_overrideConsumers.Remove(consumer);
Debug.Log($"[InputManager] Override consumer unregistered: {consumer}");
}
/// <summary>
/// Clears all registered override consumers.
/// </summary>
public void ClearOverrideConsumers()
{
_overrideConsumers.Clear();
Debug.Log("[InputManager] All override consumers cleared.");
}
/// <summary>
/// Attempts to delegate a tap to the topmost registered override consumer, if any.
/// </summary>
private bool TryDelegateToOverrideConsumer(Vector2 screenPos, Vector2 worldPos)
{
if (_overrideConsumers.Count == 0)
return false;
// Get the topmost override consumer (last registered)
var consumer = _overrideConsumers[_overrideConsumers.Count - 1];
Debug.unityLogger.Log("Interactable", $"[InputManager] Delegating tap to override consumer at {worldPos} (GameObject: {consumer})");
consumer.OnTap(worldPos);
return true;
}
}
}