Skip to content

Commit

Permalink
Xxxx support target align from position
Browse files Browse the repository at this point in the history
A lot of files changed, but they're mostly boilerplate code and changes to the API of the actions.
This PR adds support for using Align Target without moving the aligned target to the pointer position.
Instead, it moves the element from its starting point following the mouse position.
It adds a new boolean property to enable the feature.
In order to achieve this, it's necessary to provide to all actions the current position and the previous position so the action can calculate the delta.

Diffs=
a55f1ffb6 Xxxx support target align from position (#7154)

Co-authored-by: hernan <hernan@rive.app>
  • Loading branch information
bodymovin and bodymovin committed May 1, 2024
1 parent c5c6a96 commit 331c05a
Show file tree
Hide file tree
Showing 20 changed files with 180 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7d0125c9256d329a11844184e6cd1244f3496012
a55f1ffb6cabe9b918fa0b8fd1ad11b4d656ae1c
9 changes: 9 additions & 0 deletions dev/defs/animation/listener_align_target.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@
"string": "targetid"
},
"description": "Identifier used to track the object use as a target fo this listener action."
},
"preserveOffset": {
"type": "bool",
"initialValue": "false",
"key": {
"int": 541,
"string": "preserveoffset"
},
"description": "Whether to preserve offset between mouse position and target position."
}
}
}
4 changes: 3 additions & 1 deletion include/rive/animation/listener_action.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ class ListenerAction : public ListenerActionBase
{
public:
StatusCode import(ImportStack& importStack) override;
virtual void perform(StateMachineInstance* stateMachineInstance, Vec2D position) const = 0;
virtual void perform(StateMachineInstance* stateMachineInstance,
Vec2D position,
Vec2D previousPosition) const = 0;
};
} // namespace rive

Expand Down
4 changes: 3 additions & 1 deletion include/rive/animation/listener_align_target.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ namespace rive
class ListenerAlignTarget : public ListenerAlignTargetBase
{
public:
void perform(StateMachineInstance* stateMachineInstance, Vec2D position) const override;
void perform(StateMachineInstance* stateMachineInstance,
Vec2D position,
Vec2D previousPosition) const override;
};
} // namespace rive

Expand Down
4 changes: 3 additions & 1 deletion include/rive/animation/listener_bool_change.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ class ListenerBoolChange : public ListenerBoolChangeBase
public:
bool validateInputType(const StateMachineInput* input) const override;
bool validateNestedInputType(const NestedInput* input) const override;
void perform(StateMachineInstance* stateMachineInstance, Vec2D position) const override;
void perform(StateMachineInstance* stateMachineInstance,
Vec2D position,
Vec2D previousPosition) const override;
};
} // namespace rive

Expand Down
4 changes: 3 additions & 1 deletion include/rive/animation/listener_fire_event.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ namespace rive
class ListenerFireEvent : public ListenerFireEventBase
{
public:
void perform(StateMachineInstance* stateMachineInstance, Vec2D position) const override;
void perform(StateMachineInstance* stateMachineInstance,
Vec2D position,
Vec2D previousPosition) const override;
};
} // namespace rive

Expand Down
4 changes: 3 additions & 1 deletion include/rive/animation/listener_number_change.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ class ListenerNumberChange : public ListenerNumberChangeBase
public:
bool validateInputType(const StateMachineInput* input) const override;
bool validateNestedInputType(const NestedInput* input) const override;
void perform(StateMachineInstance* stateMachineInstance, Vec2D position) const override;
void perform(StateMachineInstance* stateMachineInstance,
Vec2D position,
Vec2D previousPosition) const override;
};
} // namespace rive

Expand Down
4 changes: 3 additions & 1 deletion include/rive/animation/listener_trigger_change.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ class ListenerTriggerChange : public ListenerTriggerChangeBase
public:
bool validateInputType(const StateMachineInput* input) const override;
bool validateNestedInputType(const NestedInput* input) const override;
void perform(StateMachineInstance* stateMachineInstance, Vec2D position) const override;
void perform(StateMachineInstance* stateMachineInstance,
Vec2D position,
Vec2D previousPosition) const override;
};
} // namespace rive

Expand Down
4 changes: 3 additions & 1 deletion include/rive/animation/state_machine_listener.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ class StateMachineListener : public StateMachineListenerBase
StatusCode onAddedClean(CoreContext* context) override;

const std::vector<uint32_t>& hitShapeIds() const { return m_HitShapesIds; }
void performChanges(StateMachineInstance* stateMachineInstance, Vec2D position) const;
void performChanges(StateMachineInstance* stateMachineInstance,
Vec2D position,
Vec2D previousPosition) const;
};
} // namespace rive

