From b90ab4b0bae8e669ad2044ef72e1a933b14138f6 Mon Sep 17 00:00:00 2001 From: Michal Pikulski Date: Mon, 24 Nov 2025 15:54:03 +0100 Subject: [PATCH] FInalize first pass over cement decoration game --- .../AEblerup_Map_Statue.png.meta | 34 ++- .../StatueDressup/TestDecorationData 1.asset | 3 +- .../StatueDressup/TestDecorationData 2.asset | 3 +- .../StatueDressup/TestDecorationData 3.asset | 3 +- .../StatueDressup/TestDecorationData 4.asset | 3 +- .../StatueDressup/TestDecorationData 5.asset | 3 +- .../StatueDressup/TestDecorationData 6.asset | 3 +- .../StatueDressup/TestDecorationData 7.asset | 3 +- .../StatueDressup/TestDecorationData 8.asset | 3 +- .../StatueDressup/TestDecorationData 9.asset | 3 +- .../StatueDressup/TestDecorationData.asset | 3 +- .../External/Placeholders/statue_outline.png | Bin 0 -> 4456 bytes .../Placeholders/statue_outline.png.meta | 195 ++++++++++++ ...fab => DecorationDraggableInstance.prefab} | 39 +-- ...> DecorationDraggableInstance.prefab.meta} | 0 .../StatueDressup/DecorationGridIcon.prefab | 105 +++++++ .../DecorationGridIcon.prefab.meta | 7 + .../Scenes/MiniGames/StatueDecoration.unity | 114 +++++-- .../Core/Settings/SettingsInterfaces.cs | 1 - .../Core/Settings/StatueDressupSettings.cs | 6 - .../Controllers/DecorationMenuController.cs | 208 +++++++------ .../Controllers/StatueDecorationController.cs | 9 +- .../StatueDressup/Data/DecorationData.cs | 4 - .../DragDrop/DecorationDraggableInstance.cs | 242 +++++++++++++++ .../DecorationDraggableInstance.cs.meta | 3 + .../DragDrop/DecorationGridIcon.cs | 100 ++++++ .../DragDrop/DecorationGridIcon.cs.meta | 3 + .../StatueDressup/DragDrop/DecorationItem.cs | 288 ------------------ .../DragDrop/DecorationItem.cs.meta | 3 - .../DragDrop/StatueDecorationSlot.cs | 110 ------- .../DragDrop/StatueDecorationSlot.cs.meta | 3 - .../Utils/TweenAnimationUtility.cs | 20 ++ 32 files changed, 954 insertions(+), 570 deletions(-) create mode 100644 Assets/External/Placeholders/statue_outline.png create mode 100644 Assets/External/Placeholders/statue_outline.png.meta rename Assets/Prefabs/Minigames/StatueDressup/{DecorationItem.prefab => DecorationDraggableInstance.prefab} (88%) rename Assets/Prefabs/Minigames/StatueDressup/{DecorationItem.prefab.meta => DecorationDraggableInstance.prefab.meta} (100%) create mode 100644 Assets/Prefabs/Minigames/StatueDressup/DecorationGridIcon.prefab create mode 100644 Assets/Prefabs/Minigames/StatueDressup/DecorationGridIcon.prefab.meta create mode 100644 Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationDraggableInstance.cs create mode 100644 Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationDraggableInstance.cs.meta create mode 100644 Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationGridIcon.cs create mode 100644 Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationGridIcon.cs.meta delete mode 100644 Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationItem.cs delete mode 100644 Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationItem.cs.meta delete mode 100644 Assets/Scripts/Minigames/StatueDressup/DragDrop/StatueDecorationSlot.cs delete mode 100644 Assets/Scripts/Minigames/StatueDressup/DragDrop/StatueDecorationSlot.cs.meta diff --git a/Assets/Art/Sprites/OverworldBuildings/AEblerup_Map_Statue.png.meta b/Assets/Art/Sprites/OverworldBuildings/AEblerup_Map_Statue.png.meta index 041175fc..f673f5f7 100644 --- a/Assets/Art/Sprites/OverworldBuildings/AEblerup_Map_Statue.png.meta +++ b/Assets/Art/Sprites/OverworldBuildings/AEblerup_Map_Statue.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,10 +155,10 @@ TextureImporter: name: AEblerup_Map_Statue_0 rect: serializedVersion: 2 - x: 59 - y: 48 - width: 405 - height: 567 + x: 0 + y: 0 + width: 555 + height: 676 alignment: 9 pivot: {x: 0.5, y: 0.25} border: {x: 0, y: 0, z: 0, w: 0} diff --git a/Assets/Data/Minigames/StatueDressup/TestDecorationData 1.asset b/Assets/Data/Minigames/StatueDressup/TestDecorationData 1.asset index c7f3fe8a..61d245ae 100644 --- a/Assets/Data/Minigames/StatueDressup/TestDecorationData 1.asset +++ b/Assets/Data/Minigames/StatueDressup/TestDecorationData 1.asset @@ -15,6 +15,5 @@ MonoBehaviour: decorationId: Shoe decorationName: Shoe decorationSprite: {fileID: -792204027, guid: f1b529408513adc409a57c9ba7131823, type: 3} - authoredSize: {x: 512, y: 512} - iconSize: {x: 256, y: 256} + authoredSize: {x: 300, y: 300} isUnlocked: 1 diff --git a/Assets/Data/Minigames/StatueDressup/TestDecorationData 2.asset b/Assets/Data/Minigames/StatueDressup/TestDecorationData 2.asset index 08c22658..e6c86cf0 100644 --- a/Assets/Data/Minigames/StatueDressup/TestDecorationData 2.asset +++ b/Assets/Data/Minigames/StatueDressup/TestDecorationData 2.asset @@ -15,6 +15,5 @@ MonoBehaviour: decorationId: axe decorationName: axe decorationSprite: {fileID: 6674386295937086461, guid: 3bd1c178a78fcd144965cd1731dc309b, type: 3} - authoredSize: {x: 512, y: 512} - iconSize: {x: 256, y: 256} + authoredSize: {x: 300, y: 300} isUnlocked: 1 diff --git a/Assets/Data/Minigames/StatueDressup/TestDecorationData 3.asset b/Assets/Data/Minigames/StatueDressup/TestDecorationData 3.asset index 67bf4561..4297c1d6 100644 --- a/Assets/Data/Minigames/StatueDressup/TestDecorationData 3.asset +++ b/Assets/Data/Minigames/StatueDressup/TestDecorationData 3.asset @@ -15,6 +15,5 @@ MonoBehaviour: decorationId: can decorationName: can decorationSprite: {fileID: 792078976, guid: f1b529408513adc409a57c9ba7131823, type: 3} - authoredSize: {x: 512, y: 512} - iconSize: {x: 256, y: 256} + authoredSize: {x: 300, y: 300} isUnlocked: 1 diff --git a/Assets/Data/Minigames/StatueDressup/TestDecorationData 4.asset b/Assets/Data/Minigames/StatueDressup/TestDecorationData 4.asset index 34922fd3..614d5d8f 100644 --- a/Assets/Data/Minigames/StatueDressup/TestDecorationData 4.asset +++ b/Assets/Data/Minigames/StatueDressup/TestDecorationData 4.asset @@ -15,6 +15,5 @@ MonoBehaviour: decorationId: i_feel_the_magic_between_you_and_i decorationName: I feel the magic between you and I decorationSprite: {fileID: 1623587888, guid: 1630961e1f25e4243ad74e4e3b0c7e54, type: 3} - authoredSize: {x: 512, y: 512} - iconSize: {x: 256, y: 256} + authoredSize: {x: 300, y: 300} isUnlocked: 1 diff --git a/Assets/Data/Minigames/StatueDressup/TestDecorationData 5.asset b/Assets/Data/Minigames/StatueDressup/TestDecorationData 5.asset index 6c1d6121..94caddf2 100644 --- a/Assets/Data/Minigames/StatueDressup/TestDecorationData 5.asset +++ b/Assets/Data/Minigames/StatueDressup/TestDecorationData 5.asset @@ -15,6 +15,5 @@ MonoBehaviour: decorationId: the_people's_sticker decorationName: the people's sticker decorationSprite: {fileID: 3452003437791708593, guid: 4c13556eeb918624c9dd3d7e4086242e, type: 3} - authoredSize: {x: 512, y: 512} - iconSize: {x: 256, y: 256} + authoredSize: {x: 300, y: 300} isUnlocked: 1 diff --git a/Assets/Data/Minigames/StatueDressup/TestDecorationData 6.asset b/Assets/Data/Minigames/StatueDressup/TestDecorationData 6.asset index 96afc9d8..5983097d 100644 --- a/Assets/Data/Minigames/StatueDressup/TestDecorationData 6.asset +++ b/Assets/Data/Minigames/StatueDressup/TestDecorationData 6.asset @@ -15,6 +15,5 @@ MonoBehaviour: decorationId: cardalbum decorationName: CardAlbum decorationSprite: {fileID: -4354454609415314374, guid: 1ba1f8cf73f79214190f1432fe1e3bc6, type: 3} - authoredSize: {x: 512, y: 512} - iconSize: {x: 256, y: 256} + authoredSize: {x: 300, y: 300} isUnlocked: 1 diff --git a/Assets/Data/Minigames/StatueDressup/TestDecorationData 7.asset b/Assets/Data/Minigames/StatueDressup/TestDecorationData 7.asset index 18f1d1ed..124bf5da 100644 --- a/Assets/Data/Minigames/StatueDressup/TestDecorationData 7.asset +++ b/Assets/Data/Minigames/StatueDressup/TestDecorationData 7.asset @@ -15,6 +15,5 @@ MonoBehaviour: decorationId: chocolate decorationName: chocolate decorationSprite: {fileID: -509776585262497855, guid: c648336c825f7d7479582bbe4d95d0bc, type: 3} - authoredSize: {x: 512, y: 512} - iconSize: {x: 256, y: 256} + authoredSize: {x: 300, y: 300} isUnlocked: 1 diff --git a/Assets/Data/Minigames/StatueDressup/TestDecorationData 8.asset b/Assets/Data/Minigames/StatueDressup/TestDecorationData 8.asset index c467b930..90398526 100644 --- a/Assets/Data/Minigames/StatueDressup/TestDecorationData 8.asset +++ b/Assets/Data/Minigames/StatueDressup/TestDecorationData 8.asset @@ -15,6 +15,5 @@ MonoBehaviour: decorationId: tennis_ball decorationName: tennis ball decorationSprite: {fileID: -8897872742393391051, guid: 44a64b7a80921694790236bab7765357, type: 3} - authoredSize: {x: 512, y: 512} - iconSize: {x: 256, y: 256} + authoredSize: {x: 300, y: 300} isUnlocked: 1 diff --git a/Assets/Data/Minigames/StatueDressup/TestDecorationData 9.asset b/Assets/Data/Minigames/StatueDressup/TestDecorationData 9.asset index fdab1f82..7333058a 100644 --- a/Assets/Data/Minigames/StatueDressup/TestDecorationData 9.asset +++ b/Assets/Data/Minigames/StatueDressup/TestDecorationData 9.asset @@ -15,6 +15,5 @@ MonoBehaviour: decorationId: bird_poop decorationName: bird poop decorationSprite: {fileID: 6130942287420046110, guid: 9ef635f111f888a4386a7f0290117264, type: 3} - authoredSize: {x: 512, y: 512} - iconSize: {x: 256, y: 256} + authoredSize: {x: 300, y: 300} isUnlocked: 1 diff --git a/Assets/Data/Minigames/StatueDressup/TestDecorationData.asset b/Assets/Data/Minigames/StatueDressup/TestDecorationData.asset index feb3c7b2..95d89ca9 100644 --- a/Assets/Data/Minigames/StatueDressup/TestDecorationData.asset +++ b/Assets/Data/Minigames/StatueDressup/TestDecorationData.asset @@ -15,6 +15,5 @@ MonoBehaviour: decorationId: backpack decorationName: backpack decorationSprite: {fileID: -6415490079858998490, guid: b9d1a045f7c163a4d9e2d38071913885, type: 3} - authoredSize: {x: 512, y: 512} - iconSize: {x: 256, y: 256} + authoredSize: {x: 300, y: 300} isUnlocked: 1 diff --git a/Assets/External/Placeholders/statue_outline.png b/Assets/External/Placeholders/statue_outline.png new file mode 100644 index 0000000000000000000000000000000000000000..1c418172f0457a4bac2bb3831175d74056b109e0 GIT binary patch literal 4456 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 defaultIconSize; public Vector2 DefaultAuthoredSize => defaultAuthoredSize; // IStatueDressupSettings implementation - Decoration Content @@ -120,8 +116,6 @@ namespace Core.Settings base.OnValidate(); // Validate decoration display - defaultIconSize.x = Mathf.Max(16f, defaultIconSize.x); - defaultIconSize.y = Mathf.Max(16f, defaultIconSize.y); defaultAuthoredSize.x = Mathf.Max(32f, defaultAuthoredSize.x); defaultAuthoredSize.y = Mathf.Max(32f, defaultAuthoredSize.y); diff --git a/Assets/Scripts/Minigames/StatueDressup/Controllers/DecorationMenuController.cs b/Assets/Scripts/Minigames/StatueDressup/Controllers/DecorationMenuController.cs index f6c93145..df8285a5 100644 --- a/Assets/Scripts/Minigames/StatueDressup/Controllers/DecorationMenuController.cs +++ b/Assets/Scripts/Minigames/StatueDressup/Controllers/DecorationMenuController.cs @@ -3,7 +3,6 @@ using Core; using Core.Lifecycle; using Minigames.StatueDressup.Data; using Minigames.StatueDressup.DragDrop; -using UI.DragAndDrop.Core; using UnityEngine; using UnityEngine.UI; @@ -15,21 +14,21 @@ namespace Minigames.StatueDressup.Controllers public class DecorationMenuController : ManagedBehaviour { [Header("References")] - [SerializeField] private DecorationItem itemPrefab; + [SerializeField] private DecorationGridIcon iconPrefab; + [SerializeField] private DecorationDraggableInstance draggablePrefab; [SerializeField] private Transform itemsContainer; + [SerializeField] private Transform draggableContainer; // Parent for spawned draggables [SerializeField] private Button nextPageButton; [SerializeField] private Button previousPageButton; - [SerializeField] private RectTransform statueArea; // For overlap detection - [SerializeField] private Transform statueParent; // Parent for placed decorations [SerializeField] private StatueDecorationController statueController; // Controller for registration + [SerializeField] private Image statueOutline; // Outline image shown during drag to indicate valid drop area [Header("Layout")] [SerializeField] private GridLayoutGroup gridLayout; private int _currentPage; private int _totalPages; - private List _spawnedItems = new List(); - private Dictionary _itemDataMapping = new Dictionary(); + private List _spawnedIcons = new List(); private AppleHills.Core.Settings.IStatueDressupSettings _settings; // Properties @@ -65,6 +64,12 @@ namespace Minigames.StatueDressup.Controllers return; } + // Ensure outline starts hidden + if (statueOutline != null) + { + statueOutline.gameObject.SetActive(false); + } + var allDecorations = _settings.AllDecorations; int itemsPerPage = _settings.ItemsPerPage; @@ -101,7 +106,7 @@ namespace Minigames.StatueDressup.Controllers } /// - /// Populate the current page with decoration items + /// Populate the current page with decoration icons /// private void PopulateCurrentPage() { @@ -118,19 +123,19 @@ namespace Minigames.StatueDressup.Controllers Logging.Debug($"[DecorationMenuController] Populating page {_currentPage + 1}/{_totalPages}"); - // Clear existing items - ClearItems(); + // Clear existing icons + ClearIcons(); // Calculate range for current page int startIndex = _currentPage * itemsPerPage; int endIndex = Mathf.Min(startIndex + itemsPerPage, allDecorations.Count); - Logging.Debug($"[DecorationMenuController] Spawning items {startIndex} to {endIndex - 1}"); + Logging.Debug($"[DecorationMenuController] Spawning icons {startIndex} to {endIndex - 1}"); - // Spawn items for this page + // Spawn icons for this page for (int i = startIndex; i < endIndex; i++) { - SpawnDecorationItem(allDecorations[i]); + SpawnGridIcon(allDecorations[i]); } // Update button states @@ -138,99 +143,126 @@ namespace Minigames.StatueDressup.Controllers } /// - /// Spawn a decoration item in the menu + /// Spawn a grid icon in the menu /// - private void SpawnDecorationItem(DecorationData data) + private void SpawnGridIcon(DecorationData data) { - if (itemPrefab == null || itemsContainer == null) + if (iconPrefab == null || itemsContainer == null) { - Logging.Warning("[DecorationMenuController] Missing prefab or container"); + Logging.Warning("[DecorationMenuController] Missing icon prefab or container"); return; } - DecorationItem item = Instantiate(itemPrefab, itemsContainer); - item.SetDecorationData(data); + DecorationGridIcon icon = Instantiate(iconPrefab, itemsContainer); + icon.Initialize(data, this); - // Set statue references for overlap detection - item.SetStatueArea(statueArea); - item.SetStatueParent(statueParent); - item.SetMenuParent(itemsContainer); - item.SetController(statueController); + _spawnedIcons.Add(icon); - // Store original position for return animation - if (item.RectTransform != null) - { - // Force layout update to get correct position - Canvas.ForceUpdateCanvases(); - item.SetOriginalMenuPosition(item.RectTransform.anchoredPosition); - } - - // Subscribe to drag events - item.OnDragStarted += HandleItemPickedUp; - item.OnDragEnded += HandleItemDropped; - - _spawnedItems.Add(item); - _itemDataMapping[item] = data; - - Logging.Debug($"[DecorationMenuController] Spawned: {data.DecorationName} at position {item.RectTransform?.anchoredPosition}"); + Logging.Debug($"[DecorationMenuController] Spawned icon: {data.DecorationName}"); } /// - /// Handle item picked up from menu + /// Factory method: Spawn a draggable instance at cursor position + /// Called by DecorationGridIcon when drag starts /// - private void HandleItemPickedUp(DraggableObject draggable) + public DecorationDraggableInstance SpawnDraggableInstance(DecorationData data, Vector3 screenPosition) { - if (draggable is DecorationItem item && _itemDataMapping.ContainsKey(item)) + if (draggablePrefab == null || statueController == null) { - Logging.Debug($"[DecorationMenuController] Item picked up: {item.Data?.DecorationName}"); + Logging.Warning("[DecorationMenuController] Missing draggable prefab or statue controller"); + return null; + } + + // Show statue outline + ShowStatueOutline(); + + // Determine parent - use draggableContainer if set, otherwise itemsContainer's parent + Transform parent = draggableContainer != null ? draggableContainer : itemsContainer.parent; + + // Spawn draggable instance + DecorationDraggableInstance instance = Instantiate(draggablePrefab, parent); + + // Get outline RectTransform for overlap detection + RectTransform outlineRect = statueOutline != null ? statueOutline.rectTransform : null; + + // Initialize with references + instance.Initialize( + data, + outlineRect, + statueController.StatueParent, + statueController, + _settings, + OnDraggableFinished + ); + + // Position at cursor (in local space) + Canvas canvas = GetComponentInParent(); + if (canvas != null) + { + RectTransformUtility.ScreenPointToLocalPointInRectangle( + canvas.transform as RectTransform, + screenPosition, + canvas.worldCamera, + out Vector2 localPoint); - // We'll spawn replacement only if item is actually placed, not on pickup - } - } - - /// - /// Handle item dropped (either placed on statue or returned to menu) - /// - private void HandleItemDropped(DraggableObject draggable) - { - if (draggable is DecorationItem item && _itemDataMapping.ContainsKey(item)) - { - Logging.Debug($"[DecorationMenuController] Item dropped: {item.Data?.DecorationName}, isPlacedOnStatue={item.IsPlacedOnStatue}"); - - // If item was placed on statue, spawn replacement in menu - if (item.IsPlacedOnStatue && !item.IsInMenu) + RectTransform instanceRect = instance.GetComponent(); + if (instanceRect != null) { - DecorationData data = _itemDataMapping[item]; - - // Remove original from tracking - _spawnedItems.Remove(item); - _itemDataMapping.Remove(item); - - // Spawn replacement - SpawnDecorationItem(data); - - Logging.Debug($"[DecorationMenuController] Spawned replacement for: {data.DecorationName}"); - } - } - } - - /// - /// Clear all spawned items - /// - private void ClearItems() - { - foreach (var item in _spawnedItems) - { - if (item != null) - { - item.OnDragStarted -= HandleItemPickedUp; - item.OnDragEnded -= HandleItemDropped; - Destroy(item.gameObject); + instanceRect.localPosition = localPoint; } } - _spawnedItems.Clear(); - _itemDataMapping.Clear(); + Logging.Debug($"[DecorationMenuController] Spawned draggable instance: {data.DecorationName}"); + + return instance; + } + + /// + /// Show the statue outline to indicate valid drop area + /// + private void ShowStatueOutline() + { + if (statueOutline != null) + { + statueOutline.gameObject.SetActive(true); + Logging.Debug("[DecorationMenuController] Statue outline shown"); + } + } + + /// + /// Hide the statue outline after drag ends + /// + private void HideStatueOutline() + { + if (statueOutline != null) + { + statueOutline.gameObject.SetActive(false); + Logging.Debug("[DecorationMenuController] Statue outline hidden"); + } + } + + /// + /// Callback from DecorationDraggableInstance when drag finishes + /// + private void OnDraggableFinished() + { + HideStatueOutline(); + } + + /// + /// Clear all spawned icons + /// + private void ClearIcons() + { + foreach (var icon in _spawnedIcons) + { + if (icon != null) + { + Destroy(icon.gameObject); + } + } + + _spawnedIcons.Clear(); } /// @@ -293,8 +325,8 @@ namespace Minigames.StatueDressup.Controllers previousPageButton.onClick.RemoveListener(OnPreviousPage); } - // Cleanup item listeners - ClearItems(); + // Cleanup icons + ClearIcons(); } } } diff --git a/Assets/Scripts/Minigames/StatueDressup/Controllers/StatueDecorationController.cs b/Assets/Scripts/Minigames/StatueDressup/Controllers/StatueDecorationController.cs index 0dc588d0..abd31db8 100644 --- a/Assets/Scripts/Minigames/StatueDressup/Controllers/StatueDecorationController.cs +++ b/Assets/Scripts/Minigames/StatueDressup/Controllers/StatueDecorationController.cs @@ -27,10 +27,13 @@ namespace Minigames.StatueDressup.Controllers [SerializeField] private RectTransform photoArea; // Area to capture [SerializeField] private string photoSaveKey = "MrCementStatuePhoto"; - private List _placedDecorations = new List(); + private List _placedDecorations = new List(); private bool _minigameCompleted; private AppleHills.Core.Settings.IStatueDressupSettings _settings; + // Public property for menu controller + public Transform StatueParent => statueParent; + /// /// Early initialization - get settings reference /// @@ -72,7 +75,7 @@ namespace Minigames.StatueDressup.Controllers /// /// Register a decoration as placed on statue /// - public void RegisterDecoration(DecorationItem decoration) + public void RegisterDecoration(DecorationDraggableInstance decoration) { if (decoration != null && !_placedDecorations.Contains(decoration)) { @@ -87,7 +90,7 @@ namespace Minigames.StatueDressup.Controllers /// /// Unregister a decoration (when removed) /// - public void UnregisterDecoration(DecorationItem decoration) + public void UnregisterDecoration(DecorationDraggableInstance decoration) { if (decoration != null && _placedDecorations.Contains(decoration)) { diff --git a/Assets/Scripts/Minigames/StatueDressup/Data/DecorationData.cs b/Assets/Scripts/Minigames/StatueDressup/Data/DecorationData.cs index d484106a..1177cffc 100644 --- a/Assets/Scripts/Minigames/StatueDressup/Data/DecorationData.cs +++ b/Assets/Scripts/Minigames/StatueDressup/Data/DecorationData.cs @@ -19,9 +19,6 @@ namespace Minigames.StatueDressup.Data [Tooltip("Full size when placed on statue (actual sprite size)")] [SerializeField] private Vector2 authoredSize = new Vector2(128f, 128f); - [Tooltip("Small size in menu icon")] - [SerializeField] private Vector2 iconSize = new Vector2(64f, 64f); - [Header("Progression (Optional)")] [SerializeField] private bool isUnlocked = true; @@ -30,7 +27,6 @@ namespace Minigames.StatueDressup.Data public string DecorationName => decorationName; public Sprite DecorationSprite => decorationSprite; public Vector2 AuthoredSize => authoredSize; - public Vector2 IconSize => iconSize; public bool IsUnlocked => isUnlocked; private void OnValidate() diff --git a/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationDraggableInstance.cs b/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationDraggableInstance.cs new file mode 100644 index 00000000..e4f2f0fb --- /dev/null +++ b/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationDraggableInstance.cs @@ -0,0 +1,242 @@ +using Core; +using Minigames.StatueDressup.Controllers; +using Minigames.StatueDressup.Data; +using Minigames.StatueDressup.Utils; +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.UI; + +namespace Minigames.StatueDressup.DragDrop +{ + /// + /// Draggable instance of a decoration that can be placed on the statue. + /// Created dynamically when dragging from menu or picking up from statue. + /// Destroyed if dropped outside statue area. + /// + public class DecorationDraggableInstance : MonoBehaviour + { + [Header("References")] + [SerializeField] private Image decorationImage; + [SerializeField] private CanvasGroup canvasGroup; + + private DecorationData _decorationData; + private RectTransform _rectTransform; + private Canvas _canvas; + private RectTransform _statueOutline; + private Transform _statueParent; + private StatueDecorationController _controller; + private AppleHills.Core.Settings.IStatueDressupSettings _settings; + private System.Action _onFinishedCallback; + + private bool _isDragging; + private bool _isPlacedOnStatue; + private Vector3 _dragOffset; + + // Properties + public DecorationData Data => _decorationData; + public bool IsPlacedOnStatue => _isPlacedOnStatue; + + private void Awake() + { + _rectTransform = GetComponent(); + _canvas = GetComponentInParent(); + + if (canvasGroup == null) + { + canvasGroup = gameObject.AddComponent(); + } + } + + /// + /// Initialize the draggable instance + /// + public void Initialize(DecorationData data, RectTransform statueOutline, Transform statueParent, + StatueDecorationController controller, AppleHills.Core.Settings.IStatueDressupSettings settings, + System.Action onFinishedCallback) + { + _decorationData = data; + _statueOutline = statueOutline; + _statueParent = statueParent; + _controller = controller; + _settings = settings; + _onFinishedCallback = onFinishedCallback; + + // 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; + } + + Logging.Debug($"[DecorationDraggableInstance] Initialized: {data?.DecorationName}"); + } + + /// + /// Start dragging from icon + /// + public void StartDragFromIcon(PointerEventData eventData) + { + _isDragging = true; + + // Calculate offset from cursor to object center + RectTransformUtility.ScreenPointToLocalPointInRectangle( + _canvas.transform as RectTransform, + eventData.position, + eventData.pressEventCamera, + out Vector2 localPoint); + + _dragOffset = _rectTransform.localPosition - (Vector3)localPoint; + + Logging.Debug($"[DecorationDraggableInstance] Started drag from icon: {_decorationData?.DecorationName}"); + } + + /// + /// Continue dragging + /// + public void ContinueDrag(PointerEventData eventData) + { + if (!_isDragging) return; + + // Update position to follow cursor + RectTransformUtility.ScreenPointToLocalPointInRectangle( + _canvas.transform as RectTransform, + eventData.position, + eventData.pressEventCamera, + out Vector2 localPoint); + + _rectTransform.localPosition = localPoint + (Vector2)_dragOffset; + } + + /// + /// End drag - check placement + /// + public void EndDrag(PointerEventData eventData) + { + _isDragging = false; + + Logging.Debug($"[DecorationDraggableInstance] Drag ended: {_decorationData?.DecorationName}"); + + // Check if overlapping with statue + if (IsOverlappingStatue()) + { + PlaceOnStatue(); + } + else + { + PlayPopOutAndDestroy(); + } + } + + /// + /// Check if item overlaps with statue outline + /// + private bool IsOverlappingStatue() + { + if (_statueOutline == null || _rectTransform == null) + { + Logging.Warning($"[DecorationDraggableInstance] Cannot check overlap - statueOutline or RectTransform is null"); + return false; + } + + // Get bounds of this item in world space + Rect itemRect = GetWorldRect(_rectTransform); + Rect outlineRect = GetWorldRect(_statueOutline); + + // Check for any overlap + bool overlaps = itemRect.Overlaps(outlineRect); + + Logging.Debug($"[DecorationDraggableInstance] Overlap check: {_decorationData?.DecorationName}, overlaps={overlaps}"); + + return overlaps; + } + + /// + /// Get world space rect for a RectTransform + /// + private Rect GetWorldRect(RectTransform rectTransform) + { + Vector3[] corners = new Vector3[4]; + rectTransform.GetWorldCorners(corners); + + Vector3 bottomLeft = corners[0]; + Vector3 topRight = corners[2]; + + return new Rect(bottomLeft.x, bottomLeft.y, topRight.x - bottomLeft.x, topRight.y - bottomLeft.y); + } + + /// + /// Place item on statue at current position + /// + private void PlaceOnStatue() + { + Logging.Debug($"[DecorationDraggableInstance] Placing on statue: {_decorationData?.DecorationName}"); + + _isPlacedOnStatue = true; + + // Move to statue parent if specified + if (_statueParent != null && transform.parent != _statueParent) + { + transform.SetParent(_statueParent, true); // Keep world position + } + + // Register with controller + if (_controller != null) + { + _controller.RegisterDecoration(this); + } + + // Notify menu controller to hide outline + _onFinishedCallback?.Invoke(); + } + + /// + /// Play pop-out animation and destroy + /// + private void PlayPopOutAndDestroy() + { + Logging.Debug($"[DecorationDraggableInstance] Pop-out and destroy: {_decorationData?.DecorationName}"); + + // Notify menu controller to hide outline immediately + _onFinishedCallback?.Invoke(); + + float duration = _settings?.PlacementAnimationDuration ?? 0.3f; + + // Play pop-out with fade animation + TweenAnimationUtility.PopOutWithFade(transform, canvasGroup, duration, () => + { + Destroy(gameObject); + }); + } + + /// + /// Allow picking up from statue for repositioning + /// + public void StartDragFromStatue(Vector3 pointerPosition) + { + if (_controller != null) + { + _controller.UnregisterDecoration(this); + } + + _isPlacedOnStatue = false; + _isDragging = true; + + // Calculate offset + RectTransformUtility.ScreenPointToLocalPointInRectangle( + _canvas.transform as RectTransform, + pointerPosition, + null, + out Vector2 localPoint); + + _dragOffset = _rectTransform.localPosition - (Vector3)localPoint; + + Logging.Debug($"[DecorationDraggableInstance] Started drag from statue: {_decorationData?.DecorationName}"); + } + } +} + diff --git a/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationDraggableInstance.cs.meta b/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationDraggableInstance.cs.meta new file mode 100644 index 00000000..ab89e5a6 --- /dev/null +++ b/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationDraggableInstance.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e4659fd035c74a79af0311de9e17f44a +timeCreated: 1763991638 \ No newline at end of file diff --git a/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationGridIcon.cs b/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationGridIcon.cs new file mode 100644 index 00000000..d26874f4 --- /dev/null +++ b/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationGridIcon.cs @@ -0,0 +1,100 @@ +using Core; +using Minigames.StatueDressup.Data; +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.UI; + +namespace Minigames.StatueDressup.DragDrop +{ + /// + /// Static grid icon for decorations in the menu. + /// Handles tap and drag initiation, but doesn't move itself. + /// Spawns a draggable instance when drag starts. + /// + public class DecorationGridIcon : MonoBehaviour, IPointerClickHandler, IBeginDragHandler, IDragHandler, IEndDragHandler + { + [Header("References")] + [SerializeField] private Image iconImage; + [SerializeField] private DecorationData decorationData; + + private Controllers.DecorationMenuController _menuController; + private DecorationDraggableInstance _activeDraggableInstance; + + // Properties + public DecorationData Data => decorationData; + + /// + /// Initialize the icon with decoration data + /// + public void Initialize(DecorationData data, Controllers.DecorationMenuController controller) + { + decorationData = data; + _menuController = controller; + + if (iconImage != null && data != null && data.DecorationSprite != null) + { + iconImage.sprite = data.DecorationSprite; + } + } + + /// + /// Handle tap/click on icon + /// + public void OnPointerClick(PointerEventData eventData) + { + // Only process clicks if we're not dragging + if (_activeDraggableInstance == null) + { + Logging.Debug($"[DecorationGridIcon] Item tapped: {decorationData?.DecorationName}"); + // Future: Open detail view, preview, etc. + } + } + + /// + /// Handle drag start - spawn draggable instance + /// + public void OnBeginDrag(PointerEventData eventData) + { + if (_menuController == null || decorationData == null) + { + Logging.Warning("[DecorationGridIcon] Cannot start drag - missing controller or data"); + return; + } + + Logging.Debug($"[DecorationGridIcon] Starting drag for: {decorationData.DecorationName}"); + + // Spawn draggable instance at cursor position + _activeDraggableInstance = _menuController.SpawnDraggableInstance(decorationData, eventData.position); + + // Start the drag on the spawned instance + if (_activeDraggableInstance != null) + { + _activeDraggableInstance.StartDragFromIcon(eventData); + } + } + + /// + /// Forward drag events to the active draggable instance + /// + public void OnDrag(PointerEventData eventData) + { + if (_activeDraggableInstance != null) + { + _activeDraggableInstance.ContinueDrag(eventData); + } + } + + /// + /// Forward drag end to the active draggable instance + /// + public void OnEndDrag(PointerEventData eventData) + { + if (_activeDraggableInstance != null) + { + _activeDraggableInstance.EndDrag(eventData); + _activeDraggableInstance = null; + } + } + } +} + diff --git a/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationGridIcon.cs.meta b/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationGridIcon.cs.meta new file mode 100644 index 00000000..6a273f13 --- /dev/null +++ b/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationGridIcon.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9c806d80a321498c9f33f13d7a31065c +timeCreated: 1763991611 \ No newline at end of file diff --git a/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationItem.cs b/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationItem.cs deleted file mode 100644 index 5dbb5fa6..00000000 --- a/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationItem.cs +++ /dev/null @@ -1,288 +0,0 @@ -using Core; -using Minigames.StatueDressup.Controllers; -using Minigames.StatueDressup.Data; -using Minigames.StatueDressup.Utils; -using UI.DragAndDrop.Core; -using UnityEngine; -using UnityEngine.UI; - -namespace Minigames.StatueDressup.DragDrop -{ - /// - /// Individual decoration item that can be dragged from menu to statue - /// Uses overlap detection instead of slot-based placement - /// - public class DecorationItem : DraggableObject - { - [Header("Decoration Data")] - [SerializeField] private DecorationData decorationData; - [SerializeField] private Image decorationImage; - - [Header("Placement")] - [SerializeField] private RectTransform statueArea; // Reference to statue area for overlap check - - private Vector2 _iconSize; - private Vector2 _authoredSize; - private Vector2 _originalMenuPosition; - private Vector2 _placedPosition; // Position when placed on statue - private bool _isInMenu = true; - private bool _isPlacedOnStatue = false; - private Transform _menuParent; // Original parent in menu - private Transform _statueParent; // Parent when placed on statue - private StatueDecorationController _controller; // Controller for registration - private AppleHills.Core.Settings.IStatueDressupSettings _settings; // Settings reference - - // Properties - public DecorationData Data => decorationData; - public bool IsInMenu => _isInMenu; - public bool IsPlacedOnStatue => _isPlacedOnStatue; - - protected override void Initialize() - { - base.Initialize(); - - // Get settings - _settings = GameManager.GetSettingsObject(); - - // Store menu parent - _menuParent = transform.parent; - - // Find statue parent (will be set by controller) - // statueParent will be assigned externally - - if (decorationData != null) - { - _iconSize = decorationData.IconSize; - _authoredSize = decorationData.AuthoredSize; - - // Set initial icon size - if (RectTransform != null) - { - RectTransform.sizeDelta = _iconSize; - } - - // Set sprite - if (decorationImage != null && decorationData.DecorationSprite != null) - { - decorationImage.sprite = decorationData.DecorationSprite; - } - } - - // Store original menu position - if (RectTransform != null) - { - _originalMenuPosition = RectTransform.anchoredPosition; - } - } - - /// - /// Set decoration data (for spawned instances) - /// - public void SetDecorationData(DecorationData data) - { - decorationData = data; - - if (data != null) - { - _iconSize = data.IconSize; - _authoredSize = data.AuthoredSize; - - // Update visual - if (decorationImage != null && data.DecorationSprite != null) - { - decorationImage.sprite = data.DecorationSprite; - } - - // Set icon size - if (RectTransform != null) - { - RectTransform.sizeDelta = _iconSize; - } - - Logging.Debug($"[DecorationItem] Set data: {data.DecorationName}, iconSize={_iconSize}, authoredSize={_authoredSize}"); - } - } - - /// - /// Set statue area reference for overlap detection - /// - public void SetStatueArea(RectTransform statue) - { - statueArea = statue; - } - - /// - /// Set statue parent for placing items - /// - public void SetStatueParent(Transform parent) - { - _statueParent = parent; - } - - /// - /// Set controller for registration callbacks - /// - public void SetController(StatueDecorationController controller) - { - _controller = controller; - } - - protected override void OnDragStartedHook() - { - Logging.Debug($"[DecorationItem] OnDragStarted: {decorationData?.DecorationName}"); - - // If picking up from statue, allow re-positioning - if (_isPlacedOnStatue) - { - _isPlacedOnStatue = false; - Logging.Debug($"[DecorationItem] Picking up from statue for re-positioning"); - } - - // Scale to authored size when dragging starts - if (RectTransform != null) - { - // Smoothly transition from icon size to authored size - RectTransform.sizeDelta = _authoredSize; - float duration = _settings?.DragScaleTransitionDuration ?? 0.2f; - TweenAnimationUtility.AnimateScale(transform, Vector3.one, duration); - } - } - - protected override void OnDragEndedHook() - { - Logging.Debug($"[DecorationItem] OnDragEnded: {decorationData?.DecorationName}"); - - // Check if overlapping with statue - if (IsOverlappingStatue()) - { - PlaceOnStatue(); - } - else - { - ReturnToMenu(); - } - } - - /// - /// Check if item overlaps with statue area - /// - private bool IsOverlappingStatue() - { - if (statueArea == null || RectTransform == null) - { - Logging.Warning($"[DecorationItem] Cannot check overlap - statueArea or RectTransform is null"); - return false; - } - - // Get bounds of this item in world space - Rect itemRect = GetWorldRect(RectTransform); - Rect statueRect = GetWorldRect(statueArea); - - // Check for any overlap - bool overlaps = itemRect.Overlaps(statueRect); - - Logging.Debug($"[DecorationItem] Overlap check: {decorationData?.DecorationName}, overlaps={overlaps}"); - Logging.Debug($"[DecorationItem] Item rect: {itemRect}, Statue rect: {statueRect}"); - - return overlaps; - } - - /// - /// Get world space rect for a RectTransform - /// - private Rect GetWorldRect(RectTransform rectTransform) - { - Vector3[] corners = new Vector3[4]; - rectTransform.GetWorldCorners(corners); - - Vector3 bottomLeft = corners[0]; - Vector3 topRight = corners[2]; - - return new Rect(bottomLeft.x, bottomLeft.y, topRight.x - bottomLeft.x, topRight.y - bottomLeft.y); - } - - /// - /// Place item on statue at current position - /// - private void PlaceOnStatue() - { - Logging.Debug($"[DecorationItem] Placing on statue: {decorationData?.DecorationName}"); - - _isInMenu = false; - _isPlacedOnStatue = true; - - // Store current position - if (RectTransform != null) - { - _placedPosition = RectTransform.anchoredPosition; - } - - // Move to statue parent if specified - if (_statueParent != null && transform.parent != _statueParent) - { - transform.SetParent(_statueParent, true); // Keep world position - } - - // Register with controller - if (_controller != null) - { - _controller.RegisterDecoration(this); - } - - // Keep authored size - // Position is already set by drag - } - - /// - /// Return item to menu with animation - /// - private void ReturnToMenu() - { - Logging.Debug($"[DecorationItem] Returning to menu: {decorationData?.DecorationName}"); - - // Unregister from controller if was placed on statue - if (_isPlacedOnStatue && _controller != null) - { - _controller.UnregisterDecoration(this); - } - - _isInMenu = true; - _isPlacedOnStatue = false; - - // Return to menu parent - if (_menuParent != null && transform.parent != _menuParent) - { - transform.SetParent(_menuParent, false); // Use local positioning - } - - if (RectTransform != null) - { - // Animate back to icon size - RectTransform.sizeDelta = _iconSize; - float scaleDuration = _settings?.DragScaleTransitionDuration ?? 0.2f; - TweenAnimationUtility.AnimateScale(transform, Vector3.one, scaleDuration); - - // Animate back to original position - float returnDuration = _settings?.ReturnToMenuDuration ?? 0.3f; - TweenAnimationUtility.AnimateAnchoredPosition(RectTransform, _originalMenuPosition, returnDuration); - } - } - - /// - /// Set original menu position (called by menu controller) - /// - public void SetOriginalMenuPosition(Vector2 position) - { - _originalMenuPosition = position; - } - - /// - /// Set menu parent (called by menu controller) - /// - public void SetMenuParent(Transform parent) - { - _menuParent = parent; - } - } -} - diff --git a/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationItem.cs.meta b/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationItem.cs.meta deleted file mode 100644 index 49d3682a..00000000 --- a/Assets/Scripts/Minigames/StatueDressup/DragDrop/DecorationItem.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 31a82dde0ffb439e86b79499b9daa92b -timeCreated: 1763745531 \ No newline at end of file diff --git a/Assets/Scripts/Minigames/StatueDressup/DragDrop/StatueDecorationSlot.cs b/Assets/Scripts/Minigames/StatueDressup/DragDrop/StatueDecorationSlot.cs deleted file mode 100644 index 1d5e70a1..00000000 --- a/Assets/Scripts/Minigames/StatueDressup/DragDrop/StatueDecorationSlot.cs +++ /dev/null @@ -1,110 +0,0 @@ -using Core; -using Minigames.StatueDressup.Data; -using Minigames.StatueDressup.Utils; -using UI.DragAndDrop.Core; -using UnityEngine; -using UnityEngine.EventSystems; - -namespace Minigames.StatueDressup.DragDrop -{ - /// - /// Slot on the statue where decorations can be placed - /// - public class StatueDecorationSlot : DraggableSlot, IPointerEnterHandler, IPointerExitHandler - { - [Header("Slot Configuration")] - [SerializeField] private bool isPermanent = true; // Can't remove once placed - - [Header("Glow Effect")] - [SerializeField] private GameObject glowEffect; - [SerializeField] private float glowPulseAmount = 1.1f; - [SerializeField] private float glowPulseDuration = 0.8f; - - private bool _isGlowing; - private Pixelplacement.TweenSystem.TweenBase _glowTween; - - public bool IsPermanent => isPermanent; - - private void Start() - { - // Hide glow effect initially - if (glowEffect != null) - { - glowEffect.SetActive(false); - } - } - - public new void OnPointerEnter(PointerEventData eventData) - { - // Only glow when dragging a matching decoration - if (eventData.pointerDrag != null) - { - var decoration = eventData.pointerDrag.GetComponent(); - if (decoration != null && !IsOccupied) - { - StartGlow(); - } - } - } - - public new void OnPointerExit(PointerEventData eventData) - { - StopGlow(); - } - - /// - /// Start glow effect - /// - private void StartGlow() - { - if (_isGlowing || glowEffect == null) - return; - - _isGlowing = true; - glowEffect.SetActive(true); - - Logging.Debug($"[StatueDecorationSlot] Starting glow on {name}"); - - // Pulse animation - _glowTween = TweenAnimationUtility.StartGlowPulse(glowEffect.transform, glowPulseAmount, glowPulseDuration); - } - - /// - /// Stop glow effect - /// - private void StopGlow() - { - if (!_isGlowing || glowEffect == null) - return; - - _isGlowing = false; - - Logging.Debug($"[StatueDecorationSlot] Stopping glow on {name}"); - - // Stop pulse animation - if (_glowTween != null) - { - TweenAnimationUtility.StopTweens(glowEffect.transform); - _glowTween = null; - } - - glowEffect.SetActive(false); - } - - /// - /// Override to check category matching (uses base CanAccept) - /// - public new bool CanAccept(DraggableObject draggable) - { - // First check base conditions - return base.CanAccept(draggable); - } - - private void OnDisable() - { - // Clean up glow on disable - StopGlow(); - } - } -} - diff --git a/Assets/Scripts/Minigames/StatueDressup/DragDrop/StatueDecorationSlot.cs.meta b/Assets/Scripts/Minigames/StatueDressup/DragDrop/StatueDecorationSlot.cs.meta deleted file mode 100644 index a9fbb317..00000000 --- a/Assets/Scripts/Minigames/StatueDressup/DragDrop/StatueDecorationSlot.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: f68e3749518141b6bc818938dd8dc57d -timeCreated: 1763745550 \ No newline at end of file diff --git a/Assets/Scripts/Minigames/StatueDressup/Utils/TweenAnimationUtility.cs b/Assets/Scripts/Minigames/StatueDressup/Utils/TweenAnimationUtility.cs index 2326941c..50699db0 100644 --- a/Assets/Scripts/Minigames/StatueDressup/Utils/TweenAnimationUtility.cs +++ b/Assets/Scripts/Minigames/StatueDressup/Utils/TweenAnimationUtility.cs @@ -145,6 +145,26 @@ namespace Minigames.StatueDressup.Utils return Tween.CanvasGroupAlpha(canvasGroup, targetAlpha, duration, 0f, Tween.EaseInOut, completeCallback: onComplete); } + /// + /// Pop-out with fade - scale to 0 and fade out simultaneously + /// + public static void PopOutWithFade(Transform transform, CanvasGroup canvasGroup, float duration, Action onComplete = null) + { + // Scale to 0 + Tween.LocalScale(transform, Vector3.zero, duration, 0f, Tween.EaseInBack); + + // Fade out simultaneously + if (canvasGroup != null) + { + Tween.CanvasGroupAlpha(canvasGroup, 0f, duration, 0f, Tween.EaseInOut, completeCallback: onComplete); + } + else + { + // If no canvas group, just call complete after scale + Tween.LocalScale(transform, Vector3.zero, duration, 0f, Tween.EaseInBack, completeCallback: onComplete); + } + } + #endregion } }