Update the statue game to include rotation etc.
This commit is contained in:
1154
Assets/Prefabs/Minigames/StatueDressup/ScaleUI.prefab
Normal file
1154
Assets/Prefabs/Minigames/StatueDressup/ScaleUI.prefab
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ad71c1dc8542e54494a857fa06095fb
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,10 @@ namespace Minigames.StatueDressup.Controllers
|
||||
[SerializeField] private GameObject statue;
|
||||
[SerializeField] private DecorationDraggableInstance draggablePrefab; // Prefab for spawning decorations
|
||||
|
||||
[Header("Edit UI")]
|
||||
[SerializeField] private UI.DecorationEditUI editUIPrefab; // Prefab for edit UI
|
||||
private UI.DecorationEditUI _editUIInstance;
|
||||
|
||||
[Header("UI Pages")]
|
||||
[SerializeField] private UI.PlayAreaPage playAreaPage;
|
||||
[SerializeField] private UI.PhotoGalleryPage photoGalleryPage;
|
||||
@@ -37,8 +41,8 @@ namespace Minigames.StatueDressup.Controllers
|
||||
[Header("Photo Settings")]
|
||||
[SerializeField] private RectTransform photoArea; // Area to capture
|
||||
|
||||
private List<DecorationDraggableInstance> placedDecorations = new List<DecorationDraggableInstance>();
|
||||
private bool minigameCompleted;
|
||||
private List<DecorationDraggableInstance> _placedDecorations = new List<DecorationDraggableInstance>();
|
||||
private bool _minigameCompleted;
|
||||
|
||||
// Public properties
|
||||
public Transform StatueParent => statueParent;
|
||||
@@ -127,9 +131,9 @@ namespace Minigames.StatueDressup.Controllers
|
||||
/// </summary>
|
||||
public void RegisterDecoration(DecorationDraggableInstance decoration)
|
||||
{
|
||||
if (decoration != null && !placedDecorations.Contains(decoration))
|
||||
if (decoration != null && !_placedDecorations.Contains(decoration))
|
||||
{
|
||||
placedDecorations.Add(decoration);
|
||||
_placedDecorations.Add(decoration);
|
||||
Logging.Debug($"[StatueDecorationController] Decoration placed: {decoration.Data?.DecorationName}");
|
||||
|
||||
// Auto-save state
|
||||
@@ -142,9 +146,9 @@ namespace Minigames.StatueDressup.Controllers
|
||||
/// </summary>
|
||||
public void UnregisterDecoration(DecorationDraggableInstance decoration)
|
||||
{
|
||||
if (decoration != null && placedDecorations.Contains(decoration))
|
||||
if (decoration != null && _placedDecorations.Contains(decoration))
|
||||
{
|
||||
placedDecorations.Remove(decoration);
|
||||
_placedDecorations.Remove(decoration);
|
||||
Logging.Debug($"[StatueDecorationController] Decoration removed: {decoration.Data?.DecorationName}");
|
||||
|
||||
// Auto-save state
|
||||
@@ -157,7 +161,7 @@ namespace Minigames.StatueDressup.Controllers
|
||||
/// </summary>
|
||||
private void OnTakePhoto()
|
||||
{
|
||||
if (minigameCompleted)
|
||||
if (_minigameCompleted)
|
||||
{
|
||||
Logging.Debug("[StatueDecorationController] Minigame already completed");
|
||||
return;
|
||||
@@ -174,7 +178,7 @@ namespace Minigames.StatueDressup.Controllers
|
||||
/// </summary>
|
||||
private System.Collections.IEnumerator CapturePhotoCoroutine()
|
||||
{
|
||||
int decorationCount = placedDecorations.Count;
|
||||
int decorationCount = _placedDecorations.Count;
|
||||
bool captureSuccess = false;
|
||||
string savedPhotoId = null;
|
||||
|
||||
@@ -222,7 +226,7 @@ namespace Minigames.StatueDressup.Controllers
|
||||
// Show completion feedback
|
||||
ShowCompletionFeedback();
|
||||
|
||||
minigameCompleted = true;
|
||||
_minigameCompleted = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -290,7 +294,7 @@ namespace Minigames.StatueDressup.Controllers
|
||||
};
|
||||
|
||||
// Collect all decoration placements
|
||||
foreach (var decoration in placedDecorations)
|
||||
foreach (var decoration in _placedDecorations)
|
||||
{
|
||||
if (decoration == null || decoration.Data == null) continue;
|
||||
|
||||
@@ -455,6 +459,38 @@ namespace Minigames.StatueDressup.Controllers
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show edit UI for a placed decoration
|
||||
/// </summary>
|
||||
public void ShowEditUI(DecorationDraggableInstance decoration)
|
||||
{
|
||||
if (decoration == null)
|
||||
{
|
||||
Logging.Warning("[StatueDecorationController] Cannot show edit UI - decoration is null");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create edit UI instance if needed
|
||||
if (_editUIInstance == null)
|
||||
{
|
||||
if (editUIPrefab == null)
|
||||
{
|
||||
Logging.Error("[StatueDecorationController] Edit UI prefab is not assigned!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Instantiate as child of canvas (find appropriate parent)
|
||||
Transform canvasTransform = statueArea != null ? statueArea.root : transform.root;
|
||||
_editUIInstance = Instantiate(editUIPrefab, canvasTransform);
|
||||
_editUIInstance.transform.SetAsLastSibling(); // Ensure it's on top
|
||||
|
||||
Logging.Debug("[StatueDecorationController] Created edit UI instance");
|
||||
}
|
||||
|
||||
// Show the UI
|
||||
_editUIInstance.Show(decoration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup when controller is destroyed
|
||||
/// </summary>
|
||||
|
||||
@@ -21,36 +21,36 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
[SerializeField] private Image decorationImage;
|
||||
[SerializeField] private CanvasGroup canvasGroup;
|
||||
|
||||
private DecorationData decorationData;
|
||||
private RectTransform rectTransform;
|
||||
private Canvas canvas;
|
||||
private Transform canvasParent; // Parent transform for dragging (usually canvas or draggable container)
|
||||
private RectTransform statueOutline;
|
||||
private Transform statueParent;
|
||||
private StatueDecorationController controller;
|
||||
private AppleHills.Core.Settings.IStatueDressupSettings settings;
|
||||
private System.Action onFinishedCallback;
|
||||
private System.Action onShowOutlineCallback;
|
||||
private System.Action onHideOutlineCallback;
|
||||
private DecorationData _decorationData;
|
||||
private RectTransform _rectTransform;
|
||||
private Canvas _canvas;
|
||||
private Transform _canvasParent; // Parent transform for dragging (usually canvas or draggable container)
|
||||
private RectTransform _statueOutline;
|
||||
private Transform _statueParent;
|
||||
private StatueDecorationController _controller;
|
||||
private AppleHills.Core.Settings.IStatueDressupSettings _settings;
|
||||
private System.Action _onFinishedCallback;
|
||||
private System.Action _onShowOutlineCallback;
|
||||
private System.Action _onHideOutlineCallback;
|
||||
|
||||
private bool isDragging;
|
||||
private bool isPlacedOnStatue;
|
||||
private Vector3 dragOffset;
|
||||
private bool dragStarted; // Track if drag actually started (vs just a click)
|
||||
private bool _isDragging;
|
||||
private bool _isPlacedOnStatue;
|
||||
private Vector3 _dragOffset;
|
||||
private bool _dragStarted; // Track if drag actually started (vs just a click)
|
||||
|
||||
// Properties
|
||||
public DecorationData Data => decorationData;
|
||||
public bool IsPlacedOnStatue => isPlacedOnStatue;
|
||||
public DecorationData Data => _decorationData;
|
||||
public bool IsPlacedOnStatue => _isPlacedOnStatue;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
rectTransform = GetComponent<RectTransform>();
|
||||
canvas = GetComponentInParent<Canvas>();
|
||||
_rectTransform = GetComponent<RectTransform>();
|
||||
_canvas = GetComponentInParent<Canvas>();
|
||||
|
||||
// Store initial parent for dragging context
|
||||
if (transform.parent != null)
|
||||
{
|
||||
canvasParent = transform.parent;
|
||||
_canvasParent = transform.parent;
|
||||
}
|
||||
|
||||
if (canvasGroup == null)
|
||||
@@ -76,24 +76,24 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
return;
|
||||
}
|
||||
|
||||
decorationData = context.Data;
|
||||
statueOutline = context.StatueOutline;
|
||||
statueParent = context.StatueParent;
|
||||
controller = context.Controller;
|
||||
settings = context.Settings;
|
||||
onFinishedCallback = context.OnFinished;
|
||||
onShowOutlineCallback = context.OnShowOutline;
|
||||
onHideOutlineCallback = context.OnHideOutline;
|
||||
_decorationData = context.Data;
|
||||
_statueOutline = context.StatueOutline;
|
||||
_statueParent = context.StatueParent;
|
||||
_controller = context.Controller;
|
||||
_settings = context.Settings;
|
||||
_onFinishedCallback = context.OnFinished;
|
||||
_onShowOutlineCallback = context.OnShowOutline;
|
||||
_onHideOutlineCallback = context.OnHideOutline;
|
||||
|
||||
// Handle placed vs new drag
|
||||
if (context.IsPlaced)
|
||||
{
|
||||
isPlacedOnStatue = true;
|
||||
isDragging = false;
|
||||
statueParent = transform.parent; // Already parented to statue
|
||||
_isPlacedOnStatue = true;
|
||||
_isDragging = false;
|
||||
_statueParent = transform.parent; // Already parented to statue
|
||||
if (context.CanvasParent != null)
|
||||
{
|
||||
canvasParent = context.CanvasParent;
|
||||
_canvasParent = context.CanvasParent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,9 +104,9 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
}
|
||||
|
||||
// Set authored size
|
||||
if (rectTransform != null && context.Data != null)
|
||||
if (_rectTransform != null && context.Data != null)
|
||||
{
|
||||
rectTransform.sizeDelta = context.Data.AuthoredSize;
|
||||
_rectTransform.sizeDelta = context.Data.AuthoredSize;
|
||||
}
|
||||
|
||||
// Make interactive if placed (so it can be picked up)
|
||||
@@ -154,22 +154,22 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
/// </summary>
|
||||
public void StartDragFromIcon(PointerEventData eventData)
|
||||
{
|
||||
isDragging = true;
|
||||
_isDragging = true;
|
||||
|
||||
// Broadcast started dragging event (from grid)
|
||||
var eventDataObj = new DecorationEventData(decorationData, gameObject, transform.position, fromStatue: false);
|
||||
var eventDataObj = new DecorationEventData(_decorationData, gameObject, transform.position, fromStatue: false);
|
||||
DecorationEventsManager.BroadcastDecorationStartedDragging(eventDataObj);
|
||||
|
||||
// Calculate offset from cursor to object center
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||
canvas.transform as RectTransform,
|
||||
_canvas.transform as RectTransform,
|
||||
eventData.position,
|
||||
eventData.pressEventCamera,
|
||||
out Vector2 localPoint);
|
||||
|
||||
dragOffset = rectTransform.localPosition - (Vector3)localPoint;
|
||||
_dragOffset = _rectTransform.localPosition - (Vector3)localPoint;
|
||||
|
||||
Logging.Debug($"[DecorationDraggableInstance] Started drag from icon: {decorationData?.DecorationName}");
|
||||
Logging.Debug($"[DecorationDraggableInstance] Started drag from icon: {_decorationData?.DecorationName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -177,16 +177,16 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
/// </summary>
|
||||
public void ContinueDrag(PointerEventData eventData)
|
||||
{
|
||||
if (!isDragging) return;
|
||||
if (!_isDragging) return;
|
||||
|
||||
// Update position to follow cursor
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||
canvas.transform as RectTransform,
|
||||
_canvas.transform as RectTransform,
|
||||
eventData.position,
|
||||
eventData.pressEventCamera,
|
||||
out Vector2 localPoint);
|
||||
|
||||
rectTransform.localPosition = localPoint + (Vector2)dragOffset;
|
||||
_rectTransform.localPosition = localPoint + (Vector2)_dragOffset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -194,12 +194,12 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
/// </summary>
|
||||
public void EndDrag(PointerEventData eventData)
|
||||
{
|
||||
isDragging = false;
|
||||
_isDragging = false;
|
||||
|
||||
Logging.Debug($"[DecorationDraggableInstance] Drag ended: {decorationData?.DecorationName}");
|
||||
Logging.Debug($"[DecorationDraggableInstance] Drag ended: {_decorationData?.DecorationName}");
|
||||
|
||||
// Broadcast finished dragging event
|
||||
var eventDataObj = new DecorationEventData(decorationData, gameObject, transform.position, fromStatue: isPlacedOnStatue);
|
||||
var eventDataObj = new DecorationEventData(_decorationData, gameObject, transform.position, fromStatue: _isPlacedOnStatue);
|
||||
DecorationEventsManager.BroadcastDecorationFinishedDragging(eventDataObj);
|
||||
|
||||
// Check if overlapping with statue
|
||||
@@ -218,20 +218,20 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
/// </summary>
|
||||
private bool IsOverlappingStatue()
|
||||
{
|
||||
if (statueOutline == null || rectTransform == null)
|
||||
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);
|
||||
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}");
|
||||
Logging.Debug($"[DecorationDraggableInstance] Overlap check: {_decorationData?.DecorationName}, overlaps={overlaps}");
|
||||
|
||||
return overlaps;
|
||||
}
|
||||
@@ -255,28 +255,28 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
/// </summary>
|
||||
private void PlaceOnStatue()
|
||||
{
|
||||
Logging.Debug($"[DecorationDraggableInstance] Placing on statue: {decorationData?.DecorationName}");
|
||||
Logging.Debug($"[DecorationDraggableInstance] Placing on statue: {_decorationData?.DecorationName}");
|
||||
|
||||
isPlacedOnStatue = true;
|
||||
_isPlacedOnStatue = true;
|
||||
|
||||
// Broadcast dropped on statue event
|
||||
var eventDataObj = new DecorationEventData(decorationData, gameObject, transform.position, fromStatue: false);
|
||||
var eventDataObj = new DecorationEventData(_decorationData, gameObject, transform.position, fromStatue: false);
|
||||
DecorationEventsManager.BroadcastDecorationDroppedOnStatue(eventDataObj);
|
||||
|
||||
// Move to statue parent if specified
|
||||
if (statueParent != null && transform.parent != statueParent)
|
||||
if (_statueParent != null && transform.parent != _statueParent)
|
||||
{
|
||||
transform.SetParent(statueParent, true); // Keep world position
|
||||
transform.SetParent(_statueParent, true); // Keep world position
|
||||
}
|
||||
|
||||
// Register with controller
|
||||
if (controller != null)
|
||||
if (_controller != null)
|
||||
{
|
||||
controller.RegisterDecoration(this);
|
||||
_controller.RegisterDecoration(this);
|
||||
}
|
||||
|
||||
// Notify menu controller to hide outline
|
||||
onFinishedCallback?.Invoke();
|
||||
_onFinishedCallback?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -284,22 +284,22 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
/// </summary>
|
||||
private void PlayPopOutAndDestroy()
|
||||
{
|
||||
Logging.Debug($"[DecorationDraggableInstance] Pop-out and destroy: {decorationData?.DecorationName}");
|
||||
Logging.Debug($"[DecorationDraggableInstance] Pop-out and destroy: {_decorationData?.DecorationName}");
|
||||
|
||||
// Broadcast dropped out event (animation starting)
|
||||
var eventDataObj = new DecorationEventData(decorationData, gameObject, transform.position, fromStatue: false);
|
||||
var eventDataObj = new DecorationEventData(_decorationData, gameObject, transform.position, fromStatue: false);
|
||||
DecorationEventsManager.BroadcastDecorationDroppedOut(eventDataObj);
|
||||
|
||||
// Notify menu controller to hide outline immediately
|
||||
onFinishedCallback?.Invoke();
|
||||
_onFinishedCallback?.Invoke();
|
||||
|
||||
float duration = settings?.PlacementAnimationDuration ?? StatueDressupConstants.DefaultAnimationDuration;
|
||||
float duration = _settings?.PlacementAnimationDuration ?? StatueDressupConstants.DefaultAnimationDuration;
|
||||
|
||||
// Play pop-out with fade animation
|
||||
TweenAnimationUtility.PopOutWithFade(transform, canvasGroup, duration, () =>
|
||||
{
|
||||
// Broadcast finished dropping out event (animation complete)
|
||||
var finalEventData = new DecorationEventData(decorationData, gameObject, transform.position, fromStatue: false);
|
||||
var finalEventData = new DecorationEventData(_decorationData, gameObject, transform.position, fromStatue: false);
|
||||
DecorationEventsManager.BroadcastDecorationFinishedDroppingOut(finalEventData);
|
||||
|
||||
Destroy(gameObject);
|
||||
@@ -311,26 +311,26 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
/// </summary>
|
||||
public void StartDragFromStatue(PointerEventData eventData)
|
||||
{
|
||||
Logging.Debug($"[DecorationDraggableInstance] StartDragFromStatue called for: {decorationData?.DecorationName}");
|
||||
Logging.Debug($"[DecorationDraggableInstance] Show outline callback is null: {onShowOutlineCallback == null}");
|
||||
Logging.Debug($"[DecorationDraggableInstance] StartDragFromStatue called for: {_decorationData?.DecorationName}");
|
||||
Logging.Debug($"[DecorationDraggableInstance] Show outline callback is null: {_onShowOutlineCallback == null}");
|
||||
|
||||
if (controller != null)
|
||||
if (_controller != null)
|
||||
{
|
||||
controller.UnregisterDecoration(this);
|
||||
_controller.UnregisterDecoration(this);
|
||||
}
|
||||
|
||||
isPlacedOnStatue = false;
|
||||
isDragging = true;
|
||||
_isPlacedOnStatue = false;
|
||||
_isDragging = true;
|
||||
|
||||
// Broadcast started dragging event (from statue)
|
||||
var eventDataObj = new DecorationEventData(decorationData, gameObject, transform.position, fromStatue: true);
|
||||
var eventDataObj = new DecorationEventData(_decorationData, gameObject, transform.position, fromStatue: true);
|
||||
DecorationEventsManager.BroadcastDecorationStartedDragging(eventDataObj);
|
||||
|
||||
// Show statue outline when picking up from statue
|
||||
if (onShowOutlineCallback != null)
|
||||
if (_onShowOutlineCallback != null)
|
||||
{
|
||||
Logging.Debug("[DecorationDraggableInstance] Invoking show outline callback");
|
||||
onShowOutlineCallback.Invoke();
|
||||
_onShowOutlineCallback.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -338,24 +338,24 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
}
|
||||
|
||||
// Reparent to canvas for dragging (so coordinates work correctly)
|
||||
if (canvasParent != null && transform.parent != canvasParent)
|
||||
if (_canvasParent != null && transform.parent != _canvasParent)
|
||||
{
|
||||
// Store world position before reparenting
|
||||
Vector3 worldPos = transform.position;
|
||||
transform.SetParent(canvasParent, false);
|
||||
transform.SetParent(_canvasParent, false);
|
||||
transform.position = worldPos; // Restore world position
|
||||
}
|
||||
|
||||
// Calculate offset using proper camera
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||
canvas.transform as RectTransform,
|
||||
_canvas.transform as RectTransform,
|
||||
eventData.position,
|
||||
eventData.pressEventCamera,
|
||||
out Vector2 localPoint);
|
||||
|
||||
dragOffset = rectTransform.localPosition - (Vector3)localPoint;
|
||||
_dragOffset = _rectTransform.localPosition - (Vector3)localPoint;
|
||||
|
||||
Logging.Debug($"[DecorationDraggableInstance] Started drag from statue: {decorationData?.DecorationName}");
|
||||
Logging.Debug($"[DecorationDraggableInstance] Started drag from statue: {_decorationData?.DecorationName}");
|
||||
}
|
||||
|
||||
#region Pointer Event Handlers
|
||||
@@ -366,15 +366,23 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
public void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
// Only handle clicks when placed on statue and not currently dragging
|
||||
if (!isPlacedOnStatue || dragStarted) return;
|
||||
if (!_isPlacedOnStatue || _dragStarted) return;
|
||||
|
||||
Logging.Debug($"[DecorationDraggableInstance] Decoration tapped: {decorationData?.DecorationName}");
|
||||
Logging.Debug($"[DecorationDraggableInstance] Decoration tapped: {_decorationData?.DecorationName}");
|
||||
|
||||
// Broadcast tap event
|
||||
var eventDataObj = new DecorationEventData(decorationData, gameObject, transform.position, fromStatue: true);
|
||||
var eventDataObj = new DecorationEventData(_decorationData, gameObject, transform.position, fromStatue: true);
|
||||
DecorationEventsManager.BroadcastDecorationTappedOnStatue(eventDataObj);
|
||||
|
||||
// Future: Open detail view, play sound effect, show info popup, etc.
|
||||
// Show edit UI
|
||||
if (_controller != null)
|
||||
{
|
||||
_controller.ShowEditUI(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning("[DecorationDraggableInstance] Cannot show edit UI - controller reference is null");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -383,9 +391,9 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
public void OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
// Only handle drag from statue if already placed
|
||||
if (!isPlacedOnStatue) return;
|
||||
if (!_isPlacedOnStatue) return;
|
||||
|
||||
dragStarted = true;
|
||||
_dragStarted = true;
|
||||
StartDragFromStatue(eventData);
|
||||
}
|
||||
|
||||
@@ -394,7 +402,7 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
/// </summary>
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
if (!isDragging) return;
|
||||
if (!_isDragging) return;
|
||||
|
||||
ContinueDrag(eventData);
|
||||
}
|
||||
@@ -404,9 +412,9 @@ namespace Minigames.StatueDressup.DragDrop
|
||||
/// </summary>
|
||||
public void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
if (!isDragging) return;
|
||||
if (!_isDragging) return;
|
||||
|
||||
dragStarted = false;
|
||||
_dragStarted = false;
|
||||
EndDrag(eventData);
|
||||
}
|
||||
|
||||
|
||||
288
Assets/Scripts/Minigames/StatueDressup/UI/DecorationEditUI.cs
Normal file
288
Assets/Scripts/Minigames/StatueDressup/UI/DecorationEditUI.cs
Normal file
@@ -0,0 +1,288 @@
|
||||
using Core;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Minigames.StatueDressup.DragDrop;
|
||||
|
||||
namespace Minigames.StatueDressup.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// UI panel for editing a placed decoration's scale and rotation.
|
||||
/// Shows sliders for scale (0.1x - 2x) and rotation (-180° to 180°).
|
||||
/// Changes are applied immediately to the decoration's transform.
|
||||
/// </summary>
|
||||
public class DecorationEditUI : MonoBehaviour
|
||||
{
|
||||
[Header("UI References")]
|
||||
[SerializeField] private Slider scaleSlider;
|
||||
[SerializeField] private Slider rotationSlider;
|
||||
[SerializeField] private Button confirmButton;
|
||||
[SerializeField] private Button resetButton;
|
||||
[SerializeField] private CanvasGroup canvasGroup;
|
||||
|
||||
[Header("Slider Ranges")]
|
||||
[SerializeField] private float minScale = 0.1f;
|
||||
[SerializeField] private float maxScale = 2.0f;
|
||||
[SerializeField] private float minRotation = -180f;
|
||||
[SerializeField] private float maxRotation = 180f;
|
||||
|
||||
private DecorationDraggableInstance _targetDecoration;
|
||||
private RectTransform _rectTransform;
|
||||
private float _originalRotation;
|
||||
private bool _isInitialized;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Get RectTransform
|
||||
_rectTransform = GetComponent<RectTransform>();
|
||||
|
||||
// Ensure canvas group exists
|
||||
if (canvasGroup == null)
|
||||
{
|
||||
canvasGroup = GetComponent<CanvasGroup>();
|
||||
if (canvasGroup == null)
|
||||
{
|
||||
canvasGroup = gameObject.AddComponent<CanvasGroup>();
|
||||
}
|
||||
}
|
||||
|
||||
// Setup slider ranges
|
||||
if (scaleSlider != null)
|
||||
{
|
||||
scaleSlider.minValue = minScale;
|
||||
scaleSlider.maxValue = maxScale;
|
||||
scaleSlider.onValueChanged.AddListener(OnScaleChanged);
|
||||
}
|
||||
|
||||
if (rotationSlider != null)
|
||||
{
|
||||
rotationSlider.minValue = minRotation;
|
||||
rotationSlider.maxValue = maxRotation;
|
||||
rotationSlider.onValueChanged.AddListener(OnRotationChanged);
|
||||
}
|
||||
|
||||
// Setup buttons
|
||||
if (confirmButton != null)
|
||||
{
|
||||
confirmButton.onClick.AddListener(OnConfirm);
|
||||
}
|
||||
|
||||
if (resetButton != null)
|
||||
{
|
||||
resetButton.onClick.AddListener(OnReset);
|
||||
}
|
||||
|
||||
// Start hidden
|
||||
gameObject.SetActive(false);
|
||||
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
// Clean up listeners
|
||||
if (scaleSlider != null)
|
||||
{
|
||||
scaleSlider.onValueChanged.RemoveListener(OnScaleChanged);
|
||||
}
|
||||
|
||||
if (rotationSlider != null)
|
||||
{
|
||||
rotationSlider.onValueChanged.RemoveListener(OnRotationChanged);
|
||||
}
|
||||
|
||||
if (confirmButton != null)
|
||||
{
|
||||
confirmButton.onClick.RemoveListener(OnConfirm);
|
||||
}
|
||||
|
||||
if (resetButton != null)
|
||||
{
|
||||
resetButton.onClick.RemoveListener(OnReset);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the edit UI for the given decoration
|
||||
/// </summary>
|
||||
public void Show(DecorationDraggableInstance decoration)
|
||||
{
|
||||
if (!_isInitialized)
|
||||
{
|
||||
Logging.Error("[DecorationEditUI] Attempted to show before initialization!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (decoration == null)
|
||||
{
|
||||
Logging.Error("[DecorationEditUI] Cannot show edit UI - decoration is null!");
|
||||
return;
|
||||
}
|
||||
|
||||
_targetDecoration = decoration;
|
||||
|
||||
// Store original rotation for reference
|
||||
_originalRotation = decoration.transform.localEulerAngles.z;
|
||||
|
||||
// Normalize rotation to -180 to 180 range
|
||||
if (_originalRotation > 180f)
|
||||
{
|
||||
_originalRotation -= 360f;
|
||||
}
|
||||
|
||||
// Initialize sliders from current transform values
|
||||
if (scaleSlider != null)
|
||||
{
|
||||
// Use X component for uniform scale
|
||||
float currentScale = decoration.transform.localScale.x;
|
||||
scaleSlider.value = Mathf.Clamp(currentScale, minScale, maxScale);
|
||||
}
|
||||
|
||||
if (rotationSlider != null)
|
||||
{
|
||||
rotationSlider.value = Mathf.Clamp(_originalRotation, minRotation, maxRotation);
|
||||
}
|
||||
|
||||
// Disable decoration raycasts during editing
|
||||
CanvasGroup decorationCanvasGroup = decoration.GetComponent<CanvasGroup>();
|
||||
if (decorationCanvasGroup != null)
|
||||
{
|
||||
decorationCanvasGroup.blocksRaycasts = false;
|
||||
}
|
||||
|
||||
// Position UI centered over the decoration (context menu style)
|
||||
PositionOverDecoration(decoration);
|
||||
|
||||
// Show UI immediately
|
||||
gameObject.SetActive(true);
|
||||
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
canvasGroup.alpha = 1f;
|
||||
}
|
||||
|
||||
Logging.Debug($"[DecorationEditUI] Showing edit UI for: {decoration.Data?.DecorationName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Position the UI centered over the decoration (context menu style)
|
||||
/// </summary>
|
||||
private void PositionOverDecoration(DecorationDraggableInstance decoration)
|
||||
{
|
||||
if (_rectTransform == null || decoration == null) return;
|
||||
|
||||
// Get decoration's world position
|
||||
Vector3 decorationWorldPos = decoration.transform.position;
|
||||
|
||||
// Convert to canvas space if using screen space overlay
|
||||
Canvas canvas = GetComponentInParent<Canvas>();
|
||||
if (canvas != null && canvas.renderMode == RenderMode.ScreenSpaceOverlay)
|
||||
{
|
||||
// For overlay canvas, world position is already correct
|
||||
_rectTransform.position = decorationWorldPos;
|
||||
}
|
||||
else if (canvas != null)
|
||||
{
|
||||
// For other canvas modes, convert properly
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||
canvas.transform as RectTransform,
|
||||
RectTransformUtility.WorldToScreenPoint(canvas.worldCamera, decorationWorldPos),
|
||||
canvas.worldCamera,
|
||||
out Vector2 localPoint
|
||||
);
|
||||
_rectTransform.localPosition = localPoint;
|
||||
}
|
||||
|
||||
Logging.Debug($"[DecorationEditUI] Positioned at decoration location: {decorationWorldPos}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hide the edit UI
|
||||
/// </summary>
|
||||
public void Hide()
|
||||
{
|
||||
if (_targetDecoration != null)
|
||||
{
|
||||
// Re-enable decoration raycasts
|
||||
CanvasGroup decorationCanvasGroup = _targetDecoration.GetComponent<CanvasGroup>();
|
||||
if (decorationCanvasGroup != null)
|
||||
{
|
||||
decorationCanvasGroup.blocksRaycasts = true;
|
||||
}
|
||||
}
|
||||
|
||||
_targetDecoration = null;
|
||||
gameObject.SetActive(false);
|
||||
|
||||
Logging.Debug("[DecorationEditUI] Edit UI hidden");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle scale slider change
|
||||
/// </summary>
|
||||
private void OnScaleChanged(float value)
|
||||
{
|
||||
if (_targetDecoration == null) return;
|
||||
|
||||
// Apply uniform scale (X, Y, Z all the same)
|
||||
_targetDecoration.transform.localScale = Vector3.one * value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle rotation slider change
|
||||
/// </summary>
|
||||
private void OnRotationChanged(float value)
|
||||
{
|
||||
if (_targetDecoration == null) return;
|
||||
|
||||
// Apply Z rotation only
|
||||
_targetDecoration.transform.localEulerAngles = new Vector3(0f, 0f, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle confirm button - save changes and close
|
||||
/// </summary>
|
||||
private void OnConfirm()
|
||||
{
|
||||
if (_targetDecoration != null)
|
||||
{
|
||||
// Trigger auto-save through the controller
|
||||
var controller = Controllers.StatueDecorationController.Instance;
|
||||
if (controller != null)
|
||||
{
|
||||
// The controller's RegisterDecoration already triggers SaveStatueState
|
||||
// Since the decoration is already registered, we just need to trigger a save
|
||||
// This happens automatically on the next RegisterDecoration/UnregisterDecoration call
|
||||
Logging.Debug("[DecorationEditUI] Changes confirmed - will be auto-saved");
|
||||
}
|
||||
}
|
||||
|
||||
Hide();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle reset button - restore original values
|
||||
/// </summary>
|
||||
private void OnReset()
|
||||
{
|
||||
if (_targetDecoration == null) return;
|
||||
|
||||
// Reset to authored size (scale 1.0) and 0 rotation
|
||||
float defaultScale = 1.0f;
|
||||
float defaultRotation = 0f;
|
||||
|
||||
if (scaleSlider != null)
|
||||
{
|
||||
scaleSlider.value = defaultScale;
|
||||
}
|
||||
|
||||
if (rotationSlider != null)
|
||||
{
|
||||
rotationSlider.value = defaultRotation;
|
||||
}
|
||||
|
||||
// Values are applied through the slider callbacks
|
||||
Logging.Debug("[DecorationEditUI] Reset to defaults");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f3e2a1b9c4d5e6f7a8b9c0d1e2f3a4b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
Reference in New Issue
Block a user