Compare commits
27 Commits
hud_unific
...
7307971748
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7307971748 | ||
|
|
9a6914b9bd | ||
| 0aa2270e1a | |||
|
|
c4d356886f | ||
|
|
64d7f19b83 | ||
| ce21e8b02e | |||
| f44f8c5171 | |||
| 9772206362 | |||
|
|
3ebbecc277 | ||
|
|
c99aad49f3 | ||
| 3fe4c6afd9 | |||
| 9c61065947 | |||
|
|
7c09db641a | ||
|
|
e369660a8f | ||
| a6e3413499 | |||
| 7bb992acb8 | |||
|
|
cefa488a92 | ||
| 9344f06886 | |||
| af7e081c9a | |||
|
|
4a6ac7281f | ||
| 861797ba41 | |||
| 98883bd382 | |||
| 474941f421 | |||
|
|
75cd70a18a | ||
| e82ec90723 | |||
|
|
252cb99884 | ||
| 3f548c3ed4 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -104,3 +104,6 @@ InitTestScene*.unity*
|
|||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
.idea/.idea.AppleHillsProduction/.idea/indexLayout.xml
|
.idea/.idea.AppleHillsProduction/.idea/indexLayout.xml
|
||||||
|
|
||||||
|
# WIP docs
|
||||||
|
/docs/wip/
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ MonoBehaviour:
|
|||||||
m_DefaultGroup: 6f3207429a65b3e4b83935ac19791077
|
m_DefaultGroup: 6f3207429a65b3e4b83935ac19791077
|
||||||
m_currentHash:
|
m_currentHash:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
Hash: f08b6489862aaf7bfceb29f571e2ef6c
|
Hash: 589e22fe6cd2fe0e25d89bd44a35bcbc
|
||||||
m_OptimizeCatalogSize: 0
|
m_OptimizeCatalogSize: 0
|
||||||
m_BuildRemoteCatalog: 0
|
m_BuildRemoteCatalog: 0
|
||||||
m_CatalogRequestsTimeout: 0
|
m_CatalogRequestsTimeout: 0
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ namespace AppleHills.Editor
|
|||||||
{
|
{
|
||||||
CardSystemManager.Instance.OnBoosterOpened += OnBoosterOpened;
|
CardSystemManager.Instance.OnBoosterOpened += OnBoosterOpened;
|
||||||
CardSystemManager.Instance.OnCardCollected += OnCardCollected;
|
CardSystemManager.Instance.OnCardCollected += OnCardCollected;
|
||||||
CardSystemManager.Instance.OnCardRarityUpgraded += OnCardRarityUpgraded;
|
|
||||||
CardSystemManager.Instance.OnBoosterCountChanged += OnBoosterCountChanged;
|
CardSystemManager.Instance.OnBoosterCountChanged += OnBoosterCountChanged;
|
||||||
|
|
||||||
isSubscribed = true;
|
isSubscribed = true;
|
||||||
@@ -87,7 +86,6 @@ namespace AppleHills.Editor
|
|||||||
{
|
{
|
||||||
CardSystemManager.Instance.OnBoosterOpened -= OnBoosterOpened;
|
CardSystemManager.Instance.OnBoosterOpened -= OnBoosterOpened;
|
||||||
CardSystemManager.Instance.OnCardCollected -= OnCardCollected;
|
CardSystemManager.Instance.OnCardCollected -= OnCardCollected;
|
||||||
CardSystemManager.Instance.OnCardRarityUpgraded -= OnCardRarityUpgraded;
|
|
||||||
CardSystemManager.Instance.OnBoosterCountChanged -= OnBoosterCountChanged;
|
CardSystemManager.Instance.OnBoosterCountChanged -= OnBoosterCountChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,13 +107,6 @@ namespace AppleHills.Editor
|
|||||||
Repaint();
|
Repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCardRarityUpgraded(CardData card)
|
|
||||||
{
|
|
||||||
lastEventMessage = $"Card upgraded: {card.Name} → {card.Rarity}!";
|
|
||||||
RefreshData();
|
|
||||||
Repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnBoosterCountChanged(int count)
|
private void OnBoosterCountChanged(int count)
|
||||||
{
|
{
|
||||||
boosterCount = count;
|
boosterCount = count;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
|
|
||||||
namespace Interactions
|
namespace Interactions
|
||||||
|
|||||||
829
Assets/Editor/CustomLogWindow.cs
Normal file
829
Assets/Editor/CustomLogWindow.cs
Normal file
@@ -0,0 +1,829 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using Core;
|
||||||
|
|
||||||
|
namespace Editor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Custom dockable log window with advanced filtering capabilities.
|
||||||
|
/// Supports filtering by class, method, log level, time range, and text search.
|
||||||
|
/// Multiple instances can be opened with independent filter states.
|
||||||
|
///
|
||||||
|
/// PERFORMANCE NOTE: For large log counts (10,000+), consider implementing virtualized scrolling.
|
||||||
|
/// Only render visible entries within the scroll view to avoid GUI overhead.
|
||||||
|
/// See DrawLogEntries() method for potential optimization location.
|
||||||
|
/// </summary>
|
||||||
|
public class CustomLogWindow : EditorWindow
|
||||||
|
{
|
||||||
|
#region Window State
|
||||||
|
|
||||||
|
private Vector2 scrollPosition;
|
||||||
|
private readonly List<LogEntry> allLogs = new List<LogEntry>();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Filter State
|
||||||
|
|
||||||
|
private HashSet<string> activeClassTags = new HashSet<string>();
|
||||||
|
private HashSet<string> activeMethodTags = new HashSet<string>();
|
||||||
|
private HashSet<string> selectedClassFilters = new HashSet<string>();
|
||||||
|
private HashSet<string> selectedMethodFilters = new HashSet<string>();
|
||||||
|
private HashSet<LogLevel> selectedLevelFilters = new HashSet<LogLevel>
|
||||||
|
{
|
||||||
|
LogLevel.Debug, LogLevel.Info, LogLevel.Warning, LogLevel.Error
|
||||||
|
};
|
||||||
|
private string searchText = "";
|
||||||
|
private bool autoScroll = true;
|
||||||
|
|
||||||
|
// Time range filtering
|
||||||
|
private bool enableTimeFilter = false;
|
||||||
|
private float minTimestamp = 0;
|
||||||
|
private float maxTimestamp = 0;
|
||||||
|
private float currentMaxTimestamp = 0;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UI State
|
||||||
|
|
||||||
|
// Colors for log levels
|
||||||
|
private readonly Color debugColor = Color.white;
|
||||||
|
private readonly Color infoColor = Color.white;
|
||||||
|
private readonly Color warningColor = Color.yellow;
|
||||||
|
private readonly Color errorColor = new Color(1f, 0.3f, 0.3f);
|
||||||
|
|
||||||
|
// Alternating row background colors
|
||||||
|
private readonly Color evenRowColor = new Color(0.22f, 0.22f, 0.22f);
|
||||||
|
private readonly Color oddRowColor = new Color(0.26f, 0.26f, 0.26f);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Menu Items
|
||||||
|
|
||||||
|
[MenuItem("AppleHills/Custom Log Console")]
|
||||||
|
public static void ShowWindow()
|
||||||
|
{
|
||||||
|
var window = GetWindow<CustomLogWindow>("Custom Log");
|
||||||
|
window.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Unity Lifecycle
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
// Subscribe to new log events
|
||||||
|
Logging.OnLogEntryAdded += OnLogAdded;
|
||||||
|
|
||||||
|
// Load existing logs
|
||||||
|
allLogs.AddRange(Logging.GetRecentLogs());
|
||||||
|
|
||||||
|
// Build initial tag lists
|
||||||
|
RebuildTagLists();
|
||||||
|
|
||||||
|
// Initialize time range
|
||||||
|
UpdateTimeRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
Logging.OnLogEntryAdded -= OnLogAdded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLogAdded(LogEntry entry)
|
||||||
|
{
|
||||||
|
allLogs.Add(entry);
|
||||||
|
|
||||||
|
// Update active tags
|
||||||
|
activeClassTags.Add(entry.ClassName);
|
||||||
|
activeMethodTags.Add(entry.MethodName);
|
||||||
|
|
||||||
|
// Update time range
|
||||||
|
UpdateTimeRange();
|
||||||
|
|
||||||
|
if (autoScroll)
|
||||||
|
scrollPosition.y = float.MaxValue;
|
||||||
|
|
||||||
|
Repaint(); // Redraw window
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region GUI Drawing
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
DrawToolbar();
|
||||||
|
DrawLogEntries();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawToolbar()
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
|
||||||
|
|
||||||
|
// Clear button
|
||||||
|
if (GUILayout.Button("Clear", EditorStyles.toolbarButton, GUILayout.Width(50)))
|
||||||
|
{
|
||||||
|
allLogs.Clear();
|
||||||
|
activeClassTags.Clear();
|
||||||
|
activeMethodTags.Clear();
|
||||||
|
Logging.ClearLogs();
|
||||||
|
Repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto-scroll toggle
|
||||||
|
autoScroll = GUILayout.Toggle(autoScroll, "Auto-scroll", EditorStyles.toolbarButton, GUILayout.Width(80));
|
||||||
|
|
||||||
|
GUILayout.Space(10);
|
||||||
|
|
||||||
|
// Class Filter Button
|
||||||
|
string classLabel = selectedClassFilters.Count == 0 ? "Classes: All" :
|
||||||
|
selectedClassFilters.Count == activeClassTags.Count ? "Classes: All" :
|
||||||
|
$"Classes: {selectedClassFilters.Count}";
|
||||||
|
if (GUILayout.Button(new GUIContent(classLabel, "Filter by class"), EditorStyles.toolbarDropDown, GUILayout.Width(100)))
|
||||||
|
{
|
||||||
|
ShowClassFilterMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Filter Button
|
||||||
|
string methodLabel = selectedMethodFilters.Count == 0 ? "Methods: All" :
|
||||||
|
selectedMethodFilters.Count == activeMethodTags.Count ? "Methods: All" :
|
||||||
|
$"Methods: {selectedMethodFilters.Count}";
|
||||||
|
if (GUILayout.Button(new GUIContent(methodLabel, "Filter by method"), EditorStyles.toolbarDropDown, GUILayout.Width(110)))
|
||||||
|
{
|
||||||
|
ShowMethodFilterMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log Level Filter Button
|
||||||
|
string levelLabel = selectedLevelFilters.Count == 4 ? "Levels: All" :
|
||||||
|
selectedLevelFilters.Count == 0 ? "Levels: None" :
|
||||||
|
$"Levels: {selectedLevelFilters.Count}";
|
||||||
|
if (GUILayout.Button(new GUIContent(levelLabel, "Filter by log level"), EditorStyles.toolbarDropDown, GUILayout.Width(90)))
|
||||||
|
{
|
||||||
|
ShowLevelFilterMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Range Filter Button
|
||||||
|
if (GUILayout.Button(new GUIContent("⏱", "Time range filter"), EditorStyles.toolbarButton, GUILayout.Width(25)))
|
||||||
|
{
|
||||||
|
ShowTimeRangeWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
|
||||||
|
// Search box
|
||||||
|
GUILayout.Label("Search:", GUILayout.Width(50));
|
||||||
|
searchText = GUILayout.TextField(searchText, EditorStyles.toolbarSearchField, GUILayout.Width(150));
|
||||||
|
|
||||||
|
GUILayout.Space(10);
|
||||||
|
|
||||||
|
// Export button
|
||||||
|
if (GUILayout.Button("Export", EditorStyles.toolbarButton, GUILayout.Width(60)))
|
||||||
|
{
|
||||||
|
ExportLogs();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.Space(5);
|
||||||
|
|
||||||
|
// Log count
|
||||||
|
var filteredCount = GetFilteredLogs().Count();
|
||||||
|
GUILayout.Label($"{filteredCount}/{allLogs.Count}", GUILayout.Width(80));
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowClassFilterMenu()
|
||||||
|
{
|
||||||
|
ClassFilterWindow.ShowWindow(this, activeClassTags, selectedClassFilters,
|
||||||
|
(newSelection) =>
|
||||||
|
{
|
||||||
|
selectedClassFilters = newSelection;
|
||||||
|
Repaint();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowMethodFilterMenu()
|
||||||
|
{
|
||||||
|
MethodFilterWindow.ShowWindow(this, activeMethodTags, selectedMethodFilters,
|
||||||
|
(newSelection) =>
|
||||||
|
{
|
||||||
|
selectedMethodFilters = newSelection;
|
||||||
|
Repaint();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowLevelFilterMenu()
|
||||||
|
{
|
||||||
|
LevelFilterWindow.ShowWindow(this, selectedLevelFilters,
|
||||||
|
(newSelection) =>
|
||||||
|
{
|
||||||
|
selectedLevelFilters = newSelection;
|
||||||
|
Repaint();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowTimeRangeWindow()
|
||||||
|
{
|
||||||
|
TimeRangeFilterWindow.ShowWindow(this, enableTimeFilter, minTimestamp, maxTimestamp, currentMaxTimestamp,
|
||||||
|
(enabled, min, max) =>
|
||||||
|
{
|
||||||
|
enableTimeFilter = enabled;
|
||||||
|
minTimestamp = min;
|
||||||
|
maxTimestamp = max;
|
||||||
|
Repaint();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawLogEntries()
|
||||||
|
{
|
||||||
|
// PERFORMANCE NOTE: For 10,000+ logs, consider virtualized scrolling here.
|
||||||
|
// Only render entries visible within the scroll view rect.
|
||||||
|
// Current implementation renders all filtered logs which may cause GUI slowdown.
|
||||||
|
|
||||||
|
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
||||||
|
|
||||||
|
var filteredLogs = GetFilteredLogs().ToList();
|
||||||
|
|
||||||
|
for (int i = 0; i < filteredLogs.Count; i++)
|
||||||
|
{
|
||||||
|
DrawLogEntry(filteredLogs[i], i);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawLogEntry(LogEntry entry, int index)
|
||||||
|
{
|
||||||
|
// Draw alternating row background
|
||||||
|
Color bgColor = (index % 2 == 0) ? evenRowColor : oddRowColor;
|
||||||
|
Rect rowRect = EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUI.DrawRect(rowRect, bgColor);
|
||||||
|
|
||||||
|
// Color-code by log level
|
||||||
|
Color color = GetColorForLevel(entry.Level);
|
||||||
|
var originalColor = GUI.contentColor;
|
||||||
|
GUI.contentColor = color;
|
||||||
|
|
||||||
|
// Timestamp
|
||||||
|
GUILayout.Label($"[{entry.Timestamp:F2}s]", GUILayout.Width(80));
|
||||||
|
|
||||||
|
// Level
|
||||||
|
GUILayout.Label($"[{entry.Level}]", GUILayout.Width(70));
|
||||||
|
|
||||||
|
// Class
|
||||||
|
GUILayout.Label($"[{entry.ClassName}]", GUILayout.Width(150));
|
||||||
|
|
||||||
|
// Method
|
||||||
|
GUILayout.Label($"[{entry.MethodName}]", GUILayout.Width(150));
|
||||||
|
|
||||||
|
// Message
|
||||||
|
GUILayout.Label(entry.Message, GUILayout.ExpandWidth(true));
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
GUI.contentColor = originalColor;
|
||||||
|
|
||||||
|
// Right-click context menu
|
||||||
|
if (Event.current.type == EventType.ContextClick && rowRect.Contains(Event.current.mousePosition))
|
||||||
|
{
|
||||||
|
GenericMenu menu = new GenericMenu();
|
||||||
|
|
||||||
|
menu.AddItem(new GUIContent("Copy Full Message"), false, () =>
|
||||||
|
{
|
||||||
|
EditorGUIUtility.systemCopyBuffer = entry.FullFormattedMessage;
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.AddItem(new GUIContent("Copy Message Only"), false, () =>
|
||||||
|
{
|
||||||
|
EditorGUIUtility.systemCopyBuffer = entry.Message;
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.AddSeparator("");
|
||||||
|
|
||||||
|
menu.AddItem(new GUIContent("Filter to this Class"), false, () =>
|
||||||
|
{
|
||||||
|
selectedClassFilters.Clear();
|
||||||
|
selectedClassFilters.Add(entry.ClassName);
|
||||||
|
Repaint();
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.AddItem(new GUIContent("Filter to this Method"), false, () =>
|
||||||
|
{
|
||||||
|
selectedMethodFilters.Clear();
|
||||||
|
selectedMethodFilters.Add(entry.MethodName);
|
||||||
|
Repaint();
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.AddItem(new GUIContent("Filter to this Class + Method"), false, () =>
|
||||||
|
{
|
||||||
|
selectedClassFilters.Clear();
|
||||||
|
selectedClassFilters.Add(entry.ClassName);
|
||||||
|
selectedMethodFilters.Clear();
|
||||||
|
selectedMethodFilters.Add(entry.MethodName);
|
||||||
|
Repaint();
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.AddSeparator("");
|
||||||
|
|
||||||
|
menu.AddItem(new GUIContent("Filter to this Log Level"), false, () =>
|
||||||
|
{
|
||||||
|
selectedLevelFilters.Clear();
|
||||||
|
selectedLevelFilters.Add(entry.Level);
|
||||||
|
Repaint();
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.ShowAsContext();
|
||||||
|
Event.current.Use();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Filtering Logic
|
||||||
|
|
||||||
|
private IEnumerable<LogEntry> GetFilteredLogs()
|
||||||
|
{
|
||||||
|
return allLogs.Where(entry =>
|
||||||
|
{
|
||||||
|
// Filter by class (if any selected)
|
||||||
|
if (selectedClassFilters.Count > 0 && !selectedClassFilters.Contains(entry.ClassName))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Filter by method (if any selected)
|
||||||
|
if (selectedMethodFilters.Count > 0 && !selectedMethodFilters.Contains(entry.MethodName))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Filter by log level
|
||||||
|
if (!selectedLevelFilters.Contains(entry.Level))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Filter by time range
|
||||||
|
if (enableTimeFilter)
|
||||||
|
{
|
||||||
|
if (entry.Timestamp < minTimestamp || entry.Timestamp > maxTimestamp)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter by search text
|
||||||
|
if (!string.IsNullOrEmpty(searchText))
|
||||||
|
{
|
||||||
|
bool matchesSearch =
|
||||||
|
entry.ClassName.Contains(searchText, StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
entry.MethodName.Contains(searchText, StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
entry.Message.Contains(searchText, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
if (!matchesSearch)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Helper Methods
|
||||||
|
|
||||||
|
private Color GetColorForLevel(LogLevel level)
|
||||||
|
{
|
||||||
|
return level switch
|
||||||
|
{
|
||||||
|
LogLevel.Debug => debugColor,
|
||||||
|
LogLevel.Info => infoColor,
|
||||||
|
LogLevel.Warning => warningColor,
|
||||||
|
LogLevel.Error => errorColor,
|
||||||
|
_ => infoColor
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RebuildTagLists()
|
||||||
|
{
|
||||||
|
activeClassTags.Clear();
|
||||||
|
activeMethodTags.Clear();
|
||||||
|
|
||||||
|
foreach (var log in allLogs)
|
||||||
|
{
|
||||||
|
activeClassTags.Add(log.ClassName);
|
||||||
|
activeMethodTags.Add(log.MethodName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateTimeRange()
|
||||||
|
{
|
||||||
|
if (allLogs.Count > 0)
|
||||||
|
{
|
||||||
|
currentMaxTimestamp = allLogs.Max(l => l.Timestamp);
|
||||||
|
|
||||||
|
// Initialize time range on first log
|
||||||
|
if (maxTimestamp == 0)
|
||||||
|
{
|
||||||
|
maxTimestamp = currentMaxTimestamp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Auto-expand max range as new logs come in
|
||||||
|
maxTimestamp = currentMaxTimestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExportLogs()
|
||||||
|
{
|
||||||
|
string defaultFileName = $"logs_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.txt";
|
||||||
|
string path = EditorUtility.SaveFilePanel("Export Logs", "", defaultFileName, "txt");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filteredLogs = GetFilteredLogs().ToList();
|
||||||
|
var lines = filteredLogs.Select(e => e.FullFormattedMessage);
|
||||||
|
File.WriteAllLines(path, lines);
|
||||||
|
|
||||||
|
EditorUtility.DisplayDialog("Export Successful",
|
||||||
|
$"Exported {filteredLogs.Count} log entries to:\n{path}", "OK");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
EditorUtility.DisplayDialog("Export Failed",
|
||||||
|
$"Failed to export logs:\n{ex.Message}", "OK");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Persistent popup window for class filtering with multi-selection support
|
||||||
|
/// </summary>
|
||||||
|
public class ClassFilterWindow : EditorWindow
|
||||||
|
{
|
||||||
|
private HashSet<string> availableTags;
|
||||||
|
private HashSet<string> selectedTags;
|
||||||
|
private System.Action<HashSet<string>> onApply;
|
||||||
|
private Vector2 scrollPosition;
|
||||||
|
private string searchFilter = "";
|
||||||
|
|
||||||
|
public static void ShowWindow(CustomLogWindow parent, HashSet<string> available, HashSet<string> selected,
|
||||||
|
System.Action<HashSet<string>> applyCallback)
|
||||||
|
{
|
||||||
|
var window = CreateInstance<ClassFilterWindow>();
|
||||||
|
window.titleContent = new GUIContent("Class Filter");
|
||||||
|
window.availableTags = available;
|
||||||
|
window.selectedTags = new HashSet<string>(selected);
|
||||||
|
window.onApply = applyCallback;
|
||||||
|
|
||||||
|
var parentRect = parent.position;
|
||||||
|
window.position = new Rect(parentRect.x + 50, parentRect.y + 50, 300, 400);
|
||||||
|
window.ShowUtility();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
|
||||||
|
// Control buttons
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("All", GUILayout.Width(60)))
|
||||||
|
{
|
||||||
|
if (availableTags != null)
|
||||||
|
selectedTags = new HashSet<string>(availableTags);
|
||||||
|
}
|
||||||
|
if (GUILayout.Button("None", GUILayout.Width(60)))
|
||||||
|
{
|
||||||
|
selectedTags.Clear();
|
||||||
|
}
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
searchFilter = EditorGUILayout.TextField(searchFilter, EditorStyles.toolbarSearchField, GUILayout.Width(150));
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
|
||||||
|
// Scrollable list of toggles
|
||||||
|
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
||||||
|
|
||||||
|
if (availableTags != null && availableTags.Count > 0)
|
||||||
|
{
|
||||||
|
var filteredTags = string.IsNullOrEmpty(searchFilter)
|
||||||
|
? availableTags.OrderBy(t => t)
|
||||||
|
: availableTags.Where(t => t.Contains(searchFilter, StringComparison.OrdinalIgnoreCase)).OrderBy(t => t);
|
||||||
|
|
||||||
|
foreach (var tag in filteredTags)
|
||||||
|
{
|
||||||
|
bool isSelected = selectedTags.Contains(tag);
|
||||||
|
bool newSelection = EditorGUILayout.ToggleLeft(tag, isSelected);
|
||||||
|
|
||||||
|
if (newSelection != isSelected)
|
||||||
|
{
|
||||||
|
if (newSelection)
|
||||||
|
selectedTags.Add(tag);
|
||||||
|
else
|
||||||
|
selectedTags.Remove(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("No classes available", MessageType.Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
|
||||||
|
// Apply/Close buttons
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
|
||||||
|
if (GUILayout.Button("Apply", GUILayout.Width(80)))
|
||||||
|
{
|
||||||
|
onApply?.Invoke(selectedTags);
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("Close", GUILayout.Width(80)))
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Persistent popup window for method filtering with multi-selection support
|
||||||
|
/// </summary>
|
||||||
|
public class MethodFilterWindow : EditorWindow
|
||||||
|
{
|
||||||
|
private HashSet<string> availableTags;
|
||||||
|
private HashSet<string> selectedTags;
|
||||||
|
private System.Action<HashSet<string>> onApply;
|
||||||
|
private Vector2 scrollPosition;
|
||||||
|
private string searchFilter = "";
|
||||||
|
|
||||||
|
public static void ShowWindow(CustomLogWindow parent, HashSet<string> available, HashSet<string> selected,
|
||||||
|
System.Action<HashSet<string>> applyCallback)
|
||||||
|
{
|
||||||
|
var window = CreateInstance<MethodFilterWindow>();
|
||||||
|
window.titleContent = new GUIContent("Method Filter");
|
||||||
|
window.availableTags = available;
|
||||||
|
window.selectedTags = new HashSet<string>(selected);
|
||||||
|
window.onApply = applyCallback;
|
||||||
|
|
||||||
|
var parentRect = parent.position;
|
||||||
|
window.position = new Rect(parentRect.x + 50, parentRect.y + 50, 300, 400);
|
||||||
|
window.ShowUtility();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
|
||||||
|
// Control buttons
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("All", GUILayout.Width(60)))
|
||||||
|
{
|
||||||
|
if (availableTags != null)
|
||||||
|
selectedTags = new HashSet<string>(availableTags);
|
||||||
|
}
|
||||||
|
if (GUILayout.Button("None", GUILayout.Width(60)))
|
||||||
|
{
|
||||||
|
selectedTags.Clear();
|
||||||
|
}
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
searchFilter = EditorGUILayout.TextField(searchFilter, EditorStyles.toolbarSearchField, GUILayout.Width(150));
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
|
||||||
|
// Scrollable list of toggles
|
||||||
|
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
||||||
|
|
||||||
|
if (availableTags != null && availableTags.Count > 0)
|
||||||
|
{
|
||||||
|
var filteredTags = string.IsNullOrEmpty(searchFilter)
|
||||||
|
? availableTags.OrderBy(t => t)
|
||||||
|
: availableTags.Where(t => t.Contains(searchFilter, StringComparison.OrdinalIgnoreCase)).OrderBy(t => t);
|
||||||
|
|
||||||
|
foreach (var tag in filteredTags)
|
||||||
|
{
|
||||||
|
bool isSelected = selectedTags.Contains(tag);
|
||||||
|
bool newSelection = EditorGUILayout.ToggleLeft(tag, isSelected);
|
||||||
|
|
||||||
|
if (newSelection != isSelected)
|
||||||
|
{
|
||||||
|
if (newSelection)
|
||||||
|
selectedTags.Add(tag);
|
||||||
|
else
|
||||||
|
selectedTags.Remove(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("No methods available", MessageType.Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
|
||||||
|
// Apply/Close buttons
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
|
||||||
|
if (GUILayout.Button("Apply", GUILayout.Width(80)))
|
||||||
|
{
|
||||||
|
onApply?.Invoke(selectedTags);
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("Close", GUILayout.Width(80)))
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Persistent popup window for log level filtering with multi-selection support
|
||||||
|
/// </summary>
|
||||||
|
public class LevelFilterWindow : EditorWindow
|
||||||
|
{
|
||||||
|
private HashSet<LogLevel> selectedLevels;
|
||||||
|
private System.Action<HashSet<LogLevel>> onApply;
|
||||||
|
|
||||||
|
public static void ShowWindow(CustomLogWindow parent, HashSet<LogLevel> selected,
|
||||||
|
System.Action<HashSet<LogLevel>> applyCallback)
|
||||||
|
{
|
||||||
|
var window = CreateInstance<LevelFilterWindow>();
|
||||||
|
window.titleContent = new GUIContent("Log Level Filter");
|
||||||
|
window.selectedLevels = new HashSet<LogLevel>(selected);
|
||||||
|
window.onApply = applyCallback;
|
||||||
|
|
||||||
|
var parentRect = parent.position;
|
||||||
|
window.position = new Rect(parentRect.x + 50, parentRect.y + 50, 250, 180);
|
||||||
|
window.ShowUtility();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
|
||||||
|
// Control buttons
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("All", GUILayout.Width(60)))
|
||||||
|
{
|
||||||
|
selectedLevels = new HashSet<LogLevel>
|
||||||
|
{
|
||||||
|
LogLevel.Debug, LogLevel.Info, LogLevel.Warning, LogLevel.Error
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (GUILayout.Button("None", GUILayout.Width(60)))
|
||||||
|
{
|
||||||
|
selectedLevels.Clear();
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.Space(10);
|
||||||
|
|
||||||
|
// Log level toggles
|
||||||
|
foreach (LogLevel level in Enum.GetValues(typeof(LogLevel)))
|
||||||
|
{
|
||||||
|
bool isSelected = selectedLevels.Contains(level);
|
||||||
|
bool newSelection = EditorGUILayout.ToggleLeft(level.ToString(), isSelected);
|
||||||
|
|
||||||
|
if (newSelection != isSelected)
|
||||||
|
{
|
||||||
|
if (newSelection)
|
||||||
|
selectedLevels.Add(level);
|
||||||
|
else
|
||||||
|
selectedLevels.Remove(level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.Space(10);
|
||||||
|
|
||||||
|
// Apply/Close buttons
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
|
||||||
|
if (GUILayout.Button("Apply", GUILayout.Width(80)))
|
||||||
|
{
|
||||||
|
onApply?.Invoke(selectedLevels);
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("Close", GUILayout.Width(80)))
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Popup window for configuring time range filters
|
||||||
|
/// </summary>
|
||||||
|
public class TimeRangeFilterWindow : EditorWindow
|
||||||
|
{
|
||||||
|
private bool enableTimeFilter;
|
||||||
|
private float minTimestamp;
|
||||||
|
private float maxTimestamp;
|
||||||
|
private float currentMaxTimestamp;
|
||||||
|
private System.Action<bool, float, float> onApply;
|
||||||
|
|
||||||
|
public static void ShowWindow(CustomLogWindow parent, bool enabled, float min, float max, float currentMax,
|
||||||
|
System.Action<bool, float, float> applyCallback)
|
||||||
|
{
|
||||||
|
var window = CreateInstance<TimeRangeFilterWindow>();
|
||||||
|
window.titleContent = new GUIContent("Time Range Filter");
|
||||||
|
window.enableTimeFilter = enabled;
|
||||||
|
window.minTimestamp = min;
|
||||||
|
window.maxTimestamp = max;
|
||||||
|
window.currentMaxTimestamp = currentMax;
|
||||||
|
window.onApply = applyCallback;
|
||||||
|
|
||||||
|
// Position near the parent window
|
||||||
|
var parentRect = parent.position;
|
||||||
|
window.position = new Rect(parentRect.x + 100, parentRect.y + 100, 350, 120);
|
||||||
|
|
||||||
|
window.ShowUtility();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
EditorGUILayout.Space(10);
|
||||||
|
|
||||||
|
enableTimeFilter = EditorGUILayout.Toggle("Enable Time Filter", enableTimeFilter);
|
||||||
|
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
|
||||||
|
if (enableTimeFilter && currentMaxTimestamp > 0)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.LabelField($"Min: {minTimestamp:F2}s", GUILayout.Width(100));
|
||||||
|
EditorGUILayout.LabelField($"Max: {maxTimestamp:F2}s", GUILayout.Width(100));
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.MinMaxSlider(
|
||||||
|
ref minTimestamp,
|
||||||
|
ref maxTimestamp,
|
||||||
|
0,
|
||||||
|
currentMaxTimestamp);
|
||||||
|
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("Reset Range"))
|
||||||
|
{
|
||||||
|
minTimestamp = 0;
|
||||||
|
maxTimestamp = currentMaxTimestamp;
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
else if (enableTimeFilter)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("No logs available for time filtering", MessageType.Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.Space(10);
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
|
||||||
|
if (GUILayout.Button("Apply", GUILayout.Width(80)))
|
||||||
|
{
|
||||||
|
onApply?.Invoke(enableTimeFilter, minTimestamp, maxTimestamp);
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("Cancel", GUILayout.Width(80)))
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.Space(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Assets/Editor/CustomLogWindow.cs.meta
Normal file
3
Assets/Editor/CustomLogWindow.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 60a300585fef4ac990c963c8b37c3887
|
||||||
|
timeCreated: 1762814971
|
||||||
@@ -181,7 +181,7 @@ namespace Editor
|
|||||||
string scenePath = AssetDatabase.GUIDToAssetPath(guid);
|
string scenePath = AssetDatabase.GUIDToAssetPath(guid);
|
||||||
var scene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Additive);
|
var scene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Additive);
|
||||||
|
|
||||||
var allComponents = GameObject.FindObjectsOfType<Component>(true);
|
var allComponents = GameObject.FindObjectsByType<Component>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||||
foreach (var component in allComponents)
|
foreach (var component in allComponents)
|
||||||
{
|
{
|
||||||
if (component == null || component.gameObject.scene != scene) continue;
|
if (component == null || component.gameObject.scene != scene) continue;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Editor.Lifecycle
|
|||||||
/// Editor-only bootstrap that ensures OnSceneReady is triggered when playing directly from a scene in Unity Editor.
|
/// Editor-only bootstrap that ensures OnSceneReady is triggered when playing directly from a scene in Unity Editor.
|
||||||
///
|
///
|
||||||
/// PROBLEM: When you press Play in the editor without going through the scene manager:
|
/// PROBLEM: When you press Play in the editor without going through the scene manager:
|
||||||
/// - CustomBoot runs and triggers OnBootCompletionTriggered (which broadcasts OnManagedAwake)
|
/// - CustomBoot runs and triggers OnBootCompletionTriggered (which broadcasts OnManagedStart)
|
||||||
/// - But BroadcastSceneReady is NEVER called for the initial scene
|
/// - But BroadcastSceneReady is NEVER called for the initial scene
|
||||||
/// - Components in the scene never receive their OnSceneReady() callback
|
/// - Components in the scene never receive their OnSceneReady() callback
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using AppleHills.Core.Settings;
|
using AppleHills.Core.Settings;
|
||||||
using Core;
|
using Core;
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Rendering.VirtualTexturing;
|
|
||||||
|
|
||||||
namespace AppleHills.Editor
|
namespace AppleHills.Editor
|
||||||
{
|
{
|
||||||
@@ -65,7 +63,7 @@ namespace AppleHills.Editor
|
|||||||
GetPuzzlePromptRange
|
GetPuzzlePromptRange
|
||||||
);
|
);
|
||||||
|
|
||||||
LogDebugMessage("Editor settings loaded for Scene View use");
|
Logging.Debug("Editor settings loaded for Scene View use");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RefreshSceneViews()
|
public static void RefreshSceneViews()
|
||||||
@@ -102,14 +100,5 @@ namespace AppleHills.Editor
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void LogDebugMessage(string message)
|
|
||||||
{
|
|
||||||
if (Application.isPlaying &&
|
|
||||||
DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().settingsLogVerbosity <= LogVerbosity.Debug)
|
|
||||||
{
|
|
||||||
Logging.Debug($"[EditorSettingsProvider] {message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,153 +0,0 @@
|
|||||||
using Interactions;
|
|
||||||
using PuzzleS;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Editor
|
|
||||||
{
|
|
||||||
public class ItemPrefabEditorWindow : EditorWindow
|
|
||||||
{
|
|
||||||
private GameObject _selectedGameObject;
|
|
||||||
private InteractableBase _interactable;
|
|
||||||
private PickupItemData _pickupData;
|
|
||||||
private PuzzleStepSO _objectiveData;
|
|
||||||
private UnityEditor.Editor _soEditor;
|
|
||||||
private string _pickupSoFolderPath = "Assets/Data/Items";
|
|
||||||
private string _puzzleSoFolderPath = "Assets/Data/Puzzles";
|
|
||||||
|
|
||||||
private enum ItemType { None, Pickup, ItemSlot }
|
|
||||||
private ItemType _itemType = ItemType.None;
|
|
||||||
|
|
||||||
[MenuItem("AppleHills/Item Prefab Editor")]
|
|
||||||
public static void ShowWindow()
|
|
||||||
{
|
|
||||||
var window = GetWindow<ItemPrefabEditorWindow>("Item Prefab Editor");
|
|
||||||
window.minSize = new Vector2(400, 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
Selection.selectionChanged += Repaint;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDisable()
|
|
||||||
{
|
|
||||||
Selection.selectionChanged -= Repaint;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnGUI()
|
|
||||||
{
|
|
||||||
_selectedGameObject = null;
|
|
||||||
_interactable = null;
|
|
||||||
if (Selection.activeGameObject != null)
|
|
||||||
{
|
|
||||||
_selectedGameObject = Selection.activeGameObject;
|
|
||||||
_interactable = _selectedGameObject.GetComponent<InteractableBase>();
|
|
||||||
}
|
|
||||||
else if (Selection.activeObject is GameObject go)
|
|
||||||
{
|
|
||||||
_selectedGameObject = go;
|
|
||||||
_interactable = go.GetComponent<InteractableBase>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_selectedGameObject == null || _interactable == null)
|
|
||||||
{
|
|
||||||
EditorGUILayout.HelpBox("Select a GameObject or prefab with an InteractableBase component to edit.", MessageType.Info);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.LabelField("Editing: ", _selectedGameObject.name, EditorStyles.boldLabel);
|
|
||||||
EditorGUILayout.Space();
|
|
||||||
|
|
||||||
// Determine current type
|
|
||||||
bool hasPickup = _selectedGameObject.GetComponent<Pickup>() != null;
|
|
||||||
bool hasSlot = _selectedGameObject.GetComponent<ItemSlot>() != null;
|
|
||||||
if (hasSlot) _itemType = ItemType.ItemSlot;
|
|
||||||
else if (hasPickup) _itemType = ItemType.Pickup;
|
|
||||||
else _itemType = ItemType.None;
|
|
||||||
|
|
||||||
// Item type selection
|
|
||||||
var newType = (ItemType)EditorGUILayout.EnumPopup("Item Type", _itemType);
|
|
||||||
if (newType != _itemType)
|
|
||||||
{
|
|
||||||
// Remove both, then add selected
|
|
||||||
PrefabEditorUtility.RemoveComponent<Pickup>(_selectedGameObject);
|
|
||||||
PrefabEditorUtility.RemoveComponent<ItemSlot>(_selectedGameObject);
|
|
||||||
if (newType == ItemType.Pickup)
|
|
||||||
PrefabEditorUtility.AddOrGetComponent<Pickup>(_selectedGameObject);
|
|
||||||
else if (newType == ItemType.ItemSlot)
|
|
||||||
PrefabEditorUtility.AddOrGetComponent<ItemSlot>(_selectedGameObject);
|
|
||||||
_itemType = newType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectiveStepBehaviour
|
|
||||||
bool hasObjective = _selectedGameObject.GetComponent<ObjectiveStepBehaviour>() != null;
|
|
||||||
bool addObjective = EditorGUILayout.Toggle("ObjectiveStepBehaviour", hasObjective);
|
|
||||||
if (addObjective && !hasObjective)
|
|
||||||
{
|
|
||||||
PrefabEditorUtility.AddOrGetComponent<ObjectiveStepBehaviour>(_selectedGameObject);
|
|
||||||
}
|
|
||||||
else if (!addObjective && hasObjective)
|
|
||||||
{
|
|
||||||
PrefabEditorUtility.RemoveComponent<ObjectiveStepBehaviour>(_selectedGameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pickup Data (for Pickup or ItemSlot)
|
|
||||||
if (_itemType == ItemType.Pickup || _itemType == ItemType.ItemSlot)
|
|
||||||
{
|
|
||||||
var pickup = _selectedGameObject.GetComponent<Pickup>();
|
|
||||||
_pickupData = pickup.itemData;
|
|
||||||
EditorGUILayout.LabelField("Pickup Data:", EditorStyles.boldLabel);
|
|
||||||
_pickupData = (PickupItemData)EditorGUILayout.ObjectField("PickupItemData", _pickupData, typeof(PickupItemData), false);
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
EditorGUILayout.PrefixLabel("Save To");
|
|
||||||
EditorGUILayout.SelectableLabel(_pickupSoFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
|
|
||||||
if (GUILayout.Button("Select...", GUILayout.Width(80)))
|
|
||||||
{
|
|
||||||
_pickupSoFolderPath = PrefabEditorUtility.SelectFolder(_pickupSoFolderPath, "Data/Items");
|
|
||||||
}
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
if (_pickupData == null && GUILayout.Button("Create New PickupItemData"))
|
|
||||||
{
|
|
||||||
_pickupData = PrefabEditorUtility.CreateScriptableAsset<PickupItemData>(_selectedGameObject.name + "_pickup", _pickupSoFolderPath);
|
|
||||||
}
|
|
||||||
if (_pickupData != null)
|
|
||||||
{
|
|
||||||
PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _pickupData);
|
|
||||||
pickup.itemData = _pickupData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Objective Data
|
|
||||||
if (addObjective)
|
|
||||||
{
|
|
||||||
var obj = _selectedGameObject.GetComponent<ObjectiveStepBehaviour>();
|
|
||||||
_objectiveData = obj.stepData;
|
|
||||||
EditorGUILayout.LabelField("Objective Data:", EditorStyles.boldLabel);
|
|
||||||
_objectiveData = (PuzzleStepSO)EditorGUILayout.ObjectField("PuzzleStepSO", _objectiveData, typeof(PuzzleStepSO), false);
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
EditorGUILayout.PrefixLabel("Save To");
|
|
||||||
EditorGUILayout.SelectableLabel(_puzzleSoFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
|
|
||||||
if (GUILayout.Button("Select...", GUILayout.Width(80)))
|
|
||||||
{
|
|
||||||
_puzzleSoFolderPath = PrefabEditorUtility.SelectFolder(_puzzleSoFolderPath, "Data/Puzzles");
|
|
||||||
}
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
if (_objectiveData == null && GUILayout.Button("Create New PuzzleStepSO"))
|
|
||||||
{
|
|
||||||
_objectiveData = PrefabEditorUtility.CreateScriptableAsset<PuzzleStepSO>(_selectedGameObject.name + "_puzzle", _puzzleSoFolderPath);
|
|
||||||
}
|
|
||||||
if (_objectiveData != null)
|
|
||||||
{
|
|
||||||
PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _objectiveData);
|
|
||||||
obj.stepData = _objectiveData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (GUI.changed)
|
|
||||||
{
|
|
||||||
EditorUtility.SetDirty(_selectedGameObject);
|
|
||||||
PrefabUtility.RecordPrefabInstancePropertyModifications(_selectedGameObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 943b203cde5343c68a6278c111fce2ed
|
|
||||||
timeCreated: 1757508162
|
|
||||||
@@ -1,168 +0,0 @@
|
|||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
using System.IO;
|
|
||||||
using Interactions;
|
|
||||||
using PuzzleS;
|
|
||||||
|
|
||||||
namespace Editor
|
|
||||||
{
|
|
||||||
public class PrefabCreatorWindow : EditorWindow
|
|
||||||
{
|
|
||||||
private string _prefabName = "NewPrefab";
|
|
||||||
private string _saveFolderPath = "Assets/Prefabs/Items";
|
|
||||||
private string _pickupSoFolderPath = "Assets/Data/Items";
|
|
||||||
private string _puzzleSoFolderPath = "Assets/Data/Puzzles";
|
|
||||||
private bool _addObjective;
|
|
||||||
|
|
||||||
private PickupItemData _pickupData;
|
|
||||||
private PuzzleStepSO _objectiveData;
|
|
||||||
private UnityEditor.Editor _soEditor;
|
|
||||||
|
|
||||||
private enum ItemType { None, Pickup, ItemSlot }
|
|
||||||
private ItemType _itemType = ItemType.None;
|
|
||||||
|
|
||||||
private bool _createNext = false;
|
|
||||||
|
|
||||||
[MenuItem("AppleHills/Item Prefab Creator")]
|
|
||||||
public static void ShowWindow()
|
|
||||||
{
|
|
||||||
var window = GetWindow<PrefabCreatorWindow>("Prefab Creator");
|
|
||||||
window.minSize = new Vector2(400, 400);
|
|
||||||
// Set default paths if not already set
|
|
||||||
if (string.IsNullOrEmpty(window._saveFolderPath))
|
|
||||||
window._saveFolderPath = "Assets/Prefabs/Items";
|
|
||||||
if (string.IsNullOrEmpty(window._pickupSoFolderPath))
|
|
||||||
window._pickupSoFolderPath = "Assets/Data/Items";
|
|
||||||
if (string.IsNullOrEmpty(window._puzzleSoFolderPath))
|
|
||||||
window._puzzleSoFolderPath = "Assets/Data/Puzzles";
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnGUI()
|
|
||||||
{
|
|
||||||
EditorGUILayout.LabelField("Prefab Creator", EditorStyles.boldLabel);
|
|
||||||
_prefabName = EditorGUILayout.TextField("Prefab Name", _prefabName);
|
|
||||||
// Prefab save folder
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
EditorGUILayout.PrefixLabel("Save Folder");
|
|
||||||
EditorGUILayout.SelectableLabel(_saveFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
|
|
||||||
if (GUILayout.Button("Select...", GUILayout.Width(80)))
|
|
||||||
{
|
|
||||||
_saveFolderPath = PrefabEditorUtility.SelectFolder(_saveFolderPath, "Prefabs/Items");
|
|
||||||
}
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
EditorGUILayout.Space();
|
|
||||||
EditorGUILayout.LabelField("Add Components:", EditorStyles.boldLabel);
|
|
||||||
|
|
||||||
// Item type selection
|
|
||||||
var newType = (ItemType)EditorGUILayout.EnumPopup("Item Type", _itemType);
|
|
||||||
if (newType != _itemType)
|
|
||||||
{
|
|
||||||
_itemType = newType;
|
|
||||||
}
|
|
||||||
bool addObjective = EditorGUILayout.Toggle("ObjectiveStepBehaviour", _addObjective);
|
|
||||||
_addObjective = addObjective;
|
|
||||||
EditorGUILayout.Space();
|
|
||||||
|
|
||||||
// Pickup Data (for Pickup or ItemSlot)
|
|
||||||
if (_itemType == ItemType.Pickup || _itemType == ItemType.ItemSlot)
|
|
||||||
{
|
|
||||||
EditorGUILayout.LabelField("Pickup Data:", EditorStyles.boldLabel);
|
|
||||||
_pickupData = (PickupItemData)EditorGUILayout.ObjectField("PickupItemData", _pickupData, typeof(PickupItemData), false);
|
|
||||||
// Pickup SO save folder
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
EditorGUILayout.PrefixLabel("Save To");
|
|
||||||
EditorGUILayout.SelectableLabel(_pickupSoFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
|
|
||||||
if (GUILayout.Button("Select...", GUILayout.Width(80)))
|
|
||||||
{
|
|
||||||
_pickupSoFolderPath = PrefabEditorUtility.SelectFolder(_pickupSoFolderPath, "Data/Items");
|
|
||||||
}
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
if (_pickupData == null && GUILayout.Button("Create New PickupItemData"))
|
|
||||||
{
|
|
||||||
_pickupData = PrefabEditorUtility.CreateScriptableAsset<PickupItemData>(_prefabName + "_pickup", _pickupSoFolderPath);
|
|
||||||
}
|
|
||||||
if (_pickupData != null)
|
|
||||||
{
|
|
||||||
PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _pickupData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Objective Data
|
|
||||||
if (_addObjective)
|
|
||||||
{
|
|
||||||
EditorGUILayout.LabelField("Objective Data:", EditorStyles.boldLabel);
|
|
||||||
_objectiveData = (PuzzleStepSO)EditorGUILayout.ObjectField("PuzzleStepSO", _objectiveData, typeof(PuzzleStepSO), false);
|
|
||||||
// Puzzle SO save folder
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
EditorGUILayout.PrefixLabel("Save To");
|
|
||||||
EditorGUILayout.SelectableLabel(_puzzleSoFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
|
|
||||||
if (GUILayout.Button("Select...", GUILayout.Width(80)))
|
|
||||||
{
|
|
||||||
_puzzleSoFolderPath = PrefabEditorUtility.SelectFolder(_puzzleSoFolderPath, "Data/Puzzles");
|
|
||||||
}
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
if (_objectiveData == null && GUILayout.Button("Create New PuzzleStepSO"))
|
|
||||||
{
|
|
||||||
_objectiveData = PrefabEditorUtility.CreateScriptableAsset<PuzzleStepSO>(_prefabName + "_puzzle", _puzzleSoFolderPath);
|
|
||||||
}
|
|
||||||
if (_objectiveData != null)
|
|
||||||
{
|
|
||||||
PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _objectiveData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GUILayout.FlexibleSpace();
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
GUI.enabled = !string.IsNullOrEmpty(_prefabName) && !string.IsNullOrEmpty(_saveFolderPath);
|
|
||||||
if (GUILayout.Button("Create Prefab", GUILayout.Height(28)))
|
|
||||||
{
|
|
||||||
CreatePrefab();
|
|
||||||
}
|
|
||||||
_createNext = GUILayout.Toggle(_createNext, "Create Next", GUILayout.Width(100), GUILayout.Height(28));
|
|
||||||
GUI.enabled = true;
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreatePrefab()
|
|
||||||
{
|
|
||||||
var go = new GameObject(_prefabName);
|
|
||||||
// Note: No need to add InteractableBase separately - Pickup and ItemSlot inherit from it
|
|
||||||
go.AddComponent<BoxCollider>();
|
|
||||||
int interactableLayer = LayerMask.NameToLayer("Interactable");
|
|
||||||
if (interactableLayer != -1)
|
|
||||||
go.layer = interactableLayer;
|
|
||||||
go.AddComponent<SpriteRenderer>();
|
|
||||||
if (_itemType == ItemType.Pickup)
|
|
||||||
{
|
|
||||||
var pickup = go.AddComponent<Pickup>();
|
|
||||||
pickup.itemData = _pickupData;
|
|
||||||
}
|
|
||||||
else if (_itemType == ItemType.ItemSlot)
|
|
||||||
{
|
|
||||||
var slot = go.AddComponent<ItemSlot>();
|
|
||||||
slot.itemData = _pickupData;
|
|
||||||
}
|
|
||||||
if (_addObjective)
|
|
||||||
{
|
|
||||||
var obj = go.AddComponent<ObjectiveStepBehaviour>();
|
|
||||||
obj.stepData = _objectiveData;
|
|
||||||
}
|
|
||||||
string prefabPath = Path.Combine(_saveFolderPath, _prefabName + ".prefab").Replace("\\", "/");
|
|
||||||
var prefab = PrefabUtility.SaveAsPrefabAsset(go, prefabPath);
|
|
||||||
DestroyImmediate(go);
|
|
||||||
AssetDatabase.Refresh();
|
|
||||||
Selection.activeObject = prefab;
|
|
||||||
EditorGUIUtility.PingObject(prefab);
|
|
||||||
EditorUtility.DisplayDialog("Prefab Created", $"Prefab saved to {prefabPath}", "OK");
|
|
||||||
if (_createNext)
|
|
||||||
{
|
|
||||||
_prefabName = "NewPrefab";
|
|
||||||
_pickupData = null;
|
|
||||||
_objectiveData = null;
|
|
||||||
_itemType = ItemType.None;
|
|
||||||
_addObjective = false;
|
|
||||||
_soEditor = null;
|
|
||||||
GUI.FocusControl(null);
|
|
||||||
Repaint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f67e06e997f642509ba61ea12b0f793e
|
|
||||||
timeCreated: 1757503955
|
|
||||||
@@ -248,7 +248,9 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 2bd397a60643eed45b586961ae6e3453, type: 3}
|
m_Script: {fileID: 11500000, guid: 2bd397a60643eed45b586961ae6e3453, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: AppleHillsScripts::PulverAudioController
|
m_EditorClassIdentifier: AppleHillsScripts::PulverAudioController
|
||||||
|
audioSource: {fileID: 887004370483616855}
|
||||||
combineAudio: {fileID: 8300000, guid: 768a16f348fe1d94c9cc267dc7ecf3b5, type: 3}
|
combineAudio: {fileID: 8300000, guid: 768a16f348fe1d94c9cc267dc7ecf3b5, type: 3}
|
||||||
|
itemManager: {fileID: 0}
|
||||||
--- !u!82 &4467608046243604209
|
--- !u!82 &4467608046243604209
|
||||||
AudioSource:
|
AudioSource:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@@ -154,10 +154,10 @@ RectTransform:
|
|||||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 3194400469127591113}
|
|
||||||
- {fileID: 6565376648640168889}
|
- {fileID: 6565376648640168889}
|
||||||
- {fileID: 5539807896859420487}
|
- {fileID: 5539807896859420487}
|
||||||
- {fileID: 4167457363450270236}
|
- {fileID: 4167457363450270236}
|
||||||
|
- {fileID: 3864057818161790164}
|
||||||
m_Father: {fileID: 3475216782073696103}
|
m_Father: {fileID: 3475216782073696103}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
@@ -715,6 +715,171 @@ MonoBehaviour:
|
|||||||
m_EditorClassIdentifier: AppleHillsScripts::UI.HudMenuButton
|
m_EditorClassIdentifier: AppleHillsScripts::UI.HudMenuButton
|
||||||
pagePrefab: {fileID: 7668937303613647057, guid: fe049e0d73eadd7479140c8e7bd10efe, type: 3}
|
pagePrefab: {fileID: 7668937303613647057, guid: fe049e0d73eadd7479140c8e7bd10efe, type: 3}
|
||||||
buttonName: PauseMenuButton
|
buttonName: PauseMenuButton
|
||||||
|
--- !u!1 &4599222264323240281
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 3864057818161790164}
|
||||||
|
- component: {fileID: 5271824036850954050}
|
||||||
|
- component: {fileID: 8081783206361873868}
|
||||||
|
- component: {fileID: 5548642987123338363}
|
||||||
|
- component: {fileID: 3058107077406709872}
|
||||||
|
- component: {fileID: 587711432829270645}
|
||||||
|
m_Layer: 5
|
||||||
|
m_Name: Icon
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!224 &3864057818161790164
|
||||||
|
RectTransform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 4599222264323240281}
|
||||||
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 0.99999, y: 0.99999, z: 0.99999}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 2474710976069581060}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
m_AnchorMin: {x: 1, y: 1}
|
||||||
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
|
m_AnchoredPosition: {x: -50, y: -50}
|
||||||
|
m_SizeDelta: {x: 200, y: 200}
|
||||||
|
m_Pivot: {x: 1, y: 1}
|
||||||
|
--- !u!222 &5271824036850954050
|
||||||
|
CanvasRenderer:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 4599222264323240281}
|
||||||
|
m_CullTransparentMesh: 1
|
||||||
|
--- !u!114 &8081783206361873868
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 4599222264323240281}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 1344c3c82d62a2a41a3576d8abb8e3ea, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.RawImage
|
||||||
|
m_Material: {fileID: 0}
|
||||||
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_RaycastTarget: 1
|
||||||
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_Maskable: 1
|
||||||
|
m_OnCullStateChanged:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_UVRect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 1
|
||||||
|
height: -1
|
||||||
|
--- !u!114 &5548642987123338363
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 4599222264323240281}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 2fd09147b9e9d42a48d6ddc915ddc3d2, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: SkiaSharp.Unity::SkiaSharp.Unity.SkottiePlayerV2
|
||||||
|
lottieFile: {fileID: 4900000, guid: 50e22b5bb8a496840952f2563758c13c, type: 3}
|
||||||
|
customResolution: 0
|
||||||
|
resWidth: 250
|
||||||
|
resHeight: 250
|
||||||
|
stateName: Idle
|
||||||
|
resetAfterFinished: 0
|
||||||
|
autoPlay: 1
|
||||||
|
loop: 1
|
||||||
|
--- !u!114 &3058107077406709872
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 4599222264323240281}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Button
|
||||||
|
m_Navigation:
|
||||||
|
m_Mode: 3
|
||||||
|
m_WrapAround: 0
|
||||||
|
m_SelectOnUp: {fileID: 0}
|
||||||
|
m_SelectOnDown: {fileID: 0}
|
||||||
|
m_SelectOnLeft: {fileID: 0}
|
||||||
|
m_SelectOnRight: {fileID: 0}
|
||||||
|
m_Transition: 1
|
||||||
|
m_Colors:
|
||||||
|
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||||
|
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||||
|
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||||
|
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||||
|
m_ColorMultiplier: 1
|
||||||
|
m_FadeDuration: 0.1
|
||||||
|
m_SpriteState:
|
||||||
|
m_HighlightedSprite: {fileID: 0}
|
||||||
|
m_PressedSprite: {fileID: 0}
|
||||||
|
m_SelectedSprite: {fileID: 0}
|
||||||
|
m_DisabledSprite: {fileID: 0}
|
||||||
|
m_AnimationTriggers:
|
||||||
|
m_NormalTrigger: Normal
|
||||||
|
m_HighlightedTrigger: Highlighted
|
||||||
|
m_PressedTrigger: Pressed
|
||||||
|
m_SelectedTrigger: Selected
|
||||||
|
m_DisabledTrigger: Disabled
|
||||||
|
m_Interactable: 1
|
||||||
|
m_TargetGraphic: {fileID: 8081783206361873868}
|
||||||
|
m_OnClick:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls:
|
||||||
|
- m_Target: {fileID: 0}
|
||||||
|
m_TargetAssemblyTypeName: AppSwitcher, AppleHillsScripts
|
||||||
|
m_MethodName: OpenAppSwitcher
|
||||||
|
m_Mode: 1
|
||||||
|
m_Arguments:
|
||||||
|
m_ObjectArgument: {fileID: 0}
|
||||||
|
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
|
||||||
|
m_IntArgument: 0
|
||||||
|
m_FloatArgument: 0
|
||||||
|
m_StringArgument:
|
||||||
|
m_BoolArgument: 0
|
||||||
|
m_CallState: 2
|
||||||
|
--- !u!114 &587711432829270645
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 4599222264323240281}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: e29407f14afc4428a48d3d1b4245b210, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: AppleHillsScripts::UI.HudMenuButton
|
||||||
|
pagePrefab: {fileID: 1498581815400593087, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
||||||
|
buttonName: RamaSjang Button
|
||||||
--- !u!1 &5113586844274188410
|
--- !u!1 &5113586844274188410
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1018,8 +1183,9 @@ MonoBehaviour:
|
|||||||
portraitObject: {fileID: 2258532551510216878}
|
portraitObject: {fileID: 2258532551510216878}
|
||||||
cinematicsParentObject: {fileID: 5598823553633962789}
|
cinematicsParentObject: {fileID: 5598823553633962789}
|
||||||
CinematicBackground: {fileID: 1256355336041814197}
|
CinematicBackground: {fileID: 1256355336041814197}
|
||||||
appSwitcher: {fileID: 3087409191859087859}
|
|
||||||
eagleEye: {fileID: 8093509920149135307}
|
eagleEye: {fileID: 8093509920149135307}
|
||||||
|
ramaSjangButton: {fileID: 4599222264323240281}
|
||||||
|
scrabBookButton: {fileID: 2880351836456325619}
|
||||||
cinematicSprites: {fileID: 0}
|
cinematicSprites: {fileID: 0}
|
||||||
cinematicBackgroundSprites: {fileID: 0}
|
cinematicBackgroundSprites: {fileID: 0}
|
||||||
currentCinematicPlayer: {fileID: 0}
|
currentCinematicPlayer: {fileID: 0}
|
||||||
@@ -1422,161 +1588,6 @@ GameObject:
|
|||||||
m_CorrespondingSourceObject: {fileID: 6980564769726958139, guid: 428a0feafda9d6d4e87ecf43ad41dc20, type: 3}
|
m_CorrespondingSourceObject: {fileID: 6980564769726958139, guid: 428a0feafda9d6d4e87ecf43ad41dc20, type: 3}
|
||||||
m_PrefabInstance: {fileID: 1192924796845315568}
|
m_PrefabInstance: {fileID: 1192924796845315568}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
--- !u!1001 &4473383355500896076
|
|
||||||
PrefabInstance:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Modification:
|
|
||||||
serializedVersion: 3
|
|
||||||
m_TransformParent: {fileID: 2474710976069581060}
|
|
||||||
m_Modifications:
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_Pivot.x
|
|
||||||
value: 0.5
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_Pivot.y
|
|
||||||
value: 0.5
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_AnchorMax.x
|
|
||||||
value: 1
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_AnchorMax.y
|
|
||||||
value: 1
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_AnchorMin.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_AnchorMin.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_SizeDelta.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_SizeDelta.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_LocalScale.x
|
|
||||||
value: 1
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_LocalScale.y
|
|
||||||
value: 1
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_LocalScale.z
|
|
||||||
value: 1
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_LocalPosition.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_LocalPosition.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_LocalPosition.z
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_LocalRotation.w
|
|
||||||
value: 1
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_LocalRotation.x
|
|
||||||
value: -0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_LocalRotation.y
|
|
||||||
value: -0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_LocalRotation.z
|
|
||||||
value: -0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_AnchoredPosition.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_AnchoredPosition.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_LocalEulerAnglesHint.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_LocalEulerAnglesHint.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_LocalEulerAnglesHint.z
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1498581815400593087, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_Name
|
|
||||||
value: AppSwitcher
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 1702317823502492223, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_PresetInfoIsWorld
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 4404111907760364827, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_IsActive
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7920249735731934357, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_Texture
|
|
||||||
value:
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 8490254979303535795, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
propertyPath: m_Texture
|
|
||||||
value:
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
m_RemovedComponents: []
|
|
||||||
m_RemovedGameObjects: []
|
|
||||||
m_AddedGameObjects: []
|
|
||||||
m_AddedComponents:
|
|
||||||
- targetCorrespondingSourceObject: {fileID: 6784053660381911346, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
insertIndex: -1
|
|
||||||
addedObject: {fileID: 1247411094983283289}
|
|
||||||
m_SourcePrefab: {fileID: 100100000, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
--- !u!1 &3087409191859087859 stripped
|
|
||||||
GameObject:
|
|
||||||
m_CorrespondingSourceObject: {fileID: 1498581815400593087, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
m_PrefabInstance: {fileID: 4473383355500896076}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
--- !u!224 &3194400469127591113 stripped
|
|
||||||
RectTransform:
|
|
||||||
m_CorrespondingSourceObject: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
m_PrefabInstance: {fileID: 4473383355500896076}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
--- !u!1 &6931438578476385918 stripped
|
|
||||||
GameObject:
|
|
||||||
m_CorrespondingSourceObject: {fileID: 6784053660381911346, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
|
|
||||||
m_PrefabInstance: {fileID: 4473383355500896076}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
--- !u!114 &1247411094983283289
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 6931438578476385918}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 494d0aedce9744308499355006071138, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier: AppleHillsScripts::UI.DummyInput
|
|
||||||
--- !u!1001 &6191884954105193926
|
--- !u!1001 &6191884954105193926
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@@ -614,6 +614,7 @@ GameObject:
|
|||||||
- component: {fileID: 768265498311662326}
|
- component: {fileID: 768265498311662326}
|
||||||
- component: {fileID: 6338084184716153992}
|
- component: {fileID: 6338084184716153992}
|
||||||
- component: {fileID: 253472492358066383}
|
- component: {fileID: 253472492358066383}
|
||||||
|
- component: {fileID: 7628818949793551399}
|
||||||
m_Layer: 10
|
m_Layer: 10
|
||||||
m_Name: FakeChoco
|
m_Name: FakeChoco
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -633,7 +634,8 @@ Transform:
|
|||||||
m_LocalPosition: {x: -6.784, y: -2.901, z: 0}
|
m_LocalPosition: {x: -6.784, y: -2.901, z: 0}
|
||||||
m_LocalScale: {x: 0.7, y: 0.7, z: 0.7}
|
m_LocalScale: {x: 0.7, y: 0.7, z: 0.7}
|
||||||
m_ConstrainProportionsScale: 1
|
m_ConstrainProportionsScale: 1
|
||||||
m_Children: []
|
m_Children:
|
||||||
|
- {fileID: 2205893234949555645}
|
||||||
m_Father: {fileID: 1509867968154593713}
|
m_Father: {fileID: 1509867968154593713}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!212 &6338084184716153992
|
--- !u!212 &6338084184716153992
|
||||||
@@ -740,6 +742,45 @@ BoxCollider2D:
|
|||||||
m_AutoTiling: 0
|
m_AutoTiling: 0
|
||||||
m_Size: {x: 6, y: 6}
|
m_Size: {x: 6, y: 6}
|
||||||
m_EdgeRadius: 0
|
m_EdgeRadius: 0
|
||||||
|
--- !u!114 &7628818949793551399
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2391935521422290070}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 833a4ccef651449e973e623d9107bef5, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: AppleHillsScripts::Interactions.OneClickInteraction
|
||||||
|
isOneTime: 0
|
||||||
|
cooldown: -1
|
||||||
|
characterToInteract: 2
|
||||||
|
interactionStarted:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
|
interactionInterrupted:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
|
characterArrived:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls:
|
||||||
|
- m_Target: {fileID: 5762733430166618195}
|
||||||
|
m_TargetAssemblyTypeName: PicnicBehaviour, AppleHillsScripts
|
||||||
|
m_MethodName: triedToStealChocolate
|
||||||
|
m_Mode: 1
|
||||||
|
m_Arguments:
|
||||||
|
m_ObjectArgument: {fileID: 0}
|
||||||
|
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
|
||||||
|
m_IntArgument: 0
|
||||||
|
m_FloatArgument: 0
|
||||||
|
m_StringArgument:
|
||||||
|
m_BoolArgument: 0
|
||||||
|
m_CallState: 2
|
||||||
|
interactionComplete:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
--- !u!1 &2728537141134591410
|
--- !u!1 &2728537141134591410
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1322,6 +1363,104 @@ GameObject:
|
|||||||
m_CorrespondingSourceObject: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3}
|
m_CorrespondingSourceObject: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3}
|
||||||
m_PrefabInstance: {fileID: 3750141998400252915}
|
m_PrefabInstance: {fileID: 3750141998400252915}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
--- !u!1001 &7365721869475958115
|
||||||
|
PrefabInstance:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Modification:
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransformParent: {fileID: 768265498311662326}
|
||||||
|
m_Modifications:
|
||||||
|
- target: {fileID: 2991221189157356317, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalScale.x
|
||||||
|
value: 0.3
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 2991221189157356317, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalScale.y
|
||||||
|
value: 0.3
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 2991221189157356317, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalScale.z
|
||||||
|
value: 0.3
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8506461915049351794, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_Name
|
||||||
|
value: HighlightEffect
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8506461915049351794, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalScale.x
|
||||||
|
value: 0.5
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalScale.y
|
||||||
|
value: 0.5
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalScale.z
|
||||||
|
value: 0.5
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalPosition.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalPosition.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalPosition.z
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalRotation.w
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalRotation.x
|
||||||
|
value: -0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalRotation.y
|
||||||
|
value: -0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalRotation.z
|
||||||
|
value: -0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalEulerAnglesHint.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalEulerAnglesHint.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_LocalEulerAnglesHint.z
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_ConstrainProportionsScale
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8998003315986923927, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
propertyPath: m_SortingOrder
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
m_RemovedComponents: []
|
||||||
|
m_RemovedGameObjects: []
|
||||||
|
m_AddedGameObjects: []
|
||||||
|
m_AddedComponents: []
|
||||||
|
m_SourcePrefab: {fileID: 100100000, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
--- !u!4 &2205893234949555645 stripped
|
||||||
|
Transform:
|
||||||
|
m_CorrespondingSourceObject: {fileID: 8693254833721559262, guid: f21581740b83b624cac5e6a8fa4d0f47, type: 3}
|
||||||
|
m_PrefabInstance: {fileID: 7365721869475958115}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
--- !u!1001 &7995402114015427944
|
--- !u!1001 &7995402114015427944
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1362,6 +1501,34 @@ PrefabInstance:
|
|||||||
propertyPath: m_SortingOrder
|
propertyPath: m_SortingOrder
|
||||||
value: 1
|
value: 1
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 2846246689251721816, guid: b3fc964bec385174f85a143f2fcff121, type: 3}
|
||||||
|
propertyPath: interactionComplete.m_PersistentCalls.m_Calls.Array.size
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 2846246689251721816, guid: b3fc964bec385174f85a143f2fcff121, type: 3}
|
||||||
|
propertyPath: interactionComplete.m_PersistentCalls.m_Calls.Array.data[0].m_Mode
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 2846246689251721816, guid: b3fc964bec385174f85a143f2fcff121, type: 3}
|
||||||
|
propertyPath: interactionComplete.m_PersistentCalls.m_Calls.Array.data[0].m_Target
|
||||||
|
value:
|
||||||
|
objectReference: {fileID: 5762733430166618195}
|
||||||
|
- target: {fileID: 2846246689251721816, guid: b3fc964bec385174f85a143f2fcff121, type: 3}
|
||||||
|
propertyPath: interactionComplete.m_PersistentCalls.m_Calls.Array.data[0].m_CallState
|
||||||
|
value: 2
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 2846246689251721816, guid: b3fc964bec385174f85a143f2fcff121, type: 3}
|
||||||
|
propertyPath: interactionComplete.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName
|
||||||
|
value: destroyFakeChocolate
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 2846246689251721816, guid: b3fc964bec385174f85a143f2fcff121, type: 3}
|
||||||
|
propertyPath: interactionComplete.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName
|
||||||
|
value: PicnicBehaviour, AppleHillsScripts
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 2846246689251721816, guid: b3fc964bec385174f85a143f2fcff121, type: 3}
|
||||||
|
propertyPath: interactionComplete.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName
|
||||||
|
value: UnityEngine.Object, UnityEngine
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3984039030829909690, guid: b3fc964bec385174f85a143f2fcff121, type: 3}
|
- target: {fileID: 3984039030829909690, guid: b3fc964bec385174f85a143f2fcff121, type: 3}
|
||||||
propertyPath: m_LocalScale.x
|
propertyPath: m_LocalScale.x
|
||||||
value: 0.7
|
value: 0.7
|
||||||
|
|||||||
@@ -135,13 +135,13 @@ AnimatorStateMachine:
|
|||||||
m_ChildStates:
|
m_ChildStates:
|
||||||
- serializedVersion: 1
|
- serializedVersion: 1
|
||||||
m_State: {fileID: -7925442279578022247}
|
m_State: {fileID: -7925442279578022247}
|
||||||
m_Position: {x: 400, y: 370, z: 0}
|
m_Position: {x: 410, y: 370, z: 0}
|
||||||
- serializedVersion: 1
|
- serializedVersion: 1
|
||||||
m_State: {fileID: -892202757677891130}
|
m_State: {fileID: -892202757677891130}
|
||||||
m_Position: {x: -20, y: 260, z: 0}
|
m_Position: {x: -20, y: 260, z: 0}
|
||||||
- serializedVersion: 1
|
- serializedVersion: 1
|
||||||
m_State: {fileID: 1937208649765278840}
|
m_State: {fileID: 1937208649765278840}
|
||||||
m_Position: {x: 489.1548, y: 156.18289, z: 0}
|
m_Position: {x: 490, y: 150, z: 0}
|
||||||
m_ChildStateMachines: []
|
m_ChildStateMachines: []
|
||||||
m_AnyStateTransitions: []
|
m_AnyStateTransitions: []
|
||||||
m_EntryTransitions: []
|
m_EntryTransitions: []
|
||||||
|
|||||||
@@ -120,6 +120,44 @@ MonoBehaviour:
|
|||||||
m_OnClick:
|
m_OnClick:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
|
--- !u!1 &879012544333199198
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 8293076336493130222}
|
||||||
|
m_Layer: 5
|
||||||
|
m_Name: Rainbows
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!224 &8293076336493130222
|
||||||
|
RectTransform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 879012544333199198}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children:
|
||||||
|
- {fileID: 6108475066390421500}
|
||||||
|
- {fileID: 6717870941799174515}
|
||||||
|
- {fileID: 4136733570236406132}
|
||||||
|
m_Father: {fileID: 1315170081792486277}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!1 &904161782565348054
|
--- !u!1 &904161782565348054
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -166,7 +204,7 @@ RectTransform:
|
|||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||||
m_AnchoredPosition: {x: 0, y: 200}
|
m_AnchoredPosition: {x: 0, y: 200}
|
||||||
m_SizeDelta: {x: 1550, y: 700}
|
m_SizeDelta: {x: 1550, y: 750}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!223 &4291423916360628965
|
--- !u!223 &4291423916360628965
|
||||||
Canvas:
|
Canvas:
|
||||||
@@ -252,7 +290,7 @@ MonoBehaviour:
|
|||||||
m_StartCorner: 0
|
m_StartCorner: 0
|
||||||
m_StartAxis: 0
|
m_StartAxis: 0
|
||||||
m_CellSize: {x: 350, y: 350}
|
m_CellSize: {x: 350, y: 350}
|
||||||
m_Spacing: {x: 50, y: 0}
|
m_Spacing: {x: 50, y: 50}
|
||||||
m_Constraint: 2
|
m_Constraint: 2
|
||||||
m_ConstraintCount: 2
|
m_ConstraintCount: 2
|
||||||
--- !u!114 &7425566603516801919
|
--- !u!114 &7425566603516801919
|
||||||
@@ -281,7 +319,6 @@ GameObject:
|
|||||||
- component: {fileID: 6669614972729775195}
|
- component: {fileID: 6669614972729775195}
|
||||||
- component: {fileID: 2981106092574900430}
|
- component: {fileID: 2981106092574900430}
|
||||||
- component: {fileID: 8074691980395114238}
|
- component: {fileID: 8074691980395114238}
|
||||||
- component: {fileID: 1630362919770549177}
|
|
||||||
m_Layer: 5
|
m_Layer: 5
|
||||||
m_Name: AppSwitcher
|
m_Name: AppSwitcher
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -301,8 +338,7 @@ RectTransform:
|
|||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 6108475066390421500}
|
- {fileID: 8293076336493130222}
|
||||||
- {fileID: 1495118611075801417}
|
|
||||||
- {fileID: 808554455652734252}
|
- {fileID: 808554455652734252}
|
||||||
- {fileID: 2831878373711017175}
|
- {fileID: 2831878373711017175}
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
@@ -364,36 +400,14 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: bac6124b3ada8a048a0b87a729a22312, type: 3}
|
m_Script: {fileID: 11500000, guid: bac6124b3ada8a048a0b87a729a22312, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: '::'
|
m_EditorClassIdentifier: '::'
|
||||||
iconIdle: {fileID: 4900000, guid: 50e22b5bb8a496840952f2563758c13c, type: 3}
|
PageName:
|
||||||
iconEstablish: {fileID: 4900000, guid: 975218623da47f8428c484d886554a6c, type: 3}
|
transitionDuration: 0.3
|
||||||
rainbowEstablish: {fileID: 4900000, guid: 622be2ef9d5e27d45a9deaf7ed805f5f, type: 3}
|
rainbowIn: {fileID: 5382650426034128680}
|
||||||
rainbowRemove: {fileID: 4900000, guid: 589505308c5daf449800f30dd4b92ce7, type: 3}
|
rainbowOut: {fileID: 3983328028282460839}
|
||||||
rainbow: {fileID: 5382650426034128680}
|
|
||||||
icon: {fileID: 6784053660381911346}
|
|
||||||
gameLayoutContainer: {fileID: 904161782565348054}
|
gameLayoutContainer: {fileID: 904161782565348054}
|
||||||
exitButton: {fileID: 8427602740714176801}
|
exitButton: {fileID: 8427602740714176801}
|
||||||
--- !u!95 &1630362919770549177
|
rectMask: {fileID: 7425566603516801919}
|
||||||
Animator:
|
slideDuration: 0.6
|
||||||
serializedVersion: 7
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1498581815400593087}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_Avatar: {fileID: 0}
|
|
||||||
m_Controller: {fileID: 9100000, guid: fc380d833ededb441a23b106de60bedd, type: 2}
|
|
||||||
m_CullingMode: 0
|
|
||||||
m_UpdateMode: 2
|
|
||||||
m_ApplyRootMotion: 0
|
|
||||||
m_LinearVelocityBlending: 0
|
|
||||||
m_StabilizeFeet: 0
|
|
||||||
m_AnimatePhysics: 0
|
|
||||||
m_WarningMessage:
|
|
||||||
m_HasTransformHierarchy: 1
|
|
||||||
m_AllowConstantClipSamplingOptimization: 1
|
|
||||||
m_KeepAnimatorStateOnDisable: 0
|
|
||||||
m_WriteDefaultValuesOnDisable: 0
|
|
||||||
--- !u!1 &2426870979657684456
|
--- !u!1 &2426870979657684456
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -514,6 +528,99 @@ MonoBehaviour:
|
|||||||
m_OnClick:
|
m_OnClick:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
|
--- !u!1 &3983328028282460839
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 6717870941799174515}
|
||||||
|
- component: {fileID: 6334910097310371923}
|
||||||
|
- component: {fileID: 8821021733826365168}
|
||||||
|
- component: {fileID: 9163925342151684341}
|
||||||
|
m_Layer: 5
|
||||||
|
m_Name: RainbowOut
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!224 &6717870941799174515
|
||||||
|
RectTransform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 3983328028282460839}
|
||||||
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 8293076336493130222}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
|
--- !u!222 &6334910097310371923
|
||||||
|
CanvasRenderer:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 3983328028282460839}
|
||||||
|
m_CullTransparentMesh: 1
|
||||||
|
--- !u!114 &8821021733826365168
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 3983328028282460839}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 1344c3c82d62a2a41a3576d8abb8e3ea, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.RawImage
|
||||||
|
m_Material: {fileID: 0}
|
||||||
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_RaycastTarget: 1
|
||||||
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_Maskable: 1
|
||||||
|
m_OnCullStateChanged:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_UVRect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 1
|
||||||
|
height: -1
|
||||||
|
--- !u!114 &9163925342151684341
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 3983328028282460839}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 2fd09147b9e9d42a48d6ddc915ddc3d2, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: SkiaSharp.Unity::SkiaSharp.Unity.SkottiePlayerV2
|
||||||
|
lottieFile: {fileID: 4900000, guid: 589505308c5daf449800f30dd4b92ce7, type: 3}
|
||||||
|
customResolution: 0
|
||||||
|
resWidth: 250
|
||||||
|
resHeight: 250
|
||||||
|
stateName:
|
||||||
|
resetAfterFinished: 0
|
||||||
|
autoPlay: 0
|
||||||
|
loop: 0
|
||||||
--- !u!1 &4270065472017787841
|
--- !u!1 &4270065472017787841
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -664,7 +771,7 @@ RectTransform:
|
|||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 6108475066390421500}
|
m_Father: {fileID: 8293076336493130222}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
@@ -842,7 +949,7 @@ GameObject:
|
|||||||
- component: {fileID: 7920249735731934357}
|
- component: {fileID: 7920249735731934357}
|
||||||
- component: {fileID: 3566391948883171773}
|
- component: {fileID: 3566391948883171773}
|
||||||
m_Layer: 5
|
m_Layer: 5
|
||||||
m_Name: Rainbow
|
m_Name: RainbowIn
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
@@ -855,13 +962,12 @@ RectTransform:
|
|||||||
m_PrefabInstance: {fileID: 0}
|
m_PrefabInstance: {fileID: 0}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 5382650426034128680}
|
m_GameObject: {fileID: 5382650426034128680}
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children:
|
m_Children: []
|
||||||
- {fileID: 4136733570236406132}
|
m_Father: {fileID: 8293076336493130222}
|
||||||
m_Father: {fileID: 1315170081792486277}
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
@@ -1043,156 +1149,6 @@ MonoBehaviour:
|
|||||||
m_OnClick:
|
m_OnClick:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
--- !u!1 &6784053660381911346
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 1495118611075801417}
|
|
||||||
- component: {fileID: 9118909078554628244}
|
|
||||||
- component: {fileID: 8490254979303535795}
|
|
||||||
- component: {fileID: 4316986085632541161}
|
|
||||||
- component: {fileID: 6597789131808754055}
|
|
||||||
m_Layer: 5
|
|
||||||
m_Name: Icon
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!224 &1495118611075801417
|
|
||||||
RectTransform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 6784053660381911346}
|
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children: []
|
|
||||||
m_Father: {fileID: 1315170081792486277}
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
m_AnchorMin: {x: 1, y: 1}
|
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
|
||||||
m_AnchoredPosition: {x: -50, y: -50}
|
|
||||||
m_SizeDelta: {x: 200, y: 200}
|
|
||||||
m_Pivot: {x: 1, y: 1}
|
|
||||||
--- !u!222 &9118909078554628244
|
|
||||||
CanvasRenderer:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 6784053660381911346}
|
|
||||||
m_CullTransparentMesh: 1
|
|
||||||
--- !u!114 &8490254979303535795
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 6784053660381911346}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 1344c3c82d62a2a41a3576d8abb8e3ea, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.RawImage
|
|
||||||
m_Material: {fileID: 0}
|
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
||||||
m_RaycastTarget: 1
|
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
m_Maskable: 1
|
|
||||||
m_OnCullStateChanged:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls: []
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_UVRect:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 1
|
|
||||||
height: -1
|
|
||||||
--- !u!114 &4316986085632541161
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 6784053660381911346}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 2fd09147b9e9d42a48d6ddc915ddc3d2, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier: SkiaSharp.Unity::SkiaSharp.Unity.SkottiePlayerV2
|
|
||||||
lottieFile: {fileID: 4900000, guid: 50e22b5bb8a496840952f2563758c13c, type: 3}
|
|
||||||
customResolution: 0
|
|
||||||
resWidth: 250
|
|
||||||
resHeight: 250
|
|
||||||
stateName: Idle
|
|
||||||
resetAfterFinished: 0
|
|
||||||
autoPlay: 1
|
|
||||||
loop: 1
|
|
||||||
--- !u!114 &6597789131808754055
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 6784053660381911346}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Button
|
|
||||||
m_Navigation:
|
|
||||||
m_Mode: 3
|
|
||||||
m_WrapAround: 0
|
|
||||||
m_SelectOnUp: {fileID: 0}
|
|
||||||
m_SelectOnDown: {fileID: 0}
|
|
||||||
m_SelectOnLeft: {fileID: 0}
|
|
||||||
m_SelectOnRight: {fileID: 0}
|
|
||||||
m_Transition: 1
|
|
||||||
m_Colors:
|
|
||||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
|
||||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
|
||||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
|
||||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
|
||||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
|
||||||
m_ColorMultiplier: 1
|
|
||||||
m_FadeDuration: 0.1
|
|
||||||
m_SpriteState:
|
|
||||||
m_HighlightedSprite: {fileID: 0}
|
|
||||||
m_PressedSprite: {fileID: 0}
|
|
||||||
m_SelectedSprite: {fileID: 0}
|
|
||||||
m_DisabledSprite: {fileID: 0}
|
|
||||||
m_AnimationTriggers:
|
|
||||||
m_NormalTrigger: Normal
|
|
||||||
m_HighlightedTrigger: Highlighted
|
|
||||||
m_PressedTrigger: Pressed
|
|
||||||
m_SelectedTrigger: Selected
|
|
||||||
m_DisabledTrigger: Disabled
|
|
||||||
m_Interactable: 1
|
|
||||||
m_TargetGraphic: {fileID: 8490254979303535795}
|
|
||||||
m_OnClick:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls:
|
|
||||||
- m_Target: {fileID: 8074691980395114238}
|
|
||||||
m_TargetAssemblyTypeName: AppSwitcher, AppleHillsScripts
|
|
||||||
m_MethodName: OpenAppSwitcher
|
|
||||||
m_Mode: 1
|
|
||||||
m_Arguments:
|
|
||||||
m_ObjectArgument: {fileID: 0}
|
|
||||||
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
|
|
||||||
m_IntArgument: 0
|
|
||||||
m_FloatArgument: 0
|
|
||||||
m_StringArgument:
|
|
||||||
m_BoolArgument: 0
|
|
||||||
m_CallState: 2
|
|
||||||
--- !u!1 &7713997083397969887
|
--- !u!1 &7713997083397969887
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1565,6 +1521,7 @@ GameObject:
|
|||||||
- component: {fileID: 5972191288640444065}
|
- component: {fileID: 5972191288640444065}
|
||||||
- component: {fileID: 236099612463072939}
|
- component: {fileID: 236099612463072939}
|
||||||
- component: {fileID: 447310668687539451}
|
- component: {fileID: 447310668687539451}
|
||||||
|
- component: {fileID: 6704345904811573523}
|
||||||
m_Layer: 5
|
m_Layer: 5
|
||||||
m_Name: CloseUIButton
|
m_Name: CloseUIButton
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -1675,7 +1632,7 @@ MonoBehaviour:
|
|||||||
m_Calls:
|
m_Calls:
|
||||||
- m_Target: {fileID: 8074691980395114238}
|
- m_Target: {fileID: 8074691980395114238}
|
||||||
m_TargetAssemblyTypeName: AppSwitcher, AppleHillsScripts
|
m_TargetAssemblyTypeName: AppSwitcher, AppleHillsScripts
|
||||||
m_MethodName: CloseAppSwitcher
|
m_MethodName: OnBackPressed
|
||||||
m_Mode: 1
|
m_Mode: 1
|
||||||
m_Arguments:
|
m_Arguments:
|
||||||
m_ObjectArgument: {fileID: 0}
|
m_ObjectArgument: {fileID: 0}
|
||||||
@@ -1685,3 +1642,15 @@ MonoBehaviour:
|
|||||||
m_StringArgument:
|
m_StringArgument:
|
||||||
m_BoolArgument: 0
|
m_BoolArgument: 0
|
||||||
m_CallState: 2
|
m_CallState: 2
|
||||||
|
--- !u!114 &6704345904811573523
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 8427602740714176801}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 494d0aedce9744308499355006071138, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: AppleHillsScripts::UI.DummyInput
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -285,8 +285,8 @@ RectTransform:
|
|||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 1}
|
m_AnchorMin: {x: 0.5, y: 1}
|
||||||
m_AnchorMax: {x: 0.5, y: 1}
|
m_AnchorMax: {x: 0.5, y: 1}
|
||||||
m_AnchoredPosition: {x: 0, y: 173}
|
m_AnchoredPosition: {x: 0, y: 125}
|
||||||
m_SizeDelta: {x: 600, y: 150}
|
m_SizeDelta: {x: 600, y: 120}
|
||||||
m_Pivot: {x: 0.5, y: 1}
|
m_Pivot: {x: 0.5, y: 1}
|
||||||
--- !u!222 &5545241165728741220
|
--- !u!222 &5545241165728741220
|
||||||
CanvasRenderer:
|
CanvasRenderer:
|
||||||
@@ -343,8 +343,8 @@ MonoBehaviour:
|
|||||||
m_faceColor:
|
m_faceColor:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
rgba: 4294967295
|
rgba: 4294967295
|
||||||
m_fontSize: 150
|
m_fontSize: 125
|
||||||
m_fontSizeBase: 150
|
m_fontSizeBase: 125
|
||||||
m_fontWeight: 400
|
m_fontWeight: 400
|
||||||
m_enableAutoSizing: 0
|
m_enableAutoSizing: 0
|
||||||
m_fontSizeMin: 18
|
m_fontSizeMin: 18
|
||||||
@@ -1053,6 +1053,10 @@ PrefabInstance:
|
|||||||
propertyPath: m_SizeDelta.x
|
propertyPath: m_SizeDelta.x
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4925415087786595420, guid: 1d8cc8d9238eec34b8e600e7050e2979, type: 3}
|
||||||
|
propertyPath: m_fontSize
|
||||||
|
value: 54.45
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 5378230129755544441, guid: 1d8cc8d9238eec34b8e600e7050e2979, type: 3}
|
- target: {fileID: 5378230129755544441, guid: 1d8cc8d9238eec34b8e600e7050e2979, type: 3}
|
||||||
propertyPath: m_AnchorMax.x
|
propertyPath: m_AnchorMax.x
|
||||||
value: 0
|
value: 0
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -453761,6 +453761,10 @@ PrefabInstance:
|
|||||||
propertyPath: m_PlayOnAwake
|
propertyPath: m_PlayOnAwake
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8545106365577783398, guid: ead4e790fa3a1924ebd1586c93cd5479, type: 3}
|
||||||
|
propertyPath: isOneTime
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
|
|||||||
@@ -1562,7 +1562,7 @@ AudioSource:
|
|||||||
OutputAudioMixerGroup: {fileID: 3533147658878909314, guid: 727a7e4b6df4b0d47897f7d8ee7fa323, type: 2}
|
OutputAudioMixerGroup: {fileID: 3533147658878909314, guid: 727a7e4b6df4b0d47897f7d8ee7fa323, type: 2}
|
||||||
m_audioClip: {fileID: 0}
|
m_audioClip: {fileID: 0}
|
||||||
m_Resource: {fileID: 0}
|
m_Resource: {fileID: 0}
|
||||||
m_PlayOnAwake: 1
|
m_PlayOnAwake: 0
|
||||||
m_Volume: 1
|
m_Volume: 1
|
||||||
m_Pitch: 1
|
m_Pitch: 1
|
||||||
Loop: 0
|
Loop: 0
|
||||||
@@ -3633,6 +3633,18 @@ PrefabInstance:
|
|||||||
propertyPath: m_Name
|
propertyPath: m_Name
|
||||||
value: Tutorial
|
value: Tutorial
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4267886887244421663, guid: a4dd78ff48942854ebb4c65025a8dc36, type: 3}
|
||||||
|
propertyPath: introVO
|
||||||
|
value:
|
||||||
|
objectReference: {fileID: 8300000, guid: fca641cdc8dcd074483fad3db1cbe24c, type: 3}
|
||||||
|
- target: {fileID: 4267886887244421663, guid: a4dd78ff48942854ebb4c65025a8dc36, type: 3}
|
||||||
|
propertyPath: playTutorial
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4267886887244421663, guid: a4dd78ff48942854ebb4c65025a8dc36, type: 3}
|
||||||
|
propertyPath: bottleAudioPlayer
|
||||||
|
value:
|
||||||
|
objectReference: {fileID: 747976408}
|
||||||
- target: {fileID: 8452897808363562605, guid: a4dd78ff48942854ebb4c65025a8dc36, type: 3}
|
- target: {fileID: 8452897808363562605, guid: a4dd78ff48942854ebb4c65025a8dc36, type: 3}
|
||||||
propertyPath: m_Sprite
|
propertyPath: m_Sprite
|
||||||
value:
|
value:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -56,7 +56,7 @@ public class BirdEyesBehavior : ManagedBehaviour
|
|||||||
_statemachine.ChangeState("BirdSpawned");
|
_statemachine.ChangeState("BirdSpawned");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneRestoreRequested(string serializedData)
|
internal override void OnSceneRestoreRequested(string serializedData)
|
||||||
{
|
{
|
||||||
base.OnSceneRestoreRequested(serializedData);
|
base.OnSceneRestoreRequested(serializedData);
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ public class BirdEyesBehavior : ManagedBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string OnSceneSaveRequested()
|
internal override string OnSceneSaveRequested()
|
||||||
{
|
{
|
||||||
return _wolterisoutTriggered.ToString();
|
return _wolterisoutTriggered.ToString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using AppleHills.Core.Settings;
|
using AppleHills.Core.Settings;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Core;
|
using Core;
|
||||||
@@ -30,14 +30,10 @@ namespace Bootstrap
|
|||||||
private float _sceneLoadingProgress = 0f;
|
private float _sceneLoadingProgress = 0f;
|
||||||
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
|
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
|
||||||
|
|
||||||
// Run very early - need to set up loading screen before other systems initialize
|
|
||||||
public override int ManagedAwakePriority => 5;
|
|
||||||
|
|
||||||
protected override void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake(); // Register with LifecycleManager
|
Logging.Debug("BootSceneController.Awake() - Initializing loading screen DURING bootstrap");
|
||||||
|
|
||||||
LogDebugMessage("BootSceneController.Awake() - Initializing loading screen DURING bootstrap");
|
|
||||||
|
|
||||||
// Validate loading screen exists
|
// Validate loading screen exists
|
||||||
if (initialLoadingScreen == null)
|
if (initialLoadingScreen == null)
|
||||||
@@ -71,11 +67,11 @@ namespace Bootstrap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
LogDebugMessage("BootSceneController.OnManagedAwake() - Boot is GUARANTEED complete, starting scene loading");
|
Logging.Debug("BootSceneController.OnManagedStart() - Boot is GUARANTEED complete, starting scene loading");
|
||||||
|
|
||||||
// Boot is GUARANTEED complete at this point - that's the whole point of OnManagedAwake!
|
// Boot is GUARANTEED complete at this point - that's the whole point of OnManagedStart!
|
||||||
// No need to subscribe to OnBootCompleted or check CustomBoot.Initialised
|
// No need to subscribe to OnBootCompleted or check CustomBoot.Initialised
|
||||||
_bootComplete = true;
|
_bootComplete = true;
|
||||||
_currentPhase = LoadingPhase.SceneLoading;
|
_currentPhase = LoadingPhase.SceneLoading;
|
||||||
@@ -85,10 +81,8 @@ namespace Bootstrap
|
|||||||
Invoke(nameof(StartLoadingMainMenu), minDelayAfterBoot);
|
Invoke(nameof(StartLoadingMainMenu), minDelayAfterBoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
// Manual cleanup for events
|
// Manual cleanup for events
|
||||||
if (initialLoadingScreen != null)
|
if (initialLoadingScreen != null)
|
||||||
{
|
{
|
||||||
@@ -102,12 +96,12 @@ namespace Bootstrap
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnInitialLoadingComplete()
|
private void OnInitialLoadingComplete()
|
||||||
{
|
{
|
||||||
LogDebugMessage("Initial loading screen fully hidden, boot sequence completed");
|
Logging.Debug("Initial loading screen fully hidden, boot sequence completed");
|
||||||
|
|
||||||
// Play the intro cinematic if available
|
// Play the intro cinematic if available
|
||||||
if (CinematicsManager.Instance != null)
|
if (CinematicsManager.Instance != null)
|
||||||
{
|
{
|
||||||
LogDebugMessage("Attempting to play intro cinematic");
|
Logging.Debug("Attempting to play intro cinematic");
|
||||||
|
|
||||||
// Use LoadAndPlayCinematic to play the intro sequence
|
// Use LoadAndPlayCinematic to play the intro sequence
|
||||||
CinematicsManager.Instance.LoadAndPlayCinematic("IntroSequence", false);
|
CinematicsManager.Instance.LoadAndPlayCinematic("IntroSequence", false);
|
||||||
@@ -149,13 +143,13 @@ namespace Bootstrap
|
|||||||
{
|
{
|
||||||
if (debugMode)
|
if (debugMode)
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Bootstrap progress: {progress:P0}, Combined: {GetCombinedProgress():P0}");
|
Logging.Debug($"Bootstrap progress: {progress:P0}, Combined: {GetCombinedProgress():P0}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LogDebugInfo()
|
private void LogDebugInfo()
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Debug - Phase: {_currentPhase}, Bootstrap: {CustomBoot.CurrentProgress:P0}, " +
|
Logging.Debug($"Debug - Phase: {_currentPhase}, Bootstrap: {CustomBoot.CurrentProgress:P0}, " +
|
||||||
$"Scene: {_sceneLoadingProgress:P0}, Combined: {GetCombinedProgress():P0}, Boot Complete: {_bootComplete}");
|
$"Scene: {_sceneLoadingProgress:P0}, Combined: {GetCombinedProgress():P0}, Boot Complete: {_bootComplete}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +166,7 @@ namespace Bootstrap
|
|||||||
|
|
||||||
private async void LoadMainScene()
|
private async void LoadMainScene()
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Loading main menu scene: {mainSceneName}");
|
Logging.Debug($"Loading main menu scene: {mainSceneName}");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -186,7 +180,7 @@ namespace Bootstrap
|
|||||||
|
|
||||||
if (debugMode)
|
if (debugMode)
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Scene loading raw: {value:P0}, Combined: {GetCombinedProgress():P0}");
|
Logging.Debug($"Scene loading raw: {value:P0}, Combined: {GetCombinedProgress():P0}");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -210,13 +204,13 @@ namespace Bootstrap
|
|||||||
_sceneLoadingProgress = 1f;
|
_sceneLoadingProgress = 1f;
|
||||||
|
|
||||||
// CRITICAL: Broadcast lifecycle events so components get their OnSceneReady callbacks
|
// CRITICAL: Broadcast lifecycle events so components get their OnSceneReady callbacks
|
||||||
LogDebugMessage($"Broadcasting OnSceneReady for: {mainSceneName}");
|
Logging.Debug($"Broadcasting OnSceneReady for: {mainSceneName}");
|
||||||
LifecycleManager.Instance?.BroadcastSceneReady(mainSceneName);
|
LifecycleManager.Instance?.BroadcastSceneReady(mainSceneName);
|
||||||
|
|
||||||
// Restore scene data for the main menu
|
// Restore scene data for the main menu
|
||||||
if (SaveLoadManager.Instance != null)
|
if (SaveLoadManager.Instance != null)
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Restoring scene data for: {mainSceneName}");
|
Logging.Debug($"Restoring scene data for: {mainSceneName}");
|
||||||
SaveLoadManager.Instance.RestoreSceneData();
|
SaveLoadManager.Instance.RestoreSceneData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +240,7 @@ namespace Bootstrap
|
|||||||
Scene currentScene = SceneManager.GetActiveScene();
|
Scene currentScene = SceneManager.GetActiveScene();
|
||||||
string startingSceneName = currentScene.name;
|
string startingSceneName = currentScene.name;
|
||||||
|
|
||||||
LogDebugMessage($"Unloading StartingScene: {startingSceneName}");
|
Logging.Debug($"Unloading StartingScene: {startingSceneName}");
|
||||||
|
|
||||||
// Unload the StartingScene
|
// Unload the StartingScene
|
||||||
await SceneManager.UnloadSceneAsync(startingSceneName);
|
await SceneManager.UnloadSceneAsync(startingSceneName);
|
||||||
@@ -255,14 +249,14 @@ namespace Bootstrap
|
|||||||
Scene mainMenuScene = SceneManager.GetSceneByName(mainSceneName);
|
Scene mainMenuScene = SceneManager.GetSceneByName(mainSceneName);
|
||||||
SceneManager.SetActiveScene(mainMenuScene);
|
SceneManager.SetActiveScene(mainMenuScene);
|
||||||
|
|
||||||
LogDebugMessage($"Transition complete: {startingSceneName} unloaded, {mainSceneName} is now active");
|
Logging.Debug($"Transition complete: {startingSceneName} unloaded, {mainSceneName} is now active");
|
||||||
|
|
||||||
// Destroy the boot scene controller since its job is done
|
// Destroy the boot scene controller since its job is done
|
||||||
Destroy(gameObject);
|
Destroy(gameObject);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logging.Warning($"[BootSceneController] Error unloading StartingScene: {e.Message}");
|
Logging.Warning($"Error unloading StartingScene: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,13 +277,5 @@ namespace Bootstrap
|
|||||||
_progressAction?.Invoke(value);
|
_progressAction?.Invoke(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LogDebugMessage(string message)
|
|
||||||
{
|
|
||||||
if ( _logVerbosity <= LogVerbosity.Debug)
|
|
||||||
{
|
|
||||||
Logging.Debug($"[BootSceneController] {message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AppleHills.Core.Settings;
|
|
||||||
using Core;
|
using Core;
|
||||||
using Core.Lifecycle;
|
using Core.Lifecycle;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -105,7 +104,7 @@ namespace Bootstrap
|
|||||||
// Notify the LifecycleManager that boot is complete
|
// Notify the LifecycleManager that boot is complete
|
||||||
if (Application.isPlaying)
|
if (Application.isPlaying)
|
||||||
{
|
{
|
||||||
LogDebugMessage("Calling LifecycleManager.OnBootCompletionTriggered()");
|
Logging.Debug("Calling LifecycleManager.OnBootCompletionTriggered()");
|
||||||
if (LifecycleManager.Instance != null)
|
if (LifecycleManager.Instance != null)
|
||||||
{
|
{
|
||||||
LifecycleManager.Instance.OnBootCompletionTriggered();
|
LifecycleManager.Instance.OnBootCompletionTriggered();
|
||||||
@@ -127,7 +126,7 @@ namespace Bootstrap
|
|||||||
// Notify the LifecycleManager that boot is complete
|
// Notify the LifecycleManager that boot is complete
|
||||||
if (Application.isPlaying)
|
if (Application.isPlaying)
|
||||||
{
|
{
|
||||||
LogDebugMessage("Calling LifecycleManager.OnBootCompletionTriggered()");
|
Logging.Debug("Calling LifecycleManager.OnBootCompletionTriggered()");
|
||||||
if (LifecycleManager.Instance != null)
|
if (LifecycleManager.Instance != null)
|
||||||
{
|
{
|
||||||
LifecycleManager.Instance.OnBootCompletionTriggered();
|
LifecycleManager.Instance.OnBootCompletionTriggered();
|
||||||
@@ -238,16 +237,7 @@ namespace Bootstrap
|
|||||||
{
|
{
|
||||||
CurrentProgress = Mathf.Clamp01(progress);
|
CurrentProgress = Mathf.Clamp01(progress);
|
||||||
OnBootProgressChanged?.Invoke(CurrentProgress);
|
OnBootProgressChanged?.Invoke(CurrentProgress);
|
||||||
LogDebugMessage($"Progress: {CurrentProgress:P0}");
|
Logging.Debug($"Progress: {CurrentProgress:P0}");
|
||||||
}
|
|
||||||
|
|
||||||
private static void LogDebugMessage(string message)
|
|
||||||
{
|
|
||||||
if (DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().bootstrapLogVerbosity <=
|
|
||||||
LogVerbosity.Debug)
|
|
||||||
{
|
|
||||||
Logging.Debug($"[CustomBoot] {message}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,7 +138,7 @@ namespace Bootstrap
|
|||||||
float displayProgress = Mathf.Min(steadyProgress, actualProgress);
|
float displayProgress = Mathf.Min(steadyProgress, actualProgress);
|
||||||
|
|
||||||
// Log the progress values for debugging
|
// Log the progress values for debugging
|
||||||
LogDebugMessage($"Progress - Default: {steadyProgress:F2}, Actual: {actualProgress:F2}, Display: {displayProgress:F2}");
|
Logging.Debug($"Progress - Default: {steadyProgress:F2}, Actual: {actualProgress:F2}, Display: {displayProgress:F2}");
|
||||||
|
|
||||||
// Directly set the progress bar fill amount without smoothing
|
// Directly set the progress bar fill amount without smoothing
|
||||||
if (progressBarImage != null)
|
if (progressBarImage != null)
|
||||||
@@ -151,7 +151,7 @@ namespace Bootstrap
|
|||||||
if (steadyProgress >= 1.0f && displayProgress >= 1.0f)
|
if (steadyProgress >= 1.0f && displayProgress >= 1.0f)
|
||||||
{
|
{
|
||||||
_animationComplete = true;
|
_animationComplete = true;
|
||||||
LogDebugMessage("Animation complete");
|
Logging.Debug("Animation complete");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +163,7 @@ namespace Bootstrap
|
|||||||
if (progressBarImage != null)
|
if (progressBarImage != null)
|
||||||
{
|
{
|
||||||
progressBarImage.fillAmount = 1.0f;
|
progressBarImage.fillAmount = 1.0f;
|
||||||
LogDebugMessage("Final progress set to 1.0");
|
Logging.Debug("Final progress set to 1.0");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide the screen if loading is also complete
|
// Hide the screen if loading is also complete
|
||||||
@@ -172,7 +172,7 @@ namespace Bootstrap
|
|||||||
if (loadingScreenContainer != null)
|
if (loadingScreenContainer != null)
|
||||||
{
|
{
|
||||||
loadingScreenContainer.SetActive(false);
|
loadingScreenContainer.SetActive(false);
|
||||||
LogDebugMessage("Animation AND loading complete, hiding screen");
|
Logging.Debug("Animation AND loading complete, hiding screen");
|
||||||
|
|
||||||
// Invoke the callback when fully hidden
|
// Invoke the callback when fully hidden
|
||||||
_onLoadingScreenFullyHidden?.Invoke();
|
_onLoadingScreenFullyHidden?.Invoke();
|
||||||
@@ -189,7 +189,7 @@ namespace Bootstrap
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void HideLoadingScreen()
|
public void HideLoadingScreen()
|
||||||
{
|
{
|
||||||
LogDebugMessage("Loading complete, marking loading as finished");
|
Logging.Debug("Loading complete, marking loading as finished");
|
||||||
|
|
||||||
// Mark that loading is complete
|
// Mark that loading is complete
|
||||||
_loadingComplete = true;
|
_loadingComplete = true;
|
||||||
@@ -200,7 +200,7 @@ namespace Bootstrap
|
|||||||
if (loadingScreenContainer != null)
|
if (loadingScreenContainer != null)
|
||||||
{
|
{
|
||||||
loadingScreenContainer.SetActive(false);
|
loadingScreenContainer.SetActive(false);
|
||||||
LogDebugMessage("Animation already complete, hiding screen immediately");
|
Logging.Debug("Animation already complete, hiding screen immediately");
|
||||||
|
|
||||||
// Invoke the callback when fully hidden
|
// Invoke the callback when fully hidden
|
||||||
_onLoadingScreenFullyHidden?.Invoke();
|
_onLoadingScreenFullyHidden?.Invoke();
|
||||||
@@ -210,7 +210,7 @@ namespace Bootstrap
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogDebugMessage("Animation still in progress, waiting for it to complete");
|
Logging.Debug("Animation still in progress, waiting for it to complete");
|
||||||
// The coroutine will handle hiding when animation completes
|
// The coroutine will handle hiding when animation completes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,13 +244,5 @@ namespace Bootstrap
|
|||||||
|
|
||||||
return tcs.Task;
|
return tcs.Task;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LogDebugMessage(string message)
|
|
||||||
{
|
|
||||||
if ( _logVerbosity <= LogVerbosity.Debug)
|
|
||||||
{
|
|
||||||
Logging.Debug($"[InitialLoadingScreen] {message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,17 +37,13 @@ namespace Cinematics
|
|||||||
|
|
||||||
public PlayableDirector playableDirector;
|
public PlayableDirector playableDirector;
|
||||||
|
|
||||||
public override int ManagedAwakePriority => 170; // Cinematic systems
|
internal override void OnManagedAwake()
|
||||||
|
|
||||||
private new void Awake()
|
|
||||||
{
|
{
|
||||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
// Set instance immediately (early initialization)
|
||||||
|
|
||||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
Logging.Debug("[CinematicsManager] Initialized");
|
Logging.Debug("[CinematicsManager] Initialized");
|
||||||
}
|
}
|
||||||
@@ -86,7 +82,7 @@ namespace Cinematics
|
|||||||
// If still null, try to add the component
|
// If still null, try to add the component
|
||||||
if (playableDirector == null)
|
if (playableDirector == null)
|
||||||
{
|
{
|
||||||
Debug.Log("[CinematicsManager] Could not find Playable Director on the PlayerHudManager");
|
Logging.Debug("[CinematicsManager] Could not find Playable Director on the PlayerHudManager");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +95,7 @@ namespace Cinematics
|
|||||||
// If still null, return error
|
// If still null, return error
|
||||||
if (_cinematicSprites == null)
|
if (_cinematicSprites == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[CinematicsManager] No Image found for cinematics display. Cinematics may not display correctly.");
|
Logging.Warning("[CinematicsManager] No Image found for cinematics display. Cinematics may not display correctly.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,11 +15,8 @@ namespace Cinematics
|
|||||||
private float _holdStartTime;
|
private float _holdStartTime;
|
||||||
private bool _isHolding;
|
private bool _isHolding;
|
||||||
private bool _skipPerformed;
|
private bool _skipPerformed;
|
||||||
private bool _initialized = false;
|
|
||||||
|
|
||||||
public override int ManagedAwakePriority => 180; // Cinematic UI
|
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
// Reset the progress bar
|
// Reset the progress bar
|
||||||
if (radialProgressBar != null)
|
if (radialProgressBar != null)
|
||||||
@@ -33,10 +30,8 @@ namespace Cinematics
|
|||||||
Logging.Debug("[SkipCinematic] Initialized");
|
Logging.Debug("[SkipCinematic] Initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
// Clean up subscriptions
|
// Clean up subscriptions
|
||||||
UnsubscribeFromCinematicsEvents();
|
UnsubscribeFromCinematicsEvents();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,17 +34,13 @@ namespace Core
|
|||||||
public event Action OnGamePaused;
|
public event Action OnGamePaused;
|
||||||
public event Action OnGameResumed;
|
public event Action OnGameResumed;
|
||||||
|
|
||||||
// ManagedBehaviour configuration
|
|
||||||
public override int ManagedAwakePriority => 10; // Core infrastructure - runs early
|
|
||||||
|
|
||||||
private new void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
// Set instance immediately (early initialization)
|
||||||
|
|
||||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
|
|
||||||
// Create settings providers - must happen in Awake so other managers can access settings in their ManagedAwake
|
// Create settings providers - must happen in OnManagedAwake so other managers can access settings in their ManagedStart
|
||||||
SettingsProvider.Instance.gameObject.name = "Settings Provider";
|
SettingsProvider.Instance.gameObject.name = "Settings Provider";
|
||||||
DeveloperSettingsProvider.Instance.gameObject.name = "Developer Settings Provider";
|
DeveloperSettingsProvider.Instance.gameObject.name = "Developer Settings Provider";
|
||||||
|
|
||||||
@@ -57,9 +53,9 @@ namespace Core
|
|||||||
_managerLogVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().gameManagerLogVerbosity;
|
_managerLogVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().gameManagerLogVerbosity;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
// Settings are already initialized in Awake()
|
// Settings are already initialized in OnManagedAwake()
|
||||||
// This is available for future initialization that depends on other managers
|
// This is available for future initialization that depends on other managers
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +75,7 @@ namespace Core
|
|||||||
component.Pause();
|
component.Pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
LogDebugMessage($"Registered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}");
|
Logging.Debug($"Registered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +88,7 @@ namespace Core
|
|||||||
if (component != null && _pausableComponents.Contains(component))
|
if (component != null && _pausableComponents.Contains(component))
|
||||||
{
|
{
|
||||||
_pausableComponents.Remove(component);
|
_pausableComponents.Remove(component);
|
||||||
LogDebugMessage($"Unregistered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}");
|
Logging.Debug($"Unregistered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +104,7 @@ namespace Core
|
|||||||
ApplyPause(true);
|
ApplyPause(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
LogDebugMessage($"Pause requested by {requester?.ToString() ?? "Unknown"}. pauseCount = {_pauseCount}");
|
Logging.Debug($"Pause requested by {requester?.ToString() ?? "Unknown"}. pauseCount = {_pauseCount}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -123,7 +119,7 @@ namespace Core
|
|||||||
ApplyPause(false);
|
ApplyPause(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
LogDebugMessage($"Pause released by {requester?.ToString() ?? "Unknown"}. pauseCount = {_pauseCount}");
|
Logging.Debug($"Pause released by {requester?.ToString() ?? "Unknown"}. pauseCount = {_pauseCount}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -162,12 +158,12 @@ namespace Core
|
|||||||
OnGameResumed?.Invoke();
|
OnGameResumed?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
LogDebugMessage($"Game {(shouldPause ? "paused" : "resumed")}. Paused {_pausableComponents.Count} components.");
|
Logging.Debug($"Game {(shouldPause ? "paused" : "resumed")}. Paused {_pausableComponents.Count} components.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeSettings()
|
private void InitializeSettings()
|
||||||
{
|
{
|
||||||
LogDebugMessage("Starting settings initialization...", "SettingsInitialization", _settingsLogVerbosity);
|
Logging.Debug("Starting settings initialization...");
|
||||||
|
|
||||||
// Load settings synchronously
|
// Load settings synchronously
|
||||||
var playerSettings = SettingsProvider.Instance.LoadSettingsSynchronous<PlayerFollowerSettings>();
|
var playerSettings = SettingsProvider.Instance.LoadSettingsSynchronous<PlayerFollowerSettings>();
|
||||||
@@ -178,7 +174,7 @@ namespace Core
|
|||||||
if (playerSettings != null)
|
if (playerSettings != null)
|
||||||
{
|
{
|
||||||
ServiceLocator.Register<IPlayerFollowerSettings>(playerSettings);
|
ServiceLocator.Register<IPlayerFollowerSettings>(playerSettings);
|
||||||
LogDebugMessage("PlayerFollowerSettings registered successfully", "SettingsInitialization", _settingsLogVerbosity);
|
Logging.Debug("PlayerFollowerSettings registered successfully");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -188,7 +184,7 @@ namespace Core
|
|||||||
if (interactionSettings != null)
|
if (interactionSettings != null)
|
||||||
{
|
{
|
||||||
ServiceLocator.Register<IInteractionSettings>(interactionSettings);
|
ServiceLocator.Register<IInteractionSettings>(interactionSettings);
|
||||||
LogDebugMessage("InteractionSettings registered successfully", "SettingsInitialization", _settingsLogVerbosity);
|
Logging.Debug("InteractionSettings registered successfully");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -198,7 +194,7 @@ namespace Core
|
|||||||
if (minigameSettings != null)
|
if (minigameSettings != null)
|
||||||
{
|
{
|
||||||
ServiceLocator.Register<IDivingMinigameSettings>(minigameSettings);
|
ServiceLocator.Register<IDivingMinigameSettings>(minigameSettings);
|
||||||
LogDebugMessage("MinigameSettings registered successfully", "SettingsInitialization", _settingsLogVerbosity);
|
Logging.Debug("MinigameSettings registered successfully");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -209,7 +205,7 @@ namespace Core
|
|||||||
_settingsLoaded = playerSettings != null && interactionSettings != null && minigameSettings != null;
|
_settingsLoaded = playerSettings != null && interactionSettings != null && minigameSettings != null;
|
||||||
if (_settingsLoaded)
|
if (_settingsLoaded)
|
||||||
{
|
{
|
||||||
LogDebugMessage("All settings loaded and registered with ServiceLocator", "SettingsInitialization", _settingsLogVerbosity);
|
Logging.Debug("All settings loaded and registered with ServiceLocator");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -222,7 +218,7 @@ namespace Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeDeveloperSettings()
|
private void InitializeDeveloperSettings()
|
||||||
{
|
{
|
||||||
LogDebugMessage("Starting developer settings initialization...", "SettingsInitialization", _settingsLogVerbosity);
|
Logging.Debug("Starting developer settings initialization...");
|
||||||
|
|
||||||
// Load developer settings
|
// Load developer settings
|
||||||
var divingDevSettings = DeveloperSettingsProvider.Instance.GetSettings<DivingDeveloperSettings>();
|
var divingDevSettings = DeveloperSettingsProvider.Instance.GetSettings<DivingDeveloperSettings>();
|
||||||
@@ -232,7 +228,7 @@ namespace Core
|
|||||||
|
|
||||||
if (_developerSettingsLoaded)
|
if (_developerSettingsLoaded)
|
||||||
{
|
{
|
||||||
LogDebugMessage("All developer settings loaded successfully", "SettingsInitialization", _settingsLogVerbosity);
|
Logging.Debug("All developer settings loaded successfully");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -266,19 +262,6 @@ namespace Core
|
|||||||
{
|
{
|
||||||
return DeveloperSettingsProvider.Instance?.GetSettings<T>();
|
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
|
// LEFTOVER LEGACY SETTINGS
|
||||||
public float PlayerStopDistance => GetSettings<IInteractionSettings>()?.PlayerStopDistance ?? 6.0f;
|
public float PlayerStopDistance => GetSettings<IInteractionSettings>()?.PlayerStopDistance ?? 6.0f;
|
||||||
|
|||||||
@@ -47,32 +47,26 @@ namespace Core
|
|||||||
// Broadcasts when any two items are successfully combined
|
// Broadcasts when any two items are successfully combined
|
||||||
// Args: first item data, second item data, result item data
|
// Args: first item data, second item data, result item data
|
||||||
public event Action<PickupItemData, PickupItemData, PickupItemData> OnItemsCombined;
|
public event Action<PickupItemData, PickupItemData, PickupItemData> OnItemsCombined;
|
||||||
|
|
||||||
public override int ManagedAwakePriority => 75; // Item registry
|
|
||||||
|
|
||||||
private new void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
// Set instance immediately (early initialization)
|
||||||
|
|
||||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
Logging.Debug("[ItemManager] Initialized");
|
Logging.Debug("[ItemManager] Initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneReady()
|
internal override void OnSceneReady()
|
||||||
{
|
{
|
||||||
// Replaces SceneLoadStarted subscription for clearing registrations
|
// Replaces SceneLoadStarted subscription for clearing registrations
|
||||||
ClearAllRegistrations();
|
ClearAllRegistrations();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
// Ensure we clean up any subscriptions from registered items when the manager is destroyed
|
// Ensure we clean up any subscriptions from registered items when the manager is destroyed
|
||||||
ClearAllRegistrations();
|
ClearAllRegistrations();
|
||||||
}
|
}
|
||||||
@@ -144,7 +138,6 @@ namespace Core
|
|||||||
{
|
{
|
||||||
s.OnCorrectItemSlotted -= ItemSlot_OnCorrectItemSlotted;
|
s.OnCorrectItemSlotted -= ItemSlot_OnCorrectItemSlotted;
|
||||||
s.OnIncorrectItemSlotted -= ItemSlot_OnIncorrectItemSlotted;
|
s.OnIncorrectItemSlotted -= ItemSlot_OnIncorrectItemSlotted;
|
||||||
s.OnForbiddenItemSlotted -= ItemSlot_OnForbiddenItemSlotted;
|
|
||||||
s.OnItemSlotRemoved -= ItemSlot_OnItemSlotRemoved;
|
s.OnItemSlotRemoved -= ItemSlot_OnItemSlotRemoved;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,7 +184,6 @@ namespace Core
|
|||||||
// Subscribe to all slot events
|
// Subscribe to all slot events
|
||||||
slot.OnCorrectItemSlotted += ItemSlot_OnCorrectItemSlotted;
|
slot.OnCorrectItemSlotted += ItemSlot_OnCorrectItemSlotted;
|
||||||
slot.OnIncorrectItemSlotted += ItemSlot_OnIncorrectItemSlotted;
|
slot.OnIncorrectItemSlotted += ItemSlot_OnIncorrectItemSlotted;
|
||||||
slot.OnForbiddenItemSlotted += ItemSlot_OnForbiddenItemSlotted;
|
|
||||||
slot.OnItemSlotRemoved += ItemSlot_OnItemSlotRemoved;
|
slot.OnItemSlotRemoved += ItemSlot_OnItemSlotRemoved;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,7 +196,6 @@ namespace Core
|
|||||||
// Unsubscribe from all slot events
|
// Unsubscribe from all slot events
|
||||||
slot.OnCorrectItemSlotted -= ItemSlot_OnCorrectItemSlotted;
|
slot.OnCorrectItemSlotted -= ItemSlot_OnCorrectItemSlotted;
|
||||||
slot.OnIncorrectItemSlotted -= ItemSlot_OnIncorrectItemSlotted;
|
slot.OnIncorrectItemSlotted -= ItemSlot_OnIncorrectItemSlotted;
|
||||||
slot.OnForbiddenItemSlotted -= ItemSlot_OnForbiddenItemSlotted;
|
|
||||||
slot.OnItemSlotRemoved -= ItemSlot_OnItemSlotRemoved;
|
slot.OnItemSlotRemoved -= ItemSlot_OnItemSlotRemoved;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,19 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public enum LifecyclePhase
|
public enum LifecyclePhase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Called immediately during registration (during Awake).
|
||||||
|
/// Use for early initialization such as setting singleton instances.
|
||||||
|
/// NOT ordered - fires whenever Unity calls this component's Awake().
|
||||||
|
/// </summary>
|
||||||
|
ManagedAwake,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called once per component after bootstrap completes.
|
/// Called once per component after bootstrap completes.
|
||||||
/// Guaranteed to be called after all bootstrap resources are loaded.
|
/// Guaranteed to be called after all bootstrap resources are loaded.
|
||||||
/// For late-registered components, called immediately upon registration.
|
/// For late-registered components, called immediately upon registration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ManagedAwake,
|
ManagedStart,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called before a scene is unloaded.
|
/// Called before a scene is unloaded.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ namespace Core.Lifecycle
|
|||||||
{
|
{
|
||||||
if (_instance != null)
|
if (_instance != null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[LifecycleManager] Instance already exists");
|
Logging.Warning("[LifecycleManager] Instance already exists");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ namespace Core.Lifecycle
|
|||||||
_instance = go.AddComponent<LifecycleManager>();
|
_instance = go.AddComponent<LifecycleManager>();
|
||||||
DontDestroyOnLoad(go);
|
DontDestroyOnLoad(go);
|
||||||
|
|
||||||
Debug.Log("[LifecycleManager] Instance created");
|
Logging.Debug("[LifecycleManager] Instance created");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -59,11 +59,11 @@ namespace Core.Lifecycle
|
|||||||
|
|
||||||
#region State Flags
|
#region State Flags
|
||||||
|
|
||||||
private bool isBootComplete = false;
|
private bool isBootComplete;
|
||||||
private string currentSceneReady = "";
|
private string currentSceneReady = "";
|
||||||
|
|
||||||
// Scene loading state tracking
|
// Scene loading state tracking
|
||||||
private bool isLoadingScene = false;
|
private bool isLoadingScene;
|
||||||
private string sceneBeingLoaded = "";
|
private string sceneBeingLoaded = "";
|
||||||
private List<ManagedBehaviour> pendingSceneComponents = new List<ManagedBehaviour>();
|
private List<ManagedBehaviour> pendingSceneComponents = new List<ManagedBehaviour>();
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ namespace Core.Lifecycle
|
|||||||
}
|
}
|
||||||
else if (_instance != this)
|
else if (_instance != this)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[LifecycleManager] Duplicate instance detected. Destroying.");
|
Logging.Warning("[LifecycleManager] Duplicate instance detected. Destroying.");
|
||||||
Destroy(gameObject);
|
Destroy(gameObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,7 +111,7 @@ namespace Core.Lifecycle
|
|||||||
{
|
{
|
||||||
if (component == null)
|
if (component == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[LifecycleManager] Attempted to register null component");
|
Logging.Warning("[LifecycleManager] Attempted to register null component");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,43 +120,49 @@ namespace Core.Lifecycle
|
|||||||
// Track which scene this component belongs to
|
// Track which scene this component belongs to
|
||||||
componentScenes[component] = sceneName;
|
componentScenes[component] = sceneName;
|
||||||
|
|
||||||
// ALWAYS add to managedAwakeList - this is the master list used for save/load
|
// Add to all lifecycle lists (order of registration determines execution order)
|
||||||
InsertSorted(managedAwakeList, component, component.ManagedAwakePriority);
|
managedAwakeList.Add(component);
|
||||||
|
sceneUnloadingList.Add(component);
|
||||||
|
sceneReadyList.Add(component);
|
||||||
|
saveRequestedList.Add(component);
|
||||||
|
restoreRequestedList.Add(component);
|
||||||
|
destroyList.Add(component);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
component.OnManagedAwake();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError($"[LifecycleManager] Error in OnManagedAwake for {component.gameObject.name}: {ex}");
|
||||||
|
}
|
||||||
|
|
||||||
// Handle ManagedAwake timing based on boot state
|
// Handle OnManagedStart timing based on boot state
|
||||||
if (isBootComplete)
|
if (isBootComplete)
|
||||||
{
|
{
|
||||||
// Check if we're currently loading a scene
|
// Check if we're currently loading a scene
|
||||||
if (isLoadingScene && sceneName == sceneBeingLoaded)
|
if (isLoadingScene && sceneName == sceneBeingLoaded)
|
||||||
{
|
{
|
||||||
// Batch this component - will be processed in priority order when scene load completes
|
// Batch this component - will be processed when scene load completes
|
||||||
pendingSceneComponents.Add(component);
|
pendingSceneComponents.Add(component);
|
||||||
LogDebug($"Batched component for scene load: {component.gameObject.name} (Scene: {sceneName})");
|
LogDebug($"Batched component for scene load: {component.gameObject.name} (Scene: {sceneName})");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Truly late registration (component enabled after scene is ready)
|
// Truly late registration (component enabled after scene is ready)
|
||||||
// Call OnManagedAwake immediately since boot already completed
|
// Call OnManagedStart immediately since boot already completed
|
||||||
LogDebug($"Late registration: Calling OnManagedAwake immediately for {component.gameObject.name}");
|
LogDebug($"Late registration: Calling OnManagedStart immediately for {component.gameObject.name}");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
component.InvokeManagedAwake();
|
component.OnManagedStart();
|
||||||
HandleAutoRegistrations(component);
|
HandleAutoRegistrations(component);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[LifecycleManager] Error in OnManagedAwake for {component.gameObject.name}: {ex}");
|
Debug.LogError($"[LifecycleManager] Error in OnManagedStart for {component.gameObject.name}: {ex}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If boot not complete, component stays in list and will be processed by BroadcastManagedAwake()
|
// If boot not complete, component stays in list and will be processed by BroadcastManagedStart()
|
||||||
|
|
||||||
// Register for all scene lifecycle hooks
|
|
||||||
InsertSorted(sceneUnloadingList, component, component.SceneUnloadingPriority);
|
|
||||||
InsertSorted(sceneReadyList, component, component.SceneReadyPriority);
|
|
||||||
InsertSorted(saveRequestedList, component, component.SavePriority);
|
|
||||||
InsertSorted(restoreRequestedList, component, component.RestorePriority);
|
|
||||||
InsertSorted(destroyList, component, component.DestroyPriority);
|
|
||||||
|
|
||||||
// If this scene is already ready (and we're not in loading mode), call OnSceneReady immediately
|
// If this scene is already ready (and we're not in loading mode), call OnSceneReady immediately
|
||||||
if (!isLoadingScene && currentSceneReady == sceneName)
|
if (!isLoadingScene && currentSceneReady == sceneName)
|
||||||
@@ -164,7 +170,7 @@ namespace Core.Lifecycle
|
|||||||
LogDebug($"Late registration: Calling OnSceneReady immediately for {component.gameObject.name}");
|
LogDebug($"Late registration: Calling OnSceneReady immediately for {component.gameObject.name}");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
component.InvokeSceneReady();
|
component.OnSceneReady();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -202,7 +208,7 @@ namespace Core.Lifecycle
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called by CustomBoot when boot completes.
|
/// Called by CustomBoot when boot completes.
|
||||||
/// Broadcasts ManagedAwake to all registered components.
|
/// Broadcasts ManagedStart to all registered components.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void OnBootCompletionTriggered()
|
public void OnBootCompletionTriggered()
|
||||||
{
|
{
|
||||||
@@ -210,16 +216,16 @@ namespace Core.Lifecycle
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
LogDebug("=== Boot Completion Triggered ===");
|
LogDebug("=== Boot Completion Triggered ===");
|
||||||
BroadcastManagedAwake();
|
BroadcastManagedStart();
|
||||||
isBootComplete = true;
|
isBootComplete = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Broadcast OnManagedAwake to all registered components (priority ordered).
|
/// Broadcast OnManagedStart to all registered components (priority ordered).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void BroadcastManagedAwake()
|
private void BroadcastManagedStart()
|
||||||
{
|
{
|
||||||
LogDebug($"Broadcasting ManagedAwake to {managedAwakeList.Count} components");
|
LogDebug($"Broadcasting ManagedStart to {managedAwakeList.Count} components");
|
||||||
|
|
||||||
// Create a copy to avoid collection modification during iteration
|
// Create a copy to avoid collection modification during iteration
|
||||||
var componentsCopy = new List<ManagedBehaviour>(managedAwakeList);
|
var componentsCopy = new List<ManagedBehaviour>(managedAwakeList);
|
||||||
@@ -230,12 +236,12 @@ namespace Core.Lifecycle
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
component.InvokeManagedAwake();
|
component.OnManagedStart();
|
||||||
HandleAutoRegistrations(component);
|
HandleAutoRegistrations(component);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[LifecycleManager] Error in OnManagedAwake for {component.gameObject.name}: {ex}");
|
Debug.LogError($"[LifecycleManager] Error in OnManagedStart for {component.gameObject.name}: {ex}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,23 +278,20 @@ namespace Core.Lifecycle
|
|||||||
|
|
||||||
LogDebug($"Processing {pendingSceneComponents.Count} batched components for scene: {sceneBeingLoaded}");
|
LogDebug($"Processing {pendingSceneComponents.Count} batched components for scene: {sceneBeingLoaded}");
|
||||||
|
|
||||||
// Sort by ManagedAwake priority (lower values first)
|
// Call OnManagedStart in registration order
|
||||||
pendingSceneComponents.Sort((a, b) => a.ManagedAwakePriority.CompareTo(b.ManagedAwakePriority));
|
|
||||||
|
|
||||||
// Call OnManagedAwake in priority order
|
|
||||||
foreach (var component in pendingSceneComponents)
|
foreach (var component in pendingSceneComponents)
|
||||||
{
|
{
|
||||||
if (component == null) continue;
|
if (component == null) continue;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
component.InvokeManagedAwake();
|
component.OnManagedStart();
|
||||||
HandleAutoRegistrations(component);
|
HandleAutoRegistrations(component);
|
||||||
LogDebug($"Processed batched component: {component.gameObject.name} (Priority: {component.ManagedAwakePriority})");
|
LogDebug($"Processed batched component: {component.gameObject.name}");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[LifecycleManager] Error in OnManagedAwake for batched component {component.gameObject.name}: {ex}");
|
Debug.LogError($"[LifecycleManager] Error in OnManagedStart for batched component {component.gameObject.name}: {ex}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +302,7 @@ namespace Core.Lifecycle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Broadcast OnSceneUnloading to components in the specified scene (reverse priority order).
|
/// Broadcast OnSceneUnloading to components in the specified scene.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void BroadcastSceneUnloading(string sceneName)
|
public void BroadcastSceneUnloading(string sceneName)
|
||||||
{
|
{
|
||||||
@@ -315,7 +318,7 @@ namespace Core.Lifecycle
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
component.InvokeSceneUnloading();
|
component.OnSceneUnloading();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -326,8 +329,8 @@ namespace Core.Lifecycle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Broadcast OnSceneReady to components in the specified scene (priority order).
|
/// Broadcast OnSceneReady to components in the specified scene.
|
||||||
/// If scene loading mode is active, processes batched components first.
|
/// Processes batched components first, then calls OnSceneReady on all components in that scene.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void BroadcastSceneReady(string sceneName)
|
public void BroadcastSceneReady(string sceneName)
|
||||||
{
|
{
|
||||||
@@ -351,7 +354,7 @@ namespace Core.Lifecycle
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
component.InvokeSceneReady();
|
component.OnSceneReady();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -379,7 +382,7 @@ namespace Core.Lifecycle
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string serializedData = component.InvokeSceneSaveRequested();
|
string serializedData = component.OnSceneSaveRequested();
|
||||||
if (!string.IsNullOrEmpty(serializedData))
|
if (!string.IsNullOrEmpty(serializedData))
|
||||||
{
|
{
|
||||||
string saveId = component.SaveId;
|
string saveId = component.SaveId;
|
||||||
@@ -415,7 +418,7 @@ namespace Core.Lifecycle
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string serializedData = component.InvokeGlobalSaveRequested();
|
string serializedData = component.OnGlobalSaveRequested();
|
||||||
if (!string.IsNullOrEmpty(serializedData))
|
if (!string.IsNullOrEmpty(serializedData))
|
||||||
{
|
{
|
||||||
saveData[component.SaveId] = serializedData;
|
saveData[component.SaveId] = serializedData;
|
||||||
@@ -455,7 +458,7 @@ namespace Core.Lifecycle
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
component.InvokeSceneRestoreRequested(serializedData);
|
component.OnSceneRestoreRequested(serializedData);
|
||||||
restoredCount++;
|
restoredCount++;
|
||||||
LogDebug($"Restored scene data to: {component.SaveId}");
|
LogDebug($"Restored scene data to: {component.SaveId}");
|
||||||
}
|
}
|
||||||
@@ -469,6 +472,34 @@ namespace Core.Lifecycle
|
|||||||
LogDebug($"Restored scene data to {restoredCount} components");
|
LogDebug($"Restored scene data to {restoredCount} components");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Broadcasts scene restore completed event to all registered components.
|
||||||
|
/// Called AFTER all OnSceneRestoreRequested calls complete.
|
||||||
|
/// </summary>
|
||||||
|
public void BroadcastSceneRestoreCompleted()
|
||||||
|
{
|
||||||
|
LogDebug("Broadcasting SceneRestoreCompleted");
|
||||||
|
|
||||||
|
// Create a copy to avoid collection modification during iteration
|
||||||
|
var componentsCopy = new List<ManagedBehaviour>(managedAwakeList);
|
||||||
|
|
||||||
|
foreach (var component in componentsCopy)
|
||||||
|
{
|
||||||
|
if (component == null) continue;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
component.OnSceneRestoreCompleted();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError($"[LifecycleManager] Exception during scene restore completed for {component.SaveId}: {ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogDebug("SceneRestoreCompleted broadcast complete");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Broadcasts global restore request to all registered components that opt-in.
|
/// Broadcasts global restore request to all registered components that opt-in.
|
||||||
/// Distributes serialized data to matching components by SaveId.
|
/// Distributes serialized data to matching components by SaveId.
|
||||||
@@ -491,7 +522,7 @@ namespace Core.Lifecycle
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
component.InvokeGlobalRestoreRequested(serializedData);
|
component.OnGlobalRestoreRequested(serializedData);
|
||||||
restoredCount++;
|
restoredCount++;
|
||||||
LogDebug($"Restored global data to: {component.SaveId}");
|
LogDebug($"Restored global data to: {component.SaveId}");
|
||||||
}
|
}
|
||||||
@@ -523,7 +554,7 @@ namespace Core.Lifecycle
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
component.InvokeGlobalLoadCompleted();
|
component.OnGlobalLoadCompleted();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -550,7 +581,7 @@ namespace Core.Lifecycle
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
component.InvokeGlobalSaveStarted();
|
component.OnGlobalSaveStarted();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -583,42 +614,6 @@ namespace Core.Lifecycle
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Helper Methods
|
#region Helper Methods
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Insert component into list maintaining sorted order by priority.
|
|
||||||
/// Uses binary search for efficient insertion.
|
|
||||||
/// </summary>
|
|
||||||
private void InsertSorted(List<ManagedBehaviour> list, ManagedBehaviour component, int priority)
|
|
||||||
{
|
|
||||||
// Simple linear insertion for now (can optimize with binary search later if needed)
|
|
||||||
int index = 0;
|
|
||||||
for (int i = 0; i < list.Count; i++)
|
|
||||||
{
|
|
||||||
int existingPriority = GetPriorityForList(list[i], list);
|
|
||||||
if (priority < existingPriority)
|
|
||||||
{
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
index = i + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
list.Insert(index, component);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the priority value for a component based on which list it's in.
|
|
||||||
/// </summary>
|
|
||||||
private int GetPriorityForList(ManagedBehaviour component, List<ManagedBehaviour> list)
|
|
||||||
{
|
|
||||||
if (list == managedAwakeList) return component.ManagedAwakePriority;
|
|
||||||
if (list == sceneUnloadingList) return component.SceneUnloadingPriority;
|
|
||||||
if (list == sceneReadyList) return component.SceneReadyPriority;
|
|
||||||
if (list == saveRequestedList) return component.SavePriority;
|
|
||||||
if (list == restoreRequestedList) return component.RestorePriority;
|
|
||||||
if (list == destroyList) return component.DestroyPriority;
|
|
||||||
return 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Log debug message if debug logging is enabled.
|
/// Log debug message if debug logging is enabled.
|
||||||
@@ -627,7 +622,7 @@ namespace Core.Lifecycle
|
|||||||
{
|
{
|
||||||
if (enableDebugLogging)
|
if (enableDebugLogging)
|
||||||
{
|
{
|
||||||
Debug.Log($"[LifecycleManager] {message}");
|
Logging.Debug($"[LifecycleManager] {message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using UnityEngine;
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Core.Lifecycle
|
namespace Core.Lifecycle
|
||||||
{
|
{
|
||||||
@@ -9,46 +8,6 @@ namespace Core.Lifecycle
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class ManagedBehaviour : MonoBehaviour
|
public abstract class ManagedBehaviour : MonoBehaviour
|
||||||
{
|
{
|
||||||
#region Priority Properties
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Priority for OnManagedAwake (lower values execute first).
|
|
||||||
/// Default: 100
|
|
||||||
/// </summary>
|
|
||||||
public virtual int ManagedAwakePriority => 100;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Priority for OnSceneUnloading (executed in reverse: higher values execute first).
|
|
||||||
/// Default: 100
|
|
||||||
/// </summary>
|
|
||||||
public virtual int SceneUnloadingPriority => 100;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Priority for OnSceneReady (lower values execute first).
|
|
||||||
/// Default: 100
|
|
||||||
/// </summary>
|
|
||||||
public virtual int SceneReadyPriority => 100;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Priority for OnSaveRequested (executed in reverse: higher values execute first).
|
|
||||||
/// Default: 100
|
|
||||||
/// </summary>
|
|
||||||
public virtual int SavePriority => 100;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Priority for OnRestoreRequested (lower values execute first).
|
|
||||||
/// Default: 100
|
|
||||||
/// </summary>
|
|
||||||
public virtual int RestorePriority => 100;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Priority for OnManagedDestroy (executed in reverse: higher values execute first).
|
|
||||||
/// Default: 100
|
|
||||||
/// </summary>
|
|
||||||
public virtual int DestroyPriority => 100;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Configuration Properties
|
#region Configuration Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -68,38 +27,28 @@ namespace Core.Lifecycle
|
|||||||
/// Unique identifier for this component in the save system.
|
/// Unique identifier for this component in the save system.
|
||||||
/// Default: "SceneName/GameObjectName/ComponentType"
|
/// Default: "SceneName/GameObjectName/ComponentType"
|
||||||
/// Override ONLY for special cases (e.g., singletons like "PlayerController", or custom IDs).
|
/// Override ONLY for special cases (e.g., singletons like "PlayerController", or custom IDs).
|
||||||
|
/// Cached on first access to avoid runtime allocation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual string SaveId
|
public virtual string SaveId
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
string sceneName = gameObject.scene.IsValid() ? gameObject.scene.name : "UnknownScene";
|
if (_cachedSaveId == null)
|
||||||
string componentType = GetType().Name;
|
{
|
||||||
return $"{sceneName}/{gameObject.name}/{componentType}";
|
string sceneName = gameObject.scene.IsValid() ? gameObject.scene.name : "UnknownScene";
|
||||||
|
string componentType = GetType().Name;
|
||||||
|
_cachedSaveId = $"{sceneName}/{gameObject.name}/{componentType}";
|
||||||
|
}
|
||||||
|
return _cachedSaveId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Accessors (for LifecycleManager)
|
|
||||||
|
|
||||||
// Public wrappers to invoke protected lifecycle methods
|
|
||||||
public void InvokeManagedAwake() => OnManagedAwake();
|
|
||||||
public void InvokeSceneUnloading() => OnSceneUnloading();
|
|
||||||
public void InvokeSceneReady() => OnSceneReady();
|
|
||||||
public string InvokeSceneSaveRequested() => OnSceneSaveRequested();
|
|
||||||
public void InvokeSceneRestoreRequested(string data) => OnSceneRestoreRequested(data);
|
|
||||||
public string InvokeGlobalSaveRequested() => OnGlobalSaveRequested();
|
|
||||||
public void InvokeGlobalRestoreRequested(string data) => OnGlobalRestoreRequested(data);
|
|
||||||
public void InvokeManagedDestroy() => OnManagedDestroy();
|
|
||||||
public void InvokeGlobalLoadCompleted() => OnGlobalLoadCompleted();
|
|
||||||
public void InvokeGlobalSaveStarted() => OnGlobalSaveStarted();
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private bool _isRegistered;
|
private bool _isRegistered;
|
||||||
|
private string _cachedSaveId;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -107,9 +56,9 @@ namespace Core.Lifecycle
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unity Awake - automatically registers with LifecycleManager.
|
/// Unity Awake - automatically registers with LifecycleManager.
|
||||||
/// IMPORTANT: Derived classes that override Awake MUST call base.Awake()
|
/// SEALED: Cannot be overridden. Use OnManagedAwake() for early initialization or OnManagedStart() for late initialization.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
if (LifecycleManager.Instance != null)
|
if (LifecycleManager.Instance != null)
|
||||||
{
|
{
|
||||||
@@ -118,19 +67,22 @@ namespace Core.Lifecycle
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ManagedBehaviour] LifecycleManager not found for {gameObject.name}. Component will not receive lifecycle callbacks.");
|
Logging.Warning($"[ManagedBehaviour] LifecycleManager not found for {gameObject.name}. Component will not receive lifecycle callbacks.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unity OnDestroy - automatically unregisters and cleans up.
|
/// Unity OnDestroy - automatically unregisters and cleans up.
|
||||||
/// IMPORTANT: Derived classes that override OnDestroy MUST call base.OnDestroy()
|
/// SEALED: Cannot be overridden. Use OnManagedDestroy() for custom cleanup logic.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void OnDestroy()
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
if (!_isRegistered)
|
if (!_isRegistered)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Call managed destroy hook
|
||||||
|
OnManagedDestroy();
|
||||||
|
|
||||||
// Unregister from LifecycleManager
|
// Unregister from LifecycleManager
|
||||||
if (LifecycleManager.Instance != null)
|
if (LifecycleManager.Instance != null)
|
||||||
{
|
{
|
||||||
@@ -151,34 +103,47 @@ namespace Core.Lifecycle
|
|||||||
|
|
||||||
#region Managed Lifecycle Hooks
|
#region Managed Lifecycle Hooks
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called immediately during registration (during Awake).
|
||||||
|
/// Use for early initialization such as setting singleton instances.
|
||||||
|
/// TIMING: Fires during component's Awake(), no execution order guarantees between components.
|
||||||
|
/// NOT priority-ordered - fires whenever Unity calls this component's Awake().
|
||||||
|
/// NOTE: Internal visibility allows LifecycleManager to call directly. Override in derived classes.
|
||||||
|
/// </summary>
|
||||||
|
internal virtual void OnManagedAwake()
|
||||||
|
{
|
||||||
|
// Override in derived classes
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called once per component after bootstrap completes.
|
/// Called once per component after bootstrap completes.
|
||||||
/// GUARANTEE: Bootstrap resources are available, all managers are initialized.
|
/// GUARANTEE: Bootstrap resources are available, all managers are initialized.
|
||||||
/// For boot-time components: Called during LifecycleManager.BroadcastManagedAwake (priority ordered).
|
/// For boot-time components: Called during LifecycleManager.BroadcastManagedStart (registration order).
|
||||||
/// For late-registered components: Called immediately upon registration (bootstrap already complete).
|
/// For late-registered components: Called immediately upon registration (bootstrap already complete).
|
||||||
/// Replaces the old Awake + InitializePostBoot pattern.
|
/// Use for initialization that depends on other systems.
|
||||||
|
/// NOTE: Internal visibility allows LifecycleManager to call directly. Override in derived classes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void OnManagedAwake()
|
internal virtual void OnManagedStart()
|
||||||
{
|
{
|
||||||
// Override in derived classes
|
// Override in derived classes
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called before the scene this component belongs to is unloaded.
|
/// Called before the scene this component belongs to is unloaded.
|
||||||
/// Called in REVERSE priority order (higher values execute first).
|
|
||||||
/// Use for scene-specific cleanup.
|
/// Use for scene-specific cleanup.
|
||||||
|
/// NOTE: Internal visibility allows LifecycleManager to call directly. Override in derived classes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void OnSceneUnloading()
|
internal virtual void OnSceneUnloading()
|
||||||
{
|
{
|
||||||
// Override in derived classes
|
// Override in derived classes
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called after the scene this component belongs to has finished loading.
|
/// Called after the scene this component belongs to has finished loading.
|
||||||
/// Called in priority order (lower values execute first).
|
|
||||||
/// Use for scene-specific initialization.
|
/// Use for scene-specific initialization.
|
||||||
|
/// NOTE: Internal visibility allows LifecycleManager to call directly. Override in derived classes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void OnSceneReady()
|
internal virtual void OnSceneReady()
|
||||||
{
|
{
|
||||||
// Override in derived classes
|
// Override in derived classes
|
||||||
}
|
}
|
||||||
@@ -192,8 +157,10 @@ namespace Core.Lifecycle
|
|||||||
/// - Called BEFORE scene unload during scene transitions
|
/// - Called BEFORE scene unload during scene transitions
|
||||||
/// - Frequency: Every scene transition
|
/// - Frequency: Every scene transition
|
||||||
/// - Use for: Level progress, object positions, puzzle states
|
/// - Use for: Level progress, object positions, puzzle states
|
||||||
|
///
|
||||||
|
/// NOTE: Internal visibility allows LifecycleManager to call directly. Override in derived classes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual string OnSceneSaveRequested()
|
internal virtual string OnSceneSaveRequested()
|
||||||
{
|
{
|
||||||
return null; // Default: no data to save
|
return null; // Default: no data to save
|
||||||
}
|
}
|
||||||
@@ -202,12 +169,43 @@ namespace Core.Lifecycle
|
|||||||
/// Called during scene transitions to restore scene-specific state.
|
/// Called during scene transitions to restore scene-specific state.
|
||||||
/// Receives previously serialized data (from OnSceneSaveRequested).
|
/// Receives previously serialized data (from OnSceneSaveRequested).
|
||||||
///
|
///
|
||||||
|
/// IMPORTANT: This method MUST be synchronous. Do not use coroutines or async/await.
|
||||||
|
/// OnSceneRestoreCompleted is called immediately after all restore calls complete,
|
||||||
|
/// so any async operations would still be running when it fires.
|
||||||
|
///
|
||||||
/// TIMING:
|
/// TIMING:
|
||||||
/// - Called AFTER scene load, during OnSceneReady phase
|
/// - Called AFTER scene load, during OnSceneReady phase
|
||||||
/// - Frequency: Every scene transition
|
/// - Frequency: Every scene transition
|
||||||
/// - Use for: Restoring level progress, object positions, puzzle states
|
/// - Use for: Restoring level progress, object positions, puzzle states
|
||||||
|
///
|
||||||
|
/// NOTE: Internal visibility allows LifecycleManager to call directly. Override in derived classes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void OnSceneRestoreRequested(string serializedData)
|
internal virtual void OnSceneRestoreRequested(string serializedData)
|
||||||
|
{
|
||||||
|
// Default: no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called after all scene restore operations complete.
|
||||||
|
/// Does NOT receive data - use OnSceneRestoreRequested for that.
|
||||||
|
///
|
||||||
|
/// GUARANTEE:
|
||||||
|
/// - ALWAYS called after scene load, whether there's save data or not
|
||||||
|
/// - All OnSceneRestoreRequested() calls have RETURNED (but async operations may still be running)
|
||||||
|
/// - Safe for synchronous restore operations (JSON deserialization, setting fields, etc.)
|
||||||
|
///
|
||||||
|
/// TIMING:
|
||||||
|
/// - Called AFTER all OnSceneRestoreRequested calls complete (or immediately if no save data exists)
|
||||||
|
/// - Frequency: Every scene transition
|
||||||
|
/// - Use for: Post-restore initialization, first-time initialization, triggering events after state is restored
|
||||||
|
///
|
||||||
|
/// COMMON PATTERN:
|
||||||
|
/// Use this to perform actions that depend on whether data was restored or not.
|
||||||
|
/// Example: Play one-time audio only if it hasn't been played before (_hasPlayed == false).
|
||||||
|
///
|
||||||
|
/// NOTE: Internal visibility allows LifecycleManager to call directly. Override in derived classes.
|
||||||
|
/// </summary>
|
||||||
|
internal virtual void OnSceneRestoreCompleted()
|
||||||
{
|
{
|
||||||
// Default: no-op
|
// Default: no-op
|
||||||
}
|
}
|
||||||
@@ -220,8 +218,10 @@ namespace Core.Lifecycle
|
|||||||
/// - Called ONCE on game boot after save file is read
|
/// - Called ONCE on game boot after save file is read
|
||||||
/// - NOT called during scene transitions
|
/// - NOT called during scene transitions
|
||||||
/// - Use for: Player inventory, unlocked features, card collections
|
/// - Use for: Player inventory, unlocked features, card collections
|
||||||
|
///
|
||||||
|
/// NOTE: Internal visibility allows LifecycleManager to call directly. Override in derived classes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void OnGlobalRestoreRequested(string serializedData)
|
internal virtual void OnGlobalRestoreRequested(string serializedData)
|
||||||
{
|
{
|
||||||
// Default: no-op
|
// Default: no-op
|
||||||
}
|
}
|
||||||
@@ -235,8 +235,10 @@ namespace Core.Lifecycle
|
|||||||
/// - Called ONCE before save file is written (on quit, manual save, etc.)
|
/// - Called ONCE before save file is written (on quit, manual save, etc.)
|
||||||
/// - NOT called during scene transitions
|
/// - NOT called during scene transitions
|
||||||
/// - Use for: Player inventory, unlocked features, card collections
|
/// - Use for: Player inventory, unlocked features, card collections
|
||||||
|
///
|
||||||
|
/// NOTE: Internal visibility allows LifecycleManager to call directly. Override in derived classes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual string OnGlobalSaveRequested()
|
internal virtual string OnGlobalSaveRequested()
|
||||||
{
|
{
|
||||||
return null; // Default: no data to save
|
return null; // Default: no data to save
|
||||||
}
|
}
|
||||||
@@ -250,8 +252,10 @@ namespace Core.Lifecycle
|
|||||||
/// - Called ONCE on game boot after all restore operations complete
|
/// - Called ONCE on game boot after all restore operations complete
|
||||||
/// - NOT called during scene transitions
|
/// - NOT called during scene transitions
|
||||||
/// - Use for: Triggering UI updates, broadcasting load events
|
/// - Use for: Triggering UI updates, broadcasting load events
|
||||||
|
///
|
||||||
|
/// NOTE: Internal visibility allows LifecycleManager to call directly. Override in derived classes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void OnGlobalLoadCompleted()
|
internal virtual void OnGlobalLoadCompleted()
|
||||||
{
|
{
|
||||||
// Default: no-op
|
// Default: no-op
|
||||||
}
|
}
|
||||||
@@ -265,19 +269,21 @@ namespace Core.Lifecycle
|
|||||||
/// - Called ONCE before save file is written
|
/// - Called ONCE before save file is written
|
||||||
/// - NOT called during scene transitions
|
/// - NOT called during scene transitions
|
||||||
/// - Use for: Final validation, cleanup operations
|
/// - Use for: Final validation, cleanup operations
|
||||||
|
///
|
||||||
|
/// NOTE: Internal visibility allows LifecycleManager to call directly. Override in derived classes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void OnGlobalSaveStarted()
|
internal virtual void OnGlobalSaveStarted()
|
||||||
{
|
{
|
||||||
// Default: no-op
|
// Default: no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called during OnDestroy before component is destroyed.
|
/// Called during OnDestroy before component is destroyed.
|
||||||
/// Called in REVERSE priority order (higher values execute first).
|
|
||||||
/// NOTE: Most cleanup is automatic (managed events, auto-registrations).
|
/// NOTE: Most cleanup is automatic (managed events, auto-registrations).
|
||||||
/// Only override if you need custom cleanup logic.
|
/// Only override if you need custom cleanup logic.
|
||||||
|
/// Internal visibility allows LifecycleManager to call directly. Override in derived classes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void OnManagedDestroy()
|
internal virtual void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
// Override in derived classes
|
// Override in derived classes
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,144 @@
|
|||||||
namespace Core
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Centralized logging system with automatic class/method tagging and editor integration.
|
||||||
|
/// Broadcasts log entries to custom editor windows for filtering and analysis.
|
||||||
|
/// </summary>
|
||||||
public static class Logging
|
public static class Logging
|
||||||
{
|
{
|
||||||
[System.Diagnostics.Conditional("ENABLE_LOG")]
|
/// <summary>
|
||||||
public static void Debug(object message)
|
/// Event fired when a new log entry is added. Subscribe to this in editor windows.
|
||||||
|
/// </summary>
|
||||||
|
public static event Action<LogEntry> OnLogEntryAdded;
|
||||||
|
|
||||||
|
// Store recent logs for late-subscriber editor windows (e.g., windows opened after play mode started)
|
||||||
|
private static readonly List<LogEntry> RecentLogs = new List<LogEntry>();
|
||||||
|
private const int MaxStoredLogs = 5000; // Prevent memory bloat
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all recent logs. Used by editor windows when they first open.
|
||||||
|
/// </summary>
|
||||||
|
public static IReadOnlyList<LogEntry> GetRecentLogs() => RecentLogs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clear all stored logs. Useful for editor windows "Clear" button.
|
||||||
|
/// </summary>
|
||||||
|
public static void ClearLogs()
|
||||||
{
|
{
|
||||||
UnityEngine.Debug.Log(message);
|
RecentLogs.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
[System.Diagnostics.Conditional("ENABLE_LOG")]
|
[System.Diagnostics.Conditional("ENABLE_LOG")]
|
||||||
public static void Warning(object message)
|
public static void Debug(string message,
|
||||||
|
[CallerFilePath] string filePath = "",
|
||||||
|
[CallerMemberName] string memberName = "")
|
||||||
{
|
{
|
||||||
UnityEngine.Debug.LogWarning(message);
|
LogInternal(LogLevel.Debug, message, filePath, memberName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Diagnostics.Conditional("ENABLE_LOG")]
|
||||||
|
public static void Info(string message,
|
||||||
|
[CallerFilePath] string filePath = "",
|
||||||
|
[CallerMemberName] string memberName = "")
|
||||||
|
{
|
||||||
|
LogInternal(LogLevel.Info, message, filePath, memberName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Diagnostics.Conditional("ENABLE_LOG")]
|
||||||
|
public static void Warning(string message,
|
||||||
|
[CallerFilePath] string filePath = "",
|
||||||
|
[CallerMemberName] string memberName = "")
|
||||||
|
{
|
||||||
|
LogInternal(LogLevel.Warning, message, filePath, memberName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Error(string message,
|
||||||
|
[CallerFilePath] string filePath = "",
|
||||||
|
[CallerMemberName] string memberName = "")
|
||||||
|
{
|
||||||
|
LogInternal(LogLevel.Error, message, filePath, memberName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void LogInternal(LogLevel level, string message, string filePath, string memberName)
|
||||||
|
{
|
||||||
|
string className = Path.GetFileNameWithoutExtension(filePath);
|
||||||
|
string formattedMessage = $"[{className}][{memberName}] {message}";
|
||||||
|
|
||||||
|
// Create log entry
|
||||||
|
var entry = new LogEntry(className, memberName, message, level, Time.realtimeSinceStartup);
|
||||||
|
|
||||||
|
// Store for late subscribers
|
||||||
|
RecentLogs.Add(entry);
|
||||||
|
if (RecentLogs.Count > MaxStoredLogs)
|
||||||
|
RecentLogs.RemoveAt(0);
|
||||||
|
|
||||||
|
// Broadcast to editor windows (editor-only, won't fire in builds)
|
||||||
|
OnLogEntryAdded?.Invoke(entry);
|
||||||
|
|
||||||
|
// Also log to Unity console
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case LogLevel.Debug:
|
||||||
|
case LogLevel.Info:
|
||||||
|
UnityEngine.Debug.Log(formattedMessage);
|
||||||
|
break;
|
||||||
|
case LogLevel.Warning:
|
||||||
|
UnityEngine.Debug.LogWarning(formattedMessage);
|
||||||
|
break;
|
||||||
|
case LogLevel.Error:
|
||||||
|
UnityEngine.Debug.LogError(formattedMessage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a single log entry with class, method, message, level, and timestamp.
|
||||||
|
/// </summary>
|
||||||
|
public class LogEntry
|
||||||
|
{
|
||||||
|
public string ClassName { get; }
|
||||||
|
public string MethodName { get; }
|
||||||
|
public string Message { get; }
|
||||||
|
public LogLevel Level { get; }
|
||||||
|
public float Timestamp { get; }
|
||||||
|
|
||||||
|
public LogEntry(string className, string methodName, string message, LogLevel level, float timestamp)
|
||||||
|
{
|
||||||
|
ClassName = className;
|
||||||
|
MethodName = methodName;
|
||||||
|
Message = message;
|
||||||
|
Level = level;
|
||||||
|
Timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Formatted message with class and method tags.
|
||||||
|
/// Format: [ClassName][MethodName] Message
|
||||||
|
/// </summary>
|
||||||
|
public string FormattedMessage => $"[{ClassName}][{MethodName}] {Message}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Full formatted message with timestamp and level.
|
||||||
|
/// Format: [12.34s][Debug][ClassName][MethodName] Message
|
||||||
|
/// </summary>
|
||||||
|
public string FullFormattedMessage => $"[{Timestamp:F2}s][{Level}]{FormattedMessage}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Log severity levels.
|
||||||
|
/// </summary>
|
||||||
|
public enum LogLevel
|
||||||
|
{
|
||||||
|
Debug,
|
||||||
|
Info,
|
||||||
|
Warning,
|
||||||
|
Error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -24,9 +24,6 @@ namespace AppleHills.Core
|
|||||||
|
|
||||||
#endregion Singleton Setup
|
#endregion Singleton Setup
|
||||||
|
|
||||||
// Very early initialization - QuickAccess should be available immediately
|
|
||||||
public override int ManagedAwakePriority => 5;
|
|
||||||
|
|
||||||
#region Manager Instances
|
#region Manager Instances
|
||||||
|
|
||||||
// Core Managers
|
// Core Managers
|
||||||
@@ -129,20 +126,18 @@ namespace AppleHills.Core
|
|||||||
|
|
||||||
#region Lifecycle Methods
|
#region Lifecycle Methods
|
||||||
|
|
||||||
private new void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
// Set instance immediately (early initialization)
|
||||||
|
|
||||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
// QuickAccess has minimal initialization
|
// QuickAccess has minimal initialization
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneUnloading()
|
internal override void OnSceneUnloading()
|
||||||
{
|
{
|
||||||
// Clear references BEFORE scene unloads for better cleanup timing
|
// Clear references BEFORE scene unloads for better cleanup timing
|
||||||
ClearReferences();
|
ClearReferences();
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ namespace Core.SaveLoad
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[AppleMachine] SaveLoadManager not available for '{name}'", this);
|
Logging.Warning($"[AppleMachine] SaveLoadManager not available for '{name}'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ namespace Core.SaveLoad
|
|||||||
// Optional: Log the auto-generated ID in verbose mode
|
// Optional: Log the auto-generated ID in verbose mode
|
||||||
if (verbose && string.IsNullOrEmpty(customSaveId))
|
if (verbose && string.IsNullOrEmpty(customSaveId))
|
||||||
{
|
{
|
||||||
Debug.Log($"[SaveableStateMachine] '{name}' will use auto-generated Save ID: {GetSaveId()}", this);
|
Logging.Debug($"[SaveableStateMachine] '{name}' will use auto-generated Save ID: {GetSaveId()}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -158,7 +158,7 @@ namespace Core.SaveLoad
|
|||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[SaveableStateMachine] No data to restore for '{name}'", this);
|
Logging.Warning($"[SaveableStateMachine] No data to restore for '{name}'");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -171,7 +171,7 @@ namespace Core.SaveLoad
|
|||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[SaveableStateMachine] No state name in save data for '{name}'", this);
|
Logging.Warning($"[SaveableStateMachine] No state name in save data for '{name}'");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -197,7 +197,7 @@ namespace Core.SaveLoad
|
|||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
Debug.Log($"[SaveableStateMachine] Restored '{name}' to state: {saveData.stateName}", this);
|
Logging.Debug($"[SaveableStateMachine] Restored '{name}' to state: {saveData.stateName}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (System.Exception ex)
|
catch (System.Exception ex)
|
||||||
@@ -215,14 +215,14 @@ namespace Core.SaveLoad
|
|||||||
[ContextMenu("Log Save ID")]
|
[ContextMenu("Log Save ID")]
|
||||||
private void LogSaveId()
|
private void LogSaveId()
|
||||||
{
|
{
|
||||||
Debug.Log($"Save ID: {GetSaveId()}", this);
|
Logging.Debug($"Save ID: {GetSaveId()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
[ContextMenu("Test Serialize")]
|
[ContextMenu("Test Serialize")]
|
||||||
private void TestSerialize()
|
private void TestSerialize()
|
||||||
{
|
{
|
||||||
string serialized = SerializeState();
|
string serialized = SerializeState();
|
||||||
Debug.Log($"Serialized state: {serialized}", this);
|
Logging.Debug($"Serialized state: {serialized}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -43,14 +43,10 @@ namespace Core.SaveLoad
|
|||||||
public event Action<string> OnLoadCompleted;
|
public event Action<string> OnLoadCompleted;
|
||||||
public event Action OnParticipantStatesRestored;
|
public event Action OnParticipantStatesRestored;
|
||||||
|
|
||||||
// ManagedBehaviour configuration
|
|
||||||
public override int ManagedAwakePriority => 20; // After GameManager and SceneManagerService
|
|
||||||
|
|
||||||
private new void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
// Set instance immediately (early initialization)
|
||||||
|
|
||||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
|
|
||||||
// Initialize critical state immediately
|
// Initialize critical state immediately
|
||||||
@@ -58,7 +54,7 @@ namespace Core.SaveLoad
|
|||||||
IsRestoringState = false;
|
IsRestoringState = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
Logging.Debug("[SaveLoadManager] Initialized");
|
Logging.Debug("[SaveLoadManager] Initialized");
|
||||||
|
|
||||||
@@ -69,19 +65,19 @@ namespace Core.SaveLoad
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneReady()
|
internal override void OnSceneReady()
|
||||||
{
|
{
|
||||||
// SaveableInteractables now auto-register via ManagedBehaviour lifecycle
|
// SaveableInteractables now auto-register via ManagedBehaviour lifecycle
|
||||||
// No need to discover and register them manually
|
// No need to discover and register them manually
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string OnSceneSaveRequested()
|
internal override string OnSceneSaveRequested()
|
||||||
{
|
{
|
||||||
// SaveLoadManager orchestrates saves, doesn't participate in them
|
// SaveLoadManager orchestrates saves, doesn't participate in them
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string OnGlobalSaveRequested()
|
internal override string OnGlobalSaveRequested()
|
||||||
{
|
{
|
||||||
// SaveLoadManager orchestrates saves, doesn't participate in them
|
// SaveLoadManager orchestrates saves, doesn't participate in them
|
||||||
return null;
|
return null;
|
||||||
@@ -97,10 +93,8 @@ namespace Core.SaveLoad
|
|||||||
|
|
||||||
// ...existing code...
|
// ...existing code...
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy(); // Important: call base to unregister from LifecycleManager
|
|
||||||
|
|
||||||
if (_instance == this)
|
if (_instance == this)
|
||||||
{
|
{
|
||||||
_instance = null;
|
_instance = null;
|
||||||
@@ -504,9 +498,19 @@ namespace Core.SaveLoad
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void RestoreSceneData()
|
public void RestoreSceneData()
|
||||||
{
|
{
|
||||||
|
if (Lifecycle.LifecycleManager.Instance == null)
|
||||||
|
{
|
||||||
|
Logging.Warning("[SaveLoadManager] LifecycleManager not available for scene restore");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (currentSaveData == null || currentSaveData.participantStates == null)
|
if (currentSaveData == null || currentSaveData.participantStates == null)
|
||||||
{
|
{
|
||||||
Logging.Debug("[SaveLoadManager] No scene data to restore");
|
Logging.Debug("[SaveLoadManager] No scene data to restore (first visit or no save data)");
|
||||||
|
|
||||||
|
// Still broadcast restore completed so components can initialize properly
|
||||||
|
Lifecycle.LifecycleManager.Instance.BroadcastSceneRestoreCompleted();
|
||||||
|
Logging.Debug($"[SaveLoadManager] Scene restore completed (no data)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,11 +524,12 @@ namespace Core.SaveLoad
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Restore scene data via LifecycleManager
|
// Restore scene data via LifecycleManager
|
||||||
if (Lifecycle.LifecycleManager.Instance != null)
|
Lifecycle.LifecycleManager.Instance.BroadcastSceneRestoreRequested(saveDataDict);
|
||||||
{
|
Logging.Debug($"[SaveLoadManager] Broadcast scene restore to LifecycleManager");
|
||||||
Lifecycle.LifecycleManager.Instance.BroadcastSceneRestoreRequested(saveDataDict);
|
|
||||||
Logging.Debug($"[SaveLoadManager] Broadcast scene restore to LifecycleManager");
|
// Broadcast scene restore completed - ALWAYS called, whether there's data or not
|
||||||
}
|
Lifecycle.LifecycleManager.Instance.BroadcastSceneRestoreCompleted();
|
||||||
|
Logging.Debug($"[SaveLoadManager] Scene restore completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -706,7 +711,7 @@ namespace Core.SaveLoad
|
|||||||
{
|
{
|
||||||
IsSaving = false;
|
IsSaving = false;
|
||||||
OnSaveCompleted?.Invoke(slot);
|
OnSaveCompleted?.Invoke(slot);
|
||||||
Debug.Log($"[SaveLoadManager] Save completed for slot '{slot}'");
|
Logging.Debug($"[SaveLoadManager] Save completed for slot '{slot}'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ namespace Core
|
|||||||
// Enable save/load participation
|
// Enable save/load participation
|
||||||
public override bool AutoRegisterForSave => true;
|
public override bool AutoRegisterForSave => true;
|
||||||
|
|
||||||
protected override void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake();
|
base.OnManagedAwake();
|
||||||
|
|
||||||
_director = GetComponent<PlayableDirector>();
|
_director = GetComponent<PlayableDirector>();
|
||||||
if (_director != null)
|
if (_director != null)
|
||||||
@@ -42,10 +42,8 @@ namespace Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
if (_director != null)
|
if (_director != null)
|
||||||
{
|
{
|
||||||
_director.stopped -= OnDirectorStopped;
|
_director.stopped -= OnDirectorStopped;
|
||||||
@@ -65,7 +63,7 @@ namespace Core
|
|||||||
|
|
||||||
#region Save/Load Implementation
|
#region Save/Load Implementation
|
||||||
|
|
||||||
protected override string OnSceneSaveRequested()
|
internal override string OnSceneSaveRequested()
|
||||||
{
|
{
|
||||||
var saveData = new PlayableDirectorSaveData
|
var saveData = new PlayableDirectorSaveData
|
||||||
{
|
{
|
||||||
@@ -77,11 +75,11 @@ namespace Core
|
|||||||
return JsonUtility.ToJson(saveData);
|
return JsonUtility.ToJson(saveData);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneRestoreRequested(string serializedData)
|
internal override void OnSceneRestoreRequested(string serializedData)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(serializedData))
|
if (string.IsNullOrEmpty(serializedData))
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[SaveablePlayableDirector] No save data to restore for {gameObject.name}");
|
Logging.Warning($"[SaveablePlayableDirector] No save data to restore for {gameObject.name}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +97,7 @@ namespace Core
|
|||||||
_director.time = _director.duration;
|
_director.time = _director.duration;
|
||||||
_director.Evaluate(); // Force evaluation to apply the state
|
_director.Evaluate(); // Force evaluation to apply the state
|
||||||
|
|
||||||
Debug.Log($"[SaveablePlayableDirector] Restored completed timeline '{gameObject.name}' - seeked to end");
|
Logging.Debug($"[SaveablePlayableDirector] Restored completed timeline '{gameObject.name}' - seeked to end");
|
||||||
}
|
}
|
||||||
else if (_hasPlayed && saveData.playbackTime > 0)
|
else if (_hasPlayed && saveData.playbackTime > 0)
|
||||||
{
|
{
|
||||||
@@ -107,7 +105,7 @@ namespace Core
|
|||||||
_director.time = saveData.playbackTime;
|
_director.time = saveData.playbackTime;
|
||||||
_director.Evaluate();
|
_director.Evaluate();
|
||||||
|
|
||||||
Debug.Log($"[SaveablePlayableDirector] Restored timeline '{gameObject.name}' at time {saveData.playbackTime}");
|
Logging.Debug($"[SaveablePlayableDirector] Restored timeline '{gameObject.name}' at time {saveData.playbackTime}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -115,7 +113,7 @@ namespace Core
|
|||||||
_director.time = 0;
|
_director.time = 0;
|
||||||
_director.Evaluate();
|
_director.Evaluate();
|
||||||
|
|
||||||
Debug.Log($"[SaveablePlayableDirector] Timeline '{gameObject.name}' not yet played - at start");
|
Logging.Debug($"[SaveablePlayableDirector] Timeline '{gameObject.name}' not yet played - at start");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,14 +44,10 @@ namespace Core
|
|||||||
private LogVerbosity _logVerbosity = LogVerbosity.Debug;
|
private LogVerbosity _logVerbosity = LogVerbosity.Debug;
|
||||||
private const string BootstrapSceneName = "BootstrapScene";
|
private const string BootstrapSceneName = "BootstrapScene";
|
||||||
|
|
||||||
// ManagedBehaviour configuration
|
|
||||||
public override int ManagedAwakePriority => 15; // Core infrastructure, after GameManager
|
|
||||||
|
|
||||||
private new void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
// Set instance immediately (early initialization)
|
||||||
|
|
||||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
|
|
||||||
// Initialize current scene tracking - critical for scene management
|
// Initialize current scene tracking - critical for scene management
|
||||||
@@ -65,17 +61,17 @@ namespace Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
// Set up loading screen reference and events
|
// Set up loading screen reference and events
|
||||||
// This must happen in ManagedAwake because LoadingScreenController instance needs to be set first
|
// This must happen in ManagedStart because LoadingScreenController instance needs to be set first
|
||||||
_loadingScreen = LoadingScreenController.Instance;
|
_loadingScreen = LoadingScreenController.Instance;
|
||||||
SetupLoadingScreenEvents();
|
SetupLoadingScreenEvents();
|
||||||
|
|
||||||
// Load verbosity settings
|
// Load verbosity settings
|
||||||
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().sceneLogVerbosity;
|
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().sceneLogVerbosity;
|
||||||
|
|
||||||
LogDebugMessage($"SceneManagerService initialized, current scene is: {CurrentGameplayScene}");
|
Logging.Debug($"SceneManagerService initialized, current scene is: {CurrentGameplayScene}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -93,19 +89,19 @@ namespace Core
|
|||||||
if (activeScene.name != BootstrapSceneName)
|
if (activeScene.name != BootstrapSceneName)
|
||||||
{
|
{
|
||||||
CurrentGameplayScene = activeScene.name;
|
CurrentGameplayScene = activeScene.name;
|
||||||
LogDebugMessage($"Initialized with current scene: {CurrentGameplayScene}");
|
Logging.Debug($"Initialized with current scene: {CurrentGameplayScene}");
|
||||||
}
|
}
|
||||||
// Otherwise default to MainMenu
|
// Otherwise default to MainMenu
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CurrentGameplayScene = "AppleHillsOverworld";
|
CurrentGameplayScene = "AppleHillsOverworld";
|
||||||
LogDebugMessage($"Initialized with default scene: {CurrentGameplayScene}");
|
Logging.Debug($"Initialized with default scene: {CurrentGameplayScene}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CurrentGameplayScene = "AppleHillsOverworld";
|
CurrentGameplayScene = "AppleHillsOverworld";
|
||||||
LogDebugMessage($"No valid active scene, defaulting to: {CurrentGameplayScene}");
|
Logging.Debug($"No valid active scene, defaulting to: {CurrentGameplayScene}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,7 +303,7 @@ namespace Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PHASE 2: Broadcast scene unloading - notify components to cleanup
|
// PHASE 2: Broadcast scene unloading - notify components to cleanup
|
||||||
LogDebugMessage($"Broadcasting OnSceneUnloading for: {oldSceneName}");
|
Logging.Debug($"Broadcasting OnSceneUnloading for: {oldSceneName}");
|
||||||
LifecycleManager.Instance?.BroadcastSceneUnloading(oldSceneName);
|
LifecycleManager.Instance?.BroadcastSceneUnloading(oldSceneName);
|
||||||
|
|
||||||
// PHASE 3: Save scene-specific data via SaveLoadManager (unless skipSave is true)
|
// PHASE 3: Save scene-specific data via SaveLoadManager (unless skipSave is true)
|
||||||
@@ -316,19 +312,19 @@ namespace Core
|
|||||||
var debugSettings = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>();
|
var debugSettings = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>();
|
||||||
if (debugSettings.useSaveLoadSystem)
|
if (debugSettings.useSaveLoadSystem)
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Saving scene data for: {oldSceneName}");
|
Logging.Debug($"Saving scene data for: {oldSceneName}");
|
||||||
SaveLoadManager.Instance.SaveSceneData();
|
SaveLoadManager.Instance.SaveSceneData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (skipSave)
|
else if (skipSave)
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Skipping save for: {oldSceneName} (skipSave=true)");
|
Logging.Debug($"Skipping save for: {oldSceneName} (skipSave=true)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// PHASE 4: Clear PuzzleManager state before scene transition
|
// PHASE 4: Clear PuzzleManager state before scene transition
|
||||||
if (PuzzleS.PuzzleManager.Instance != null)
|
if (PuzzleS.PuzzleManager.Instance != null)
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Clearing puzzle state before scene transition");
|
Logging.Debug($"Clearing puzzle state before scene transition");
|
||||||
PuzzleS.PuzzleManager.Instance.ClearPuzzleState();
|
PuzzleS.PuzzleManager.Instance.ClearPuzzleState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,7 +348,7 @@ namespace Core
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logging.Warning($"[SceneManagerService] Previous scene '{oldSceneName}' is not loaded, skipping unload.");
|
Logging.Warning($"Previous scene '{oldSceneName}' is not loaded, skipping unload.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,15 +360,15 @@ namespace Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PHASE 8: Begin scene loading mode - enables priority-ordered component initialization
|
// PHASE 8: Begin scene loading mode - enables priority-ordered component initialization
|
||||||
LogDebugMessage($"Beginning scene load for: {newSceneName}");
|
Logging.Debug($"Beginning scene load for: {newSceneName}");
|
||||||
LifecycleManager.Instance?.BeginSceneLoad(newSceneName);
|
LifecycleManager.Instance?.BeginSceneLoad(newSceneName);
|
||||||
|
|
||||||
// PHASE 9: Load new gameplay scene
|
// PHASE 9: Load new gameplay scene
|
||||||
await LoadSceneAsync(newSceneName, progress);
|
await LoadSceneAsync(newSceneName, progress);
|
||||||
CurrentGameplayScene = newSceneName;
|
CurrentGameplayScene = newSceneName;
|
||||||
|
|
||||||
// PHASE 10: Broadcast scene ready - processes batched components in priority order, then calls OnSceneReady
|
// PHASE 10: Broadcast scene ready - processes batched components, then calls OnSceneReady
|
||||||
LogDebugMessage($"Broadcasting OnSceneReady for: {newSceneName}");
|
Logging.Debug($"Broadcasting OnSceneReady for: {newSceneName}");
|
||||||
LifecycleManager.Instance?.BroadcastSceneReady(newSceneName);
|
LifecycleManager.Instance?.BroadcastSceneReady(newSceneName);
|
||||||
|
|
||||||
// PHASE 11: Restore scene-specific data via SaveLoadManager
|
// PHASE 11: Restore scene-specific data via SaveLoadManager
|
||||||
@@ -381,13 +377,14 @@ namespace Core
|
|||||||
var debugSettings = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>();
|
var debugSettings = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>();
|
||||||
if (debugSettings.useSaveLoadSystem)
|
if (debugSettings.useSaveLoadSystem)
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Restoring scene data for: {newSceneName}");
|
Logging.Debug($"Restoring scene data for: {newSceneName}");
|
||||||
SaveLoadManager.Instance.RestoreSceneData();
|
SaveLoadManager.Instance.RestoreSceneData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (skipSave)
|
else if (skipSave)
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Skipping restore for: {newSceneName} (skipSave=true)");
|
SaveLoadManager.Instance.RestoreSceneData();
|
||||||
|
Logging.Debug($"Skipping restore for: {newSceneName} (skipSave=true)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// PHASE 12: Only hide the loading screen if autoHideLoadingScreen is true
|
// PHASE 12: Only hide the loading screen if autoHideLoadingScreen is true
|
||||||
@@ -396,13 +393,5 @@ namespace Core
|
|||||||
_loadingScreen.HideLoadingScreen();
|
_loadingScreen.HideLoadingScreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LogDebugMessage(string message)
|
|
||||||
{
|
|
||||||
if (_logVerbosity <= LogVerbosity.Debug)
|
|
||||||
{
|
|
||||||
Logging.Debug($"[SceneManagerService] {message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,23 +18,18 @@ namespace Core
|
|||||||
public GameObject orientationPromptPrefab;
|
public GameObject orientationPromptPrefab;
|
||||||
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
|
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
|
||||||
|
|
||||||
// ManagedBehaviour configuration
|
internal override void OnManagedAwake()
|
||||||
public override int ManagedAwakePriority => 70; // Platform-specific utility
|
|
||||||
|
|
||||||
private new void Awake()
|
|
||||||
{
|
{
|
||||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
// Set instance immediately (early initialization)
|
||||||
|
|
||||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
|
|
||||||
// Load verbosity settings early (GameManager sets up settings in its Awake)
|
// Load verbosity settings early (GameManager sets up settings in its OnManagedAwake)
|
||||||
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().sceneLogVerbosity;
|
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().sceneLogVerbosity;
|
||||||
|
|
||||||
LogDebugMessage("Initialized");
|
Logging.Debug("Initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
// Subscribe to SceneManagerService to enforce orientation on every scene load
|
// Subscribe to SceneManagerService to enforce orientation on every scene load
|
||||||
if (SceneManagerService.Instance != null)
|
if (SceneManagerService.Instance != null)
|
||||||
@@ -51,7 +46,7 @@ namespace Core
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneReady()
|
internal override void OnSceneReady()
|
||||||
{
|
{
|
||||||
// Handle orientation when scene is ready (initial scene)
|
// Handle orientation when scene is ready (initial scene)
|
||||||
// Note: This fires for the scene that just loaded, LifecycleManager tracks which scene
|
// Note: This fires for the scene that just loaded, LifecycleManager tracks which scene
|
||||||
@@ -73,7 +68,7 @@ namespace Core
|
|||||||
if (sceneName.ToLower().Contains("bootstrap"))
|
if (sceneName.ToLower().Contains("bootstrap"))
|
||||||
{
|
{
|
||||||
// Bootstrap being loaded additively, don't do anything
|
// Bootstrap being loaded additively, don't do anything
|
||||||
LogDebugMessage($"Detected bootstrapped scene: '{sceneName}'. Skipping orientation enforcement.");
|
Logging.Debug($"Detected bootstrapped scene: '{sceneName}'. Skipping orientation enforcement.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,37 +78,35 @@ namespace Core
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogDebugMessage($"No orientationConfig assigned. Defaulting to Landscape for scene '{sceneName}'");
|
Logging.Debug($"No orientationConfig assigned. Defaulting to Landscape for scene '{sceneName}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (requirement)
|
switch (requirement)
|
||||||
{
|
{
|
||||||
case ScreenOrientationRequirement.Portrait:
|
case ScreenOrientationRequirement.Portrait:
|
||||||
LogDebugMessage($"Forcing Portrait for scene '{sceneName}'");
|
Logging.Debug($"Forcing Portrait for scene '{sceneName}'");
|
||||||
StartCoroutine(ForcePortrait());
|
StartCoroutine(ForcePortrait());
|
||||||
break;
|
break;
|
||||||
case ScreenOrientationRequirement.Landscape:
|
case ScreenOrientationRequirement.Landscape:
|
||||||
LogDebugMessage($"Forcing Landscape for scene '{sceneName}'");
|
Logging.Debug($"Forcing Landscape for scene '{sceneName}'");
|
||||||
StartCoroutine(ForceLandscape());
|
StartCoroutine(ForceLandscape());
|
||||||
break;
|
break;
|
||||||
case ScreenOrientationRequirement.NotApplicable:
|
case ScreenOrientationRequirement.NotApplicable:
|
||||||
default:
|
default:
|
||||||
// Default to landscape when no specific requirement is found
|
// Default to landscape when no specific requirement is found
|
||||||
LogDebugMessage($"No specific orientation for scene '{sceneName}'. Defaulting to Landscape");
|
Logging.Debug($"No specific orientation for scene '{sceneName}'. Defaulting to Landscape");
|
||||||
StartCoroutine(ForceLandscape());
|
StartCoroutine(ForceLandscape());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
// Unsubscribe from events to prevent memory leaks
|
// Unsubscribe from events to prevent memory leaks
|
||||||
if (SceneManagerService.Instance != null)
|
if (SceneManagerService.Instance != null)
|
||||||
{
|
{
|
||||||
SceneManagerService.Instance.SceneLoadCompleted -= OnSceneLoadCompleted;
|
SceneManagerService.Instance.SceneLoadCompleted -= OnSceneLoadCompleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
base.OnDestroy(); // Important: call base
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -127,12 +120,12 @@ namespace Core
|
|||||||
if (!currentlyLandscape)
|
if (!currentlyLandscape)
|
||||||
{
|
{
|
||||||
// Lock it to portrait and allow the device to orient itself
|
// Lock it to portrait and allow the device to orient itself
|
||||||
LogDebugMessage($"Actually forcing Portrait from previous: {Screen.orientation}");
|
Logging.Debug($"Actually forcing Portrait from previous: {Screen.orientation}");
|
||||||
Screen.orientation = ScreenOrientation.LandscapeRight;
|
Screen.orientation = ScreenOrientation.LandscapeRight;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Skipping Landscape enforcement, device already in: {Screen.orientation}");
|
Logging.Debug($"Skipping Landscape enforcement, device already in: {Screen.orientation}");
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return null;
|
yield return null;
|
||||||
@@ -160,12 +153,12 @@ namespace Core
|
|||||||
if (!currentlyPortrait)
|
if (!currentlyPortrait)
|
||||||
{
|
{
|
||||||
// Lock it to portrait and allow the device to orient itself
|
// Lock it to portrait and allow the device to orient itself
|
||||||
LogDebugMessage($"Actually forcing Portrait from previous: {Screen.orientation}");
|
Logging.Debug($"Actually forcing Portrait from previous: {Screen.orientation}");
|
||||||
Screen.orientation = ScreenOrientation.PortraitUpsideDown;
|
Screen.orientation = ScreenOrientation.PortraitUpsideDown;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Skipping Portrait enforcement, device already in: {Screen.orientation}");
|
Logging.Debug($"Skipping Portrait enforcement, device already in: {Screen.orientation}");
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return null;
|
yield return null;
|
||||||
@@ -181,13 +174,5 @@ namespace Core
|
|||||||
// Allow device to auto-rotate to correct portrait orientation
|
// Allow device to auto-rotate to correct portrait orientation
|
||||||
Screen.orientation = ScreenOrientation.AutoRotation;
|
Screen.orientation = ScreenOrientation.AutoRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LogDebugMessage(string message)
|
|
||||||
{
|
|
||||||
if (_logVerbosity <= LogVerbosity.Debug)
|
|
||||||
{
|
|
||||||
Logging.Debug($"[SceneOrientationEnforcer] {message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using AppleHills.Core.Settings;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Core.Settings
|
namespace Core.Settings
|
||||||
{
|
{
|
||||||
@@ -21,7 +19,7 @@ namespace Core.Settings
|
|||||||
public static void Register<T>(T service) where T : class
|
public static void Register<T>(T service) where T : class
|
||||||
{
|
{
|
||||||
Services[typeof(T)] = service;
|
Services[typeof(T)] = service;
|
||||||
LogDebugMessage($"Service registered: {typeof(T).Name}");
|
Logging.Debug($"Service registered: {typeof(T).Name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -36,7 +34,7 @@ namespace Core.Settings
|
|||||||
return service as T;
|
return service as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logging.Warning($"[ServiceLocator] Service of type {typeof(T).Name} not found!");
|
Logging.Warning($"Service of type {typeof(T).Name} not found!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,16 +44,7 @@ namespace Core.Settings
|
|||||||
public static void Clear()
|
public static void Clear()
|
||||||
{
|
{
|
||||||
Services.Clear();
|
Services.Clear();
|
||||||
LogDebugMessage("All services cleared");
|
Logging.Debug("All services cleared");
|
||||||
}
|
|
||||||
|
|
||||||
private static void LogDebugMessage(string message)
|
|
||||||
{
|
|
||||||
if (DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().settingsLogVerbosity <=
|
|
||||||
LogVerbosity.Debug)
|
|
||||||
{
|
|
||||||
Logging.Debug($"[ServiceLocator] {message}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Pixelplacement;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using Core;
|
using Core;
|
||||||
|
using Core.Lifecycle;
|
||||||
using Core.SaveLoad;
|
using Core.SaveLoad;
|
||||||
using UnityEngine.Audio;
|
using UnityEngine.Audio;
|
||||||
|
|
||||||
public class PicnicBehaviour : MonoBehaviour
|
public class PicnicBehaviour : ManagedBehaviour
|
||||||
{
|
{
|
||||||
[Header("Random Call Settings")]
|
[Header("Random Call Settings")]
|
||||||
public float getDistractedMin = 2f;
|
public float getDistractedMin = 2f;
|
||||||
@@ -17,7 +18,8 @@ public class PicnicBehaviour : MonoBehaviour
|
|||||||
private Animator animator;
|
private Animator animator;
|
||||||
|
|
||||||
[Header("The FakeChocolate to destroy!")]
|
[Header("The FakeChocolate to destroy!")]
|
||||||
[SerializeField] private GameObject fakeChocolate; // Assign in Inspector
|
[SerializeField] private GameObject fakeChocolate;
|
||||||
|
[SerializeField] private GameObject realChocolate;
|
||||||
|
|
||||||
private AppleAudioSource _audioSource;
|
private AppleAudioSource _audioSource;
|
||||||
public AudioResource distractedAudioClips;
|
public AudioResource distractedAudioClips;
|
||||||
@@ -25,32 +27,44 @@ public class PicnicBehaviour : MonoBehaviour
|
|||||||
public AudioResource feederClips;
|
public AudioResource feederClips;
|
||||||
public AudioResource moanerClips;
|
public AudioResource moanerClips;
|
||||||
|
|
||||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
// Save system configuration
|
||||||
void Start()
|
public override bool AutoRegisterForSave => true;
|
||||||
{
|
|
||||||
StartCoroutine(StateCycleRoutine());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Awake()
|
// Runtime state tracking
|
||||||
|
private bool _fakeChocolateDestroyed;
|
||||||
|
|
||||||
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
stateMachine = GetComponent<AppleMachine>();
|
stateMachine = GetComponent<AppleMachine>();
|
||||||
animator = GetComponent<Animator>();
|
animator = GetComponent<Animator>();
|
||||||
_audioSource = GetComponent<AppleAudioSource>();
|
_audioSource = GetComponent<AppleAudioSource>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal override void OnSceneRestoreCompleted()
|
||||||
|
{
|
||||||
|
if (_fakeChocolateDestroyed)
|
||||||
|
{
|
||||||
|
DestroyChocolateObjects();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StartCoroutine(StateCycleRoutine());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private IEnumerator StateCycleRoutine()
|
private IEnumerator StateCycleRoutine()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// Distracted state
|
// Distracted state
|
||||||
float distractedWait = Random.Range(getDistractedMin, getDistractedMax);
|
float distractedWait = UnityEngine.Random.Range(getDistractedMin, getDistractedMax);
|
||||||
stateMachine.ChangeState("Picnic PPL Distracted");
|
stateMachine.ChangeState("Picnic PPL Distracted");
|
||||||
animator.SetBool("theyDistracted", true);
|
animator.SetBool("theyDistracted", true);
|
||||||
_audioSource.Stop();
|
_audioSource.Stop();
|
||||||
yield return new WaitForSeconds(distractedWait);
|
yield return new WaitForSeconds(distractedWait);
|
||||||
|
|
||||||
// Chilling state
|
// Chilling state
|
||||||
float chillingWait = Random.Range(getFlirtyMin, getFlirtyMax);
|
float chillingWait = UnityEngine.Random.Range(getFlirtyMin, getFlirtyMax);
|
||||||
stateMachine.ChangeState("Picnic PPL Chilling");
|
stateMachine.ChangeState("Picnic PPL Chilling");
|
||||||
animator.SetBool("theyDistracted", false);
|
animator.SetBool("theyDistracted", false);
|
||||||
_audioSource.Stop();
|
_audioSource.Stop();
|
||||||
@@ -58,27 +72,33 @@ public class PicnicBehaviour : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StopAudio()
|
|
||||||
{
|
|
||||||
_audioSource.Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void triedToStealChocolate()
|
public void triedToStealChocolate()
|
||||||
{
|
{
|
||||||
_audioSource.Stop();
|
_audioSource.Stop();
|
||||||
animator.SetTrigger("theyAngry");
|
animator.SetTrigger("theyAngry");
|
||||||
//stateMachine.ChangeState("Picnic PPL Angry");
|
|
||||||
Logging.Debug("Hey! Don't steal my chocolate!");
|
Logging.Debug("Hey! Don't steal my chocolate!");
|
||||||
_audioSource.audioSource.resource = angryAudioClips;
|
_audioSource.audioSource.resource = angryAudioClips;
|
||||||
_audioSource.Play(0);
|
_audioSource.Play(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroyFakeChocolate()
|
public void destroyFakeChocolate()
|
||||||
|
{
|
||||||
|
_fakeChocolateDestroyed = true;
|
||||||
|
Destroy(fakeChocolate);
|
||||||
|
Destroy(realChocolate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DestroyChocolateObjects()
|
||||||
{
|
{
|
||||||
if (fakeChocolate != null)
|
if (fakeChocolate != null)
|
||||||
{
|
{
|
||||||
Destroy(fakeChocolate);
|
Destroy(fakeChocolate);
|
||||||
fakeChocolate = null; // Optional: clear reference
|
fakeChocolate = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (realChocolate != null)
|
||||||
|
{
|
||||||
|
realChocolate.SetActive(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,5 +120,33 @@ public class PicnicBehaviour : MonoBehaviour
|
|||||||
_audioSource.Play(0);
|
_audioSource.Play(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal override string OnSceneSaveRequested()
|
||||||
|
{
|
||||||
|
var state = new PicnicBehaviourState { fakeChocolateDestroyed = _fakeChocolateDestroyed };
|
||||||
|
return JsonUtility.ToJson(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void OnSceneRestoreRequested(string serializedData)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(serializedData)) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var state = JsonUtility.FromJson<PicnicBehaviourState>(serializedData);
|
||||||
|
if (state != null)
|
||||||
|
{
|
||||||
|
_fakeChocolateDestroyed = state.fakeChocolateDestroyed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"[PicnicBehaviour] Failed to restore state: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class PicnicBehaviourState
|
||||||
|
{
|
||||||
|
public bool fakeChocolateDestroyed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Core;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Core.Lifecycle;
|
using Core.Lifecycle;
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ public class soundBird_CanFly : ManagedBehaviour
|
|||||||
|
|
||||||
#region Save/Load Implementation
|
#region Save/Load Implementation
|
||||||
|
|
||||||
protected override string OnSceneSaveRequested()
|
internal override string OnSceneSaveRequested()
|
||||||
{
|
{
|
||||||
var saveData = new SoundBirdSaveData
|
var saveData = new SoundBirdSaveData
|
||||||
{
|
{
|
||||||
@@ -31,11 +32,11 @@ public class soundBird_CanFly : ManagedBehaviour
|
|||||||
return JsonUtility.ToJson(saveData);
|
return JsonUtility.ToJson(saveData);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneRestoreRequested(string serializedData)
|
internal override void OnSceneRestoreRequested(string serializedData)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(serializedData))
|
if (string.IsNullOrEmpty(serializedData))
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[soundBird_CanFly] No save data to restore for {gameObject.name}");
|
Logging.Warning($"[soundBird_CanFly] No save data to restore for {gameObject.name}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ public class soundBird_CanFly : ManagedBehaviour
|
|||||||
if (saveData != null)
|
if (saveData != null)
|
||||||
{
|
{
|
||||||
canFly = saveData.canFly;
|
canFly = saveData.canFly;
|
||||||
Debug.Log($"[soundBird_CanFly] Restored canFly state: {canFly}");
|
Logging.Debug($"[soundBird_CanFly] Restored canFly state: {canFly}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ namespace AppleHills.Data.CardSystem
|
|||||||
|
|
||||||
public enum CardZone
|
public enum CardZone
|
||||||
{
|
{
|
||||||
|
NotApplicable,
|
||||||
AppleHills,
|
AppleHills,
|
||||||
Quarry,
|
Quarry,
|
||||||
CementFactory,
|
CementFactory,
|
||||||
|
|||||||
@@ -40,25 +40,20 @@ namespace Data.CardSystem
|
|||||||
// Event callbacks using System.Action
|
// Event callbacks using System.Action
|
||||||
public event Action<List<CardData>> OnBoosterOpened;
|
public event Action<List<CardData>> OnBoosterOpened;
|
||||||
public event Action<CardData> OnCardCollected;
|
public event Action<CardData> OnCardCollected;
|
||||||
public event Action<CardData> OnCardRarityUpgraded;
|
|
||||||
public event Action<int> OnBoosterCountChanged;
|
public event Action<int> OnBoosterCountChanged;
|
||||||
public event Action<CardData> OnPendingCardAdded;
|
public event Action<CardData> OnPendingCardAdded;
|
||||||
public event Action<CardData> OnCardPlacedInAlbum;
|
public event Action<CardData> OnCardPlacedInAlbum;
|
||||||
|
|
||||||
public override int ManagedAwakePriority => 60; // Data systems
|
|
||||||
|
|
||||||
private new void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
// Set instance immediately (early initialization)
|
||||||
|
|
||||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
|
|
||||||
// Load card definitions from Addressables, then register with save system
|
// Load card definitions from Addressables, then register with save system
|
||||||
LoadCardDefinitionsFromAddressables();
|
LoadCardDefinitionsFromAddressables();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
Logging.Debug("[CardSystemManager] Initialized");
|
Logging.Debug("[CardSystemManager] Initialized");
|
||||||
}
|
}
|
||||||
@@ -720,13 +715,13 @@ namespace Data.CardSystem
|
|||||||
|
|
||||||
#region Save/Load Lifecycle Hooks
|
#region Save/Load Lifecycle Hooks
|
||||||
|
|
||||||
protected override string OnGlobalSaveRequested()
|
internal override string OnGlobalSaveRequested()
|
||||||
{
|
{
|
||||||
var state = ExportCardCollectionState();
|
var state = ExportCardCollectionState();
|
||||||
return JsonUtility.ToJson(state);
|
return JsonUtility.ToJson(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnGlobalRestoreRequested(string serializedData)
|
internal override void OnGlobalRestoreRequested(string serializedData)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(serializedData))
|
if (string.IsNullOrEmpty(serializedData))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Core;
|
using Core;
|
||||||
using Core.Lifecycle;
|
using Core.Lifecycle;
|
||||||
using Interactions;
|
using Interactions;
|
||||||
@@ -34,10 +32,7 @@ namespace Dialogue
|
|||||||
public bool IsCompleted { get; private set; }
|
public bool IsCompleted { get; private set; }
|
||||||
public string CurrentSpeakerName => dialogueGraph?.speakerName;
|
public string CurrentSpeakerName => dialogueGraph?.speakerName;
|
||||||
|
|
||||||
|
internal override void OnManagedStart()
|
||||||
public override int ManagedAwakePriority => 150; // Dialogue systems
|
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
|
||||||
{
|
{
|
||||||
// Get required components
|
// Get required components
|
||||||
appleAudioSource = GetComponent<AppleAudioSource>();
|
appleAudioSource = GetComponent<AppleAudioSource>();
|
||||||
@@ -186,7 +181,7 @@ namespace Dialogue
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
// Unregister from events
|
// Unregister from events
|
||||||
if (PuzzleManager.Instance != null)
|
if (PuzzleManager.Instance != null)
|
||||||
|
|||||||
@@ -49,14 +49,10 @@ namespace Input
|
|||||||
private ITouchInputConsumer defaultConsumer;
|
private ITouchInputConsumer defaultConsumer;
|
||||||
private bool isHoldActive;
|
private bool isHoldActive;
|
||||||
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
|
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
|
||||||
|
|
||||||
public override int ManagedAwakePriority => 25; // Input infrastructure
|
|
||||||
|
|
||||||
private new void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
// Set instance immediately (early initialization)
|
||||||
|
|
||||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
|
|
||||||
// Load verbosity settings early
|
// Load verbosity settings early
|
||||||
@@ -89,10 +85,10 @@ namespace Input
|
|||||||
SwitchInputOnSceneLoaded(SceneManager.GetActiveScene().name);
|
SwitchInputOnSceneLoaded(SceneManager.GetActiveScene().name);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
// Subscribe to scene load events from SceneManagerService
|
// Subscribe to scene load events from SceneManagerService
|
||||||
// This must happen in ManagedAwake because SceneManagerService instance needs to be set first
|
// This must happen in ManagedStart because SceneManagerService instance needs to be set first
|
||||||
if (SceneManagerService.Instance != null)
|
if (SceneManagerService.Instance != null)
|
||||||
{
|
{
|
||||||
SceneManagerService.Instance.SceneLoadCompleted += OnSceneLoadCompleted;
|
SceneManagerService.Instance.SceneLoadCompleted += OnSceneLoadCompleted;
|
||||||
@@ -104,11 +100,11 @@ namespace Input
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnSceneLoadCompleted(string sceneName)
|
private void OnSceneLoadCompleted(string sceneName)
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Scene loaded: {sceneName}, restoring input mode");
|
Logging.Debug($"Scene loaded: {sceneName}, restoring input mode");
|
||||||
SwitchInputOnSceneLoaded(sceneName);
|
SwitchInputOnSceneLoaded(sceneName);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
// Unsubscribe from SceneManagerService events
|
// Unsubscribe from SceneManagerService events
|
||||||
if (SceneManagerService.Instance != null)
|
if (SceneManagerService.Instance != null)
|
||||||
@@ -116,7 +112,6 @@ namespace Input
|
|||||||
SceneManagerService.Instance.SceneLoadCompleted -= OnSceneLoadCompleted;
|
SceneManagerService.Instance.SceneLoadCompleted -= OnSceneLoadCompleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
base.OnDestroy();
|
|
||||||
// Input action cleanup happens automatically
|
// Input action cleanup happens automatically
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,24 +177,24 @@ namespace Input
|
|||||||
Vector2 screenPos = positionAction.ReadValue<Vector2>();
|
Vector2 screenPos = positionAction.ReadValue<Vector2>();
|
||||||
Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos);
|
Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos);
|
||||||
Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y);
|
Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y);
|
||||||
LogDebugMessage($"TapMove performed at {worldPos2D}");
|
Logging.Debug($"TapMove performed at {worldPos2D}");
|
||||||
|
|
||||||
// First try to delegate to an override consumer if available
|
// First try to delegate to an override consumer if available
|
||||||
if (TryDelegateToOverrideConsumer(screenPos, worldPos2D))
|
if (TryDelegateToOverrideConsumer(screenPos, worldPos2D))
|
||||||
{
|
{
|
||||||
LogDebugMessage("Tap delegated to override consumer");
|
Logging.Debug("Tap delegated to override consumer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then try to delegate to any ITouchInputConsumer (UI or world interactable)
|
// Then try to delegate to any ITouchInputConsumer (UI or world interactable)
|
||||||
if (!TryDelegateToAnyInputConsumer(screenPos, worldPos2D))
|
if (!TryDelegateToAnyInputConsumer(screenPos, worldPos2D))
|
||||||
{
|
{
|
||||||
LogDebugMessage("No input consumer found, forwarding tap to default consumer");
|
Logging.Debug("No input consumer found, forwarding tap to default consumer");
|
||||||
defaultConsumer?.OnTap(worldPos2D);
|
defaultConsumer?.OnTap(worldPos2D);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogDebugMessage("Tap delegated to input consumer");
|
Logging.Debug("Tap delegated to input consumer");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,13 +207,13 @@ namespace Input
|
|||||||
Vector2 screenPos = positionAction.ReadValue<Vector2>();
|
Vector2 screenPos = positionAction.ReadValue<Vector2>();
|
||||||
Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos);
|
Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos);
|
||||||
Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y);
|
Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y);
|
||||||
LogDebugMessage($"HoldMove started at {worldPos2D}");
|
Logging.Debug($"HoldMove started at {worldPos2D}");
|
||||||
|
|
||||||
// First check for override consumers
|
// First check for override consumers
|
||||||
if (_overrideConsumers.Count > 0)
|
if (_overrideConsumers.Count > 0)
|
||||||
{
|
{
|
||||||
_activeHoldConsumer = _overrideConsumers[_overrideConsumers.Count - 1];
|
_activeHoldConsumer = _overrideConsumers[_overrideConsumers.Count - 1];
|
||||||
LogDebugMessage($"Hold delegated to override consumer: {_activeHoldConsumer}");
|
Logging.Debug($"Hold delegated to override consumer: {_activeHoldConsumer}");
|
||||||
_activeHoldConsumer.OnHoldStart(worldPos2D);
|
_activeHoldConsumer.OnHoldStart(worldPos2D);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -238,7 +233,7 @@ namespace Input
|
|||||||
Vector2 screenPos = positionAction.ReadValue<Vector2>();
|
Vector2 screenPos = positionAction.ReadValue<Vector2>();
|
||||||
Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos);
|
Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos);
|
||||||
Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y);
|
Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y);
|
||||||
LogDebugMessage($"HoldMove canceled at {worldPos2D}");
|
Logging.Debug($"HoldMove canceled at {worldPos2D}");
|
||||||
|
|
||||||
// Notify the active hold consumer that the hold has ended
|
// Notify the active hold consumer that the hold has ended
|
||||||
_activeHoldConsumer?.OnHoldEnd(worldPos2D);
|
_activeHoldConsumer?.OnHoldEnd(worldPos2D);
|
||||||
@@ -302,7 +297,7 @@ namespace Input
|
|||||||
}
|
}
|
||||||
if (consumer != null)
|
if (consumer != null)
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Delegating tap to UI consumer at {screenPos} (GameObject: {result.gameObject.name})");
|
Logging.Debug($"Delegating tap to UI consumer at {screenPos} (GameObject: {result.gameObject.name})");
|
||||||
consumer.OnTap(screenPos);
|
consumer.OnTap(screenPos);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -331,7 +326,7 @@ namespace Input
|
|||||||
}
|
}
|
||||||
if (consumer != null)
|
if (consumer != null)
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Delegating tap to consumer at {worldPos} (GameObject: {hitWithMask.gameObject.name})");
|
Logging.Debug($"Delegating tap to consumer at {worldPos} (GameObject: {hitWithMask.gameObject.name})");
|
||||||
consumer.OnTap(worldPos);
|
consumer.OnTap(worldPos);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -345,15 +340,15 @@ namespace Input
|
|||||||
var consumer = hit.GetComponent<ITouchInputConsumer>();
|
var consumer = hit.GetComponent<ITouchInputConsumer>();
|
||||||
if (consumer != null)
|
if (consumer != null)
|
||||||
{
|
{
|
||||||
LogDebugMessage($"Delegating tap to consumer at {worldPos} (GameObject: {hit.gameObject.name})");
|
Logging.Debug($"Delegating tap to consumer at {worldPos} (GameObject: {hit.gameObject.name})");
|
||||||
consumer.OnTap(worldPos);
|
consumer.OnTap(worldPos);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
LogDebugMessage($"Collider2D hit at {worldPos} (GameObject: {hit.gameObject.name}), but no ITouchInputConsumer found.");
|
Logging.Debug($"Collider2D hit at {worldPos} (GameObject: {hit.gameObject.name}), but no ITouchInputConsumer found.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogDebugMessage($"No Collider2D found at {worldPos} for interactable delegation.");
|
Logging.Debug($"No Collider2D found at {worldPos} for interactable delegation.");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -368,7 +363,7 @@ namespace Input
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
_overrideConsumers.Add(consumer);
|
_overrideConsumers.Add(consumer);
|
||||||
LogDebugMessage($"Override consumer registered: {consumer}");
|
Logging.Debug($"Override consumer registered: {consumer}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -386,7 +381,7 @@ namespace Input
|
|||||||
}
|
}
|
||||||
|
|
||||||
_overrideConsumers.Remove(consumer);
|
_overrideConsumers.Remove(consumer);
|
||||||
LogDebugMessage($"Override consumer unregistered: {consumer}");
|
Logging.Debug($"Override consumer unregistered: {consumer}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -396,7 +391,7 @@ namespace Input
|
|||||||
{
|
{
|
||||||
_activeHoldConsumer = null;
|
_activeHoldConsumer = null;
|
||||||
_overrideConsumers.Clear();
|
_overrideConsumers.Clear();
|
||||||
LogDebugMessage("All override consumers cleared.");
|
Logging.Debug("All override consumers cleared.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -409,17 +404,9 @@ namespace Input
|
|||||||
|
|
||||||
// Get the topmost override consumer (last registered)
|
// Get the topmost override consumer (last registered)
|
||||||
var consumer = _overrideConsumers[_overrideConsumers.Count - 1];
|
var consumer = _overrideConsumers[_overrideConsumers.Count - 1];
|
||||||
LogDebugMessage($"Delegating tap to override consumer at {worldPos} (GameObject: {consumer})");
|
Logging.Debug($"Delegating tap to override consumer at {worldPos} (GameObject: {consumer})");
|
||||||
consumer.OnTap(worldPos);
|
consumer.OnTap(worldPos);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LogDebugMessage(string message)
|
|
||||||
{
|
|
||||||
if (_logVerbosity <= LogVerbosity.Debug)
|
|
||||||
{
|
|
||||||
Logging.Debug($"[InputManager] {message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Pathfinding;
|
|||||||
using AppleHills.Core.Settings;
|
using AppleHills.Core.Settings;
|
||||||
using Core;
|
using Core;
|
||||||
using Core.Lifecycle;
|
using Core.Lifecycle;
|
||||||
using Core.SaveLoad;
|
|
||||||
|
|
||||||
namespace Input
|
namespace Input
|
||||||
{
|
{
|
||||||
@@ -71,9 +70,8 @@ namespace Input
|
|||||||
public override bool AutoRegisterForSave => true;
|
public override bool AutoRegisterForSave => true;
|
||||||
// Scene-specific SaveId - each level has its own player state
|
// Scene-specific SaveId - each level has its own player state
|
||||||
public override string SaveId => $"{gameObject.scene.name}/PlayerController";
|
public override string SaveId => $"{gameObject.scene.name}/PlayerController";
|
||||||
public override int ManagedAwakePriority => 100; // Player controller
|
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
aiPath = GetComponent<AIPath>();
|
aiPath = GetComponent<AIPath>();
|
||||||
artTransform = transform.Find("CharacterArt");
|
artTransform = transform.Find("CharacterArt");
|
||||||
@@ -103,7 +101,7 @@ namespace Input
|
|||||||
public void OnTap(Vector2 worldPosition)
|
public void OnTap(Vector2 worldPosition)
|
||||||
{
|
{
|
||||||
InterruptMoveTo();
|
InterruptMoveTo();
|
||||||
LogDebugMessage($"OnTap at {worldPosition}");
|
Logging.Debug($"OnTap at {worldPosition}");
|
||||||
if (aiPath != null)
|
if (aiPath != null)
|
||||||
{
|
{
|
||||||
aiPath.enabled = true;
|
aiPath.enabled = true;
|
||||||
@@ -122,7 +120,7 @@ namespace Input
|
|||||||
public void OnHoldStart(Vector2 worldPosition)
|
public void OnHoldStart(Vector2 worldPosition)
|
||||||
{
|
{
|
||||||
InterruptMoveTo();
|
InterruptMoveTo();
|
||||||
LogDebugMessage($"OnHoldStart at {worldPosition}");
|
Logging.Debug($"OnHoldStart at {worldPosition}");
|
||||||
lastHoldPosition = worldPosition;
|
lastHoldPosition = worldPosition;
|
||||||
isHolding = true;
|
isHolding = true;
|
||||||
if (_settings.DefaultHoldMovementMode == HoldMovementMode.Pathfinding &&
|
if (_settings.DefaultHoldMovementMode == HoldMovementMode.Pathfinding &&
|
||||||
@@ -159,7 +157,7 @@ namespace Input
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void OnHoldEnd(Vector2 worldPosition)
|
public void OnHoldEnd(Vector2 worldPosition)
|
||||||
{
|
{
|
||||||
LogDebugMessage($"OnHoldEnd at {worldPosition}");
|
Logging.Debug($"OnHoldEnd at {worldPosition}");
|
||||||
isHolding = false;
|
isHolding = false;
|
||||||
directMoveVelocity = Vector3.zero;
|
directMoveVelocity = Vector3.zero;
|
||||||
if (aiPath != null && _settings.DefaultHoldMovementMode ==
|
if (aiPath != null && _settings.DefaultHoldMovementMode ==
|
||||||
@@ -335,13 +333,13 @@ namespace Input
|
|||||||
{
|
{
|
||||||
_isMoving = true;
|
_isMoving = true;
|
||||||
OnMovementStarted?.Invoke();
|
OnMovementStarted?.Invoke();
|
||||||
LogDebugMessage("Movement started");
|
Logging.Debug("Movement started");
|
||||||
}
|
}
|
||||||
else if (!isCurrentlyMoving && _isMoving)
|
else if (!isCurrentlyMoving && _isMoving)
|
||||||
{
|
{
|
||||||
_isMoving = false;
|
_isMoving = false;
|
||||||
OnMovementStopped?.Invoke();
|
OnMovementStopped?.Invoke();
|
||||||
LogDebugMessage("Movement stopped");
|
Logging.Debug("Movement stopped");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,18 +422,10 @@ namespace Input
|
|||||||
OnArrivedAtTarget?.Invoke();
|
OnArrivedAtTarget?.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LogDebugMessage(string message)
|
|
||||||
{
|
|
||||||
if (_logVerbosity <= LogVerbosity.Debug)
|
|
||||||
{
|
|
||||||
Logging.Debug($"[PlayerTouchController] {message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Save/Load Lifecycle Hooks
|
#region Save/Load Lifecycle Hooks
|
||||||
|
|
||||||
protected override string OnSceneSaveRequested()
|
internal override string OnSceneSaveRequested()
|
||||||
{
|
{
|
||||||
var saveData = new PlayerSaveData
|
var saveData = new PlayerSaveData
|
||||||
{
|
{
|
||||||
@@ -445,7 +435,7 @@ namespace Input
|
|||||||
return JsonUtility.ToJson(saveData);
|
return JsonUtility.ToJson(saveData);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneRestoreRequested(string serializedData)
|
internal override void OnSceneRestoreRequested(string serializedData)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(serializedData))
|
if (string.IsNullOrEmpty(serializedData))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,9 +41,6 @@ namespace Interactions
|
|||||||
// Action component system
|
// Action component system
|
||||||
private List<InteractionActionBase> _registeredActions = new List<InteractionActionBase>();
|
private List<InteractionActionBase> _registeredActions = new List<InteractionActionBase>();
|
||||||
|
|
||||||
// ManagedBehaviour configuration
|
|
||||||
public override int ManagedAwakePriority => 100; // Gameplay base classes
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register an action component with this interactable
|
/// Register an action component with this interactable
|
||||||
@@ -190,7 +187,7 @@ namespace Interactions
|
|||||||
/// <returns>True if interaction succeeded, false otherwise</returns>
|
/// <returns>True if interaction succeeded, false otherwise</returns>
|
||||||
protected virtual bool DoInteraction()
|
protected virtual bool DoInteraction()
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[Interactable] DoInteraction not implemented for {GetType().Name}");
|
Logging.Warning($"[Interactable] DoInteraction not implemented for {GetType().Name}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,8 +68,6 @@ namespace Interactions
|
|||||||
public event Action<PickupItemData, PickupItemData> OnIncorrectItemSlotted;
|
public event Action<PickupItemData, PickupItemData> OnIncorrectItemSlotted;
|
||||||
|
|
||||||
public UnityEvent onForbiddenItemSlotted;
|
public UnityEvent onForbiddenItemSlotted;
|
||||||
// Native C# event alternative for code-only subscribers
|
|
||||||
public event Action<PickupItemData, PickupItemData> OnForbiddenItemSlotted;
|
|
||||||
|
|
||||||
public GameObject GetSlottedObject()
|
public GameObject GetSlottedObject()
|
||||||
{
|
{
|
||||||
@@ -85,9 +83,9 @@ namespace Interactions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake(); // SaveableInteractable registration
|
base.OnManagedAwake(); // SaveableInteractable registration
|
||||||
|
|
||||||
// Setup visuals
|
// Setup visuals
|
||||||
if (iconRenderer == null)
|
if (iconRenderer == null)
|
||||||
@@ -289,10 +287,8 @@ namespace Interactions
|
|||||||
ItemManager.Instance?.RegisterItemSlot(this);
|
ItemManager.Instance?.RegisterItemSlot(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
// Unregister from slot manager
|
// Unregister from slot manager
|
||||||
ItemManager.Instance?.UnregisterItemSlot(this);
|
ItemManager.Instance?.UnregisterItemSlot(this);
|
||||||
}
|
}
|
||||||
@@ -333,7 +329,7 @@ namespace Interactions
|
|||||||
ItemSlotSaveData data = JsonUtility.FromJson<ItemSlotSaveData>(serializedData);
|
ItemSlotSaveData data = JsonUtility.FromJson<ItemSlotSaveData>(serializedData);
|
||||||
if (data == null)
|
if (data == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ItemSlot] Failed to deserialize save data for {gameObject.name}");
|
Logging.Warning($"[ItemSlot] Failed to deserialize save data for {gameObject.name}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,7 +339,7 @@ namespace Interactions
|
|||||||
// Restore slotted item if there was one
|
// Restore slotted item if there was one
|
||||||
if (!string.IsNullOrEmpty(data.slottedItemSaveId))
|
if (!string.IsNullOrEmpty(data.slottedItemSaveId))
|
||||||
{
|
{
|
||||||
Debug.Log($"[ItemSlot] Restoring slotted item: {data.slottedItemSaveId} (itemId: {data.slottedItemDataId})");
|
Logging.Debug($"[ItemSlot] Restoring slotted item: {data.slottedItemSaveId} (itemId: {data.slottedItemDataId})");
|
||||||
RestoreSlottedItem(data.slottedItemSaveId, data.slottedItemDataId);
|
RestoreSlottedItem(data.slottedItemSaveId, data.slottedItemDataId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -361,7 +357,7 @@ namespace Interactions
|
|||||||
{
|
{
|
||||||
// Item not found in scene - it might be a dynamically spawned combined item
|
// Item not found in scene - it might be a dynamically spawned combined item
|
||||||
// Try to spawn it from the itemDataId
|
// Try to spawn it from the itemDataId
|
||||||
Debug.Log($"[ItemSlot] Slotted item not found in scene: {slottedItemSaveId}, attempting to spawn from itemId: {expectedItemDataId}");
|
Logging.Debug($"[ItemSlot] Slotted item not found in scene: {slottedItemSaveId}, attempting to spawn from itemId: {expectedItemDataId}");
|
||||||
|
|
||||||
GameObject prefab = interactionSettings?.FindPickupPrefabByItemId(expectedItemDataId);
|
GameObject prefab = interactionSettings?.FindPickupPrefabByItemId(expectedItemDataId);
|
||||||
if (prefab != null)
|
if (prefab != null)
|
||||||
@@ -369,17 +365,17 @@ namespace Interactions
|
|||||||
// Spawn the item (inactive, since it will be slotted)
|
// Spawn the item (inactive, since it will be slotted)
|
||||||
slottedObject = Instantiate(prefab, transform.position, Quaternion.identity);
|
slottedObject = Instantiate(prefab, transform.position, Quaternion.identity);
|
||||||
slottedObject.SetActive(false);
|
slottedObject.SetActive(false);
|
||||||
Debug.Log($"[ItemSlot] Successfully spawned combined item for slot: {expectedItemDataId}");
|
Logging.Debug($"[ItemSlot] Successfully spawned combined item for slot: {expectedItemDataId}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ItemSlot] Could not find prefab for itemId: {expectedItemDataId}");
|
Logging.Warning($"[ItemSlot] Could not find prefab for itemId: {expectedItemDataId}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (slottedObject == null)
|
else if (slottedObject == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ItemSlot] Could not find slotted item with save ID: {slottedItemSaveId}");
|
Logging.Warning($"[ItemSlot] Could not find slotted item with save ID: {slottedItemSaveId}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,13 +391,13 @@ namespace Interactions
|
|||||||
{
|
{
|
||||||
if (slottedData.itemId != expectedItemDataId)
|
if (slottedData.itemId != expectedItemDataId)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ItemSlot] ItemId mismatch! Pickup has '{slottedData.itemId}' but expected '{expectedItemDataId}'");
|
Logging.Warning($"[ItemSlot] ItemId mismatch! Pickup has '{slottedData.itemId}' but expected '{expectedItemDataId}'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slottedData == null)
|
if (slottedData == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ItemSlot] Pickup {pickup.gameObject.name} has null itemData! Expected itemId: {expectedItemDataId}");
|
Logging.Warning($"[ItemSlot] Pickup {pickup.gameObject.name} has null itemData! Expected itemId: {expectedItemDataId}");
|
||||||
if (slottedObject != null)
|
if (slottedObject != null)
|
||||||
Destroy(slottedObject);
|
Destroy(slottedObject);
|
||||||
return;
|
return;
|
||||||
@@ -409,7 +405,7 @@ namespace Interactions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ItemSlot] Slotted object has no Pickup component: {slottedObject.name}");
|
Logging.Warning($"[ItemSlot] Slotted object has no Pickup component: {slottedObject.name}");
|
||||||
if (slottedObject != null)
|
if (slottedObject != null)
|
||||||
Destroy(slottedObject);
|
Destroy(slottedObject);
|
||||||
return;
|
return;
|
||||||
@@ -419,7 +415,7 @@ namespace Interactions
|
|||||||
// Follower state is managed separately during save/load restoration
|
// Follower state is managed separately during save/load restoration
|
||||||
ApplySlottedItemState(slottedObject, slottedData, triggerEvents: false);
|
ApplySlottedItemState(slottedObject, slottedData, triggerEvents: false);
|
||||||
|
|
||||||
Debug.Log($"[ItemSlot] Successfully restored slotted item: {slottedData.itemName} (itemId: {slottedData.itemId})");
|
Logging.Debug($"[ItemSlot] Successfully restored slotted item: {slottedData.itemName} (itemId: {slottedData.itemId})");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -526,7 +522,7 @@ namespace Interactions
|
|||||||
// If slot already has an item, reject the claim
|
// If slot already has an item, reject the claim
|
||||||
if (currentlySlottedItemObject != null)
|
if (currentlySlottedItemObject != null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ItemSlot] Already has a slotted item, rejecting claim from {pickup.gameObject.name}");
|
Logging.Warning($"[ItemSlot] Already has a slotted item, rejecting claim from {pickup.gameObject.name}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,7 +533,7 @@ namespace Interactions
|
|||||||
// Claim the pickup
|
// Claim the pickup
|
||||||
ApplySlottedItemState(pickup.gameObject, pickup.itemData, triggerEvents: false);
|
ApplySlottedItemState(pickup.gameObject, pickup.itemData, triggerEvents: false);
|
||||||
|
|
||||||
Debug.Log($"[ItemSlot] Successfully claimed slotted item: {pickup.itemData?.itemName}");
|
Logging.Debug($"[ItemSlot] Successfully claimed slotted item: {pickup.itemData?.itemName}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ namespace Interactions
|
|||||||
public event Action<PickupItemData> OnItemPickedUp;
|
public event Action<PickupItemData> OnItemPickedUp;
|
||||||
public event Action<PickupItemData, PickupItemData, PickupItemData> OnItemsCombined;
|
public event Action<PickupItemData, PickupItemData, PickupItemData> OnItemsCombined;
|
||||||
|
|
||||||
protected override void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake(); // Register with save system
|
base.OnManagedAwake(); // Register with save system
|
||||||
|
|
||||||
if (iconRenderer == null)
|
if (iconRenderer == null)
|
||||||
iconRenderer = GetComponent<SpriteRenderer>();
|
iconRenderer = GetComponent<SpriteRenderer>();
|
||||||
@@ -44,15 +44,14 @@ namespace Interactions
|
|||||||
|
|
||||||
// Always register with ItemManager, even if picked up
|
// Always register with ItemManager, even if picked up
|
||||||
// This allows the save/load system to find held items when restoring state
|
// This allows the save/load system to find held items when restoring state
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
|
base.OnManagedStart();
|
||||||
ItemManager.Instance?.RegisterPickup(this);
|
ItemManager.Instance?.RegisterPickup(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
// Unregister from ItemManager
|
// Unregister from ItemManager
|
||||||
ItemManager.Instance?.UnregisterPickup(this);
|
ItemManager.Instance?.UnregisterPickup(this);
|
||||||
}
|
}
|
||||||
@@ -166,7 +165,7 @@ namespace Interactions
|
|||||||
PickupSaveData data = JsonUtility.FromJson<PickupSaveData>(serializedData);
|
PickupSaveData data = JsonUtility.FromJson<PickupSaveData>(serializedData);
|
||||||
if (data == null)
|
if (data == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[Pickup] Failed to deserialize save data for {gameObject.name}");
|
Logging.Warning($"[Pickup] Failed to deserialize save data for {gameObject.name}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +199,7 @@ namespace Interactions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[Pickup] Could not find slot with SaveId: {data.slotSaveId}");
|
Logging.Warning($"[Pickup] Could not find slot with SaveId: {data.slotSaveId}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using UnityEngine;
|
using Core;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Interactions
|
namespace Interactions
|
||||||
{
|
{
|
||||||
@@ -23,7 +24,7 @@ namespace Interactions
|
|||||||
|
|
||||||
#region Save/Load Lifecycle Hooks
|
#region Save/Load Lifecycle Hooks
|
||||||
|
|
||||||
protected override string OnSceneSaveRequested()
|
internal override string OnSceneSaveRequested()
|
||||||
{
|
{
|
||||||
object stateData = GetSerializableState();
|
object stateData = GetSerializableState();
|
||||||
if (stateData == null)
|
if (stateData == null)
|
||||||
@@ -34,11 +35,11 @@ namespace Interactions
|
|||||||
return JsonUtility.ToJson(stateData);
|
return JsonUtility.ToJson(stateData);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneRestoreRequested(string serializedData)
|
internal override void OnSceneRestoreRequested(string serializedData)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(serializedData))
|
if (string.IsNullOrEmpty(serializedData))
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[SaveableInteractable] Empty save data for {SaveId}");
|
Logging.Warning($"[SaveableInteractable] Empty save data for {SaveId}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,17 +86,17 @@ namespace Interactions
|
|||||||
[ContextMenu("Log Save ID")]
|
[ContextMenu("Log Save ID")]
|
||||||
private void LogSaveId()
|
private void LogSaveId()
|
||||||
{
|
{
|
||||||
Debug.Log($"Save ID: {SaveId}");
|
Logging.Debug($"Save ID: {SaveId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
[ContextMenu("Test Serialize/Deserialize")]
|
[ContextMenu("Test Serialize/Deserialize")]
|
||||||
private void TestSerializeDeserialize()
|
private void TestSerializeDeserialize()
|
||||||
{
|
{
|
||||||
string serialized = OnSceneSaveRequested();
|
string serialized = OnSceneSaveRequested();
|
||||||
Debug.Log($"Serialized state: {serialized}");
|
Logging.Debug($"Serialized state: {serialized}");
|
||||||
|
|
||||||
OnSceneRestoreRequested(serialized);
|
OnSceneRestoreRequested(serialized);
|
||||||
Debug.Log("Deserialization test complete");
|
Logging.Debug("Deserialization test complete");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ namespace Levels
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unity Awake callback. Sets up icon, interactable, and event handlers.
|
/// Unity Awake callback. Sets up icon, interactable, and event handlers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake();
|
base.OnManagedAwake();
|
||||||
|
|
||||||
Debug.Log($"[LevelSwitch] Awake called for {gameObject.name} in scene {gameObject.scene.name}");
|
Logging.Debug($"[LevelSwitch] Awake called for {gameObject.name} in scene {gameObject.scene.name}");
|
||||||
|
|
||||||
if (_iconRenderer == null)
|
if (_iconRenderer == null)
|
||||||
_iconRenderer = GetComponent<SpriteRenderer>();
|
_iconRenderer = GetComponent<SpriteRenderer>();
|
||||||
@@ -36,14 +36,14 @@ namespace Levels
|
|||||||
ApplySwitchData();
|
ApplySwitchData();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
Debug.Log($"[LevelSwitch] OnManagedAwake called for {gameObject.name}");
|
Logging.Debug($"[LevelSwitch] OnManagedStart called for {gameObject.name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneReady()
|
internal override void OnSceneReady()
|
||||||
{
|
{
|
||||||
Debug.Log($"[LevelSwitch] OnSceneReady called for {gameObject.name}");
|
Logging.Debug($"[LevelSwitch] OnSceneReady called for {gameObject.name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
@@ -79,7 +79,7 @@ namespace Levels
|
|||||||
{
|
{
|
||||||
if (switchData == null || string.IsNullOrEmpty(switchData.targetLevelSceneName))
|
if (switchData == null || string.IsNullOrEmpty(switchData.targetLevelSceneName))
|
||||||
{
|
{
|
||||||
Debug.LogWarning("LevelSwitch has no valid switchData!");
|
Logging.Warning("LevelSwitch has no valid switchData!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,21 +35,16 @@ namespace Levels
|
|||||||
[SerializeField] private bool startUnlocked = false;
|
[SerializeField] private bool startUnlocked = false;
|
||||||
|
|
||||||
private SpriteRenderer iconRenderer;
|
private SpriteRenderer iconRenderer;
|
||||||
|
|
||||||
// Settings reference
|
|
||||||
private IInteractionSettings interactionSettings;
|
private IInteractionSettings interactionSettings;
|
||||||
|
|
||||||
private bool switchActive = true;
|
|
||||||
private bool isUnlocked;
|
private bool isUnlocked;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unity Awake callback. Sets up icon, interactable, and event handlers.
|
/// Unity Awake callback. Sets up icon, interactable, and event handlers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake();
|
base.OnManagedAwake();
|
||||||
|
|
||||||
switchActive = true;
|
|
||||||
if (iconRenderer == null)
|
if (iconRenderer == null)
|
||||||
iconRenderer = GetComponent<SpriteRenderer>();
|
iconRenderer = GetComponent<SpriteRenderer>();
|
||||||
|
|
||||||
@@ -64,10 +59,9 @@ namespace Levels
|
|||||||
ApplySwitchData();
|
ApplySwitchData();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
base.OnManagedAwake();
|
base.OnManagedStart();
|
||||||
|
|
||||||
// If startUnlocked is true, always start active
|
// If startUnlocked is true, always start active
|
||||||
if (startUnlocked)
|
if (startUnlocked)
|
||||||
{
|
{
|
||||||
@@ -86,10 +80,8 @@ namespace Levels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
if (PuzzleManager.Instance != null)
|
if (PuzzleManager.Instance != null)
|
||||||
{
|
{
|
||||||
PuzzleManager.Instance.OnAllPuzzlesComplete -= HandleAllPuzzlesComplete;
|
PuzzleManager.Instance.OnAllPuzzlesComplete -= HandleAllPuzzlesComplete;
|
||||||
@@ -144,15 +136,7 @@ namespace Levels
|
|||||||
{
|
{
|
||||||
return base.CanBeClicked() && isUnlocked;
|
return base.CanBeClicked() && isUnlocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Setup: Prevent re-entry while interaction is in progress.
|
|
||||||
/// </summary>
|
|
||||||
protected override void OnInteractionStarted()
|
|
||||||
{
|
|
||||||
switchActive = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Main interaction logic: Spawn menu and switch input mode.
|
/// Main interaction logic: Spawn menu and switch input mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -160,7 +144,7 @@ namespace Levels
|
|||||||
{
|
{
|
||||||
if (switchData == null || string.IsNullOrEmpty(switchData.targetLevelSceneName))
|
if (switchData == null || string.IsNullOrEmpty(switchData.targetLevelSceneName))
|
||||||
{
|
{
|
||||||
Debug.LogWarning("MinigameSwitch has no valid switchData!");
|
Logging.Warning("MinigameSwitch has no valid switchData!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +187,7 @@ namespace Levels
|
|||||||
|
|
||||||
private void OnMenuCancel()
|
private void OnMenuCancel()
|
||||||
{
|
{
|
||||||
switchActive = true; // Allow interaction again if cancelled
|
|
||||||
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
|
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +215,7 @@ namespace Levels
|
|||||||
MinigameSwitchSaveData data = JsonUtility.FromJson<MinigameSwitchSaveData>(serializedData);
|
MinigameSwitchSaveData data = JsonUtility.FromJson<MinigameSwitchSaveData>(serializedData);
|
||||||
if (data == null)
|
if (data == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[MinigameSwitch] Failed to deserialize save data for {gameObject.name}");
|
Logging.Warning($"[MinigameSwitch] Failed to deserialize save data for {gameObject.name}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -104,13 +104,10 @@ namespace Minigames.DivingForPictures
|
|||||||
|
|
||||||
public static DivingGameManager Instance => _instance;
|
public static DivingGameManager Instance => _instance;
|
||||||
|
|
||||||
public override int ManagedAwakePriority => 190;
|
|
||||||
public override bool AutoRegisterPausable => true; // Automatic GameManager registration
|
public override bool AutoRegisterPausable => true; // Automatic GameManager registration
|
||||||
|
|
||||||
protected override void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake();
|
|
||||||
|
|
||||||
if (_instance == null)
|
if (_instance == null)
|
||||||
{
|
{
|
||||||
_instance = this;
|
_instance = this;
|
||||||
@@ -121,7 +118,7 @@ namespace Minigames.DivingForPictures
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
_settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
|
_settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
|
||||||
_currentSpawnProbability = _settings?.BaseSpawnProbability ?? 0.2f;
|
_currentSpawnProbability = _settings?.BaseSpawnProbability ?? 0.2f;
|
||||||
@@ -132,7 +129,7 @@ namespace Minigames.DivingForPictures
|
|||||||
Logging.Debug("[DivingGameManager] Initialized");
|
Logging.Debug("[DivingGameManager] Initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneReady()
|
internal override void OnSceneReady()
|
||||||
{
|
{
|
||||||
InitializeGame();
|
InitializeGame();
|
||||||
|
|
||||||
@@ -164,10 +161,8 @@ namespace Minigames.DivingForPictures
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy(); // Handles auto-unregister from GameManager
|
|
||||||
|
|
||||||
// Unsubscribe from events when the manager is destroyed
|
// Unsubscribe from events when the manager is destroyed
|
||||||
PlayerCollisionBehavior.OnDamageTaken -= OnPlayerDamageTaken;
|
PlayerCollisionBehavior.OnDamageTaken -= OnPlayerDamageTaken;
|
||||||
OnMonsterSpawned -= DoMonsterSpawned;
|
OnMonsterSpawned -= DoMonsterSpawned;
|
||||||
|
|||||||
@@ -106,9 +106,7 @@ public class FollowerController : ManagedBehaviour
|
|||||||
private bool _hasRestoredHeldItem; // Track if held item restoration completed
|
private bool _hasRestoredHeldItem; // Track if held item restoration completed
|
||||||
private string _expectedHeldItemSaveId; // Expected saveId during restoration
|
private string _expectedHeldItemSaveId; // Expected saveId during restoration
|
||||||
|
|
||||||
public override int ManagedAwakePriority => 110; // Follower after player
|
internal override void OnManagedStart()
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
|
||||||
{
|
{
|
||||||
_aiPath = GetComponent<AIPath>();
|
_aiPath = GetComponent<AIPath>();
|
||||||
// Find art prefab and animator
|
// Find art prefab and animator
|
||||||
@@ -129,7 +127,7 @@ public class FollowerController : ManagedBehaviour
|
|||||||
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
|
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneReady()
|
internal override void OnSceneReady()
|
||||||
{
|
{
|
||||||
// Find player reference when scene is ready (called for every scene load)
|
// Find player reference when scene is ready (called for every scene load)
|
||||||
FindPlayerReference();
|
FindPlayerReference();
|
||||||
@@ -727,7 +725,7 @@ public class FollowerController : ManagedBehaviour
|
|||||||
|
|
||||||
#region Save/Load Lifecycle Hooks
|
#region Save/Load Lifecycle Hooks
|
||||||
|
|
||||||
protected override string OnSceneSaveRequested()
|
internal override string OnSceneSaveRequested()
|
||||||
{
|
{
|
||||||
var saveData = new FollowerSaveData
|
var saveData = new FollowerSaveData
|
||||||
{
|
{
|
||||||
@@ -754,7 +752,7 @@ public class FollowerController : ManagedBehaviour
|
|||||||
return JsonUtility.ToJson(saveData);
|
return JsonUtility.ToJson(saveData);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneRestoreRequested(string serializedData)
|
internal override void OnSceneRestoreRequested(string serializedData)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(serializedData))
|
if (string.IsNullOrEmpty(serializedData))
|
||||||
{
|
{
|
||||||
@@ -914,7 +912,7 @@ public class FollowerController : ManagedBehaviour
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static FollowerController FindInstance()
|
public static FollowerController FindInstance()
|
||||||
{
|
{
|
||||||
return FindObjectOfType<FollowerController>();
|
return FindFirstObjectByType<FollowerController>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Save/Load Lifecycle Hooks
|
#endregion Save/Load Lifecycle Hooks
|
||||||
|
|||||||
@@ -1,19 +1,74 @@
|
|||||||
|
using System;
|
||||||
|
using Core;
|
||||||
|
using Core.Lifecycle;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class BirdGameStats : MonoBehaviour
|
namespace PuzzleS
|
||||||
{
|
{
|
||||||
public int birdsFoundInLevel;
|
/// <summary>
|
||||||
|
/// Tracks bird discovery progress in the bird finding minigame.
|
||||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
/// Saves scene-specific progress using the ManagedBehaviour lifecycle system.
|
||||||
void Start()
|
/// </summary>
|
||||||
|
public class BirdGameStats : ManagedBehaviour
|
||||||
{
|
{
|
||||||
|
public int birdsFoundInLevel;
|
||||||
|
|
||||||
|
// Save system configuration
|
||||||
|
public override bool AutoRegisterForSave => true;
|
||||||
|
|
||||||
|
internal override void OnManagedStart()
|
||||||
|
{
|
||||||
|
// Initialize after all managers are ready
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BirdFound()
|
||||||
|
{
|
||||||
|
birdsFoundInLevel += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Save/Load Lifecycle Hooks
|
||||||
|
|
||||||
|
internal override string OnSceneSaveRequested()
|
||||||
|
{
|
||||||
|
// Save scene-specific progress
|
||||||
|
var state = new BirdGameState
|
||||||
|
{
|
||||||
|
birdsFoundInLevel = this.birdsFoundInLevel
|
||||||
|
};
|
||||||
|
return JsonUtility.ToJson(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void OnSceneRestoreRequested(string serializedData)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(serializedData))
|
||||||
|
{
|
||||||
|
// No saved data, keep default values
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var state = JsonUtility.FromJson<BirdGameState>(serializedData);
|
||||||
|
if (state != null)
|
||||||
|
{
|
||||||
|
birdsFoundInLevel = state.birdsFoundInLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.Warning($"[BirdGameStats] Failed to restore state: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BirdFound()
|
/// <summary>
|
||||||
|
/// Serializable state for bird game progress
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class BirdGameState
|
||||||
{
|
{
|
||||||
birdsFoundInLevel += 1;
|
public int birdsFoundInLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace PuzzleS
|
|||||||
// Enum for tracking proximity state (simplified to just Close and Far)
|
// Enum for tracking proximity state (simplified to just Close and Far)
|
||||||
public enum ProximityState { Close, Far }
|
public enum ProximityState { Close, Far }
|
||||||
|
|
||||||
protected override void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
_interactable = GetComponent<InteractableBase>();
|
_interactable = GetComponent<InteractableBase>();
|
||||||
|
|
||||||
@@ -56,14 +56,10 @@ namespace PuzzleS
|
|||||||
Logging.Warning($"[Puzzles] Indicator prefab for {stepData?.stepId} does not implement IPuzzlePrompt");
|
Logging.Warning($"[Puzzles] Indicator prefab for {stepData?.stepId} does not implement IPuzzlePrompt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Awake();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
base.OnManagedAwake();
|
|
||||||
|
|
||||||
// Register with PuzzleManager - safe to access .Instance here
|
// Register with PuzzleManager - safe to access .Instance here
|
||||||
if (stepData != null && PuzzleManager.Instance != null)
|
if (stepData != null && PuzzleManager.Instance != null)
|
||||||
{
|
{
|
||||||
@@ -87,10 +83,8 @@ namespace PuzzleS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
if (PuzzleManager.Instance != null && stepData != null)
|
if (PuzzleManager.Instance != null && stepData != null)
|
||||||
{
|
{
|
||||||
PuzzleManager.Instance.UnregisterStepBehaviour(this);
|
PuzzleManager.Instance.UnregisterStepBehaviour(this);
|
||||||
|
|||||||
@@ -93,18 +93,14 @@ namespace PuzzleS
|
|||||||
|
|
||||||
// Track pending unlocks for steps that were unlocked before their behavior registered
|
// Track pending unlocks for steps that were unlocked before their behavior registered
|
||||||
private HashSet<string> _pendingUnlocks = new HashSet<string>();
|
private HashSet<string> _pendingUnlocks = new HashSet<string>();
|
||||||
|
|
||||||
public override int ManagedAwakePriority => 80; // Puzzle systems
|
|
||||||
|
|
||||||
private new void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
// Set instance immediately (early initialization)
|
||||||
|
|
||||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
// Initialize settings reference
|
// Initialize settings reference
|
||||||
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
|
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
|
||||||
@@ -140,10 +136,8 @@ namespace PuzzleS
|
|||||||
LoadPuzzlesForScene(sceneName);
|
LoadPuzzlesForScene(sceneName);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
// Unsubscribe from SceneManagerService events
|
// Unsubscribe from SceneManagerService events
|
||||||
if (SceneManagerService.Instance != null)
|
if (SceneManagerService.Instance != null)
|
||||||
{
|
{
|
||||||
@@ -591,7 +585,7 @@ namespace PuzzleS
|
|||||||
|
|
||||||
#region Save/Load Lifecycle Hooks
|
#region Save/Load Lifecycle Hooks
|
||||||
|
|
||||||
protected override string OnSceneSaveRequested()
|
internal override string OnSceneSaveRequested()
|
||||||
{
|
{
|
||||||
if (_currentLevelData == null)
|
if (_currentLevelData == null)
|
||||||
{
|
{
|
||||||
@@ -611,9 +605,9 @@ namespace PuzzleS
|
|||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneRestoreRequested(string data)
|
internal override void OnSceneRestoreRequested(string data)
|
||||||
{
|
{
|
||||||
Debug.Log("[XAXA] PuzzleManager loading with data: " + data);
|
Logging.Debug("[XAXA] PuzzleManager loading with data: " + data);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(data) || data == "{}")
|
if (string.IsNullOrEmpty(data) || data == "{}")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ using System;
|
|||||||
using System.Diagnostics.Tracing;
|
using System.Diagnostics.Tracing;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Audio;
|
using UnityEngine.Audio;
|
||||||
|
using Core;
|
||||||
|
using Core.Lifecycle;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// We automatically add the AudioSource component here so we can control it. Do not add it manually!
|
/// We automatically add the AudioSource component here so we can control it. Do not add it manually!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RequireComponent(typeof(AudioSource))]
|
[RequireComponent(typeof(AudioSource))]
|
||||||
public class AppleAudioSource : MonoBehaviour
|
public class AppleAudioSource : ManagedBehaviour
|
||||||
{
|
{
|
||||||
public enum AudioSourceType{CriticalVO,VO,Ambience,SFX,Music}
|
public enum AudioSourceType{CriticalVO,VO,Ambience,SFX,Music}
|
||||||
public AudioSourceType audioSourceType;
|
public AudioSourceType audioSourceType;
|
||||||
@@ -17,10 +19,14 @@ public class AppleAudioSource : MonoBehaviour
|
|||||||
[HideInInspector ] public int clipPriority;
|
[HideInInspector ] public int clipPriority;
|
||||||
public int sourcePriority;
|
public int sourcePriority;
|
||||||
|
|
||||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
|
||||||
void OnEnable()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
audioSource = GetComponent<AudioSource>();
|
audioSource = GetComponent<AudioSource>();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void OnManagedStart()
|
||||||
|
{
|
||||||
AudioManager.Instance.RegisterNewAudioSource(this);
|
AudioManager.Instance.RegisterNewAudioSource(this);
|
||||||
_audioMixer = AudioManager.Instance.audioMixer;
|
_audioMixer = AudioManager.Instance.audioMixer;
|
||||||
InitializeAudioSource();
|
InitializeAudioSource();
|
||||||
@@ -54,6 +60,10 @@ public class AppleAudioSource : MonoBehaviour
|
|||||||
|
|
||||||
public void Play(int requestedClipPriority)
|
public void Play(int requestedClipPriority)
|
||||||
{
|
{
|
||||||
|
if (audioSource == null)
|
||||||
|
{
|
||||||
|
audioSource = GetComponent<AudioSource>();
|
||||||
|
}
|
||||||
clipPriority = requestedClipPriority;
|
clipPriority = requestedClipPriority;
|
||||||
if (audioSourceType == AudioSourceType.CriticalVO || audioSourceType == AudioSourceType.VO)
|
if (audioSourceType == AudioSourceType.CriticalVO || audioSourceType == AudioSourceType.VO)
|
||||||
{
|
{
|
||||||
@@ -63,7 +73,7 @@ public class AppleAudioSource : MonoBehaviour
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Log("[AUDIOMANAGER] AppleAudioSource " + name + " was suppressed because something more important is playing");
|
Logging.Debug("[AUDIOMANAGER] AppleAudioSource " + name + " was suppressed because something more important is playing");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using AppleHills.Core.Interfaces;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using AudioSourceEvents;
|
using AudioSourceEvents;
|
||||||
using System;
|
using System;
|
||||||
|
using Core;
|
||||||
using Core.Lifecycle;
|
using Core.Lifecycle;
|
||||||
|
|
||||||
public class AudioManager : ManagedBehaviour, IPausable
|
public class AudioManager : ManagedBehaviour, IPausable
|
||||||
@@ -39,19 +40,15 @@ public class AudioManager : ManagedBehaviour, IPausable
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static AudioManager Instance => _instance;
|
public static AudioManager Instance => _instance;
|
||||||
|
|
||||||
// ManagedBehaviour configuration
|
|
||||||
public override int ManagedAwakePriority => 30; // Audio infrastructure
|
|
||||||
public override bool AutoRegisterPausable => true; // Auto-register as IPausable
|
public override bool AutoRegisterPausable => true; // Auto-register as IPausable
|
||||||
|
|
||||||
private new void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
// Set instance immediately (early initialization)
|
||||||
|
|
||||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
// Initialize lists if they were not set in inspector
|
// Initialize lists if they were not set in inspector
|
||||||
criticalVOSources = criticalVOSources ?? new List<AppleAudioSource>();
|
criticalVOSources = criticalVOSources ?? new List<AppleAudioSource>();
|
||||||
@@ -71,16 +68,14 @@ public class AudioManager : ManagedBehaviour, IPausable
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[AudioManager] QuickAccess.Instance is null during OnManagedAwake. Some audio references may remain unset.");
|
Logging.Warning("[AudioManager] QuickAccess.Instance is null during OnManagedStart. Some audio references may remain unset.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diagnostic
|
// Diagnostic
|
||||||
foreach (AppleAudioSource _audioSource in criticalVOSources)
|
foreach (AppleAudioSource _audioSource in criticalVOSources)
|
||||||
{
|
{
|
||||||
Debug.Log("Found source: " + _audioSource.name);
|
Logging.Debug("Found source: " + _audioSource.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log("[AudioManager] OnManagedAwake completed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAudioPauseBehavior(PauseBehavior newPauseBehavior)
|
public void SetAudioPauseBehavior(PauseBehavior newPauseBehavior)
|
||||||
@@ -104,15 +99,15 @@ public class AudioManager : ManagedBehaviour, IPausable
|
|||||||
|
|
||||||
public LevelAudioObject GetCurrentLevelAudioObject()
|
public LevelAudioObject GetCurrentLevelAudioObject()
|
||||||
{
|
{
|
||||||
Debug.Log("Audio objects: " + FindObjectsByType<LevelAudioObject>(FindObjectsInactive.Include, FindObjectsSortMode.None).Length);
|
Logging.Debug("Audio objects: " + FindObjectsByType<LevelAudioObject>(FindObjectsInactive.Include, FindObjectsSortMode.None).Length);
|
||||||
if (FindObjectsByType<LevelAudioObject>(FindObjectsInactive.Include, FindObjectsSortMode.None).Length > 1)
|
if (FindObjectsByType<LevelAudioObject>(FindObjectsInactive.Include, FindObjectsSortMode.None).Length > 1)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("Warning! More than one LevelAudioObject in the level! Using the first one found");
|
Logging.Warning("Warning! More than one LevelAudioObject in the level! Using the first one found");
|
||||||
return FindObjectsByType<LevelAudioObject>(FindObjectsInactive.Include, FindObjectsSortMode.None)[0];
|
return FindObjectsByType<LevelAudioObject>(FindObjectsInactive.Include, FindObjectsSortMode.None)[0];
|
||||||
}
|
}
|
||||||
if (FindObjectsByType<LevelAudioObject>(FindObjectsInactive.Include, FindObjectsSortMode.None).Length == 0)
|
if (FindObjectsByType<LevelAudioObject>(FindObjectsInactive.Include, FindObjectsSortMode.None).Length == 0)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("Error! No LevelAudioObject found, AudioManager might not function properly!");
|
Logging.Warning("Error! No LevelAudioObject found, AudioManager might not function properly!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -158,12 +153,10 @@ public class AudioManager : ManagedBehaviour, IPausable
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool RequestPlayVO(AppleAudioSource requestedAudioSource)
|
public bool RequestPlayVO(AppleAudioSource requestedAudioSource)
|
||||||
{
|
{
|
||||||
//Debug.Log($"[AUDIOMANAGER] CurrentVO source prio: {currentlyPlayingVO.sourcePriority}, clip prio: {currentlyPlayingVO.clipPriority} requested VO prio: {requestedAudioSource.sourcePriority}, clip prio: {clipPriority}");
|
|
||||||
// If nothing is playing, let the requested audio source play
|
// If nothing is playing, let the requested audio source play
|
||||||
if (currentlyPlayingVO == null)
|
if (currentlyPlayingVO == null)
|
||||||
{
|
{
|
||||||
SetupNewAudioSource(requestedAudioSource);
|
SetupNewAudioSource(requestedAudioSource);
|
||||||
Debug.Log($"[AUDIOMANAGER] Playing {currentlyPlayingVO.name} as nothing is currently playing.");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +170,6 @@ public class AudioManager : ManagedBehaviour, IPausable
|
|||||||
{
|
{
|
||||||
InterruptAudioSource(requestedAudioSource);
|
InterruptAudioSource(requestedAudioSource);
|
||||||
SetupNewAudioSource(requestedAudioSource);
|
SetupNewAudioSource(requestedAudioSource);
|
||||||
Debug.Log($"[AUDIOMANAGER] {currentlyPlayingVO.name} is the same as {requestedAudioSource.name}. Triggering it again.");
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -187,7 +179,6 @@ public class AudioManager : ManagedBehaviour, IPausable
|
|||||||
|
|
||||||
InterruptAudioSource(requestedAudioSource);
|
InterruptAudioSource(requestedAudioSource);
|
||||||
SetupNewAudioSource(requestedAudioSource);
|
SetupNewAudioSource(requestedAudioSource);
|
||||||
Debug.Log($"[AUDIOMANAGER] {currentlyPlayingVO.name} is not critical. Playing {requestedAudioSource.name} instead because it is critical.");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// If the requested audio source has the same priority as currently playing source, check the priority of the requested clip
|
// If the requested audio source has the same priority as currently playing source, check the priority of the requested clip
|
||||||
@@ -197,8 +188,6 @@ public class AudioManager : ManagedBehaviour, IPausable
|
|||||||
{
|
{
|
||||||
InterruptAudioSource(requestedAudioSource);
|
InterruptAudioSource(requestedAudioSource);
|
||||||
SetupNewAudioSource(requestedAudioSource);
|
SetupNewAudioSource(requestedAudioSource);
|
||||||
Debug.Log($"[AUDIOMANAGER] Interrupted {currentlyPlayingVO.name} because it has same priority as {requestedAudioSource.name} but the requested clip has higher priority");
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -210,7 +199,6 @@ public class AudioManager : ManagedBehaviour, IPausable
|
|||||||
if (currentlyPlayingVO.audioSourceType == AppleAudioSource.AudioSourceType.CriticalVO && currentlyPlayingVO.sourcePriority > requestedAudioSource.sourcePriority)
|
if (currentlyPlayingVO.audioSourceType == AppleAudioSource.AudioSourceType.CriticalVO && currentlyPlayingVO.sourcePriority > requestedAudioSource.sourcePriority)
|
||||||
{
|
{
|
||||||
currentlyPlayingVO.InterruptAudio(requestedAudioSource.name);
|
currentlyPlayingVO.InterruptAudio(requestedAudioSource.name);
|
||||||
Debug.Log($"[AUDIOMANAGER] Interrupted {currentlyPlayingVO.name} because {requestedAudioSource.name} has higher priority");
|
|
||||||
InterruptAudioSource(requestedAudioSource);
|
InterruptAudioSource(requestedAudioSource);
|
||||||
SetupNewAudioSource(requestedAudioSource);
|
SetupNewAudioSource(requestedAudioSource);
|
||||||
return true;
|
return true;
|
||||||
@@ -218,7 +206,6 @@ public class AudioManager : ManagedBehaviour, IPausable
|
|||||||
// If the requested audio source didn't clear any of the above cases, tell it to get rekt.
|
// If the requested audio source didn't clear any of the above cases, tell it to get rekt.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Log($"[AUDIOMANAGER] {currentlyPlayingVO.name} is still playing. {requestedAudioSource.name} has lower priority");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,7 +219,6 @@ public class AudioManager : ManagedBehaviour, IPausable
|
|||||||
{
|
{
|
||||||
if (audioSource.audioSource.resource == null)
|
if (audioSource.audioSource.resource == null)
|
||||||
{
|
{
|
||||||
Debug.Log($"[AUDIOMANAGER] Faled to setup {audioSource.name}. Invalid resource");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -281,7 +267,15 @@ public class AudioManager : ManagedBehaviour, IPausable
|
|||||||
{
|
{
|
||||||
foreach (AppleAudioSource source in criticalVOSources)
|
foreach (AppleAudioSource source in criticalVOSources)
|
||||||
{
|
{
|
||||||
source.InterruptAudio("GlobalInterrupt");
|
if (source == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
source.InterruptAudio("GlobalInterrupt");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
foreach (AppleAudioSource source in VOSources)
|
foreach (AppleAudioSource source in VOSources)
|
||||||
|
|||||||
@@ -4,8 +4,11 @@ using System;
|
|||||||
using System.Diagnostics.Tracing;
|
using System.Diagnostics.Tracing;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Audio;
|
using UnityEngine.Audio;
|
||||||
|
using Core;
|
||||||
|
using Core.Lifecycle;
|
||||||
|
using PuzzleS;
|
||||||
|
|
||||||
public class BushAudioController : MonoBehaviour
|
public class BushAudioController : ManagedBehaviour
|
||||||
{
|
{
|
||||||
private IAudioEventSource _eventSource;
|
private IAudioEventSource _eventSource;
|
||||||
public AppleAudioSource VOPlayer;
|
public AppleAudioSource VOPlayer;
|
||||||
@@ -20,7 +23,7 @@ public class BushAudioController : MonoBehaviour
|
|||||||
|
|
||||||
|
|
||||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||||
void Start()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
_eventSource = VOPlayer.audioSource.RequestEventHandlers();
|
_eventSource = VOPlayer.audioSource.RequestEventHandlers();
|
||||||
_eventSource.AudioStopped += PlayBirdCounter;
|
_eventSource.AudioStopped += PlayBirdCounter;
|
||||||
@@ -48,9 +51,9 @@ public class BushAudioController : MonoBehaviour
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnDisable()
|
//public void OnDisable()
|
||||||
{
|
//{
|
||||||
// Unsubscribe from events when disabled
|
// // Unsubscribe from events when disabled
|
||||||
_eventSource.AudioStopped -= PlayBirdCounter;
|
// _eventSource.AudioStopped -= PlayBirdCounter;
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,81 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Audio;
|
using UnityEngine.Audio;
|
||||||
using System;
|
using System;
|
||||||
|
using Core;
|
||||||
|
using Core.Lifecycle;
|
||||||
|
|
||||||
public class LevelAudioObject : MonoBehaviour
|
[Serializable]
|
||||||
|
public class LevelAudioObjectSaveData
|
||||||
{
|
{
|
||||||
|
public bool hasPlayed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LevelAudioObject : ManagedBehaviour
|
||||||
|
{
|
||||||
|
[Header("Audio Settings")]
|
||||||
public AppleAudioSource narratorAudioSource;
|
public AppleAudioSource narratorAudioSource;
|
||||||
public AudioResource firstNarration;
|
public AudioResource firstNarration;
|
||||||
|
|
||||||
|
[Header("Playback Settings")]
|
||||||
|
[Tooltip("If true, the audio will only play once and never again after being played")]
|
||||||
|
public bool isOneTime;
|
||||||
|
|
||||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
private bool _hasPlayed;
|
||||||
void Start()
|
|
||||||
|
#region ManagedBehaviour Overrides
|
||||||
|
|
||||||
|
public override bool AutoRegisterForSave => isOneTime; // Only save if one-time audio
|
||||||
|
|
||||||
|
internal override string OnSceneSaveRequested()
|
||||||
{
|
{
|
||||||
PlayNarrationAudio();
|
if (!isOneTime)
|
||||||
|
return null; // No need to save if not one-time
|
||||||
|
|
||||||
|
LevelAudioObjectSaveData saveData = new LevelAudioObjectSaveData
|
||||||
|
{
|
||||||
|
hasPlayed = _hasPlayed
|
||||||
|
};
|
||||||
|
|
||||||
|
return JsonUtility.ToJson(saveData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayNarrationAudio()
|
internal override void OnSceneRestoreRequested(string serializedData)
|
||||||
{
|
{
|
||||||
|
if (!isOneTime || string.IsNullOrEmpty(serializedData))
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LevelAudioObjectSaveData saveData = JsonUtility.FromJson<LevelAudioObjectSaveData>(serializedData);
|
||||||
|
_hasPlayed = saveData.hasPlayed;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logging.Warning($"[LevelAudioObject] Failed to restore audio state: {e.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void OnSceneRestoreCompleted()
|
||||||
|
{
|
||||||
|
if (isOneTime && !_hasPlayed)
|
||||||
|
{
|
||||||
|
PlayNarrationAudio();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void PlayNarrationAudio()
|
||||||
|
{
|
||||||
|
if (narratorAudioSource == null || firstNarration == null)
|
||||||
|
{
|
||||||
|
Logging.Warning($"[LevelAudioObject] Missing audio source or narration resource on {gameObject.name}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
narratorAudioSource.audioSource.resource = firstNarration;
|
narratorAudioSource.audioSource.resource = firstNarration;
|
||||||
narratorAudioSource.Play(0);
|
narratorAudioSource.Play(0);
|
||||||
|
|
||||||
|
_hasPlayed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Core;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class ProximitySoundReaction : MonoBehaviour
|
public class ProximitySoundReaction : MonoBehaviour
|
||||||
@@ -12,13 +13,13 @@ public class ProximitySoundReaction : MonoBehaviour
|
|||||||
|
|
||||||
private void OnCollisionEnter2D(Collision2D collision)
|
private void OnCollisionEnter2D(Collision2D collision)
|
||||||
{
|
{
|
||||||
Debug.Log("overlap!");
|
Logging.Debug("overlap!");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTriggerEnter2D(Collider2D collision)
|
private void OnTriggerEnter2D(Collider2D collision)
|
||||||
{
|
{
|
||||||
Debug.Log("Wolter triggered!");
|
Logging.Debug("Wolter triggered!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
using Core;
|
using Core;
|
||||||
|
using Core.Lifecycle;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Audio;
|
using UnityEngine.Audio;
|
||||||
|
|
||||||
public class PulverAudioController : MonoBehaviour
|
public class PulverAudioController : ManagedBehaviour
|
||||||
{
|
{
|
||||||
private AppleAudioSource audioSource;
|
public AppleAudioSource audioSource;
|
||||||
public AudioResource combineAudio;
|
public AudioResource combineAudio;
|
||||||
private FollowerController followerController;
|
private FollowerController followerController;
|
||||||
public ItemManager itemManager;
|
public ItemManager itemManager;
|
||||||
|
|
||||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
internal override void OnManagedStart()
|
||||||
void Start()
|
|
||||||
{
|
{
|
||||||
audioSource = GetComponent<AppleAudioSource>();
|
|
||||||
followerController = GetComponent<FollowerController>();
|
followerController = GetComponent<FollowerController>();
|
||||||
followerController.PulverIsCombining.AddListener(PulverIsCombining);
|
followerController.PulverIsCombining.AddListener(PulverIsCombining);
|
||||||
|
|
||||||
|
|||||||
@@ -1,89 +1,120 @@
|
|||||||
|
using System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
using SkiaSharp.Unity;
|
using SkiaSharp.Unity;
|
||||||
using Input;
|
using Input;
|
||||||
using AppleHills.Core;
|
using AppleHills.Core;
|
||||||
|
using UI.Core;
|
||||||
|
using Pixelplacement;
|
||||||
|
using Pixelplacement.TweenSystem;
|
||||||
using UI;
|
using UI;
|
||||||
using UnityEngine.Events;
|
|
||||||
|
|
||||||
public class AppSwitcher : MonoBehaviour
|
public class AppSwitcher : UIPage
|
||||||
{
|
{
|
||||||
|
public GameObject rainbowIn;
|
||||||
public TextAsset iconIdle;
|
public GameObject rainbowOut;
|
||||||
public TextAsset iconEstablish;
|
|
||||||
public TextAsset rainbowEstablish;
|
|
||||||
public TextAsset rainbowRemove;
|
|
||||||
public GameObject rainbow;
|
|
||||||
public GameObject icon;
|
|
||||||
public GameObject gameLayoutContainer;
|
public GameObject gameLayoutContainer;
|
||||||
public GameObject exitButton;
|
public GameObject exitButton;
|
||||||
|
public RectMask2D rectMask;
|
||||||
|
|
||||||
|
[Header("Slide Animation Settings")]
|
||||||
|
public float slideDuration = 0.5f;
|
||||||
|
|
||||||
|
private SkottiePlayerV2 rainbowInPlayer;
|
||||||
|
private SkottiePlayerV2 rainbowOutPlayer;
|
||||||
|
private TweenBase slideInTween;
|
||||||
|
private TweenBase slideOutTween;
|
||||||
|
|
||||||
private SkottiePlayerV2 iconPlayer;
|
internal override void OnManagedAwake()
|
||||||
private SkottiePlayerV2 rainbowPlayer;
|
|
||||||
private Animator animator;
|
|
||||||
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
{
|
||||||
iconPlayer = icon.GetComponentInChildren<SkottiePlayerV2>();
|
base.OnManagedAwake();
|
||||||
rainbowPlayer = rainbow.GetComponentInChildren<SkottiePlayerV2>();
|
|
||||||
animator = GetComponent<Animator>();
|
PageName = "AppSwitcher";
|
||||||
rainbow.SetActive(false);
|
rainbowInPlayer = rainbowIn.GetComponent<SkottiePlayerV2>();
|
||||||
|
rainbowOutPlayer = rainbowOut.GetComponent<SkottiePlayerV2>();
|
||||||
|
|
||||||
|
if (rectMask == null)
|
||||||
|
{
|
||||||
|
rectMask = GetComponent<RectMask2D>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initially hide both
|
||||||
|
rainbowIn.SetActive(true);
|
||||||
|
exitButton.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenAppSwitcher()
|
protected override void DoTransitionIn(Action onComplete)
|
||||||
{
|
{
|
||||||
PlayerHudManager.Instance.HideAllHudExcept(gameObject);
|
|
||||||
|
|
||||||
rainbow.SetActive(true);
|
|
||||||
//Activate players
|
|
||||||
rainbow.SetActive(true);
|
|
||||||
gameLayoutContainer.SetActive(true);
|
|
||||||
|
|
||||||
// Play establishing animations
|
|
||||||
rainbowPlayer.LoadAnimation(rainbowEstablish.text);
|
|
||||||
rainbowPlayer.PlayAnimation(false);
|
|
||||||
rainbowPlayer.loop = false;
|
|
||||||
gameLayoutContainer.SetActive(true);
|
|
||||||
animator.Play("GamesReveal");
|
|
||||||
|
|
||||||
// Show the exit button
|
|
||||||
exitButton.SetActive(true);
|
|
||||||
|
|
||||||
// Set input mode to UI
|
|
||||||
QuickAccess.Instance.PlayerController.InterruptMoveTo();
|
|
||||||
InputManager.Instance.SetInputMode(InputMode.UI);
|
InputManager.Instance.SetInputMode(InputMode.UI);
|
||||||
|
|
||||||
|
gameLayoutContainer.SetActive(true);
|
||||||
|
|
||||||
rainbowPlayer.OnAnimationFinished += AnimFinished;
|
// Hide rainbow out, show rainbow in
|
||||||
|
rainbowOut.SetActive(false);
|
||||||
|
|
||||||
|
// Play animation on rainbow in without resetting state
|
||||||
|
rainbowInPlayer.PlayAnimation(true);
|
||||||
|
|
||||||
|
// Slide in animation - tween padding.left from 1700 to 0
|
||||||
|
slideInTween = TweenPaddingLeft(1700f, 0f, Tween.EaseOut, () =>
|
||||||
|
{
|
||||||
|
onComplete?.Invoke();
|
||||||
|
rainbowOut.SetActive(true);
|
||||||
|
exitButton.SetActive(true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CloseAppSwitcher()
|
protected override void DoTransitionOut(Action onComplete)
|
||||||
{
|
{
|
||||||
rainbowPlayer.resetAfterFinished = true;
|
rainbowIn.SetActive(false);
|
||||||
rainbowPlayer.LoadAnimation(rainbowRemove.text);
|
|
||||||
rainbowPlayer.PlayAnimation(false);
|
// Play animation on rainbow out with resetting state
|
||||||
rainbowPlayer.loop = false;
|
rainbowOutPlayer.PlayAnimation(true);
|
||||||
animator.Play("GamesHide");
|
|
||||||
|
|
||||||
// Set input mode to game and ui
|
|
||||||
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
|
|
||||||
|
|
||||||
// Hide the exit button
|
// Hide the exit button
|
||||||
exitButton.SetActive(false);
|
exitButton.SetActive(false);
|
||||||
|
|
||||||
PlayerHudManager.Instance.ShowAllHud();
|
// Slide out animation - tween padding.left from 0 to 1700
|
||||||
|
slideOutTween = TweenPaddingLeft(0f, 1700f, Tween.EaseIn, () => {
|
||||||
|
gameLayoutContainer.SetActive(false);
|
||||||
|
rainbowIn.SetActive(true);
|
||||||
|
onComplete?.Invoke();
|
||||||
|
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GamesHiddenAnimationEvent()
|
|
||||||
{
|
|
||||||
rainbow.SetActive(false);
|
|
||||||
gameLayoutContainer.SetActive(false);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AnimFinished(string str)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tweens the left padding of the rectMask from startValue to endValue.
|
||||||
|
/// </summary>
|
||||||
|
private TweenBase TweenPaddingLeft(float startValue, float endValue, AnimationCurve easeCurve, Action onComplete)
|
||||||
|
{
|
||||||
|
// Set starting position
|
||||||
|
Vector4 startPadding = rectMask.padding;
|
||||||
|
startPadding.x = startValue;
|
||||||
|
rectMask.padding = startPadding;
|
||||||
|
|
||||||
|
return Tween.Value(
|
||||||
|
startValue,
|
||||||
|
endValue,
|
||||||
|
(value) => {
|
||||||
|
Vector4 padding = rectMask.padding;
|
||||||
|
padding.x = value;
|
||||||
|
rectMask.padding = padding;
|
||||||
|
},
|
||||||
|
slideDuration,
|
||||||
|
0f, // no delay
|
||||||
|
easeCurve,
|
||||||
|
Tween.LoopType.None,
|
||||||
|
null, // onStart
|
||||||
|
onComplete
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void OnManagedDestroy()
|
||||||
|
{
|
||||||
|
// Clean up tweens
|
||||||
|
slideInTween?.Stop();
|
||||||
|
slideOutTween?.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using AppleHills.Data.CardSystem;
|
using AppleHills.Data.CardSystem;
|
||||||
|
using Core;
|
||||||
using Pixelplacement;
|
using Pixelplacement;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
@@ -82,37 +83,37 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void OnPointerClick(PointerEventData eventData)
|
public void OnPointerClick(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-ALBUMCARD] OnPointerClick on {name}, _parentSlot={((_parentSlot != null) ? _parentSlot.name : "NULL")}, _isEnlarged={_isEnlarged}, position={eventData.position}");
|
Logging.Debug($"[CLICK-TRACE-ALBUMCARD] OnPointerClick on {name}, _parentSlot={((_parentSlot != null) ? _parentSlot.name : "NULL")}, _isEnlarged={_isEnlarged}, position={eventData.position}");
|
||||||
|
|
||||||
// During reveal flow (before placed in slot), forward clicks to parent FlippableCard
|
// During reveal flow (before placed in slot), forward clicks to parent FlippableCard
|
||||||
if (_parentSlot == null)
|
if (_parentSlot == null)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-ALBUMCARD] {name} - No parent slot, forwarding click to parent FlippableCard");
|
Logging.Debug($"[CLICK-TRACE-ALBUMCARD] {name} - No parent slot, forwarding click to parent FlippableCard");
|
||||||
|
|
||||||
// Find parent FlippableCard and forward the click
|
// Find parent FlippableCard and forward the click
|
||||||
FlippableCard parentFlippable = GetComponentInParent<FlippableCard>();
|
FlippableCard parentFlippable = GetComponentInParent<FlippableCard>();
|
||||||
if (parentFlippable != null)
|
if (parentFlippable != null)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-ALBUMCARD] {name} - Found parent FlippableCard, calling OnPointerClick");
|
Logging.Debug($"[CLICK-TRACE-ALBUMCARD] {name} - Found parent FlippableCard, calling OnPointerClick");
|
||||||
parentFlippable.OnPointerClick(eventData);
|
parentFlippable.OnPointerClick(eventData);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[CLICK-TRACE-ALBUMCARD] {name} - No parent FlippableCard found!");
|
Logging.Warning($"[CLICK-TRACE-ALBUMCARD] {name} - No parent FlippableCard found!");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[CLICK-TRACE-ALBUMCARD] {name} - Has parent slot, processing click");
|
Logging.Debug($"[CLICK-TRACE-ALBUMCARD] {name} - Has parent slot, processing click");
|
||||||
|
|
||||||
if (_isEnlarged)
|
if (_isEnlarged)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-ALBUMCARD] {name} - Is enlarged, requesting shrink");
|
Logging.Debug($"[CLICK-TRACE-ALBUMCARD] {name} - Is enlarged, requesting shrink");
|
||||||
OnShrinkRequested?.Invoke(this);
|
OnShrinkRequested?.Invoke(this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-ALBUMCARD] {name} - Is normal size, requesting enlarge");
|
Logging.Debug($"[CLICK-TRACE-ALBUMCARD] {name} - Is normal size, requesting enlarge");
|
||||||
OnEnlargeRequested?.Invoke(this);
|
OnEnlargeRequested?.Invoke(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ namespace UI.CardSystem
|
|||||||
[SerializeField] private BookCurlPro.BookPro book;
|
[SerializeField] private BookCurlPro.BookPro book;
|
||||||
|
|
||||||
[Header("Zone Navigation")]
|
[Header("Zone Navigation")]
|
||||||
[SerializeField] private BookTabButton[] zoneTabs; // All zone tab buttons
|
[SerializeField] private Transform tabContainer; // Container holding all BookTabButton children
|
||||||
|
|
||||||
|
private BookTabButton[] zoneTabs; // Discovered zone tab buttons
|
||||||
|
|
||||||
[Header("Album Card Reveal")]
|
[Header("Album Card Reveal")]
|
||||||
[SerializeField] private SlotContainer bottomRightSlots;
|
[SerializeField] private SlotContainer bottomRightSlots;
|
||||||
@@ -42,9 +44,10 @@ namespace UI.CardSystem
|
|||||||
private List<AlbumCardPlacementDraggable> _activeCards = new List<AlbumCardPlacementDraggable>();
|
private List<AlbumCardPlacementDraggable> _activeCards = new List<AlbumCardPlacementDraggable>();
|
||||||
private const int MAX_VISIBLE_CARDS = 3;
|
private const int MAX_VISIBLE_CARDS = 3;
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
base.OnManagedAwake();
|
// Discover zone tabs from container
|
||||||
|
DiscoverZoneTabs();
|
||||||
|
|
||||||
// Make sure we have a CanvasGroup for transitions
|
// Make sure we have a CanvasGroup for transitions
|
||||||
if (canvasGroup == null)
|
if (canvasGroup == null)
|
||||||
@@ -67,6 +70,17 @@ namespace UI.CardSystem
|
|||||||
// Set up booster pack button listeners
|
// Set up booster pack button listeners
|
||||||
SetupBoosterButtonListeners();
|
SetupBoosterButtonListeners();
|
||||||
|
|
||||||
|
// Subscribe to book page flip events
|
||||||
|
if (book != null)
|
||||||
|
{
|
||||||
|
book.OnFlip.AddListener(OnPageFlipped);
|
||||||
|
Logging.Debug("[AlbumViewPage] Subscribed to book.OnFlip event");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logging.Warning("[AlbumViewPage] Book reference is null, cannot subscribe to OnFlip event!");
|
||||||
|
}
|
||||||
|
|
||||||
// Subscribe to CardSystemManager events (managers are guaranteed to be initialized)
|
// Subscribe to CardSystemManager events (managers are guaranteed to be initialized)
|
||||||
if (CardSystemManager.Instance != null)
|
if (CardSystemManager.Instance != null)
|
||||||
{
|
{
|
||||||
@@ -83,6 +97,36 @@ namespace UI.CardSystem
|
|||||||
gameObject.SetActive(false);
|
gameObject.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Discover all BookTabButton components from the tab container
|
||||||
|
/// </summary>
|
||||||
|
private void DiscoverZoneTabs()
|
||||||
|
{
|
||||||
|
if (tabContainer == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("[AlbumViewPage] Tab container is not assigned! Cannot discover zone tabs.");
|
||||||
|
zoneTabs = new BookTabButton[0];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all BookTabButton components from children
|
||||||
|
zoneTabs = tabContainer.GetComponentsInChildren<BookTabButton>(includeInactive: false);
|
||||||
|
|
||||||
|
if (zoneTabs == null || zoneTabs.Length == 0)
|
||||||
|
{
|
||||||
|
Logging.Warning($"[AlbumViewPage] No BookTabButton components found in tab container '{tabContainer.name}'!");
|
||||||
|
zoneTabs = new BookTabButton[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logging.Debug($"[AlbumViewPage] Discovered {zoneTabs.Length} zone tabs from container '{tabContainer.name}'");
|
||||||
|
foreach (var tab in zoneTabs)
|
||||||
|
{
|
||||||
|
Logging.Debug($" - Tab: {tab.name}, Zone: {tab.Zone}, TargetPage: {tab.TargetPage}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void SetupBoosterButtonListeners()
|
private void SetupBoosterButtonListeners()
|
||||||
{
|
{
|
||||||
if (boosterPackButtons == null) return;
|
if (boosterPackButtons == null) return;
|
||||||
@@ -90,6 +134,12 @@ namespace UI.CardSystem
|
|||||||
for (int i = 0; i < boosterPackButtons.Length; i++)
|
for (int i = 0; i < boosterPackButtons.Length; i++)
|
||||||
{
|
{
|
||||||
if (boosterPackButtons[i] == null) continue;
|
if (boosterPackButtons[i] == null) continue;
|
||||||
|
// Unsubscribe from book events
|
||||||
|
if (book != null)
|
||||||
|
{
|
||||||
|
book.OnFlip.RemoveListener(OnPageFlipped);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Button button = boosterPackButtons[i].GetComponent<Button>();
|
Button button = boosterPackButtons[i].GetComponent<Button>();
|
||||||
if (button != null)
|
if (button != null)
|
||||||
@@ -99,7 +149,7 @@ namespace UI.CardSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
// Unsubscribe from CardSystemManager
|
// Unsubscribe from CardSystemManager
|
||||||
if (CardSystemManager.Instance != null)
|
if (CardSystemManager.Instance != null)
|
||||||
@@ -131,9 +181,6 @@ namespace UI.CardSystem
|
|||||||
|
|
||||||
// Clean up active cards
|
// Clean up active cards
|
||||||
CleanupActiveCards();
|
CleanupActiveCards();
|
||||||
|
|
||||||
// Call base implementation
|
|
||||||
base.OnDestroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnExitButtonClicked()
|
private void OnExitButtonClicked()
|
||||||
@@ -157,7 +204,7 @@ namespace UI.CardSystem
|
|||||||
if (Input.InputManager.Instance != null)
|
if (Input.InputManager.Instance != null)
|
||||||
{
|
{
|
||||||
Input.InputManager.Instance.SetInputMode(_previousInputMode);
|
Input.InputManager.Instance.SetInputMode(_previousInputMode);
|
||||||
Debug.Log($"[AlbumViewPage] Restored input mode to {_previousInputMode} on exit");
|
Logging.Debug($"[AlbumViewPage] Restored input mode to {_previousInputMode} on exit");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UIPageController.Instance != null)
|
if (UIPageController.Instance != null)
|
||||||
@@ -165,15 +212,6 @@ namespace UI.CardSystem
|
|||||||
UIPageController.Instance.PopPage();
|
UIPageController.Instance.PopPage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If album exits while in Overworld, show AppSwitcher. If not, keep it hidden.
|
|
||||||
if (PlayerHudManager.Instance.currentUIMode == PlayerHudManager.UIMode.Overworld)
|
|
||||||
{
|
|
||||||
PlayerHudManager.Instance.ToggleAppSwitcher(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PlayerHudManager.Instance.ToggleAppSwitcher(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnBoosterCountChanged(int newCount)
|
private void OnBoosterCountChanged(int newCount)
|
||||||
@@ -217,7 +255,7 @@ namespace UI.CardSystem
|
|||||||
// Store the current input mode before switching
|
// Store the current input mode before switching
|
||||||
_previousInputMode = Input.InputMode.GameAndUI;
|
_previousInputMode = Input.InputMode.GameAndUI;
|
||||||
Input.InputManager.Instance.SetInputMode(Input.InputMode.UI);
|
Input.InputManager.Instance.SetInputMode(Input.InputMode.UI);
|
||||||
Debug.Log("[AlbumViewPage] Switched to UI-only input mode on first entry");
|
Logging.Debug("[AlbumViewPage] Switched to UI-only input mode on first entry");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subscribe to pending card events while page is active
|
// Subscribe to pending card events while page is active
|
||||||
@@ -226,8 +264,16 @@ namespace UI.CardSystem
|
|||||||
CardSystemManager.Instance.OnPendingCardAdded += OnPendingCardAdded;
|
CardSystemManager.Instance.OnPendingCardAdded += OnPendingCardAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn pending cards when opening album
|
// Only spawn pending cards if we're already on an album page (not the menu)
|
||||||
SpawnPendingCards();
|
if (IsInAlbumProper())
|
||||||
|
{
|
||||||
|
Logging.Debug("[AlbumViewPage] Opening directly to album page - spawning cards immediately");
|
||||||
|
SpawnPendingCards();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logging.Debug("[AlbumViewPage] Opening to menu page - cards will spawn when entering album");
|
||||||
|
}
|
||||||
|
|
||||||
base.TransitionIn();
|
base.TransitionIn();
|
||||||
}
|
}
|
||||||
@@ -240,6 +286,9 @@ namespace UI.CardSystem
|
|||||||
CardSystemManager.Instance.OnPendingCardAdded -= OnPendingCardAdded;
|
CardSystemManager.Instance.OnPendingCardAdded -= OnPendingCardAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean up active pending cards to prevent duplicates on next opening
|
||||||
|
CleanupActiveCards();
|
||||||
|
|
||||||
// Don't restore input mode here - only restore when actually exiting (in OnExitButtonClicked)
|
// Don't restore input mode here - only restore when actually exiting (in OnExitButtonClicked)
|
||||||
base.TransitionOut();
|
base.TransitionOut();
|
||||||
}
|
}
|
||||||
@@ -313,6 +362,46 @@ namespace UI.CardSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if we're currently viewing the album proper (not the menu page)
|
||||||
|
/// </summary>
|
||||||
|
private bool IsInAlbumProper()
|
||||||
|
{
|
||||||
|
if (book == null)
|
||||||
|
{
|
||||||
|
Logging.Warning("[AlbumViewPage] Book reference is null in IsInAlbumProper check");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page 1 is the menu/cover, page 2+ are album pages with card slots
|
||||||
|
bool inAlbum = book.CurrentPaper > 1;
|
||||||
|
return inAlbum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when book page flips - show/hide pending cards based on whether we're in the album proper
|
||||||
|
/// </summary>
|
||||||
|
private void OnPageFlipped()
|
||||||
|
{
|
||||||
|
bool isInAlbum = IsInAlbumProper();
|
||||||
|
if (isInAlbum && _activeCards.Count == 0)
|
||||||
|
{
|
||||||
|
// Entering album proper and no cards spawned yet - spawn them with animation
|
||||||
|
Logging.Debug("[AlbumViewPage] Entering album proper - spawning pending cards with animation");
|
||||||
|
SpawnPendingCards();
|
||||||
|
}
|
||||||
|
else if (!isInAlbum && _activeCards.Count > 0)
|
||||||
|
{
|
||||||
|
// Returning to menu page - cleanup cards
|
||||||
|
Logging.Debug("[AlbumViewPage] Returning to menu page - cleaning up pending cards");
|
||||||
|
CleanupActiveCards();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logging.Debug($"[AlbumViewPage] Page flipped but no card state change needed (already in correct state)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region Album Card Reveal System
|
#region Album Card Reveal System
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -336,7 +425,7 @@ namespace UI.CardSystem
|
|||||||
|
|
||||||
int spawnCount = Mathf.Min(uniquePending.Count, MAX_VISIBLE_CARDS);
|
int spawnCount = Mathf.Min(uniquePending.Count, MAX_VISIBLE_CARDS);
|
||||||
|
|
||||||
Debug.Log($"[AlbumViewPage] Spawning {spawnCount} unique pending cards (total pending: {pending.Count})");
|
Logging.Debug($"[AlbumViewPage] Spawning {spawnCount} unique pending cards (total pending: {pending.Count})");
|
||||||
|
|
||||||
for (int i = 0; i < spawnCount; i++)
|
for (int i = 0; i < spawnCount; i++)
|
||||||
{
|
{
|
||||||
@@ -352,14 +441,14 @@ namespace UI.CardSystem
|
|||||||
// Guard: Don't spawn cards with zero copies
|
// Guard: Don't spawn cards with zero copies
|
||||||
if (cardData.CopiesOwned <= 0)
|
if (cardData.CopiesOwned <= 0)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[AlbumViewPage] Skipping spawn of card '{cardData.Name}' with {cardData.CopiesOwned} copies");
|
Logging.Warning($"[AlbumViewPage] Skipping spawn of card '{cardData.Name}' with {cardData.CopiesOwned} copies");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DraggableSlot slot = FindSlotByIndex(slotIndex);
|
DraggableSlot slot = FindSlotByIndex(slotIndex);
|
||||||
if (slot == null)
|
if (slot == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[AlbumViewPage] Could not find slot with SlotIndex {slotIndex}");
|
Logging.Warning($"[AlbumViewPage] Could not find slot with SlotIndex {slotIndex}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,11 +475,11 @@ namespace UI.CardSystem
|
|||||||
// Track it
|
// Track it
|
||||||
_activeCards.Add(cardPlacement);
|
_activeCards.Add(cardPlacement);
|
||||||
|
|
||||||
Debug.Log($"[AlbumViewPage] Spawned card '{cardData.Name}' (CopiesOwned: {cardData.CopiesOwned}) in slot {slotIndex}");
|
Logging.Debug($"[AlbumViewPage] Spawned card '{cardData.Name}' (CopiesOwned: {cardData.CopiesOwned}) in slot {slotIndex}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[AlbumViewPage] Spawned card has no AlbumCardDraggable component!");
|
Logging.Warning($"[AlbumViewPage] Spawned card has no AlbumCardDraggable component!");
|
||||||
Destroy(cardObj);
|
Destroy(cardObj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -404,7 +493,7 @@ namespace UI.CardSystem
|
|||||||
// Guard: Don't spawn cards with zero copies
|
// Guard: Don't spawn cards with zero copies
|
||||||
if (card.CopiesOwned <= 0)
|
if (card.CopiesOwned <= 0)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[AlbumViewPage] Ignoring pending card '{card.Name}' with {card.CopiesOwned} copies");
|
Logging.Warning($"[AlbumViewPage] Ignoring pending card '{card.Name}' with {card.CopiesOwned} copies");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,7 +504,7 @@ namespace UI.CardSystem
|
|||||||
|
|
||||||
if (alreadySpawned)
|
if (alreadySpawned)
|
||||||
{
|
{
|
||||||
Debug.Log($"[AlbumViewPage] Card '{card.Name}' already spawned, skipping duplicate spawn");
|
Logging.Debug($"[AlbumViewPage] Card '{card.Name}' already spawned, skipping duplicate spawn");
|
||||||
return; // Don't spawn duplicates
|
return; // Don't spawn duplicates
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,13 +521,13 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnCardRevealed(AlbumCardPlacementDraggable cardPlacement, CardData cardData)
|
private void OnCardRevealed(AlbumCardPlacementDraggable cardPlacement, CardData cardData)
|
||||||
{
|
{
|
||||||
Debug.Log($"[AlbumViewPage] Card revealed: {cardData.Name} (Zone: {cardData.Zone}, CopiesOwned: {cardData.CopiesOwned})");
|
Logging.Debug($"[AlbumViewPage] Card revealed: {cardData.Name} (Zone: {cardData.Zone}, CopiesOwned: {cardData.CopiesOwned})");
|
||||||
|
|
||||||
// IMMEDIATELY move card from pending to inventory upon reveal
|
// IMMEDIATELY move card from pending to inventory upon reveal
|
||||||
if (CardSystemManager.Instance != null)
|
if (CardSystemManager.Instance != null)
|
||||||
{
|
{
|
||||||
CardSystemManager.Instance.MarkCardAsPlaced(cardData);
|
CardSystemManager.Instance.MarkCardAsPlaced(cardData);
|
||||||
Debug.Log($"[AlbumViewPage] Moved card '{cardData.Name}' from pending to inventory on reveal");
|
Logging.Debug($"[AlbumViewPage] Moved card '{cardData.Name}' from pending to inventory on reveal");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove this card from active cards list
|
// Remove this card from active cards list
|
||||||
@@ -450,12 +539,12 @@ namespace UI.CardSystem
|
|||||||
if (currentZone != cardData.Zone)
|
if (currentZone != cardData.Zone)
|
||||||
{
|
{
|
||||||
// Card is from a different zone - navigate to its zone
|
// Card is from a different zone - navigate to its zone
|
||||||
Debug.Log($"[AlbumViewPage] Card zone ({cardData.Zone}) doesn't match current zone ({currentZone}). Navigating to card's zone...");
|
Logging.Debug($"[AlbumViewPage] Card zone ({cardData.Zone}) doesn't match current zone ({currentZone}). Navigating to card's zone...");
|
||||||
NavigateToZone(cardData.Zone);
|
NavigateToZone(cardData.Zone);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Log($"[AlbumViewPage] Card zone ({cardData.Zone}) matches current zone - no navigation needed.");
|
Logging.Debug($"[AlbumViewPage] Card zone ({cardData.Zone}) matches current zone - no navigation needed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shuffle remaining cards to front and spawn next unique card
|
// Shuffle remaining cards to front and spawn next unique card
|
||||||
@@ -470,7 +559,7 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnCardPlacedInAlbum(AlbumCardPlacementDraggable cardPlacement, CardData cardData)
|
private void OnCardPlacedInAlbum(AlbumCardPlacementDraggable cardPlacement, CardData cardData)
|
||||||
{
|
{
|
||||||
Debug.Log($"[AlbumViewPage] Card placed in album slot: {cardData.Name}");
|
Logging.Debug($"[AlbumViewPage] Card placed in album slot: {cardData.Name}");
|
||||||
|
|
||||||
// Unsubscribe from events (card is now static in album)
|
// Unsubscribe from events (card is now static in album)
|
||||||
cardPlacement.OnCardRevealed -= OnCardRevealed;
|
cardPlacement.OnCardRevealed -= OnCardRevealed;
|
||||||
@@ -554,7 +643,9 @@ namespace UI.CardSystem
|
|||||||
public CardZone GetCurrentZone()
|
public CardZone GetCurrentZone()
|
||||||
{
|
{
|
||||||
if (book == null || zoneTabs == null || zoneTabs.Length == 0)
|
if (book == null || zoneTabs == null || zoneTabs.Length == 0)
|
||||||
|
{
|
||||||
return CardZone.AppleHills; // Default
|
return CardZone.AppleHills; // Default
|
||||||
|
}
|
||||||
|
|
||||||
int currentPage = book.CurrentPaper;
|
int currentPage = book.CurrentPaper;
|
||||||
|
|
||||||
@@ -566,9 +657,8 @@ namespace UI.CardSystem
|
|||||||
return tab.Zone;
|
return tab.Zone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to first zone
|
// Fallback to first zone
|
||||||
return zoneTabs[0].Zone;
|
return CardZone.NotApplicable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -576,16 +666,20 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public BookTabButton GetTabForZone(CardZone zone)
|
public BookTabButton GetTabForZone(CardZone zone)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (zoneTabs == null)
|
if (zoneTabs == null)
|
||||||
|
{
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var tab in zoneTabs)
|
foreach (var tab in zoneTabs)
|
||||||
{
|
{
|
||||||
if (tab.Zone == zone)
|
if (tab.Zone == zone)
|
||||||
{
|
{
|
||||||
return tab;
|
return tab;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -652,7 +746,7 @@ namespace UI.CardSystem
|
|||||||
{
|
{
|
||||||
if (card == null) return;
|
if (card == null) return;
|
||||||
|
|
||||||
Debug.Log($"[AlbumViewPage] OnCardEnlargeRequested called for card: {card.name}, current parent: {card.transform.parent.name}");
|
Logging.Debug($"[AlbumViewPage] OnCardEnlargeRequested called for card: {card.name}, current parent: {card.transform.parent.name}");
|
||||||
|
|
||||||
// IMPORTANT: Call EnlargeCard FIRST to store original parent (the slot)
|
// IMPORTANT: Call EnlargeCard FIRST to store original parent (the slot)
|
||||||
// BEFORE reparenting to the enlarged container
|
// BEFORE reparenting to the enlarged container
|
||||||
@@ -662,7 +756,7 @@ namespace UI.CardSystem
|
|||||||
if (cardEnlargedBackdrop != null)
|
if (cardEnlargedBackdrop != null)
|
||||||
{
|
{
|
||||||
cardEnlargedBackdrop.SetActive(true);
|
cardEnlargedBackdrop.SetActive(true);
|
||||||
Debug.Log($"[AlbumViewPage] Backdrop shown");
|
Logging.Debug($"[AlbumViewPage] Backdrop shown");
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOW reparent card to enlarged container (above backdrop)
|
// NOW reparent card to enlarged container (above backdrop)
|
||||||
@@ -670,10 +764,10 @@ namespace UI.CardSystem
|
|||||||
{
|
{
|
||||||
card.transform.SetParent(cardEnlargedContainer, true);
|
card.transform.SetParent(cardEnlargedContainer, true);
|
||||||
card.transform.SetAsLastSibling(); // Ensure on top
|
card.transform.SetAsLastSibling(); // Ensure on top
|
||||||
Debug.Log($"[AlbumViewPage] Card reparented to enlarged container");
|
Logging.Debug($"[AlbumViewPage] Card reparented to enlarged container");
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[AlbumViewPage] Card enlarged: {card.GetCardData()?.Name}");
|
Logging.Debug($"[AlbumViewPage] Card enlarged: {card.GetCardData()?.Name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -701,7 +795,7 @@ namespace UI.CardSystem
|
|||||||
card.transform.localRotation = card.GetOriginalLocalRotation();
|
card.transform.localRotation = card.GetOriginalLocalRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[AlbumViewPage] Card shrunk: {card.GetCardData()?.Name}");
|
Logging.Debug($"[AlbumViewPage] Card shrunk: {card.GetCardData()?.Name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -712,7 +806,7 @@ namespace UI.CardSystem
|
|||||||
if (previewCardTransform == null)
|
if (previewCardTransform == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug.Log($"[AlbumViewPage] ShowSlotPreview called for slot: {slot.name}");
|
Logging.Debug($"[AlbumViewPage] ShowSlotPreview called for slot: {slot.name}");
|
||||||
|
|
||||||
// Show backdrop
|
// Show backdrop
|
||||||
if (cardEnlargedBackdrop != null)
|
if (cardEnlargedBackdrop != null)
|
||||||
@@ -736,7 +830,7 @@ namespace UI.CardSystem
|
|||||||
if (previewCardTransform == null)
|
if (previewCardTransform == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug.Log($"[AlbumViewPage] HideSlotPreview called for slot: {slot.name}");
|
Logging.Debug($"[AlbumViewPage] HideSlotPreview called for slot: {slot.name}");
|
||||||
|
|
||||||
// Hide backdrop
|
// Hide backdrop
|
||||||
if (cardEnlargedBackdrop != null)
|
if (cardEnlargedBackdrop != null)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using AppleHills.Data.CardSystem;
|
using AppleHills.Data.CardSystem;
|
||||||
using BookCurlPro;
|
using BookCurlPro;
|
||||||
|
using Core;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using Tween = Pixelplacement.Tween;
|
using Tween = Pixelplacement.Tween;
|
||||||
@@ -69,7 +70,7 @@ namespace UI.CardSystem
|
|||||||
{
|
{
|
||||||
if (book == null)
|
if (book == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[BookTabButton] No BookPro reference assigned on {gameObject.name}");
|
Logging.Warning($"[BookTabButton] No BookPro reference assigned on {gameObject.name}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,10 +40,8 @@ namespace UI.CardSystem
|
|||||||
|
|
||||||
private TweenBase _activeTween;
|
private TweenBase _activeTween;
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
base.OnManagedAwake();
|
|
||||||
|
|
||||||
// Store original scale for pulse animation
|
// Store original scale for pulse animation
|
||||||
if (dotBackground != null)
|
if (dotBackground != null)
|
||||||
{
|
{
|
||||||
@@ -72,16 +70,13 @@ namespace UI.CardSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
// Unsubscribe from CardSystemManager events to prevent memory leaks
|
// Unsubscribe from CardSystemManager events to prevent memory leaks
|
||||||
if (CardSystemManager.Instance != null)
|
if (CardSystemManager.Instance != null)
|
||||||
{
|
{
|
||||||
CardSystemManager.Instance.OnBoosterCountChanged -= OnBoosterCountChanged;
|
CardSystemManager.Instance.OnBoosterCountChanged -= OnBoosterCountChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call base implementation
|
|
||||||
base.OnDestroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using AppleHills.Data.CardSystem;
|
using AppleHills.Data.CardSystem;
|
||||||
|
using Core;
|
||||||
using Data.CardSystem;
|
using Data.CardSystem;
|
||||||
using Pixelplacement;
|
using Pixelplacement;
|
||||||
using UI.Core;
|
using UI.Core;
|
||||||
@@ -33,7 +34,6 @@ namespace UI.CardSystem
|
|||||||
[SerializeField] private float cardSpacing = 150f;
|
[SerializeField] private float cardSpacing = 150f;
|
||||||
|
|
||||||
[Header("Settings")]
|
[Header("Settings")]
|
||||||
[SerializeField] private float cardRevealDelay = 0.5f;
|
|
||||||
[SerializeField] private float boosterDisappearDuration = 0.5f;
|
[SerializeField] private float boosterDisappearDuration = 0.5f;
|
||||||
[SerializeField] private CinemachineImpulseSource impulseSource;
|
[SerializeField] private CinemachineImpulseSource impulseSource;
|
||||||
[SerializeField] private ParticleSystem openingParticleSystem;
|
[SerializeField] private ParticleSystem openingParticleSystem;
|
||||||
@@ -68,7 +68,7 @@ namespace UI.CardSystem
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[BoosterOpeningPage] albumIcon does not have a Button component!");
|
Logging.Warning("[BoosterOpeningPage] albumIcon does not have a Button component!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ namespace UI.CardSystem
|
|||||||
gameObject.SetActive(false);
|
gameObject.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
// Unsubscribe from dismiss button
|
// Unsubscribe from dismiss button
|
||||||
if (_dismissButton != null)
|
if (_dismissButton != null)
|
||||||
@@ -111,13 +111,20 @@ namespace UI.CardSystem
|
|||||||
if (UIPageController.Instance != null)
|
if (UIPageController.Instance != null)
|
||||||
{
|
{
|
||||||
UIPageController.Instance.PopPage();
|
UIPageController.Instance.PopPage();
|
||||||
Debug.Log("[BoosterOpeningPage] Dismiss button clicked, popping page from stack");
|
Logging.Debug("[BoosterOpeningPage] Dismiss button clicked, popping page from stack");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void TransitionIn()
|
public override void TransitionIn()
|
||||||
{
|
{
|
||||||
base.TransitionIn();
|
base.TransitionIn();
|
||||||
|
|
||||||
|
// Ensure album icon is visible when page opens
|
||||||
|
if (albumIcon != null)
|
||||||
|
{
|
||||||
|
albumIcon.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
InitializeBoosterDisplay();
|
InitializeBoosterDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,17 +139,17 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeBoosterDisplay()
|
private void InitializeBoosterDisplay()
|
||||||
{
|
{
|
||||||
Debug.Log($"[BoosterOpeningPage] InitializeBoosterDisplay called with {_availableBoosterCount} boosters available");
|
Logging.Debug($"[BoosterOpeningPage] InitializeBoosterDisplay called with {_availableBoosterCount} boosters available");
|
||||||
|
|
||||||
if (boosterPackPrefab == null)
|
if (boosterPackPrefab == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("BoosterOpeningPage: No booster pack prefab assigned!");
|
Logging.Warning("BoosterOpeningPage: No booster pack prefab assigned!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bottomRightSlots == null || bottomRightSlots.SlotCount == 0)
|
if (bottomRightSlots == null || bottomRightSlots.SlotCount == 0)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("BoosterOpeningPage: No slots available!");
|
Logging.Warning("BoosterOpeningPage: No slots available!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +159,7 @@ namespace UI.CardSystem
|
|||||||
// Calculate how many boosters to show (max 3, or available count, whichever is lower)
|
// Calculate how many boosters to show (max 3, or available count, whichever is lower)
|
||||||
int visibleCount = Mathf.Min(_availableBoosterCount, MAX_VISIBLE_BOOSTERS);
|
int visibleCount = Mathf.Min(_availableBoosterCount, MAX_VISIBLE_BOOSTERS);
|
||||||
|
|
||||||
Debug.Log($"[BoosterOpeningPage] Will spawn {visibleCount} boosters");
|
Logging.Debug($"[BoosterOpeningPage] Will spawn {visibleCount} boosters");
|
||||||
|
|
||||||
// Spawn boosters and assign to slots
|
// Spawn boosters and assign to slots
|
||||||
for (int i = 0; i < visibleCount; i++)
|
for (int i = 0; i < visibleCount; i++)
|
||||||
@@ -165,11 +172,11 @@ namespace UI.CardSystem
|
|||||||
{
|
{
|
||||||
centerOpeningSlot.OnOccupied += OnBoosterPlacedInCenter;
|
centerOpeningSlot.OnOccupied += OnBoosterPlacedInCenter;
|
||||||
centerOpeningSlot.OnVacated += OnBoosterRemovedFromCenter;
|
centerOpeningSlot.OnVacated += OnBoosterRemovedFromCenter;
|
||||||
Debug.Log($"[BoosterOpeningPage] Subscribed to center slot events");
|
Logging.Debug($"[BoosterOpeningPage] Subscribed to center slot events");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[BoosterOpeningPage] centerOpeningSlot is null!");
|
Logging.Warning("[BoosterOpeningPage] centerOpeningSlot is null!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +188,7 @@ namespace UI.CardSystem
|
|||||||
DraggableSlot slot = FindSlotByIndex(slotIndex);
|
DraggableSlot slot = FindSlotByIndex(slotIndex);
|
||||||
if (slot == null)
|
if (slot == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[BoosterOpeningPage] Could not find slot with SlotIndex {slotIndex}!");
|
Logging.Warning($"[BoosterOpeningPage] Could not find slot with SlotIndex {slotIndex}!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,11 +211,11 @@ namespace UI.CardSystem
|
|||||||
// Track it
|
// Track it
|
||||||
_activeBoostersInSlots.Add(booster);
|
_activeBoostersInSlots.Add(booster);
|
||||||
|
|
||||||
Debug.Log($"[BoosterOpeningPage] Spawned booster in slot with SlotIndex {slotIndex}");
|
Logging.Debug($"[BoosterOpeningPage] Spawned booster in slot with SlotIndex {slotIndex}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[BoosterOpeningPage] Spawned booster has no BoosterPackDraggable component!");
|
Logging.Warning($"[BoosterOpeningPage] Spawned booster has no BoosterPackDraggable component!");
|
||||||
Destroy(boosterObj);
|
Destroy(boosterObj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,7 +251,7 @@ namespace UI.CardSystem
|
|||||||
booster.CurrentSlot.Vacate();
|
booster.CurrentSlot.Vacate();
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[BoosterOpeningPage] Removed booster from slot {slotIndex}");
|
Logging.Debug($"[BoosterOpeningPage] Removed booster from slot {slotIndex}");
|
||||||
}
|
}
|
||||||
|
|
||||||
_activeBoostersInSlots.RemoveAt(slotIndex);
|
_activeBoostersInSlots.RemoveAt(slotIndex);
|
||||||
@@ -264,7 +271,7 @@ namespace UI.CardSystem
|
|||||||
RemoveBoosterFromSlot(lastIndex);
|
RemoveBoosterFromSlot(lastIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[BoosterOpeningPage] Updated visible boosters: {_activeBoostersInSlots.Count}/{targetCount}");
|
Logging.Debug($"[BoosterOpeningPage] Updated visible boosters: {_activeBoostersInSlots.Count}/{targetCount}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -274,7 +281,7 @@ namespace UI.CardSystem
|
|||||||
{
|
{
|
||||||
if (_activeBoostersInSlots.Count == 0) return;
|
if (_activeBoostersInSlots.Count == 0) return;
|
||||||
|
|
||||||
Debug.Log($"[BoosterOpeningPage] Shuffling {_activeBoostersInSlots.Count} boosters to front slots");
|
Logging.Debug($"[BoosterOpeningPage] Shuffling {_activeBoostersInSlots.Count} boosters to front slots");
|
||||||
|
|
||||||
// Unassign all boosters from their current slots
|
// Unassign all boosters from their current slots
|
||||||
foreach (var booster in _activeBoostersInSlots)
|
foreach (var booster in _activeBoostersInSlots)
|
||||||
@@ -294,12 +301,12 @@ namespace UI.CardSystem
|
|||||||
|
|
||||||
if (targetSlot != null)
|
if (targetSlot != null)
|
||||||
{
|
{
|
||||||
Debug.Log($"[BoosterOpeningPage] Assigning booster to slot with SlotIndex {i} {targetSlot.name}");
|
Logging.Debug($"[BoosterOpeningPage] Assigning booster to slot with SlotIndex {i} {targetSlot.name}");
|
||||||
booster.AssignToSlot(targetSlot, true); // Animate the move
|
booster.AssignToSlot(targetSlot, true); // Animate the move
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[BoosterOpeningPage] Could not find slot with SlotIndex {i} {targetSlot.name}");
|
Logging.Warning($"[BoosterOpeningPage] Could not find slot with SlotIndex {i} {targetSlot.name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,7 +351,7 @@ namespace UI.CardSystem
|
|||||||
if (slot != null && !slot.IsOccupied)
|
if (slot != null && !slot.IsOccupied)
|
||||||
{
|
{
|
||||||
SpawnBoosterInSlot(i);
|
SpawnBoosterInSlot(i);
|
||||||
Debug.Log($"[BoosterOpeningPage] Spawned new booster in slot with SlotIndex {i}");
|
Logging.Debug($"[BoosterOpeningPage] Spawned new booster in slot with SlotIndex {i}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -363,13 +370,20 @@ namespace UI.CardSystem
|
|||||||
// Remove from active slots list
|
// Remove from active slots list
|
||||||
_activeBoostersInSlots.Remove(booster);
|
_activeBoostersInSlots.Remove(booster);
|
||||||
|
|
||||||
|
// Hide album icon when booster is placed in center
|
||||||
|
if (albumIcon != null)
|
||||||
|
{
|
||||||
|
albumIcon.SetActive(false);
|
||||||
|
Logging.Debug($"[BoosterOpeningPage] Album icon hidden");
|
||||||
|
}
|
||||||
|
|
||||||
// Lock the slot so it can't be dragged out
|
// Lock the slot so it can't be dragged out
|
||||||
Debug.Log($"[BoosterOpeningPage] Locking center slot. IsLocked before: {centerOpeningSlot.IsLocked}");
|
Logging.Debug($"[BoosterOpeningPage] Locking center slot. IsLocked before: {centerOpeningSlot.IsLocked}");
|
||||||
centerOpeningSlot.SetLocked(true);
|
centerOpeningSlot.SetLocked(true);
|
||||||
Debug.Log($"[BoosterOpeningPage] IsLocked after: {centerOpeningSlot.IsLocked}");
|
Logging.Debug($"[BoosterOpeningPage] IsLocked after: {centerOpeningSlot.IsLocked}");
|
||||||
|
|
||||||
// Configure booster for opening (disables drag, enables tapping, resets tap count)
|
// Configure booster for opening (disables drag, enables tapping, resets tap count)
|
||||||
Debug.Log($"[BoosterOpeningPage] Calling SetInOpeningSlot(true) on booster");
|
Logging.Debug($"[BoosterOpeningPage] Calling SetInOpeningSlot(true) on booster");
|
||||||
booster.SetInOpeningSlot(true);
|
booster.SetInOpeningSlot(true);
|
||||||
|
|
||||||
// Subscribe to tap events for visual feedback
|
// Subscribe to tap events for visual feedback
|
||||||
@@ -384,7 +398,7 @@ namespace UI.CardSystem
|
|||||||
// Shuffle remaining boosters to occupy the first slots
|
// Shuffle remaining boosters to occupy the first slots
|
||||||
ShuffleBoostersToFront();
|
ShuffleBoostersToFront();
|
||||||
|
|
||||||
Debug.Log($"[BoosterOpeningPage] Booster placed in center, ready for taps. Active boosters in slots: {_activeBoostersInSlots.Count}");
|
Logging.Debug($"[BoosterOpeningPage] Booster placed in center, ready for taps. Active boosters in slots: {_activeBoostersInSlots.Count}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -403,12 +417,12 @@ namespace UI.CardSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
_currentBoosterInCenter = null;
|
_currentBoosterInCenter = null;
|
||||||
Debug.Log($"[BoosterOpeningPage] Booster removed from center");
|
Logging.Debug($"[BoosterOpeningPage] Booster removed from center");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnBoosterTapped(BoosterPackDraggable booster, int currentTaps, int maxTaps)
|
private void OnBoosterTapped(BoosterPackDraggable booster, int currentTaps, int maxTaps)
|
||||||
{
|
{
|
||||||
Debug.Log($"[BoosterOpeningPage] Booster tapped: {currentTaps}/{maxTaps}");
|
Logging.Debug($"[BoosterOpeningPage] Booster tapped: {currentTaps}/{maxTaps}");
|
||||||
|
|
||||||
// Fire Cinemachine impulse with random velocity (excluding Z)
|
// Fire Cinemachine impulse with random velocity (excluding Z)
|
||||||
if (impulseSource != null)
|
if (impulseSource != null)
|
||||||
@@ -433,7 +447,7 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnBoosterOpened(BoosterPackDraggable booster)
|
private void OnBoosterOpened(BoosterPackDraggable booster)
|
||||||
{
|
{
|
||||||
Debug.Log($"[BoosterOpeningPage] Booster opened, playing particle effect");
|
Logging.Debug($"[BoosterOpeningPage] Booster opened, playing particle effect");
|
||||||
|
|
||||||
// Reset and play particle system
|
// Reset and play particle system
|
||||||
if (openingParticleSystem != null)
|
if (openingParticleSystem != null)
|
||||||
@@ -471,7 +485,7 @@ namespace UI.CardSystem
|
|||||||
{
|
{
|
||||||
if (_isProcessingOpening) return;
|
if (_isProcessingOpening) return;
|
||||||
|
|
||||||
Debug.Log($"[BoosterOpeningPage] Booster ready to open!");
|
Logging.Debug($"[BoosterOpeningPage] Booster ready to open!");
|
||||||
|
|
||||||
// Trigger the actual opening sequence
|
// Trigger the actual opening sequence
|
||||||
booster.TriggerOpen();
|
booster.TriggerOpen();
|
||||||
@@ -514,7 +528,7 @@ namespace UI.CardSystem
|
|||||||
// WaitForCardReveals already includes: 0.5s wait + (cardCount * 0.5s stagger) + 0.5s animation + 0.5s final
|
// WaitForCardReveals already includes: 0.5s wait + (cardCount * 0.5s stagger) + 0.5s animation + 0.5s final
|
||||||
// Total is: 1.5s + (cardCount * 0.5s)
|
// Total is: 1.5s + (cardCount * 0.5s)
|
||||||
// For 5 cards that's 4 seconds total, which should be enough
|
// For 5 cards that's 4 seconds total, which should be enough
|
||||||
Debug.Log("[BoosterOpeningPage] Last booster opened, auto-transitioning to album main page");
|
Logging.Debug("[BoosterOpeningPage] Last booster opened, auto-transitioning to album main page");
|
||||||
if (UIPageController.Instance != null)
|
if (UIPageController.Instance != null)
|
||||||
{
|
{
|
||||||
UIPageController.Instance.PopPage();
|
UIPageController.Instance.PopPage();
|
||||||
@@ -561,7 +575,7 @@ namespace UI.CardSystem
|
|||||||
{
|
{
|
||||||
if (flippableCardPrefab == null || cardDisplayContainer == null)
|
if (flippableCardPrefab == null || cardDisplayContainer == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("BoosterOpeningPage: Missing card prefab or container!");
|
Logging.Warning("BoosterOpeningPage: Missing card prefab or container!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -605,7 +619,7 @@ namespace UI.CardSystem
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[BoosterOpeningPage] FlippableCard component not found on card {i}!");
|
Logging.Warning($"[BoosterOpeningPage] FlippableCard component not found on card {i}!");
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentRevealedCards.Add(cardObj);
|
_currentRevealedCards.Add(cardObj);
|
||||||
@@ -621,7 +635,7 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnCardFlipStarted(FlippableCard flippingCard)
|
private void OnCardFlipStarted(FlippableCard flippingCard)
|
||||||
{
|
{
|
||||||
Debug.Log($"[BoosterOpeningPage] Card flip started, disabling all other cards.");
|
Logging.Debug($"[BoosterOpeningPage] Card flip started, disabling all other cards.");
|
||||||
|
|
||||||
// Disable ALL cards immediately to prevent multi-flip
|
// Disable ALL cards immediately to prevent multi-flip
|
||||||
foreach (GameObject cardObj in _currentRevealedCards)
|
foreach (GameObject cardObj in _currentRevealedCards)
|
||||||
@@ -639,14 +653,14 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnCardRevealed(int cardIndex)
|
private void OnCardRevealed(int cardIndex)
|
||||||
{
|
{
|
||||||
Debug.Log($"[BoosterOpeningPage] Card {cardIndex} revealed!");
|
Logging.Debug($"[BoosterOpeningPage] Card {cardIndex} revealed!");
|
||||||
_revealedCardCount++;
|
_revealedCardCount++;
|
||||||
|
|
||||||
// Get the flippable card and card data
|
// Get the flippable card and card data
|
||||||
FlippableCard flippableCard = _currentRevealedCards[cardIndex].GetComponent<FlippableCard>();
|
FlippableCard flippableCard = _currentRevealedCards[cardIndex].GetComponent<FlippableCard>();
|
||||||
if (flippableCard == null)
|
if (flippableCard == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[BoosterOpeningPage] FlippableCard not found for card {cardIndex}!");
|
Logging.Warning($"[BoosterOpeningPage] FlippableCard not found for card {cardIndex}!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,7 +671,7 @@ namespace UI.CardSystem
|
|||||||
|
|
||||||
if (isNew)
|
if (isNew)
|
||||||
{
|
{
|
||||||
Debug.Log($"[BoosterOpeningPage] Card '{cardData.Name}' is NEW!");
|
Logging.Debug($"[BoosterOpeningPage] Card '{cardData.Name}' is NEW!");
|
||||||
flippableCard.ShowAsNew();
|
flippableCard.ShowAsNew();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -665,7 +679,7 @@ namespace UI.CardSystem
|
|||||||
// Check if card is already Legendary - if so, skip progress bar and auto-progress
|
// Check if card is already Legendary - if so, skip progress bar and auto-progress
|
||||||
if (existingCard.Rarity == AppleHills.Data.CardSystem.CardRarity.Legendary)
|
if (existingCard.Rarity == AppleHills.Data.CardSystem.CardRarity.Legendary)
|
||||||
{
|
{
|
||||||
Debug.Log($"[BoosterOpeningPage] Card '{cardData.Name}' is LEGENDARY - auto-progressing!");
|
Logging.Debug($"[BoosterOpeningPage] Card '{cardData.Name}' is LEGENDARY - auto-progressing!");
|
||||||
// Add to inventory immediately and move to next card
|
// Add to inventory immediately and move to next card
|
||||||
Data.CardSystem.CardSystemManager.Instance.AddCardToInventoryDelayed(cardData);
|
Data.CardSystem.CardSystemManager.Instance.AddCardToInventoryDelayed(cardData);
|
||||||
_cardsCompletedInteraction++;
|
_cardsCompletedInteraction++;
|
||||||
@@ -675,14 +689,14 @@ namespace UI.CardSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ownedCount = existingCard.CopiesOwned;
|
int ownedCount = existingCard.CopiesOwned;
|
||||||
Debug.Log($"[BoosterOpeningPage] Card '{cardData.Name}' is a REPEAT! Owned: {ownedCount}");
|
Logging.Debug($"[BoosterOpeningPage] Card '{cardData.Name}' is a REPEAT! Owned: {ownedCount}");
|
||||||
|
|
||||||
// Check if this card will trigger an upgrade (ownedCount + 1 >= threshold)
|
// Check if this card will trigger an upgrade (ownedCount + 1 >= threshold)
|
||||||
bool willUpgrade = (ownedCount + 1) >= flippableCard.CardsToUpgrade && existingCard.Rarity < AppleHills.Data.CardSystem.CardRarity.Legendary;
|
bool willUpgrade = (ownedCount + 1) >= flippableCard.CardsToUpgrade && existingCard.Rarity < AppleHills.Data.CardSystem.CardRarity.Legendary;
|
||||||
|
|
||||||
if (willUpgrade)
|
if (willUpgrade)
|
||||||
{
|
{
|
||||||
Debug.Log($"[BoosterOpeningPage] This card will trigger upgrade! ({ownedCount + 1}/{flippableCard.CardsToUpgrade})");
|
Logging.Debug($"[BoosterOpeningPage] This card will trigger upgrade! ({ownedCount + 1}/{flippableCard.CardsToUpgrade})");
|
||||||
// Show as repeat - progress bar will fill and auto-trigger upgrade
|
// Show as repeat - progress bar will fill and auto-trigger upgrade
|
||||||
flippableCard.ShowAsRepeatWithUpgrade(ownedCount, existingCard);
|
flippableCard.ShowAsRepeatWithUpgrade(ownedCount, existingCard);
|
||||||
}
|
}
|
||||||
@@ -705,7 +719,7 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnCardCompletedInteraction(FlippableCard card, int cardIndex)
|
private void OnCardCompletedInteraction(FlippableCard card, int cardIndex)
|
||||||
{
|
{
|
||||||
Debug.Log($"[BoosterOpeningPage] Card {cardIndex} interaction complete!");
|
Logging.Debug($"[BoosterOpeningPage] Card {cardIndex} interaction complete!");
|
||||||
|
|
||||||
// Add card to inventory NOW (after player saw it)
|
// Add card to inventory NOW (after player saw it)
|
||||||
Data.CardSystem.CardSystemManager.Instance.AddCardToInventoryDelayed(card.CardData);
|
Data.CardSystem.CardSystemManager.Instance.AddCardToInventoryDelayed(card.CardData);
|
||||||
@@ -722,7 +736,7 @@ namespace UI.CardSystem
|
|||||||
// Re-enable all unrevealed cards (they can be flipped now)
|
// Re-enable all unrevealed cards (they can be flipped now)
|
||||||
EnableUnrevealedCards();
|
EnableUnrevealedCards();
|
||||||
|
|
||||||
Debug.Log($"[BoosterOpeningPage] Cards completed interaction: {_cardsCompletedInteraction}/{_currentCardData.Length}");
|
Logging.Debug($"[BoosterOpeningPage] Cards completed interaction: {_cardsCompletedInteraction}/{_currentCardData.Length}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -743,7 +757,7 @@ namespace UI.CardSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[BoosterOpeningPage] Set active card. Only one card is now clickable.");
|
Logging.Debug($"[BoosterOpeningPage] Set active card. Only one card is now clickable.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -760,7 +774,7 @@ namespace UI.CardSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[BoosterOpeningPage] Re-enabled unrevealed cards for flipping.");
|
Logging.Debug($"[BoosterOpeningPage] Re-enabled unrevealed cards for flipping.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -768,7 +782,7 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnCardClickedWhileInactive(FlippableCard inactiveCard)
|
private void OnCardClickedWhileInactive(FlippableCard inactiveCard)
|
||||||
{
|
{
|
||||||
Debug.Log($"[BoosterOpeningPage] Inactive card clicked, jiggling active card.");
|
Logging.Debug($"[BoosterOpeningPage] Inactive card clicked, jiggling active card.");
|
||||||
|
|
||||||
if (_currentActiveCard != null)
|
if (_currentActiveCard != null)
|
||||||
{
|
{
|
||||||
@@ -787,7 +801,7 @@ namespace UI.CardSystem
|
|||||||
yield return null;
|
yield return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[BoosterOpeningPage] All cards revealed! Waiting for interactions...");
|
Logging.Debug($"[BoosterOpeningPage] All cards revealed! Waiting for interactions...");
|
||||||
|
|
||||||
// Wait until all cards have completed their new/repeat interaction
|
// Wait until all cards have completed their new/repeat interaction
|
||||||
while (_cardsCompletedInteraction < _currentCardData.Length)
|
while (_cardsCompletedInteraction < _currentCardData.Length)
|
||||||
@@ -795,11 +809,18 @@ namespace UI.CardSystem
|
|||||||
yield return null;
|
yield return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[BoosterOpeningPage] All interactions complete! Animating cards to album...");
|
Logging.Debug($"[BoosterOpeningPage] All interactions complete! Animating cards to album...");
|
||||||
|
|
||||||
// All cards revealed and interacted with, wait a moment
|
// All cards revealed and interacted with, wait a moment
|
||||||
yield return new WaitForSeconds(0.5f);
|
yield return new WaitForSeconds(0.5f);
|
||||||
|
|
||||||
|
// Show album icon before cards start tweening to it
|
||||||
|
if (albumIcon != null)
|
||||||
|
{
|
||||||
|
albumIcon.SetActive(true);
|
||||||
|
Logging.Debug($"[BoosterOpeningPage] Album icon shown for card tween target");
|
||||||
|
}
|
||||||
|
|
||||||
// Animate cards to album icon (or center if no icon assigned) with staggered delays
|
// Animate cards to album icon (or center if no icon assigned) with staggered delays
|
||||||
Vector3 targetPosition = albumIcon != null ? albumIcon.transform.position : Vector3.zero;
|
Vector3 targetPosition = albumIcon != null ? albumIcon.transform.position : Vector3.zero;
|
||||||
|
|
||||||
@@ -828,6 +849,8 @@ namespace UI.CardSystem
|
|||||||
_currentRevealedCards.Clear();
|
_currentRevealedCards.Clear();
|
||||||
|
|
||||||
yield return new WaitForSeconds(totalAnimationTime);
|
yield return new WaitForSeconds(totalAnimationTime);
|
||||||
|
|
||||||
|
// Album icon stays visible for next booster (will be hidden when next booster is placed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using Core;
|
||||||
using Data.CardSystem;
|
using Data.CardSystem;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
@@ -58,7 +59,7 @@ namespace UI.CardSystem
|
|||||||
{
|
{
|
||||||
if (Instance != null && Instance != this)
|
if (Instance != null && Instance != this)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[BoosterPackGiver] Duplicate instance detected. Destroying this component.");
|
Logging.Warning("[BoosterPackGiver] Duplicate instance detected. Destroying this component.");
|
||||||
Destroy(this);
|
Destroy(this);
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using UI.Core;
|
using Core;
|
||||||
|
using UI.Core;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ namespace UI.CardSystem
|
|||||||
openAlbumButton.onClick.RemoveListener(OnOpenAlbumClicked);
|
openAlbumButton.onClick.RemoveListener(OnOpenAlbumClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log("ALBUM: CardAlbumDestroyed");
|
Logging.Debug("ALBUM: CardAlbumDestroyed");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnOpenAlbumClicked()
|
private void OnOpenAlbumClicked()
|
||||||
@@ -70,11 +71,8 @@ namespace UI.CardSystem
|
|||||||
if (albumViewPage != null)
|
if (albumViewPage != null)
|
||||||
{
|
{
|
||||||
UIPageController.Instance.PushPage(albumViewPage);
|
UIPageController.Instance.PushPage(albumViewPage);
|
||||||
PlayerHudManager.Instance.appSwitcher.SetActive(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PlayerHudManager.Instance.ToggleAppSwitcher(false);
|
|
||||||
// If we're already on the album main page, do nothing
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPageChanged(UIPage currentPage)
|
private void OnPageChanged(UIPage currentPage)
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ namespace UI.CardSystem
|
|||||||
{
|
{
|
||||||
if (editorCardDefinition == null)
|
if (editorCardDefinition == null)
|
||||||
{
|
{
|
||||||
UnityEngine.Debug.LogWarning("[CardDisplay] No Card Definition assigned in Editor Tools.");
|
Debug.LogWarning("[CardDisplay] No Card Definition assigned in Editor Tools.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using AppleHills.Data.CardSystem;
|
using AppleHills.Data.CardSystem;
|
||||||
|
using Core;
|
||||||
using Data.CardSystem;
|
using Data.CardSystem;
|
||||||
using Pixelplacement;
|
using Pixelplacement;
|
||||||
using UI.DragAndDrop.Core;
|
using UI.DragAndDrop.Core;
|
||||||
@@ -63,15 +64,15 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void RevealCard()
|
public void RevealCard()
|
||||||
{
|
{
|
||||||
if (_isRevealed) return;
|
if (_isRevealed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
_isRevealed = true;
|
_isRevealed = true;
|
||||||
|
|
||||||
if (flippableCard != null)
|
if (flippableCard != null)
|
||||||
{
|
{
|
||||||
flippableCard.FlipToReveal();
|
flippableCard.FlipToReveal();
|
||||||
}
|
}
|
||||||
|
|
||||||
OnCardRevealed?.Invoke(this, _cardData);
|
OnCardRevealed?.Invoke(this, _cardData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +83,7 @@ namespace UI.CardSystem
|
|||||||
{
|
{
|
||||||
if (_cardData == null)
|
if (_cardData == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[AlbumCardPlacementDraggable] Cannot snap to slot - no card data assigned.");
|
Logging.Warning("[AlbumCardPlacementDraggable] Cannot snap to slot - no card data assigned.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +118,7 @@ namespace UI.CardSystem
|
|||||||
TweenExtractedCardToSlot(extractedCard, () =>
|
TweenExtractedCardToSlot(extractedCard, () =>
|
||||||
{
|
{
|
||||||
// After animation completes
|
// After animation completes
|
||||||
Debug.Log($"[AlbumCardPlacementDraggable] Card placement animation complete for {_cardData.Name}");
|
Logging.Debug($"[AlbumCardPlacementDraggable] Card placement animation complete for {_cardData.Name}");
|
||||||
|
|
||||||
// Notify that card was placed
|
// Notify that card was placed
|
||||||
OnCardPlacedInAlbum?.Invoke(this, _cardData);
|
OnCardPlacedInAlbum?.Invoke(this, _cardData);
|
||||||
@@ -128,13 +129,13 @@ namespace UI.CardSystem
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[AlbumCardPlacementDraggable] Failed to extract AlbumCard from wrapper!");
|
Logging.Warning("[AlbumCardPlacementDraggable] Failed to extract AlbumCard from wrapper!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[AlbumCardPlacementDraggable] Could not find matching slot for card '{_cardData.Name}' (Zone: {_cardData.Zone}, Index: {_cardData.CollectionIndex})");
|
Logging.Warning($"[AlbumCardPlacementDraggable] Could not find matching slot for card '{_cardData.Name}' (Zone: {_cardData.Zone}, Index: {_cardData.CollectionIndex})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +163,7 @@ namespace UI.CardSystem
|
|||||||
Tween.LocalRotation(cardTransform, Quaternion.identity, snapDuration, 0f, Tween.EaseOutBack,
|
Tween.LocalRotation(cardTransform, Quaternion.identity, snapDuration, 0f, Tween.EaseOutBack,
|
||||||
completeCallback: () =>
|
completeCallback: () =>
|
||||||
{
|
{
|
||||||
Debug.Log($"[AlbumCardPlacementDraggable] Tween complete for extracted card {card.name}, final height: {cardRect.sizeDelta.y}");
|
Logging.Debug($"[AlbumCardPlacementDraggable] Tween complete for extracted card {card.name}, final height: {cardRect.sizeDelta.y}");
|
||||||
onComplete?.Invoke();
|
onComplete?.Invoke();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -191,9 +192,6 @@ namespace UI.CardSystem
|
|||||||
protected override void OnPointerUpHook(bool longPress)
|
protected override void OnPointerUpHook(bool longPress)
|
||||||
{
|
{
|
||||||
base.OnPointerUpHook(longPress);
|
base.OnPointerUpHook(longPress);
|
||||||
|
|
||||||
Debug.Log($"[CLICK-TRACE-PLACEMENT] OnPointerUpHook on {name}, _wasDragged={_wasDragged}, _isRevealed={_isRevealed}, _waitingForPlacementTap={_waitingForPlacementTap}, longPress={longPress}");
|
|
||||||
|
|
||||||
_isHolding = false;
|
_isHolding = false;
|
||||||
|
|
||||||
// Cancel hold timer if running
|
// Cancel hold timer if running
|
||||||
@@ -202,40 +200,35 @@ namespace UI.CardSystem
|
|||||||
StopCoroutine(_holdRevealCoroutine);
|
StopCoroutine(_holdRevealCoroutine);
|
||||||
_holdRevealCoroutine = null;
|
_holdRevealCoroutine = null;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Handle tap (not dragged)
|
// Handle tap (not dragged)
|
||||||
if (!_wasDragged)
|
if (!_wasDragged)
|
||||||
{
|
{
|
||||||
if (!_isRevealed)
|
if (!_isRevealed)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-PLACEMENT] {name} - First tap, revealing card");
|
|
||||||
// First tap: reveal the card
|
// First tap: reveal the card
|
||||||
RevealCard();
|
RevealCard();
|
||||||
_waitingForPlacementTap = true;
|
_waitingForPlacementTap = true;
|
||||||
}
|
}
|
||||||
else if (_waitingForPlacementTap)
|
else if (_waitingForPlacementTap)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-PLACEMENT] {name} - Second tap, snapping to slot");
|
|
||||||
// Second tap: snap to slot
|
// Second tap: snap to slot
|
||||||
_waitingForPlacementTap = false;
|
_waitingForPlacementTap = false;
|
||||||
SnapToAlbumSlot();
|
SnapToAlbumSlot();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-PLACEMENT] {name} - Tap after reveal but not waiting for placement tap");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_isDragRevealing)
|
else if (_isDragRevealing)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-PLACEMENT] {name} - Was drag-revealed, auto-snapping");
|
|
||||||
// Was drag-revealed, auto-snap on release
|
// Was drag-revealed, auto-snap on release
|
||||||
_isDragRevealing = false;
|
_isDragRevealing = false;
|
||||||
SnapToAlbumSlot();
|
SnapToAlbumSlot();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.Log($"[CLICK-TRACE-PLACEMENT] {name} - Was dragged but no special handling");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -250,7 +243,6 @@ namespace UI.CardSystem
|
|||||||
{
|
{
|
||||||
RevealCard();
|
RevealCard();
|
||||||
_isDragRevealing = true;
|
_isDragRevealing = true;
|
||||||
Debug.Log("[AlbumCardDraggable] Card revealed via hold");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_holdRevealCoroutine = null;
|
_holdRevealCoroutine = null;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using AppleHills.Data.CardSystem;
|
using AppleHills.Data.CardSystem;
|
||||||
|
using Core;
|
||||||
using Data.CardSystem;
|
using Data.CardSystem;
|
||||||
using UI.DragAndDrop.Core;
|
using UI.DragAndDrop.Core;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -72,7 +73,7 @@ namespace UI.CardSystem
|
|||||||
albumCard.SetParentSlot(this);
|
albumCard.SetParentSlot(this);
|
||||||
|
|
||||||
// Register with AlbumViewPage for enlarge/shrink handling
|
// Register with AlbumViewPage for enlarge/shrink handling
|
||||||
AlbumViewPage albumPage = FindObjectOfType<AlbumViewPage>();
|
AlbumViewPage albumPage = FindFirstObjectByType<AlbumViewPage>();
|
||||||
if (albumPage != null)
|
if (albumPage != null)
|
||||||
{
|
{
|
||||||
albumPage.RegisterAlbumCard(albumCard);
|
albumPage.RegisterAlbumCard(albumCard);
|
||||||
@@ -133,7 +134,7 @@ namespace UI.CardSystem
|
|||||||
// Keep preview hidden - it'll show when user taps to enlarge
|
// Keep preview hidden - it'll show when user taps to enlarge
|
||||||
previewCardDisplay.gameObject.SetActive(false);
|
previewCardDisplay.gameObject.SetActive(false);
|
||||||
|
|
||||||
Debug.Log($"[AlbumCardSlot] Setup preview card for {targetCardDefinition.Name} (hidden until tap)");
|
Logging.Debug($"[AlbumCardSlot] Setup preview card for {targetCardDefinition.Name} (hidden until tap)");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -152,7 +153,7 @@ namespace UI.CardSystem
|
|||||||
// Guard: need prefab to spawn
|
// Guard: need prefab to spawn
|
||||||
if (albumCardPrefab == null)
|
if (albumCardPrefab == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[AlbumCardSlot] No albumCardPrefab assigned for slot targeting {targetCardDefinition.name}");
|
Logging.Warning($"[AlbumCardSlot] No albumCardPrefab assigned for slot targeting {targetCardDefinition.name}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,17 +208,17 @@ namespace UI.CardSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register with AlbumViewPage for enlarge/shrink handling
|
// Register with AlbumViewPage for enlarge/shrink handling
|
||||||
AlbumViewPage albumPage = FindObjectOfType<AlbumViewPage>();
|
AlbumViewPage albumPage = FindFirstObjectByType<AlbumViewPage>();
|
||||||
if (albumPage != null)
|
if (albumPage != null)
|
||||||
{
|
{
|
||||||
albumPage.RegisterAlbumCard(albumCard);
|
albumPage.RegisterAlbumCard(albumCard);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[AlbumCardSlot] Spawned owned card '{cardData.Name}' ({cardData.Rarity}) in slot");
|
Logging.Debug($"[AlbumCardSlot] Spawned owned card '{cardData.Name}' ({cardData.Rarity}) in slot");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[AlbumCardSlot] Spawned prefab has no AlbumCard component!");
|
Logging.Warning($"[AlbumCardSlot] Spawned prefab has no AlbumCard component!");
|
||||||
Destroy(cardObj);
|
Destroy(cardObj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,30 +236,30 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void OnPointerClick(PointerEventData eventData)
|
public void OnPointerClick(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-SLOT] OnPointerClick on {name}, _isOccupiedPermanently={_isOccupiedPermanently}, _placedCard={((_placedCard != null) ? _placedCard.name : "NULL")}, _isPreviewShowing={_isPreviewShowing}, position={eventData.position}");
|
Logging.Debug($"[CLICK-TRACE-SLOT] OnPointerClick on {name}, _isOccupiedPermanently={_isOccupiedPermanently}, _placedCard={((_placedCard != null) ? _placedCard.name : "NULL")}, _isPreviewShowing={_isPreviewShowing}, position={eventData.position}");
|
||||||
|
|
||||||
// Only handle clicks if slot is empty
|
// Only handle clicks if slot is empty
|
||||||
if (_isOccupiedPermanently || _placedCard != null)
|
if (_isOccupiedPermanently || _placedCard != null)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-SLOT] {name} - Slot is occupied, ignoring");
|
Logging.Debug($"[CLICK-TRACE-SLOT] {name} - Slot is occupied, ignoring");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only handle if we have a preview card setup
|
// Only handle if we have a preview card setup
|
||||||
if (previewCardDisplay == null || targetCardDefinition == null)
|
if (previewCardDisplay == null || targetCardDefinition == null)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-SLOT] {name} - No preview setup, ignoring");
|
Logging.Debug($"[CLICK-TRACE-SLOT] {name} - No preview setup, ignoring");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_isPreviewShowing)
|
if (_isPreviewShowing)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-SLOT] {name} - Preview is showing, hiding it");
|
Logging.Debug($"[CLICK-TRACE-SLOT] {name} - Preview is showing, hiding it");
|
||||||
HidePreview();
|
HidePreview();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-SLOT] {name} - Preview is hidden, showing it");
|
Logging.Debug($"[CLICK-TRACE-SLOT] {name} - Preview is hidden, showing it");
|
||||||
ShowPreview();
|
ShowPreview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,7 +284,7 @@ namespace UI.CardSystem
|
|||||||
previewCardDisplay.transform.localScale = _previewOriginalScale;
|
previewCardDisplay.transform.localScale = _previewOriginalScale;
|
||||||
|
|
||||||
// Get AlbumViewPage to show backdrop and reparent
|
// Get AlbumViewPage to show backdrop and reparent
|
||||||
AlbumViewPage albumPage = FindObjectOfType<AlbumViewPage>();
|
AlbumViewPage albumPage = FindFirstObjectByType<AlbumViewPage>();
|
||||||
if (albumPage != null)
|
if (albumPage != null)
|
||||||
{
|
{
|
||||||
albumPage.ShowSlotPreview(this, previewCardDisplay.transform);
|
albumPage.ShowSlotPreview(this, previewCardDisplay.transform);
|
||||||
@@ -293,7 +294,7 @@ namespace UI.CardSystem
|
|||||||
Pixelplacement.Tween.LocalScale(previewCardDisplay.transform, _previewOriginalScale * previewEnlargedScale,
|
Pixelplacement.Tween.LocalScale(previewCardDisplay.transform, _previewOriginalScale * previewEnlargedScale,
|
||||||
previewScaleDuration, 0f, Pixelplacement.Tween.EaseOutBack);
|
previewScaleDuration, 0f, Pixelplacement.Tween.EaseOutBack);
|
||||||
|
|
||||||
Debug.Log($"[AlbumCardSlot] Showing preview for {targetCardDefinition.Name}");
|
Logging.Debug($"[AlbumCardSlot] Showing preview for {targetCardDefinition.Name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -310,7 +311,7 @@ namespace UI.CardSystem
|
|||||||
previewCardDisplay.SetPreviewMode(false, null);
|
previewCardDisplay.SetPreviewMode(false, null);
|
||||||
|
|
||||||
// Get AlbumViewPage to hide backdrop
|
// Get AlbumViewPage to hide backdrop
|
||||||
AlbumViewPage albumPage = FindObjectOfType<AlbumViewPage>();
|
AlbumViewPage albumPage = FindFirstObjectByType<AlbumViewPage>();
|
||||||
if (albumPage != null)
|
if (albumPage != null)
|
||||||
{
|
{
|
||||||
albumPage.HideSlotPreview(this, previewCardDisplay.transform, () =>
|
albumPage.HideSlotPreview(this, previewCardDisplay.transform, () =>
|
||||||
@@ -340,11 +341,11 @@ namespace UI.CardSystem
|
|||||||
// Hide the preview card after returning to slot
|
// Hide the preview card after returning to slot
|
||||||
previewCardDisplay.gameObject.SetActive(false);
|
previewCardDisplay.gameObject.SetActive(false);
|
||||||
|
|
||||||
Debug.Log($"[AlbumCardSlot] Preview hidden and reset for {targetCardDefinition.Name}");
|
Logging.Debug($"[AlbumCardSlot] Preview hidden and reset for {targetCardDefinition.Name}");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[AlbumCardSlot] Hiding preview for {targetCardDefinition.Name}");
|
Logging.Debug($"[AlbumCardSlot] Hiding preview for {targetCardDefinition.Name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -352,7 +353,7 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void DismissPreview()
|
public void DismissPreview()
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-SLOT] DismissPreview called on {name}");
|
Logging.Debug($"[CLICK-TRACE-SLOT] DismissPreview called on {name}");
|
||||||
HidePreview();
|
HidePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using UI.DragAndDrop.Core;
|
using Core;
|
||||||
|
using UI.DragAndDrop.Core;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UI.CardSystem.DragDrop
|
namespace UI.CardSystem.DragDrop
|
||||||
@@ -127,10 +128,10 @@ namespace UI.CardSystem.DragDrop
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetInOpeningSlot(bool inSlot)
|
public void SetInOpeningSlot(bool inSlot)
|
||||||
{
|
{
|
||||||
Debug.Log($"[BoosterPackDraggable] SetInOpeningSlot({inSlot}) called on {name}");
|
Logging.Debug($"[BoosterPackDraggable] SetInOpeningSlot({inSlot}) called on {name}");
|
||||||
|
|
||||||
SetDraggingEnabled(!inSlot); // Disable dragging when in opening slot
|
SetDraggingEnabled(!inSlot); // Disable dragging when in opening slot
|
||||||
Debug.Log($"[BoosterPackDraggable] SetDraggingEnabled({!inSlot}) called");
|
Logging.Debug($"[BoosterPackDraggable] SetDraggingEnabled({!inSlot}) called");
|
||||||
|
|
||||||
canTapToOpen = inSlot; // Enable tap-to-open when in opening slot
|
canTapToOpen = inSlot; // Enable tap-to-open when in opening slot
|
||||||
|
|
||||||
|
|||||||
@@ -308,10 +308,8 @@ namespace UI.CardSystem.DragDrop
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
protected override void OnDestroy()
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
if (_boosterDraggable != null)
|
if (_boosterDraggable != null)
|
||||||
{
|
{
|
||||||
_boosterDraggable.OnBoosterOpened -= HandleBoosterOpened;
|
_boosterDraggable.OnBoosterOpened -= HandleBoosterOpened;
|
||||||
|
|||||||
@@ -107,10 +107,8 @@ namespace UI.CardSystem.DragDrop
|
|||||||
// Card-specific visual effects when dragging ends
|
// Card-specific visual effects when dragging ends
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
if (_cardDraggable != null)
|
if (_cardDraggable != null)
|
||||||
{
|
{
|
||||||
_cardDraggable.OnCardDataChanged -= HandleCardDataChanged;
|
_cardDraggable.OnCardDataChanged -= HandleCardDataChanged;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using AppleHills.Data.CardSystem;
|
using AppleHills.Data.CardSystem;
|
||||||
|
using Core;
|
||||||
using Pixelplacement;
|
using Pixelplacement;
|
||||||
using Pixelplacement.TweenSystem;
|
using Pixelplacement.TweenSystem;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -40,7 +41,6 @@ namespace UI.CardSystem
|
|||||||
// State
|
// State
|
||||||
private bool _isFlipped = false;
|
private bool _isFlipped = false;
|
||||||
private bool _isFlipping = false;
|
private bool _isFlipping = false;
|
||||||
private bool _isHovering = false;
|
|
||||||
private TweenBase _idleHoverTween;
|
private TweenBase _idleHoverTween;
|
||||||
private CardData _cardData;
|
private CardData _cardData;
|
||||||
private Vector2 _originalPosition; // Track original spawn position
|
private Vector2 _originalPosition; // Track original spawn position
|
||||||
@@ -241,8 +241,6 @@ namespace UI.CardSystem
|
|||||||
if (_isFlipped || _isFlipping)
|
if (_isFlipped || _isFlipping)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_isHovering = true;
|
|
||||||
|
|
||||||
// Scale up slightly on hover
|
// Scale up slightly on hover
|
||||||
Tween.LocalScale(transform, Vector3.one * hoverScaleMultiplier, 0.2f, 0f, Tween.EaseOutBack);
|
Tween.LocalScale(transform, Vector3.one * hoverScaleMultiplier, 0.2f, 0f, Tween.EaseOutBack);
|
||||||
}
|
}
|
||||||
@@ -252,20 +250,18 @@ namespace UI.CardSystem
|
|||||||
if (_isFlipped || _isFlipping)
|
if (_isFlipped || _isFlipping)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_isHovering = false;
|
|
||||||
|
|
||||||
// Scale back to normal
|
// Scale back to normal
|
||||||
Tween.LocalScale(transform, Vector3.one, 0.2f, 0f, Tween.EaseOutBack);
|
Tween.LocalScale(transform, Vector3.one, 0.2f, 0f, Tween.EaseOutBack);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnPointerClick(PointerEventData eventData)
|
public void OnPointerClick(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-FLIPPABLE] OnPointerClick on {name}, _isClickable={_isClickable}, _isWaitingForTap={_isWaitingForTap}, _isFlipped={_isFlipped}, position={eventData.position}");
|
Logging.Debug($"[CLICK-TRACE-FLIPPABLE] OnPointerClick on {name}, _isClickable={_isClickable}, _isWaitingForTap={_isWaitingForTap}, _isFlipped={_isFlipped}, position={eventData.position}");
|
||||||
|
|
||||||
// If not clickable, notify and return
|
// If not clickable, notify and return
|
||||||
if (!_isClickable)
|
if (!_isClickable)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-FLIPPABLE] {name} - Not clickable, firing OnClickedWhileInactive");
|
Logging.Debug($"[CLICK-TRACE-FLIPPABLE] {name} - Not clickable, firing OnClickedWhileInactive");
|
||||||
OnClickedWhileInactive?.Invoke(this);
|
OnClickedWhileInactive?.Invoke(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -273,7 +269,7 @@ namespace UI.CardSystem
|
|||||||
// If waiting for tap after reveal, handle that
|
// If waiting for tap after reveal, handle that
|
||||||
if (_isWaitingForTap)
|
if (_isWaitingForTap)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-FLIPPABLE] {name} - Waiting for tap, dismissing enlarged state");
|
Logging.Debug($"[CLICK-TRACE-FLIPPABLE] {name} - Waiting for tap, dismissing enlarged state");
|
||||||
OnCardTappedAfterReveal?.Invoke(this);
|
OnCardTappedAfterReveal?.Invoke(this);
|
||||||
_isWaitingForTap = false;
|
_isWaitingForTap = false;
|
||||||
return;
|
return;
|
||||||
@@ -281,11 +277,11 @@ namespace UI.CardSystem
|
|||||||
|
|
||||||
if (_isFlipped || _isFlipping)
|
if (_isFlipped || _isFlipping)
|
||||||
{
|
{
|
||||||
Debug.Log($"[CLICK-TRACE-FLIPPABLE] {name} - Ignoring click (flipped={_isFlipped}, flipping={_isFlipping})");
|
Logging.Debug($"[CLICK-TRACE-FLIPPABLE] {name} - Ignoring click (flipped={_isFlipped}, flipping={_isFlipping})");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[CLICK-TRACE-FLIPPABLE] {name} - Processing click, starting flip");
|
Logging.Debug($"[CLICK-TRACE-FLIPPABLE] {name} - Processing click, starting flip");
|
||||||
// Flip on click
|
// Flip on click
|
||||||
FlipToReveal();
|
FlipToReveal();
|
||||||
}
|
}
|
||||||
@@ -341,7 +337,7 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void TriggerUpgradeTransition(AppleHills.Data.CardSystem.CardData lowerRarityCard)
|
private void TriggerUpgradeTransition(AppleHills.Data.CardSystem.CardData lowerRarityCard)
|
||||||
{
|
{
|
||||||
Debug.Log($"[FlippableCard] Triggering upgrade transition from {lowerRarityCard.Rarity}!");
|
Logging.Debug($"[FlippableCard] Triggering upgrade transition from {lowerRarityCard.Rarity}!");
|
||||||
|
|
||||||
AppleHills.Data.CardSystem.CardRarity oldRarity = lowerRarityCard.Rarity;
|
AppleHills.Data.CardSystem.CardRarity oldRarity = lowerRarityCard.Rarity;
|
||||||
AppleHills.Data.CardSystem.CardRarity newRarity = oldRarity + 1;
|
AppleHills.Data.CardSystem.CardRarity newRarity = oldRarity + 1;
|
||||||
@@ -429,7 +425,7 @@ namespace UI.CardSystem
|
|||||||
if (newCardText != null)
|
if (newCardText != null)
|
||||||
newCardText.SetActive(true);
|
newCardText.SetActive(true);
|
||||||
|
|
||||||
Debug.Log($"[FlippableCard] Card upgraded from {oldRarity} to {newRarity}! Showing as NEW.");
|
Logging.Debug($"[FlippableCard] Card upgraded from {oldRarity} to {newRarity}! Showing as NEW.");
|
||||||
|
|
||||||
// Card is already enlarged from the repeat display, so no need to enlarge again
|
// Card is already enlarged from the repeat display, so no need to enlarge again
|
||||||
}
|
}
|
||||||
@@ -457,7 +453,7 @@ namespace UI.CardSystem
|
|||||||
TransitionToNewCardView(newRarity);
|
TransitionToNewCardView(newRarity);
|
||||||
});
|
});
|
||||||
|
|
||||||
Debug.Log($"[FlippableCard] Card upgraded from {oldRarity} to {newRarity}! Showing progress {ownedAtNewRarity}/5");
|
Logging.Debug($"[FlippableCard] Card upgraded from {oldRarity} to {newRarity}! Showing progress {ownedAtNewRarity}/5");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -465,7 +461,7 @@ namespace UI.CardSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void TransitionToNewCardView(AppleHills.Data.CardSystem.CardRarity newRarity)
|
private void TransitionToNewCardView(AppleHills.Data.CardSystem.CardRarity newRarity)
|
||||||
{
|
{
|
||||||
Debug.Log($"[FlippableCard] Transitioning to NEW CARD view at {newRarity} rarity");
|
Logging.Debug($"[FlippableCard] Transitioning to NEW CARD view at {newRarity} rarity");
|
||||||
|
|
||||||
// Update the CardDisplay to show new rarity
|
// Update the CardDisplay to show new rarity
|
||||||
if (cardDisplay != null && _cardData != null)
|
if (cardDisplay != null && _cardData != null)
|
||||||
@@ -488,7 +484,7 @@ namespace UI.CardSystem
|
|||||||
_isNew = true;
|
_isNew = true;
|
||||||
_isWaitingForTap = true;
|
_isWaitingForTap = true;
|
||||||
|
|
||||||
Debug.Log($"[FlippableCard] Now showing as NEW CARD at {newRarity}, waiting for tap");
|
Logging.Debug($"[FlippableCard] Now showing as NEW CARD at {newRarity}, waiting for tap");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -538,7 +534,7 @@ namespace UI.CardSystem
|
|||||||
// Check if we have the required number of elements (should match cardsToUpgrade)
|
// Check if we have the required number of elements (should match cardsToUpgrade)
|
||||||
if (progressElements.Length < cardsToUpgrade)
|
if (progressElements.Length < cardsToUpgrade)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[FlippableCard] Not enough Image components in progress bar! Expected {cardsToUpgrade}, found {progressElements.Length}");
|
Logging.Warning($"[FlippableCard] Not enough Image components in progress bar! Expected {cardsToUpgrade}, found {progressElements.Length}");
|
||||||
onComplete?.Invoke();
|
onComplete?.Invoke();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -647,7 +643,7 @@ namespace UI.CardSystem
|
|||||||
{
|
{
|
||||||
if (albumCard == null)
|
if (albumCard == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[FlippableCard] Cannot extract AlbumCard - none found!");
|
Logging.Warning("[FlippableCard] Cannot extract AlbumCard - none found!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,7 +657,7 @@ namespace UI.CardSystem
|
|||||||
albumCard.SetupCard(_cardData);
|
albumCard.SetupCard(_cardData);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[FlippableCard] Extracted AlbumCard '{_cardData?.Name}' to {newParent.name} - ready for tween");
|
Logging.Debug($"[FlippableCard] Extracted AlbumCard '{_cardData?.Name}' to {newParent.name} - ready for tween");
|
||||||
|
|
||||||
return albumCard;
|
return albumCard;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using Core;
|
||||||
using Data.CardSystem;
|
using Data.CardSystem;
|
||||||
using Pixelplacement;
|
using Pixelplacement;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -10,7 +11,8 @@ namespace UI.CardSystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Singleton UI component for granting booster packs from minigames.
|
/// Singleton UI component for granting booster packs from minigames.
|
||||||
/// Displays a booster pack with glow effect, waits for user to click continue,
|
/// Displays a booster pack with glow effect, waits for user to click continue,
|
||||||
/// then animates the pack flying to bottom-left corner before granting the reward.
|
/// then shows the scrapbook button and animates the pack flying to it before granting the reward.
|
||||||
|
/// The scrapbook button is automatically hidden after the animation completes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MinigameBoosterGiver : MonoBehaviour
|
public class MinigameBoosterGiver : MonoBehaviour
|
||||||
{
|
{
|
||||||
@@ -25,7 +27,6 @@ namespace UI.CardSystem
|
|||||||
[Header("Animation Settings")]
|
[Header("Animation Settings")]
|
||||||
[SerializeField] private float hoverAmount = 20f;
|
[SerializeField] private float hoverAmount = 20f;
|
||||||
[SerializeField] private float hoverDuration = 1.5f;
|
[SerializeField] private float hoverDuration = 1.5f;
|
||||||
[SerializeField] private float glowPulseMin = 0.9f;
|
|
||||||
[SerializeField] private float glowPulseMax = 1.1f;
|
[SerializeField] private float glowPulseMax = 1.1f;
|
||||||
[SerializeField] private float glowPulseDuration = 1.2f;
|
[SerializeField] private float glowPulseDuration = 1.2f;
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@ namespace UI.CardSystem
|
|||||||
// Singleton pattern
|
// Singleton pattern
|
||||||
if (Instance != null && Instance != this)
|
if (Instance != null && Instance != this)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[MinigameBoosterGiver] Duplicate instance found. Destroying.");
|
Logging.Warning("[MinigameBoosterGiver] Duplicate instance found. Destroying.");
|
||||||
Destroy(gameObject);
|
Destroy(gameObject);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -98,7 +99,7 @@ namespace UI.CardSystem
|
|||||||
{
|
{
|
||||||
if (_currentSequence != null)
|
if (_currentSequence != null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[MinigameBoosterGiver] Already running a sequence. Ignoring new request.");
|
Logging.Warning("[MinigameBoosterGiver] Already running a sequence. Ignoring new request.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,23 +188,61 @@ namespace UI.CardSystem
|
|||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate bottom-left corner position in local space
|
// Show scrapbook button temporarily using HUD visibility context
|
||||||
RectTransform canvasRect = GetComponentInParent<Canvas>()?.GetComponent<RectTransform>();
|
PlayerHudManager.HudVisibilityContext hudContext = null;
|
||||||
Vector3 targetPosition;
|
GameObject scrapbookButton = null;
|
||||||
|
|
||||||
if (canvasRect != null)
|
scrapbookButton = PlayerHudManager.Instance.GetScrabookButton();
|
||||||
|
if (scrapbookButton != null)
|
||||||
{
|
{
|
||||||
// Convert bottom-left corner with offset to local position
|
hudContext = PlayerHudManager.Instance.ShowElementTemporarily(scrapbookButton);
|
||||||
Vector2 bottomLeft = new Vector2(-canvasRect.rect.width / 2f, -canvasRect.rect.height / 2f);
|
|
||||||
targetPosition = bottomLeft + targetBottomLeftOffset;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Fallback if no canvas found
|
Logging.Warning("[MinigameBoosterGiver] Scrapbook button not found in PlayerHudManager.");
|
||||||
targetPosition = _boosterInitialPosition + new Vector3(-500f, -500f, 0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tween to bottom-left corner
|
// Calculate target position - use scrapbook button position if available
|
||||||
|
Vector3 targetPosition;
|
||||||
|
|
||||||
|
if (scrapbookButton != null)
|
||||||
|
{
|
||||||
|
// Get the scrapbook button's position in the same coordinate space as boosterImage
|
||||||
|
RectTransform scrapbookRect = scrapbookButton.GetComponent<RectTransform>();
|
||||||
|
if (scrapbookRect != null)
|
||||||
|
{
|
||||||
|
// Convert scrapbook button's world position to local position relative to boosterImage's parent
|
||||||
|
Canvas canvas = GetComponentInParent<Canvas>();
|
||||||
|
if (canvas != null && canvas.renderMode == RenderMode.ScreenSpaceOverlay)
|
||||||
|
{
|
||||||
|
// For overlay canvas, convert screen position to local position
|
||||||
|
Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(null, scrapbookRect.position);
|
||||||
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||||
|
boosterImage.parent as RectTransform,
|
||||||
|
screenPos,
|
||||||
|
null,
|
||||||
|
out Vector2 localPoint);
|
||||||
|
targetPosition = localPoint;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For world space or camera canvas
|
||||||
|
targetPosition = boosterImage.parent.InverseTransformPoint(scrapbookRect.position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logging.Warning("[MinigameBoosterGiver] Scrapbook button has no RectTransform, using fallback position.");
|
||||||
|
targetPosition = GetFallbackPosition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Fallback to bottom-left corner
|
||||||
|
targetPosition = GetFallbackPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tween to scrapbook button position
|
||||||
Tween.LocalPosition(boosterImage, targetPosition, disappearDuration, 0f, Tween.EaseInBack);
|
Tween.LocalPosition(boosterImage, targetPosition, disappearDuration, 0f, Tween.EaseInBack);
|
||||||
|
|
||||||
// Scale down
|
// Scale down
|
||||||
@@ -217,13 +256,16 @@ namespace UI.CardSystem
|
|||||||
if (CardSystemManager.Instance != null)
|
if (CardSystemManager.Instance != null)
|
||||||
{
|
{
|
||||||
CardSystemManager.Instance.AddBoosterPack(1);
|
CardSystemManager.Instance.AddBoosterPack(1);
|
||||||
Debug.Log("[MinigameBoosterGiver] Booster pack granted!");
|
Logging.Debug("[MinigameBoosterGiver] Booster pack granted!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[MinigameBoosterGiver] CardSystemManager not found, cannot grant booster pack.");
|
Logging.Warning("[MinigameBoosterGiver] CardSystemManager not found, cannot grant booster pack.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hide scrapbook button by disposing the context
|
||||||
|
hudContext?.Dispose();
|
||||||
|
|
||||||
// Hide the visual
|
// Hide the visual
|
||||||
if (visualContainer != null)
|
if (visualContainer != null)
|
||||||
{
|
{
|
||||||
@@ -237,6 +279,22 @@ namespace UI.CardSystem
|
|||||||
// Clear sequence reference
|
// Clear sequence reference
|
||||||
_currentSequence = null;
|
_currentSequence = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Vector3 GetFallbackPosition()
|
||||||
|
{
|
||||||
|
RectTransform canvasRect = GetComponentInParent<Canvas>()?.GetComponent<RectTransform>();
|
||||||
|
if (canvasRect != null)
|
||||||
|
{
|
||||||
|
// Convert bottom-left corner with offset to local position
|
||||||
|
Vector2 bottomLeft = new Vector2(-canvasRect.rect.width / 2f, -canvasRect.rect.height / 2f);
|
||||||
|
return bottomLeft + targetBottomLeftOffset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Ultimate fallback if no canvas found
|
||||||
|
return _boosterInitialPosition + new Vector3(-500f, -500f, 0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UI.DragAndDrop.Core;
|
using Core;
|
||||||
|
using UI.DragAndDrop.Core;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UI.CardSystem
|
namespace UI.CardSystem
|
||||||
@@ -22,7 +23,7 @@ namespace UI.CardSystem
|
|||||||
if (container == null || objects == null || objects.Count == 0)
|
if (container == null || objects == null || objects.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug.Log($"[SlotContainerHelper] Shuffling {objects.Count} objects to front slots");
|
Logging.Debug($"[SlotContainerHelper] Shuffling {objects.Count} objects to front slots");
|
||||||
|
|
||||||
// Unassign all objects from their current slots
|
// Unassign all objects from their current slots
|
||||||
foreach (var obj in objects)
|
foreach (var obj in objects)
|
||||||
@@ -41,12 +42,12 @@ namespace UI.CardSystem
|
|||||||
|
|
||||||
if (targetSlot != null)
|
if (targetSlot != null)
|
||||||
{
|
{
|
||||||
Debug.Log($"[SlotContainerHelper] Assigning object to slot with SlotIndex {i}");
|
Logging.Debug($"[SlotContainerHelper] Assigning object to slot with SlotIndex {i}");
|
||||||
obj.AssignToSlot(targetSlot, animate);
|
obj.AssignToSlot(targetSlot, animate);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[SlotContainerHelper] Could not find slot with SlotIndex {i}");
|
Logging.Warning($"[SlotContainerHelper] Could not find slot with SlotIndex {i}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,6 @@ namespace UI.Core
|
|||||||
[Header("Page Settings")]
|
[Header("Page Settings")]
|
||||||
public string PageName;
|
public string PageName;
|
||||||
|
|
||||||
// UI pages load after UI infrastructure (UIPageController is priority 50)
|
|
||||||
public override int ManagedAwakePriority => 200;
|
|
||||||
|
|
||||||
// Events using System.Action instead of UnityEvents
|
// Events using System.Action instead of UnityEvents
|
||||||
public event Action OnTransitionInStarted;
|
public event Action OnTransitionInStarted;
|
||||||
public event Action OnTransitionInCompleted;
|
public event Action OnTransitionInCompleted;
|
||||||
|
|||||||
@@ -37,25 +37,19 @@ namespace UI.Core
|
|||||||
private PlayerInput _playerInput;
|
private PlayerInput _playerInput;
|
||||||
private InputAction _cancelAction;
|
private InputAction _cancelAction;
|
||||||
|
|
||||||
public override int ManagedAwakePriority => 50; // UI infrastructure
|
internal override void OnManagedAwake()
|
||||||
|
|
||||||
private new void Awake()
|
|
||||||
{
|
{
|
||||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
// Set instance immediately (early initialization)
|
||||||
|
|
||||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
Logging.Debug("[UIPageController] Initialized");
|
Logging.Debug("[UIPageController] Initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
// Clean up cached instances
|
// Clean up cached instances
|
||||||
foreach (var cachedPage in _prefabInstanceCache.Values)
|
foreach (var cachedPage in _prefabInstanceCache.Values)
|
||||||
{
|
{
|
||||||
@@ -190,23 +184,35 @@ namespace UI.Core
|
|||||||
{
|
{
|
||||||
if (_pageStack.Count <= 0) return;
|
if (_pageStack.Count <= 0) return;
|
||||||
|
|
||||||
// Hide and pop current page
|
// Pop current page from stack
|
||||||
UIPage currentPage = _pageStack.Pop();
|
UIPage currentPage = _pageStack.Pop();
|
||||||
currentPage.TransitionOut();
|
|
||||||
|
|
||||||
// Show previous page if there is one
|
// Subscribe to transition out completion event
|
||||||
if (_pageStack.Count > 0)
|
Action onTransitionComplete = null;
|
||||||
|
onTransitionComplete = () =>
|
||||||
{
|
{
|
||||||
UIPage previousPage = _pageStack.Peek();
|
// Unsubscribe to prevent memory leaks
|
||||||
previousPage.TransitionIn();
|
currentPage.OnTransitionOutCompleted -= onTransitionComplete;
|
||||||
OnPageChanged?.Invoke(previousPage);
|
|
||||||
Logging.Debug($"[UIPageController] Popped to previous page: {previousPage.PageName}");
|
// Fire OnPageChanged AFTER transition completes
|
||||||
}
|
if (_pageStack.Count > 0)
|
||||||
else
|
{
|
||||||
{
|
UIPage previousPage = _pageStack.Peek();
|
||||||
OnPageChanged?.Invoke(null);
|
previousPage.TransitionIn();
|
||||||
Logging.Debug("[UIPageController] Popped last page, no pages left in stack");
|
OnPageChanged?.Invoke(previousPage);
|
||||||
}
|
Logging.Debug($"[UIPageController] Popped to previous page: {previousPage.PageName}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OnPageChanged?.Invoke(null);
|
||||||
|
Logging.Debug("[UIPageController] Popped last page, no pages left in stack");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
currentPage.OnTransitionOutCompleted += onTransitionComplete;
|
||||||
|
|
||||||
|
// Start the transition out animation
|
||||||
|
currentPage.TransitionOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using Core;
|
||||||
using Pixelplacement;
|
using Pixelplacement;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
@@ -79,10 +80,10 @@ namespace UI.DragAndDrop.Core
|
|||||||
|
|
||||||
protected virtual void Initialize()
|
protected virtual void Initialize()
|
||||||
{
|
{
|
||||||
Debug.Log($"[DraggableObject] Initializing {name} at world pos {transform.position}, local pos {transform.localPosition}, parent: {(transform.parent != null ? transform.parent.name : "NULL")}");
|
Logging.Debug($"[DraggableObject] Initializing {name} at world pos {transform.position}, local pos {transform.localPosition}, parent: {(transform.parent != null ? transform.parent.name : "NULL")}");
|
||||||
|
|
||||||
_canvas = GetComponentInParent<Canvas>();
|
_canvas = GetComponentInParent<Canvas>();
|
||||||
Debug.Log($"[DraggableObject] {name} found canvas: {(_canvas != null ? _canvas.name : "NULL")}, canvas pos: {(_canvas != null ? _canvas.transform.position.ToString() : "N/A")}");
|
Logging.Debug($"[DraggableObject] {name} found canvas: {(_canvas != null ? _canvas.name : "NULL")}, canvas pos: {(_canvas != null ? _canvas.transform.position.ToString() : "N/A")}");
|
||||||
|
|
||||||
_imageComponent = GetComponent<Image>();
|
_imageComponent = GetComponent<Image>();
|
||||||
_canvasGroup = GetComponent<CanvasGroup>();
|
_canvasGroup = GetComponent<CanvasGroup>();
|
||||||
@@ -95,7 +96,7 @@ namespace UI.DragAndDrop.Core
|
|||||||
_imageComponent = gameObject.AddComponent<Image>();
|
_imageComponent = gameObject.AddComponent<Image>();
|
||||||
_imageComponent.color = new Color(1, 1, 1, 0.01f); // Nearly transparent (0 doesn't work)
|
_imageComponent.color = new Color(1, 1, 1, 0.01f); // Nearly transparent (0 doesn't work)
|
||||||
_imageComponent.raycastTarget = true;
|
_imageComponent.raycastTarget = true;
|
||||||
Debug.Log($"[DraggableObject] Added invisible Image to {name} for raycast detection");
|
Logging.Debug($"[DraggableObject] Added invisible Image to {name} for raycast detection");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use assigned visual, or find in children recursively if not assigned
|
// Use assigned visual, or find in children recursively if not assigned
|
||||||
@@ -190,19 +191,19 @@ namespace UI.DragAndDrop.Core
|
|||||||
if (eventData.button != PointerEventData.InputButton.Left)
|
if (eventData.button != PointerEventData.InputButton.Left)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug.Log($"[DraggableObject] OnBeginDrag called on {name}. _isDraggingEnabled={_isDraggingEnabled}");
|
Logging.Debug($"[DraggableObject] OnBeginDrag called on {name}. _isDraggingEnabled={_isDraggingEnabled}");
|
||||||
|
|
||||||
// Check if dragging is enabled BEFORE setting any state
|
// Check if dragging is enabled BEFORE setting any state
|
||||||
if (!_isDraggingEnabled)
|
if (!_isDraggingEnabled)
|
||||||
{
|
{
|
||||||
Debug.Log($"[DraggableObject] OnBeginDrag blocked - dragging disabled on {name}");
|
Logging.Debug($"[DraggableObject] OnBeginDrag blocked - dragging disabled on {name}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_isDragging = true;
|
_isDragging = true;
|
||||||
_wasDragged = true;
|
_wasDragged = true;
|
||||||
|
|
||||||
Debug.Log($"[DraggableObject] Drag started on {name}");
|
Logging.Debug($"[DraggableObject] Drag started on {name}");
|
||||||
|
|
||||||
// ...existing code...
|
// ...existing code...
|
||||||
if (_canvas != null && _canvas.renderMode == RenderMode.ScreenSpaceOverlay && RectTransform != null)
|
if (_canvas != null && _canvas.renderMode == RenderMode.ScreenSpaceOverlay && RectTransform != null)
|
||||||
@@ -345,7 +346,7 @@ namespace UI.DragAndDrop.Core
|
|||||||
|
|
||||||
protected virtual void FindAndSnapToSlot()
|
protected virtual void FindAndSnapToSlot()
|
||||||
{
|
{
|
||||||
SlotContainer[] containers = FindObjectsOfType<SlotContainer>();
|
SlotContainer[] containers = FindObjectsByType<SlotContainer>(FindObjectsSortMode.None);
|
||||||
DraggableSlot closestSlot = null;
|
DraggableSlot closestSlot = null;
|
||||||
float closestDistance = float.MaxValue;
|
float closestDistance = float.MaxValue;
|
||||||
|
|
||||||
@@ -413,7 +414,7 @@ namespace UI.DragAndDrop.Core
|
|||||||
if (slot == null)
|
if (slot == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug.Log($"[DraggableObject] Assigning {name} to slot {slot.name}, animate={animate}, current pos={transform.position}, slot pos={slot.transform.position}");
|
Logging.Debug($"[DraggableObject] Assigning {name} to slot {slot.name}, animate={animate}, current pos={transform.position}, slot pos={slot.transform.position}");
|
||||||
|
|
||||||
DraggableSlot previousSlot = _currentSlot;
|
DraggableSlot previousSlot = _currentSlot;
|
||||||
_currentSlot = slot;
|
_currentSlot = slot;
|
||||||
@@ -429,7 +430,7 @@ namespace UI.DragAndDrop.Core
|
|||||||
transform.SetParent(slot.transform);
|
transform.SetParent(slot.transform);
|
||||||
transform.localPosition = _isSelected ? new Vector3(0, selectionOffset, 0) : Vector3.zero;
|
transform.localPosition = _isSelected ? new Vector3(0, selectionOffset, 0) : Vector3.zero;
|
||||||
transform.localRotation = Quaternion.identity;
|
transform.localRotation = Quaternion.identity;
|
||||||
Debug.Log($"[DraggableObject] {name} assigned to slot {slot.name}, new world pos={transform.position}, local pos={transform.localPosition}");
|
Logging.Debug($"[DraggableObject] {name} assigned to slot {slot.name}, new world pos={transform.position}, local pos={transform.localPosition}");
|
||||||
}
|
}
|
||||||
|
|
||||||
OnSlotChanged?.Invoke(this, slot);
|
OnSlotChanged?.Invoke(this, slot);
|
||||||
@@ -510,14 +511,14 @@ namespace UI.DragAndDrop.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void SetDraggingEnabled(bool enabled)
|
public virtual void SetDraggingEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
Debug.Log($"[DraggableObject] SetDraggingEnabled({enabled}) called on {name}. _isDragging={_isDragging}, _isDraggingEnabled={_isDraggingEnabled}");
|
Logging.Debug($"[DraggableObject] SetDraggingEnabled({enabled}) called on {name}. _isDragging={_isDragging}, _isDraggingEnabled={_isDraggingEnabled}");
|
||||||
|
|
||||||
_isDraggingEnabled = enabled;
|
_isDraggingEnabled = enabled;
|
||||||
|
|
||||||
// If disabling dragging while actively dragging, stop the drag
|
// If disabling dragging while actively dragging, stop the drag
|
||||||
if (!enabled && _isDragging)
|
if (!enabled && _isDragging)
|
||||||
{
|
{
|
||||||
Debug.Log($"[DraggableObject] Stopping active drag on {name}");
|
Logging.Debug($"[DraggableObject] Stopping active drag on {name}");
|
||||||
_isDragging = false;
|
_isDragging = false;
|
||||||
|
|
||||||
// Re-enable raycasting
|
// Re-enable raycasting
|
||||||
@@ -529,7 +530,7 @@ namespace UI.DragAndDrop.Core
|
|||||||
_canvasGroup.blocksRaycasts = true;
|
_canvasGroup.blocksRaycasts = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[DraggableObject] After SetDraggingEnabled: _isDragging={_isDragging}, _isDraggingEnabled={_isDraggingEnabled}");
|
Logging.Debug($"[DraggableObject] After SetDraggingEnabled: _isDragging={_isDragging}, _isDraggingEnabled={_isDraggingEnabled}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Pixelplacement;
|
using Core;
|
||||||
|
using Pixelplacement;
|
||||||
using Pixelplacement.TweenSystem;
|
using Pixelplacement.TweenSystem;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.InputSystem; // Added for new Input System
|
using UnityEngine.InputSystem; // Added for new Input System
|
||||||
@@ -67,14 +68,14 @@ namespace UI.DragAndDrop.Core
|
|||||||
_parentDraggable = parent;
|
_parentDraggable = parent;
|
||||||
|
|
||||||
Canvas parentCanvas = parent.GetComponentInParent<Canvas>();
|
Canvas parentCanvas = parent.GetComponentInParent<Canvas>();
|
||||||
Debug.Log($"[DraggableVisual] Initializing visual for {parent.name} at world pos {parent.transform.position}, parent canvas: {(parentCanvas != null ? parentCanvas.name + " (renderMode: " + parentCanvas.renderMode + ")" : "NULL")}");
|
Logging.Debug($"[DraggableVisual] Initializing visual for {parent.name} at world pos {parent.transform.position}, parent canvas: {(parentCanvas != null ? parentCanvas.name + " (renderMode: " + parentCanvas.renderMode + ")" : "NULL")}");
|
||||||
|
|
||||||
// CRITICAL: Reparent visual to canvas (not base) so it can move independently
|
// CRITICAL: Reparent visual to canvas (not base) so it can move independently
|
||||||
// This enables the delayed follow effect
|
// This enables the delayed follow effect
|
||||||
if (parentCanvas != null)
|
if (parentCanvas != null)
|
||||||
{
|
{
|
||||||
transform.SetParent(parentCanvas.transform, true); // worldPositionStays = true
|
transform.SetParent(parentCanvas.transform, true); // worldPositionStays = true
|
||||||
Debug.Log($"[DraggableVisual] Reparented visual {name} to canvas {parentCanvas.name} for independent movement");
|
Logging.Debug($"[DraggableVisual] Reparented visual {name} to canvas {parentCanvas.name} for independent movement");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get components if assigned (don't auto-create Canvas to avoid Unity's auto-reparenting)
|
// Get components if assigned (don't auto-create Canvas to avoid Unity's auto-reparenting)
|
||||||
@@ -106,7 +107,7 @@ namespace UI.DragAndDrop.Core
|
|||||||
tiltParent.localRotation = Quaternion.identity;
|
tiltParent.localRotation = Quaternion.identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[DraggableVisual] Visual {name} initialized at world pos {transform.position}, local pos {transform.localPosition}, local rotation {transform.localRotation.eulerAngles}, parent at world pos {parent.transform.position}, local pos {parent.transform.localPosition}, rotation {parent.transform.rotation.eulerAngles}");
|
Logging.Debug($"[DraggableVisual] Visual {name} initialized at world pos {transform.position}, local pos {transform.localPosition}, local rotation {transform.localRotation.eulerAngles}, parent at world pos {parent.transform.position}, local pos {parent.transform.localPosition}, rotation {parent.transform.rotation.eulerAngles}");
|
||||||
|
|
||||||
_isInitialized = true;
|
_isInitialized = true;
|
||||||
|
|
||||||
@@ -202,7 +203,7 @@ namespace UI.DragAndDrop.Core
|
|||||||
float distance = Vector3.Distance(currentPosition, targetPosition);
|
float distance = Vector3.Distance(currentPosition, targetPosition);
|
||||||
if (distance > 500f)
|
if (distance > 500f)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[DraggableVisual] Large position delta detected! Visual {name} at {currentPosition}, target {targetPosition}, parent {_parentDraggable.name}, distance: {distance}");
|
Logging.Warning($"[DraggableVisual] Large position delta detected! Visual {name} at {currentPosition}, target {targetPosition}, parent {_parentDraggable.name}, distance: {distance}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply follow logic with snappy easing
|
// Apply follow logic with snappy easing
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using UI.Core;
|
using Core;
|
||||||
|
using UI.Core;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ namespace UI
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[HudMenuButton] {buttonName} opening page from prefab: {pagePrefab.name}");
|
Logging.Debug($"[HudMenuButton] {buttonName} opening page from prefab: {pagePrefab.name}");
|
||||||
UIPageController.Instance.PushPageFromPrefab(pagePrefab);
|
UIPageController.Instance.PushPageFromPrefab(pagePrefab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,15 +52,10 @@ namespace UI
|
|||||||
/// Singleton instance of the LoadingScreenController. No longer creates an instance if one doesn't exist.
|
/// Singleton instance of the LoadingScreenController. No longer creates an instance if one doesn't exist.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static LoadingScreenController Instance => _instance;
|
public static LoadingScreenController Instance => _instance;
|
||||||
|
|
||||||
// ManagedBehaviour configuration
|
|
||||||
public override int ManagedAwakePriority => 45; // UI infrastructure, before UIPageController
|
|
||||||
|
|
||||||
private new void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
// Set instance immediately (early initialization)
|
||||||
|
|
||||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
|
|
||||||
// Set up container reference early
|
// Set up container reference early
|
||||||
@@ -74,7 +69,7 @@ namespace UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
Logging.Debug("[LoadingScreenController] Initialized");
|
Logging.Debug("[LoadingScreenController] Initialized");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,15 +27,10 @@ namespace UI
|
|||||||
[SerializeField] private UnityEngine.UI.Button devOptionsButton;
|
[SerializeField] private UnityEngine.UI.Button devOptionsButton;
|
||||||
[SerializeField] private GameObject mainOptionsContainer;
|
[SerializeField] private GameObject mainOptionsContainer;
|
||||||
[SerializeField] private GameObject devOptionsContainer;
|
[SerializeField] private GameObject devOptionsContainer;
|
||||||
|
|
||||||
// After UIPageController (50)
|
|
||||||
public override int ManagedAwakePriority => 55;
|
|
||||||
|
|
||||||
private new void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
// Set instance immediately (early initialization)
|
||||||
|
|
||||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
|
|
||||||
// Ensure we have a CanvasGroup for transitions
|
// Ensure we have a CanvasGroup for transitions
|
||||||
@@ -51,9 +46,9 @@ namespace UI
|
|||||||
gameObject.SetActive(false);
|
gameObject.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
// Subscribe to scene-dependent events - must be in OnManagedAwake, not OnSceneReady
|
// Subscribe to scene-dependent events - must be in OnManagedStart, not OnSceneReady
|
||||||
// because PauseMenu is in DontDestroyOnLoad and OnSceneReady only fires once
|
// because PauseMenu is in DontDestroyOnLoad and OnSceneReady only fires once
|
||||||
if (SceneManagerService.Instance != null)
|
if (SceneManagerService.Instance != null)
|
||||||
{
|
{
|
||||||
@@ -73,15 +68,13 @@ namespace UI
|
|||||||
Logging.Debug("[PauseMenu] Subscribed to SceneManagerService events");
|
Logging.Debug("[PauseMenu] Subscribed to SceneManagerService events");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSceneReady()
|
internal override void OnSceneReady()
|
||||||
{
|
{
|
||||||
// This only fires once for DontDestroyOnLoad objects, so we handle scene loads in OnManagedAwake
|
// This only fires once for DontDestroyOnLoad objects, so we handle scene loads in OnManagedAwake
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
// Unsubscribe when destroyed
|
// Unsubscribe when destroyed
|
||||||
if (SceneManagerService.Instance != null)
|
if (SceneManagerService.Instance != null)
|
||||||
{
|
{
|
||||||
@@ -421,6 +414,7 @@ namespace UI
|
|||||||
{
|
{
|
||||||
SaveLoadManager.Instance.currentSaveData.participantStates.Clear();
|
SaveLoadManager.Instance.currentSaveData.participantStates.Clear();
|
||||||
SaveLoadManager.Instance.currentSaveData.unlockedMinigames.Clear();
|
SaveLoadManager.Instance.currentSaveData.unlockedMinigames.Clear();
|
||||||
|
SaveLoadManager.Instance.currentSaveData.playedDivingTutorial = false;
|
||||||
Logging.Debug("[PauseMenu] Cleared all save data from memory");
|
Logging.Debug("[PauseMenu] Cleared all save data from memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using UnityEngine.Playables;
|
|||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace UI
|
namespace UI
|
||||||
{
|
{
|
||||||
@@ -19,6 +20,73 @@ namespace UI
|
|||||||
{
|
{
|
||||||
public enum UIMode { Overworld, Puzzle, Minigame, HideAll };
|
public enum UIMode { Overworld, Puzzle, Minigame, HideAll };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Context object for managing temporary HUD element visibility.
|
||||||
|
/// Automatically restores previous visibility state when disposed.
|
||||||
|
/// Usage: using (var ctx = PlayerHudManager.Instance.ShowElementTemporarily(myButton)) { ... }
|
||||||
|
/// </summary>
|
||||||
|
public class HudVisibilityContext : IDisposable
|
||||||
|
{
|
||||||
|
private readonly GameObject _element;
|
||||||
|
private readonly bool _previousState;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
internal HudVisibilityContext(GameObject element, bool show)
|
||||||
|
{
|
||||||
|
_element = element;
|
||||||
|
_previousState = element.activeSelf;
|
||||||
|
_element.SetActive(show);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_disposed) return;
|
||||||
|
_disposed = true;
|
||||||
|
|
||||||
|
if (_element != null)
|
||||||
|
{
|
||||||
|
_element.SetActive(_previousState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Multi-element visibility context for managing multiple HUD elements at once.
|
||||||
|
/// Automatically restores previous visibility states when disposed.
|
||||||
|
/// </summary>
|
||||||
|
public class MultiHudVisibilityContext : IDisposable
|
||||||
|
{
|
||||||
|
private readonly List<(GameObject element, bool previousState)> _elements;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
internal MultiHudVisibilityContext(IEnumerable<GameObject> elements, bool show)
|
||||||
|
{
|
||||||
|
_elements = new List<(GameObject, bool)>();
|
||||||
|
foreach (var element in elements)
|
||||||
|
{
|
||||||
|
if (element != null)
|
||||||
|
{
|
||||||
|
_elements.Add((element, element.activeSelf));
|
||||||
|
element.SetActive(show);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_disposed) return;
|
||||||
|
_disposed = true;
|
||||||
|
|
||||||
|
foreach (var (element, previousState) in _elements)
|
||||||
|
{
|
||||||
|
if (element != null)
|
||||||
|
{
|
||||||
|
element.SetActive(previousState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public UIMode currentUIMode;
|
public UIMode currentUIMode;
|
||||||
|
|
||||||
[Header("HUD Management")]
|
[Header("HUD Management")]
|
||||||
@@ -31,9 +99,9 @@ namespace UI
|
|||||||
public GameObject CinematicBackground;
|
public GameObject CinematicBackground;
|
||||||
|
|
||||||
[Header("HUD Elements")]
|
[Header("HUD Elements")]
|
||||||
public GameObject appSwitcher;
|
|
||||||
public GameObject eagleEye;
|
public GameObject eagleEye;
|
||||||
|
public GameObject ramaSjangButton;
|
||||||
|
public GameObject scrabBookButton;
|
||||||
|
|
||||||
[HideInInspector] public Image cinematicSprites;
|
[HideInInspector] public Image cinematicSprites;
|
||||||
[HideInInspector] public Image cinematicBackgroundSprites;
|
[HideInInspector] public Image cinematicBackgroundSprites;
|
||||||
@@ -47,14 +115,14 @@ namespace UI
|
|||||||
private UIPageController _uiPageController;
|
private UIPageController _uiPageController;
|
||||||
private AppSwitcher _appSwitcherComponent;
|
private AppSwitcher _appSwitcherComponent;
|
||||||
|
|
||||||
private new void Awake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.Awake();
|
|
||||||
if (Instance != null)
|
if (Instance != null)
|
||||||
{
|
{
|
||||||
Destroy(this);
|
Destroy(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Set instance immediately (early initialization)
|
||||||
_instance = this;
|
_instance = this;
|
||||||
|
|
||||||
// Get UIPageController on same GameObject
|
// Get UIPageController on same GameObject
|
||||||
@@ -64,16 +132,10 @@ namespace UI
|
|||||||
UnityEngine.Debug.LogError("[PlayerHudManager] UIPageController not found on same GameObject!");
|
UnityEngine.Debug.LogError("[PlayerHudManager] UIPageController not found on same GameObject!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get AppSwitcher component reference
|
|
||||||
if (appSwitcher != null)
|
|
||||||
{
|
|
||||||
_appSwitcherComponent = appSwitcher.GetComponent<AppSwitcher>();
|
|
||||||
}
|
|
||||||
|
|
||||||
InitializeReferences();
|
InitializeReferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
// Subscribe to UIPageController page changes for auto HUD management
|
// Subscribe to UIPageController page changes for auto HUD management
|
||||||
if (_uiPageController != null)
|
if (_uiPageController != null)
|
||||||
@@ -110,10 +172,8 @@ namespace UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
internal override void OnManagedDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
// Unsubscribe from events
|
// Unsubscribe from events
|
||||||
if (_uiPageController != null)
|
if (_uiPageController != null)
|
||||||
{
|
{
|
||||||
@@ -164,53 +224,17 @@ namespace UI
|
|||||||
switch (sceneName)
|
switch (sceneName)
|
||||||
{
|
{
|
||||||
case "AppleHillsOverworld":
|
case "AppleHillsOverworld":
|
||||||
UpdateUIMode(UIMode.Overworld);
|
currentUIMode = UIMode.Overworld;
|
||||||
break;
|
break;
|
||||||
case "Quarry":
|
case "Quarry":
|
||||||
UpdateUIMode(UIMode.Puzzle);
|
currentUIMode = UIMode.Puzzle;
|
||||||
break;
|
break;
|
||||||
case "DivingForPictures":
|
case "DivingForPictures":
|
||||||
UpdateUIMode(UIMode.Minigame);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateUIMode(UIMode mode)
|
|
||||||
{
|
|
||||||
switch (mode)
|
|
||||||
{
|
|
||||||
case UIMode.Overworld:
|
|
||||||
// Update currentUIMode var
|
|
||||||
currentUIMode = UIMode.Overworld;
|
|
||||||
// Show app switcher
|
|
||||||
appSwitcher.SetActive(true);
|
|
||||||
// Hide eagle eye
|
|
||||||
eagleEye.SetActive(false);
|
|
||||||
break;
|
|
||||||
case UIMode.Puzzle:
|
|
||||||
// Update currentUIMode var
|
|
||||||
currentUIMode = UIMode.Puzzle;
|
|
||||||
// Hide app switcher
|
|
||||||
appSwitcher.SetActive(false);
|
|
||||||
// show eagle eye
|
|
||||||
eagleEye.SetActive(true);
|
|
||||||
break;
|
|
||||||
case UIMode.Minigame:
|
|
||||||
// Update currentUIMode var
|
|
||||||
currentUIMode = UIMode.Minigame;
|
currentUIMode = UIMode.Minigame;
|
||||||
// Hide app switcher
|
|
||||||
appSwitcher.SetActive(false);
|
|
||||||
// Hide birds eye
|
|
||||||
eagleEye.SetActive(false);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
ShowAllHud();
|
||||||
public void ToggleAppSwitcher(bool boo)
|
|
||||||
{
|
|
||||||
appSwitcher.SetActive(boo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -263,14 +287,50 @@ namespace UI
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set visibility for all HUD children
|
||||||
foreach (Transform child in hudButtonsContainer)
|
foreach (Transform child in hudButtonsContainer)
|
||||||
{
|
{
|
||||||
child.gameObject.SetActive(visible);
|
child.gameObject.SetActive(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApplyUIModeOverrides(visible);
|
||||||
|
|
||||||
Logging.Debug($"[PlayerHudManager] {(visible ? "Shown" : "Hidden")} all HUD elements");
|
Logging.Debug($"[PlayerHudManager] {(visible ? "Shown" : "Hidden")} all HUD elements");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies UI mode-specific visibility rules (e.g., hiding eagleEye in certain modes)
|
||||||
|
/// </summary>
|
||||||
|
private void ApplyUIModeOverrides(bool visible)
|
||||||
|
{
|
||||||
|
switch (currentUIMode)
|
||||||
|
{
|
||||||
|
case UIMode.Overworld:
|
||||||
|
if (visible)
|
||||||
|
{
|
||||||
|
eagleEye.SetActive(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UIMode.Puzzle:
|
||||||
|
if (visible)
|
||||||
|
{
|
||||||
|
ramaSjangButton.SetActive(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UIMode.Minigame:
|
||||||
|
if (visible)
|
||||||
|
{
|
||||||
|
eagleEye.SetActive(false);
|
||||||
|
ramaSjangButton.SetActive(false);
|
||||||
|
scrabBookButton.SetActive(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UIMode.HideAll:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Automatically manages HUD visibility based on page stack state
|
/// Automatically manages HUD visibility based on page stack state
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -328,6 +388,64 @@ namespace UI
|
|||||||
UnityEngine.Debug.LogError("[PlayerHudManager] Cannot push page - UIPageController not found!");
|
UnityEngine.Debug.LogError("[PlayerHudManager] Cannot push page - UIPageController not found!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region HUD Element Getters
|
||||||
|
|
||||||
|
public GameObject GetEagleEye() => eagleEye;
|
||||||
|
public GameObject GetRamaSjangButton() => ramaSjangButton;
|
||||||
|
public GameObject GetScrabookButton() => scrabBookButton;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Context-Based Visibility Management
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Temporarily shows a HUD element. Returns a context object that restores the previous state when disposed.
|
||||||
|
/// Usage: using (var ctx = PlayerHudManager.Instance.ShowElementTemporarily(myButton)) { /* element is visible */ }
|
||||||
|
/// </summary>
|
||||||
|
public HudVisibilityContext ShowElementTemporarily(GameObject element)
|
||||||
|
{
|
||||||
|
if (element == null)
|
||||||
|
{
|
||||||
|
Logging.Warning("[PlayerHudManager] Attempted to show null element");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new HudVisibilityContext(element, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Temporarily hides a HUD element. Returns a context object that restores the previous state when disposed.
|
||||||
|
/// Usage: using (var ctx = PlayerHudManager.Instance.HideElementTemporarily(myButton)) { /* element is hidden */ }
|
||||||
|
/// </summary>
|
||||||
|
public HudVisibilityContext HideElementTemporarily(GameObject element)
|
||||||
|
{
|
||||||
|
if (element == null)
|
||||||
|
{
|
||||||
|
Logging.Warning("[PlayerHudManager] Attempted to hide null element");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new HudVisibilityContext(element, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Temporarily shows multiple HUD elements. Returns a context object that restores all previous states when disposed.
|
||||||
|
/// Usage: using (var ctx = PlayerHudManager.Instance.ShowElementsTemporarily(button1, button2, button3)) { /* elements are visible */ }
|
||||||
|
/// </summary>
|
||||||
|
public MultiHudVisibilityContext ShowElementsTemporarily(params GameObject[] elements)
|
||||||
|
{
|
||||||
|
return new MultiHudVisibilityContext(elements, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Temporarily hides multiple HUD elements. Returns a context object that restores all previous states when disposed.
|
||||||
|
/// Usage: using (var ctx = PlayerHudManager.Instance.HideElementsTemporarily(button1, button2, button3)) { /* elements are hidden */ }
|
||||||
|
/// </summary>
|
||||||
|
public MultiHudVisibilityContext HideElementsTemporarily(params GameObject[] elements)
|
||||||
|
{
|
||||||
|
return new MultiHudVisibilityContext(elements, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,6 @@ public class ScrapbookController : MonoBehaviour
|
|||||||
|
|
||||||
public void DebugClick()
|
public void DebugClick()
|
||||||
{
|
{
|
||||||
// Debug.Log("Yey I was clicked!");
|
// Logging.Debug("Yey I was clicked!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Input;
|
|||||||
using Pixelplacement;
|
using Pixelplacement;
|
||||||
using UI.Core;
|
using UI.Core;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.Audio;
|
||||||
|
|
||||||
namespace UI.Tutorial
|
namespace UI.Tutorial
|
||||||
{
|
{
|
||||||
@@ -19,6 +20,8 @@ namespace UI.Tutorial
|
|||||||
|
|
||||||
private StateMachine _stateMachine;
|
private StateMachine _stateMachine;
|
||||||
public bool playTutorial;
|
public bool playTutorial;
|
||||||
|
public AudioSource bottleAudioPlayer;
|
||||||
|
public AudioResource introVO;
|
||||||
[SerializeField] private ProgressType progressType = ProgressType.Auto;
|
[SerializeField] private ProgressType progressType = ProgressType.Auto;
|
||||||
|
|
||||||
// gating for input until current state's animation finishes first loop
|
// gating for input until current state's animation finishes first loop
|
||||||
@@ -27,9 +30,8 @@ namespace UI.Tutorial
|
|||||||
private bool _canAcceptInput;
|
private bool _canAcceptInput;
|
||||||
private Coroutine _waitLoopCoroutine;
|
private Coroutine _waitLoopCoroutine;
|
||||||
|
|
||||||
public override int ManagedAwakePriority => 200; // Tutorial runs late, after other systems
|
|
||||||
|
|
||||||
protected override void OnManagedAwake()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
// Ensure prompt is hidden initially (even before tutorial initialization)
|
// Ensure prompt is hidden initially (even before tutorial initialization)
|
||||||
if (tapPrompt != null)
|
if (tapPrompt != null)
|
||||||
@@ -59,7 +61,7 @@ namespace UI.Tutorial
|
|||||||
|
|
||||||
void RemoveTutorial()
|
void RemoveTutorial()
|
||||||
{
|
{
|
||||||
Debug.Log("Remove me!");
|
Logging.Debug("Remove me!");
|
||||||
if (_waitLoopCoroutine != null)
|
if (_waitLoopCoroutine != null)
|
||||||
{
|
{
|
||||||
StopCoroutine(_waitLoopCoroutine);
|
StopCoroutine(_waitLoopCoroutine);
|
||||||
@@ -76,6 +78,8 @@ namespace UI.Tutorial
|
|||||||
tapPrompt.SetActive(false);
|
tapPrompt.SetActive(false);
|
||||||
|
|
||||||
Destroy(gameObject);
|
Destroy(gameObject);
|
||||||
|
bottleAudioPlayer.resource = introVO;
|
||||||
|
bottleAudioPlayer.Play();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnTap(Vector2 position)
|
public void OnTap(Vector2 position)
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ namespace Utils
|
|||||||
}
|
}
|
||||||
catch (System.Exception ex)
|
catch (System.Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[AppleHillsUtils] Error checking addressable key existence: {ex.Message}");
|
Logging.Warning($"[AppleHillsUtils] Error checking addressable key existence: {ex.Message}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
Assets/Settings/Build Profiles.meta
Normal file
8
Assets/Settings/Build Profiles.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 53ec386bba82c1748886a5beb8468ecf
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
48
Assets/Settings/Build Profiles/iOS.asset
Normal file
48
Assets/Settings/Build Profiles/iOS.asset
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 15003, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name: iOS
|
||||||
|
m_EditorClassIdentifier: UnityEditor.dll::UnityEditor.Build.Profile.BuildProfile
|
||||||
|
m_AssetVersion: 1
|
||||||
|
m_BuildTarget: 9
|
||||||
|
m_Subtarget: 0
|
||||||
|
m_PlatformId: ad48d16a66894befa4d8181998c3cb09
|
||||||
|
m_PlatformBuildProfile:
|
||||||
|
rid: 3475452038477774988
|
||||||
|
m_OverrideGlobalSceneList: 0
|
||||||
|
m_Scenes: []
|
||||||
|
m_ScriptingDefines: []
|
||||||
|
m_PlayerSettingsYaml:
|
||||||
|
m_Settings: []
|
||||||
|
references:
|
||||||
|
version: 2
|
||||||
|
RefIds:
|
||||||
|
- rid: 3475452038477774988
|
||||||
|
type: {class: iOSPlatformSettings, ns: UnityEditor.iOS, asm: UnityEditor.iOS.Extensions}
|
||||||
|
data:
|
||||||
|
m_Development: 0
|
||||||
|
m_ConnectProfiler: 0
|
||||||
|
m_BuildWithDeepProfilingSupport: 0
|
||||||
|
m_AllowDebugging: 0
|
||||||
|
m_WaitForManagedDebugger: 0
|
||||||
|
m_ManagedDebuggerFixedPort: 0
|
||||||
|
m_ExplicitNullChecks: 0
|
||||||
|
m_ExplicitDivideByZeroChecks: 0
|
||||||
|
m_ExplicitArrayBoundsChecks: 0
|
||||||
|
m_CompressionType: -1
|
||||||
|
m_InstallInBuildFolder: 0
|
||||||
|
m_InsightsSettingsContainer:
|
||||||
|
m_BuildProfileEngineDiagnosticsState: 2
|
||||||
|
m_iOSXcodeBuildConfig: 1
|
||||||
|
m_SymlinkSources: 0
|
||||||
|
m_PreferredXcode:
|
||||||
|
m_SymlinkTrampoline: 0
|
||||||
8
Assets/Settings/Build Profiles/iOS.asset.meta
Normal file
8
Assets/Settings/Build Profiles/iOS.asset.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 110a4eabb37dbaa428e55c751696cd1e
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user