Expand Down
19 changes: 19 additions & 0 deletions include/rive/generated/animation/listener_align_target_base.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef _RIVE_LISTENER_ALIGN_TARGET_BASE_HPP_
#define _RIVE_LISTENER_ALIGN_TARGET_BASE_HPP_
#include "rive/animation/listener_action.hpp"
#include "rive/core/field_types/core_bool_type.hpp"
#include "rive/core/field_types/core_uint_type.hpp"
namespace rive
{
Expand Down Expand Up @@ -29,9 +30,11 @@ class ListenerAlignTargetBase : public ListenerAction
uint16_t coreType() const override { return typeKey; }

static const uint16_t targetIdPropertyKey = 240;
static const uint16_t preserveOffsetPropertyKey = 541;

private:
uint32_t m_TargetId = 0;
bool m_PreserveOffset = false;

public:
inline uint32_t targetId() const { return m_TargetId; }
Expand All @@ -45,10 +48,22 @@ class ListenerAlignTargetBase : public ListenerAction
targetIdChanged();
}

inline bool preserveOffset() const { return m_PreserveOffset; }
void preserveOffset(bool value)
{
if (m_PreserveOffset == value)
{
return;
}
m_PreserveOffset = value;
preserveOffsetChanged();
}

Core* clone() const override;
void copy(const ListenerAlignTargetBase& object)
{
m_TargetId = object.m_TargetId;
m_PreserveOffset = object.m_PreserveOffset;
ListenerAction::copy(object);
}

Expand All @@ -59,12 +74,16 @@ class ListenerAlignTargetBase : public ListenerAction
case targetIdPropertyKey:
m_TargetId = CoreUintType::deserialize(reader);
return true;
case preserveOffsetPropertyKey:
m_PreserveOffset = CoreBoolType::deserialize(reader);
return true;
}
return ListenerAction::deserialize(propertyKey, reader);
}

protected:
virtual void targetIdChanged() {}
virtual void preserveOffsetChanged() {}
};
} // namespace rive

Expand Down
6 changes: 6 additions & 0 deletions include/rive/generated/core_registry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,9 @@ class CoreRegistry
case KeyFrameBoolBase::valuePropertyKey:
object->as<KeyFrameBoolBase>()->value(value);
break;
case ListenerAlignTargetBase::preserveOffsetPropertyKey:
object->as<ListenerAlignTargetBase>()->preserveOffset(value);
break;
case NestedBoolBase::nestedValuePropertyKey:
object->as<NestedBoolBase>()->nestedValue(value);
break;
Expand Down Expand Up @@ -1720,6 +1723,8 @@ class CoreRegistry
return object->as<NestedSimpleAnimationBase>()->isPlaying();
case KeyFrameBoolBase::valuePropertyKey:
return object->as<KeyFrameBoolBase>()->value();
case ListenerAlignTargetBase::preserveOffsetPropertyKey:
return object->as<ListenerAlignTargetBase>()->preserveOffset();
case NestedBoolBase::nestedValuePropertyKey:
return object->as<NestedBoolBase>()->nestedValue();
case LinearAnimationBase::enableWorkAreaPropertyKey:
Expand Down Expand Up @@ -2013,6 +2018,7 @@ class CoreRegistry
case FollowPathConstraintBase::offsetPropertyKey:
case NestedSimpleAnimationBase::isPlayingPropertyKey:
case KeyFrameBoolBase::valuePropertyKey:
case ListenerAlignTargetBase::preserveOffsetPropertyKey:
case NestedBoolBase::nestedValuePropertyKey:
case LinearAnimationBase::enableWorkAreaPropertyKey:
case LinearAnimationBase::quantizePropertyKey:
Expand Down
20 changes: 16 additions & 4 deletions src/animation/listener_align_target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@

using namespace rive;

void ListenerAlignTarget::perform(StateMachineInstance* stateMachineInstance, Vec2D position) const
void ListenerAlignTarget::perform(StateMachineInstance* stateMachineInstance,
Vec2D position,
Vec2D previousPosition) const
{
auto coreTarget = stateMachineInstance->artboard()->resolve(targetId());
if (coreTarget == nullptr || !coreTarget->is<Node>())
Expand All @@ -19,8 +21,18 @@ void ListenerAlignTarget::perform(StateMachineInstance* stateMachineInstance, Ve
{
return;
}
if (preserveOffset())
{

auto localPosition = inverse * position;
target->x(localPosition.x);
target->y(localPosition.y);
auto localPosition = inverse * position;
auto prevLocalPosition = inverse * previousPosition;
target->x(target->x() + localPosition.x - prevLocalPosition.x);
target->y(target->y() + localPosition.y - prevLocalPosition.y);
}
else
{
auto localPosition = inverse * position;
target->x(localPosition.x);
target->y(localPosition.y);
}
}
4 changes: 3 additions & 1 deletion src/animation/listener_bool_change.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ bool ListenerBoolChange::validateNestedInputType(const NestedInput* input) const
return input == nullptr || input->is<NestedBool>();
}

