Cleanup compile warnings, cleanup logs, spruce up level selection menu

This commit is contained in:
Michal Pikulski
2025-10-28 14:31:17 +01:00
parent a5b1a4f8a0
commit 43779c560e
67 changed files with 4814 additions and 1050 deletions

View File

@@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AppleHills.Core.Settings;
using Core;
using UnityEngine;
namespace Bootstrap
@@ -56,7 +58,7 @@ namespace Bootstrap
IsBootComplete = true;
Debug.Log("[BootCompletionService] Boot process completed, executing initialization actions");
LogDebugMessage("Boot process completed, executing initialization actions");
// Execute initialization actions in priority order (lower number = higher priority)
ExecuteInitializationActions();
@@ -67,7 +69,7 @@ namespace Bootstrap
// Complete the task for async waiters
_bootCompletionTask.TrySetResult(true);
Debug.Log("[BootCompletionService] All boot completion handlers executed");
LogDebugMessage("All boot completion handlers executed");
}
/// <summary>
@@ -90,21 +92,21 @@ namespace Bootstrap
if (IsBootComplete)
{
// If boot is already complete, execute immediately
Debug.Log($"[BootCompletionService] Executing late registration: {name} (Priority: {priority})");
LogDebugMessage($"Executing late registration: {name} (Priority: {priority})");
try
{
action();
}
catch (Exception ex)
{
Debug.LogError($"[BootCompletionService] Error executing init action '{name}': {ex}");
LogDebugMessage($"Error executing init action '{name}': {ex}");
}
}
else
{
// Otherwise add to the queue
_initializationActions.Add(initAction);
Debug.Log($"[BootCompletionService] Registered init action: {name} (Priority: {priority})");
LogDebugMessage($"Registered init action: {name} (Priority: {priority})");
}
}
@@ -134,17 +136,26 @@ namespace Bootstrap
{
try
{
Debug.Log($"[BootCompletionService] Executing: {action.Name} (Priority: {action.Priority})");
LogDebugMessage($"Executing: {action.Name} (Priority: {action.Priority})");
action.Action();
}
catch (Exception ex)
{
Debug.LogError($"[BootCompletionService] Error executing init action '{action.Name}': {ex}");
LogDebugMessage($"Error executing init action '{action.Name}': {ex}");
}
}
// Clear the list after execution
_initializationActions.Clear();
}
private static void LogDebugMessage(string message)
{
if (DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().bootstrapLogVerbosity <=
LogVerbosity.Debug)
{
Logging.Debug($"[BootCompletionService] {message}");
}
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using AppleHills.Core.Settings;
using UnityEngine;
using UI;
using Core;
@@ -27,10 +28,11 @@ namespace Bootstrap
private bool _bootComplete = false;
private bool _hasStartedLoading = false;
private float _sceneLoadingProgress = 0f;
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
private void Start()
{
Debug.Log("[BootSceneController] Boot scene started");
LogDebugMessage("Boot scene started");
// Ensure the initial loading screen exists
if (initialLoadingScreen == null)
@@ -56,6 +58,8 @@ namespace Bootstrap
50, // Higher priority (lower number)
"BootSceneController.OnBootCompleted"
);
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().bootstrapLogVerbosity;
// In debug mode, log additional information
if (debugMode)
@@ -69,12 +73,12 @@ namespace Bootstrap
/// </summary>
private void OnInitialLoadingComplete()
{
Debug.Log("[BootSceneController] Initial loading screen fully hidden, boot sequence completed");
LogDebugMessage("Initial loading screen fully hidden, boot sequence completed");
// Play the intro cinematic if available
if (CinematicsManager.Instance != null)
{
Debug.Log("[BootSceneController] Attempting to play intro cinematic");
LogDebugMessage("Attempting to play intro cinematic");
// Use LoadAndPlayCinematic to play the intro sequence
CinematicsManager.Instance.LoadAndPlayCinematic("IntroSequence");
@@ -131,13 +135,13 @@ namespace Bootstrap
{
if (debugMode)
{
Debug.Log($"[BootSceneController] Bootstrap progress: {progress:P0}, Combined: {GetCombinedProgress():P0}");
LogDebugMessage($"Bootstrap progress: {progress:P0}, Combined: {GetCombinedProgress():P0}");
}
}
private void LogDebugInfo()
{
Debug.Log($"[BootSceneController] Debug - Phase: {_currentPhase}, Bootstrap: {CustomBoot.CurrentProgress:P0}, " +
LogDebugMessage($"Debug - Phase: {_currentPhase}, Bootstrap: {CustomBoot.CurrentProgress:P0}, " +
$"Scene: {_sceneLoadingProgress:P0}, Combined: {GetCombinedProgress():P0}, Boot Complete: {_bootComplete}");
}
@@ -146,7 +150,7 @@ namespace Bootstrap
// Unsubscribe to prevent duplicate calls
CustomBoot.OnBootCompleted -= OnBootCompleted;
Debug.Log("[BootSceneController] Boot process completed");
LogDebugMessage("Boot process completed");
_bootComplete = true;
// After a small delay, start loading the main menu
@@ -166,7 +170,7 @@ namespace Bootstrap
private async void LoadMainScene()
{
Debug.Log($"[BootSceneController] Loading main menu scene: {mainSceneName}");
LogDebugMessage($"Loading main menu scene: {mainSceneName}");
try
{
@@ -180,7 +184,7 @@ namespace Bootstrap
if (debugMode)
{
Debug.Log($"[BootSceneController] Scene loading raw: {value:P0}, Combined: {GetCombinedProgress():P0}");
LogDebugMessage($"Scene loading raw: {value:P0}, Combined: {GetCombinedProgress():P0}");
}
});
@@ -229,7 +233,7 @@ namespace Bootstrap
Scene currentScene = SceneManager.GetActiveScene();
string startingSceneName = currentScene.name;
Debug.Log($"[BootSceneController] Unloading StartingScene: {startingSceneName}");
LogDebugMessage($"Unloading StartingScene: {startingSceneName}");
// Unload the StartingScene
await SceneManager.UnloadSceneAsync(startingSceneName);
@@ -238,7 +242,7 @@ namespace Bootstrap
Scene mainMenuScene = SceneManager.GetSceneByName(mainSceneName);
SceneManager.SetActiveScene(mainMenuScene);
Debug.Log($"[BootSceneController] Transition complete: {startingSceneName} unloaded, {mainSceneName} is now active");
LogDebugMessage($"Transition complete: {startingSceneName} unloaded, {mainSceneName} is now active");
// Destroy the boot scene controller since its job is done
Destroy(gameObject);
@@ -266,5 +270,13 @@ namespace Bootstrap
_progressAction?.Invoke(value);
}
}
private void LogDebugMessage(string message)
{
if ( _logVerbosity <= LogVerbosity.Debug)
{
Logging.Debug($"[BootSceneController] {message}");
}
}
}
}

View File

@@ -1,5 +1,7 @@
using System;
using System.Threading.Tasks;
using AppleHills.Core.Settings;
using Core;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
@@ -99,7 +101,7 @@ namespace Bootstrap
if (Application.isPlaying)
{
// Direct call to boot completion service
Debug.Log("[CustomBoot] Calling BootCompletionService.HandleBootCompleted()");
LogDebugMessage("Calling BootCompletionService.HandleBootCompleted()");
BootCompletionService.HandleBootCompleted();
}
}
@@ -119,7 +121,7 @@ namespace Bootstrap
if (Application.isPlaying)
{
// Direct call to boot completion service
Debug.Log("[CustomBoot] Calling BootCompletionService.HandleBootCompleted()");
LogDebugMessage("Calling BootCompletionService.HandleBootCompleted()");
BootCompletionService.HandleBootCompleted();
}
}
@@ -227,7 +229,16 @@ namespace Bootstrap
{
CurrentProgress = Mathf.Clamp01(progress);
OnBootProgressChanged?.Invoke(CurrentProgress);
Debug.Log($"[CustomBoot] Progress: {CurrentProgress:P0}");
LogDebugMessage($"Progress: {CurrentProgress:P0}");
}
private static void LogDebugMessage(string message)
{
if (DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().bootstrapLogVerbosity <=
LogVerbosity.Debug)
{
Logging.Debug($"[CustomBoot] {message}");
}
}
}
}

