Update the statue game to include rotation etc.

This commit is contained in:
Michal Pikulski
2025-12-08 14:48:09 +01:00
parent fff50990f1
commit e338e28673
7 changed files with 2720 additions and 96 deletions

View File

@@ -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);
}