void ListenerBoolChange::perform(StateMachineInstance* stateMachineInstance, Vec2D position) const
void ListenerBoolChange::perform(StateMachineInstance* stateMachineInstance,
Vec2D position,
Vec2D previousPosition) const
{
if (nestedInputId() != Core::emptyId)
{
Expand Down
4 changes: 3 additions & 1 deletion src/animation/listener_fire_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

using namespace rive;

void ListenerFireEvent::perform(StateMachineInstance* stateMachineInstance, Vec2D position) const
void ListenerFireEvent::perform(StateMachineInstance* stateMachineInstance,
Vec2D position,
Vec2D previousPosition) const
{
auto coreEvent = stateMachineInstance->artboard()->resolve(eventId());
if (coreEvent == nullptr || !coreEvent->is<Event>())
Expand Down
4 changes: 3 additions & 1 deletion src/animation/listener_number_change.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ bool ListenerNumberChange::validateNestedInputType(const NestedInput* input) con
return input == nullptr || input->is<NestedNumber>();
}

void ListenerNumberChange::perform(StateMachineInstance* stateMachineInstance, Vec2D position) const
void ListenerNumberChange::perform(StateMachineInstance* stateMachineInstance,
Vec2D position,
Vec2D previousPosition) const
{
if (nestedInputId() != Core::emptyId)
{
Expand Down
3 changes: 2 additions & 1 deletion src/animation/listener_trigger_change.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ bool ListenerTriggerChange::validateNestedInputType(const NestedInput* input) co
}

void ListenerTriggerChange::perform(StateMachineInstance* stateMachineInstance,
Vec2D position) const
Vec2D position,
Vec2D previousPosition) const
{
if (nestedInputId() != Core::emptyId)
{
Expand Down
16 changes: 12 additions & 4 deletions src/animation/state_machine_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ class HitShape : public HitComponent
{}
bool isHovered = false;
float hitRadius = 2;
Vec2D previousPosition;
std::vector<const StateMachineListener*> listeners;
HitResult processEvent(Vec2D position, ListenerType hitType, bool canHit) override
{
Expand All @@ -423,6 +424,11 @@ class HitShape : public HitComponent
bool isOver = canHit ? shape->hitTest(hitArea) : false;
bool hoverChange = isHovered != isOver;
isHovered = isOver;
if (hoverChange && isHovered)
{
previousPosition.x = position.x;
previousPosition.y = position.y;
}

// // iterate all listeners associated with this hit shape
for (auto listener : listeners)
Expand All @@ -433,21 +439,23 @@ class HitShape : public HitComponent
{
if (isOver && listener->listenerType() == ListenerType::enter)
{
listener->performChanges(m_stateMachineInstance, position);
listener->performChanges(m_stateMachineInstance, position, previousPosition);
m_stateMachineInstance->markNeedsAdvance();
}
else if (!isOver && listener->listenerType() == ListenerType::exit)
{
listener->performChanges(m_stateMachineInstance, position);
listener->performChanges(m_stateMachineInstance, position, previousPosition);
m_stateMachineInstance->markNeedsAdvance();
}
}
if (isOver && hitType == listener->listenerType())
{
listener->performChanges(m_stateMachineInstance, position);
listener->performChanges(m_stateMachineInstance, position, previousPosition);
m_stateMachineInstance->markNeedsAdvance();
}
}
previousPosition.x = position.x;
previousPosition.y = position.y;
return isOver ? shape->isTargetOpaque() ? HitResult::hitOpaque : HitResult::hit
: HitResult::none;
}
Expand Down Expand Up @@ -891,7 +899,7 @@ void StateMachineInstance::notifyEventListeners(const std::vector<EventReport>&
auto listenerEvent = sourceArtboard->resolve(listener->eventId());
if (listenerEvent == event.event())
{
listener->performChanges(this, Vec2D());
listener->performChanges(this, Vec2D(), Vec2D());
break;
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/animation/state_machine_listener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,11 @@ StatusCode StateMachineListener::onAddedClean(CoreContext* context)
}

void StateMachineListener::performChanges(StateMachineInstance* stateMachineInstance,
Vec2D position) const
Vec2D position,
Vec2D previousPosition) const
{
for (auto& action : m_Actions)
{
action->perform(stateMachineInstance, position);
action->perform(stateMachineInstance, position, previousPosition);
}
}
Binary file added test/assets/align_target.riv
Binary file not shown.
Loading

0 comments on commit 331c05a

Please sign in to comment.