View File

@@ -1,8 +1,9 @@
using System;
using System.Collections;
using AppleHills.Core.Settings;
using Core;
using UnityEngine;
using UnityEngine.UI;
using Core;
namespace Bootstrap
{
@@ -40,7 +41,9 @@ namespace Bootstrap
/// Current progress provider being used for the loading screen
/// </summary>
private ProgressProvider _currentProgressProvider;
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
/// <summary>
/// Default progress provider that returns 0 (or 1 if loading is complete)
/// </summary>
@@ -62,7 +65,12 @@ namespace Bootstrap
loadingScreenContainer.SetActive(false);
}
}
private void Start()
{
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().bootstrapLogVerbosity;
}
/// <summary>
/// Shows the loading screen and resets the progress bar to zero
/// </summary>
@@ -130,7 +138,7 @@ namespace Bootstrap
float displayProgress = Mathf.Min(steadyProgress, actualProgress);
// Log the progress values for debugging
Debug.Log($"[InitialLoadingScreen] Progress - Default: {steadyProgress:F2}, Actual: {actualProgress:F2}, Display: {displayProgress:F2}");
LogDebugMessage($"Progress - Default: {steadyProgress:F2}, Actual: {actualProgress:F2}, Display: {displayProgress:F2}");
// Directly set the progress bar fill amount without smoothing
if (progressBarImage != null)
@@ -143,7 +151,7 @@ namespace Bootstrap
if (steadyProgress >= 1.0f && displayProgress >= 1.0f)
{
_animationComplete = true;
Debug.Log("[InitialLoadingScreen] Animation complete");
LogDebugMessage("Animation complete");
break;
}
@@ -155,7 +163,7 @@ namespace Bootstrap
if (progressBarImage != null)
{
progressBarImage.fillAmount = 1.0f;
Debug.Log("[InitialLoadingScreen] Final progress set to 1.0");
LogDebugMessage("Final progress set to 1.0");
}
// Hide the screen if loading is also complete
@@ -164,7 +172,7 @@ namespace Bootstrap
if (loadingScreenContainer != null)
{
loadingScreenContainer.SetActive(false);
Debug.Log("[InitialLoadingScreen] Animation AND loading complete, hiding screen");
LogDebugMessage("Animation AND loading complete, hiding screen");
// Invoke the callback when fully hidden
_onLoadingScreenFullyHidden?.Invoke();
@@ -181,7 +189,7 @@ namespace Bootstrap
/// </summary>
public void HideLoadingScreen()
{
Debug.Log("[InitialLoadingScreen] Loading complete, marking loading as finished");
LogDebugMessage("Loading complete, marking loading as finished");
// Mark that loading is complete
_loadingComplete = true;
@@ -192,7 +200,7 @@ namespace Bootstrap
if (loadingScreenContainer != null)
{
loadingScreenContainer.SetActive(false);
Debug.Log("[InitialLoadingScreen] Animation already complete, hiding screen immediately");
LogDebugMessage("Animation already complete, hiding screen immediately");
// Invoke the callback when fully hidden
_onLoadingScreenFullyHidden?.Invoke();
@@ -202,7 +210,7 @@ namespace Bootstrap
}
else
{
Debug.Log("[InitialLoadingScreen] Animation still in progress, waiting for it to complete");
LogDebugMessage("Animation still in progress, waiting for it to complete");
// The coroutine will handle hiding when animation completes
}
}
@@ -236,5 +244,13 @@ namespace Bootstrap
return tcs.Task;
}
private void LogDebugMessage(string message)
{
if ( _logVerbosity <= LogVerbosity.Debug)
{
Logging.Debug($"[InitialLoadingScreen] {message}");
}
}
}
}

View File

