Cleanup code structure, code smells, rename paramter, break out more granular managers
This commit is contained in:
@@ -15,7 +15,7 @@ MonoBehaviour:
|
|||||||
m_DefaultGroup: 6f3207429a65b3e4b83935ac19791077
|
m_DefaultGroup: 6f3207429a65b3e4b83935ac19791077
|
||||||
m_currentHash:
|
m_currentHash:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
Hash: 027dc5937f1a989438d4c39629cbe46f
|
Hash: b9c3c669d28f187e4cec7b0693d59a99
|
||||||
m_OptimizeCatalogSize: 0
|
m_OptimizeCatalogSize: 0
|
||||||
m_BuildRemoteCatalog: 0
|
m_BuildRemoteCatalog: 0
|
||||||
m_CatalogRequestsTimeout: 0
|
m_CatalogRequestsTimeout: 0
|
||||||
@@ -65,6 +65,7 @@ MonoBehaviour:
|
|||||||
- {fileID: 11400000, guid: efe7e1728e73e9546ac5dfee2eff524f, type: 2}
|
- {fileID: 11400000, guid: efe7e1728e73e9546ac5dfee2eff524f, type: 2}
|
||||||
- {fileID: 11400000, guid: 6e4927e7e19eef34b93dc2baa9e9e8e2, type: 2}
|
- {fileID: 11400000, guid: 6e4927e7e19eef34b93dc2baa9e9e8e2, type: 2}
|
||||||
- {fileID: 11400000, guid: 4186fdd83f912a14b97fbf4644266b0d, type: 2}
|
- {fileID: 11400000, guid: 4186fdd83f912a14b97fbf4644266b0d, type: 2}
|
||||||
|
- {fileID: 11400000, guid: fd8b6934620e3a54a818495e62a103e0, type: 2}
|
||||||
- {fileID: 11400000, guid: e25c7672a65b5974bb354fcfb2a8400c, type: 2}
|
- {fileID: 11400000, guid: e25c7672a65b5974bb354fcfb2a8400c, type: 2}
|
||||||
- {fileID: 11400000, guid: 7fcc03e584505ed4381983b6ebb1179d, type: 2}
|
- {fileID: 11400000, guid: 7fcc03e584505ed4381983b6ebb1179d, type: 2}
|
||||||
m_BuildSettings:
|
m_BuildSettings:
|
||||||
@@ -107,6 +108,7 @@ MonoBehaviour:
|
|||||||
m_LabelNames:
|
m_LabelNames:
|
||||||
- default
|
- default
|
||||||
- BlokkemonCard
|
- BlokkemonCard
|
||||||
|
- StatueDecorations
|
||||||
m_SchemaTemplates: []
|
m_SchemaTemplates: []
|
||||||
m_GroupTemplateObjects:
|
m_GroupTemplateObjects:
|
||||||
- {fileID: 11400000, guid: ea0a5135f5495eb4693a23d94617fe92, type: 2}
|
- {fileID: 11400000, guid: ea0a5135f5495eb4693a23d94617fe92, type: 2}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -3186,6 +3186,12 @@ PrefabInstance:
|
|||||||
- targetCorrespondingSourceObject: {fileID: 7404622075362872657, guid: f44866deaba5f5c4a90f0330dd9957f0, type: 3}
|
- targetCorrespondingSourceObject: {fileID: 7404622075362872657, guid: f44866deaba5f5c4a90f0330dd9957f0, type: 3}
|
||||||
insertIndex: -1
|
insertIndex: -1
|
||||||
addedObject: {fileID: 1460027146}
|
addedObject: {fileID: 1460027146}
|
||||||
|
- targetCorrespondingSourceObject: {fileID: 7404622075362872657, guid: f44866deaba5f5c4a90f0330dd9957f0, type: 3}
|
||||||
|
insertIndex: -1
|
||||||
|
addedObject: {fileID: 1460027150}
|
||||||
|
- targetCorrespondingSourceObject: {fileID: 7404622075362872657, guid: f44866deaba5f5c4a90f0330dd9957f0, type: 3}
|
||||||
|
insertIndex: -1
|
||||||
|
addedObject: {fileID: 1460027149}
|
||||||
m_SourcePrefab: {fileID: 100100000, guid: f44866deaba5f5c4a90f0330dd9957f0, type: 3}
|
m_SourcePrefab: {fileID: 100100000, guid: f44866deaba5f5c4a90f0330dd9957f0, type: 3}
|
||||||
--- !u!4 &1460027142 stripped
|
--- !u!4 &1460027142 stripped
|
||||||
Transform:
|
Transform:
|
||||||
@@ -3206,7 +3212,32 @@ MonoBehaviour:
|
|||||||
m_EditorClassIdentifier: AppleHillsScripts::Minigames.StatueDressup.Display.StatueDecorationLoader
|
m_EditorClassIdentifier: AppleHillsScripts::Minigames.StatueDressup.Display.StatueDecorationLoader
|
||||||
statueSpriteRenderer: {fileID: 831113526}
|
statueSpriteRenderer: {fileID: 831113526}
|
||||||
specificPhotoId:
|
specificPhotoId:
|
||||||
|
applyPivotOffset: 1
|
||||||
showDebugInfo: 1
|
showDebugInfo: 1
|
||||||
|
--- !u!114 &1460027149
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 175866977}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: acf5624b19664ce5900f1a7c1328edbc, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: AppleHillsScripts::Minigames.StatueDressup.Controllers.StatueDressupSettings
|
||||||
|
--- !u!114 &1460027150
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 175866977}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: afa56ec5b1f84b32ba014a91d9d9a0a0, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: AppleHillsScripts::Minigames.StatueDressup.Controllers.DecorationDataManager
|
||||||
--- !u!4 &1572710089 stripped
|
--- !u!4 &1572710089 stripped
|
||||||
Transform:
|
Transform:
|
||||||
m_CorrespondingSourceObject: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3}
|
m_CorrespondingSourceObject: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3}
|
||||||
|
|||||||
@@ -1163,7 +1163,6 @@ MonoBehaviour:
|
|||||||
draggableContainer: {fileID: 1217454518}
|
draggableContainer: {fileID: 1217454518}
|
||||||
nextPageButton: {fileID: 2071711339}
|
nextPageButton: {fileID: 2071711339}
|
||||||
previousPageButton: {fileID: 194466356}
|
previousPageButton: {fileID: 194466356}
|
||||||
statueController: {fileID: 1647993458}
|
|
||||||
statueOutline: {fileID: 1325274732}
|
statueOutline: {fileID: 1325274732}
|
||||||
gridLayout: {fileID: 699865156}
|
gridLayout: {fileID: 699865156}
|
||||||
--- !u!1 &435994659
|
--- !u!1 &435994659
|
||||||
@@ -2076,6 +2075,152 @@ CanvasRenderer:
|
|||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 1140141871}
|
m_GameObject: {fileID: 1140141871}
|
||||||
m_CullTransparentMesh: 1
|
m_CullTransparentMesh: 1
|
||||||
|
--- !u!1 &1181815683
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 1181815686}
|
||||||
|
- component: {fileID: 1181815685}
|
||||||
|
- component: {fileID: 1181815684}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: SFXManager
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!114 &1181815684
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1181815683}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 242e6101be071f44fb14c3c12641c833, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: AppleHillsScripts::AppleAudioSource
|
||||||
|
audioSourceType: 3
|
||||||
|
audioSource: {fileID: 0}
|
||||||
|
clipPriority: 0
|
||||||
|
sourcePriority: 0
|
||||||
|
--- !u!82 &1181815685
|
||||||
|
AudioSource:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1181815683}
|
||||||
|
m_Enabled: 1
|
||||||
|
serializedVersion: 4
|
||||||
|
OutputAudioMixerGroup: {fileID: 0}
|
||||||
|
m_audioClip: {fileID: 0}
|
||||||
|
m_Resource: {fileID: 0}
|
||||||
|
m_PlayOnAwake: 0
|
||||||
|
m_Volume: 1
|
||||||
|
m_Pitch: 1
|
||||||
|
Loop: 0
|
||||||
|
Mute: 0
|
||||||
|
Spatialize: 0
|
||||||
|
SpatializePostEffects: 0
|
||||||
|
Priority: 128
|
||||||
|
DopplerLevel: 1
|
||||||
|
MinDistance: 1
|
||||||
|
MaxDistance: 500
|
||||||
|
Pan2D: 0
|
||||||
|
rolloffMode: 0
|
||||||
|
BypassEffects: 0
|
||||||
|
BypassListenerEffects: 0
|
||||||
|
BypassReverbZones: 0
|
||||||
|
rolloffCustomCurve:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Curve:
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 0
|
||||||
|
value: 1
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 1
|
||||||
|
value: 0
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
m_PreInfinity: 2
|
||||||
|
m_PostInfinity: 2
|
||||||
|
m_RotationOrder: 4
|
||||||
|
panLevelCustomCurve:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Curve:
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 0
|
||||||
|
value: 0
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
m_PreInfinity: 2
|
||||||
|
m_PostInfinity: 2
|
||||||
|
m_RotationOrder: 4
|
||||||
|
spreadCustomCurve:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Curve:
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 0
|
||||||
|
value: 0
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
m_PreInfinity: 2
|
||||||
|
m_PostInfinity: 2
|
||||||
|
m_RotationOrder: 4
|
||||||
|
reverbZoneMixCustomCurve:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Curve:
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 0
|
||||||
|
value: 1
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
m_PreInfinity: 2
|
||||||
|
m_PostInfinity: 2
|
||||||
|
m_RotationOrder: 4
|
||||||
|
--- !u!4 &1181815686
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1181815683}
|
||||||
|
serializedVersion: 2
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 1218.915, y: 722.89856, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1 &1217454514
|
--- !u!1 &1217454514
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -2719,6 +2864,8 @@ GameObject:
|
|||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 1647993459}
|
- component: {fileID: 1647993459}
|
||||||
- component: {fileID: 1647993458}
|
- component: {fileID: 1647993458}
|
||||||
|
- component: {fileID: 1647993461}
|
||||||
|
- component: {fileID: 1647993460}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: StatueDecorationController
|
m_Name: StatueDecorationController
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -2740,7 +2887,6 @@ MonoBehaviour:
|
|||||||
m_EditorClassIdentifier: AppleHillsScripts::Minigames.StatueDressup.Controllers.StatueDecorationController
|
m_EditorClassIdentifier: AppleHillsScripts::Minigames.StatueDressup.Controllers.StatueDecorationController
|
||||||
statueArea: {fileID: 65358845}
|
statueArea: {fileID: 65358845}
|
||||||
statueParent: {fileID: 166400579}
|
statueParent: {fileID: 166400579}
|
||||||
menuController: {fileID: 403667980}
|
|
||||||
takePhotoButton: {fileID: 37633367}
|
takePhotoButton: {fileID: 37633367}
|
||||||
statue: {fileID: 1078270173}
|
statue: {fileID: 1078270173}
|
||||||
draggablePrefab: {fileID: 8998709565229564215, guid: 064cd4d021ea13e47860a59bbe8224aa, type: 3}
|
draggablePrefab: {fileID: 8998709565229564215, guid: 064cd4d021ea13e47860a59bbe8224aa, type: 3}
|
||||||
@@ -2764,6 +2910,30 @@ Transform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &1647993460
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1647993457}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: afa56ec5b1f84b32ba014a91d9d9a0a0, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: AppleHillsScripts::Minigames.StatueDressup.Controllers.DecorationDataManager
|
||||||
|
--- !u!114 &1647993461
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1647993457}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: acf5624b19664ce5900f1a7c1328edbc, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: AppleHillsScripts::Minigames.StatueDressup.Controllers.StatueDressupSettings
|
||||||
--- !u!1 &1685271989
|
--- !u!1 &1685271989
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -3297,6 +3467,7 @@ SceneRoots:
|
|||||||
- {fileID: 951788}
|
- {fileID: 951788}
|
||||||
- {fileID: 1542794369}
|
- {fileID: 1542794369}
|
||||||
- {fileID: 1647993459}
|
- {fileID: 1647993459}
|
||||||
|
- {fileID: 1181815686}
|
||||||
- {fileID: 1217454518}
|
- {fileID: 1217454518}
|
||||||
- {fileID: 1126329096}
|
- {fileID: 1126329096}
|
||||||
- {fileID: 483064112}
|
- {fileID: 483064112}
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Core;
|
||||||
|
using Core.Lifecycle;
|
||||||
|
using Minigames.StatueDressup.Data;
|
||||||
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||||
|
using Utils;
|
||||||
|
|
||||||
|
namespace Minigames.StatueDressup.Controllers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Singleton manager for decoration data loading and caching.
|
||||||
|
/// Loads all DecorationData assets once via Addressables and provides shared access.
|
||||||
|
/// Used by both minigame and town map to avoid duplicate loading.
|
||||||
|
/// </summary>
|
||||||
|
public class DecorationDataManager : ManagedBehaviour
|
||||||
|
{
|
||||||
|
public static DecorationDataManager Instance { get; private set; }
|
||||||
|
|
||||||
|
private Dictionary<string, DecorationData> decorationDataDict;
|
||||||
|
private AsyncOperationHandle<System.Collections.Generic.IList<DecorationData>> decorationDataHandle;
|
||||||
|
private bool isLoaded;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if data is loaded and ready
|
||||||
|
/// </summary>
|
||||||
|
public bool IsLoaded => isLoaded;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all decoration data as dictionary
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, DecorationData> AllData => decorationDataDict;
|
||||||
|
|
||||||
|
internal override void OnManagedAwake()
|
||||||
|
{
|
||||||
|
base.OnManagedAwake();
|
||||||
|
|
||||||
|
// Singleton pattern
|
||||||
|
if (Instance != null && Instance != this)
|
||||||
|
{
|
||||||
|
Logging.Warning("[DecorationDataManager] Duplicate instance detected. Destroying duplicate.");
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override async void OnManagedStart()
|
||||||
|
{
|
||||||
|
base.OnManagedStart();
|
||||||
|
|
||||||
|
await LoadAllDecorationData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load all DecorationData assets via Addressables
|
||||||
|
/// </summary>
|
||||||
|
private async System.Threading.Tasks.Task LoadAllDecorationData()
|
||||||
|
{
|
||||||
|
if (isLoaded)
|
||||||
|
{
|
||||||
|
Logging.Warning("[DecorationDataManager] Data already loaded");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var settings = StatueDressupSettings.Instance?.Settings;
|
||||||
|
string label = settings?.DecorationDataLabel;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(label))
|
||||||
|
{
|
||||||
|
Logging.Error("[DecorationDataManager] Decoration data label not set in settings!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logging.Debug($"[DecorationDataManager] Loading DecorationData with label '{label}'...");
|
||||||
|
|
||||||
|
// Use utility to load all DecorationData and create dictionary by ID
|
||||||
|
var result = await AddressablesUtility.LoadAssetsByLabelAsync<DecorationData, string>(
|
||||||
|
label,
|
||||||
|
data => data.DecorationId
|
||||||
|
);
|
||||||
|
|
||||||
|
decorationDataDict = result.dictionary;
|
||||||
|
decorationDataHandle = result.handle;
|
||||||
|
isLoaded = true;
|
||||||
|
|
||||||
|
Logging.Debug($"[DecorationDataManager] Loaded {decorationDataDict.Count} DecorationData assets");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get decoration data by ID
|
||||||
|
/// </summary>
|
||||||
|
public DecorationData GetData(string decorationId)
|
||||||
|
{
|
||||||
|
if (!isLoaded)
|
||||||
|
{
|
||||||
|
Logging.Warning("[DecorationDataManager] Data not loaded yet!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(decorationId))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
decorationDataDict.TryGetValue(decorationId, out DecorationData data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try get decoration data by ID
|
||||||
|
/// </summary>
|
||||||
|
public bool TryGetData(string decorationId, out DecorationData data)
|
||||||
|
{
|
||||||
|
data = null;
|
||||||
|
|
||||||
|
if (!isLoaded || string.IsNullOrEmpty(decorationId))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return decorationDataDict.TryGetValue(decorationId, out data);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void OnManagedDestroy()
|
||||||
|
{
|
||||||
|
base.OnManagedDestroy();
|
||||||
|
|
||||||
|
// Release Addressables handle
|
||||||
|
AddressablesUtility.ReleaseHandle(decorationDataHandle);
|
||||||
|
|
||||||
|
if (Instance == this)
|
||||||
|
{
|
||||||
|
Instance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: afa56ec5b1f84b32ba014a91d9d9a0a0
|
||||||
|
timeCreated: 1764240174
|
||||||
@@ -13,6 +13,8 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class DecorationMenuController : ManagedBehaviour
|
public class DecorationMenuController : ManagedBehaviour
|
||||||
{
|
{
|
||||||
|
public static DecorationMenuController Instance { get; private set; }
|
||||||
|
|
||||||
[Header("References")]
|
[Header("References")]
|
||||||
[SerializeField] private DecorationGridIcon iconPrefab;
|
[SerializeField] private DecorationGridIcon iconPrefab;
|
||||||
[SerializeField] private DecorationDraggableInstance draggablePrefab;
|
[SerializeField] private DecorationDraggableInstance draggablePrefab;
|
||||||
@@ -20,36 +22,36 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
[SerializeField] private Transform draggableContainer; // Parent for spawned draggables
|
[SerializeField] private Transform draggableContainer; // Parent for spawned draggables
|
||||||
[SerializeField] private Button nextPageButton;
|
[SerializeField] private Button nextPageButton;
|
||||||
[SerializeField] private Button previousPageButton;
|
[SerializeField] private Button previousPageButton;
|
||||||
[SerializeField] private StatueDecorationController statueController; // Controller for registration
|
|
||||||
[SerializeField] private Image statueOutline; // Outline image shown during drag to indicate valid drop area
|
[SerializeField] private Image statueOutline; // Outline image shown during drag to indicate valid drop area
|
||||||
|
|
||||||
[Header("Layout")]
|
[Header("Layout")]
|
||||||
[SerializeField] private GridLayoutGroup gridLayout;
|
[SerializeField] private GridLayoutGroup gridLayout;
|
||||||
|
|
||||||
private int _currentPage;
|
private int currentPage;
|
||||||
private int _totalPages;
|
private int totalPages;
|
||||||
private List<DecorationGridIcon> _spawnedIcons = new List<DecorationGridIcon>();
|
private List<DecorationGridIcon> spawnedIcons = new List<DecorationGridIcon>();
|
||||||
private AppleHills.Core.Settings.IStatueDressupSettings _settings;
|
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
public int CurrentPage => _currentPage;
|
public int CurrentPage => currentPage;
|
||||||
public int TotalPages => _totalPages;
|
public int TotalPages => totalPages;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Early initialization - get settings reference
|
/// Early initialization - singleton setup
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal override void OnManagedAwake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.OnManagedAwake();
|
base.OnManagedAwake();
|
||||||
|
|
||||||
// Get settings early
|
// Singleton pattern
|
||||||
_settings = GameManager.GetSettingsObject<AppleHills.Core.Settings.IStatueDressupSettings>();
|
if (Instance != null && Instance != this)
|
||||||
|
|
||||||
if (_settings == null)
|
|
||||||
{
|
{
|
||||||
Logging.Error("[DecorationMenuController] Failed to load StatueDressupSettings!");
|
Logging.Warning("[DecorationMenuController] Duplicate instance detected. Destroying duplicate.");
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
// Ensure outline starts hidden (do this early so it's ready for saved decorations)
|
// Ensure outline starts hidden (do this early so it's ready for saved decorations)
|
||||||
if (statueOutline != null)
|
if (statueOutline != null)
|
||||||
{
|
{
|
||||||
@@ -64,27 +66,29 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
{
|
{
|
||||||
base.OnManagedStart();
|
base.OnManagedStart();
|
||||||
|
|
||||||
if (_settings == null)
|
var settings = StatueDressupSettings.Instance?.Settings;
|
||||||
|
|
||||||
|
if (settings == null)
|
||||||
{
|
{
|
||||||
Logging.Error("[DecorationMenuController] Cannot initialize without settings!");
|
Logging.Error("[DecorationMenuController] Cannot initialize without settings!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var allDecorations = _settings.AllDecorations;
|
var allDecorations = settings.AllDecorations;
|
||||||
int itemsPerPage = _settings.ItemsPerPage;
|
int itemsPerPage = settings.ItemsPerPage;
|
||||||
|
|
||||||
Logging.Debug($"[DecorationMenuController] Initializing with {allDecorations?.Count ?? 0} decorations");
|
Logging.Debug($"[DecorationMenuController] Initializing with {allDecorations?.Count ?? 0} decorations");
|
||||||
|
|
||||||
// Calculate total pages
|
// Calculate total pages
|
||||||
if (allDecorations != null && allDecorations.Count > 0)
|
if (allDecorations != null && allDecorations.Count > 0)
|
||||||
{
|
{
|
||||||
_totalPages = Mathf.CeilToInt((float)allDecorations.Count / itemsPerPage);
|
totalPages = Mathf.CeilToInt((float)allDecorations.Count / itemsPerPage);
|
||||||
Logging.Debug($"[DecorationMenuController] Total pages: {_totalPages}");
|
Logging.Debug($"[DecorationMenuController] Total pages: {totalPages}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logging.Warning("[DecorationMenuController] No decorations found in settings!");
|
Logging.Warning("[DecorationMenuController] No decorations found in settings!");
|
||||||
_totalPages = 0;
|
totalPages = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup buttons
|
// Setup buttons
|
||||||
@@ -110,10 +114,11 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void PopulateCurrentPage()
|
private void PopulateCurrentPage()
|
||||||
{
|
{
|
||||||
if (_settings == null) return;
|
var settings = StatueDressupSettings.Instance?.Settings;
|
||||||
|
if (settings == null) return;
|
||||||
|
|
||||||
var allDecorations = _settings.AllDecorations;
|
var allDecorations = settings.AllDecorations;
|
||||||
int itemsPerPage = _settings.ItemsPerPage;
|
int itemsPerPage = settings.ItemsPerPage;
|
||||||
|
|
||||||
if (allDecorations == null || allDecorations.Count == 0)
|
if (allDecorations == null || allDecorations.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -121,13 +126,13 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logging.Debug($"[DecorationMenuController] Populating page {_currentPage + 1}/{_totalPages}");
|
Logging.Debug($"[DecorationMenuController] Populating page {currentPage + 1}/{totalPages}");
|
||||||
|
|
||||||
// Clear existing icons
|
// Clear existing icons
|
||||||
ClearIcons();
|
ClearIcons();
|
||||||
|
|
||||||
// Calculate range for current page
|
// Calculate range for current page
|
||||||
int startIndex = _currentPage * itemsPerPage;
|
int startIndex = currentPage * itemsPerPage;
|
||||||
int endIndex = Mathf.Min(startIndex + itemsPerPage, allDecorations.Count);
|
int endIndex = Mathf.Min(startIndex + itemsPerPage, allDecorations.Count);
|
||||||
|
|
||||||
Logging.Debug($"[DecorationMenuController] Spawning icons {startIndex} to {endIndex - 1}");
|
Logging.Debug($"[DecorationMenuController] Spawning icons {startIndex} to {endIndex - 1}");
|
||||||
@@ -156,7 +161,7 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
DecorationGridIcon icon = Instantiate(iconPrefab, itemsContainer);
|
DecorationGridIcon icon = Instantiate(iconPrefab, itemsContainer);
|
||||||
icon.Initialize(data, this);
|
icon.Initialize(data, this);
|
||||||
|
|
||||||
_spawnedIcons.Add(icon);
|
spawnedIcons.Add(icon);
|
||||||
|
|
||||||
Logging.Debug($"[DecorationMenuController] Spawned icon: {data.DecorationName}");
|
Logging.Debug($"[DecorationMenuController] Spawned icon: {data.DecorationName}");
|
||||||
}
|
}
|
||||||
@@ -167,7 +172,7 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DecorationDraggableInstance SpawnDraggableInstance(DecorationData data, Vector3 screenPosition)
|
public DecorationDraggableInstance SpawnDraggableInstance(DecorationData data, Vector3 screenPosition)
|
||||||
{
|
{
|
||||||
if (draggablePrefab == null || statueController == null)
|
if (draggablePrefab == null || StatueDecorationController.Instance == null)
|
||||||
{
|
{
|
||||||
Logging.Warning("[DecorationMenuController] Missing draggable prefab or statue controller");
|
Logging.Warning("[DecorationMenuController] Missing draggable prefab or statue controller");
|
||||||
return null;
|
return null;
|
||||||
@@ -185,18 +190,21 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
// Get outline RectTransform for overlap detection
|
// Get outline RectTransform for overlap detection
|
||||||
RectTransform outlineRect = statueOutline != null ? statueOutline.rectTransform : null;
|
RectTransform outlineRect = statueOutline != null ? statueOutline.rectTransform : null;
|
||||||
|
|
||||||
// Initialize with references including outline callbacks
|
// Create context for new drag
|
||||||
instance.Initialize(
|
var context = DecorationDragContext.CreateForNewDrag(
|
||||||
data,
|
data,
|
||||||
outlineRect,
|
outlineRect,
|
||||||
statueController.StatueParent,
|
StatueDecorationController.Instance.StatueParent,
|
||||||
statueController,
|
StatueDecorationController.Instance,
|
||||||
_settings,
|
StatueDressupSettings.Instance.Settings,
|
||||||
OnDraggableFinished,
|
OnDraggableFinished,
|
||||||
ShowStatueOutline, // Show outline when picking up from statue
|
ShowStatueOutline,
|
||||||
HideStatueOutline // Hide outline when drag ends
|
HideStatueOutline
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Initialize with context
|
||||||
|
instance.InitializeWithContext(context);
|
||||||
|
|
||||||
// Position at cursor (in local space)
|
// Position at cursor (in local space)
|
||||||
Canvas canvas = GetComponentInParent<Canvas>();
|
Canvas canvas = GetComponentInParent<Canvas>();
|
||||||
if (canvas != null)
|
if (canvas != null)
|
||||||
@@ -261,7 +269,7 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void ClearIcons()
|
private void ClearIcons()
|
||||||
{
|
{
|
||||||
foreach (var icon in _spawnedIcons)
|
foreach (var icon in spawnedIcons)
|
||||||
{
|
{
|
||||||
if (icon != null)
|
if (icon != null)
|
||||||
{
|
{
|
||||||
@@ -269,7 +277,7 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_spawnedIcons.Clear();
|
spawnedIcons.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -277,11 +285,11 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnNextPage()
|
private void OnNextPage()
|
||||||
{
|
{
|
||||||
if (_currentPage < _totalPages - 1)
|
if (currentPage < totalPages - 1)
|
||||||
{
|
{
|
||||||
_currentPage++;
|
currentPage++;
|
||||||
PopulateCurrentPage();
|
PopulateCurrentPage();
|
||||||
Logging.Debug($"[DecorationMenuController] Next page: {_currentPage + 1}/{_totalPages}");
|
Logging.Debug($"[DecorationMenuController] Next page: {currentPage + 1}/{totalPages}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,11 +298,11 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnPreviousPage()
|
private void OnPreviousPage()
|
||||||
{
|
{
|
||||||
if (_currentPage > 0)
|
if (currentPage > 0)
|
||||||
{
|
{
|
||||||
_currentPage--;
|
currentPage--;
|
||||||
PopulateCurrentPage();
|
PopulateCurrentPage();
|
||||||
Logging.Debug($"[DecorationMenuController] Previous page: {_currentPage + 1}/{_totalPages}");
|
Logging.Debug($"[DecorationMenuController] Previous page: {currentPage + 1}/{totalPages}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,14 +311,14 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdateNavigationButtons()
|
private void UpdateNavigationButtons()
|
||||||
{
|
{
|
||||||
if (previousPageButton != null)
|
|
||||||
{
|
|
||||||
previousPageButton.interactable = _currentPage > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextPageButton != null)
|
if (nextPageButton != null)
|
||||||
{
|
{
|
||||||
nextPageButton.interactable = _currentPage < _totalPages - 1;
|
nextPageButton.interactable = currentPage < totalPages - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previousPageButton != null)
|
||||||
|
{
|
||||||
|
previousPageButton.interactable = currentPage > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,6 +342,12 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
|
|
||||||
// Cleanup icons
|
// Cleanup icons
|
||||||
ClearIcons();
|
ClearIcons();
|
||||||
|
|
||||||
|
// Singleton cleanup
|
||||||
|
if (Instance == this)
|
||||||
|
{
|
||||||
|
Instance = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,11 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class StatueDecorationController : ManagedBehaviour
|
public class StatueDecorationController : ManagedBehaviour
|
||||||
{
|
{
|
||||||
|
public static StatueDecorationController Instance { get; private set; }
|
||||||
|
|
||||||
[Header("References")]
|
[Header("References")]
|
||||||
[SerializeField] private RectTransform statueArea; // Statue area for overlap detection
|
[SerializeField] private RectTransform statueArea; // Statue area for overlap detection
|
||||||
[SerializeField] private Transform statueParent; // Parent for placed decorations
|
[SerializeField] private Transform statueParent; // Parent for placed decorations
|
||||||
[SerializeField] private DecorationMenuController menuController;
|
|
||||||
[SerializeField] private Button takePhotoButton;
|
[SerializeField] private Button takePhotoButton;
|
||||||
[SerializeField] private GameObject statue;
|
[SerializeField] private GameObject statue;
|
||||||
[SerializeField] private DecorationDraggableInstance draggablePrefab; // Prefab for spawning decorations
|
[SerializeField] private DecorationDraggableInstance draggablePrefab; // Prefab for spawning decorations
|
||||||
@@ -36,38 +37,71 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
[Header("Photo Settings")]
|
[Header("Photo Settings")]
|
||||||
[SerializeField] private RectTransform photoArea; // Area to capture
|
[SerializeField] private RectTransform photoArea; // Area to capture
|
||||||
|
|
||||||
private List<DecorationDraggableInstance> _placedDecorations = new List<DecorationDraggableInstance>();
|
private List<DecorationDraggableInstance> placedDecorations = new List<DecorationDraggableInstance>();
|
||||||
private bool _minigameCompleted;
|
private bool minigameCompleted;
|
||||||
private AppleHills.Core.Settings.IStatueDressupSettings _settings;
|
|
||||||
private Dictionary<string, DecorationData> _decorationDataDict;
|
|
||||||
private UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle<System.Collections.Generic.IList<DecorationData>> _decorationDataHandle;
|
|
||||||
|
|
||||||
// Public property for menu controller
|
// Public properties
|
||||||
public Transform StatueParent => statueParent;
|
public Transform StatueParent => statueParent;
|
||||||
|
public RectTransform StatueArea => statueArea;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Early initialization - get settings reference
|
/// Early initialization - singleton setup
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal override void OnManagedAwake()
|
internal override void OnManagedAwake()
|
||||||
{
|
{
|
||||||
base.OnManagedAwake();
|
base.OnManagedAwake();
|
||||||
|
|
||||||
// Get settings early
|
// Singleton pattern
|
||||||
_settings = GameManager.GetSettingsObject<AppleHills.Core.Settings.IStatueDressupSettings>();
|
if (Instance != null && Instance != this)
|
||||||
|
{
|
||||||
|
Logging.Warning("[StatueDecorationController] Duplicate instance detected. Destroying duplicate.");
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Main initialization after all managers are ready
|
/// Main initialization after all managers are ready
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal override async void OnManagedStart()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
base.OnManagedStart();
|
base.OnManagedStart();
|
||||||
|
|
||||||
Logging.Debug("[StatueDecorationController] Initializing minigame");
|
Logging.Debug("[StatueDecorationController] Initializing minigame");
|
||||||
|
|
||||||
// Load all DecorationData via Addressables first
|
// DecorationDataManager exists (initialized in OnManagedAwake) but data loads async in OnManagedStart
|
||||||
await LoadDecorationDataAsync();
|
// Wait for data to finish loading before initializing
|
||||||
|
if (!DecorationDataManager.Instance.IsLoaded)
|
||||||
|
{
|
||||||
|
Logging.Debug("[StatueDecorationController] Waiting for DecorationData to load...");
|
||||||
|
StartCoroutine(WaitForDataAndInitialize());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeMinigame();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wait for data manager to finish loading data before initializing
|
||||||
|
/// </summary>
|
||||||
|
private System.Collections.IEnumerator WaitForDataAndInitialize()
|
||||||
|
{
|
||||||
|
while (!DecorationDataManager.Instance.IsLoaded)
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logging.Debug("[StatueDecorationController] DecorationData loaded, initializing minigame");
|
||||||
|
InitializeMinigame();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize the minigame after data is ready
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeMinigame()
|
||||||
|
{
|
||||||
// TODO: If ever picture gallery
|
// TODO: If ever picture gallery
|
||||||
// Setup UI pages (DISABLED - kept for future gallery integration)
|
// Setup UI pages (DISABLED - kept for future gallery integration)
|
||||||
// if (playAreaPage != null && UIPageController.Instance != null)
|
// if (playAreaPage != null && UIPageController.Instance != null)
|
||||||
@@ -89,45 +123,10 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
// openGalleryButton.onClick.AddListener(OnOpenGallery);
|
// openGalleryButton.onClick.AddListener(OnOpenGallery);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Subscribe to menu controller for tracking placed items
|
|
||||||
// Items will manage their own placement via overlap detection
|
|
||||||
if (menuController != null)
|
|
||||||
{
|
|
||||||
// Menu controller will handle spawning replacements
|
|
||||||
Logging.Debug("[StatueDecorationController] Menu controller connected");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load saved state if exists
|
// Load saved state if exists
|
||||||
LoadStatueState();
|
LoadStatueState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Load all DecorationData assets via Addressables and build lookup dictionary
|
|
||||||
/// </summary>
|
|
||||||
private async System.Threading.Tasks.Task LoadDecorationDataAsync()
|
|
||||||
{
|
|
||||||
string label = _settings?.DecorationDataLabel;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(label))
|
|
||||||
{
|
|
||||||
Logging.Error("[StatueDecorationController] Decoration data label not set in settings!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logging.Debug($"[StatueDecorationController] Loading DecorationData with label '{label}'...");
|
|
||||||
|
|
||||||
// Use utility to load all DecorationData and create dictionary by ID
|
|
||||||
var result = await AddressablesUtility.LoadAssetsByLabelAsync<DecorationData, string>(
|
|
||||||
label,
|
|
||||||
data => data.DecorationId
|
|
||||||
);
|
|
||||||
|
|
||||||
_decorationDataDict = result.dictionary;
|
|
||||||
_decorationDataHandle = result.handle;
|
|
||||||
|
|
||||||
Logging.Debug($"[StatueDecorationController] Loaded {_decorationDataDict.Count} DecorationData assets");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Open photo gallery
|
/// Open photo gallery
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -149,9 +148,9 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void RegisterDecoration(DecorationDraggableInstance decoration)
|
public void RegisterDecoration(DecorationDraggableInstance decoration)
|
||||||
{
|
{
|
||||||
if (decoration != null && !_placedDecorations.Contains(decoration))
|
if (decoration != null && !placedDecorations.Contains(decoration))
|
||||||
{
|
{
|
||||||
_placedDecorations.Add(decoration);
|
placedDecorations.Add(decoration);
|
||||||
Logging.Debug($"[StatueDecorationController] Decoration placed: {decoration.Data?.DecorationName}");
|
Logging.Debug($"[StatueDecorationController] Decoration placed: {decoration.Data?.DecorationName}");
|
||||||
|
|
||||||
// Auto-save state
|
// Auto-save state
|
||||||
@@ -164,9 +163,9 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void UnregisterDecoration(DecorationDraggableInstance decoration)
|
public void UnregisterDecoration(DecorationDraggableInstance decoration)
|
||||||
{
|
{
|
||||||
if (decoration != null && _placedDecorations.Contains(decoration))
|
if (decoration != null && placedDecorations.Contains(decoration))
|
||||||
{
|
{
|
||||||
_placedDecorations.Remove(decoration);
|
placedDecorations.Remove(decoration);
|
||||||
Logging.Debug($"[StatueDecorationController] Decoration removed: {decoration.Data?.DecorationName}");
|
Logging.Debug($"[StatueDecorationController] Decoration removed: {decoration.Data?.DecorationName}");
|
||||||
|
|
||||||
// Auto-save state
|
// Auto-save state
|
||||||
@@ -179,7 +178,7 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnTakePhoto()
|
private void OnTakePhoto()
|
||||||
{
|
{
|
||||||
if (_minigameCompleted)
|
if (minigameCompleted)
|
||||||
{
|
{
|
||||||
Logging.Debug("[StatueDecorationController] Minigame already completed");
|
Logging.Debug("[StatueDecorationController] Minigame already completed");
|
||||||
return;
|
return;
|
||||||
@@ -196,7 +195,7 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private System.Collections.IEnumerator CapturePhotoCoroutine()
|
private System.Collections.IEnumerator CapturePhotoCoroutine()
|
||||||
{
|
{
|
||||||
int decorationCount = _placedDecorations.Count;
|
int decorationCount = placedDecorations.Count;
|
||||||
bool captureSuccess = false;
|
bool captureSuccess = false;
|
||||||
string savedPhotoId = null;
|
string savedPhotoId = null;
|
||||||
|
|
||||||
@@ -244,7 +243,7 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
// Show completion feedback
|
// Show completion feedback
|
||||||
ShowCompletionFeedback();
|
ShowCompletionFeedback();
|
||||||
|
|
||||||
_minigameCompleted = true;
|
minigameCompleted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -306,13 +305,13 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
StatueDecorationData data = new StatueDecorationData
|
StatueDecorationData data = new StatueDecorationData
|
||||||
{
|
{
|
||||||
photoId = photoId,
|
photoId = photoId,
|
||||||
timestamp = System.DateTime.Now.ToString("o"),
|
timestamp = DateTime.Now.ToString("o"),
|
||||||
coordinateSystem = isUIRectTransform ? CoordinateSystemType.UIRectTransform : CoordinateSystemType.WorldSpace,
|
coordinateSystem = isUIRectTransform ? CoordinateSystemType.UIRectTransform : CoordinateSystemType.WorldSpace,
|
||||||
sourceStatueSize = statueSize
|
sourceStatueSize = statueSize
|
||||||
};
|
};
|
||||||
|
|
||||||
// Collect all decoration placements
|
// Collect all decoration placements
|
||||||
foreach (var decoration in _placedDecorations)
|
foreach (var decoration in placedDecorations)
|
||||||
{
|
{
|
||||||
if (decoration == null || decoration.Data == null) continue;
|
if (decoration == null || decoration.Data == null) continue;
|
||||||
|
|
||||||
@@ -343,8 +342,10 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void SaveStatueState()
|
private void SaveStatueState()
|
||||||
{
|
{
|
||||||
|
var settings = StatueDressupSettings.Instance?.Settings;
|
||||||
|
|
||||||
// Check if persistence is enabled
|
// Check if persistence is enabled
|
||||||
if (_settings == null || !_settings.EnableStatePersistence)
|
if (settings == null || !settings.EnableStatePersistence)
|
||||||
{
|
{
|
||||||
Logging.Debug("[StatueDecorationController] State persistence disabled");
|
Logging.Debug("[StatueDecorationController] State persistence disabled");
|
||||||
return;
|
return;
|
||||||
@@ -354,7 +355,7 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
// Save decoration ID + position + rotation for each placed item
|
// Save decoration ID + position + rotation for each placed item
|
||||||
// Respect MaxSavedDecorations limit
|
// Respect MaxSavedDecorations limit
|
||||||
|
|
||||||
Logging.Debug($"[StatueDecorationController] State saved to {_settings.StateSaveKey} (TODO: implement persistence)");
|
Logging.Debug($"[StatueDecorationController] State saved to {settings.StateSaveKey} (TODO: implement persistence)");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -362,15 +363,17 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void LoadStatueState()
|
private void LoadStatueState()
|
||||||
{
|
{
|
||||||
|
var settings = StatueDressupSettings.Instance?.Settings;
|
||||||
|
|
||||||
// Check if persistence is enabled
|
// Check if persistence is enabled
|
||||||
if (_settings == null || !_settings.EnableStatePersistence)
|
if (settings == null || !settings.EnableStatePersistence)
|
||||||
{
|
{
|
||||||
Logging.Debug("[StatueDecorationController] State persistence disabled");
|
Logging.Debug("[StatueDecorationController] State persistence disabled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if DecorationData is loaded
|
// Check if DecorationData is loaded
|
||||||
if (_decorationDataDict == null || _decorationDataDict.Count == 0)
|
if (DecorationDataManager.Instance == null || !DecorationDataManager.Instance.IsLoaded)
|
||||||
{
|
{
|
||||||
Logging.Warning("[StatueDecorationController] DecorationData not loaded yet. Cannot restore state.");
|
Logging.Warning("[StatueDecorationController] DecorationData not loaded yet. Cannot restore state.");
|
||||||
return;
|
return;
|
||||||
@@ -405,8 +408,8 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool SpawnSavedDecoration(DecorationPlacement placement)
|
private bool SpawnSavedDecoration(DecorationPlacement placement)
|
||||||
{
|
{
|
||||||
// Look up DecorationData from dictionary
|
// Look up DecorationData from manager
|
||||||
if (!_decorationDataDict.TryGetValue(placement.decorationId, out DecorationData decorationData))
|
if (!DecorationDataManager.Instance.TryGetData(placement.decorationId, out DecorationData decorationData))
|
||||||
{
|
{
|
||||||
Logging.Warning($"[StatueDecorationController] DecorationData not found for ID: {placement.decorationId}");
|
Logging.Warning($"[StatueDecorationController] DecorationData not found for ID: {placement.decorationId}");
|
||||||
return false;
|
return false;
|
||||||
@@ -425,23 +428,24 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
Transform canvasParent = statueParent.parent; // Typically the canvas or draggable container
|
Transform canvasParent = statueParent.parent; // Typically the canvas or draggable container
|
||||||
|
|
||||||
// Create callbacks for outline show/hide
|
// Create callbacks for outline show/hide
|
||||||
Logging.Debug($"[StatueDecorationController] MenuController is null: {menuController == null}");
|
System.Action showOutlineCallback = DecorationMenuController.Instance != null ? (System.Action)DecorationMenuController.Instance.ShowStatueOutline : null;
|
||||||
System.Action showOutlineCallback = menuController != null ? (System.Action)menuController.ShowStatueOutline : null;
|
System.Action hideOutlineCallback = DecorationMenuController.Instance != null ? (System.Action)DecorationMenuController.Instance.HideStatueOutline : null;
|
||||||
System.Action hideOutlineCallback = menuController != null ? (System.Action)menuController.HideStatueOutline : null;
|
|
||||||
Logging.Debug($"[StatueDecorationController] Show outline callback is null: {showOutlineCallback == null}");
|
|
||||||
|
|
||||||
// Initialize in "placed" state (skip drag logic)
|
// Create context for placed decoration
|
||||||
instance.InitializeAsPlaced(
|
var context = DecorationDragContext.CreateForPlaced(
|
||||||
decorationData,
|
decorationData,
|
||||||
this,
|
this,
|
||||||
_settings,
|
StatueDressupSettings.Instance.Settings,
|
||||||
statueArea, // Pass statue outline for overlap detection
|
statueArea,
|
||||||
canvasParent, // Pass canvas parent for reparenting during pickup
|
canvasParent,
|
||||||
showOutlineCallback, // Show outline when picking up
|
showOutlineCallback,
|
||||||
hideOutlineCallback, // Hide outline when drag ends
|
hideOutlineCallback,
|
||||||
hideOutlineCallback // Also use hide callback for onFinished
|
hideOutlineCallback
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Initialize in "placed" state (skip drag logic)
|
||||||
|
instance.InitializeWithContext(context);
|
||||||
|
|
||||||
// Apply saved transform
|
// Apply saved transform
|
||||||
instance.transform.localPosition = placement.localPosition;
|
instance.transform.localPosition = placement.localPosition;
|
||||||
instance.transform.localScale = placement.localScale;
|
instance.transform.localScale = placement.localScale;
|
||||||
@@ -479,9 +483,6 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
{
|
{
|
||||||
base.OnManagedDestroy();
|
base.OnManagedDestroy();
|
||||||
|
|
||||||
// Release Addressables handle
|
|
||||||
AddressablesUtility.ReleaseHandle(_decorationDataHandle);
|
|
||||||
|
|
||||||
// Cleanup button listeners
|
// Cleanup button listeners
|
||||||
if (takePhotoButton != null)
|
if (takePhotoButton != null)
|
||||||
{
|
{
|
||||||
@@ -494,6 +495,12 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
// {
|
// {
|
||||||
// openGalleryButton.onClick.RemoveListener(OnOpenGallery);
|
// openGalleryButton.onClick.RemoveListener(OnOpenGallery);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// Singleton cleanup
|
||||||
|
if (Instance == this)
|
||||||
|
{
|
||||||
|
Instance = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void ExitToAppleHills()
|
public async void ExitToAppleHills()
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
using Core;
|
||||||
|
using Core.Lifecycle;
|
||||||
|
|
||||||
|
namespace Minigames.StatueDressup.Controllers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Singleton manager for StatueDressup settings access.
|
||||||
|
/// Loads settings once and provides global access point.
|
||||||
|
/// </summary>
|
||||||
|
public class StatueDressupSettings : ManagedBehaviour
|
||||||
|
{
|
||||||
|
public static StatueDressupSettings Instance { get; private set; }
|
||||||
|
|
||||||
|
private AppleHills.Core.Settings.IStatueDressupSettings settings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the settings instance
|
||||||
|
/// </summary>
|
||||||
|
public AppleHills.Core.Settings.IStatueDressupSettings Settings => settings;
|
||||||
|
|
||||||
|
internal override void OnManagedAwake()
|
||||||
|
{
|
||||||
|
base.OnManagedAwake();
|
||||||
|
|
||||||
|
// Singleton pattern
|
||||||
|
if (Instance != null && Instance != this)
|
||||||
|
{
|
||||||
|
Logging.Warning("[StatueDressupSettings] Duplicate instance detected. Destroying duplicate.");
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
// Load settings once
|
||||||
|
settings = GameManager.GetSettingsObject<AppleHills.Core.Settings.IStatueDressupSettings>();
|
||||||
|
|
||||||
|
if (settings == null)
|
||||||
|
{
|
||||||
|
Logging.Error("[StatueDressupSettings] Failed to load StatueDressupSettings!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logging.Debug("[StatueDressupSettings] Settings loaded successfully");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void OnManagedDestroy()
|
||||||
|
{
|
||||||
|
base.OnManagedDestroy();
|
||||||
|
|
||||||
|
if (Instance == this)
|
||||||
|
{
|
||||||
|
Instance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: acf5624b19664ce5900f1a7c1328edbc
|
||||||
|
timeCreated: 1764240158
|
||||||
@@ -15,6 +15,8 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class StatuePhotoGalleryController : ManagedBehaviour
|
public class StatuePhotoGalleryController : ManagedBehaviour
|
||||||
{
|
{
|
||||||
|
public static StatuePhotoGalleryController Instance { get; private set; }
|
||||||
|
|
||||||
[Header("Gallery UI")]
|
[Header("Gallery UI")]
|
||||||
[SerializeField] private Transform gridContainer;
|
[SerializeField] private Transform gridContainer;
|
||||||
[SerializeField] private PhotoGridItem gridItemPrefab;
|
[SerializeField] private PhotoGridItem gridItemPrefab;
|
||||||
@@ -29,25 +31,33 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
[SerializeField] private Button nextPageButton;
|
[SerializeField] private Button nextPageButton;
|
||||||
[SerializeField] private Text pageStatusText;
|
[SerializeField] private Text pageStatusText;
|
||||||
|
|
||||||
private AppleHills.Core.Settings.IStatueDressupSettings _settings;
|
private int currentPage;
|
||||||
private int _currentPage;
|
private List<string> allPhotoIds = new List<string>();
|
||||||
private List<string> _allPhotoIds = new List<string>();
|
private Dictionary<string, PhotoGridItem> activeGridItems = new Dictionary<string, PhotoGridItem>();
|
||||||
private Dictionary<string, PhotoGridItem> _activeGridItems = new Dictionary<string, PhotoGridItem>();
|
private Dictionary<string, Texture2D> thumbnailCache = new Dictionary<string, Texture2D>();
|
||||||
private Dictionary<string, Texture2D> _thumbnailCache = new Dictionary<string, Texture2D>();
|
private Dictionary<string, Texture2D> fullPhotoCache = new Dictionary<string, Texture2D>(); // Cache full photos for enlargement
|
||||||
private Dictionary<string, Texture2D> _fullPhotoCache = new Dictionary<string, Texture2D>(); // Cache full photos for enlargement
|
private Queue<string> thumbnailCacheOrder = new Queue<string>();
|
||||||
private Queue<string> _thumbnailCacheOrder = new Queue<string>();
|
private bool isLoadingPage;
|
||||||
private bool _isLoadingPage;
|
private PhotoEnlargeController enlargeController;
|
||||||
private PhotoEnlargeController _enlargeController;
|
|
||||||
|
|
||||||
internal override void OnManagedStart()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
base.OnManagedStart();
|
base.OnManagedStart();
|
||||||
|
|
||||||
// Get settings
|
// Singleton pattern
|
||||||
_settings = GameManager.GetSettingsObject<AppleHills.Core.Settings.IStatueDressupSettings>();
|
if (Instance != null && Instance != this)
|
||||||
|
{
|
||||||
|
Logging.Warning("[StatuePhotoGalleryController] Duplicate instance detected. Destroying duplicate.");
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
var settings = StatueDressupSettings.Instance?.Settings;
|
||||||
|
|
||||||
// Initialize enlarge controller
|
// Initialize enlarge controller
|
||||||
_enlargeController = new PhotoEnlargeController(backdrop, enlargedContainer, _settings?.GalleryAnimationDuration ?? 0.3f);
|
enlargeController = new PhotoEnlargeController(backdrop, enlargedContainer, settings?.GalleryAnimationDuration ?? 0.3f);
|
||||||
|
|
||||||
// Setup page navigation buttons
|
// Setup page navigation buttons
|
||||||
if (previousPageButton != null)
|
if (previousPageButton != null)
|
||||||
@@ -76,10 +86,10 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
ClearGrid();
|
ClearGrid();
|
||||||
|
|
||||||
// Get all photo IDs
|
// Get all photo IDs
|
||||||
_allPhotoIds = PhotoManager.GetAllPhotoIds(CaptureType.StatueMinigame);
|
allPhotoIds = PhotoManager.GetAllPhotoIds(CaptureType.StatueMinigame);
|
||||||
_currentPage = 0;
|
currentPage = 0;
|
||||||
|
|
||||||
Logging.Debug($"[StatuePhotoGalleryController] Gallery refreshed: {_allPhotoIds.Count} photos");
|
Logging.Debug($"[StatuePhotoGalleryController] Gallery refreshed: {allPhotoIds.Count} photos");
|
||||||
|
|
||||||
// Display first page
|
// Display first page
|
||||||
DisplayCurrentPage();
|
DisplayCurrentPage();
|
||||||
@@ -90,18 +100,18 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void DisplayCurrentPage()
|
private void DisplayCurrentPage()
|
||||||
{
|
{
|
||||||
if (_isLoadingPage) return;
|
if (isLoadingPage) return;
|
||||||
|
|
||||||
_isLoadingPage = true;
|
isLoadingPage = true;
|
||||||
|
|
||||||
// Clear current grid
|
// Clear current grid
|
||||||
ClearGrid();
|
ClearGrid();
|
||||||
|
|
||||||
// Get photos for current page
|
// Get photos for current page
|
||||||
int itemsPerPage = _settings?.GalleryItemsPerPage ?? 20;
|
int itemsPerPage = StatueDressupSettings.Instance?.Settings?.GalleryItemsPerPage ?? 20;
|
||||||
List<string> pagePhotoIds = PhotoManager.GetPhotoIdsPage(CaptureType.StatueMinigame, _currentPage, itemsPerPage);
|
List<string> pagePhotoIds = PhotoManager.GetPhotoIdsPage(CaptureType.StatueMinigame, currentPage, itemsPerPage);
|
||||||
|
|
||||||
Logging.Debug($"[StatuePhotoGalleryController] Displaying page {_currentPage + 1}: {pagePhotoIds.Count} items");
|
Logging.Debug($"[StatuePhotoGalleryController] Displaying page {currentPage + 1}: {pagePhotoIds.Count} items");
|
||||||
|
|
||||||
// Spawn grid items for this page
|
// Spawn grid items for this page
|
||||||
foreach (string photoId in pagePhotoIds)
|
foreach (string photoId in pagePhotoIds)
|
||||||
@@ -113,10 +123,10 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
UpdatePageButtons();
|
UpdatePageButtons();
|
||||||
|
|
||||||
// Update status text
|
// Update status text
|
||||||
int totalPages = Mathf.CeilToInt((float)_allPhotoIds.Count / itemsPerPage);
|
int totalPages = Mathf.CeilToInt((float)allPhotoIds.Count / itemsPerPage);
|
||||||
UpdateStatusText($"Page {_currentPage + 1}/{totalPages} ({_allPhotoIds.Count} photos)");
|
UpdateStatusText($"Page {currentPage + 1}/{totalPages} ({allPhotoIds.Count} photos)");
|
||||||
|
|
||||||
_isLoadingPage = false;
|
isLoadingPage = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -124,19 +134,19 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdatePageButtons()
|
private void UpdatePageButtons()
|
||||||
{
|
{
|
||||||
int itemsPerPage = _settings?.GalleryItemsPerPage ?? 20;
|
int itemsPerPage = StatueDressupSettings.Instance?.Settings?.GalleryItemsPerPage ?? 20;
|
||||||
int totalPages = Mathf.CeilToInt((float)_allPhotoIds.Count / itemsPerPage);
|
int totalPages = Mathf.CeilToInt((float)allPhotoIds.Count / itemsPerPage);
|
||||||
|
|
||||||
// Enable/disable previous button
|
// Enable/disable previous button
|
||||||
if (previousPageButton != null)
|
if (previousPageButton != null)
|
||||||
{
|
{
|
||||||
previousPageButton.interactable = _currentPage > 0;
|
previousPageButton.interactable = currentPage > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable/disable next button
|
// Enable/disable next button
|
||||||
if (nextPageButton != null)
|
if (nextPageButton != null)
|
||||||
{
|
{
|
||||||
nextPageButton.interactable = _currentPage < totalPages - 1;
|
nextPageButton.interactable = currentPage < totalPages - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,11 +155,11 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnPreviousPageClicked()
|
private void OnPreviousPageClicked()
|
||||||
{
|
{
|
||||||
if (_currentPage > 0)
|
if (currentPage > 0)
|
||||||
{
|
{
|
||||||
_currentPage--;
|
currentPage--;
|
||||||
DisplayCurrentPage();
|
DisplayCurrentPage();
|
||||||
Logging.Debug($"[StatuePhotoGalleryController] Navigated to previous page: {_currentPage}");
|
Logging.Debug($"[StatuePhotoGalleryController] Navigated to previous page: {currentPage}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,14 +168,14 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnNextPageClicked()
|
private void OnNextPageClicked()
|
||||||
{
|
{
|
||||||
int itemsPerPage = _settings?.GalleryItemsPerPage ?? 20;
|
int itemsPerPage = StatueDressupSettings.Instance?.Settings?.GalleryItemsPerPage ?? 20;
|
||||||
int totalPages = Mathf.CeilToInt((float)_allPhotoIds.Count / itemsPerPage);
|
int totalPages = Mathf.CeilToInt((float)allPhotoIds.Count / itemsPerPage);
|
||||||
|
|
||||||
if (_currentPage < totalPages - 1)
|
if (currentPage < totalPages - 1)
|
||||||
{
|
{
|
||||||
_currentPage++;
|
currentPage++;
|
||||||
DisplayCurrentPage();
|
DisplayCurrentPage();
|
||||||
Logging.Debug($"[StatuePhotoGalleryController] Navigated to next page: {_currentPage}");
|
Logging.Debug($"[StatuePhotoGalleryController] Navigated to next page: {currentPage}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +184,7 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void SpawnGridItem(string photoId)
|
private void SpawnGridItem(string photoId)
|
||||||
{
|
{
|
||||||
if (_activeGridItems.ContainsKey(photoId))
|
if (activeGridItems.ContainsKey(photoId))
|
||||||
{
|
{
|
||||||
Logging.Warning($"[StatuePhotoGalleryController] Grid item already exists: {photoId}");
|
Logging.Warning($"[StatuePhotoGalleryController] Grid item already exists: {photoId}");
|
||||||
return;
|
return;
|
||||||
@@ -183,7 +193,7 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
PhotoGridItem gridItem = Instantiate(gridItemPrefab, gridContainer);
|
PhotoGridItem gridItem = Instantiate(gridItemPrefab, gridContainer);
|
||||||
gridItem.Initialize(photoId, this);
|
gridItem.Initialize(photoId, this);
|
||||||
|
|
||||||
_activeGridItems[photoId] = gridItem;
|
activeGridItems[photoId] = gridItem;
|
||||||
|
|
||||||
// Load thumbnail asynchronously
|
// Load thumbnail asynchronously
|
||||||
StartCoroutine(LoadThumbnailAsync(photoId, gridItem));
|
StartCoroutine(LoadThumbnailAsync(photoId, gridItem));
|
||||||
@@ -195,7 +205,7 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
private IEnumerator LoadThumbnailAsync(string photoId, PhotoGridItem gridItem)
|
private IEnumerator LoadThumbnailAsync(string photoId, PhotoGridItem gridItem)
|
||||||
{
|
{
|
||||||
// Check cache first
|
// Check cache first
|
||||||
if (_thumbnailCache.TryGetValue(photoId, out Texture2D cachedThumbnail))
|
if (thumbnailCache.TryGetValue(photoId, out Texture2D cachedThumbnail))
|
||||||
{
|
{
|
||||||
gridItem.SetThumbnail(cachedThumbnail);
|
gridItem.SetThumbnail(cachedThumbnail);
|
||||||
yield break;
|
yield break;
|
||||||
@@ -214,7 +224,7 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create thumbnail
|
// Create thumbnail
|
||||||
int thumbSize = _settings?.GalleryThumbnailSize ?? 256;
|
int thumbSize = StatueDressupSettings.Instance?.Settings?.GalleryThumbnailSize ?? 256;
|
||||||
Texture2D thumbnail = PhotoManager.CreateThumbnail(fullPhoto, thumbSize);
|
Texture2D thumbnail = PhotoManager.CreateThumbnail(fullPhoto, thumbSize);
|
||||||
|
|
||||||
// Destroy full photo immediately (we only need thumbnail)
|
// Destroy full photo immediately (we only need thumbnail)
|
||||||
@@ -236,19 +246,19 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
private void CacheThumbnail(string photoId, Texture2D thumbnail)
|
private void CacheThumbnail(string photoId, Texture2D thumbnail)
|
||||||
{
|
{
|
||||||
// Add to cache
|
// Add to cache
|
||||||
_thumbnailCache[photoId] = thumbnail;
|
thumbnailCache[photoId] = thumbnail;
|
||||||
_thumbnailCacheOrder.Enqueue(photoId);
|
thumbnailCacheOrder.Enqueue(photoId);
|
||||||
|
|
||||||
// Evict oldest if over limit
|
// Evict oldest if over limit
|
||||||
int maxCached = _settings?.GalleryMaxCachedThumbnails ?? 50;
|
int maxCached = StatueDressupSettings.Instance?.Settings?.GalleryMaxCachedThumbnails ?? 50;
|
||||||
while (_thumbnailCache.Count > maxCached && _thumbnailCacheOrder.Count > 0)
|
while (thumbnailCache.Count > maxCached && thumbnailCacheOrder.Count > 0)
|
||||||
{
|
{
|
||||||
string oldestId = _thumbnailCacheOrder.Dequeue();
|
string oldestId = thumbnailCacheOrder.Dequeue();
|
||||||
|
|
||||||
if (_thumbnailCache.TryGetValue(oldestId, out Texture2D oldThumbnail))
|
if (thumbnailCache.TryGetValue(oldestId, out Texture2D oldThumbnail))
|
||||||
{
|
{
|
||||||
Destroy(oldThumbnail);
|
Destroy(oldThumbnail);
|
||||||
_thumbnailCache.Remove(oldestId);
|
thumbnailCache.Remove(oldestId);
|
||||||
Logging.Debug($"[StatuePhotoGalleryController] Evicted thumbnail from cache: {oldestId}");
|
Logging.Debug($"[StatuePhotoGalleryController] Evicted thumbnail from cache: {oldestId}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,28 +269,28 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void OnGridItemClicked(PhotoGridItem gridItem, string photoId)
|
public void OnGridItemClicked(PhotoGridItem gridItem, string photoId)
|
||||||
{
|
{
|
||||||
if (_enlargeController == null)
|
if (enlargeController == null)
|
||||||
{
|
{
|
||||||
Logging.Error("[StatuePhotoGalleryController] Enlarge controller not initialized");
|
Logging.Error("[StatuePhotoGalleryController] Enlarge controller not initialized");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If already enlarged, shrink it
|
// If already enlarged, shrink it
|
||||||
if (_enlargeController.IsPhotoEnlarged)
|
if (enlargeController.IsPhotoEnlarged)
|
||||||
{
|
{
|
||||||
_enlargeController.ShrinkPhoto();
|
enlargeController.ShrinkPhoto();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logging.Debug($"[StatuePhotoGalleryController] Enlarging photo: {photoId}");
|
Logging.Debug($"[StatuePhotoGalleryController] Enlarging photo: {photoId}");
|
||||||
|
|
||||||
float enlargedScale = _settings?.GalleryEnlargedScale ?? 2.5f;
|
float enlargedScale = StatueDressupSettings.Instance?.Settings?.GalleryEnlargedScale ?? 2.5f;
|
||||||
|
|
||||||
// Check cache first
|
// Check cache first
|
||||||
if (_fullPhotoCache.TryGetValue(photoId, out Texture2D fullPhoto))
|
if (fullPhotoCache.TryGetValue(photoId, out Texture2D fullPhoto))
|
||||||
{
|
{
|
||||||
// Use cached photo
|
// Use cached photo
|
||||||
_enlargeController.EnlargePhoto(gridItem, enlargedPreviewPrefab != null ? enlargedPreviewPrefab : gridItem.gameObject, fullPhoto, enlargedScale);
|
enlargeController.EnlargePhoto(gridItem, enlargedPreviewPrefab != null ? enlargedPreviewPrefab : gridItem.gameObject, fullPhoto, enlargedScale);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -294,12 +304,12 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache it (limited cache)
|
// Cache it (limited cache)
|
||||||
if (_fullPhotoCache.Count < 10) // Keep only recent 10 full photos
|
if (fullPhotoCache.Count < 10) // Keep only recent 10 full photos
|
||||||
{
|
{
|
||||||
_fullPhotoCache[photoId] = fullPhoto;
|
fullPhotoCache[photoId] = fullPhoto;
|
||||||
}
|
}
|
||||||
|
|
||||||
_enlargeController.EnlargePhoto(gridItem, enlargedPreviewPrefab != null ? enlargedPreviewPrefab : gridItem.gameObject, fullPhoto, enlargedScale);
|
enlargeController.EnlargePhoto(gridItem, enlargedPreviewPrefab != null ? enlargedPreviewPrefab : gridItem.gameObject, fullPhoto, enlargedScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,20 +318,20 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void CleanupGallery()
|
public void CleanupGallery()
|
||||||
{
|
{
|
||||||
if (_enlargeController != null)
|
if (enlargeController != null)
|
||||||
{
|
{
|
||||||
_enlargeController.Cleanup();
|
enlargeController.Cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up cached full photos
|
// Clean up cached full photos
|
||||||
foreach (var photo in _fullPhotoCache.Values)
|
foreach (var photo in fullPhotoCache.Values)
|
||||||
{
|
{
|
||||||
if (photo != null)
|
if (photo != null)
|
||||||
{
|
{
|
||||||
Destroy(photo);
|
Destroy(photo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_fullPhotoCache.Clear();
|
fullPhotoCache.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -341,12 +351,12 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
private void ClearGrid()
|
private void ClearGrid()
|
||||||
{
|
{
|
||||||
// Destroy grid items
|
// Destroy grid items
|
||||||
foreach (var gridItem in _activeGridItems.Values)
|
foreach (var gridItem in activeGridItems.Values)
|
||||||
{
|
{
|
||||||
if (gridItem != null)
|
if (gridItem != null)
|
||||||
Destroy(gridItem.gameObject);
|
Destroy(gridItem.gameObject);
|
||||||
}
|
}
|
||||||
_activeGridItems.Clear();
|
activeGridItems.Clear();
|
||||||
|
|
||||||
Logging.Debug("[StatuePhotoGalleryController] Grid cleared");
|
Logging.Debug("[StatuePhotoGalleryController] Grid cleared");
|
||||||
}
|
}
|
||||||
@@ -359,13 +369,13 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
ClearGrid();
|
ClearGrid();
|
||||||
|
|
||||||
// Clear thumbnail cache
|
// Clear thumbnail cache
|
||||||
foreach (var thumbnail in _thumbnailCache.Values)
|
foreach (var thumbnail in thumbnailCache.Values)
|
||||||
{
|
{
|
||||||
if (thumbnail != null)
|
if (thumbnail != null)
|
||||||
Destroy(thumbnail);
|
Destroy(thumbnail);
|
||||||
}
|
}
|
||||||
_thumbnailCache.Clear();
|
thumbnailCache.Clear();
|
||||||
_thumbnailCacheOrder.Clear();
|
thumbnailCacheOrder.Clear();
|
||||||
|
|
||||||
Logging.Debug("[StatuePhotoGalleryController] Gallery fully cleared");
|
Logging.Debug("[StatuePhotoGalleryController] Gallery fully cleared");
|
||||||
}
|
}
|
||||||
@@ -374,7 +384,13 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
{
|
{
|
||||||
base.OnManagedDestroy();
|
base.OnManagedDestroy();
|
||||||
|
|
||||||
// Cleanup
|
// Singleton cleanup
|
||||||
|
if (Instance == this)
|
||||||
|
{
|
||||||
|
Instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up cached textures
|
||||||
ClearGallery();
|
ClearGallery();
|
||||||
CleanupGallery();
|
CleanupGallery();
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
using System.Collections.Generic;
|
using Core;
|
||||||
using Core;
|
|
||||||
using Core.Lifecycle;
|
using Core.Lifecycle;
|
||||||
|
using Minigames.StatueDressup.Controllers;
|
||||||
using Minigames.StatueDressup.Data;
|
using Minigames.StatueDressup.Data;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace Minigames.StatueDressup.Display
|
namespace Minigames.StatueDressup.Display
|
||||||
@@ -27,10 +26,6 @@ namespace Minigames.StatueDressup.Display
|
|||||||
[Header("Debug")]
|
[Header("Debug")]
|
||||||
[SerializeField] private bool showDebugInfo = true;
|
[SerializeField] private bool showDebugInfo = true;
|
||||||
|
|
||||||
private Dictionary<string, DecorationData> decorationDataDict;
|
|
||||||
private AsyncOperationHandle<IList<DecorationData>> decorationDataHandle;
|
|
||||||
private AppleHills.Core.Settings.IStatueDressupSettings settings;
|
|
||||||
|
|
||||||
internal override void OnManagedStart()
|
internal override void OnManagedStart()
|
||||||
{
|
{
|
||||||
base.OnManagedStart();
|
base.OnManagedStart();
|
||||||
@@ -44,81 +39,40 @@ namespace Minigames.StatueDressup.Display
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get settings
|
// DecorationDataManager exists (initialized in OnManagedAwake) but data loads async
|
||||||
settings = GameManager.GetSettingsObject<AppleHills.Core.Settings.IStatueDressupSettings>();
|
// Wait for data to finish loading before displaying decorations
|
||||||
|
StartCoroutine(WaitForDataAndDisplay());
|
||||||
// Start async loading via coroutine wrapper
|
|
||||||
StartCoroutine(LoadAndDisplayDecorationsCoroutine());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Coroutine wrapper for async loading and display
|
/// Wait for DecorationDataManager to finish loading data before displaying decorations
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private System.Collections.IEnumerator LoadAndDisplayDecorationsCoroutine()
|
private System.Collections.IEnumerator WaitForDataAndDisplay()
|
||||||
{
|
{
|
||||||
// Convert async Task to coroutine-compatible operation
|
// Wait for data to load (manager is guaranteed to exist)
|
||||||
var loadTask = LoadDecorationDataAsync();
|
while (!DecorationDataManager.Instance.IsLoaded)
|
||||||
|
|
||||||
// Wait for async operation to complete
|
|
||||||
while (!loadTask.IsCompleted)
|
|
||||||
{
|
{
|
||||||
yield return null;
|
yield return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for exceptions
|
if (showDebugInfo)
|
||||||
if (loadTask.IsFaulted)
|
|
||||||
{
|
{
|
||||||
Logging.Error($"[StatueDecorationLoader] Failed to load decoration data: {loadTask.Exception?.GetBaseException().Message}");
|
Logging.Debug("[StatueDecorationLoader] DecorationData loaded, displaying decorations");
|
||||||
yield break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load and display decorations
|
// Load and display decorations
|
||||||
LoadAndDisplayDecorations();
|
LoadAndDisplayDecorations();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Load all DecorationData assets via Addressables and build lookup dictionary
|
|
||||||
/// </summary>
|
|
||||||
private async System.Threading.Tasks.Task LoadDecorationDataAsync()
|
|
||||||
{
|
|
||||||
string label = settings?.DecorationDataLabel;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(label))
|
|
||||||
{
|
|
||||||
Logging.Error("[StatueDecorationLoader] Decoration data label not set in settings!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (showDebugInfo)
|
|
||||||
{
|
|
||||||
Logging.Debug($"[StatueDecorationLoader] Loading DecorationData with label '{label}'...");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use utility to load all DecorationData and create dictionary by ID
|
|
||||||
var result = await AddressablesUtility.LoadAssetsByLabelAsync<DecorationData, string>(
|
|
||||||
label,
|
|
||||||
data => data.DecorationId, // Key selector: use DecorationId as key
|
|
||||||
progress => { /* Optional: could show loading bar */ }
|
|
||||||
);
|
|
||||||
|
|
||||||
decorationDataDict = result.dictionary;
|
|
||||||
decorationDataHandle = result.handle;
|
|
||||||
|
|
||||||
if (showDebugInfo)
|
|
||||||
{
|
|
||||||
Logging.Debug($"[StatueDecorationLoader] Loaded {decorationDataDict.Count} DecorationData assets");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Load decoration metadata and spawn decorations
|
/// Load decoration metadata and spawn decorations
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void LoadAndDisplayDecorations()
|
public void LoadAndDisplayDecorations()
|
||||||
{
|
{
|
||||||
// Check if DecorationData is loaded
|
// Check if DecorationData is loaded via manager
|
||||||
if (decorationDataDict == null || decorationDataDict.Count == 0)
|
if (DecorationDataManager.Instance == null || !DecorationDataManager.Instance.IsLoaded)
|
||||||
{
|
{
|
||||||
Logging.Warning("[StatueDecorationLoader] DecorationData not loaded yet. Cannot display decorations.");
|
Logging.Warning("[StatueDecorationLoader] DecorationDataManager not ready. Cannot display decorations.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,12 +160,12 @@ namespace Minigames.StatueDressup.Display
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Spawn a single decoration from placement data
|
/// Spawn a single decoration from placement data
|
||||||
/// Looks up DecorationData from pre-loaded dictionary and applies coordinate conversion
|
/// Looks up DecorationData from manager and applies coordinate conversion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool SpawnDecoration(DecorationPlacement placement, float conversionFactor, Vector2 sourceStatueSize, Vector2 targetStatueWorldSize)
|
private bool SpawnDecoration(DecorationPlacement placement, float conversionFactor, Vector2 sourceStatueSize, Vector2 targetStatueWorldSize)
|
||||||
{
|
{
|
||||||
// Look up DecorationData from dictionary
|
// Look up DecorationData from manager
|
||||||
if (!decorationDataDict.TryGetValue(placement.decorationId, out DecorationData decorationData))
|
if (!DecorationDataManager.Instance.TryGetData(placement.decorationId, out DecorationData decorationData))
|
||||||
{
|
{
|
||||||
Logging.Warning($"[StatueDecorationLoader] DecorationData not found for ID: {placement.decorationId}");
|
Logging.Warning($"[StatueDecorationLoader] DecorationData not found for ID: {placement.decorationId}");
|
||||||
return false;
|
return false;
|
||||||
@@ -375,14 +329,7 @@ namespace Minigames.StatueDressup.Display
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// Cleanup handled by DecorationDataManager - no need for OnDestroy here
|
||||||
/// Cleanup - release Addressables handle
|
|
||||||
/// </summary>
|
|
||||||
private void OnDestroy()
|
|
||||||
{
|
|
||||||
// Release DecorationData handle
|
|
||||||
AddressablesUtility.ReleaseHandle(decorationDataHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reload decorations (useful for testing)
|
/// Reload decorations (useful for testing)
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
using Minigames.StatueDressup.Data;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Minigames.StatueDressup.DragDrop
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Context object for initializing draggable decorations.
|
||||||
|
/// Consolidates multiple parameters into a single, cohesive object.
|
||||||
|
/// </summary>
|
||||||
|
public class DecorationDragContext
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The decoration data to display
|
||||||
|
/// </summary>
|
||||||
|
public DecorationData Data { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The statue outline area for overlap detection
|
||||||
|
/// </summary>
|
||||||
|
public RectTransform StatueOutline { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parent transform for decorations placed on statue
|
||||||
|
/// </summary>
|
||||||
|
public Transform StatueParent { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parent transform for dragging (usually canvas or draggable container)
|
||||||
|
/// </summary>
|
||||||
|
public Transform CanvasParent { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controller for registering/unregistering decorations
|
||||||
|
/// </summary>
|
||||||
|
public Controllers.StatueDecorationController Controller { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Settings for the minigame
|
||||||
|
/// </summary>
|
||||||
|
public AppleHills.Core.Settings.IStatueDressupSettings Settings { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback when drag operation finishes (success or failure)
|
||||||
|
/// </summary>
|
||||||
|
public System.Action OnFinished { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback to show statue outline during drag
|
||||||
|
/// </summary>
|
||||||
|
public System.Action OnShowOutline { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback to hide statue outline after drag
|
||||||
|
/// </summary>
|
||||||
|
public System.Action OnHideOutline { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this decoration is being initialized as already placed (from saved state)
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPlaced { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a context for a new decoration being dragged from menu
|
||||||
|
/// </summary>
|
||||||
|
public static DecorationDragContext CreateForNewDrag(
|
||||||
|
DecorationData data,
|
||||||
|
RectTransform statueOutline,
|
||||||
|
Transform statueParent,
|
||||||
|
Controllers.StatueDecorationController controller,
|
||||||
|
AppleHills.Core.Settings.IStatueDressupSettings settings,
|
||||||
|
System.Action onFinished,
|
||||||
|
System.Action onShowOutline,
|
||||||
|
System.Action onHideOutline)
|
||||||
|
{
|
||||||
|
return new DecorationDragContext
|
||||||
|
{
|
||||||
|
Data = data,
|
||||||
|
StatueOutline = statueOutline,
|
||||||
|
StatueParent = statueParent,
|
||||||
|
Controller = controller,
|
||||||
|
Settings = settings,
|
||||||
|
OnFinished = onFinished,
|
||||||
|
OnShowOutline = onShowOutline,
|
||||||
|
OnHideOutline = onHideOutline,
|
||||||
|
IsPlaced = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a context for a decoration being loaded from saved state
|
||||||
|
/// </summary>
|
||||||
|
public static DecorationDragContext CreateForPlaced(
|
||||||
|
DecorationData data,
|
||||||
|
Controllers.StatueDecorationController controller,
|
||||||
|
AppleHills.Core.Settings.IStatueDressupSettings settings,
|
||||||
|
RectTransform statueOutline = null,
|
||||||
|
Transform canvasParent = null,
|
||||||
|
System.Action onShowOutline = null,
|
||||||
|
System.Action onHideOutline = null,
|
||||||
|
System.Action onFinished = null)
|
||||||
|
{
|
||||||
|
return new DecorationDragContext
|
||||||
|
{
|
||||||
|
Data = data,
|
||||||
|
StatueOutline = statueOutline,
|
||||||
|
CanvasParent = canvasParent,
|
||||||
|
Controller = controller,
|
||||||
|
Settings = settings,
|
||||||
|
OnShowOutline = onShowOutline,
|
||||||
|
OnHideOutline = onHideOutline,
|
||||||
|
OnFinished = onFinished,
|
||||||
|
IsPlaced = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8f2a2c34f6ce482ba117f39cb669e11f
|
||||||
|
timeCreated: 1764240188
|
||||||
@@ -20,36 +20,36 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
[SerializeField] private Image decorationImage;
|
[SerializeField] private Image decorationImage;
|
||||||
[SerializeField] private CanvasGroup canvasGroup;
|
[SerializeField] private CanvasGroup canvasGroup;
|
||||||
|
|
||||||
private DecorationData _decorationData;
|
private DecorationData decorationData;
|
||||||
private RectTransform _rectTransform;
|
private RectTransform rectTransform;
|
||||||
private Canvas _canvas;
|
private Canvas canvas;
|
||||||
private Transform _canvasParent; // Parent transform for dragging (usually canvas or draggable container)
|
private Transform canvasParent; // Parent transform for dragging (usually canvas or draggable container)
|
||||||
private RectTransform _statueOutline;
|
private RectTransform statueOutline;
|
||||||
private Transform _statueParent;
|
private Transform statueParent;
|
||||||
private StatueDecorationController _controller;
|
private StatueDecorationController controller;
|
||||||
private AppleHills.Core.Settings.IStatueDressupSettings _settings;
|
private AppleHills.Core.Settings.IStatueDressupSettings settings;
|
||||||
private System.Action _onFinishedCallback;
|
private System.Action onFinishedCallback;
|
||||||
private System.Action _onShowOutlineCallback;
|
private System.Action onShowOutlineCallback;
|
||||||
private System.Action _onHideOutlineCallback;
|
private System.Action onHideOutlineCallback;
|
||||||
|
|
||||||
private bool _isDragging;
|
private bool isDragging;
|
||||||
private bool _isPlacedOnStatue;
|
private bool isPlacedOnStatue;
|
||||||
private Vector3 _dragOffset;
|
private Vector3 dragOffset;
|
||||||
private bool _dragStarted; // Track if drag actually started (vs just a click)
|
private bool dragStarted; // Track if drag actually started (vs just a click)
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
public DecorationData Data => _decorationData;
|
public DecorationData Data => decorationData;
|
||||||
public bool IsPlacedOnStatue => _isPlacedOnStatue;
|
public bool IsPlacedOnStatue => isPlacedOnStatue;
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
_rectTransform = GetComponent<RectTransform>();
|
rectTransform = GetComponent<RectTransform>();
|
||||||
_canvas = GetComponentInParent<Canvas>();
|
canvas = GetComponentInParent<Canvas>();
|
||||||
|
|
||||||
// Store initial parent for dragging context
|
// Store initial parent for dragging context
|
||||||
if (transform.parent != null)
|
if (transform.parent != null)
|
||||||
{
|
{
|
||||||
_canvasParent = transform.parent;
|
canvasParent = transform.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canvasGroup == null)
|
if (canvasGroup == null)
|
||||||
@@ -65,87 +65,87 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initialize the draggable instance
|
/// Initialize with context object (preferred method)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Initialize(DecorationData data, RectTransform statueOutline, Transform statueParent,
|
public void InitializeWithContext(DecorationDragContext context)
|
||||||
StatueDecorationController controller, AppleHills.Core.Settings.IStatueDressupSettings settings,
|
|
||||||
System.Action onFinishedCallback, System.Action onShowOutline = null, System.Action onHideOutline = null)
|
|
||||||
{
|
{
|
||||||
_decorationData = data;
|
if (context == null)
|
||||||
_statueOutline = statueOutline;
|
{
|
||||||
_statueParent = statueParent;
|
Logging.Error("[DecorationDraggableInstance] Null context provided!");
|
||||||
_controller = controller;
|
return;
|
||||||
_settings = settings;
|
}
|
||||||
_onFinishedCallback = onFinishedCallback;
|
|
||||||
_onShowOutlineCallback = onShowOutline;
|
decorationData = context.Data;
|
||||||
_onHideOutlineCallback = onHideOutline;
|
statueOutline = context.StatueOutline;
|
||||||
|
statueParent = context.StatueParent;
|
||||||
|
controller = context.Controller;
|
||||||
|
settings = context.Settings;
|
||||||
|
onFinishedCallback = context.OnFinished;
|
||||||
|
onShowOutlineCallback = context.OnShowOutline;
|
||||||
|
onHideOutlineCallback = context.OnHideOutline;
|
||||||
|
|
||||||
|
// Handle placed vs new drag
|
||||||
|
if (context.IsPlaced)
|
||||||
|
{
|
||||||
|
isPlacedOnStatue = true;
|
||||||
|
isDragging = false;
|
||||||
|
statueParent = transform.parent; // Already parented to statue
|
||||||
|
if (context.CanvasParent != null)
|
||||||
|
{
|
||||||
|
canvasParent = context.CanvasParent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set sprite
|
// Set sprite
|
||||||
if (decorationImage != null && data != null && data.DecorationSprite != null)
|
if (decorationImage != null && context.Data != null && context.Data.DecorationSprite != null)
|
||||||
{
|
{
|
||||||
decorationImage.sprite = data.DecorationSprite;
|
decorationImage.sprite = context.Data.DecorationSprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set authored size
|
// Set authored size
|
||||||
if (_rectTransform != null && data != null)
|
if (rectTransform != null && context.Data != null)
|
||||||
{
|
{
|
||||||
_rectTransform.sizeDelta = data.AuthoredSize;
|
rectTransform.sizeDelta = context.Data.AuthoredSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logging.Debug($"[DecorationDraggableInstance] Initialized: {data?.DecorationName}");
|
// Make interactive if placed (so it can be picked up)
|
||||||
}
|
if (context.IsPlaced && canvasGroup != null)
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initialize as already placed decoration (from saved state)
|
|
||||||
/// Skips drag logic and sets up as if already placed on statue
|
|
||||||
/// </summary>
|
|
||||||
public void InitializeAsPlaced(DecorationData data, StatueDecorationController controller,
|
|
||||||
AppleHills.Core.Settings.IStatueDressupSettings settings, RectTransform statueOutline = null,
|
|
||||||
Transform canvasParent = null, System.Action onShowOutline = null, System.Action onHideOutline = null,
|
|
||||||
System.Action onFinished = null)
|
|
||||||
{
|
|
||||||
_decorationData = data;
|
|
||||||
_controller = controller;
|
|
||||||
_settings = settings;
|
|
||||||
_isPlacedOnStatue = true;
|
|
||||||
_isDragging = false;
|
|
||||||
|
|
||||||
// Store references needed for pickup
|
|
||||||
_statueOutline = statueOutline;
|
|
||||||
_statueParent = transform.parent; // Already parented to statue when this is called
|
|
||||||
if (canvasParent != null)
|
|
||||||
{
|
|
||||||
_canvasParent = canvasParent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store outline callbacks for when picking up from statue
|
|
||||||
_onShowOutlineCallback = onShowOutline;
|
|
||||||
_onHideOutlineCallback = onHideOutline;
|
|
||||||
_onFinishedCallback = onFinished;
|
|
||||||
|
|
||||||
Logging.Debug($"[DecorationDraggableInstance] InitializeAsPlaced - Show outline callback is null: {_onShowOutlineCallback == null}");
|
|
||||||
Logging.Debug($"[DecorationDraggableInstance] InitializeAsPlaced - Hide outline callback is null: {_onHideOutlineCallback == null}");
|
|
||||||
Logging.Debug($"[DecorationDraggableInstance] InitializeAsPlaced - Finished callback is null: {_onFinishedCallback == null}");
|
|
||||||
|
|
||||||
// Set sprite
|
|
||||||
if (decorationImage != null && data != null && data.DecorationSprite != null)
|
|
||||||
{
|
|
||||||
decorationImage.sprite = data.DecorationSprite;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set authored size
|
|
||||||
if (_rectTransform != null && data != null)
|
|
||||||
{
|
|
||||||
_rectTransform.sizeDelta = data.AuthoredSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make interactive so it can be picked up
|
|
||||||
if (canvasGroup != null)
|
|
||||||
{
|
{
|
||||||
canvasGroup.blocksRaycasts = true;
|
canvasGroup.blocksRaycasts = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logging.Debug($"[DecorationDraggableInstance] Initialized as placed: {data?.DecorationName}");
|
Logging.Debug($"[DecorationDraggableInstance] Initialized with context: {context.Data?.DecorationName}, isPlaced={context.IsPlaced}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize the draggable instance (legacy method - prefer InitializeWithContext)
|
||||||
|
/// </summary>
|
||||||
|
[System.Obsolete("Use InitializeWithContext instead")]
|
||||||
|
public void Initialize(DecorationData data, RectTransform pStatueOutline, Transform pStatueParent,
|
||||||
|
StatueDecorationController pController, AppleHills.Core.Settings.IStatueDressupSettings pSettings,
|
||||||
|
System.Action pOnFinishedCallback, System.Action onShowOutline = null, System.Action onHideOutline = null)
|
||||||
|
{
|
||||||
|
var context = DecorationDragContext.CreateForNewDrag(
|
||||||
|
data, pStatueOutline, pStatueParent, pController, pSettings,
|
||||||
|
pOnFinishedCallback, onShowOutline, onHideOutline
|
||||||
|
);
|
||||||
|
InitializeWithContext(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize as already placed decoration (legacy method - prefer InitializeWithContext)
|
||||||
|
/// </summary>
|
||||||
|
[System.Obsolete("Use InitializeWithContext instead")]
|
||||||
|
public void InitializeAsPlaced(DecorationData data, StatueDecorationController pController,
|
||||||
|
AppleHills.Core.Settings.IStatueDressupSettings pSettings, RectTransform pStatueOutline = null,
|
||||||
|
Transform pCanvasParent = null, System.Action onShowOutline = null, System.Action onHideOutline = null,
|
||||||
|
System.Action onFinished = null)
|
||||||
|
{
|
||||||
|
var context = DecorationDragContext.CreateForPlaced(
|
||||||
|
data, pController, pSettings, pStatueOutline, pCanvasParent,
|
||||||
|
onShowOutline, onHideOutline, onFinished
|
||||||
|
);
|
||||||
|
InitializeWithContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -153,18 +153,18 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void StartDragFromIcon(PointerEventData eventData)
|
public void StartDragFromIcon(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
_isDragging = true;
|
isDragging = true;
|
||||||
|
|
||||||
// Calculate offset from cursor to object center
|
// Calculate offset from cursor to object center
|
||||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||||
_canvas.transform as RectTransform,
|
canvas.transform as RectTransform,
|
||||||
eventData.position,
|
eventData.position,
|
||||||
eventData.pressEventCamera,
|
eventData.pressEventCamera,
|
||||||
out Vector2 localPoint);
|
out Vector2 localPoint);
|
||||||
|
|
||||||
_dragOffset = _rectTransform.localPosition - (Vector3)localPoint;
|
dragOffset = rectTransform.localPosition - (Vector3)localPoint;
|
||||||
|
|
||||||
Logging.Debug($"[DecorationDraggableInstance] Started drag from icon: {_decorationData?.DecorationName}");
|
Logging.Debug($"[DecorationDraggableInstance] Started drag from icon: {decorationData?.DecorationName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -172,16 +172,16 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void ContinueDrag(PointerEventData eventData)
|
public void ContinueDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
if (!_isDragging) return;
|
if (!isDragging) return;
|
||||||
|
|
||||||
// Update position to follow cursor
|
// Update position to follow cursor
|
||||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||||
_canvas.transform as RectTransform,
|
canvas.transform as RectTransform,
|
||||||
eventData.position,
|
eventData.position,
|
||||||
eventData.pressEventCamera,
|
eventData.pressEventCamera,
|
||||||
out Vector2 localPoint);
|
out Vector2 localPoint);
|
||||||
|
|
||||||
_rectTransform.localPosition = localPoint + (Vector2)_dragOffset;
|
rectTransform.localPosition = localPoint + (Vector2)dragOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -189,9 +189,9 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void EndDrag(PointerEventData eventData)
|
public void EndDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
_isDragging = false;
|
isDragging = false;
|
||||||
|
|
||||||
Logging.Debug($"[DecorationDraggableInstance] Drag ended: {_decorationData?.DecorationName}");
|
Logging.Debug($"[DecorationDraggableInstance] Drag ended: {decorationData?.DecorationName}");
|
||||||
|
|
||||||
// Check if overlapping with statue
|
// Check if overlapping with statue
|
||||||
if (IsOverlappingStatue())
|
if (IsOverlappingStatue())
|
||||||
@@ -209,20 +209,20 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool IsOverlappingStatue()
|
private bool IsOverlappingStatue()
|
||||||
{
|
{
|
||||||
if (_statueOutline == null || _rectTransform == null)
|
if (statueOutline == null || rectTransform == null)
|
||||||
{
|
{
|
||||||
Logging.Warning($"[DecorationDraggableInstance] Cannot check overlap - statueOutline or RectTransform is null");
|
Logging.Warning($"[DecorationDraggableInstance] Cannot check overlap - statueOutline or RectTransform is null");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get bounds of this item in world space
|
// Get bounds of this item in world space
|
||||||
Rect itemRect = GetWorldRect(_rectTransform);
|
Rect itemRect = GetWorldRect(rectTransform);
|
||||||
Rect outlineRect = GetWorldRect(_statueOutline);
|
Rect outlineRect = GetWorldRect(statueOutline);
|
||||||
|
|
||||||
// Check for any overlap
|
// Check for any overlap
|
||||||
bool overlaps = itemRect.Overlaps(outlineRect);
|
bool overlaps = itemRect.Overlaps(outlineRect);
|
||||||
|
|
||||||
Logging.Debug($"[DecorationDraggableInstance] Overlap check: {_decorationData?.DecorationName}, overlaps={overlaps}");
|
Logging.Debug($"[DecorationDraggableInstance] Overlap check: {decorationData?.DecorationName}, overlaps={overlaps}");
|
||||||
|
|
||||||
return overlaps;
|
return overlaps;
|
||||||
}
|
}
|
||||||
@@ -230,10 +230,10 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get world space rect for a RectTransform
|
/// Get world space rect for a RectTransform
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Rect GetWorldRect(RectTransform rectTransform)
|
private Rect GetWorldRect(RectTransform pRectTransform)
|
||||||
{
|
{
|
||||||
Vector3[] corners = new Vector3[4];
|
Vector3[] corners = new Vector3[4];
|
||||||
rectTransform.GetWorldCorners(corners);
|
pRectTransform.GetWorldCorners(corners);
|
||||||
|
|
||||||
Vector3 bottomLeft = corners[0];
|
Vector3 bottomLeft = corners[0];
|
||||||
Vector3 topRight = corners[2];
|
Vector3 topRight = corners[2];
|
||||||
@@ -246,24 +246,24 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void PlaceOnStatue()
|
private void PlaceOnStatue()
|
||||||
{
|
{
|
||||||
Logging.Debug($"[DecorationDraggableInstance] Placing on statue: {_decorationData?.DecorationName}");
|
Logging.Debug($"[DecorationDraggableInstance] Placing on statue: {decorationData?.DecorationName}");
|
||||||
|
|
||||||
_isPlacedOnStatue = true;
|
isPlacedOnStatue = true;
|
||||||
|
|
||||||
// Move to statue parent if specified
|
// Move to statue parent if specified
|
||||||
if (_statueParent != null && transform.parent != _statueParent)
|
if (statueParent != null && transform.parent != statueParent)
|
||||||
{
|
{
|
||||||
transform.SetParent(_statueParent, true); // Keep world position
|
transform.SetParent(statueParent, true); // Keep world position
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register with controller
|
// Register with controller
|
||||||
if (_controller != null)
|
if (controller != null)
|
||||||
{
|
{
|
||||||
_controller.RegisterDecoration(this);
|
controller.RegisterDecoration(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify menu controller to hide outline
|
// Notify menu controller to hide outline
|
||||||
_onFinishedCallback?.Invoke();
|
onFinishedCallback?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -271,12 +271,12 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void PlayPopOutAndDestroy()
|
private void PlayPopOutAndDestroy()
|
||||||
{
|
{
|
||||||
Logging.Debug($"[DecorationDraggableInstance] Pop-out and destroy: {_decorationData?.DecorationName}");
|
Logging.Debug($"[DecorationDraggableInstance] Pop-out and destroy: {decorationData?.DecorationName}");
|
||||||
|
|
||||||
// Notify menu controller to hide outline immediately
|
// Notify menu controller to hide outline immediately
|
||||||
_onFinishedCallback?.Invoke();
|
onFinishedCallback?.Invoke();
|
||||||
|
|
||||||
float duration = _settings?.PlacementAnimationDuration ?? 0.3f;
|
float duration = settings?.PlacementAnimationDuration ?? 0.3f;
|
||||||
|
|
||||||
// Play pop-out with fade animation
|
// Play pop-out with fade animation
|
||||||
TweenAnimationUtility.PopOutWithFade(transform, canvasGroup, duration, () =>
|
TweenAnimationUtility.PopOutWithFade(transform, canvasGroup, duration, () =>
|
||||||
@@ -290,22 +290,22 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void StartDragFromStatue(PointerEventData eventData)
|
public void StartDragFromStatue(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
Logging.Debug($"[DecorationDraggableInstance] StartDragFromStatue called for: {_decorationData?.DecorationName}");
|
Logging.Debug($"[DecorationDraggableInstance] StartDragFromStatue called for: {decorationData?.DecorationName}");
|
||||||
Logging.Debug($"[DecorationDraggableInstance] Show outline callback is null: {_onShowOutlineCallback == null}");
|
Logging.Debug($"[DecorationDraggableInstance] Show outline callback is null: {onShowOutlineCallback == null}");
|
||||||
|
|
||||||
if (_controller != null)
|
if (controller != null)
|
||||||
{
|
{
|
||||||
_controller.UnregisterDecoration(this);
|
controller.UnregisterDecoration(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
_isPlacedOnStatue = false;
|
isPlacedOnStatue = false;
|
||||||
_isDragging = true;
|
isDragging = true;
|
||||||
|
|
||||||
// Show statue outline when picking up from statue
|
// Show statue outline when picking up from statue
|
||||||
if (_onShowOutlineCallback != null)
|
if (onShowOutlineCallback != null)
|
||||||
{
|
{
|
||||||
Logging.Debug("[DecorationDraggableInstance] Invoking show outline callback");
|
Logging.Debug("[DecorationDraggableInstance] Invoking show outline callback");
|
||||||
_onShowOutlineCallback.Invoke();
|
onShowOutlineCallback.Invoke();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -313,24 +313,24 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reparent to canvas for dragging (so coordinates work correctly)
|
// Reparent to canvas for dragging (so coordinates work correctly)
|
||||||
if (_canvasParent != null && transform.parent != _canvasParent)
|
if (canvasParent != null && transform.parent != canvasParent)
|
||||||
{
|
{
|
||||||
// Store world position before reparenting
|
// Store world position before reparenting
|
||||||
Vector3 worldPos = transform.position;
|
Vector3 worldPos = transform.position;
|
||||||
transform.SetParent(_canvasParent, false);
|
transform.SetParent(canvasParent, false);
|
||||||
transform.position = worldPos; // Restore world position
|
transform.position = worldPos; // Restore world position
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate offset using proper camera
|
// Calculate offset using proper camera
|
||||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||||
_canvas.transform as RectTransform,
|
canvas.transform as RectTransform,
|
||||||
eventData.position,
|
eventData.position,
|
||||||
eventData.pressEventCamera,
|
eventData.pressEventCamera,
|
||||||
out Vector2 localPoint);
|
out Vector2 localPoint);
|
||||||
|
|
||||||
_dragOffset = _rectTransform.localPosition - (Vector3)localPoint;
|
dragOffset = rectTransform.localPosition - (Vector3)localPoint;
|
||||||
|
|
||||||
Logging.Debug($"[DecorationDraggableInstance] Started drag from statue: {_decorationData?.DecorationName}");
|
Logging.Debug($"[DecorationDraggableInstance] Started drag from statue: {decorationData?.DecorationName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Pointer Event Handlers
|
#region Pointer Event Handlers
|
||||||
@@ -341,9 +341,9 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
public void OnPointerClick(PointerEventData eventData)
|
public void OnPointerClick(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
// Only handle clicks when placed on statue and not currently dragging
|
// Only handle clicks when placed on statue and not currently dragging
|
||||||
if (!_isPlacedOnStatue || _dragStarted) return;
|
if (!isPlacedOnStatue || dragStarted) return;
|
||||||
|
|
||||||
Logging.Debug($"[DecorationDraggableInstance] Decoration tapped: {_decorationData?.DecorationName}");
|
Logging.Debug($"[DecorationDraggableInstance] Decoration tapped: {decorationData?.DecorationName}");
|
||||||
|
|
||||||
// Future: Open detail view, play sound effect, show info popup, etc.
|
// Future: Open detail view, play sound effect, show info popup, etc.
|
||||||
}
|
}
|
||||||
@@ -354,9 +354,9 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
public void OnBeginDrag(PointerEventData eventData)
|
public void OnBeginDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
// Only handle drag from statue if already placed
|
// Only handle drag from statue if already placed
|
||||||
if (!_isPlacedOnStatue) return;
|
if (!isPlacedOnStatue) return;
|
||||||
|
|
||||||
_dragStarted = true;
|
dragStarted = true;
|
||||||
StartDragFromStatue(eventData);
|
StartDragFromStatue(eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +365,7 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void OnDrag(PointerEventData eventData)
|
public void OnDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
if (!_isDragging) return;
|
if (!isDragging) return;
|
||||||
|
|
||||||
ContinueDrag(eventData);
|
ContinueDrag(eventData);
|
||||||
}
|
}
|
||||||
@@ -375,9 +375,9 @@ namespace Minigames.StatueDressup.DragDrop
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void OnEndDrag(PointerEventData eventData)
|
public void OnEndDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
if (!_isDragging) return;
|
if (!isDragging) return;
|
||||||
|
|
||||||
_dragStarted = false;
|
dragStarted = false;
|
||||||
EndDrag(eventData);
|
EndDrag(eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
Assets/Scripts/Minigames/StatueDressup/PhotoGallery.meta
Normal file
3
Assets/Scripts/Minigames/StatueDressup/PhotoGallery.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2ad8b8c5b4f24f52af870512f5d18592
|
||||||
|
timeCreated: 1764241594
|
||||||
@@ -12,27 +12,27 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class PhotoEnlargeController
|
public class PhotoEnlargeController
|
||||||
{
|
{
|
||||||
private readonly GameObject _backdrop;
|
private readonly GameObject backdrop;
|
||||||
private readonly Transform _enlargedContainer;
|
private readonly Transform enlargedContainer;
|
||||||
private readonly float _animationDuration;
|
private readonly float animationDuration;
|
||||||
|
|
||||||
private GameObject _currentEnlargedPreview;
|
private GameObject currentEnlargedPreview;
|
||||||
private PhotoGridItem _currentSourceItem;
|
private PhotoGridItem currentSourceItem;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PhotoEnlargeController(GameObject backdrop, Transform enlargedContainer, float animationDuration = 0.3f)
|
public PhotoEnlargeController(GameObject backdrop, Transform enlargedContainer, float animationDuration = 0.3f)
|
||||||
{
|
{
|
||||||
_backdrop = backdrop;
|
this.backdrop = backdrop;
|
||||||
_enlargedContainer = enlargedContainer;
|
this.enlargedContainer = enlargedContainer;
|
||||||
_animationDuration = animationDuration;
|
this.animationDuration = animationDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if a photo is currently enlarged
|
/// Check if a photo is currently enlarged
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsPhotoEnlarged => _currentEnlargedPreview != null;
|
public bool IsPhotoEnlarged => currentEnlargedPreview != null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enlarge a photo from a grid item
|
/// Enlarge a photo from a grid item
|
||||||
@@ -46,30 +46,30 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow multiple enlargements
|
// Don't allow multiple enlargements
|
||||||
if (_currentEnlargedPreview != null)
|
if (currentEnlargedPreview != null)
|
||||||
{
|
{
|
||||||
Logging.Warning("[PhotoEnlargeController] Photo already enlarged");
|
Logging.Warning("[PhotoEnlargeController] Photo already enlarged");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentSourceItem = sourceItem;
|
currentSourceItem = sourceItem;
|
||||||
|
|
||||||
// Show backdrop
|
// Show backdrop
|
||||||
if (_backdrop != null)
|
if (backdrop != null)
|
||||||
{
|
{
|
||||||
_backdrop.SetActive(true);
|
backdrop.SetActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn preview clone
|
// Spawn preview clone
|
||||||
_currentEnlargedPreview = Object.Instantiate(previewPrefab, _enlargedContainer);
|
currentEnlargedPreview = Object.Instantiate(previewPrefab, enlargedContainer);
|
||||||
_currentEnlargedPreview.transform.SetAsLastSibling();
|
currentEnlargedPreview.transform.SetAsLastSibling();
|
||||||
|
|
||||||
// Position at source item's world position
|
// Position at source item's world position
|
||||||
_currentEnlargedPreview.transform.position = sourceItem.transform.position;
|
currentEnlargedPreview.transform.position = sourceItem.transform.position;
|
||||||
_currentEnlargedPreview.transform.localScale = sourceItem.transform.localScale;
|
currentEnlargedPreview.transform.localScale = sourceItem.transform.localScale;
|
||||||
|
|
||||||
// Set photo texture on preview
|
// Set photo texture on preview
|
||||||
var previewImage = _currentEnlargedPreview.GetComponent<UnityEngine.UI.Image>();
|
var previewImage = currentEnlargedPreview.GetComponent<UnityEngine.UI.Image>();
|
||||||
if (previewImage != null)
|
if (previewImage != null)
|
||||||
{
|
{
|
||||||
// Create sprite from texture
|
// Create sprite from texture
|
||||||
@@ -82,10 +82,10 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add click handler to preview
|
// Add click handler to preview
|
||||||
var clickHandler = _currentEnlargedPreview.GetComponent<EventTrigger>();
|
var clickHandler = currentEnlargedPreview.GetComponent<EventTrigger>();
|
||||||
if (clickHandler == null)
|
if (clickHandler == null)
|
||||||
{
|
{
|
||||||
clickHandler = _currentEnlargedPreview.AddComponent<EventTrigger>();
|
clickHandler = currentEnlargedPreview.AddComponent<EventTrigger>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var pointerClickEntry = new EventTrigger.Entry { eventID = EventTriggerType.PointerClick };
|
var pointerClickEntry = new EventTrigger.Entry { eventID = EventTriggerType.PointerClick };
|
||||||
@@ -93,8 +93,8 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
clickHandler.triggers.Add(pointerClickEntry);
|
clickHandler.triggers.Add(pointerClickEntry);
|
||||||
|
|
||||||
// Animate to center and scale up
|
// Animate to center and scale up
|
||||||
TweenAnimationUtility.AnimateLocalPosition(_currentEnlargedPreview.transform, Vector3.zero, _animationDuration);
|
TweenAnimationUtility.AnimateLocalPosition(currentEnlargedPreview.transform, Vector3.zero, animationDuration);
|
||||||
TweenAnimationUtility.AnimateScale(_currentEnlargedPreview.transform, Vector3.one * enlargedScale, _animationDuration);
|
TweenAnimationUtility.AnimateScale(currentEnlargedPreview.transform, Vector3.one * enlargedScale, animationDuration);
|
||||||
|
|
||||||
// Play audio feedback
|
// Play audio feedback
|
||||||
AudioManager.Instance.LoadAndPlayUIAudio("card_albumdrop_deep", false);
|
AudioManager.Instance.LoadAndPlayUIAudio("card_albumdrop_deep", false);
|
||||||
@@ -107,35 +107,35 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void ShrinkPhoto()
|
public void ShrinkPhoto()
|
||||||
{
|
{
|
||||||
if (_currentEnlargedPreview == null || _currentSourceItem == null)
|
if (currentEnlargedPreview == null || currentSourceItem == null)
|
||||||
{
|
{
|
||||||
Logging.Warning("[PhotoEnlargeController] No photo to shrink");
|
Logging.Warning("[PhotoEnlargeController] No photo to shrink");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide backdrop
|
// Hide backdrop
|
||||||
if (_backdrop != null)
|
if (backdrop != null)
|
||||||
{
|
{
|
||||||
_backdrop.SetActive(false);
|
backdrop.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get target position from source item
|
// Get target position from source item
|
||||||
Vector3 targetWorldPos = _currentSourceItem.transform.position;
|
Vector3 targetWorldPos = currentSourceItem.transform.position;
|
||||||
Vector3 targetScale = _currentSourceItem.transform.localScale;
|
Vector3 targetScale = currentSourceItem.transform.localScale;
|
||||||
|
|
||||||
GameObject previewToDestroy = _currentEnlargedPreview;
|
GameObject previewToDestroy = currentEnlargedPreview;
|
||||||
|
|
||||||
// Animate back to source position
|
// Animate back to source position
|
||||||
Pixelplacement.Tween.Position(previewToDestroy.transform, targetWorldPos, _animationDuration, 0f, Pixelplacement.Tween.EaseInOut);
|
Pixelplacement.Tween.Position(previewToDestroy.transform, targetWorldPos, animationDuration, 0f, Pixelplacement.Tween.EaseInOut);
|
||||||
TweenAnimationUtility.AnimateScale(previewToDestroy.transform, targetScale, _animationDuration, () =>
|
TweenAnimationUtility.AnimateScale(previewToDestroy.transform, targetScale, animationDuration, () =>
|
||||||
{
|
{
|
||||||
// Destroy preview after animation
|
// Destroy preview after animation
|
||||||
Object.Destroy(previewToDestroy);
|
Object.Destroy(previewToDestroy);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Clear references
|
// Clear references
|
||||||
_currentEnlargedPreview = null;
|
currentEnlargedPreview = null;
|
||||||
_currentSourceItem = null;
|
currentSourceItem = null;
|
||||||
|
|
||||||
Logging.Debug("[PhotoEnlargeController] Photo shrunk");
|
Logging.Debug("[PhotoEnlargeController] Photo shrunk");
|
||||||
}
|
}
|
||||||
@@ -145,18 +145,18 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void Cleanup()
|
public void Cleanup()
|
||||||
{
|
{
|
||||||
if (_currentEnlargedPreview != null)
|
if (currentEnlargedPreview != null)
|
||||||
{
|
{
|
||||||
Object.Destroy(_currentEnlargedPreview);
|
Object.Destroy(currentEnlargedPreview);
|
||||||
_currentEnlargedPreview = null;
|
currentEnlargedPreview = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_backdrop != null)
|
if (backdrop != null)
|
||||||
{
|
{
|
||||||
_backdrop.SetActive(false);
|
backdrop.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentSourceItem = null;
|
currentSourceItem = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,16 +15,16 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
[SerializeField] private Image thumbnailImage;
|
[SerializeField] private Image thumbnailImage;
|
||||||
[SerializeField] private GameObject loadingIndicator;
|
[SerializeField] private GameObject loadingIndicator;
|
||||||
|
|
||||||
private string _photoId;
|
private string photoId;
|
||||||
private StatuePhotoGalleryController _galleryController;
|
private StatuePhotoGalleryController galleryController;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initialize grid item with photo ID
|
/// Initialize grid item with photo ID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Initialize(string photoId, StatuePhotoGalleryController controller)
|
public void Initialize(string newPhotoId, StatuePhotoGalleryController controller)
|
||||||
{
|
{
|
||||||
_photoId = photoId;
|
this.photoId = newPhotoId;
|
||||||
_galleryController = controller;
|
galleryController = controller;
|
||||||
|
|
||||||
// Show loading state
|
// Show loading state
|
||||||
if (loadingIndicator != null)
|
if (loadingIndicator != null)
|
||||||
@@ -41,7 +41,7 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
{
|
{
|
||||||
if (thumbnail == null)
|
if (thumbnail == null)
|
||||||
{
|
{
|
||||||
Logging.Warning($"[PhotoGridItem] Null thumbnail for photo: {_photoId}");
|
Logging.Warning($"[PhotoGridItem] Null thumbnail for photo: {photoId}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,10 +68,10 @@ namespace Minigames.StatueDressup.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void OnPointerClick(PointerEventData eventData)
|
public void OnPointerClick(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
if (_galleryController != null && !string.IsNullOrEmpty(_photoId))
|
if (galleryController != null && !string.IsNullOrEmpty(photoId))
|
||||||
{
|
{
|
||||||
Logging.Debug($"[PhotoGridItem] Clicked: {_photoId}");
|
Logging.Debug($"[PhotoGridItem] Clicked: {photoId}");
|
||||||
_galleryController.OnGridItemClicked(this, _photoId);
|
galleryController.OnGridItemClicked(this, photoId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
3
Assets/Scripts/Minigames/StatueDressup/Test.meta
Normal file
3
Assets/Scripts/Minigames/StatueDressup/Test.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dc39e89d2088421187d48d89e0eed813
|
||||||
|
timeCreated: 1764241512
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace Minigames.StatueDressup.Controllers
|
namespace Minigames.StatueDressup.Test
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Minimal test for photo capture - just capture and save to disk
|
/// Minimal test for photo capture - just capture and save to disk
|
||||||
Reference in New Issue
Block a user