Add a semi-finished booster opening sequence
This commit is contained in:
@@ -21,7 +21,7 @@ namespace UI.DragAndDrop.Core
|
||||
{
|
||||
[Header("Draggable Settings")]
|
||||
[SerializeField] protected float moveSpeed = 50f;
|
||||
[SerializeField] protected bool smoothMovement = true;
|
||||
[SerializeField] protected bool smoothMovement = false; // Disabled for instant cursor tracking
|
||||
[SerializeField] protected float snapDuration = 0.3f;
|
||||
|
||||
[Header("Visual")]
|
||||
@@ -36,6 +36,7 @@ namespace UI.DragAndDrop.Core
|
||||
protected bool _isHovering;
|
||||
protected bool _isSelected;
|
||||
protected bool _wasDragged;
|
||||
protected bool _isDraggingEnabled = true;
|
||||
|
||||
// References
|
||||
protected Canvas _canvas;
|
||||
@@ -87,6 +88,16 @@ namespace UI.DragAndDrop.Core
|
||||
_canvasGroup = GetComponent<CanvasGroup>();
|
||||
_raycaster = _canvas?.GetComponent<GraphicRaycaster>();
|
||||
|
||||
// If no Image component exists, add an invisible one for raycast detection
|
||||
// Unity UI requires a Graphic component to receive pointer events
|
||||
if (_imageComponent == null && _canvasGroup != null)
|
||||
{
|
||||
_imageComponent = gameObject.AddComponent<Image>();
|
||||
_imageComponent.color = new Color(1, 1, 1, 0.01f); // Nearly transparent (0 doesn't work)
|
||||
_imageComponent.raycastTarget = true;
|
||||
Debug.Log($"[DraggableObject] Added invisible Image to {name} for raycast detection");
|
||||
}
|
||||
|
||||
// Use assigned visual, or find in children recursively if not assigned
|
||||
if (visual != null)
|
||||
{
|
||||
@@ -118,25 +129,44 @@ namespace UI.DragAndDrop.Core
|
||||
SmoothMoveTowardPointer();
|
||||
}
|
||||
|
||||
ClampToScreen();
|
||||
// Only clamp for non-overlay canvases (WorldSpace/ScreenSpaceCamera)
|
||||
if (_canvas != null && _canvas.renderMode != RenderMode.ScreenSpaceOverlay)
|
||||
{
|
||||
ClampToScreen();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SmoothMoveTowardPointer()
|
||||
{
|
||||
Vector3 targetPosition = _lastPointerPosition - _dragOffset;
|
||||
Vector3 direction = (targetPosition - transform.position).normalized;
|
||||
float distance = Vector3.Distance(transform.position, targetPosition);
|
||||
float speed = Mathf.Min(moveSpeed, distance / Time.deltaTime);
|
||||
|
||||
transform.Translate(direction * speed * Time.deltaTime, Space.World);
|
||||
if (RectTransform == null)
|
||||
return;
|
||||
|
||||
// For ScreenSpaceOverlay, work with screen/anchoredPosition
|
||||
if (_canvas != null && _canvas.renderMode == RenderMode.ScreenSpaceOverlay)
|
||||
{
|
||||
Vector2 targetPos = (Vector2)_lastPointerPosition - (Vector2)_dragOffset;
|
||||
Vector2 currentPos = RectTransform.position;
|
||||
Vector2 direction = (targetPos - currentPos).normalized;
|
||||
float distance = Vector2.Distance(currentPos, targetPos);
|
||||
float speed = Mathf.Min(moveSpeed, distance / Time.deltaTime);
|
||||
|
||||
RectTransform.position = currentPos + direction * speed * Time.deltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For WorldSpace/ScreenSpaceCamera, use world coordinates
|
||||
Vector3 targetPosition = _lastPointerPosition - _dragOffset;
|
||||
Vector3 direction = (targetPosition - transform.position).normalized;
|
||||
float distance = Vector3.Distance(transform.position, targetPosition);
|
||||
float speed = Mathf.Min(moveSpeed, distance / Time.deltaTime);
|
||||
|
||||
transform.Translate(direction * speed * Time.deltaTime, Space.World);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ClampToScreen()
|
||||
{
|
||||
// Skip clamping for ScreenSpaceOverlay - it doesn't use world coordinates
|
||||
if (_canvas != null && _canvas.renderMode == RenderMode.ScreenSpaceOverlay)
|
||||
return;
|
||||
|
||||
// This method is only called for WorldSpace/ScreenSpaceCamera canvases
|
||||
if (Camera.main == null || RectTransform == null)
|
||||
return;
|
||||
|
||||
@@ -159,14 +189,31 @@ namespace UI.DragAndDrop.Core
|
||||
{
|
||||
if (eventData.button != PointerEventData.InputButton.Left)
|
||||
return;
|
||||
|
||||
// Check if dragging is enabled BEFORE setting any state
|
||||
if (!_isDraggingEnabled)
|
||||
return;
|
||||
|
||||
_isDragging = true;
|
||||
_wasDragged = true;
|
||||
|
||||
// Calculate offset
|
||||
Vector3 worldPointer = GetWorldPosition(eventData);
|
||||
_dragOffset = worldPointer - transform.position;
|
||||
_lastPointerPosition = worldPointer;
|
||||
// ...existing code...
|
||||
if (_canvas != null && _canvas.renderMode == RenderMode.ScreenSpaceOverlay && RectTransform != null)
|
||||
{
|
||||
// For overlay, use screen position directly
|
||||
_dragOffset = (Vector3)eventData.position - RectTransform.position;
|
||||
_lastPointerPosition = eventData.position;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For WorldSpace/ScreenSpaceCamera, convert to world coords
|
||||
Vector3 worldPointer = GetWorldPosition(eventData);
|
||||
_dragOffset = worldPointer - transform.position;
|
||||
_lastPointerPosition = worldPointer;
|
||||
}
|
||||
|
||||
// Reset base rotation to identity (0°) for clean dragging
|
||||
Tween.Rotation(transform, Quaternion.identity, 0.2f, 0f, Tween.EaseOutBack);
|
||||
|
||||
// Disable raycasting to allow detecting slots underneath
|
||||
if (_raycaster != null)
|
||||
@@ -190,12 +237,25 @@ namespace UI.DragAndDrop.Core
|
||||
{
|
||||
if (!_isDragging)
|
||||
return;
|
||||
|
||||
_lastPointerPosition = GetWorldPosition(eventData);
|
||||
|
||||
if (!smoothMovement)
|
||||
// Update last pointer position based on canvas type
|
||||
if (_canvas != null && _canvas.renderMode == RenderMode.ScreenSpaceOverlay)
|
||||
{
|
||||
transform.position = _lastPointerPosition - _dragOffset;
|
||||
_lastPointerPosition = eventData.position;
|
||||
|
||||
if (!smoothMovement && RectTransform != null)
|
||||
{
|
||||
RectTransform.position = (Vector2)_lastPointerPosition - (Vector2)_dragOffset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastPointerPosition = GetWorldPosition(eventData);
|
||||
|
||||
if (!smoothMovement)
|
||||
{
|
||||
transform.position = _lastPointerPosition - _dragOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,6 +277,12 @@ namespace UI.DragAndDrop.Core
|
||||
// Find closest slot and snap
|
||||
FindAndSnapToSlot();
|
||||
|
||||
// Snap base rotation back to slot rotation (if in a slot)
|
||||
if (_currentSlot != null)
|
||||
{
|
||||
Tween.Rotation(transform, _currentSlot.transform.rotation, 0.3f, 0f, Tween.EaseOutBack);
|
||||
}
|
||||
|
||||
OnDragEnded?.Invoke(this);
|
||||
OnDragEndedHook();
|
||||
|
||||
@@ -276,12 +342,18 @@ namespace UI.DragAndDrop.Core
|
||||
DraggableSlot closestSlot = null;
|
||||
float closestDistance = float.MaxValue;
|
||||
|
||||
// Use RectTransform.position for overlay, transform.position for others
|
||||
Vector3 myPosition = (_canvas != null && _canvas.renderMode == RenderMode.ScreenSpaceOverlay && RectTransform != null)
|
||||
? RectTransform.position
|
||||
: transform.position;
|
||||
|
||||
foreach (var container in containers)
|
||||
{
|
||||
DraggableSlot slot = container.FindClosestSlot(transform.position, this);
|
||||
DraggableSlot slot = container.FindClosestSlot(myPosition, this);
|
||||
if (slot != null)
|
||||
{
|
||||
float distance = Vector3.Distance(transform.position, slot.WorldPosition);
|
||||
Vector3 slotPosition = slot.RectTransform != null ? slot.RectTransform.position : slot.transform.position;
|
||||
float distance = Vector3.Distance(myPosition, slotPosition);
|
||||
if (distance < closestDistance)
|
||||
{
|
||||
closestDistance = distance;
|
||||
@@ -419,6 +491,18 @@ namespace UI.DragAndDrop.Core
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dragging Control
|
||||
|
||||
/// <summary>
|
||||
/// Enable or disable dragging functionality
|
||||
/// </summary>
|
||||
public virtual void SetDraggingEnabled(bool enabled)
|
||||
{
|
||||
_isDraggingEnabled = enabled;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
protected Vector3 GetWorldPosition(PointerEventData eventData)
|
||||
|
||||
@@ -89,6 +89,12 @@ namespace UI.DragAndDrop.Core
|
||||
|
||||
case OccupantSizeMode.Scale:
|
||||
Tween.LocalScale(draggable.transform, occupantScale, scaleTransitionDuration, 0f, Tween.EaseOutBack);
|
||||
|
||||
// Also scale the visual if it exists (since visual is now independent)
|
||||
if (draggable.Visual != null)
|
||||
{
|
||||
Tween.LocalScale(draggable.Visual.transform, occupantScale, scaleTransitionDuration, 0f, Tween.EaseOutBack);
|
||||
}
|
||||
break;
|
||||
|
||||
case OccupantSizeMode.None:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Pixelplacement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem; // Added for new Input System
|
||||
|
||||
namespace UI.DragAndDrop.Core
|
||||
{
|
||||
@@ -23,7 +24,7 @@ namespace UI.DragAndDrop.Core
|
||||
[Header("Rotation/Tilt Parameters")]
|
||||
[SerializeField] protected float rotationAmount = 20f;
|
||||
[SerializeField] protected float rotationSpeed = 20f;
|
||||
[SerializeField] protected float autoTiltAmount = 30f;
|
||||
[SerializeField] protected float autoTiltAmount = 10f; // Reduced from 30f
|
||||
[SerializeField] protected float manualTiltAmount = 20f;
|
||||
[SerializeField] protected float tiltSpeed = 20f;
|
||||
|
||||
@@ -35,7 +36,7 @@ namespace UI.DragAndDrop.Core
|
||||
|
||||
[Header("Idle Animation")]
|
||||
[SerializeField] protected bool useIdleAnimation = true;
|
||||
[SerializeField] protected float idleAnimationSpeed = 1f;
|
||||
[SerializeField] protected float idleAnimationSpeed = 0.5f; // Slowed down from 1f
|
||||
|
||||
// State
|
||||
protected DraggableObject _parentDraggable;
|
||||
@@ -59,6 +60,14 @@ namespace UI.DragAndDrop.Core
|
||||
Canvas parentCanvas = parent.GetComponentInParent<Canvas>();
|
||||
Debug.Log($"[DraggableVisual] Initializing visual for {parent.name} at world pos {parent.transform.position}, parent canvas: {(parentCanvas != null ? parentCanvas.name + " (renderMode: " + parentCanvas.renderMode + ")" : "NULL")}");
|
||||
|
||||
// CRITICAL: Reparent visual to canvas (not base) so it can move independently
|
||||
// This enables the delayed follow effect
|
||||
if (parentCanvas != null)
|
||||
{
|
||||
transform.SetParent(parentCanvas.transform, true); // worldPositionStays = true
|
||||
Debug.Log($"[DraggableVisual] Reparented visual {name} to canvas {parentCanvas.name} for independent movement");
|
||||
}
|
||||
|
||||
// Get components if assigned (don't auto-create Canvas to avoid Unity's auto-reparenting)
|
||||
if (canvas == null)
|
||||
canvas = GetComponent<Canvas>();
|
||||
@@ -71,11 +80,24 @@ namespace UI.DragAndDrop.Core
|
||||
// Subscribe to parent events
|
||||
SubscribeToParentEvents();
|
||||
|
||||
// Initial position
|
||||
// Initial position to match parent
|
||||
transform.position = parent.transform.position;
|
||||
_lastPosition = transform.position;
|
||||
|
||||
Debug.Log($"[DraggableVisual] Visual {name} initialized at world pos {transform.position}, local pos {transform.localPosition}, parent at world pos {parent.transform.position}, local pos {parent.transform.localPosition}");
|
||||
// Set rotation to match base's current rotation (will be maintained via separate rotation management)
|
||||
transform.rotation = parent.transform.rotation;
|
||||
|
||||
// Reset shake and tilt parent rotations to zero (local space) for clean wobble
|
||||
if (shakeParent != null)
|
||||
{
|
||||
shakeParent.localRotation = Quaternion.identity;
|
||||
}
|
||||
if (tiltParent != null)
|
||||
{
|
||||
tiltParent.localRotation = Quaternion.identity;
|
||||
}
|
||||
|
||||
Debug.Log($"[DraggableVisual] Visual {name} initialized at world pos {transform.position}, local pos {transform.localPosition}, local rotation {transform.localRotation.eulerAngles}, parent at world pos {parent.transform.position}, local pos {parent.transform.localPosition}, rotation {parent.transform.rotation.eulerAngles}");
|
||||
|
||||
_isInitialized = true;
|
||||
|
||||
@@ -116,6 +138,7 @@ namespace UI.DragAndDrop.Core
|
||||
return;
|
||||
|
||||
UpdateFollowPosition();
|
||||
UpdateFollowRotation(); // Track base rotation changes
|
||||
UpdateRotation();
|
||||
UpdateTilt();
|
||||
UpdateVisualContent();
|
||||
@@ -123,36 +146,100 @@ namespace UI.DragAndDrop.Core
|
||||
|
||||
#region Position & Movement
|
||||
|
||||
protected virtual void UpdateFollowRotation()
|
||||
{
|
||||
if (_parentDraggable == null)
|
||||
return;
|
||||
|
||||
// Smoothly follow base rotation (since we're no longer a child)
|
||||
// Base rotation changes when picking up (→ 0°) or dropping (→ slot rotation)
|
||||
transform.rotation = Quaternion.Lerp(transform.rotation, _parentDraggable.transform.rotation, 10f * Time.deltaTime);
|
||||
}
|
||||
|
||||
protected virtual void UpdateFollowPosition()
|
||||
{
|
||||
if (_parentDraggable == null)
|
||||
return;
|
||||
|
||||
Vector3 targetPosition = GetTargetPosition();
|
||||
|
||||
// Debug log if position is drastically different (likely a clustering issue)
|
||||
if (Vector3.Distance(transform.position, targetPosition) > 500f)
|
||||
{
|
||||
Debug.LogWarning($"[DraggableVisual] Large position delta detected! Visual {name} at {transform.position}, target {targetPosition}, parent {_parentDraggable.name} at {_parentDraggable.transform.position}");
|
||||
}
|
||||
// For ScreenSpaceOverlay, use RectTransform.position consistently
|
||||
Canvas parentCanvas = _parentDraggable.GetComponentInParent<Canvas>();
|
||||
bool isOverlay = parentCanvas != null && parentCanvas.renderMode == RenderMode.ScreenSpaceOverlay;
|
||||
|
||||
if (useFollowDelay)
|
||||
Vector3 targetPosition;
|
||||
Vector3 currentPosition;
|
||||
|
||||
if (isOverlay && _parentDraggable.RectTransform != null && GetComponent<RectTransform>() != null)
|
||||
{
|
||||
transform.position = Vector3.Lerp(transform.position, targetPosition, followSpeed * Time.deltaTime);
|
||||
// Use RectTransform.position for overlay (screen space)
|
||||
RectTransform myRect = GetComponent<RectTransform>();
|
||||
targetPosition = _parentDraggable.RectTransform.position;
|
||||
currentPosition = myRect.position;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.position = targetPosition;
|
||||
// Use transform.position for WorldSpace/ScreenSpaceCamera
|
||||
targetPosition = _parentDraggable.transform.position;
|
||||
currentPosition = transform.position;
|
||||
}
|
||||
|
||||
// Debug log if position is drastically different (likely a clustering issue)
|
||||
float distance = Vector3.Distance(currentPosition, targetPosition);
|
||||
if (distance > 500f)
|
||||
{
|
||||
Debug.LogWarning($"[DraggableVisual] Large position delta detected! Visual {name} at {currentPosition}, target {targetPosition}, parent {_parentDraggable.name}, distance: {distance}");
|
||||
}
|
||||
|
||||
// Apply follow logic with snappy easing
|
||||
if (useFollowDelay)
|
||||
{
|
||||
// Calculate lerp factor with snappy ease
|
||||
float rawT = followSpeed * Time.deltaTime;
|
||||
|
||||
// Apply EaseOutCubic for snappier movement: 1 - (1-t)^3
|
||||
float t = 1f - Mathf.Pow(1f - rawT, 3f);
|
||||
|
||||
Vector3 newPosition = Vector3.Lerp(currentPosition, targetPosition, t);
|
||||
|
||||
if (isOverlay && GetComponent<RectTransform>() != null)
|
||||
{
|
||||
GetComponent<RectTransform>().position = newPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.position = newPosition;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isOverlay && GetComponent<RectTransform>() != null)
|
||||
{
|
||||
GetComponent<RectTransform>().position = targetPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.position = targetPosition;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate movement delta for tilt
|
||||
Vector3 movement = transform.position - _lastPosition;
|
||||
Vector3 actualCurrentPos = isOverlay && GetComponent<RectTransform>() != null
|
||||
? GetComponent<RectTransform>().position
|
||||
: transform.position;
|
||||
Vector3 movement = actualCurrentPos - _lastPosition;
|
||||
_movementDelta = Vector3.Lerp(_movementDelta, movement, 25f * Time.deltaTime);
|
||||
_lastPosition = transform.position;
|
||||
_lastPosition = actualCurrentPos;
|
||||
}
|
||||
|
||||
protected virtual Vector3 GetTargetPosition()
|
||||
{
|
||||
Canvas parentCanvas = _parentDraggable.GetComponentInParent<Canvas>();
|
||||
bool isOverlay = parentCanvas != null && parentCanvas.renderMode == RenderMode.ScreenSpaceOverlay;
|
||||
|
||||
if (isOverlay && _parentDraggable.RectTransform != null)
|
||||
{
|
||||
return _parentDraggable.RectTransform.position;
|
||||
}
|
||||
|
||||
return _parentDraggable.transform.position;
|
||||
}
|
||||
|
||||
@@ -162,59 +249,93 @@ namespace UI.DragAndDrop.Core
|
||||
|
||||
protected virtual void UpdateRotation()
|
||||
{
|
||||
if (_parentDraggable == null)
|
||||
if (_parentDraggable == null || shakeParent == null)
|
||||
return;
|
||||
|
||||
// Rotation based on movement direction (like Balatro)
|
||||
Vector3 movementRotation = _parentDraggable.IsDragging
|
||||
? _movementDelta * rotationAmount
|
||||
: (_lastPosition - _parentDraggable.transform.position) * rotationAmount;
|
||||
|
||||
// Apply rotation based on movement to shakeParent (not main transform)
|
||||
// This way it's additive on top of the base rotation in transform.rotation
|
||||
// Negated to make the bottom "drag behind" instead of leading
|
||||
Vector3 movementRotation = _movementDelta * -rotationAmount; // Flipped direction
|
||||
|
||||
_rotationDelta = Vector3.Lerp(_rotationDelta, movementRotation, rotationSpeed * Time.deltaTime);
|
||||
|
||||
// Apply Z-axis rotation to shakeParent as local rotation
|
||||
float clampedZ = Mathf.Clamp(_rotationDelta.x, -60f, 60f);
|
||||
transform.eulerAngles = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, clampedZ);
|
||||
shakeParent.localEulerAngles = new Vector3(0, 0, clampedZ);
|
||||
}
|
||||
|
||||
protected virtual void UpdateTilt()
|
||||
{
|
||||
if (tiltParent == null)
|
||||
return;
|
||||
|
||||
|
||||
// Save slot index when not dragging for idle animation
|
||||
_savedSlotIndex = _parentDraggable.IsDragging
|
||||
? _savedSlotIndex
|
||||
: _parentDraggable.GetSlotIndex();
|
||||
|
||||
// Idle animation (sine/cosine wobble)
|
||||
// Idle animation (sine/cosine wobble with different frequencies)
|
||||
float idleMultiplier = _parentDraggable.IsHovering ? 0.2f : 1f;
|
||||
float time = Time.time * idleAnimationSpeed + _savedSlotIndex;
|
||||
float sineWobble = Mathf.Sin(time) * idleMultiplier;
|
||||
float cosineWobble = Mathf.Cos(time) * idleMultiplier;
|
||||
|
||||
// Use sine for X wobble, cosine for Y wobble (different phases)
|
||||
float sineWobbleX = Mathf.Sin(time) * idleMultiplier;
|
||||
float cosineWobbleY = Mathf.Cos(time) * idleMultiplier;
|
||||
|
||||
// Use slower cosine for Z rotation wobble (half speed for subtle rotation)
|
||||
float cosineWobbleZ = Mathf.Cos(time * 0.5f) * idleMultiplier * 0.3f; // Much subtler
|
||||
|
||||
// Manual tilt based on pointer position (when hovering)
|
||||
float manualTiltX = 0f;
|
||||
float manualTiltY = 0f;
|
||||
|
||||
if (_parentDraggable.IsHovering && Camera.main != null)
|
||||
if (_parentDraggable.IsHovering)
|
||||
{
|
||||
Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(UnityEngine.Input.mousePosition);
|
||||
Vector3 offset = transform.position - mouseWorldPos;
|
||||
Canvas parentCanvas = _parentDraggable.GetComponentInParent<Canvas>();
|
||||
bool isOverlay = parentCanvas != null && parentCanvas.renderMode == RenderMode.ScreenSpaceOverlay;
|
||||
|
||||
Vector3 mousePos;
|
||||
Vector3 myPos;
|
||||
|
||||
// Get mouse position using new Input System
|
||||
Vector2 mouseScreenPos = Mouse.current != null ? Mouse.current.position.ReadValue() : Vector2.zero;
|
||||
|
||||
if (isOverlay)
|
||||
{
|
||||
// For overlay, use screen coordinates directly
|
||||
mousePos = mouseScreenPos;
|
||||
myPos = GetComponent<RectTransform>() != null
|
||||
? GetComponent<RectTransform>().position
|
||||
: transform.position;
|
||||
}
|
||||
else if (Camera.main != null)
|
||||
{
|
||||
// For WorldSpace/ScreenSpaceCamera, convert to world coords
|
||||
mousePos = Camera.main.ScreenToWorldPoint(mouseScreenPos);
|
||||
myPos = transform.position;
|
||||
}
|
||||
else
|
||||
{
|
||||
mousePos = myPos = Vector3.zero;
|
||||
}
|
||||
|
||||
Vector3 offset = myPos - mousePos;
|
||||
manualTiltX = (offset.y * -1f) * manualTiltAmount;
|
||||
manualTiltY = offset.x * manualTiltAmount;
|
||||
}
|
||||
|
||||
// Combine auto and manual tilt
|
||||
float targetTiltX = manualTiltX + (useIdleAnimation ? sineWobble * autoTiltAmount : 0f);
|
||||
float targetTiltY = manualTiltY + (useIdleAnimation ? cosineWobble * autoTiltAmount : 0f);
|
||||
float targetTiltZ = _parentDraggable.IsDragging ? tiltParent.eulerAngles.z : 0f;
|
||||
// X uses sine wobble, Y uses cosine wobble, Z uses slower cosine for rotation
|
||||
float targetTiltX = manualTiltX + (useIdleAnimation ? sineWobbleX * autoTiltAmount : 0f);
|
||||
float targetTiltY = manualTiltY + (useIdleAnimation ? cosineWobbleY * autoTiltAmount : 0f);
|
||||
float targetTiltZ = _parentDraggable.IsDragging ? tiltParent.localEulerAngles.z : (useIdleAnimation ? cosineWobbleZ * autoTiltAmount : 0f);
|
||||
|
||||
// Lerp to target tilt
|
||||
float lerpX = Mathf.LerpAngle(tiltParent.eulerAngles.x, targetTiltX, tiltSpeed * Time.deltaTime);
|
||||
float lerpY = Mathf.LerpAngle(tiltParent.eulerAngles.y, targetTiltY, tiltSpeed * Time.deltaTime);
|
||||
float lerpZ = Mathf.LerpAngle(tiltParent.eulerAngles.z, targetTiltZ, (tiltSpeed / 2f) * Time.deltaTime);
|
||||
// Lerp to target tilt using LOCAL rotation
|
||||
float lerpX = Mathf.LerpAngle(tiltParent.localEulerAngles.x, targetTiltX, tiltSpeed * Time.deltaTime);
|
||||
float lerpY = Mathf.LerpAngle(tiltParent.localEulerAngles.y, targetTiltY, tiltSpeed * Time.deltaTime);
|
||||
float lerpZ = Mathf.LerpAngle(tiltParent.localEulerAngles.z, targetTiltZ, (tiltSpeed / 2f) * Time.deltaTime);
|
||||
|
||||
tiltParent.eulerAngles = new Vector3(lerpX, lerpY, lerpZ);
|
||||
tiltParent.localEulerAngles = new Vector3(lerpX, lerpY, lerpZ);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -233,6 +354,21 @@ namespace UI.DragAndDrop.Core
|
||||
canvas.overrideSorting = true;
|
||||
}
|
||||
|
||||
// Reset shake parent rotation (movement wobble)
|
||||
if (shakeParent != null)
|
||||
{
|
||||
Tween.LocalRotation(shakeParent, Quaternion.identity, 0.2f, 0f, Tween.EaseOutBack);
|
||||
}
|
||||
|
||||
// Reset tilt parent rotation (idle wobble)
|
||||
if (tiltParent != null)
|
||||
{
|
||||
Tween.LocalRotation(tiltParent, Quaternion.identity, 0.2f, 0f, Tween.EaseOutBack);
|
||||
}
|
||||
|
||||
// Reset rotation delta for fresh movement wobble
|
||||
_rotationDelta = Vector3.zero;
|
||||
|
||||
OnDragStartedVisual();
|
||||
}
|
||||
|
||||
@@ -243,7 +379,24 @@ namespace UI.DragAndDrop.Core
|
||||
canvas.overrideSorting = false;
|
||||
}
|
||||
|
||||
Tween.LocalScale(transform, Vector3.one, scaleTransitionDuration, 0f, Tween.EaseOutBack);
|
||||
// Only reset scale if NOT in a slot (let slots handle their own scaling)
|
||||
if (draggable.CurrentSlot == null)
|
||||
{
|
||||
Tween.LocalScale(transform, Vector3.one, scaleTransitionDuration, 0f, Tween.EaseOutBack);
|
||||
}
|
||||
|
||||
|
||||
// Reset shake parent (movement wobble) to zero for fresh start
|
||||
if (shakeParent != null)
|
||||
{
|
||||
Tween.LocalRotation(shakeParent, Quaternion.identity, 0.3f, 0f, Tween.EaseOutBack);
|
||||
}
|
||||
|
||||
// Reset tilt parent (idle wobble) to zero for fresh start
|
||||
if (tiltParent != null)
|
||||
{
|
||||
Tween.LocalRotation(tiltParent, Quaternion.identity, 0.3f, 0f, Tween.EaseOutBack);
|
||||
}
|
||||
|
||||
OnDragEndedVisual();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user