@@ -19,7 +19,6 @@ namespace Cinematics
public event System.Action OnCinematicStarted;
public event System.Action OnCinematicStopped;
private static CinematicsManager _instance;
private static bool _isQuitting;
private Image _cinematicSprites;
public GameObject cinematicSpritesGameObject;
private bool _isCinematicPlaying = false;
@@ -70,7 +69,6 @@ namespace Cinematics
private void OnApplicationQuit()
{
_isQuitting = true;
ReleaseAllHandles();
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using AppleHills.Core.Interfaces;
using AppleHills.Core.Settings;
using Bootstrap;
using Core.Settings;
using Input;
using UnityEngine;
@@ -26,7 +27,9 @@ namespace Core
// List of pausable components that have registered with the GameManager
private List<IPausable> _pausableComponents = new List<IPausable>();
private LogVerbosity _settingsLogVerbosity = LogVerbosity.Warning;
private LogVerbosity _managerLogVerbosity = LogVerbosity.Warning;
// Events for pause state changes
public event Action OnGamePaused;
public event Action OnGameResumed;
@@ -48,7 +51,13 @@ namespace Core
// DontDestroyOnLoad(gameObject);
}
private void Start()
{
_settingsLogVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().settingsLogVerbosity;
_managerLogVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().gameManagerLogVerbosity;
}
private void InitializePostBoot()
{
// For post-boot correct initialization order
@@ -70,7 +79,7 @@ namespace Core
component.Pause();
}
Logging.Debug($"[GameManager] Registered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}");
LogDebugMessage($"Registered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}");
}
}
@@ -83,7 +92,7 @@ namespace Core
if (component != null && _pausableComponents.Contains(component))
{
_pausableComponents.Remove(component);
Logging.Debug($"[GameManager] Unregistered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}");
LogDebugMessage($"Unregistered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}");
}
}
@@ -99,7 +108,7 @@ namespace Core
ApplyPause(true);
}
Logging.Debug($"[GameManager] Pause requested by {requester?.ToString() ?? "Unknown"}. pauseCount = {_pauseCount}");
LogDebugMessage($"Pause requested by {requester?.ToString() ?? "Unknown"}. pauseCount = {_pauseCount}");
}
/// <summary>
@@ -114,7 +123,7 @@ namespace Core
ApplyPause(false);
}
Logging.Debug($"[GameManager] Pause released by {requester?.ToString() ?? "Unknown"}. pauseCount = {_pauseCount}");
LogDebugMessage($"Pause released by {requester?.ToString() ?? "Unknown"}. pauseCount = {_pauseCount}");
}
/// <summary>
@@ -153,12 +162,12 @@ namespace Core
OnGameResumed?.Invoke();
}
Logging.Debug($"[GameManager] Game {(shouldPause ? "paused" : "resumed")}. Paused {_pausableComponents.Count} components.");
LogDebugMessage($"Game {(shouldPause ? "paused" : "resumed")}. Paused {_pausableComponents.Count} components.");
}
private void InitializeSettings()
{
Logging.Debug("Starting settings initialization...");
LogDebugMessage("Starting settings initialization...", "SettingsInitialization", _settingsLogVerbosity);
// Load settings synchronously
var playerSettings = SettingsProvider.Instance.LoadSettingsSynchronous<PlayerFollowerSettings>();
@@ -169,7 +178,7 @@ namespace Core
if (playerSettings != null)
{
ServiceLocator.Register<IPlayerFollowerSettings>(playerSettings);
Logging.Debug("PlayerFollowerSettings registered successfully");
LogDebugMessage("PlayerFollowerSettings registered successfully", "SettingsInitialization", _settingsLogVerbosity);
}
else
{
@@ -179,7 +188,7 @@ namespace Core
if (interactionSettings != null)
{
ServiceLocator.Register<IInteractionSettings>(interactionSettings);
Logging.Debug("InteractionSettings registered successfully");
LogDebugMessage("InteractionSettings registered successfully", "SettingsInitialization", _settingsLogVerbosity);
}
else
{
@@ -189,7 +198,7 @@ namespace Core
if (minigameSettings != null)
{
ServiceLocator.Register<IDivingMinigameSettings>(minigameSettings);
Logging.Debug("MinigameSettings registered successfully");
LogDebugMessage("MinigameSettings registered successfully", "SettingsInitialization", _settingsLogVerbosity);
}
else
{
@@ -200,7 +209,7 @@ namespace Core
_settingsLoaded = playerSettings != null && interactionSettings != null && minigameSettings != null;
if (_settingsLoaded)
{
Logging.Debug("All settings loaded and registered with ServiceLocator");
LogDebugMessage("All settings loaded and registered with ServiceLocator", "SettingsInitialization", _settingsLogVerbosity);
}
else
{
@@ -213,7 +222,7 @@ namespace Core
/// </summary>
private void InitializeDeveloperSettings()
{
Logging.Debug("Starting developer settings initialization...");
LogDebugMessage("Starting developer settings initialization...", "SettingsInitialization", _settingsLogVerbosity);
// Load developer settings
var divingDevSettings = DeveloperSettingsProvider.Instance.GetSettings<DivingDeveloperSettings>();
@@ -223,7 +232,7 @@ namespace Core
if (_developerSettingsLoaded)
{
Logging.Debug("All developer settings loaded successfully");
LogDebugMessage("All developer settings loaded successfully", "SettingsInitialization", _settingsLogVerbosity);
}
else
{
@@ -258,6 +267,19 @@ namespace Core
return DeveloperSettingsProvider.Instance?.GetSettings<T>();
}
private void LogDebugMessage(string message, string prefix = "GameManager", LogVerbosity verbosity = LogVerbosity.None)
{
if (verbosity == LogVerbosity.None)
{
verbosity = _managerLogVerbosity;
}
if ( verbosity <= LogVerbosity.Debug)
{
Logging.Debug($"[{prefix}] {message}");
}
}
// LEFTOVER LEGACY SETTINGS
public float PlayerStopDistance => GetSettings<IInteractionSettings>()?.PlayerStopDistance ?? 6.0f;
public float PlayerStopDistanceDirectInteraction => GetSettings<IInteractionSettings>()?.PlayerStopDistanceDirectInteraction ?? 2.0f;

View File

@@ -13,7 +13,6 @@ namespace Core
public class ItemManager : MonoBehaviour
{
private static ItemManager _instance;
private static bool _isQuitting;
/// <summary>
/// Singleton instance of the ItemManager. No longer creates an instance if one doesn't exist.
@@ -73,11 +72,6 @@ namespace Core
ClearAllRegistrations();
}
void OnApplicationQuit()
{
_isQuitting = true;
}
private void OnSceneLoadStarted(string sceneName)
{
// Clear all registrations when a new scene is loaded, so no stale references persist

View File

@@ -16,17 +16,12 @@ namespace AppleHills.Core
{
#region Singleton Setup
private static QuickAccess _instance;
private static bool _isQuitting = false;
/// <summary>
/// Singleton instance of QuickAccess. No longer creates an instance if one doesn't exist.
/// </summary>
public static QuickAccess Instance => _instance;
void OnApplicationQuit()
{
_isQuitting = true;
}
#endregion Singleton Setup
#region Manager Instances

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using AppleHills.Core.Settings;
using UI;
using UnityEngine;
using UnityEngine.SceneManagement;
@@ -15,7 +16,6 @@ namespace Core
{
private LoadingScreenController _loadingScreen;
private static SceneManagerService _instance;
private static bool _isQuitting = false;
/// <summary>
/// Singleton instance of the SceneManagerService. No longer creates an instance if one doesn't exist.
@@ -32,6 +32,7 @@ namespace Core
private readonly Dictionary<string, AsyncOperation> _activeLoads = new();
private readonly Dictionary<string, AsyncOperation> _activeUnloads = new();
private LogVerbosity _logVerbosity = LogVerbosity.Debug;
private const string BootstrapSceneName = "BootstrapScene";
void Awake()
@@ -52,7 +53,12 @@ namespace Core
SceneManager.LoadScene(BootstrapSceneName, LoadSceneMode.Additive);
}
}
private void Start()
{
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().sceneLogVerbosity;
}
/// <summary>
/// Initialize current scene tracking immediately in Awake
/// This ensures scene management works correctly regardless of boot timing
@@ -68,19 +74,19 @@ namespace Core
if (activeScene.name != BootstrapSceneName)
{
CurrentGameplayScene = activeScene.name;
Logging.Debug($"[SceneManagerService] Initialized with current scene: {CurrentGameplayScene}");
LogDebugMessage($"Initialized with current scene: {CurrentGameplayScene}");
}
// Otherwise default to MainMenu
else
{
CurrentGameplayScene = "AppleHillsOverworld";
Logging.Debug($"[SceneManagerService] Initialized with default scene: {CurrentGameplayScene}");
LogDebugMessage($"Initialized with default scene: {CurrentGameplayScene}");
}
}
else
{
CurrentGameplayScene = "AppleHillsOverworld";
Logging.Debug($"[SceneManagerService] No valid active scene, defaulting to: {CurrentGameplayScene}");
LogDebugMessage($"No valid active scene, defaulting to: {CurrentGameplayScene}");
}
}
@@ -92,7 +98,7 @@ namespace Core
// Set up loading screen event handlers if available
SetupLoadingScreenEvents();
Logging.Debug($"[SceneManagerService] Post-boot initialization complete, current scene is: {CurrentGameplayScene}");
LogDebugMessage($"Post-boot initialization complete, current scene is: {CurrentGameplayScene}");
}
private void SetupLoadingScreenEvents()
@@ -103,11 +109,6 @@ namespace Core
SceneLoadCompleted += _ => _loadingScreen.HideLoadingScreen();
}
void OnApplicationQuit()
{
_isQuitting = true;
}
/// <summary>
/// Load a single scene asynchronously (additive).
/// </summary>
@@ -138,7 +139,7 @@ namespace Core
var scene = SceneManager.GetSceneByName(sceneName);
if (!scene.isLoaded)
{
Logging.Warning($"SceneManagerService: Attempted to unload scene '{sceneName}', but it is not loaded.");
Logging.Warning($"[SceneManagerService] Attempted to unload scene '{sceneName}', but it is not loaded.");
return;
}
SceneUnloadStarted?.Invoke(sceneName);
@@ -317,7 +318,7 @@ namespace Core
}
else
{
Logging.Warning($"SceneManagerService: Previous scene '{CurrentGameplayScene}' is not loaded, skipping unload.");
Logging.Warning($"[SceneManagerService] Previous scene '{CurrentGameplayScene}' is not loaded, skipping unload.");
}
}
// Ensure BootstrapScene is loaded before loading new scene
@@ -337,5 +338,13 @@ namespace Core
_loadingScreen.HideLoadingScreen();
}
}
private void LogDebugMessage(string message)
{
if (_logVerbosity <= LogVerbosity.Debug)
{
Logging.Debug($"[SceneManagerService] {message}");
}
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections;
using AppleHills.Core.Settings;
using Bootstrap;
using Input;
using Settings;
@@ -17,6 +18,7 @@ namespace Core
[Header("Config")]
public SceneOrientationConfig orientationConfig;
public GameObject orientationPromptPrefab;
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
void Awake()
{
@@ -33,11 +35,16 @@ namespace Core
}
#endif
}
private void Start()
{
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().sceneLogVerbosity;
}
private void InitializePostBoot()
{
// Initialize any dependencies that require other services to be ready
Logging.Debug("[SceneOrientationEnforcer] Post-boot initialization complete");
LogDebugMessage("Post-boot initialization complete");
// Subscribe to sceneLoaded event
SceneManager.sceneLoaded += OnSceneLoaded;
@@ -52,7 +59,7 @@ namespace Core
if (sceneName.ToLower().Contains("bootstrap"))
{
// Bootstrap being loaded additively, don't do anything
Logging.Debug($"[SceneOrientationEnforcer] Detected bootstrapped scene: '{sceneName}'. Skipping orientation enforcement.");
LogDebugMessage($"Detected bootstrapped scene: '{sceneName}'. Skipping orientation enforcement.");
return;
}
@@ -62,23 +69,23 @@ namespace Core
}
else
{
Logging.Debug($"[SceneOrientationEnforcer] No orientationConfig assigned. Defaulting to Landscape for scene '{sceneName}'");
LogDebugMessage($"No orientationConfig assigned. Defaulting to Landscape for scene '{sceneName}'");
}
switch (requirement)
{
case ScreenOrientationRequirement.Portrait:
Logging.Debug($"[SceneOrientationEnforcer] Forcing Portrait for scene '{sceneName}'");
LogDebugMessage($"Forcing Portrait for scene '{sceneName}'");
StartCoroutine(ForcePortrait());
break;
case ScreenOrientationRequirement.Landscape:
Logging.Debug($"[SceneOrientationEnforcer] Forcing Landscape for scene '{sceneName}'");
LogDebugMessage($"Forcing Landscape for scene '{sceneName}'");
StartCoroutine(ForceLandscape());
break;
case ScreenOrientationRequirement.NotApplicable:
default:
// Default to landscape when no specific requirement is found
Logging.Debug($"[SceneOrientationEnforcer] No specific orientation for scene '{sceneName}'. Defaulting to Landscape");
LogDebugMessage($"No specific orientation for scene '{sceneName}'. Defaulting to Landscape");
StartCoroutine(ForceLandscape());
break;
}
@@ -92,7 +99,7 @@ namespace Core
/// <summary>
/// Forces the game into landscape mode, allowing both LandscapeLeft and LandscapeRight.
/// </summary>
public static IEnumerator ForceLandscape()
public IEnumerator ForceLandscape()
{
// If we're already in a landscape orientation, nothing to do.
bool currentlyLandscape = Screen.orientation == ScreenOrientation.LandscapeLeft
@@ -100,12 +107,12 @@ namespace Core
if (!currentlyLandscape)
{
// Lock it to portrait and allow the device to orient itself
Logging.Debug($"[SceneOrientationEnforcer] Actually forcing Portrait from previous: {Screen.orientation}");
LogDebugMessage($"Actually forcing Portrait from previous: {Screen.orientation}");
Screen.orientation = ScreenOrientation.LandscapeRight;
}
else
{
Logging.Debug($"[SceneOrientationEnforcer] Skipping Landscape enforcement, device already in: {Screen.orientation}");
LogDebugMessage($"Skipping Landscape enforcement, device already in: {Screen.orientation}");
}
yield return null;
@@ -125,7 +132,7 @@ namespace Core
/// <summary>
/// Forces the game into portrait mode, allowing both Portrait and PortraitUpsideDown.
/// </summary>
public static IEnumerator ForcePortrait()
public IEnumerator ForcePortrait()
{
// If we're already in a portrait orientation, nothing to do.
bool currentlyPortrait = Screen.orientation == ScreenOrientation.Portrait
@@ -133,12 +140,12 @@ namespace Core
if (!currentlyPortrait)
{
// Lock it to portrait and allow the device to orient itself
Logging.Debug($"[SceneOrientationEnforcer] Actually forcing Portrait from previous: {Screen.orientation}");
LogDebugMessage($"Actually forcing Portrait from previous: {Screen.orientation}");
Screen.orientation = ScreenOrientation.PortraitUpsideDown;
}
else
{
Logging.Debug($"[SceneOrientationEnforcer] Skipping Portrait enforcement, device already in: {Screen.orientation}");
LogDebugMessage($"Skipping Portrait enforcement, device already in: {Screen.orientation}");
}
yield return null;
@@ -154,5 +161,13 @@ namespace Core
// Allow device to auto-rotate to correct portrait orientation
Screen.orientation = ScreenOrientation.AutoRotation;
}
private void LogDebugMessage(string message)
{
if (_logVerbosity <= LogVerbosity.Debug)
{
Logging.Debug($"[SceneOrientationEnforcer] {message}");
}
}
}
}

