diff --git a/Assets/AddressableAssetsData/AddressableAssetGroupSortSettings.asset b/Assets/AddressableAssetsData/AddressableAssetGroupSortSettings.asset
index d37c1b27..21081059 100644
--- a/Assets/AddressableAssetsData/AddressableAssetGroupSortSettings.asset
+++ b/Assets/AddressableAssetsData/AddressableAssetGroupSortSettings.asset
@@ -13,6 +13,7 @@ MonoBehaviour:
m_Name: AddressableAssetGroupSortSettings
m_EditorClassIdentifier:
sortOrder:
+ - b58f7c15a2ffcbc4483cb2bd0a0dee90
- 21420e71d44619f468badaed8efc42a7
- 0d5d36d6da388314b92b9c6967d23f39
- 75e1f68b7bf77f34f8ad4aeab74d4244
diff --git a/Assets/AddressableAssetsData/AssetGroups/Schemas/StatueDecorations_BundledAssetGroupSchema.asset b/Assets/AddressableAssetsData/AssetGroups/Schemas/StatueDecorations_BundledAssetGroupSchema.asset
new file mode 100644
index 00000000..cd88548e
--- /dev/null
+++ b/Assets/AddressableAssetsData/AssetGroups/Schemas/StatueDecorations_BundledAssetGroupSchema.asset
@@ -0,0 +1,48 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 0}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: e5d17a21594effb4e9591490b009e7aa, type: 3}
+ m_Name: StatueDecorations_BundledAssetGroupSchema
+ m_EditorClassIdentifier:
+ m_Group: {fileID: 11400000, guid: fd8b6934620e3a54a818495e62a103e0, type: 2}
+ m_InternalBundleIdMode: 1
+ m_Compression: 1
+ m_IncludeAddressInCatalog: 1
+ m_IncludeGUIDInCatalog: 1
+ m_IncludeLabelsInCatalog: 1
+ m_InternalIdNamingMode: 0
+ m_CacheClearBehavior: 0
+ m_IncludeInBuild: 1
+ m_BundledAssetProviderType:
+ m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
+ m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.BundledAssetProvider
+ m_StripDownloadOptions: 0
+ m_ForceUniqueProvider: 0
+ m_UseAssetBundleCache: 1
+ m_UseAssetBundleCrc: 1
+ m_UseAssetBundleCrcForCachedBundles: 1
+ m_UseUWRForLocalBundles: 0
+ m_Timeout: 0
+ m_ChunkedTransfer: 0
+ m_RedirectLimit: -1
+ m_RetryCount: 0
+ m_BuildPath:
+ m_Id: c258e2bcd3e8ac742ba98f152c0e6322
+ m_LoadPath:
+ m_Id: 88323bf0b2ef98446961cedd6232bd47
+ m_BundleMode: 0
+ m_AssetBundleProviderType:
+ m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
+ m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.AssetBundleProvider
+ m_UseDefaultSchemaSettings: 0
+ m_SelectedPathPairIndex: 0
+ m_BundleNaming: 0
+ m_AssetLoadMode: 0
diff --git a/Assets/AddressableAssetsData/AssetGroups/Schemas/StatueDecorations_BundledAssetGroupSchema.asset.meta b/Assets/AddressableAssetsData/AssetGroups/Schemas/StatueDecorations_BundledAssetGroupSchema.asset.meta
new file mode 100644
index 00000000..ce69843c
--- /dev/null
+++ b/Assets/AddressableAssetsData/AssetGroups/Schemas/StatueDecorations_BundledAssetGroupSchema.asset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5acac321571c9e84f8b97709b80b77ea
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 11400000
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AddressableAssetsData/AssetGroups/Schemas/StatueDecorations_ContentUpdateGroupSchema.asset b/Assets/AddressableAssetsData/AssetGroups/Schemas/StatueDecorations_ContentUpdateGroupSchema.asset
new file mode 100644
index 00000000..ffae72c6
--- /dev/null
+++ b/Assets/AddressableAssetsData/AssetGroups/Schemas/StatueDecorations_ContentUpdateGroupSchema.asset
@@ -0,0 +1,16 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 0}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 5834b5087d578d24c926ce20cd31e6d6, type: 3}
+ m_Name: StatueDecorations_ContentUpdateGroupSchema
+ m_EditorClassIdentifier:
+ m_Group: {fileID: 11400000, guid: fd8b6934620e3a54a818495e62a103e0, type: 2}
+ m_StaticContent: 0
diff --git a/Assets/AddressableAssetsData/AssetGroups/Schemas/StatueDecorations_ContentUpdateGroupSchema.asset.meta b/Assets/AddressableAssetsData/AssetGroups/Schemas/StatueDecorations_ContentUpdateGroupSchema.asset.meta
new file mode 100644
index 00000000..949b3820
--- /dev/null
+++ b/Assets/AddressableAssetsData/AssetGroups/Schemas/StatueDecorations_ContentUpdateGroupSchema.asset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 17c82ac3ce25c6b4e90e5e7e0e3cc941
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 11400000
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AddressableAssetsData/AssetGroups/StatueDecorations.asset b/Assets/AddressableAssetsData/AssetGroups/StatueDecorations.asset
new file mode 100644
index 00000000..16850e6c
--- /dev/null
+++ b/Assets/AddressableAssetsData/AssetGroups/StatueDecorations.asset
@@ -0,0 +1,83 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 0}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: bbb281ee3bf0b054c82ac2347e9e782c, type: 3}
+ m_Name: StatueDecorations
+ m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.AddressableAssetGroup
+ m_GroupName: StatueDecorations
+ m_GUID: b58f7c15a2ffcbc4483cb2bd0a0dee90
+ m_SerializeEntries:
+ - m_GUID: 2ea75de9ff6dbfb4b8c246a654868479
+ m_Address: Assets/Data/Minigames/StatueDressup/TestDecorationData.asset
+ m_ReadOnly: 0
+ m_SerializedLabels:
+ - StatueDecorations
+ FlaggedDuringContentUpdateRestriction: 0
+ - m_GUID: 4101d48e428899d409df02f24c83571f
+ m_Address: Assets/Data/Minigames/StatueDressup/TestDecorationData 7.asset
+ m_ReadOnly: 0
+ m_SerializedLabels:
+ - StatueDecorations
+ FlaggedDuringContentUpdateRestriction: 0
+ - m_GUID: 5efa934e009bc234e920904b05db3c2f
+ m_Address: Assets/Data/Minigames/StatueDressup/TestDecorationData 2.asset
+ m_ReadOnly: 0
+ m_SerializedLabels:
+ - StatueDecorations
+ FlaggedDuringContentUpdateRestriction: 0
+ - m_GUID: 8819ec8b1f4910a4494755cf043636d1
+ m_Address: Assets/Data/Minigames/StatueDressup/TestDecorationData 3.asset
+ m_ReadOnly: 0
+ m_SerializedLabels:
+ - StatueDecorations
+ FlaggedDuringContentUpdateRestriction: 0
+ - m_GUID: 8838477f768600848813a215ab6a46fe
+ m_Address: Assets/Data/Minigames/StatueDressup/TestDecorationData 5.asset
+ m_ReadOnly: 0
+ m_SerializedLabels:
+ - StatueDecorations
+ FlaggedDuringContentUpdateRestriction: 0
+ - m_GUID: a5d493c2c7c9cf74cab038023b401273
+ m_Address: Assets/Data/Minigames/StatueDressup/TestDecorationData 9.asset
+ m_ReadOnly: 0
+ m_SerializedLabels:
+ - StatueDecorations
+ FlaggedDuringContentUpdateRestriction: 0
+ - m_GUID: b01ee8334ee052b4784225337e9a5ece
+ m_Address: Assets/Data/Minigames/StatueDressup/TestDecorationData 8.asset
+ m_ReadOnly: 0
+ m_SerializedLabels:
+ - StatueDecorations
+ FlaggedDuringContentUpdateRestriction: 0
+ - m_GUID: b09b79db8ef15144bb2138ec59f26a9c
+ m_Address: Assets/Data/Minigames/StatueDressup/TestDecorationData 4.asset
+ m_ReadOnly: 0
+ m_SerializedLabels:
+ - StatueDecorations
+ FlaggedDuringContentUpdateRestriction: 0
+ - m_GUID: ca949a6208ce5b5488e90ea3e2eed6df
+ m_Address: Assets/Data/Minigames/StatueDressup/TestDecorationData 1.asset
+ m_ReadOnly: 0
+ m_SerializedLabels:
+ - StatueDecorations
+ FlaggedDuringContentUpdateRestriction: 0
+ - m_GUID: f0df83df3cff9d84ba9fd4895e5d1b58
+ m_Address: Assets/Data/Minigames/StatueDressup/TestDecorationData 6.asset
+ m_ReadOnly: 0
+ m_SerializedLabels:
+ - StatueDecorations
+ FlaggedDuringContentUpdateRestriction: 0
+ m_ReadOnly: 0
+ m_Settings: {fileID: 11400000, guid: 11da9bb90d9dd5848b4f7629415a6937, type: 2}
+ m_SchemaSet:
+ m_Schemas:
+ - {fileID: 11400000, guid: 5acac321571c9e84f8b97709b80b77ea, type: 2}
+ - {fileID: 11400000, guid: 17c82ac3ce25c6b4e90e5e7e0e3cc941, type: 2}
diff --git a/Assets/AddressableAssetsData/AssetGroups/StatueDecorations.asset.meta b/Assets/AddressableAssetsData/AssetGroups/StatueDecorations.asset.meta
new file mode 100644
index 00000000..6cc1974c
--- /dev/null
+++ b/Assets/AddressableAssetsData/AssetGroups/StatueDecorations.asset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: fd8b6934620e3a54a818495e62a103e0
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 11400000
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Art/Sprites/Spritesheets/TownMap/PuzzleLevelIcons/DecorationMinigame.png.meta b/Assets/Art/Sprites/Spritesheets/TownMap/PuzzleLevelIcons/DecorationMinigame.png.meta
index 8b7d2cef..891bba28 100644
--- a/Assets/Art/Sprites/Spritesheets/TownMap/PuzzleLevelIcons/DecorationMinigame.png.meta
+++ b/Assets/Art/Sprites/Spritesheets/TownMap/PuzzleLevelIcons/DecorationMinigame.png.meta
@@ -122,6 +122,32 @@ TextureImporter:
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: WebGL
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: WindowsStoreApps
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
@@ -129,12 +155,12 @@ TextureImporter:
name: DecorationMinigame_0
rect:
serializedVersion: 2
- x: 143
- y: 59
- width: 701
- height: 983
+ x: 0
+ y: 0
+ width: 962
+ height: 1109
alignment: 0
- pivot: {x: 0, y: 0}
+ pivot: {x: 0.5, y: 0.5}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
@@ -151,7 +177,7 @@ TextureImporter:
customData:
physicsShape: []
bones: []
- spriteID:
+ spriteID: 99610a41e95434e42bc921e55c481562
internalID: 0
vertices: []
indices:
diff --git a/Assets/Prefabs/Minigames/StatueDressup/DecorationDraggableInstance.prefab b/Assets/Prefabs/Minigames/StatueDressup/DecorationDraggableInstance.prefab
index c9e89879..cb75d2ff 100644
--- a/Assets/Prefabs/Minigames/StatueDressup/DecorationDraggableInstance.prefab
+++ b/Assets/Prefabs/Minigames/StatueDressup/DecorationDraggableInstance.prefab
@@ -102,4 +102,4 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::Minigames.StatueDressup.DragDrop.DecorationDraggableInstance
decorationImage: {fileID: 597267714783345863}
- canvasGroup: {fileID: 0}
+ canvasGroup: {fileID: 3617977973382190563}
diff --git a/Assets/Scenes/Levels/AppleHillsOverworld.unity b/Assets/Scenes/Levels/AppleHillsOverworld.unity
index eb3e8a51..4960e08e 100644
--- a/Assets/Scenes/Levels/AppleHillsOverworld.unity
+++ b/Assets/Scenes/Levels/AppleHillsOverworld.unity
@@ -468,6 +468,11 @@ PrefabInstance:
addedObject: {fileID: 706319199}
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 539b408cd1191614abdcd99506f1157d, type: 3}
+--- !u!1 &175866977 stripped
+GameObject:
+ m_CorrespondingSourceObject: {fileID: 7404622075362872657, guid: f44866deaba5f5c4a90f0330dd9957f0, type: 3}
+ m_PrefabInstance: {fileID: 1460027141}
+ m_PrefabAsset: {fileID: 0}
--- !u!1 &201656041
GameObject:
m_ObjectHideFlags: 0
@@ -2885,6 +2890,37 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1292467736
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1292467737}
+ m_Layer: 10
+ m_Name: DecorationsRoot
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &1292467737
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1292467736}
+ serializedVersion: 2
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1460027142}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!4 &1298174946 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 5179840719513743426, guid: 4c8aa6e55c410284aaa57c461eba5bdf, type: 3}
@@ -3060,11 +3096,11 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 8766058064105819536, guid: f44866deaba5f5c4a90f0330dd9957f0, type: 3}
propertyPath: m_SpriteTilingProperty.oldSize.x
- value: 7.01
+ value: 9.62
objectReference: {fileID: 0}
- target: {fileID: 8766058064105819536, guid: f44866deaba5f5c4a90f0330dd9957f0, type: 3}
propertyPath: m_SpriteTilingProperty.oldSize.y
- value: 9.83
+ value: 11.09
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
@@ -3075,13 +3111,35 @@ PrefabInstance:
- targetCorrespondingSourceObject: {fileID: 5727794563305583620, guid: f44866deaba5f5c4a90f0330dd9957f0, type: 3}
insertIndex: -1
addedObject: {fileID: 1253055066}
- m_AddedComponents: []
+ - targetCorrespondingSourceObject: {fileID: 5727794563305583620, guid: f44866deaba5f5c4a90f0330dd9957f0, type: 3}
+ insertIndex: -1
+ addedObject: {fileID: 1292467737}
+ m_AddedComponents:
+ - targetCorrespondingSourceObject: {fileID: 7404622075362872657, guid: f44866deaba5f5c4a90f0330dd9957f0, type: 3}
+ insertIndex: -1
+ addedObject: {fileID: 1460027146}
m_SourcePrefab: {fileID: 100100000, guid: f44866deaba5f5c4a90f0330dd9957f0, type: 3}
--- !u!4 &1460027142 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 5727794563305583620, guid: f44866deaba5f5c4a90f0330dd9957f0, type: 3}
m_PrefabInstance: {fileID: 1460027141}
m_PrefabAsset: {fileID: 0}
+--- !u!114 &1460027146
+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: 50d0f4591bbd40fc81dc615fa465e0c5, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: AppleHillsScripts::Minigames.StatueDressup.Display.StatueDecorationLoader
+ decorationDataLabel: StatueDecorations
+ decorationRoot: {fileID: 1292467737}
+ specificPhotoId:
+ showDebugInfo: 1
--- !u!4 &1572710089 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3}
diff --git a/Assets/Scenes/MiniGames/StatueDecoration.unity b/Assets/Scenes/MiniGames/StatueDecoration.unity
index 5b430854..d2bd0482 100644
--- a/Assets/Scenes/MiniGames/StatueDecoration.unity
+++ b/Assets/Scenes/MiniGames/StatueDecoration.unity
@@ -198,6 +198,81 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1678977
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1678978}
+ - component: {fileID: 1678980}
+ - component: {fileID: 1678979}
+ m_Layer: 5
+ m_Name: PhotoFlash
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 0
+--- !u!224 &1678978
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1678977}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1217454518}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 0}
+ m_AnchorMax: {x: 1, y: 1}
+ m_AnchoredPosition: {x: 0, y: 0}
+ m_SizeDelta: {x: 0, y: 0}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1678979
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1678977}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 0}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
+--- !u!222 &1678980
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1678977}
+ m_CullTransparentMesh: 1
--- !u!1 &37633365
GameObject:
m_ObjectHideFlags: 0
@@ -318,6 +393,81 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 37633365}
m_CullTransparentMesh: 1
+--- !u!1 &52826699
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 52826700}
+ - component: {fileID: 52826702}
+ - component: {fileID: 52826701}
+ m_Layer: 5
+ m_Name: Image (6)
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &52826700
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 52826699}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1733895146}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 1}
+ m_AnchorMax: {x: 0, y: 1}
+ m_AnchoredPosition: {x: 467.99994, y: -875.99994}
+ m_SizeDelta: {x: 250, y: 250}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &52826701
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 52826699}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 0}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
+--- !u!222 &52826702
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 52826699}
+ m_CullTransparentMesh: 1
--- !u!1 &61401515
GameObject:
m_ObjectHideFlags: 0
@@ -327,13 +477,14 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 61401516}
+ - component: {fileID: 61401517}
m_Layer: 5
m_Name: PhotoGallery
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
- m_IsActive: 1
+ m_IsActive: 0
--- !u!224 &61401516
RectTransform:
m_ObjectHideFlags: 0
@@ -346,7 +497,9 @@ RectTransform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- - {fileID: 1612917661}
+ - {fileID: 598551045}
+ - {fileID: 1774956263}
+ - {fileID: 487762464}
m_Father: {fileID: 1217454518}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
@@ -354,6 +507,20 @@ RectTransform:
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &61401517
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 61401515}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 3136a7edf8de421e9860c6bd4e1dca10, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: AppleHillsScripts::Minigames.StatueDressup.UI.PhotoGalleryPage
+ PageName: PhotoGalleryPage
+ transitionDuration: 0.3
--- !u!1 &65358844
GameObject:
m_ObjectHideFlags: 0
@@ -386,6 +553,7 @@ RectTransform:
- {fileID: 1078270174}
- {fileID: 1325274730}
- {fileID: 166400579}
+ - {fileID: 2147347253}
m_Father: {fileID: 1443594949}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
@@ -401,6 +569,156 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 65358844}
m_CullTransparentMesh: 1
+--- !u!1 &103521088
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 103521089}
+ - component: {fileID: 103521091}
+ - component: {fileID: 103521090}
+ m_Layer: 5
+ m_Name: Image (3)
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &103521089
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 103521088}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1733895146}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 1}
+ m_AnchorMax: {x: 0, y: 1}
+ m_AnchoredPosition: {x: 467.99994, y: -575.99994}
+ m_SizeDelta: {x: 250, y: 250}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &103521090
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 103521088}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 0}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
+--- !u!222 &103521091
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 103521088}
+ m_CullTransparentMesh: 1
+--- !u!1 &115868432
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 115868433}
+ - component: {fileID: 115868435}
+ - component: {fileID: 115868434}
+ m_Layer: 5
+ m_Name: Image (4)
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &115868433
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 115868432}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1733895146}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 1}
+ m_AnchorMax: {x: 0, y: 1}
+ m_AnchoredPosition: {x: 767.99994, y: -575.99994}
+ m_SizeDelta: {x: 250, y: 250}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &115868434
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 115868432}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 0}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
+--- !u!222 &115868435
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 115868432}
+ m_CullTransparentMesh: 1
--- !u!1 &131357294
GameObject:
m_ObjectHideFlags: 0
@@ -474,6 +792,81 @@ RectTransform:
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
+--- !u!1 &167351357
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 167351358}
+ - component: {fileID: 167351360}
+ - component: {fileID: 167351359}
+ m_Layer: 5
+ m_Name: Image (8)
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &167351358
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 167351357}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1733895146}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 1}
+ m_AnchorMax: {x: 0, y: 1}
+ m_AnchoredPosition: {x: 1068, y: -875.99994}
+ m_SizeDelta: {x: 250, y: 250}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &167351359
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 167351357}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 0}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
+--- !u!222 &167351360
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 167351357}
+ m_CullTransparentMesh: 1
--- !u!1 &194466354
GameObject:
m_ObjectHideFlags: 0
@@ -631,6 +1024,81 @@ RectTransform:
m_AnchoredPosition: {x: 0.000030517578, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
+--- !u!1 &254256966
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 254256967}
+ - component: {fileID: 254256969}
+ - component: {fileID: 254256968}
+ m_Layer: 5
+ m_Name: Background
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &254256967
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 254256966}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1774956263}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 0}
+ m_AnchorMax: {x: 1, y: 1}
+ m_AnchoredPosition: {x: 0, y: 0}
+ m_SizeDelta: {x: 0, y: 0}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &254256968
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 254256966}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
+ m_Material: {fileID: 0}
+ m_Color: {r: 0, g: 0, b: 0, a: 0.2784314}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 0}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
+--- !u!222 &254256969
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 254256966}
+ m_CullTransparentMesh: 1
--- !u!1 &403667977
GameObject:
m_ObjectHideFlags: 0
@@ -699,6 +1167,81 @@ MonoBehaviour:
statueController: {fileID: 1647993458}
statueOutline: {fileID: 1325274732}
gridLayout: {fileID: 699865156}
+--- !u!1 &435994659
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 435994660}
+ - component: {fileID: 435994662}
+ - component: {fileID: 435994661}
+ m_Layer: 5
+ m_Name: Image
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &435994660
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 435994659}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1733895146}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 1}
+ m_AnchorMax: {x: 0, y: 1}
+ m_AnchoredPosition: {x: 467.99994, y: -275.99994}
+ m_SizeDelta: {x: 250, y: 250}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &435994661
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 435994659}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 0}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
+--- !u!222 &435994662
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 435994659}
+ m_CullTransparentMesh: 1
--- !u!1 &483064110
GameObject:
m_ObjectHideFlags: 0
@@ -789,6 +1332,179 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &487762463
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 487762464}
+ m_Layer: 5
+ m_Name: PhotoPreview
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &487762464
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 487762463}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children:
+ - {fileID: 533750042}
+ - {fileID: 2034809390}
+ m_Father: {fileID: 61401516}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 0}
+ m_AnchorMax: {x: 1, y: 1}
+ m_AnchoredPosition: {x: 0, y: 0}
+ m_SizeDelta: {x: 0, y: 0}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!1 &533750041
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 533750042}
+ - component: {fileID: 533750044}
+ - component: {fileID: 533750043}
+ m_Layer: 5
+ m_Name: EnlargeBackdrop
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &533750042
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 533750041}
+ m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 487762464}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 0}
+ m_AnchorMax: {x: 1, y: 1}
+ m_AnchoredPosition: {x: 0, y: 0}
+ m_SizeDelta: {x: 0, y: 0}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &533750043
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 533750041}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
+ m_Material: {fileID: 0}
+ m_Color: {r: 0, g: 0, b: 0, a: 0.36862746}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 0}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
+--- !u!222 &533750044
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 533750041}
+ m_CullTransparentMesh: 1
+--- !u!1 &598551044
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 598551045}
+ - component: {fileID: 598551046}
+ m_Layer: 5
+ m_Name: GalleryController
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &598551045
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 598551044}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 61401516}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0.5, y: 0.5}
+ m_AnchorMax: {x: 0.5, y: 0.5}
+ m_AnchoredPosition: {x: 0, y: 0}
+ m_SizeDelta: {x: 100, y: 100}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &598551046
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 598551044}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: a7339274a0c54f8c9134942f84d47140, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: AppleHillsScripts::Minigames.StatueDressup.Controllers.StatuePhotoGalleryController
+ gridContainer: {fileID: 1733895146}
+ gridItemPrefab: {fileID: 0}
+ enlargedContainer: {fileID: 0}
+ backdrop: {fileID: 0}
+ enlargedPreviewPrefab: {fileID: 0}
+ previousPageButton: {fileID: 0}
+ nextPageButton: {fileID: 0}
+ pageStatusText: {fileID: 0}
+ itemsPerPage: 20
+ thumbnailSize: 256
+ maxCachedThumbnails: 50
+ enlargedScale: 2.5
+ animationDuration: 0.3
--- !u!1 &699865154
GameObject:
m_ObjectHideFlags: 0
@@ -1019,6 +1735,81 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &892106116
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 892106117}
+ - component: {fileID: 892106119}
+ - component: {fileID: 892106118}
+ m_Layer: 5
+ m_Name: Image (2)
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &892106117
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 892106116}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1733895146}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 1}
+ m_AnchorMax: {x: 0, y: 1}
+ m_AnchoredPosition: {x: 1068, y: -275.99994}
+ m_SizeDelta: {x: 250, y: 250}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &892106118
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 892106116}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 0}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
+--- !u!222 &892106119
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 892106116}
+ m_CullTransparentMesh: 1
--- !u!1 &1034770168
GameObject:
m_ObjectHideFlags: 0
@@ -1215,6 +2006,81 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1140141871
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1140141872}
+ - component: {fileID: 1140141874}
+ - component: {fileID: 1140141873}
+ m_Layer: 5
+ m_Name: Image (5)
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &1140141872
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1140141871}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1733895146}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 1}
+ m_AnchorMax: {x: 0, y: 1}
+ m_AnchoredPosition: {x: 1068, y: -575.99994}
+ m_SizeDelta: {x: 250, y: 250}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1140141873
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1140141871}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 0}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
+--- !u!222 &1140141874
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1140141871}
+ m_CullTransparentMesh: 1
--- !u!1 &1217454514
GameObject:
m_ObjectHideFlags: 0
@@ -1311,6 +2177,7 @@ RectTransform:
m_Children:
- {fileID: 1443594949}
- {fileID: 61401516}
+ - {fileID: 1678978}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
@@ -1318,6 +2185,81 @@ RectTransform:
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
+--- !u!1 &1259957078
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1259957079}
+ - component: {fileID: 1259957081}
+ - component: {fileID: 1259957080}
+ m_Layer: 5
+ m_Name: Image (7)
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &1259957079
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1259957078}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1733895146}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 1}
+ m_AnchorMax: {x: 0, y: 1}
+ m_AnchoredPosition: {x: 767.99994, y: -875.99994}
+ m_SizeDelta: {x: 250, y: 250}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1259957080
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1259957078}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 0}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
+--- !u!222 &1259957081
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1259957078}
+ m_CullTransparentMesh: 1
--- !u!1 &1325274729
GameObject:
m_ObjectHideFlags: 0
@@ -1417,6 +2359,7 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 1443594949}
+ - component: {fileID: 1443594950}
m_Layer: 5
m_Name: PlayArea
m_TagString: Untagged
@@ -1438,6 +2381,7 @@ RectTransform:
m_Children:
- {fileID: 65358845}
- {fileID: 403667978}
+ - {fileID: 1612917661}
m_Father: {fileID: 1217454518}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
@@ -1445,6 +2389,20 @@ RectTransform:
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1443594950
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1443594948}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: edd2867b8a4f42d8af202f215c3ecc47, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: AppleHillsScripts::Minigames.StatueDressup.UI.PlayAreaPage
+ PageName: PlayArea
+ transitionDuration: 0.3
--- !u!1 &1542794366
GameObject:
m_ObjectHideFlags: 0
@@ -1545,6 +2503,81 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1598728281
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1598728282}
+ - component: {fileID: 1598728284}
+ - component: {fileID: 1598728283}
+ m_Layer: 5
+ m_Name: Image (1)
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &1598728282
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1598728281}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1733895146}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 1}
+ m_AnchorMax: {x: 0, y: 1}
+ m_AnchoredPosition: {x: 767.99994, y: -275.99994}
+ m_SizeDelta: {x: 250, y: 250}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1598728283
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1598728281}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 0}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
+--- !u!222 &1598728284
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1598728281}
+ m_CullTransparentMesh: 1
--- !u!1 &1612917660
GameObject:
m_ObjectHideFlags: 0
@@ -1564,7 +2597,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
- m_IsActive: 1
+ m_IsActive: 0
--- !u!224 &1612917661
RectTransform:
m_ObjectHideFlags: 0
@@ -1572,17 +2605,17 @@ RectTransform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1612917660}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
- m_Father: {fileID: 61401516}
+ m_Father: {fileID: 1443594949}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 1}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: -75, y: -75}
- m_SizeDelta: {x: 172.83276, y: 0}
+ m_SizeDelta: {x: 172.83276, y: 179.2871}
m_Pivot: {x: 1, y: 1}
--- !u!114 &1612917662
MonoBehaviour:
@@ -1714,7 +2747,13 @@ MonoBehaviour:
menuController: {fileID: 403667980}
takePhotoButton: {fileID: 37633367}
statue: {fileID: 1078270173}
+ playAreaPage: {fileID: 0}
+ photoGalleryPage: {fileID: 0}
+ openGalleryButton: {fileID: 0}
uiElementsToHideForPhoto: []
+ additionalElementsToHideForCutout:
+ - {fileID: 483064110}
+ - {fileID: 403667977}
photoArea: {fileID: 65358845}
photoSaveKey: MrCementStatuePhoto
--- !u!4 &1647993459
@@ -1748,7 +2787,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
- m_IsActive: 1
+ m_IsActive: 0
--- !u!114 &1685271990
MonoBehaviour:
m_ObjectHideFlags: 0
@@ -1779,6 +2818,156 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1733895145
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1733895146}
+ - component: {fileID: 1733895148}
+ - component: {fileID: 1733895147}
+ m_Layer: 5
+ m_Name: GridContainer
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &1733895146
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1733895145}
+ m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children:
+ - {fileID: 435994660}
+ - {fileID: 1598728282}
+ - {fileID: 892106117}
+ - {fileID: 103521089}
+ - {fileID: 115868433}
+ - {fileID: 1140141872}
+ - {fileID: 52826700}
+ - {fileID: 1259957079}
+ - {fileID: 167351358}
+ m_Father: {fileID: 1774956263}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 0}
+ m_AnchorMax: {x: 1, y: 1}
+ m_AnchoredPosition: {x: 0, y: 0}
+ m_SizeDelta: {x: 0, y: 0}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &1733895147
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1733895145}
+ m_CullTransparentMesh: 1
+--- !u!114 &1733895148
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1733895145}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 8a8695521f0d02e499659fee002a26c2, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.GridLayoutGroup
+ m_Padding:
+ m_Left: 75
+ m_Right: 75
+ m_Top: 75
+ m_Bottom: 75
+ m_ChildAlignment: 4
+ m_StartCorner: 0
+ m_StartAxis: 0
+ m_CellSize: {x: 250, y: 250}
+ m_Spacing: {x: 50, y: 50}
+ m_Constraint: 1
+ m_ConstraintCount: 3
+--- !u!1 &1774956262
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1774956263}
+ m_Layer: 5
+ m_Name: GalleryGrid
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &1774956263
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1774956262}
+ m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children:
+ - {fileID: 254256967}
+ - {fileID: 1733895146}
+ m_Father: {fileID: 61401516}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0.1, y: 0.1}
+ m_AnchorMax: {x: 0.9, y: 0.9}
+ m_AnchoredPosition: {x: 0, y: 0}
+ m_SizeDelta: {x: 0, y: 0}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!1 &2034809389
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 2034809390}
+ m_Layer: 5
+ m_Name: EnlargedPhotoContainer
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &2034809390
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2034809389}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 487762464}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0.5, y: 0.5}
+ m_AnchorMax: {x: 0.5, y: 0.5}
+ m_AnchoredPosition: {x: 0, y: 0}
+ m_SizeDelta: {x: 100, y: 100}
+ m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &2071711337
GameObject:
m_ObjectHideFlags: 0
@@ -1899,6 +3088,81 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2071711337}
m_CullTransparentMesh: 1
+--- !u!1 &2147347252
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 2147347253}
+ - component: {fileID: 2147347255}
+ - component: {fileID: 2147347254}
+ m_Layer: 5
+ m_Name: PhotoOverlay
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 0
+--- !u!224 &2147347253
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2147347252}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 65358845}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 0}
+ m_AnchorMax: {x: 1, y: 1}
+ m_AnchoredPosition: {x: 0, y: 0}
+ m_SizeDelta: {x: 0, y: 0}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &2147347254
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2147347252}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 0}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
+--- !u!222 &2147347255
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2147347252}
+ m_CullTransparentMesh: 1
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
diff --git a/Assets/Scripts/Core/Settings/SettingsInterfaces.cs b/Assets/Scripts/Core/Settings/SettingsInterfaces.cs
index 4a68006c..93c79dcb 100644
--- a/Assets/Scripts/Core/Settings/SettingsInterfaces.cs
+++ b/Assets/Scripts/Core/Settings/SettingsInterfaces.cs
@@ -188,10 +188,21 @@ namespace AppleHills.Core.Settings
float HoverAnimationDuration { get; }
float PlacementAnimationDuration { get; }
+ // Addressables
+ string DecorationDataLabel { get; }
+
// Photo Settings
string PhotoSaveKey { get; }
int PhotoQuality { get; }
bool CaptureFullScreen { get; }
+ string CutoutPhotoFilename { get; } // Hardcoded filename for transparent cutout version
+
+ // Photo Gallery (DEPRECATED - Feature temporarily disabled)
+ int GalleryItemsPerPage { get; }
+ int GalleryThumbnailSize { get; }
+ int GalleryMaxCachedThumbnails { get; }
+ float GalleryEnlargedScale { get; }
+ float GalleryAnimationDuration { get; }
// Rewards
int CardsRewardCount { get; }
diff --git a/Assets/Scripts/Core/Settings/StatueDressupSettings.cs b/Assets/Scripts/Core/Settings/StatueDressupSettings.cs
index 1310d21b..f3d98f44 100644
--- a/Assets/Scripts/Core/Settings/StatueDressupSettings.cs
+++ b/Assets/Scripts/Core/Settings/StatueDressupSettings.cs
@@ -49,6 +49,10 @@ namespace Core.Settings
[Tooltip("Duration for placement animation")]
[SerializeField] private float placementAnimationDuration = 0.15f;
+ [Header("Addressables")]
+ [Tooltip("Addressables label for loading DecorationData assets")]
+ [SerializeField] private string decorationDataLabel = "StatueDecorations";
+
[Header("Photo Settings")]
[Tooltip("PlayerPrefs key for saving the statue photo")]
[SerializeField] private string photoSaveKey = "MrCementStatuePhoto";
@@ -59,6 +63,16 @@ namespace Core.Settings
[Tooltip("Whether to capture full screen or just statue area")]
[SerializeField] private bool captureFullScreen;
+ [Tooltip("Filename for transparent cutout version (overwrites each time)")]
+ [SerializeField] private string cutoutPhotoFilename = "StatueCutout_Latest";
+
+ [Header("Photo Gallery - DEPRECATED (Feature Disabled)")]
+ [HideInInspector] [SerializeField] private int galleryItemsPerPage = 20;
+ [HideInInspector] [SerializeField] private int galleryThumbnailSize = 256;
+ [HideInInspector] [SerializeField] private int galleryMaxCachedThumbnails = 50;
+ [HideInInspector] [SerializeField] private float galleryEnlargedScale = 2.5f;
+ [HideInInspector] [SerializeField] private float galleryAnimationDuration = 0.3f;
+
[Header("Rewards")]
[Tooltip("Number of Blokkemon cards awarded on completion")]
[SerializeField] private int cardsRewardCount = 3;
@@ -97,10 +111,21 @@ namespace Core.Settings
public float HoverAnimationDuration => hoverAnimationDuration;
public float PlacementAnimationDuration => placementAnimationDuration;
+ // IStatueDressupSettings implementation - Addressables
+ public string DecorationDataLabel => decorationDataLabel;
+
// IStatueDressupSettings implementation - Photo Settings
public string PhotoSaveKey => photoSaveKey;
public int PhotoQuality => photoQuality;
public bool CaptureFullScreen => captureFullScreen;
+ public string CutoutPhotoFilename => cutoutPhotoFilename;
+
+ // IStatueDressupSettings implementation - Photo Gallery (DEPRECATED)
+ public int GalleryItemsPerPage => galleryItemsPerPage;
+ public int GalleryThumbnailSize => galleryThumbnailSize;
+ public int GalleryMaxCachedThumbnails => galleryMaxCachedThumbnails;
+ public float GalleryEnlargedScale => galleryEnlargedScale;
+ public float GalleryAnimationDuration => galleryAnimationDuration;
// IStatueDressupSettings implementation - Rewards
public int CardsRewardCount => cardsRewardCount;
diff --git a/Assets/Scripts/Minigames/StatueDressup/Controllers/PhotoCaptureTestController.cs b/Assets/Scripts/Minigames/StatueDressup/Controllers/PhotoCaptureTestController.cs
index 9f177755..be2f30ee 100644
--- a/Assets/Scripts/Minigames/StatueDressup/Controllers/PhotoCaptureTestController.cs
+++ b/Assets/Scripts/Minigames/StatueDressup/Controllers/PhotoCaptureTestController.cs
@@ -1,7 +1,6 @@
-using Core;
-using Minigames.StatueDressup.Utils;
-using UnityEngine;
+using UnityEngine;
using UnityEngine.UI;
+using Utils;
namespace Minigames.StatueDressup.Controllers
{
@@ -24,7 +23,7 @@ namespace Minigames.StatueDressup.Controllers
captureButton.onClick.AddListener(OnCaptureClicked);
}
- Debug.Log($"[PhotoCaptureTest] Ready. Photo save path: {StatuePhotoManager.GetPhotoDirectory()}");
+ Debug.Log($"[PhotoCaptureTest] Ready. Photo save path: {PhotoManager.GetCaptureDirectory(CaptureType.StatueMinigame)}");
}
private void OnCaptureClicked()
@@ -41,47 +40,29 @@ namespace Minigames.StatueDressup.Controllers
private System.Collections.IEnumerator CaptureCoroutine()
{
- // Hide UI
- foreach (var obj in hideTheseObjects)
- if (obj != null) obj.SetActive(false);
-
- yield return new WaitForEndOfFrame();
-
- // Capture
- bool done = false;
- Texture2D photo = null;
-
- StatuePhotoManager.CaptureAreaPhoto(captureArea, (texture) => {
- photo = texture;
- done = true;
- });
-
- yield return new WaitUntil(() => done);
-
- // Restore UI
- foreach (var obj in hideTheseObjects)
- if (obj != null) obj.SetActive(true);
-
- // Save
- if (photo != null)
- {
- string photoId = StatuePhotoManager.SavePhoto(photo, 0);
-
- if (!string.IsNullOrEmpty(photoId))
+ // Use new PhotoManager plug-and-play coroutine
+ yield return PhotoManager.CaptureAndSaveCoroutine(
+ CaptureType.StatueMinigame,
+ captureArea,
+ hideTheseObjects,
+ onSuccess: (photoId) =>
{
- string path = $"{StatuePhotoManager.GetPhotoDirectory()}/{photoId}.png";
+ string path = $"{PhotoManager.GetCaptureDirectory(CaptureType.StatueMinigame)}/{photoId}.png";
Debug.Log($"[PhotoCaptureTest] ✅ SUCCESS! Photo saved: {path}");
- Debug.Log($"[PhotoCaptureTest] Photo size: {photo.width}x{photo.height}");
- }
- else
+
+ // Load back to verify
+ Texture2D loadedPhoto = PhotoManager.LoadPhoto(CaptureType.StatueMinigame, photoId);
+ if (loadedPhoto != null)
+ {
+ Debug.Log($"[PhotoCaptureTest] Photo size: {loadedPhoto.width}x{loadedPhoto.height}");
+ }
+ },
+ onFailure: (error) =>
{
- Debug.LogError("[PhotoCaptureTest] ❌ Failed to save photo");
- }
- }
- else
- {
- Debug.LogError("[PhotoCaptureTest] ❌ Failed to capture photo");
- }
+ Debug.LogError($"[PhotoCaptureTest] ❌ Failed: {error}");
+ },
+ metadata: 0
+ );
}
private void OnDestroy()
diff --git a/Assets/Scripts/Minigames/StatueDressup/Controllers/PhotoEnlargeController.cs b/Assets/Scripts/Minigames/StatueDressup/Controllers/PhotoEnlargeController.cs
new file mode 100644
index 00000000..d1929328
--- /dev/null
+++ b/Assets/Scripts/Minigames/StatueDressup/Controllers/PhotoEnlargeController.cs
@@ -0,0 +1,163 @@
+using Core;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using Utils;
+
+namespace Minigames.StatueDressup.Controllers
+{
+ ///
+ /// Manages enlarged photo preview display.
+ /// Handles backdrop, preview spawning, and click-to-dismiss.
+ /// Similar to CardEnlargeController but simpler (no state machine).
+ ///
+ public class PhotoEnlargeController
+ {
+ private readonly GameObject _backdrop;
+ private readonly Transform _enlargedContainer;
+ private readonly float _animationDuration;
+
+ private GameObject _currentEnlargedPreview;
+ private PhotoGridItem _currentSourceItem;
+
+ ///
+ /// Constructor
+ ///
+ public PhotoEnlargeController(GameObject backdrop, Transform enlargedContainer, float animationDuration = 0.3f)
+ {
+ _backdrop = backdrop;
+ _enlargedContainer = enlargedContainer;
+ _animationDuration = animationDuration;
+ }
+
+ ///
+ /// Check if a photo is currently enlarged
+ ///
+ public bool IsPhotoEnlarged => _currentEnlargedPreview != null;
+
+ ///
+ /// Enlarge a photo from a grid item
+ ///
+ public void EnlargePhoto(PhotoGridItem sourceItem, GameObject previewPrefab, Texture2D photoTexture, float enlargedScale)
+ {
+ if (sourceItem == null || previewPrefab == null || photoTexture == null)
+ {
+ Logging.Error("[PhotoEnlargeController] Invalid parameters for EnlargePhoto");
+ return;
+ }
+
+ // Don't allow multiple enlargements
+ if (_currentEnlargedPreview != null)
+ {
+ Logging.Warning("[PhotoEnlargeController] Photo already enlarged");
+ return;
+ }
+
+ _currentSourceItem = sourceItem;
+
+ // Show backdrop
+ if (_backdrop != null)
+ {
+ _backdrop.SetActive(true);
+ }
+
+ // Spawn preview clone
+ _currentEnlargedPreview = Object.Instantiate(previewPrefab, _enlargedContainer);
+ _currentEnlargedPreview.transform.SetAsLastSibling();
+
+ // Position at source item's world position
+ _currentEnlargedPreview.transform.position = sourceItem.transform.position;
+ _currentEnlargedPreview.transform.localScale = sourceItem.transform.localScale;
+
+ // Set photo texture on preview
+ var previewImage = _currentEnlargedPreview.GetComponent();
+ if (previewImage != null)
+ {
+ // Create sprite from texture
+ Sprite photoSprite = Sprite.Create(
+ photoTexture,
+ new Rect(0, 0, photoTexture.width, photoTexture.height),
+ new Vector2(0.5f, 0.5f)
+ );
+ previewImage.sprite = photoSprite;
+ }
+
+ // Add click handler to preview
+ var clickHandler = _currentEnlargedPreview.GetComponent();
+ if (clickHandler == null)
+ {
+ clickHandler = _currentEnlargedPreview.AddComponent();
+ }
+
+ var pointerClickEntry = new EventTrigger.Entry { eventID = EventTriggerType.PointerClick };
+ pointerClickEntry.callback.AddListener((_) => { ShrinkPhoto(); });
+ clickHandler.triggers.Add(pointerClickEntry);
+
+ // Animate to center and scale up
+ TweenAnimationUtility.AnimateLocalPosition(_currentEnlargedPreview.transform, Vector3.zero, _animationDuration);
+ TweenAnimationUtility.AnimateScale(_currentEnlargedPreview.transform, Vector3.one * enlargedScale, _animationDuration);
+
+ // Play audio feedback
+ AudioManager.Instance.LoadAndPlayUIAudio("card_albumdrop_deep", false);
+
+ Logging.Debug("[PhotoEnlargeController] Photo enlarged");
+ }
+
+ ///
+ /// Shrink the currently enlarged photo back to grid
+ ///
+ public void ShrinkPhoto()
+ {
+ if (_currentEnlargedPreview == null || _currentSourceItem == null)
+ {
+ Logging.Warning("[PhotoEnlargeController] No photo to shrink");
+ return;
+ }
+
+ // Hide backdrop
+ if (_backdrop != null)
+ {
+ _backdrop.SetActive(false);
+ }
+
+ // Get target position from source item
+ Vector3 targetWorldPos = _currentSourceItem.transform.position;
+ Vector3 targetScale = _currentSourceItem.transform.localScale;
+
+ GameObject previewToDestroy = _currentEnlargedPreview;
+
+ // Animate back to source position
+ Pixelplacement.Tween.Position(previewToDestroy.transform, targetWorldPos, _animationDuration, 0f, Pixelplacement.Tween.EaseInOut);
+ TweenAnimationUtility.AnimateScale(previewToDestroy.transform, targetScale, _animationDuration, () =>
+ {
+ // Destroy preview after animation
+ Object.Destroy(previewToDestroy);
+ });
+
+ // Clear references
+ _currentEnlargedPreview = null;
+ _currentSourceItem = null;
+
+ Logging.Debug("[PhotoEnlargeController] Photo shrunk");
+ }
+
+ ///
+ /// Cleanup - call when gallery is closed
+ ///
+ public void Cleanup()
+ {
+ if (_currentEnlargedPreview != null)
+ {
+ Object.Destroy(_currentEnlargedPreview);
+ _currentEnlargedPreview = null;
+ }
+
+ if (_backdrop != null)
+ {
+ _backdrop.SetActive(false);
+ }
+
+ _currentSourceItem = null;
+ }
+ }
+}
+
diff --git a/Assets/Scripts/Minigames/StatueDressup/Controllers/PhotoEnlargeController.cs.meta b/Assets/Scripts/Minigames/StatueDressup/Controllers/PhotoEnlargeController.cs.meta
new file mode 100644
index 00000000..920465e1
--- /dev/null
+++ b/Assets/Scripts/Minigames/StatueDressup/Controllers/PhotoEnlargeController.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 8ba20462f9a647ee90389c7480147d2e
+timeCreated: 1764151481
\ No newline at end of file
diff --git a/Assets/Scripts/Minigames/StatueDressup/Controllers/PhotoGridItem.cs b/Assets/Scripts/Minigames/StatueDressup/Controllers/PhotoGridItem.cs
index 240ede7a..8f652162 100644
--- a/Assets/Scripts/Minigames/StatueDressup/Controllers/PhotoGridItem.cs
+++ b/Assets/Scripts/Minigames/StatueDressup/Controllers/PhotoGridItem.cs
@@ -64,14 +64,14 @@ namespace Minigames.StatueDressup.Controllers
}
///
- /// Handle click to show enlarged view
+ /// Handle click to enlarge/shrink photo
///
public void OnPointerClick(PointerEventData eventData)
{
if (_galleryController != null && !string.IsNullOrEmpty(_photoId))
{
Logging.Debug($"[PhotoGridItem] Clicked: {_photoId}");
- _galleryController.ShowEnlargedView(_photoId);
+ _galleryController.OnGridItemClicked(this, _photoId);
}
}
}
diff --git a/Assets/Scripts/Minigames/StatueDressup/Controllers/StatueDecorationController.cs b/Assets/Scripts/Minigames/StatueDressup/Controllers/StatueDecorationController.cs
index 7c4fba71..42c8c697 100644
--- a/Assets/Scripts/Minigames/StatueDressup/Controllers/StatueDecorationController.cs
+++ b/Assets/Scripts/Minigames/StatueDressup/Controllers/StatueDecorationController.cs
@@ -1,9 +1,12 @@
using System.Collections.Generic;
using Core;
using Core.Lifecycle;
+using Minigames.StatueDressup.Data;
using Minigames.StatueDressup.DragDrop;
+using UI.Core;
using UnityEngine;
using UnityEngine.UI;
+using Utils;
namespace Minigames.StatueDressup.Controllers
{
@@ -19,17 +22,24 @@ namespace Minigames.StatueDressup.Controllers
[SerializeField] private DecorationMenuController menuController;
[SerializeField] private Button takePhotoButton;
[SerializeField] private GameObject statue;
+ [SerializeField] private DecorationDraggableInstance draggablePrefab; // Prefab for spawning decorations
+
+ [Header("UI Pages")]
+ [SerializeField] private UI.PlayAreaPage playAreaPage;
+ [SerializeField] private UI.PhotoGalleryPage photoGalleryPage;
+ [SerializeField] private Button openGalleryButton;
[Header("UI Elements to Hide for Photo")]
[SerializeField] private GameObject[] uiElementsToHideForPhoto;
[Header("Photo Settings")]
[SerializeField] private RectTransform photoArea; // Area to capture
- [SerializeField] private string photoSaveKey = "MrCementStatuePhoto";
private List _placedDecorations = new List();
private bool _minigameCompleted;
private AppleHills.Core.Settings.IStatueDressupSettings _settings;
+ private Dictionary _decorationDataDict;
+ private UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle> _decorationDataHandle;
// Public property for menu controller
public Transform StatueParent => statueParent;
@@ -48,19 +58,36 @@ namespace Minigames.StatueDressup.Controllers
///
/// Main initialization after all managers are ready
///
- internal override void OnManagedStart()
+ internal override async void OnManagedStart()
{
base.OnManagedStart();
Logging.Debug("[StatueDecorationController] Initializing minigame");
+ // Load all DecorationData via Addressables first
+ await LoadDecorationDataAsync();
+
+ // TODO: If ever picture gallery
+ // Setup UI pages (DISABLED - kept for future gallery integration)
+ // if (playAreaPage != null && UIPageController.Instance != null)
+ // {
+ // UIPageController.Instance.PushPage(playAreaPage);
+ // Logging.Debug("[StatueDecorationController] Play area page registered");
+ // }
+
// Setup photo button
if (takePhotoButton != null)
{
- // TODO: Remove comment when ready
- // takePhotoButton.onClick.AddListener(OnTakePhoto);
+ takePhotoButton.onClick.AddListener(OnTakePhoto);
}
+ // TODO: If ever picture gallery
+ // Setup gallery button (DISABLED - kept for future use)
+ // if (openGalleryButton != null)
+ // {
+ // openGalleryButton.onClick.AddListener(OnOpenGallery);
+ // }
+
// Subscribe to menu controller for tracking placed items
// Items will manage their own placement via overlap detection
if (menuController != null)
@@ -73,6 +100,49 @@ namespace Minigames.StatueDressup.Controllers
LoadStatueState();
}
+ ///
+ /// Load all DecorationData assets via Addressables and build lookup dictionary
+ ///
+ 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(
+ label,
+ data => data.DecorationId
+ );
+
+ _decorationDataDict = result.dictionary;
+ _decorationDataHandle = result.handle;
+
+ Logging.Debug($"[StatueDecorationController] Loaded {_decorationDataDict.Count} DecorationData assets");
+ }
+
+ ///
+ /// Open photo gallery
+ ///
+ private void OnOpenGallery()
+ {
+ if (photoGalleryPage != null && UIPageController.Instance != null)
+ {
+ UIPageController.Instance.PushPage(photoGalleryPage);
+ Logging.Debug("[StatueDecorationController] Opening photo gallery");
+ }
+ else
+ {
+ Logging.Warning("[StatueDecorationController] Photo gallery page not assigned");
+ }
+ }
+
///
/// Register a decoration as placed on statue
///
@@ -116,76 +186,66 @@ namespace Minigames.StatueDressup.Controllers
Logging.Debug("[StatueDecorationController] Taking photo of statue");
- // Hide UI elements
- HideUIForPhoto(true);
-
- // Wait a frame for UI to hide, then capture
+ // CapturePhotoCoroutine handles all UI hiding/showing
StartCoroutine(CapturePhotoCoroutine());
}
///
- /// Capture photo after UI is hidden
+ /// Capture photo and save decoration metadata
///
private System.Collections.IEnumerator CapturePhotoCoroutine()
{
- yield return new WaitForEndOfFrame();
+ int decorationCount = _placedDecorations.Count;
+ bool captureSuccess = false;
+ string savedPhotoId = null;
- // Capture using Screenshot Helper via StatuePhotoManager
- bool captureComplete = false;
- Texture2D capturedPhoto = null;
-
- Utils.StatuePhotoManager.CaptureAreaPhoto(
+ // Capture photo
+ yield return PhotoManager.CaptureAndSaveCoroutine(
+ CaptureType.StatueMinigame,
photoArea,
- (Texture2D texture) =>
- {
- capturedPhoto = texture;
- captureComplete = true;
- },
- Camera.main
- );
-
- // Wait for capture to complete
- yield return new WaitUntil(() => captureComplete);
-
- if (capturedPhoto != null)
- {
- // Save photo with StatuePhotoManager
- int decorationCount = _placedDecorations.Count;
- string photoId = Utils.StatuePhotoManager.SavePhoto(capturedPhoto, decorationCount);
-
- if (!string.IsNullOrEmpty(photoId))
+ uiElementsToHideForPhoto,
+ onSuccess: (photoId) =>
{
Logging.Debug($"[StatueDecorationController] Photo saved: {photoId}");
-
- // Award cards
- AwardCards();
-
- // Update town icon
- UpdateTownIcon(capturedPhoto);
-
- // Show completion feedback
- ShowCompletionFeedback();
-
- _minigameCompleted = true;
- }
- else
+ savedPhotoId = photoId;
+ captureSuccess = true;
+ },
+ onFailure: (error) =>
{
- Logging.Error("[StatueDecorationController] Failed to save photo!");
+ Logging.Error($"[StatueDecorationController] Photo capture failed: {error}");
DebugUIMessage.Show("Failed to save photo!", Color.red);
- }
- }
- else
+ captureSuccess = false;
+ },
+ metadata: decorationCount
+ );
+
+ // If photo failed, abort
+ if (!captureSuccess)
{
- Logging.Error("[StatueDecorationController] Failed to capture photo!");
- DebugUIMessage.Show("Failed to capture photo!", Color.red);
+ yield break;
}
- // Restore UI
- HideUIForPhoto(false);
+ // Save decoration metadata
+ SaveDecorationMetadata(savedPhotoId);
+
+ // Load the saved photo for town icon update
+ Texture2D savedPhoto = PhotoManager.LoadPhoto(CaptureType.StatueMinigame, savedPhotoId);
+
+ // Award cards
+ AwardCards();
+
+ // Update town icon
+ if (savedPhoto != null)
+ {
+ UpdateTownIcon(savedPhoto);
+ }
+
+ // Show completion feedback
+ ShowCompletionFeedback();
+
+ _minigameCompleted = true;
}
-
-
///
/// Award Blokkemon cards to player
///
@@ -219,17 +279,60 @@ namespace Minigames.StatueDressup.Controllers
}
///
- /// Hide/show UI elements for photo
+ /// Save decoration metadata for reconstruction
///
- private void HideUIForPhoto(bool hide)
+ private void SaveDecorationMetadata(string photoId)
{
- foreach (var element in uiElementsToHideForPhoto)
+ // Determine coordinate system type
+ bool isUIRectTransform = statue != null && statue.GetComponent() != null;
+
+ // Get statue size for coordinate conversion
+ Vector2 statueSize = Vector2.one;
+ if (isUIRectTransform && statue != null)
{
- if (element != null)
+ RectTransform statueRect = statue.GetComponent();
+ statueSize = statueRect.rect.size;
+ }
+ else if (statue != null)
+ {
+ SpriteRenderer statueSprite = statue.GetComponent();
+ if (statueSprite != null && statueSprite.sprite != null)
{
- element.SetActive(!hide);
+ statueSize = statueSprite.sprite.bounds.size;
}
}
+
+ StatueDecorationData data = new StatueDecorationData
+ {
+ photoId = photoId,
+ timestamp = System.DateTime.Now.ToString("o"),
+ coordinateSystem = isUIRectTransform ? CoordinateSystemType.UIRectTransform : CoordinateSystemType.WorldSpace,
+ sourceStatueSize = statueSize
+ };
+
+ // Collect all decoration placements
+ foreach (var decoration in _placedDecorations)
+ {
+ if (decoration == null || decoration.Data == null) continue;
+
+ SpriteRenderer spriteRenderer = decoration.GetComponent();
+
+ DecorationPlacement placement = new DecorationPlacement
+ {
+ decorationId = decoration.Data.DecorationId,
+ localPosition = decoration.transform.localPosition,
+ localScale = decoration.transform.localScale,
+ rotation = decoration.transform.eulerAngles.z,
+ sortingOrder = spriteRenderer != null ? spriteRenderer.sortingOrder : 0
+ };
+
+ data.placements.Add(placement);
+ }
+
+ // Save metadata using PhotoManager
+ PhotoManager.SaveDecorationMetadata(CaptureType.StatueMinigame, photoId, data);
+
+ Logging.Debug($"[StatueDecorationController] Saved decoration metadata: {data.placements.Count} decorations");
}
///
@@ -252,7 +355,7 @@ namespace Minigames.StatueDressup.Controllers
}
///
- /// Load saved statue decoration state
+ /// Load saved statue decoration state from metadata
///
private void LoadStatueState()
{
@@ -263,10 +366,83 @@ namespace Minigames.StatueDressup.Controllers
return;
}
- // TODO: Implement load system
- // Restore decorations from saved state
+ // Check if DecorationData is loaded
+ if (_decorationDataDict == null || _decorationDataDict.Count == 0)
+ {
+ Logging.Warning("[StatueDecorationController] DecorationData not loaded yet. Cannot restore state.");
+ return;
+ }
- Logging.Debug($"[StatueDecorationController] State loaded from {_settings.StateSaveKey} (TODO: implement persistence)");
+ // Load latest decoration metadata
+ StatueDecorationData data = PhotoManager.LoadLatestDecorationMetadata(CaptureType.StatueMinigame);
+
+ if (data == null || data.placements == null || data.placements.Count == 0)
+ {
+ Logging.Debug("[StatueDecorationController] No saved state found");
+ return;
+ }
+
+ Logging.Debug($"[StatueDecorationController] Restoring {data.placements.Count} decorations from saved state");
+
+ // Spawn each decoration
+ int successCount = 0;
+ foreach (var placement in data.placements)
+ {
+ if (SpawnSavedDecoration(placement))
+ {
+ successCount++;
+ }
+ }
+
+ Logging.Debug($"[StatueDecorationController] Successfully restored {successCount}/{data.placements.Count} decorations");
+ }
+
+ ///
+ /// Spawn a saved decoration from placement data
+ ///
+ private bool SpawnSavedDecoration(DecorationPlacement placement)
+ {
+ // Look up DecorationData from dictionary
+ if (!_decorationDataDict.TryGetValue(placement.decorationId, out DecorationData decorationData))
+ {
+ Logging.Warning($"[StatueDecorationController] DecorationData not found for ID: {placement.decorationId}");
+ return false;
+ }
+
+ if (draggablePrefab == null || statueParent == null)
+ {
+ Logging.Error("[StatueDecorationController] Missing draggable prefab or statue parent");
+ return false;
+ }
+
+ // Spawn decoration instance
+ DecorationDraggableInstance instance = Instantiate(draggablePrefab, statueParent);
+
+ // Initialize in "placed" state (skip drag logic)
+ instance.InitializeAsPlaced(
+ decorationData,
+ this,
+ _settings
+ );
+
+ // Apply saved transform
+ instance.transform.localPosition = placement.localPosition;
+ instance.transform.localScale = placement.localScale;
+ instance.transform.localEulerAngles = new Vector3(0, 0, placement.rotation);
+
+ // Set sorting order if has SpriteRenderer
+ SpriteRenderer spriteRenderer = instance.GetComponent();
+ if (spriteRenderer != null)
+ {
+ spriteRenderer.sortingOrder = placement.sortingOrder;
+ }
+
+ // Register with controller
+ RegisterDecoration(instance);
+
+ Logging.Debug($"[StatueDecorationController] Restored decoration: {placement.decorationId} at {placement.localPosition}");
+
+ return true;
}
///
@@ -276,11 +452,21 @@ namespace Minigames.StatueDressup.Controllers
{
base.OnManagedDestroy();
- // Cleanup button listener
+ // Release Addressables handle
+ AddressablesUtility.ReleaseHandle(_decorationDataHandle);
+
+ // Cleanup button listeners
if (takePhotoButton != null)
{
takePhotoButton.onClick.RemoveListener(OnTakePhoto);
}
+
+ // TODO: If ever picture gallery
+ // Gallery button cleanup (DISABLED - kept for future use)
+ // if (openGalleryButton != null)
+ // {
+ // openGalleryButton.onClick.RemoveListener(OnOpenGallery);
+ // }
}
}
}
diff --git a/Assets/Scripts/Minigames/StatueDressup/Controllers/StatuePhotoGalleryController.cs b/Assets/Scripts/Minigames/StatueDressup/Controllers/StatuePhotoGalleryController.cs
index 271093e3..e52c1e42 100644
--- a/Assets/Scripts/Minigames/StatueDressup/Controllers/StatuePhotoGalleryController.cs
+++ b/Assets/Scripts/Minigames/StatueDressup/Controllers/StatuePhotoGalleryController.cs
@@ -2,9 +2,9 @@
using System.Collections.Generic;
using Core;
using Core.Lifecycle;
-using Minigames.StatueDressup.Utils;
using UnityEngine;
using UnityEngine.UI;
+using Utils;
namespace Minigames.StatueDressup.Controllers
{
@@ -18,49 +18,50 @@ namespace Minigames.StatueDressup.Controllers
[Header("Gallery UI")]
[SerializeField] private Transform gridContainer;
[SerializeField] private PhotoGridItem gridItemPrefab;
- [SerializeField] private ScrollRect scrollRect;
[Header("Enlarged View")]
- [SerializeField] private GameObject enlargedViewPanel;
- [SerializeField] private Image enlargedPhotoImage;
- [SerializeField] private Button closeEnlargedButton;
- [SerializeField] private Button deletePhotoButton;
- [SerializeField] private Text photoInfoText;
+ [SerializeField] private Transform enlargedContainer; // Container for enlarged preview (top layer)
+ [SerializeField] private GameObject backdrop; // Dark backdrop for enlarged view
+ [SerializeField] private GameObject enlargedPreviewPrefab; // Prefab for enlarged preview (same as grid item)
[Header("Pagination")]
- [SerializeField] private Button loadMoreButton;
- [SerializeField] private Text statusText;
+ [SerializeField] private Button previousPageButton;
+ [SerializeField] private Button nextPageButton;
+ [SerializeField] private Text pageStatusText;
- [Header("Settings")]
- [SerializeField] private int itemsPerPage = 20;
- [SerializeField] private int thumbnailSize = 256;
- [SerializeField] private int maxCachedThumbnails = 50; // Keep recent thumbnails in memory
-
- private int _currentPage = 0;
+ private AppleHills.Core.Settings.IStatueDressupSettings _settings;
+ private int _currentPage;
private List _allPhotoIds = new List();
private Dictionary _activeGridItems = new Dictionary();
private Dictionary _thumbnailCache = new Dictionary();
+ private Dictionary _fullPhotoCache = new Dictionary(); // Cache full photos for enlargement
private Queue _thumbnailCacheOrder = new Queue();
- private string _currentEnlargedPhotoId = null;
- private Texture2D _currentEnlargedTexture = null;
+ private bool _isLoadingPage;
+ private PhotoEnlargeController _enlargeController;
internal override void OnManagedStart()
{
base.OnManagedStart();
- // Setup buttons
- if (closeEnlargedButton != null)
- closeEnlargedButton.onClick.AddListener(CloseEnlargedView);
+ // Get settings
+ _settings = GameManager.GetSettingsObject();
- if (deletePhotoButton != null)
- deletePhotoButton.onClick.AddListener(DeleteCurrentPhoto);
+ // Initialize enlarge controller
+ _enlargeController = new PhotoEnlargeController(backdrop, enlargedContainer, _settings?.GalleryAnimationDuration ?? 0.3f);
- if (loadMoreButton != null)
- loadMoreButton.onClick.AddListener(LoadNextPage);
+ // Setup page navigation buttons
+ if (previousPageButton != null)
+ previousPageButton.onClick.AddListener(OnPreviousPageClicked);
- // Hide enlarged view initially
- if (enlargedViewPanel != null)
- enlargedViewPanel.SetActive(false);
+ if (nextPageButton != null)
+ nextPageButton.onClick.AddListener(OnNextPageClicked);
+
+ // Hide backdrop initially
+ if (backdrop != null)
+ backdrop.SetActive(false);
+
+ // Clear grid initially (in case there are leftover items from scene setup)
+ ClearGrid();
// Load first page
RefreshGallery();
@@ -72,35 +73,35 @@ namespace Minigames.StatueDressup.Controllers
public void RefreshGallery()
{
// Clear existing items
- ClearGallery();
+ ClearGrid();
// Get all photo IDs
- _allPhotoIds = StatuePhotoManager.GetAllPhotoIds();
+ _allPhotoIds = PhotoManager.GetAllPhotoIds(CaptureType.StatueMinigame);
_currentPage = 0;
Logging.Debug($"[StatuePhotoGalleryController] Gallery refreshed: {_allPhotoIds.Count} photos");
- // Load first page
- LoadNextPage();
+ // Display first page
+ DisplayCurrentPage();
}
///
- /// Load next page of photos
+ /// Display the current page of photos (clears grid and shows only current page)
///
- private void LoadNextPage()
+ private void DisplayCurrentPage()
{
- List pagePhotoIds = StatuePhotoManager.GetPhotoIdsPage(_currentPage, itemsPerPage);
+ if (_isLoadingPage) return;
- if (pagePhotoIds.Count == 0)
- {
- if (loadMoreButton != null)
- loadMoreButton.gameObject.SetActive(false);
-
- UpdateStatusText($"All photos loaded ({_allPhotoIds.Count} total)");
- return;
- }
+ _isLoadingPage = true;
- Logging.Debug($"[StatuePhotoGalleryController] Loading page {_currentPage}: {pagePhotoIds.Count} items");
+ // Clear current grid
+ ClearGrid();
+
+ // Get photos for current page
+ int itemsPerPage = _settings?.GalleryItemsPerPage ?? 20;
+ List pagePhotoIds = PhotoManager.GetPhotoIdsPage(CaptureType.StatueMinigame, _currentPage, itemsPerPage);
+
+ Logging.Debug($"[StatuePhotoGalleryController] Displaying page {_currentPage + 1}: {pagePhotoIds.Count} items");
// Spawn grid items for this page
foreach (string photoId in pagePhotoIds)
@@ -108,14 +109,64 @@ namespace Minigames.StatueDressup.Controllers
SpawnGridItem(photoId);
}
- _currentPage++;
+ // Update button states
+ UpdatePageButtons();
- // Update UI state
- bool hasMore = _currentPage * itemsPerPage < _allPhotoIds.Count;
- if (loadMoreButton != null)
- loadMoreButton.gameObject.SetActive(hasMore);
+ // Update status text
+ int totalPages = Mathf.CeilToInt((float)_allPhotoIds.Count / itemsPerPage);
+ UpdateStatusText($"Page {_currentPage + 1}/{totalPages} ({_allPhotoIds.Count} photos)");
- UpdateStatusText($"Showing {_activeGridItems.Count} of {_allPhotoIds.Count} photos");
+ _isLoadingPage = false;
+ }
+
+ ///
+ /// Update page navigation button states
+ ///
+ private void UpdatePageButtons()
+ {
+ int itemsPerPage = _settings?.GalleryItemsPerPage ?? 20;
+ int totalPages = Mathf.CeilToInt((float)_allPhotoIds.Count / itemsPerPage);
+
+ // Enable/disable previous button
+ if (previousPageButton != null)
+ {
+ previousPageButton.interactable = _currentPage > 0;
+ }
+
+ // Enable/disable next button
+ if (nextPageButton != null)
+ {
+ nextPageButton.interactable = _currentPage < totalPages - 1;
+ }
+ }
+
+ ///
+ /// Navigate to previous page
+ ///
+ private void OnPreviousPageClicked()
+ {
+ if (_currentPage > 0)
+ {
+ _currentPage--;
+ DisplayCurrentPage();
+ Logging.Debug($"[StatuePhotoGalleryController] Navigated to previous page: {_currentPage}");
+ }
+ }
+
+ ///
+ /// Navigate to next page
+ ///
+ private void OnNextPageClicked()
+ {
+ int itemsPerPage = _settings?.GalleryItemsPerPage ?? 20;
+ int totalPages = Mathf.CeilToInt((float)_allPhotoIds.Count / itemsPerPage);
+
+ if (_currentPage < totalPages - 1)
+ {
+ _currentPage++;
+ DisplayCurrentPage();
+ Logging.Debug($"[StatuePhotoGalleryController] Navigated to next page: {_currentPage}");
+ }
}
///
@@ -154,7 +205,7 @@ namespace Minigames.StatueDressup.Controllers
yield return null;
// Load full photo
- Texture2D fullPhoto = StatuePhotoManager.LoadPhoto(photoId);
+ Texture2D fullPhoto = PhotoManager.LoadPhoto(CaptureType.StatueMinigame, photoId);
if (fullPhoto == null)
{
@@ -163,7 +214,8 @@ namespace Minigames.StatueDressup.Controllers
}
// Create thumbnail
- Texture2D thumbnail = StatuePhotoManager.CreateThumbnail(fullPhoto, thumbnailSize);
+ int thumbSize = _settings?.GalleryThumbnailSize ?? 256;
+ Texture2D thumbnail = PhotoManager.CreateThumbnail(fullPhoto, thumbSize);
// Destroy full photo immediately (we only need thumbnail)
Destroy(fullPhoto);
@@ -188,7 +240,8 @@ namespace Minigames.StatueDressup.Controllers
_thumbnailCacheOrder.Enqueue(photoId);
// Evict oldest if over limit
- while (_thumbnailCache.Count > maxCachedThumbnails && _thumbnailCacheOrder.Count > 0)
+ int maxCached = _settings?.GalleryMaxCachedThumbnails ?? 50;
+ while (_thumbnailCache.Count > maxCached && _thumbnailCacheOrder.Count > 0)
{
string oldestId = _thumbnailCacheOrder.Dequeue();
@@ -202,154 +255,90 @@ namespace Minigames.StatueDressup.Controllers
}
///
- /// Show enlarged view of a photo (called by PhotoGridItem)
+ /// Enlarge a photo (called by PhotoGridItem)
///
- public void ShowEnlargedView(string photoId)
+ public void OnGridItemClicked(PhotoGridItem gridItem, string photoId)
{
- if (enlargedViewPanel == null || enlargedPhotoImage == null)
+ if (_enlargeController == null)
{
- Logging.Warning("[StatuePhotoGalleryController] Enlarged view UI not configured");
+ Logging.Error("[StatuePhotoGalleryController] Enlarge controller not initialized");
return;
}
- Logging.Debug($"[StatuePhotoGalleryController] Showing enlarged view: {photoId}");
-
- // Clear previous enlarged texture
- if (_currentEnlargedTexture != null)
+ // If already enlarged, shrink it
+ if (_enlargeController.IsPhotoEnlarged)
{
- Destroy(_currentEnlargedTexture);
- _currentEnlargedTexture = null;
- }
-
- // Load full-size photo
- _currentEnlargedTexture = StatuePhotoManager.LoadPhoto(photoId);
-
- if (_currentEnlargedTexture == null)
- {
- Logging.Error($"[StatuePhotoGalleryController] Failed to load enlarged photo: {photoId}");
+ _enlargeController.ShrinkPhoto();
return;
}
- // Create sprite from texture
- Sprite enlargedSprite = Sprite.Create(
- _currentEnlargedTexture,
- new Rect(0, 0, _currentEnlargedTexture.width, _currentEnlargedTexture.height),
- new Vector2(0.5f, 0.5f)
- );
+ Logging.Debug($"[StatuePhotoGalleryController] Enlarging photo: {photoId}");
- enlargedPhotoImage.sprite = enlargedSprite;
- _currentEnlargedPhotoId = photoId;
+ float enlargedScale = _settings?.GalleryEnlargedScale ?? 2.5f;
- // Update photo info
- UpdatePhotoInfo(photoId);
-
- // Show panel
- enlargedViewPanel.SetActive(true);
- }
-
- ///
- /// Close enlarged view
- ///
- private void CloseEnlargedView()
- {
- if (enlargedViewPanel != null)
- enlargedViewPanel.SetActive(false);
-
- // Clean up texture
- if (_currentEnlargedTexture != null)
+ // Check cache first
+ if (_fullPhotoCache.TryGetValue(photoId, out Texture2D fullPhoto))
{
- Destroy(_currentEnlargedTexture);
- _currentEnlargedTexture = null;
- }
-
- _currentEnlargedPhotoId = null;
- }
-
- ///
- /// Delete currently viewed photo
- ///
- private void DeleteCurrentPhoto()
- {
- if (string.IsNullOrEmpty(_currentEnlargedPhotoId))
- {
- Logging.Warning("[StatuePhotoGalleryController] No photo selected for deletion");
- return;
- }
-
- string photoIdToDelete = _currentEnlargedPhotoId;
-
- // Close enlarged view first
- CloseEnlargedView();
-
- // Delete photo
- bool deleted = StatuePhotoManager.DeletePhoto(photoIdToDelete);
-
- if (deleted)
- {
- // Remove from grid
- if (_activeGridItems.TryGetValue(photoIdToDelete, out PhotoGridItem gridItem))
- {
- Destroy(gridItem.gameObject);
- _activeGridItems.Remove(photoIdToDelete);
- }
-
- // Remove from cache
- if (_thumbnailCache.TryGetValue(photoIdToDelete, out Texture2D thumbnail))
- {
- Destroy(thumbnail);
- _thumbnailCache.Remove(photoIdToDelete);
- }
-
- // Refresh photo list
- _allPhotoIds.Remove(photoIdToDelete);
-
- UpdateStatusText($"Photo deleted. {_allPhotoIds.Count} photos remaining");
-
- Logging.Debug($"[StatuePhotoGalleryController] Photo deleted: {photoIdToDelete}");
- }
- }
-
- ///
- /// Update photo info text in enlarged view
- ///
- private void UpdatePhotoInfo(string photoId)
- {
- if (photoInfoText == null) return;
-
- StatuePhotoManager.PhotoMetadata metadata = StatuePhotoManager.GetPhotoMetadata(photoId);
-
- if (metadata != null)
- {
- System.DateTime timestamp = System.DateTime.Parse(metadata.timestamp);
- string dateStr = timestamp.ToString("MMM dd, yyyy hh:mm tt");
-
- float fileSizeMB = metadata.fileSizeBytes / (1024f * 1024f);
-
- photoInfoText.text = $"Date: {dateStr}\n" +
- $"Decorations: {metadata.decorationCount}\n" +
- $"Size: {fileSizeMB:F2} MB";
+ // Use cached photo
+ _enlargeController.EnlargePhoto(gridItem, enlargedPreviewPrefab != null ? enlargedPreviewPrefab : gridItem.gameObject, fullPhoto, enlargedScale);
}
else
{
- photoInfoText.text = "Photo information unavailable";
+ // Load full-size photo
+ fullPhoto = PhotoManager.LoadPhoto(CaptureType.StatueMinigame, photoId);
+
+ if (fullPhoto == null)
+ {
+ Logging.Error($"[StatuePhotoGalleryController] Failed to load photo: {photoId}");
+ return;
+ }
+
+ // Cache it (limited cache)
+ if (_fullPhotoCache.Count < 10) // Keep only recent 10 full photos
+ {
+ _fullPhotoCache[photoId] = fullPhoto;
+ }
+
+ _enlargeController.EnlargePhoto(gridItem, enlargedPreviewPrefab != null ? enlargedPreviewPrefab : gridItem.gameObject, fullPhoto, enlargedScale);
}
}
+ ///
+ /// Cleanup when gallery is closed
+ ///
+ public void CleanupGallery()
+ {
+ if (_enlargeController != null)
+ {
+ _enlargeController.Cleanup();
+ }
+
+ // Clean up cached full photos
+ foreach (var photo in _fullPhotoCache.Values)
+ {
+ if (photo != null)
+ {
+ Destroy(photo);
+ }
+ }
+ _fullPhotoCache.Clear();
+ }
+
///
/// Update status text
///
private void UpdateStatusText(string message)
{
- if (statusText != null)
- statusText.text = message;
+ if (pageStatusText != null)
+ pageStatusText.text = message;
Logging.Debug($"[StatuePhotoGalleryController] Status: {message}");
}
///
- /// Clear all grid items and cached data
+ /// Clear only the grid items (used when switching pages)
///
- private void ClearGallery()
+ private void ClearGrid()
{
// Destroy grid items
foreach (var gridItem in _activeGridItems.Values)
@@ -359,6 +348,16 @@ namespace Minigames.StatueDressup.Controllers
}
_activeGridItems.Clear();
+ Logging.Debug("[StatuePhotoGalleryController] Grid cleared");
+ }
+
+ ///
+ /// Clear all grid items and cached data (full cleanup)
+ ///
+ private void ClearGallery()
+ {
+ ClearGrid();
+
// Clear thumbnail cache
foreach (var thumbnail in _thumbnailCache.Values)
{
@@ -368,7 +367,7 @@ namespace Minigames.StatueDressup.Controllers
_thumbnailCache.Clear();
_thumbnailCacheOrder.Clear();
- Logging.Debug("[StatuePhotoGalleryController] Gallery cleared");
+ Logging.Debug("[StatuePhotoGalleryController] Gallery fully cleared");
}
internal override void OnManagedDestroy()
@@ -377,17 +376,14 @@ namespace Minigames.StatueDressup.Controllers
// Cleanup
ClearGallery();
- CloseEnlargedView();
+ CleanupGallery();
// Unsubscribe buttons
- if (closeEnlargedButton != null)
- closeEnlargedButton.onClick.RemoveListener(CloseEnlargedView);
+ if (previousPageButton != null)
+ previousPageButton.onClick.RemoveListener(OnPreviousPageClicked);
- if (deletePhotoButton != null)
- deletePhotoButton.onClick.RemoveListener(DeleteCurrentPhoto);
-
- if (loadMoreButton != null)
- loadMoreButton.onClick.RemoveListener(LoadNextPage);
+ if (nextPageButton != null)
+ nextPageButton.onClick.RemoveListener(OnNextPageClicked);
}
}
}
diff --git a/Assets/Scripts/Minigames/StatueDressup/Data/DecorationMetadata.cs b/Assets/Scripts/Minigames/StatueDressup/Data/DecorationMetadata.cs
new file mode 100644
index 00000000..65b9bae2
--- /dev/null
+++ b/Assets/Scripts/Minigames/StatueDressup/Data/DecorationMetadata.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Minigames.StatueDressup.Data
+{
+ ///
+ /// Metadata for a single decoration placement
+ ///
+ [Serializable]
+ public class DecorationPlacement
+ {
+ public string decorationId; // Unique ID to load decoration
+ public Vector2 localPosition; // Position relative to statue
+ public Vector2 localScale; // Scale relative to statue
+ public float rotation; // Z rotation in degrees
+ public int sortingOrder; // Sprite sorting order
+ }
+
+ ///
+ /// Coordinate system type used when saving decoration positions
+ ///
+ public enum CoordinateSystemType
+ {
+ WorldSpace, // Regular Transform (world units)
+ UIRectTransform // UI RectTransform (pixel coordinates)
+ }
+
+ ///
+ /// Collection of decoration placements for a statue
+ ///
+ [Serializable]
+ public class StatueDecorationData
+ {
+ public string photoId; // Associated photo ID
+ public string timestamp; // When captured
+ public CoordinateSystemType coordinateSystem; // Source coordinate system
+ public Vector2 sourceStatueSize; // Size of statue in source units (for conversion)
+ public List placements = new List();
+ }
+}
+
diff --git a/Assets/Scripts/Minigames/StatueDressup/Data/DecorationMetadata.cs.meta b/Assets/Scripts/Minigames/StatueDressup/Data/DecorationMetadata.cs.meta
new file mode 100644
index 00000000..067a3fd0
--- /dev/null
+++ b/Assets/Scripts/Minigames/StatueDressup/Data/DecorationMetadata.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: bde3a2b8ef7247d29967999bb5e9dbd8
+timeCreated: 1764163703
\ No newline at end of file
diff --git a/Assets/Scripts/Minigames/StatueDressup/Display.meta b/Assets/Scripts/Minigames/StatueDressup/Display.meta
new file mode 100644
index 00000000..9cf2b339
--- /dev/null
+++ b/Assets/Scripts/Minigames/StatueDressup/Display.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 21f5742e8db64d52a293d822c93df4f3
+timeCreated: 1764163758
\ No newline at end of file
diff --git a/Assets/Scripts/Minigames/StatueDressup/Display/StatueDecorationLoader.cs b/Assets/Scripts/Minigames/StatueDressup/Display/StatueDecorationLoader.cs
new file mode 100644
index 00000000..84a9738e
--- /dev/null
+++ b/Assets/Scripts/Minigames/StatueDressup/Display/StatueDecorationLoader.cs
@@ -0,0 +1,305 @@
+using System.Collections.Generic;
+using Core;
+using Core.Lifecycle;
+using Minigames.StatueDressup.Data;
+using UnityEngine;
+using UnityEngine.ResourceManagement.AsyncOperations;
+using Utils;
+
+namespace Minigames.StatueDressup.Display
+{
+ ///
+ /// Loads decoration metadata and reconstructs decorations on a statue sprite.
+ /// Place this component on a GameObject with a SpriteRenderer showing the statue.
+ /// On Start, loads all DecorationData via Addressables label, then spawns decorations from metadata.
+ ///
+ [RequireComponent(typeof(SpriteRenderer))]
+ public class StatueDecorationLoader : ManagedBehaviour
+ {
+ [Header("Settings")]
+ [Tooltip("Root GameObject for spawning decorations (clears only this, not statue children)")]
+ [SerializeField] private Transform decorationRoot;
+
+ [Tooltip("Load specific photo ID, or leave empty to load latest")]
+ [SerializeField] private string specificPhotoId = "";
+
+ [Header("Debug")]
+ [SerializeField] private bool showDebugInfo = true;
+
+ private SpriteRenderer _statueSpriteRenderer;
+ private Dictionary _decorationDataDict;
+ private AsyncOperationHandle> _decorationDataHandle;
+ private AppleHills.Core.Settings.IStatueDressupSettings _settings;
+
+ internal override void OnManagedStart()
+ {
+ base.OnManagedStart();
+
+ _statueSpriteRenderer = GetComponent();
+
+ // Get settings
+ _settings = GameManager.GetSettingsObject();
+
+ // Ensure decoration root exists
+ if (decorationRoot == null)
+ {
+ GameObject rootObj = new GameObject("DecorationRoot");
+ rootObj.transform.SetParent(transform, false);
+ decorationRoot = rootObj.transform;
+
+ if (showDebugInfo)
+ {
+ Logging.Debug("[StatueDecorationLoader] Created decoration root automatically");
+ }
+ }
+
+ // Start async loading via coroutine wrapper
+ StartCoroutine(LoadAndDisplayDecorationsCoroutine());
+ }
+
+ ///
+ /// Coroutine wrapper for async loading and display
+ ///
+ private System.Collections.IEnumerator LoadAndDisplayDecorationsCoroutine()
+ {
+ // Convert async Task to coroutine-compatible operation
+ var loadTask = LoadDecorationDataAsync();
+
+ // Wait for async operation to complete
+ while (!loadTask.IsCompleted)
+ {
+ yield return null;
+ }
+
+ // Check for exceptions
+ if (loadTask.IsFaulted)
+ {
+ Logging.Error($"[StatueDecorationLoader] Failed to load decoration data: {loadTask.Exception?.GetBaseException().Message}");
+ yield break;
+ }
+
+ // Load and display decorations
+ LoadAndDisplayDecorations();
+ }
+
+ ///
+ /// Load all DecorationData assets via Addressables and build lookup dictionary
+ ///
+ 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(
+ 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");
+ }
+ }
+
+ ///
+ /// Load decoration metadata and spawn decorations
+ ///
+ public void LoadAndDisplayDecorations()
+ {
+ // Check if DecorationData is loaded
+ if (_decorationDataDict == null || _decorationDataDict.Count == 0)
+ {
+ Logging.Warning("[StatueDecorationLoader] DecorationData not loaded yet. Cannot display decorations.");
+ return;
+ }
+
+ // Load metadata
+ StatueDecorationData data = string.IsNullOrEmpty(specificPhotoId)
+ ? PhotoManager.LoadLatestDecorationMetadata(CaptureType.StatueMinigame)
+ : PhotoManager.LoadDecorationMetadata(CaptureType.StatueMinigame, specificPhotoId);
+
+ if (data == null)
+ {
+ Logging.Warning("[StatueDecorationLoader] No decoration metadata found");
+ return;
+ }
+
+ if (showDebugInfo)
+ {
+ Logging.Debug($"[StatueDecorationLoader] Loading {data.placements.Count} decorations from {data.photoId}");
+ Logging.Debug($"[StatueDecorationLoader] Source coordinate system: {data.coordinateSystem}, statue size: {data.sourceStatueSize}");
+ }
+
+ // Clear existing decorations (in case reloading)
+ ClearDecorations();
+
+ // Calculate coordinate conversion factor if needed
+ float conversionFactor = CalculateCoordinateConversion(data);
+
+ // Spawn each decoration synchronously (data already loaded)
+ int successCount = 0;
+ foreach (var placement in data.placements)
+ {
+ if (SpawnDecoration(placement, conversionFactor))
+ {
+ successCount++;
+ }
+ }
+
+ if (showDebugInfo)
+ {
+ Logging.Debug($"[StatueDecorationLoader] Successfully loaded {successCount}/{data.placements.Count} decorations");
+ }
+ }
+
+ ///
+ /// Calculate coordinate conversion factor between source and target coordinate systems
+ ///
+ private float CalculateCoordinateConversion(StatueDecorationData data)
+ {
+ // If source was world space and we're also world space, no conversion needed
+ if (data.coordinateSystem == CoordinateSystemType.WorldSpace)
+ {
+ if (showDebugInfo)
+ {
+ Logging.Debug("[StatueDecorationLoader] No coordinate conversion needed (WorldSpace → WorldSpace)");
+ }
+ return 1f;
+ }
+
+ // Source was UI RectTransform (pixels), target is WorldSpace (units)
+ // Need to convert from source statue pixel size to target statue world size
+
+ // Get target statue size (world units)
+ Vector2 targetStatueSize = Vector2.one;
+ if (_statueSpriteRenderer != null && _statueSpriteRenderer.sprite != null)
+ {
+ targetStatueSize = _statueSpriteRenderer.sprite.bounds.size;
+ }
+
+ // Calculate conversion factor (target size / source size)
+ float conversionX = targetStatueSize.x / data.sourceStatueSize.x;
+ float conversionY = targetStatueSize.y / data.sourceStatueSize.y;
+
+ // Use average of X and Y for uniform scaling (or could use separate X/Y)
+ float conversionFactor = (conversionX + conversionY) / 2f;
+
+ if (showDebugInfo)
+ {
+ Logging.Debug($"[StatueDecorationLoader] Coordinate conversion: UI({data.sourceStatueSize}) → World({targetStatueSize}) = factor {conversionFactor:F3}");
+ }
+
+ return conversionFactor;
+ }
+
+ ///
+ /// Spawn a single decoration from placement data
+ /// Looks up DecorationData from pre-loaded dictionary and applies coordinate conversion
+ ///
+ private bool SpawnDecoration(DecorationPlacement placement, float conversionFactor)
+ {
+ // Look up DecorationData from dictionary
+ if (!_decorationDataDict.TryGetValue(placement.decorationId, out DecorationData decorationData))
+ {
+ Logging.Warning($"[StatueDecorationLoader] DecorationData not found for ID: {placement.decorationId}");
+ return false;
+ }
+
+ // Get sprite from DecorationData
+ Sprite decorationSprite = decorationData.DecorationSprite;
+
+ if (decorationSprite == null)
+ {
+ Logging.Warning($"[StatueDecorationLoader] DecorationData has null sprite: {placement.decorationId}");
+ return false;
+ }
+
+ // Create GameObject for decoration
+ GameObject decorationObj = new GameObject($"Decoration_{placement.decorationId}");
+ decorationObj.transform.SetParent(decorationRoot, false); // false = keep local position
+
+ // Add SpriteRenderer
+ SpriteRenderer spriteRenderer = decorationObj.AddComponent();
+ spriteRenderer.sprite = decorationSprite;
+ spriteRenderer.sortingLayerName = "Foreground";
+ spriteRenderer.sortingOrder = _statueSpriteRenderer.sortingOrder + placement.sortingOrder;
+
+ // Apply transform with coordinate conversion
+ Vector3 convertedPosition = placement.localPosition * conversionFactor;
+ decorationObj.transform.localPosition = convertedPosition;
+ decorationObj.transform.localScale = placement.localScale;
+ decorationObj.transform.localEulerAngles = new Vector3(0, 0, placement.rotation);
+
+ if (showDebugInfo)
+ {
+ Logging.Debug($"[StatueDecorationLoader] Spawned: {placement.decorationId} at {convertedPosition} (original: {placement.localPosition}, factor: {conversionFactor:F3})");
+ }
+
+ return true;
+ }
+
+ ///
+ /// Clear all existing decorations from decorationRoot
+ ///
+ public void ClearDecorations()
+ {
+ if (decorationRoot == null) return;
+
+ // Remove all children from decoration root only
+ for (int i = decorationRoot.childCount - 1; i >= 0; i--)
+ {
+ if (Application.isPlaying)
+ {
+ Destroy(decorationRoot.GetChild(i).gameObject);
+ }
+ else
+ {
+ DestroyImmediate(decorationRoot.GetChild(i).gameObject);
+ }
+ }
+ }
+
+ ///
+ /// Cleanup - release Addressables handle
+ ///
+ private void OnDestroy()
+ {
+ // Release DecorationData handle
+ AddressablesUtility.ReleaseHandle(_decorationDataHandle);
+ }
+
+ ///
+ /// Reload decorations (useful for testing)
+ ///
+ [ContextMenu("Reload Decorations")]
+ public void ReloadDecorations()
+ {
+ LoadAndDisplayDecorations();
+ }
+
+ ///
+ /// Load specific photo's decorations
+ ///
+ public void LoadSpecificPhoto(string photoId)
+ {
+ specificPhotoId = photoId;
+ LoadAndDisplayDecorations();
+ }
+ }
+}
+
diff --git a/Assets/Scripts/Minigames/StatueDressup/Display/StatueDecorationLoader.cs.meta b/Assets/Scripts/Minigames/StatueDressup/Display/StatueDecorationLoader.cs.meta
new file mode 100644
index 00000000..ae856cca
--- /dev/null
+++ b/Assets/Scripts/Minigames/StatueDressup/Display/StatueDecorationLoader.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 50d0f4591bbd40fc81dc615fa465e0c5
+timeCreated: 1764163758
\ No newline at end of file
diff --git a/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationDraggableInstance.cs b/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationDraggableInstance.cs
index 77481188..d6446961 100644
--- a/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationDraggableInstance.cs
+++ b/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationDraggableInstance.cs
@@ -1,7 +1,6 @@
using Core;
using Minigames.StatueDressup.Controllers;
using Minigames.StatueDressup.Data;
-using Minigames.StatueDressup.Utils;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
@@ -77,6 +76,40 @@ namespace Minigames.StatueDressup.DragDrop
Logging.Debug($"[DecorationDraggableInstance] Initialized: {data?.DecorationName}");
}
+ ///
+ /// Initialize as already placed decoration (from saved state)
+ /// Skips drag logic and sets up as if already placed on statue
+ ///
+ public void InitializeAsPlaced(DecorationData data, StatueDecorationController controller,
+ AppleHills.Core.Settings.IStatueDressupSettings settings)
+ {
+ _decorationData = data;
+ _controller = controller;
+ _settings = settings;
+ _isPlacedOnStatue = true;
+ _isDragging = false;
+
+ // 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 non-interactive for placed state (can be made interactive later if needed)
+ if (canvasGroup != null)
+ {
+ canvasGroup.blocksRaycasts = true;
+ }
+
+ Logging.Debug($"[DecorationDraggableInstance] Initialized as placed: {data?.DecorationName}");
+ }
+
///
/// Start dragging from icon
///
diff --git a/Assets/Scripts/Minigames/StatueDressup/UI.meta b/Assets/Scripts/Minigames/StatueDressup/UI.meta
new file mode 100644
index 00000000..31ed8298
--- /dev/null
+++ b/Assets/Scripts/Minigames/StatueDressup/UI.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 49800fa9079d485cbc65922d238d214a
+timeCreated: 1764151454
\ No newline at end of file
diff --git a/Assets/Scripts/Minigames/StatueDressup/UI/PhotoGalleryPage.cs b/Assets/Scripts/Minigames/StatueDressup/UI/PhotoGalleryPage.cs
new file mode 100644
index 00000000..cdcdb5dc
--- /dev/null
+++ b/Assets/Scripts/Minigames/StatueDressup/UI/PhotoGalleryPage.cs
@@ -0,0 +1,28 @@
+using UI.Core;
+
+namespace Minigames.StatueDressup.UI
+{
+ ///
+ /// UIPage wrapper for the photo gallery.
+ /// Simple stock page with no transition animations.
+ ///
+ public class PhotoGalleryPage : UIPage
+ {
+ protected override void DoTransitionIn(System.Action onComplete)
+ {
+ // Instant transition - just show
+ gameObject.SetActive(true);
+ onComplete?.Invoke();
+ }
+
+ protected override void DoTransitionOut(System.Action onComplete)
+ {
+ // Instant transition - just hide
+ gameObject.SetActive(false);
+ onComplete?.Invoke();
+ }
+
+ // OnBackPressed uses default behavior (pops the page)
+ }
+}
+
diff --git a/Assets/Scripts/Minigames/StatueDressup/UI/PhotoGalleryPage.cs.meta b/Assets/Scripts/Minigames/StatueDressup/UI/PhotoGalleryPage.cs.meta
new file mode 100644
index 00000000..f94b1f2e
--- /dev/null
+++ b/Assets/Scripts/Minigames/StatueDressup/UI/PhotoGalleryPage.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 3136a7edf8de421e9860c6bd4e1dca10
+timeCreated: 1764151460
\ No newline at end of file
diff --git a/Assets/Scripts/Minigames/StatueDressup/UI/PlayAreaPage.cs b/Assets/Scripts/Minigames/StatueDressup/UI/PlayAreaPage.cs
new file mode 100644
index 00000000..30b03cfd
--- /dev/null
+++ b/Assets/Scripts/Minigames/StatueDressup/UI/PlayAreaPage.cs
@@ -0,0 +1,32 @@
+using UI.Core;
+
+namespace Minigames.StatueDressup.UI
+{
+ ///
+ /// UIPage wrapper for the statue decoration play area.
+ /// Simple stock page with no transition animations.
+ ///
+ public class PlayAreaPage : UIPage
+ {
+ protected override void DoTransitionIn(System.Action onComplete)
+ {
+ // Instant transition - just show
+ gameObject.SetActive(true);
+ onComplete?.Invoke();
+ }
+
+ protected override void DoTransitionOut(System.Action onComplete)
+ {
+ // Instant transition - just hide
+ gameObject.SetActive(false);
+ onComplete?.Invoke();
+ }
+
+ public override void OnBackPressed()
+ {
+ // Play area is the root page - don't allow back navigation
+ // Override if you want custom behavior (e.g., quit minigame)
+ }
+ }
+}
+
diff --git a/Assets/Scripts/Minigames/StatueDressup/UI/PlayAreaPage.cs.meta b/Assets/Scripts/Minigames/StatueDressup/UI/PlayAreaPage.cs.meta
new file mode 100644
index 00000000..4ba84080
--- /dev/null
+++ b/Assets/Scripts/Minigames/StatueDressup/UI/PlayAreaPage.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: edd2867b8a4f42d8af202f215c3ecc47
+timeCreated: 1764151454
\ No newline at end of file
diff --git a/Assets/Scripts/Utils/AddressablesUtility.cs b/Assets/Scripts/Utils/AddressablesUtility.cs
new file mode 100644
index 00000000..639dc261
--- /dev/null
+++ b/Assets/Scripts/Utils/AddressablesUtility.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Core;
+using UnityEngine.AddressableAssets;
+using UnityEngine.ResourceManagement.AsyncOperations;
+
+namespace Utils
+{
+ ///
+ /// Utility class for common Addressables operations.
+ /// Provides generic methods for loading assets by label and creating lookup dictionaries.
+ ///
+ public static class AddressablesUtility
+ {
+ ///
+ /// Load all assets with a specific label and create a dictionary indexed by a key selector.
+ ///
+ /// Type of asset to load
+ /// Type of key for dictionary
+ /// Addressables label to filter by
+ /// Function to extract key from asset (e.g., asset => asset.Id)
+ /// Optional callback for progress updates (0-1)
+ /// Dictionary of assets indexed by key, and operation handle for cleanup
+ public static async Task<(Dictionary dictionary, AsyncOperationHandle> handle)>
+ LoadAssetsByLabelAsync(
+ string label,
+ Func keySelector,
+ Action onProgress = null)
+ {
+ Dictionary dictionary = new Dictionary();
+
+ // Load all assets with the specified label
+ AsyncOperationHandle> handle = Addressables.LoadAssetsAsync(
+ label,
+ asset =>
+ {
+ // This callback is invoked for each asset as it loads
+ if (asset != null)
+ {
+ TKey key = keySelector(asset);
+ if (key != null && !dictionary.ContainsKey(key))
+ {
+ dictionary[key] = asset;
+ }
+ }
+ });
+
+ // Report progress if callback provided
+ while (!handle.IsDone)
+ {
+ onProgress?.Invoke(handle.PercentComplete);
+ await Task.Yield();
+ }
+
+ // Final progress update
+ onProgress?.Invoke(1f);
+
+ // Check if load was successful
+ if (handle.Status != AsyncOperationStatus.Succeeded)
+ {
+ Logging.Error($"[AddressablesUtility] Failed to load assets with label '{label}': {handle.OperationException?.Message}");
+ return (dictionary, handle);
+ }
+
+ Logging.Debug($"[AddressablesUtility] Loaded {dictionary.Count} assets with label '{label}'");
+
+ return (dictionary, handle);
+ }
+
+ ///
+ /// Load a single asset by address
+ ///
+ /// Type of asset to load
+ /// Addressable address/key
+ /// Loaded asset and operation handle for cleanup
+ public static async Task<(TAsset asset, AsyncOperationHandle handle)> LoadAssetAsync(string address)
+ {
+ AsyncOperationHandle handle = Addressables.LoadAssetAsync(address);
+
+ await handle.Task;
+
+ if (handle.Status != AsyncOperationStatus.Succeeded)
+ {
+ Logging.Warning($"[AddressablesUtility] Failed to load asset '{address}': {handle.OperationException?.Message}");
+ return (default(TAsset), handle);
+ }
+
+ return (handle.Result, handle);
+ }
+
+ ///
+ /// Safely release an Addressables handle
+ ///
+ public static void ReleaseHandle(AsyncOperationHandle handle)
+ {
+ if (handle.IsValid())
+ {
+ Addressables.Release(handle);
+ }
+ }
+ }
+}
+
diff --git a/Assets/Scripts/Utils/AddressablesUtility.cs.meta b/Assets/Scripts/Utils/AddressablesUtility.cs.meta
new file mode 100644
index 00000000..1dd6edfb
--- /dev/null
+++ b/Assets/Scripts/Utils/AddressablesUtility.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 81470e29c2d54df3967e373b71d18a0d
+timeCreated: 1764164457
\ No newline at end of file
diff --git a/Assets/Scripts/Utils/PhotoCaptureConfig.cs b/Assets/Scripts/Utils/PhotoCaptureConfig.cs
new file mode 100644
index 00000000..ba97f10a
--- /dev/null
+++ b/Assets/Scripts/Utils/PhotoCaptureConfig.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+
+namespace Utils
+{
+ ///
+ /// Capture types for different photo contexts
+ ///
+ public enum CaptureType
+ {
+ StatueMinigame,
+ DivingMinigame
+ }
+
+ ///
+ /// Configuration for a specific capture type
+ ///
+ [Serializable]
+ public class CaptureConfig
+ {
+ public string subFolder;
+ public string photoPrefix;
+ public string metadataPrefix;
+ public string indexKey;
+
+ public CaptureConfig(string subFolder, string photoPrefix, string metadataPrefix, string indexKey)
+ {
+ this.subFolder = subFolder;
+ this.photoPrefix = photoPrefix;
+ this.metadataPrefix = metadataPrefix;
+ this.indexKey = indexKey;
+ }
+ }
+
+ ///
+ /// Static configuration registry for all capture types
+ ///
+ public static class PhotoCaptureConfigs
+ {
+ private static readonly Dictionary Configs = new Dictionary
+ {
+ [CaptureType.StatueMinigame] = new CaptureConfig(
+ subFolder: "StatueMinigame",
+ photoPrefix: "Statue_",
+ metadataPrefix: "StatuePhoto_Meta_",
+ indexKey: "StatuePhoto_Index"
+ ),
+
+ [CaptureType.DivingMinigame] = new CaptureConfig(
+ subFolder: "DivingMinigame",
+ photoPrefix: "Diving_",
+ metadataPrefix: "DivingPhoto_Meta_",
+ indexKey: "DivingPhoto_Index"
+ )
+ };
+
+ ///
+ /// Get configuration for a specific capture type
+ ///
+ public static CaptureConfig GetConfig(CaptureType type)
+ {
+ if (Configs.TryGetValue(type, out CaptureConfig config))
+ {
+ return config;
+ }
+
+ throw new ArgumentException($"No configuration found for CaptureType: {type}");
+ }
+ }
+}
+
diff --git a/Assets/Scripts/Utils/PhotoCaptureConfig.cs.meta b/Assets/Scripts/Utils/PhotoCaptureConfig.cs.meta
new file mode 100644
index 00000000..f518c2e5
--- /dev/null
+++ b/Assets/Scripts/Utils/PhotoCaptureConfig.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 96dbe33216574c7f95d9a829f7768e69
+timeCreated: 1764159658
\ No newline at end of file
diff --git a/Assets/Scripts/Utils/PhotoManager.cs b/Assets/Scripts/Utils/PhotoManager.cs
new file mode 100644
index 00000000..a5fea87b
--- /dev/null
+++ b/Assets/Scripts/Utils/PhotoManager.cs
@@ -0,0 +1,635 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using Core;
+using UnityEngine;
+
+namespace Utils
+{
+ ///
+ /// Generalized photo capture, storage, and retrieval manager.
+ /// Supports multiple capture types (minigames, screenshots, etc.) with type-based configuration.
+ ///
+ public static class PhotoManager
+ {
+ private const string RootCapturesFolder = "Captures";
+
+ ///
+ /// Photo metadata stored in PlayerPrefs
+ ///
+ [Serializable]
+ public class PhotoMetadata
+ {
+ public string photoId;
+ public CaptureType captureType;
+ public string timestamp;
+ public int genericMetadata; // Can be decoration count, score, collectibles, etc.
+ public long fileSizeBytes;
+ }
+
+ #region Plug-and-Play Coroutine
+
+ ///
+ /// Capture and save photo in one coroutine call. Handles UI hiding, capture, save, and restoration.
+ ///
+ /// Type of capture (determines folder/prefix)
+ /// RectTransform defining the capture region
+ /// Optional UI elements to hide during capture
+ /// Callback with photoId on success
+ /// Callback with error message on failure
+ /// Generic metadata (decoration count, score, etc.)
+ /// Camera for coordinate conversion (null = Camera.main)
+ /// If true, clamps capture area to visible screen
+ public static IEnumerator CaptureAndSaveCoroutine(
+ CaptureType captureType,
+ RectTransform captureArea,
+ GameObject[] uiToHide = null,
+ Action onSuccess = null,
+ Action onFailure = null,
+ int metadata = 0,
+ Camera mainCamera = null,
+ bool clampToScreenBounds = true)
+ {
+ if (captureArea == null)
+ {
+ string error = "[PhotoManager] CaptureArea RectTransform is null!";
+ Logging.Error(error);
+ onFailure?.Invoke(error);
+ yield break;
+ }
+
+ // Hide UI elements
+ if (uiToHide != null)
+ {
+ foreach (var obj in uiToHide)
+ {
+ if (obj != null) obj.SetActive(false);
+ }
+ }
+
+ // Wait for UI to hide
+ yield return new WaitForEndOfFrame();
+
+ // Capture photo
+ bool captureComplete = false;
+ Texture2D capturedPhoto = null;
+
+ CaptureAreaPhoto(captureArea, (texture) =>
+ {
+ capturedPhoto = texture;
+ captureComplete = true;
+ }, mainCamera, clampToScreenBounds);
+
+ // Wait for capture to complete
+ yield return new WaitUntil(() => captureComplete);
+
+ // Restore UI elements
+ if (uiToHide != null)
+ {
+ foreach (var obj in uiToHide)
+ {
+ if (obj != null) obj.SetActive(true);
+ }
+ }
+
+ // Save photo
+ if (capturedPhoto != null)
+ {
+ string photoId = SavePhoto(captureType, capturedPhoto, metadata);
+
+ if (!string.IsNullOrEmpty(photoId))
+ {
+ Logging.Debug($"[PhotoManager] Photo saved successfully: {photoId}");
+ onSuccess?.Invoke(photoId);
+ }
+ else
+ {
+ string error = "[PhotoManager] Failed to save photo!";
+ Logging.Error(error);
+ onFailure?.Invoke(error);
+ }
+ }
+ else
+ {
+ string error = "[PhotoManager] Photo capture returned null!";
+ Logging.Error(error);
+ onFailure?.Invoke(error);
+ }
+ }
+
+ #endregion
+
+ #region Capture
+
+ ///
+ /// Capture a specific area of the screen using Screenshot Helper
+ ///
+ public static void CaptureAreaPhoto(
+ RectTransform captureArea,
+ Action onComplete,
+ Camera mainCamera = null,
+ bool clampToScreenBounds = true)
+ {
+ if (captureArea == null)
+ {
+ Logging.Error("[PhotoManager] CaptureArea RectTransform is null!");
+ onComplete?.Invoke(null);
+ return;
+ }
+
+ if (mainCamera == null) mainCamera = Camera.main;
+
+ // Use ScreenSpaceUtility to convert RectTransform to screen rect
+ Rect screenRect = ScreenSpaceUtility.RectTransformToScreenRect(
+ captureArea,
+ mainCamera,
+ clampToScreenBounds,
+ returnCenterPosition: true
+ );
+
+ Logging.Debug($"[PhotoManager] Capturing area: pos={screenRect.position}, size={screenRect.size}");
+
+ // Use Screenshot Helper's Capture method
+ ScreenshotHelper.Instance.Capture(
+ screenRect.position,
+ screenRect.size,
+ (texture) =>
+ {
+ if (texture != null)
+ {
+ Logging.Debug($"[PhotoManager] Photo captured: {texture.width}x{texture.height}");
+ onComplete?.Invoke(texture);
+ }
+ else
+ {
+ Logging.Error("[PhotoManager] Screenshot Helper returned null texture!");
+ onComplete?.Invoke(null);
+ }
+ }
+ );
+ }
+
+ #endregion
+
+ #region Save/Load
+
+ ///
+ /// Save photo to persistent storage with metadata
+ ///
+ public static string SavePhoto(CaptureType captureType, Texture2D photo, int metadata = 0)
+ {
+ if (photo == null)
+ {
+ Logging.Error("[PhotoManager] Cannot save null photo");
+ return null;
+ }
+
+ try
+ {
+ CaptureConfig config = PhotoCaptureConfigs.GetConfig(captureType);
+
+ // Generate unique photo ID
+ string photoId = $"{config.photoPrefix}{DateTime.Now.Ticks}";
+
+ // Get capture directory for this type
+ string captureDirectory = GetCaptureDirectory(captureType);
+
+ // Ensure directory exists
+ if (!Directory.Exists(captureDirectory))
+ {
+ Directory.CreateDirectory(captureDirectory);
+ }
+
+ // Save texture
+ string filePath = Path.Combine(captureDirectory, $"{photoId}.png");
+ byte[] pngData = photo.EncodeToPNG();
+ File.WriteAllBytes(filePath, pngData);
+
+ // Calculate file size
+ FileInfo fileInfo = new FileInfo(filePath);
+ long fileSize = fileInfo.Exists ? fileInfo.Length : 0;
+
+ // Save metadata
+ PhotoMetadata photoMetadata = new PhotoMetadata
+ {
+ photoId = photoId,
+ captureType = captureType,
+ timestamp = DateTime.Now.ToString("o"),
+ genericMetadata = metadata,
+ fileSizeBytes = fileSize
+ };
+
+ SaveMetadata(captureType, photoMetadata);
+ AddToPhotoIndex(captureType, photoId);
+
+ Logging.Debug($"[PhotoManager] Photo saved: {filePath} ({fileSize} bytes)");
+ return photoId;
+ }
+ catch (Exception e)
+ {
+ Logging.Error($"[PhotoManager] Failed to save photo: {e.Message}");
+ return null;
+ }
+ }
+
+ ///
+ /// Load photo texture from storage
+ ///
+ public static Texture2D LoadPhoto(CaptureType captureType, string photoId)
+ {
+ if (string.IsNullOrEmpty(photoId))
+ {
+ Logging.Warning("[PhotoManager] PhotoId is null or empty");
+ return null;
+ }
+
+ try
+ {
+ string filePath = GetPhotoFilePath(captureType, photoId);
+
+ if (!File.Exists(filePath))
+ {
+ Logging.Warning($"[PhotoManager] Photo not found: {filePath}");
+ return null;
+ }
+
+ byte[] fileData = File.ReadAllBytes(filePath);
+ Texture2D texture = new Texture2D(2, 2, TextureFormat.RGBA32, false);
+
+ if (texture.LoadImage(fileData))
+ {
+ Logging.Debug($"[PhotoManager] Photo loaded: {photoId} ({texture.width}x{texture.height})");
+ return texture;
+ }
+ else
+ {
+ Logging.Error($"[PhotoManager] Failed to decode image: {photoId}");
+ UnityEngine.Object.Destroy(texture);
+ return null;
+ }
+ }
+ catch (Exception e)
+ {
+ Logging.Error($"[PhotoManager] Failed to load photo {photoId}: {e.Message}");
+ return null;
+ }
+ }
+
+ ///
+ /// Load multiple photos (most recent first)
+ ///
+ public static List LoadPhotos(CaptureType captureType, int count)
+ {
+ List photoIds = GetPhotoIds(captureType, count);
+ List photos = new List();
+
+ foreach (string photoId in photoIds)
+ {
+ Texture2D photo = LoadPhoto(captureType, photoId);
+ if (photo != null)
+ {
+ photos.Add(photo);
+ }
+ }
+
+ return photos;
+ }
+
+ ///
+ /// Load all photos for a capture type
+ ///
+ public static List LoadAllPhotos(CaptureType captureType)
+ {
+ return LoadPhotos(captureType, -1);
+ }
+
+ ///
+ /// Delete photo and its metadata
+ ///
+ public static bool DeletePhoto(CaptureType captureType, string photoId)
+ {
+ if (string.IsNullOrEmpty(photoId)) return false;
+
+ try
+ {
+ string filePath = GetPhotoFilePath(captureType, photoId);
+
+ if (File.Exists(filePath))
+ {
+ File.Delete(filePath);
+ }
+
+ DeleteMetadata(captureType, photoId);
+ RemoveFromPhotoIndex(captureType, photoId);
+
+ Logging.Debug($"[PhotoManager] Photo deleted: {photoId}");
+ return true;
+ }
+ catch (Exception e)
+ {
+ Logging.Error($"[PhotoManager] Failed to delete photo {photoId}: {e.Message}");
+ return false;
+ }
+ }
+
+ #endregion
+
+ #region Retrieval & Queries
+
+ ///
+ /// Get photo IDs for a capture type (most recent first)
+ ///
+ /// Type of capture
+ /// Number of IDs to return (-1 = all)
+ public static List GetPhotoIds(CaptureType captureType, int count = -1)
+ {
+ List allIds = GetAllPhotoIds(captureType);
+
+ if (count < 0 || count >= allIds.Count)
+ {
+ return allIds;
+ }
+
+ return allIds.GetRange(0, count);
+ }
+
+ ///
+ /// Get all photo IDs sorted by timestamp (newest first)
+ ///
+ public static List GetAllPhotoIds(CaptureType captureType)
+ {
+ CaptureConfig config = PhotoCaptureConfigs.GetConfig(captureType);
+ string indexJson = PlayerPrefs.GetString(config.indexKey, "[]");
+ List photoIds = JsonUtility.FromJson(WrapJsonArray(indexJson))?.ids ?? new List();
+
+ // Sort by timestamp descending (newest first)
+ photoIds.Sort((a, b) =>
+ {
+ PhotoMetadata metaA = LoadMetadata(captureType, a);
+ PhotoMetadata metaB = LoadMetadata(captureType, b);
+
+ DateTime dateA = DateTime.Parse(metaA?.timestamp ?? DateTime.MinValue.ToString("o"));
+ DateTime dateB = DateTime.Parse(metaB?.timestamp ?? DateTime.MinValue.ToString("o"));
+
+ return dateB.CompareTo(dateA);
+ });
+
+ return photoIds;
+ }
+
+ ///
+ /// Get paginated photo IDs for optimized gallery loading
+ ///
+ public static List GetPhotoIdsPage(CaptureType captureType, int page, int pageSize)
+ {
+ List allIds = GetAllPhotoIds(captureType);
+ int startIndex = page * pageSize;
+
+ if (startIndex >= allIds.Count) return new List();
+
+ int count = Mathf.Min(pageSize, allIds.Count - startIndex);
+ return allIds.GetRange(startIndex, count);
+ }
+
+ ///
+ /// Get total number of saved photos
+ ///
+ public static int GetPhotoCount(CaptureType captureType)
+ {
+ return GetAllPhotoIds(captureType).Count;
+ }
+
+ ///
+ /// Get latest photo ID (most recent)
+ ///
+ public static string GetLatestPhotoId(CaptureType captureType)
+ {
+ List allIds = GetAllPhotoIds(captureType);
+ return allIds.Count > 0 ? allIds[0] : null;
+ }
+
+ ///
+ /// Load photo metadata
+ ///
+ public static PhotoMetadata GetPhotoMetadata(CaptureType captureType, string photoId)
+ {
+ return LoadMetadata(captureType, photoId);
+ }
+
+ #endregion
+
+ #region Utility Methods
+
+ ///
+ /// Create thumbnail from full-size photo (for gallery preview)
+ ///
+ public static Texture2D CreateThumbnail(Texture2D fullSizePhoto, int maxSize = 256)
+ {
+ if (fullSizePhoto == null) return null;
+
+ int width = fullSizePhoto.width;
+ int height = fullSizePhoto.height;
+
+ // Calculate thumbnail size maintaining aspect ratio
+ float scale = Mathf.Min((float)maxSize / width, (float)maxSize / height);
+ int thumbWidth = Mathf.RoundToInt(width * scale);
+ int thumbHeight = Mathf.RoundToInt(height * scale);
+
+ // Create thumbnail using bilinear filtering
+ RenderTexture rt = RenderTexture.GetTemporary(thumbWidth, thumbHeight, 0, RenderTextureFormat.ARGB32);
+ RenderTexture.active = rt;
+
+ Graphics.Blit(fullSizePhoto, rt);
+
+ Texture2D thumbnail = new Texture2D(thumbWidth, thumbHeight, TextureFormat.RGB24, false);
+ thumbnail.ReadPixels(new Rect(0, 0, thumbWidth, thumbHeight), 0, 0);
+ thumbnail.Apply();
+
+ RenderTexture.active = null;
+ RenderTexture.ReleaseTemporary(rt);
+
+ return thumbnail;
+ }
+
+ ///
+ /// Get capture directory for a specific type
+ ///
+ public static string GetCaptureDirectory(CaptureType captureType)
+ {
+ CaptureConfig config = PhotoCaptureConfigs.GetConfig(captureType);
+ return Path.Combine(Application.persistentDataPath, RootCapturesFolder, config.subFolder);
+ }
+
+ #endregion
+
+ #region Decoration Metadata
+
+ ///
+ /// Save decoration metadata for a photo
+ /// Saves both with photo ID and as "latest" for easy reference
+ ///
+ public static void SaveDecorationMetadata(CaptureType captureType, string photoId, T metadata) where T : class
+ {
+ try
+ {
+ string directory = GetCaptureDirectory(captureType);
+
+ // Ensure directory exists
+ if (!Directory.Exists(directory))
+ {
+ Directory.CreateDirectory(directory);
+ }
+
+ string json = JsonUtility.ToJson(metadata, true);
+
+ // Save with photo ID (for loading specific photo's decorations)
+ string specificPath = Path.Combine(directory, $"{photoId}_decorations.json");
+ File.WriteAllText(specificPath, json);
+
+ // Also save as "latest" for easy reference
+ CaptureConfig config = PhotoCaptureConfigs.GetConfig(captureType);
+ string latestPath = Path.Combine(directory, $"{config.subFolder}_latest.json");
+ File.WriteAllText(latestPath, json);
+
+ Logging.Debug($"[PhotoManager] Decoration metadata saved: {specificPath}");
+ }
+ catch (Exception e)
+ {
+ Logging.Error($"[PhotoManager] Failed to save decoration metadata: {e.Message}");
+ }
+ }
+
+ ///
+ /// Load decoration metadata for a specific photo
+ ///
+ public static T LoadDecorationMetadata(CaptureType captureType, string photoId) where T : class
+ {
+ try
+ {
+ string directory = GetCaptureDirectory(captureType);
+ string filePath = Path.Combine(directory, $"{photoId}_decorations.json");
+
+ if (!File.Exists(filePath))
+ {
+ Logging.Warning($"[PhotoManager] Decoration metadata not found: {filePath}");
+ return null;
+ }
+
+ string json = File.ReadAllText(filePath);
+ T metadata = JsonUtility.FromJson(json);
+
+ Logging.Debug($"[PhotoManager] Decoration metadata loaded: {filePath}");
+ return metadata;
+ }
+ catch (Exception e)
+ {
+ Logging.Error($"[PhotoManager] Failed to load decoration metadata: {e.Message}");
+ return null;
+ }
+ }
+
+ ///
+ /// Load the latest decoration metadata (most recent capture)
+ ///
+ public static T LoadLatestDecorationMetadata(CaptureType captureType) where T : class
+ {
+ try
+ {
+ CaptureConfig config = PhotoCaptureConfigs.GetConfig(captureType);
+ string directory = GetCaptureDirectory(captureType);
+ string filePath = Path.Combine(directory, $"{config.subFolder}_latest.json");
+
+ if (!File.Exists(filePath))
+ {
+ Logging.Warning($"[PhotoManager] Latest decoration metadata not found: {filePath}");
+ return null;
+ }
+
+ string json = File.ReadAllText(filePath);
+ T metadata = JsonUtility.FromJson(json);
+
+ Logging.Debug($"[PhotoManager] Latest decoration metadata loaded: {filePath}");
+ return metadata;
+ }
+ catch (Exception e)
+ {
+ Logging.Error($"[PhotoManager] Failed to load latest decoration metadata: {e.Message}");
+ return null;
+ }
+ }
+
+ #endregion
+
+ #region Internal Helpers
+
+ private static string GetPhotoFilePath(CaptureType captureType, string photoId)
+ {
+ return Path.Combine(GetCaptureDirectory(captureType), $"{photoId}.png");
+ }
+
+ private static void SaveMetadata(CaptureType captureType, PhotoMetadata metadata)
+ {
+ CaptureConfig config = PhotoCaptureConfigs.GetConfig(captureType);
+ string json = JsonUtility.ToJson(metadata);
+ PlayerPrefs.SetString(config.metadataPrefix + metadata.photoId, json);
+ PlayerPrefs.Save();
+ }
+
+ private static PhotoMetadata LoadMetadata(CaptureType captureType, string photoId)
+ {
+ CaptureConfig config = PhotoCaptureConfigs.GetConfig(captureType);
+ string json = PlayerPrefs.GetString(config.metadataPrefix + photoId, null);
+ return string.IsNullOrEmpty(json) ? null : JsonUtility.FromJson(json);
+ }
+
+ private static void DeleteMetadata(CaptureType captureType, string photoId)
+ {
+ CaptureConfig config = PhotoCaptureConfigs.GetConfig(captureType);
+ PlayerPrefs.DeleteKey(config.metadataPrefix + photoId);
+ PlayerPrefs.Save();
+ }
+
+ private static void AddToPhotoIndex(CaptureType captureType, string photoId)
+ {
+ List photoIds = GetAllPhotoIds(captureType);
+ if (!photoIds.Contains(photoId))
+ {
+ photoIds.Add(photoId);
+ SavePhotoIndex(captureType, photoIds);
+ }
+ }
+
+ private static void RemoveFromPhotoIndex(CaptureType captureType, string photoId)
+ {
+ List photoIds = GetAllPhotoIds(captureType);
+ if (photoIds.Remove(photoId))
+ {
+ SavePhotoIndex(captureType, photoIds);
+ }
+ }
+
+ private static void SavePhotoIndex(CaptureType captureType, List photoIds)
+ {
+ CaptureConfig config = PhotoCaptureConfigs.GetConfig(captureType);
+ string json = JsonUtility.ToJson(new PhotoIdList { ids = photoIds });
+ PlayerPrefs.SetString(config.indexKey, json);
+ PlayerPrefs.Save();
+ }
+
+ private static string WrapJsonArray(string json)
+ {
+ if (json.StartsWith("[")) return "{\"ids\":" + json + "}";
+ return json;
+ }
+
+ [Serializable]
+ private class PhotoIdList
+ {
+ public List ids = new List();
+ }
+
+ #endregion
+ }
+}
+
diff --git a/Assets/Scripts/Utils/PhotoManager.cs.meta b/Assets/Scripts/Utils/PhotoManager.cs.meta
new file mode 100644
index 00000000..59ac866d
--- /dev/null
+++ b/Assets/Scripts/Utils/PhotoManager.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: c558069d1a8e46febc1c3716e9b76490
+timeCreated: 1764159714
\ No newline at end of file
diff --git a/Assets/Settings/Developer/DebugSettings.asset b/Assets/Settings/Developer/DebugSettings.asset
index 0779a2cf..0fa6f0dd 100644
--- a/Assets/Settings/Developer/DebugSettings.asset
+++ b/Assets/Settings/Developer/DebugSettings.asset
@@ -16,7 +16,7 @@ MonoBehaviour:
pauseTimeOnPauseGame: 0
useSaveLoadSystem: 1
autoClearSaves: 0
- dontSaveOnQuit: 1
+ dontSaveOnQuit: 0
bootstrapLogVerbosity: 0
settingsLogVerbosity: 0
gameManagerLogVerbosity: 0
diff --git a/docs/statue_photo_gallery_setup.md b/docs/statue_photo_gallery_setup.md
new file mode 100644
index 00000000..95791837
--- /dev/null
+++ b/docs/statue_photo_gallery_setup.md
@@ -0,0 +1,164 @@
+# Photo Gallery Scene Setup Guide
+
+## Current Scene Status
+✅ MainCanvas exists
+✅ StatueDecorationController exists
+✅ PhotoCaptureTestController exists (testing only)
+
+---
+
+## Required Scene Setup
+
+### 1. **Create UIPage Wrappers**
+
+#### PlayAreaPage
+1. Create empty GameObject under `MainCanvas` → name: `PlayAreaPage`
+2. Add component: `PlayAreaPage.cs`
+3. Move **existing decoration UI** as children under PlayAreaPage:
+ - Decoration menu
+ - Take photo button
+ - Any other play area UI
+
+#### PhotoGalleryPage
+1. Create empty GameObject under `MainCanvas` → name: `PhotoGalleryPage`
+2. Add component: `PhotoGalleryPage.cs`
+3. Set initially inactive (will be shown when opened)
+
+---
+
+### 2. **Setup Photo Gallery UI** (under PhotoGalleryPage)
+
+```
+PhotoGalleryPage
+├── GalleryController (GameObject)
+│ └── StatuePhotoGalleryController.cs
+├── GridContainer (GameObject with GridLayoutGroup)
+├── EnlargedContainer (GameObject - top layer)
+├── Backdrop (UI Image - dark/black, alpha 0.8)
+├── PageStatusText (UI Text - shows "Page X/Y")
+└── Navigation
+ ├── PreviousPageButton (UI Button - "< Prev")
+ └── NextPageButton (UI Button - "Next >")
+```
+
+**Components to assign on StatuePhotoGalleryController:**
+- `gridContainer` → GridContainer transform
+- `gridItemPrefab` → Create prefab with PhotoGridItem.cs + UI Image
+- `enlargedContainer` → EnlargedContainer transform
+- `backdrop` → Backdrop GameObject
+- `enlargedPreviewPrefab` → Same as gridItemPrefab (or leave null to clone item)
+- `previousPageButton` → Previous page button
+- `nextPageButton` → Next page button
+- `pageStatusText` → Optional status text showing page info
+
+**GridLayoutGroup Settings (on GridContainer):**
+- Cell Size: e.g., 200x200
+- Spacing: e.g., 10x10
+- Constraint: Fixed Column Count (3-4 columns recommended)
+- Child Alignment: Upper Left (or as preferred)
+
+---
+
+### 3. **Create PhotoGridItem Prefab**
+
+1. Create UI → Image in scene
+2. Add `PhotoGridItem.cs` component
+3. Assign `thumbnailImage` → the Image component itself
+4. Optional: Add loading indicator child (simple spinner/text)
+5. Drag to Prefabs folder → name: `PhotoGridItem`
+6. Delete from scene
+
+---
+
+### 4. **Update StatueDecorationController**
+
+**Assign in Inspector:**
+- `playAreaPage` → PlayAreaPage GameObject
+- `photoGalleryPage` → PhotoGalleryPage GameObject
+- `openGalleryButton` → Create button in PlayAreaPage UI, assign here
+- `photoArea` → RectTransform defining capture area (statue + decorations)
+- `takePhotoButton` → Existing button (uncomment line 97 in code when ready)
+
+---
+
+### 5. **Create Gallery Open Button**
+
+1. Add Button in PlayAreaPage UI → name: "OpenGalleryButton"
+2. Button Text: "📷 Gallery" or "View Photos"
+3. Assign to StatueDecorationController's `openGalleryButton` field
+
+---
+
+### 6. **Page Navigation** (PhotoGalleryPage)
+
+1. Create two buttons for Previous/Next page
+2. Buttons will be auto-wired by StatuePhotoGalleryController
+3. Controller auto-disables buttons when at first/last page
+4. Grid clears and reloads on each page change
+
+---
+
+## Key Features
+
+### ✅ Button-Based Pagination
+- Previous/Next buttons navigate pages
+- Grid **clears completely** and shows only current page
+- Buttons auto-disable at boundaries (first/last page)
+- Status text shows "Page X/Y (total photos)"
+
+### ✅ Grid Clearing
+- Grid is cleared on initialization
+- Grid clears when switching pages
+- Prevents leftover items from scene setup
+
+### ✅ Enlarge System
+- Click photo → spawns preview clone, animates to center
+- Click again → shrinks back, destroys preview
+- Original grid items never move
+- Backdrop blocks grid interaction
+
+---
+
+## Testing Checklist
+
+### Photo Capture (Already Working)
+- ✅ PhotoCaptureTestController captures and saves photos
+- ✅ Photos saved to `Application.persistentDataPath/StatuePhotos/`
+
+### Gallery Integration (New Setup)
+1. Play scene
+2. Click "Open Gallery" button → Gallery page shows
+3. First page of photos loads in grid
+4. Click "Next" → Grid clears, next page loads
+5. Click "Previous" → Grid clears, previous page loads
+6. Click photo → Enlarges to center with backdrop
+7. Click enlarged photo → Shrinks back to grid
+8. Back button → Returns to play area
+
+---
+
+## Quick Setup Time
+- **PlayAreaPage wrapper:** 2 minutes
+- **PhotoGalleryPage structure:** 5 minutes
+- **PhotoGridItem prefab:** 3 minutes
+- **Wire references:** 5 minutes
+
+**Total: ~15 minutes**
+
+---
+
+## Configuration Variables
+Set these on `StatuePhotoGalleryController`:
+- `itemsPerPage`: 20 (photos per page)
+- `thumbnailSize`: 256 (pixels)
+- `maxCachedThumbnails`: 50 (LRU cache)
+- `enlargedScale`: 2.5 (zoom amount)
+- `animationDuration`: 0.3s
+
+---
+
+## Cleanup (Optional)
+Once gallery works, you can:
+- Remove `PhotoCaptureTestController` GameObject
+- Keep for quick testing if preferred
+