View File

@@ -7,11 +7,10 @@ namespace AppleHills.Core.Settings
/// </summary>
public enum LogVerbosity
{
None = 0,
Errors = 1,
Warnings = 2,
Info = 3,
Verbose = 4
None = -1,
Debug = 0,
Warning = 1,
Error = 2
}
/// <summary>
@@ -23,12 +22,26 @@ namespace AppleHills.Core.Settings
{
[Header("Visual Debugging Options")]
[Tooltip("Should debug messages be show on screen in Editor")]
[SerializeField] private bool showDebugUiMessages = false;
[SerializeField] public bool showDebugUiMessages = false;
[Header("Game Behavior Options")]
[Tooltip("Should Time.timeScale be set to 0 when the game is paused")]
[SerializeField] private bool pauseTimeOnPauseGame = true;
[SerializeField] public bool pauseTimeOnPauseGame = true;
[Header("Logging Options")]
[Tooltip("Logging level for bootstrap services")]
[SerializeField] public LogVerbosity bootstrapLogVerbosity = LogVerbosity.Warning;
[Tooltip("Logging level for settings-related services")]
[SerializeField] public LogVerbosity settingsLogVerbosity = LogVerbosity.Warning;
[Tooltip("Logging level for Game Manager")]
[SerializeField] public LogVerbosity gameManagerLogVerbosity = LogVerbosity.Warning;
[Tooltip("Logging level for Scene management services - orientation, loading etc.")]
[SerializeField] public LogVerbosity sceneLogVerbosity = LogVerbosity.Warning;
[Tooltip("Logging level for Scene Orientation Enforcer")]
[SerializeField] public LogVerbosity saveLoadLogVerbosity = LogVerbosity.Warning;
[Tooltip("Logging level for Input management services")]
[SerializeField] public LogVerbosity inputLogVerbosity = LogVerbosity.Warning;
// Property getters
public bool ShowDebugUiMessages => showDebugUiMessages;
public bool PauseTimeOnPauseGame => pauseTimeOnPauseGame;

View File

@@ -87,10 +87,6 @@ namespace AppleHills.Core.Settings
[Tooltip("Maximum normalized movement speed allowed for tiles")]
[SerializeField] private float maxNormalizedTileMoveSpeed = 1.2f;
// Legacy settings - keeping for backward compatibility
[HideInInspector] [SerializeField] private float moveSpeed = 3f;
[HideInInspector] [SerializeField] private float maxMoveSpeed = 12f;
[Tooltip("Interval for velocity calculations (seconds)")]
[SerializeField] private float velocityCalculationInterval = 0.5f;

View File

@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using Core;
using AppleHills.Core.Settings;
using UnityEngine;
namespace AppleHills.Core.Settings
namespace Core.Settings
{
/// <summary>
/// Service Locator implementation for managing settings services.
@@ -11,7 +11,7 @@ namespace AppleHills.Core.Settings
/// </summary>
public static class ServiceLocator
{
private static readonly Dictionary<Type, object> _services = new Dictionary<Type, object>();
private static readonly Dictionary<Type, object> Services = new Dictionary<Type, object>();
/// <summary>
/// Register a service with the service locator.
@@ -20,8 +20,8 @@ namespace AppleHills.Core.Settings
/// <param name="service">The service implementation</param>
public static void Register<T>(T service) where T : class
{
_services[typeof(T)] = service;
Logging.Debug($"Service registered: {typeof(T).Name}");
Services[typeof(T)] = service;
LogDebugMessage($"Service registered: {typeof(T).Name}");
}
/// <summary>
@@ -31,12 +31,12 @@ namespace AppleHills.Core.Settings
/// <returns>The service implementation, or null if not found</returns>
public static T Get<T>() where T : class
{
if (_services.TryGetValue(typeof(T), out object service))
if (Services.TryGetValue(typeof(T), out object service))
{
return service as T;
}
Logging.Warning($"Service of type {typeof(T).Name} not found!");
Logging.Warning($"[ServiceLocator] Service of type {typeof(T).Name} not found!");
return null;
}
@@ -45,8 +45,17 @@ namespace AppleHills.Core.Settings
/// </summary>
public static void Clear()
{
_services.Clear();
Logging.Debug("All services cleared");
Services.Clear();
LogDebugMessage("All services cleared");
}
private static void LogDebugMessage(string message)
{
if (DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().settingsLogVerbosity <=
LogVerbosity.Debug)
{
Logging.Debug($"[ServiceLocator] {message}");
}
}
}
}

View File

@@ -35,6 +35,11 @@ namespace AppleHills
public static float GetPlayerStopDistance()
{
#if UNITY_EDITOR
if (getPlayerStopDistanceProvider == null)
{
return 0.0f;
}
if (!Application.isPlaying && getPlayerStopDistanceProvider != null)
{
return getPlayerStopDistanceProvider();

View File

@@ -19,7 +19,6 @@ namespace Data.CardSystem
public class CardSystemManager : MonoBehaviour
{
private static CardSystemManager _instance;
private static bool _isQuitting = false;
public static CardSystemManager Instance => _instance;
[Header("Card Collection")]
@@ -56,11 +55,6 @@ namespace Data.CardSystem
Logging.Debug("[CardSystemManager] Post-boot initialization complete");
}
private void OnApplicationQuit()
{
_isQuitting = true;
}
/// <summary>
/// Loads all card definitions from Addressables using the "BlokkemonCard" label
/// </summary>

View File

@@ -33,8 +33,6 @@ namespace Dialogue
public bool IsCompleted { get; private set; }
public string CurrentSpeakerName => dialogueGraph?.speakerName;
// Event for UI updates if needed
public event Action<string> OnDialogueChanged;
private void Start()
{

View File

@@ -28,7 +28,6 @@ namespace Input
private const string GameActions = "PlayerTouch";
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>();
@@ -50,6 +49,7 @@ namespace Input
private InputAction positionAction;
private ITouchInputConsumer defaultConsumer;
private bool isHoldActive;
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
void Awake()
{
@@ -58,7 +58,12 @@ namespace Input
// Register for post-boot initialization
BootCompletionService.RegisterInitAction(InitializePostBoot);
}
private void Start()
{
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().inputLogVerbosity;
}
private void InitializePostBoot()
{
// Subscribe to scene load completed events now that boot is complete
@@ -86,8 +91,6 @@ namespace Input
}
SwitchInputOnSceneLoaded(SceneManager.GetActiveScene().name);
Logging.Debug("[InputManager] Subscribed to SceneManagerService events");
}
private void OnDestroy()
@@ -101,12 +104,10 @@ namespace Input
{
if (sceneName.ToLower().Contains("mainmenu"))
{
Logging.Debug("[InputManager] SwitchInputOnSceneLoaded - Setting InputMode to UI for MainMenu");
SetInputMode(InputMode.GameAndUI);
}
else
{
Logging.Debug("[InputManager] SwitchInputOnSceneLoaded - Setting InputMode to PlayerTouch");
SetInputMode(InputMode.GameAndUI);
}
}
@@ -144,11 +145,6 @@ namespace Input
holdMoveAction.canceled -= OnHoldMoveCanceled;
}
}
void OnApplicationQuit()
{
_isQuitting = true;
}
/// <summary>
/// Sets the default ITouchInputConsumer to receive input events.
@@ -166,24 +162,24 @@ namespace Input
Vector2 screenPos = positionAction.ReadValue<Vector2>();
Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos);
Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y);
Logging.Debug($"[InputManager] TapMove performed at {worldPos2D}");
LogDebugMessage($"TapMove performed at {worldPos2D}");
// First try to delegate to an override consumer if available
if (TryDelegateToOverrideConsumer(screenPos, worldPos2D))
{
Logging.Debug("[InputManager] Tap delegated to override consumer");
LogDebugMessage("Tap delegated to override consumer");
return;
}
// Then try to delegate to any ITouchInputConsumer (UI or world interactable)
if (!TryDelegateToAnyInputConsumer(screenPos, worldPos2D))
{
Logging.Debug("[InputManager] No input consumer found, forwarding tap to default consumer");
LogDebugMessage("No input consumer found, forwarding tap to default consumer");
defaultConsumer?.OnTap(worldPos2D);
}
else
{
Logging.Debug("[InputManager] Tap delegated to input consumer");
LogDebugMessage("Tap delegated to input consumer");
}
}
@@ -196,13 +192,13 @@ namespace Input
Vector2 screenPos = positionAction.ReadValue<Vector2>();
Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos);
Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y);
Logging.Debug($"[InputManager] HoldMove started at {worldPos2D}");
LogDebugMessage($"HoldMove started at {worldPos2D}");
// First check for override consumers
if (_overrideConsumers.Count > 0)
{
_activeHoldConsumer = _overrideConsumers[_overrideConsumers.Count - 1];
Logging.Debug($"[InputManager] Hold delegated to override consumer: {_activeHoldConsumer}");
LogDebugMessage($"Hold delegated to override consumer: {_activeHoldConsumer}");
_activeHoldConsumer.OnHoldStart(worldPos2D);
return;
}
@@ -222,7 +218,7 @@ namespace Input
Vector2 screenPos = positionAction.ReadValue<Vector2>();
Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos);
Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y);
Logging.Debug($"[InputManager] HoldMove canceled at {worldPos2D}");
LogDebugMessage($"HoldMove canceled at {worldPos2D}");
// Notify the active hold consumer that the hold has ended
_activeHoldConsumer?.OnHoldEnd(worldPos2D);
@@ -239,7 +235,7 @@ namespace Input
Vector2 screenPos = positionAction.ReadValue<Vector2>();
Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos);
Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y);
// Logging.Debug($"[InputManager] HoldMove update at {worldPos2D}");
// LogDebugMessage($"HoldMove update at {worldPos2D}");
// Send hold move updates to the active hold consumer
_activeHoldConsumer?.OnHoldMove(worldPos2D);
@@ -286,7 +282,7 @@ namespace Input
}
if (consumer != null)
{
Logging.Debug($"[InputManager] Delegating tap to UI consumer at {screenPos} (GameObject: {result.gameObject.name})");
LogDebugMessage($"Delegating tap to UI consumer at {screenPos} (GameObject: {result.gameObject.name})");
consumer.OnTap(screenPos);
return true;
}
@@ -315,7 +311,7 @@ namespace Input
}
if (consumer != null)
{
Logging.Debug($"[InputManager] Delegating tap to consumer at {worldPos} (GameObject: {hitWithMask.gameObject.name})");
LogDebugMessage($"Delegating tap to consumer at {worldPos} (GameObject: {hitWithMask.gameObject.name})");
consumer.OnTap(worldPos);
return true;
}
@@ -329,15 +325,15 @@ namespace Input
var consumer = hit.GetComponent<ITouchInputConsumer>();
if (consumer != null)
{
Logging.Debug($"[InputManager] Delegating tap to consumer at {worldPos} (GameObject: {hit.gameObject.name})");
LogDebugMessage($"Delegating tap to consumer at {worldPos} (GameObject: {hit.gameObject.name})");
consumer.OnTap(worldPos);
return true;
}
Logging.Debug($"[InputManager] Collider2D hit at {worldPos} (GameObject: {hit.gameObject.name}), but no ITouchInputConsumer found.");
LogDebugMessage($"Collider2D hit at {worldPos} (GameObject: {hit.gameObject.name}), but no ITouchInputConsumer found.");
}
else
{
Logging.Debug($"[InputManager] No Collider2D found at {worldPos} for interactable delegation.");
LogDebugMessage($"No Collider2D found at {worldPos} for interactable delegation.");
}
return false;
}
@@ -352,7 +348,7 @@ namespace Input
return;
_overrideConsumers.Add(consumer);
Logging.Debug($"[InputManager] Override consumer registered: {consumer}");
LogDebugMessage($"Override consumer registered: {consumer}");
}
/// <summary>
@@ -370,7 +366,7 @@ namespace Input
}
_overrideConsumers.Remove(consumer);
Logging.Debug($"[InputManager] Override consumer unregistered: {consumer}");
LogDebugMessage($"Override consumer unregistered: {consumer}");
}
/// <summary>
@@ -380,7 +376,7 @@ namespace Input
{
_activeHoldConsumer = null;
_overrideConsumers.Clear();
Logging.Debug("[InputManager] All override consumers cleared.");
LogDebugMessage("All override consumers cleared.");
}
/// <summary>
@@ -393,9 +389,17 @@ namespace Input
// Get the topmost override consumer (last registered)
var consumer = _overrideConsumers[_overrideConsumers.Count - 1];
Logging.Debug($"[InputManager] Delegating tap to override consumer at {worldPos} (GameObject: {consumer})");
LogDebugMessage($"Delegating tap to override consumer at {worldPos} (GameObject: {consumer})");
consumer.OnTap(worldPos);
return true;
}
private void LogDebugMessage(string message)
{
if (_logVerbosity <= LogVerbosity.Debug)
{
Logging.Debug($"[InputManager] {message}");
}
}
}
}

View File

@@ -53,6 +53,7 @@ namespace Input
public event ArrivedAtTargetHandler OnArrivedAtTarget;
public event System.Action OnMoveToCancelled;
private bool interruptMoveTo;
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
void Awake()
{
@@ -75,6 +76,7 @@ namespace Input
void Start()
{
InputManager.Instance?.SetDefaultConsumer(this);
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().inputLogVerbosity;
}
/// <summary>
@@ -84,7 +86,7 @@ namespace Input
public void OnTap(Vector2 worldPosition)
{
InterruptMoveTo();
Logging.Debug($"[PlayerTouchController] OnTap at {worldPosition}");
LogDebugMessage($"OnTap at {worldPosition}");
if (aiPath != null)
{
aiPath.enabled = true;
@@ -103,7 +105,7 @@ namespace Input
public void OnHoldStart(Vector2 worldPosition)
{
InterruptMoveTo();
Logging.Debug($"[PlayerTouchController] OnHoldStart at {worldPosition}");
LogDebugMessage($"OnHoldStart at {worldPosition}");
lastHoldPosition = worldPosition;
isHolding = true;
if (_settings.DefaultHoldMovementMode == HoldMovementMode.Pathfinding &&
@@ -140,7 +142,7 @@ namespace Input
/// </summary>
public void OnHoldEnd(Vector2 worldPosition)
{
Logging.Debug($"[PlayerTouchController] OnHoldEnd at {worldPosition}");
LogDebugMessage($"OnHoldEnd at {worldPosition}");
isHolding = false;
directMoveVelocity = Vector3.zero;
if (aiPath != null && _settings.DefaultHoldMovementMode ==
@@ -316,13 +318,13 @@ namespace Input
{
_isMoving = true;
OnMovementStarted?.Invoke();
Logging.Debug("[PlayerTouchController] Movement started");
LogDebugMessage("Movement started");
}
else if (!isCurrentlyMoving && _isMoving)
{
_isMoving = false;
OnMovementStopped?.Invoke();
Logging.Debug("[PlayerTouchController] Movement stopped");
LogDebugMessage("Movement stopped");
}
}
@@ -405,5 +407,13 @@ namespace Input
OnArrivedAtTarget?.Invoke();
}
}
private void LogDebugMessage(string message)
{
if (_logVerbosity <= LogVerbosity.Debug)
{
Logging.Debug($"[PlayerTouchController] {message}");
}
}
}
}

View File

@@ -378,14 +378,12 @@ namespace Interactions
Logging.Debug("[Interactable] All InteractingCharacterArrived actions completed, proceeding with interaction");
// Check if we have any components that might have paused the interaction flow
bool hasTimelineActions = false;
foreach (var action in _registeredActions)
{
if (action is InteractionTimelineAction timelineAction &&
timelineAction.respondToEvents.Contains(InteractionEventType.InteractingCharacterArrived) &&
timelineAction.pauseInteractionFlow)
{
hasTimelineActions = true;
break;
}
}
@@ -414,7 +412,7 @@ namespace Interactions
_ = OnPlayerMoveCancelledAsync();
}
private async Task BroadcastCharacterArrivedAsync()
private Task BroadcastCharacterArrivedAsync()
{
// Check for ObjectiveStepBehaviour and lock state
var step = GetComponent<PuzzleS.ObjectiveStepBehaviour>();
@@ -427,7 +425,7 @@ namespace Interactions
_interactionInProgress = false;
_playerRef = null;
_followerController = null;
return;
return Task.CompletedTask;
}
// Dispatch CharacterArrived event
@@ -440,6 +438,7 @@ namespace Interactions
_interactionInProgress = false;
_playerRef = null;
_followerController = null;
return Task.CompletedTask;
}
private async void OnInteractionComplete(bool success)

View File

@@ -1,24 +0,0 @@
using UnityEngine;
/// <summary>
/// ScriptableObject holding data for a level switch (scene name, description, icon).
/// </summary>
[CreateAssetMenu(fileName = "LevelSwitchData", menuName = "AppleHills/Items & Puzzles/Level Switch Data")]
public class LevelSwitchData : ScriptableObject
{
/// <summary>
/// The name of the target scene to switch to.
/// </summary>
public string targetLevelSceneName;
/// <summary>
/// Description of the level switch.
/// </summary>
[TextArea]
public string description;
/// <summary>
/// Icon to display for this level switch.
/// </summary>
public Sprite mapSprite;
}

View File

@@ -1,53 +0,0 @@
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System;
/// <summary>
/// UI overlay for confirming a level switch. Displays level info and handles confirm/cancel actions.
/// </summary>
public class LevelSwitchMenu : MonoBehaviour
{
[Header("UI References")]
public Image iconImage;
public TMP_Text levelNameText;
public Button confirmButton;
public Button cancelButton;
private Action _onConfirm;
private Action _onCancel;
private LevelSwitchData _switchData;
/// <summary>
/// Initialize the menu with data and callbacks.
/// </summary>
public void Setup(LevelSwitchData switchData, Action onConfirm, Action onCancel)
{
_switchData = switchData;
_onConfirm = onConfirm;
_onCancel = onCancel;
if (iconImage) iconImage.sprite = switchData?.mapSprite;
if (levelNameText) levelNameText.text = switchData?.targetLevelSceneName ?? "";
if (confirmButton) confirmButton.onClick.AddListener(OnConfirmClicked);
if (cancelButton) cancelButton.onClick.AddListener(OnCancelClicked);
}
private void OnDestroy()
{
if (confirmButton) confirmButton.onClick.RemoveListener(OnConfirmClicked);
if (cancelButton) cancelButton.onClick.RemoveListener(OnCancelClicked);
}
private void OnConfirmClicked()
{
_onConfirm?.Invoke();
Destroy(gameObject);
}
private void OnCancelClicked()
{
_onCancel?.Invoke();
Destroy(gameObject);
}
}

View File

@@ -3,11 +3,12 @@ using AppleHills.Core.Settings;
using Core;
using Input;
using Interactions;
using System.Threading.Tasks;
using UnityEngine;
// Added for IInteractionSettings
namespace LevelS
namespace Levels
{
/// <summary>
/// Handles level switching when interacted with. Applies switch data and triggers scene transitions.
@@ -107,18 +108,35 @@ namespace LevelS
return;
}
// Setup menu with data and callbacks
menu.Setup(switchData, OnMenuConfirm, OnMenuCancel);
menu.Setup(switchData, OnLevelSelectedWrapper, OnMinigameSelected, OnMenuCancel, OnRestartSelected);
_isActive = false; // Prevent re-triggering until menu is closed
// Switch input mode to UI only
InputManager.Instance.SetInputMode(InputMode.UI);
}
private async void OnMenuConfirm()
private void OnLevelSelectedWrapper()
{
_ = OnLevelSelected();
}
private async Task OnLevelSelected()
{
var progress = new Progress<float>(p => Logging.Debug($"Loading progress: {p * 100:F0}%"));
await SceneManagerService.Instance.SwitchSceneAsync(switchData.targetLevelSceneName, progress);
}
private async void OnMinigameSelected()
{
var progress = new Progress<float>(p => Logging.Debug($"Loading progress: {p * 100:F0}%"));
await SceneManagerService.Instance.SwitchSceneAsync(switchData.targetMinigameSceneName, progress);
}
private async void OnRestartSelected()
{
// TODO: Restart level here
await OnLevelSelected();
}
private void OnMenuCancel()
{

View File

@@ -0,0 +1,32 @@
using UnityEngine;
namespace Levels
{
/// <summary>
/// ScriptableObject holding data for a level switch (scene name, description, icon).
/// </summary>
[CreateAssetMenu(fileName = "LevelSwitchData", menuName = "AppleHills/Items & Puzzles/Level Switch Data")]
public class LevelSwitchData : ScriptableObject
{
/// <summary>
/// The name of the target scene to switch to.
/// </summary>
public string targetLevelSceneName;
/// <summary>
/// The name of the minigame scene to switch to.
/// </summary>
public string targetMinigameSceneName;
/// <summary>
/// Description of the level switch.
/// </summary>
[TextArea]
public string description;
/// <summary>
/// Icon to display for this level switch.
/// </summary>
public Sprite mapSprite;
}
}

View File

@@ -0,0 +1,110 @@
using System;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace Levels
{
/// <summary>
/// UI overlay for confirming a level switch. Displays level info and handles confirm/cancel actions.
/// </summary>
public class LevelSwitchMenu : MonoBehaviour
{
[Header("UI References")]
public Image iconImage;
public TMP_Text levelNameText;
public Button confirmButton;
public Button cancelButton;
public Button minigameButton;
public GameObject padlockIcon;
public Button restartButton;
public GameObject popupConfirmMenu;
public Button popupConfirmButton;
public Button popupCancelButton;
public Image tintTargetImage;
public Color popupTintColor = new Color(0.5f, 0.5f, 0.5f, 1f); // grey by default
private Color _originalTintColor;
private Action _onRestart;
private Action _onLevelConfirm;
private Action _onMinigameConfirm;
private Action _onCancel;
private LevelSwitchData _switchData;
/// <summary>
/// Initialize the menu with data and callbacks.
/// </summary>
public void Setup(LevelSwitchData switchData, Action onLevelConfirm, Action onMinigameConfirm, Action onCancel, Action onRestart = null)
{
_switchData = switchData;
_onLevelConfirm = onLevelConfirm;
_onMinigameConfirm = onMinigameConfirm;
_onCancel = onCancel;
_onRestart = onRestart;
if (iconImage) iconImage.sprite = switchData?.mapSprite;
if (levelNameText) levelNameText.text = switchData?.targetLevelSceneName ?? "";
if (confirmButton) confirmButton.onClick.AddListener(OnConfirmClicked);
if (cancelButton) cancelButton.onClick.AddListener(OnCancelClicked);
if (minigameButton)
{
minigameButton.onClick.AddListener(OnMinigameClicked);
bool minigameUnlocked = true;
minigameButton.interactable = !minigameUnlocked;
padlockIcon.SetActive(!minigameUnlocked);
}
if (restartButton) restartButton.onClick.AddListener(OnRestartClicked);
if (popupConfirmMenu) popupConfirmMenu.SetActive(false);
if (tintTargetImage) _originalTintColor = tintTargetImage.color;
if (popupConfirmButton) popupConfirmButton.onClick.AddListener(OnPopupConfirmClicked);
if (popupCancelButton) popupCancelButton.onClick.AddListener(OnPopupCancelClicked);
}
private void OnDestroy()
{
if (confirmButton) confirmButton.onClick.RemoveListener(OnConfirmClicked);
if (cancelButton) cancelButton.onClick.RemoveListener(OnCancelClicked);
if (minigameButton) minigameButton.onClick.RemoveListener(OnMinigameClicked);
if (restartButton) restartButton.onClick.RemoveListener(OnRestartClicked);
if (popupConfirmButton) popupConfirmButton.onClick.RemoveListener(OnPopupConfirmClicked);
if (popupCancelButton) popupCancelButton.onClick.RemoveListener(OnPopupCancelClicked);
}
private void OnConfirmClicked()
{
_onLevelConfirm?.Invoke();
Destroy(gameObject);
}
private void OnMinigameClicked()
{
_onMinigameConfirm?.Invoke();
Destroy(gameObject);
}
private void OnCancelClicked()
{
_onCancel?.Invoke();
Destroy(gameObject);
}
private void OnRestartClicked()
{
if (popupConfirmMenu) popupConfirmMenu.SetActive(true);
if (tintTargetImage) tintTargetImage.color = popupTintColor;
}
private void OnPopupCancelClicked()
{
if (popupConfirmMenu) popupConfirmMenu.SetActive(false);
if (tintTargetImage) tintTargetImage.color = _originalTintColor;
}
private void OnPopupConfirmClicked()
{
_onRestart?.Invoke();
if (popupConfirmMenu) popupConfirmMenu.SetActive(false);
if (tintTargetImage) tintTargetImage.color = _originalTintColor;
}
}
}

View File

@@ -1,12 +1,11 @@
using System;
using System.Collections;
using UnityEngine;
using AppleHills.Core.Settings;
using System.Collections;
using AppleHills.Core.Interfaces;
using AppleHills.Core.Settings;
using Core;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Minigames.DivingForPictures
namespace Minigames.DivingForPictures.Bubbles
{
/// <summary>
/// Spawns bubbles at intervals, randomizing their properties and assigning a random sprite to each.
@@ -45,9 +44,9 @@ namespace Minigames.DivingForPictures
if (_devSettings.BubbleUseObjectPooling)
{
// Create the bubble pool
GameObject poolGO = new GameObject("BubblePool");
poolGO.transform.SetParent(transform);
_bubblePool = poolGO.AddComponent<BubblePool>();
GameObject poolGo = new GameObject("BubblePool");
poolGo.transform.SetParent(transform);
_bubblePool = poolGo.AddComponent<BubblePool>();
_bubblePool.initialPoolSize = _devSettings.BubbleInitialPoolSize;
_bubblePool.maxPoolSize = _devSettings.BubbleMaxPoolSize;
_bubblePool.Initialize(bubblePrefab);
@@ -89,7 +88,7 @@ namespace Minigames.DivingForPictures
}
// Pause all active bubbles
Bubble[] activeBubbles = FindObjectsOfType<Bubble>();
Bubble[] activeBubbles = FindObjectsByType<Bubble>(FindObjectsSortMode.None);
foreach (var bubble in activeBubbles)
{
if (bubble != null)
@@ -110,7 +109,7 @@ namespace Minigames.DivingForPictures
StartSpawningCoroutine();
// Resume all active bubbles
Bubble[] activeBubbles = FindObjectsOfType<Bubble>();
Bubble[] activeBubbles = FindObjectsByType<Bubble>(FindObjectsSortMode.None);
foreach (var bubble in activeBubbles)
{
if (bubble != null)

View File

@@ -8,6 +8,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using Bootstrap;
using Minigames.DivingForPictures.Bubbles;
using UI;
using UI.Core;
using UnityEngine;
@@ -97,7 +98,6 @@ namespace Minigames.DivingForPictures
public event Action<Monster, float> OnPhotoSequenceCompleted; // Now includes proximity score
private static DivingGameManager _instance = null;
private static bool _isQuitting = false;
public AudioSource deathAudioPlayer;
public CameraViewfinderManager cameraViewfinderManager;
@@ -122,11 +122,6 @@ namespace Minigames.DivingForPictures
_isGameOver = false;
}
private void OnApplicationQuit()
{
_isQuitting = true;
}
private void Start()
{
// Register for post-boot initialization

View File

@@ -15,13 +15,11 @@ namespace Minigames.DivingForPictures.PictureCamera
{
// Singleton instance
private static CameraViewfinderManager _instance;
private static bool _isQuitting = false;
public static CameraViewfinderManager Instance
{
get
{
if (_instance == null && Application.isPlaying && !_isQuitting)
if (_instance == null && Application.isPlaying)
{
_instance = FindAnyObjectByType<CameraViewfinderManager>();
if (_instance == null)
@@ -89,11 +87,6 @@ namespace Minigames.DivingForPictures.PictureCamera
}
}
private void OnApplicationQuit()
{
_isQuitting = true;
}
private void Start()
{
settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();

View File

@@ -11,7 +11,6 @@ namespace Minigames.DivingForPictures
/// </summary>
public class TileBumpCollision : PlayerCollisionBehavior
{
private bool _isBumping;
private Coroutine _bumpCoroutine;
protected override void HandleCollisionResponse(Collider2D obstacle)
@@ -98,8 +97,6 @@ namespace Minigames.DivingForPictures
_bumpCoroutine = null;
}
_isBumping = true;
// Start bump coroutine
_bumpCoroutine = StartCoroutine(BumpCoroutine(startX, targetX, duration));
}
@@ -142,7 +139,6 @@ namespace Minigames.DivingForPictures
}
// Bump finished
_isBumping = false;
_bumpCoroutine = null;
Logging.Debug("[TileBumpCollision] Bump movement completed");

View File

@@ -73,9 +73,6 @@ namespace Minigames.DivingForPictures
// Screen normalization
private float _screenNormalizationFactor = 1.0f;
// Tracks if a floating area in the middle is currently active
private bool isFloatingAreaActive = false;
// Current depth of the trench
private int _currentDepth = 0;
@@ -714,20 +711,6 @@ namespace Minigames.DivingForPictures
_currentDepth++;
Logging.Debug($"[TrenchTileSpawner] Current Depth: {_currentDepth}");
onTileSpawned?.Invoke(tile);
// --- FLOATING AREA STATE MANAGEMENT ---
Tile spawnedTile = tile.GetComponent<Tile>();
if (spawnedTile != null)
{
if (spawnedTile.hasFloatingAreaMiddle || spawnedTile.continuesFloatingAreaMiddle)
{
isFloatingAreaActive = true;
}
if (spawnedTile.endsFloatingAreaMiddle)
{
isFloatingAreaActive = false;
}
}
}
/// <summary>
@@ -776,19 +759,6 @@ namespace Minigames.DivingForPictures
_currentDepth++;
Logging.Debug($"[TrenchTileSpawner] Current Depth: {_currentDepth}");
onTileSpawned?.Invoke(tile);
// Optionally update floating area state if needed
Tile spawnedTile = tile.GetComponent<Tile>();
if (spawnedTile != null)
{
if (spawnedTile.hasFloatingAreaMiddle || spawnedTile.continuesFloatingAreaMiddle)
{
isFloatingAreaActive = true;
}
if (spawnedTile.endsFloatingAreaMiddle)
{
isFloatingAreaActive = false;
}
}
}
/// <summary>

View File

@@ -19,7 +19,6 @@ namespace PuzzleS
public class PuzzleManager : MonoBehaviour
{
private static PuzzleManager _instance;
private static bool _isQuitting;
[SerializeField] private float proximityCheckInterval = 0.02f;
@@ -496,10 +495,5 @@ namespace PuzzleS
{
return _isDataLoaded;
}
void OnApplicationQuit()
{
_isQuitting = true;
}
}
}

View File

@@ -28,7 +28,6 @@ namespace UI.CardSystem
[Header("Animation Settings")]
[SerializeField] private float cardRevealDelay = 0.3f;
[SerializeField] private float cardMoveToBackpackDelay = 0.8f;
[SerializeField] private float flipAnimationDuration = 0.5f;
// State tracking
@@ -616,7 +615,7 @@ namespace UI.CardSystem
if (_cardAlbumUI == null)
{
_cardAlbumUI = FindObjectOfType<CardAlbumUI>();
_cardAlbumUI = FindFirstObjectByType<CardAlbumUI>();
}
// Re-cache card backs in case they changed while disabled

View File

@@ -17,12 +17,6 @@ namespace UI.CardSystem
[Tooltip("The GameObject to show/hide. Defaults to this GameObject if not assigned.")]
[SerializeField] private GameObject targetRoot;
[Header("Rules")]
[Tooltip("The scene name in which the Card System should be hidden.")]
[SerializeField] private string startingSceneName = "StartingScene";
[Tooltip("Also hide when SceneManagerService reports the Bootstrap scene.")]
[SerializeField] private bool hideInBootstrapScene = true;
private void Awake()
{
if (targetRoot == null)
@@ -64,6 +58,7 @@ namespace UI.CardSystem
private void ApplyVisibility(string sceneName)
{
// TODO: Implement actual visibility logic based on sceneName
SetActiveSafe(true);
// if (targetRoot == null)
// return;

View File

@@ -27,7 +27,6 @@ namespace UI
private Action _onLoadingScreenFullyHidden;
private static LoadingScreenController _instance;
private static bool _isQuitting;
/// <summary>
/// Delegate for providing progress values from different sources