mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 13:11:19 +01:00
feature: scripted listener actions (#11468) f3a89390cb
Co-authored-by: hernan <hernan@rive.app>
This commit is contained in:
@@ -1 +1 @@
|
||||
9112280455e25db4649d446601f443c763151649
|
||||
f3a89390cb428a5ea841d21de91f9cb2adc312df
|
||||
|
||||
20
dev/defs/animation/scripted_listener_action.json
Normal file
20
dev/defs/animation/scripted_listener_action.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "ScriptedListenerAction",
|
||||
"key": {
|
||||
"int": 646,
|
||||
"string": "scriptedlisteneraction"
|
||||
},
|
||||
"extends": "animation/listener_action.json",
|
||||
"properties": {
|
||||
"scriptAssetId": {
|
||||
"type": "Id",
|
||||
"typeRuntime": "uint",
|
||||
"initialValue": "Core.missingId",
|
||||
"initialValueRuntime": "-1",
|
||||
"key": {
|
||||
"int": 930,
|
||||
"string": "scriptassetid"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,8 @@ public:
|
||||
StatusCode import(ImportStack& importStack) override;
|
||||
virtual void perform(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const = 0;
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const = 0;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ class ListenerAlignTarget : public ListenerAlignTargetBase
|
||||
public:
|
||||
void perform(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const override;
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const override;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ public:
|
||||
bool validateNestedInputType(const NestedInput* input) const override;
|
||||
void perform(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const override;
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const override;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ class ListenerFireEvent : public ListenerFireEventBase
|
||||
public:
|
||||
void perform(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const override;
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const override;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ public:
|
||||
bool validateNestedInputType(const NestedInput* input) const override;
|
||||
void perform(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const override;
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const override;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ public:
|
||||
bool validateNestedInputType(const NestedInput* input) const override;
|
||||
void perform(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const override;
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const override;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ public:
|
||||
~ListenerViewModelChange();
|
||||
void perform(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const override;
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const override;
|
||||
StatusCode import(ImportStack& importStack) override;
|
||||
|
||||
private:
|
||||
|
||||
36
include/rive/animation/scripted_listener_action.hpp
Normal file
36
include/rive/animation/scripted_listener_action.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef _RIVE_SCRIPTED_LISTENER_ACTION_HPP_
|
||||
#define _RIVE_SCRIPTED_LISTENER_ACTION_HPP_
|
||||
#include "rive/generated/animation/scripted_listener_action_base.hpp"
|
||||
#include "rive/scripted/scripted_object.hpp"
|
||||
#include <stdio.h>
|
||||
namespace rive
|
||||
{
|
||||
class ScriptedListenerAction : public ScriptedListenerActionBase,
|
||||
public ScriptedObject
|
||||
{
|
||||
public:
|
||||
void perform(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const override;
|
||||
void performStateful(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const;
|
||||
|
||||
uint32_t assetId() override { return scriptAssetId(); }
|
||||
bool addScriptedDirt(ComponentDirt value, bool recurse = false) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ScriptProtocol scriptProtocol() override
|
||||
{
|
||||
return ScriptProtocol::listenerAction;
|
||||
}
|
||||
Component* component() override { return nullptr; }
|
||||
StatusCode import(ImportStack& importStack) override;
|
||||
Core* clone() const override;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
@@ -40,6 +40,7 @@ class DataBind;
|
||||
class BindableProperty;
|
||||
class HitDrawable;
|
||||
class ListenerViewModel;
|
||||
class ScriptedListenerAction;
|
||||
typedef void (*DataBindChanged)();
|
||||
|
||||
#ifdef WITH_RIVE_TOOLS
|
||||
@@ -205,6 +206,7 @@ public:
|
||||
bool hasListeners() { return m_hitComponents.size() > 0; }
|
||||
void clearDataContext();
|
||||
void internalDataContext(DataContext* dataContext);
|
||||
ScriptedObject* scriptedObject(const ScriptedObject*);
|
||||
#ifdef TESTING
|
||||
size_t hitComponentsCount() { return m_hitComponents.size(); };
|
||||
HitComponent* hitComponent(size_t index)
|
||||
@@ -238,6 +240,8 @@ private:
|
||||
std::vector<ListenerViewModel*> m_reportingListenerViewModels;
|
||||
std::unordered_map<BindableProperty*, BindableProperty*>
|
||||
m_bindablePropertyInstances;
|
||||
std::unordered_map<const ScriptedObject*, ScriptedObject*>
|
||||
m_scriptedListenerActionsMap;
|
||||
std::unordered_map<BindableProperty*, DataBind*>
|
||||
m_bindableDataBindsToTarget;
|
||||
std::unordered_map<BindableProperty*, DataBind*>
|
||||
|
||||
@@ -31,7 +31,8 @@ public:
|
||||
|
||||
void performChanges(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const;
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const;
|
||||
void decodeViewModelPathIds(Span<const uint8_t> value) override;
|
||||
void copyViewModelPathIds(const StateMachineListenerBase& object) override;
|
||||
std::vector<uint32_t> viewModelPathIdsBuffer() const;
|
||||
|
||||
@@ -25,7 +25,8 @@ enum ScriptProtocol
|
||||
node,
|
||||
layout,
|
||||
converter,
|
||||
pathEffect
|
||||
pathEffect,
|
||||
listenerAction
|
||||
};
|
||||
|
||||
#ifdef WITH_RIVE_SCRIPTING
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef _RIVE_SCRIPTED_LISTENER_ACTION_BASE_HPP_
|
||||
#define _RIVE_SCRIPTED_LISTENER_ACTION_BASE_HPP_
|
||||
#include "rive/animation/listener_action.hpp"
|
||||
#include "rive/core/field_types/core_uint_type.hpp"
|
||||
namespace rive
|
||||
{
|
||||
class ScriptedListenerActionBase : public ListenerAction
|
||||
{
|
||||
protected:
|
||||
typedef ListenerAction Super;
|
||||
|
||||
public:
|
||||
static const uint16_t typeKey = 646;
|
||||
|
||||
/// Helper to quickly determine if a core object extends another without
|
||||
/// RTTI at runtime.
|
||||
bool isTypeOf(uint16_t typeKey) const override
|
||||
{
|
||||
switch (typeKey)
|
||||
{
|
||||
case ScriptedListenerActionBase::typeKey:
|
||||
case ListenerActionBase::typeKey:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t coreType() const override { return typeKey; }
|
||||
|
||||
static const uint16_t scriptAssetIdPropertyKey = 930;
|
||||
|
||||
protected:
|
||||
uint32_t m_ScriptAssetId = -1;
|
||||
|
||||
public:
|
||||
inline uint32_t scriptAssetId() const { return m_ScriptAssetId; }
|
||||
void scriptAssetId(uint32_t value)
|
||||
{
|
||||
if (m_ScriptAssetId == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_ScriptAssetId = value;
|
||||
scriptAssetIdChanged();
|
||||
}
|
||||
|
||||
Core* clone() const override;
|
||||
void copy(const ScriptedListenerActionBase& object)
|
||||
{
|
||||
m_ScriptAssetId = object.m_ScriptAssetId;
|
||||
ListenerAction::copy(object);
|
||||
}
|
||||
|
||||
bool deserialize(uint16_t propertyKey, BinaryReader& reader) override
|
||||
{
|
||||
switch (propertyKey)
|
||||
{
|
||||
case scriptAssetIdPropertyKey:
|
||||
m_ScriptAssetId = CoreUintType::deserialize(reader);
|
||||
return true;
|
||||
}
|
||||
return ListenerAction::deserialize(propertyKey, reader);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void scriptAssetIdChanged() {}
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "rive/animation/nested_simple_animation.hpp"
|
||||
#include "rive/animation/nested_state_machine.hpp"
|
||||
#include "rive/animation/nested_trigger.hpp"
|
||||
#include "rive/animation/scripted_listener_action.hpp"
|
||||
#include "rive/animation/state_machine.hpp"
|
||||
#include "rive/animation/state_machine_bool.hpp"
|
||||
#include "rive/animation/state_machine_component.hpp"
|
||||
@@ -477,6 +478,8 @@ public:
|
||||
return new AnimationState();
|
||||
case NestedTriggerBase::typeKey:
|
||||
return new NestedTrigger();
|
||||
case ScriptedListenerActionBase::typeKey:
|
||||
return new ScriptedListenerAction();
|
||||
case KeyedObjectBase::typeKey:
|
||||
return new KeyedObject();
|
||||
case AnimationBase::typeKey:
|
||||
@@ -1194,6 +1197,9 @@ public:
|
||||
case NestedInputBase::inputIdPropertyKey:
|
||||
object->as<NestedInputBase>()->inputId(value);
|
||||
break;
|
||||
case ScriptedListenerActionBase::scriptAssetIdPropertyKey:
|
||||
object->as<ScriptedListenerActionBase>()->scriptAssetId(value);
|
||||
break;
|
||||
case KeyedObjectBase::objectIdPropertyKey:
|
||||
object->as<KeyedObjectBase>()->objectId(value);
|
||||
break;
|
||||
@@ -2737,6 +2743,9 @@ public:
|
||||
return object->as<AnimationStateBase>()->animationId();
|
||||
case NestedInputBase::inputIdPropertyKey:
|
||||
return object->as<NestedInputBase>()->inputId();
|
||||
case ScriptedListenerActionBase::scriptAssetIdPropertyKey:
|
||||
return object->as<ScriptedListenerActionBase>()
|
||||
->scriptAssetId();
|
||||
case KeyedObjectBase::objectIdPropertyKey:
|
||||
return object->as<KeyedObjectBase>()->objectId();
|
||||
case BlendAnimationBase::animationIdPropertyKey:
|
||||
@@ -3725,6 +3734,7 @@ public:
|
||||
case ListenerInputChangeBase::nestedInputIdPropertyKey:
|
||||
case AnimationStateBase::animationIdPropertyKey:
|
||||
case NestedInputBase::inputIdPropertyKey:
|
||||
case ScriptedListenerActionBase::scriptAssetIdPropertyKey:
|
||||
case KeyedObjectBase::objectIdPropertyKey:
|
||||
case BlendAnimationBase::animationIdPropertyKey:
|
||||
case BlendAnimationDirectBase::inputIdPropertyKey:
|
||||
@@ -4377,6 +4387,8 @@ public:
|
||||
return object->is<AnimationStateBase>();
|
||||
case NestedInputBase::inputIdPropertyKey:
|
||||
return object->is<NestedInputBase>();
|
||||
case ScriptedListenerActionBase::scriptAssetIdPropertyKey:
|
||||
return object->is<ScriptedListenerActionBase>();
|
||||
case KeyedObjectBase::objectIdPropertyKey:
|
||||
return object->is<KeyedObjectBase>();
|
||||
case BlendAnimationBase::animationIdPropertyKey:
|
||||
|
||||
@@ -33,6 +33,8 @@ protected:
|
||||
#ifdef WITH_RIVE_TOOLS
|
||||
bool hasValidVM();
|
||||
#endif
|
||||
private:
|
||||
DataContext* m_dataContext = nullptr;
|
||||
|
||||
public:
|
||||
virtual ~ScriptedObject() { scriptDispose(); }
|
||||
@@ -48,7 +50,8 @@ public:
|
||||
void scriptUpdate();
|
||||
void reinit();
|
||||
virtual void markNeedsUpdate();
|
||||
virtual DataContext* dataContext() { return nullptr; }
|
||||
virtual DataContext* dataContext() { return m_dataContext; }
|
||||
void dataContext(DataContext* value) { m_dataContext = value; }
|
||||
#ifdef WITH_RIVE_SCRIPTING
|
||||
virtual bool scriptInit(lua_State* state);
|
||||
lua_State* state() { return m_state; }
|
||||
|
||||
@@ -7,7 +7,8 @@ using namespace rive;
|
||||
|
||||
void ListenerAlignTarget::perform(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const
|
||||
{
|
||||
auto coreTarget = stateMachineInstance->artboard()->resolve(targetId());
|
||||
if (coreTarget == nullptr || !coreTarget->is<Node>())
|
||||
|
||||
@@ -26,7 +26,8 @@ bool ListenerBoolChange::validateNestedInputType(const NestedInput* input) const
|
||||
|
||||
void ListenerBoolChange::perform(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const
|
||||
{
|
||||
if (nestedInputId() != Core::emptyId)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,8 @@ using namespace rive;
|
||||
|
||||
void ListenerFireEvent::perform(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const
|
||||
{
|
||||
auto coreEvent = stateMachineInstance->artboard()->resolve(eventId());
|
||||
if (coreEvent == nullptr || !coreEvent->is<Event>())
|
||||
|
||||
@@ -29,7 +29,8 @@ bool ListenerNumberChange::validateNestedInputType(
|
||||
|
||||
void ListenerNumberChange::perform(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const
|
||||
{
|
||||
if (nestedInputId() != Core::emptyId)
|
||||
{
|
||||
|
||||
@@ -30,7 +30,8 @@ bool ListenerTriggerChange::validateNestedInputType(
|
||||
|
||||
void ListenerTriggerChange::perform(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const
|
||||
{
|
||||
if (nestedInputId() != Core::emptyId)
|
||||
{
|
||||
|
||||
@@ -37,7 +37,8 @@ StatusCode ListenerViewModelChange::import(ImportStack& importStack)
|
||||
void ListenerViewModelChange::perform(
|
||||
StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const
|
||||
{
|
||||
// Get the bindable property instance from the state machine instance
|
||||
// context
|
||||
|
||||
86
src/animation/scripted_listener_action.cpp
Normal file
86
src/animation/scripted_listener_action.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "rive/animation/scripted_listener_action.hpp"
|
||||
#include "rive/animation/state_machine_instance.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
// Note: performStateful is the actual instance of the ScriptedListenerAction
|
||||
// that will run the script. perform itself will look for the map between the
|
||||
// stateless and the stateful instances of this class.
|
||||
void ScriptedListenerAction::performStateful(
|
||||
StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const
|
||||
{
|
||||
#ifdef WITH_RIVE_SCRIPTING
|
||||
if (m_state == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Stack: []
|
||||
rive_lua_pushRef(m_state, m_self);
|
||||
// Stack: [self]
|
||||
lua_getfield(m_state, -1, "perform");
|
||||
|
||||
// Stack: [self, field]
|
||||
lua_pushvalue(m_state, -2);
|
||||
|
||||
// Stack: [self, field, self]
|
||||
lua_newrive<ScriptedPointerEvent>(m_state, pointerId, position);
|
||||
|
||||
// Stack: [self, field, self, pointerEvent]
|
||||
if (static_cast<lua_Status>(rive_lua_pcall(m_state, 2, 0)) == LUA_OK)
|
||||
{
|
||||
rive_lua_pop(m_state, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
rive_lua_pop(m_state, 2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ScriptedListenerAction::perform(StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const
|
||||
{
|
||||
#ifdef WITH_RIVE_SCRIPTING
|
||||
auto scriptedObject = stateMachineInstance->scriptedObject(this);
|
||||
if (scriptedObject != nullptr)
|
||||
{
|
||||
auto statefulListenerAction =
|
||||
static_cast<ScriptedListenerAction*>(scriptedObject);
|
||||
statefulListenerAction->performStateful(stateMachineInstance,
|
||||
position,
|
||||
previousPosition,
|
||||
pointerId);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
StatusCode ScriptedListenerAction::import(ImportStack& importStack)
|
||||
{
|
||||
auto result = registerReferencer(importStack);
|
||||
if (result != StatusCode::Ok)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return Super::import(importStack);
|
||||
}
|
||||
|
||||
Core* ScriptedListenerAction::clone() const
|
||||
{
|
||||
ScriptedListenerAction* twin =
|
||||
ScriptedListenerActionBase::clone()->as<ScriptedListenerAction>();
|
||||
if (m_fileAsset != nullptr)
|
||||
{
|
||||
twin->setAsset(m_fileAsset);
|
||||
}
|
||||
for (auto prop : m_customProperties)
|
||||
{
|
||||
auto clonedValue = prop->clone()->as<CustomProperty>();
|
||||
twin->addProperty(clonedValue);
|
||||
}
|
||||
return twin;
|
||||
}
|
||||
@@ -19,6 +19,8 @@
|
||||
#include "rive/animation/state_machine_trigger.hpp"
|
||||
#include "rive/animation/state_machine.hpp"
|
||||
#include "rive/animation/state_transition.hpp"
|
||||
#include "rive/animation/listener_action.hpp"
|
||||
#include "rive/animation/scripted_listener_action.hpp"
|
||||
#include "rive/animation/transition_condition.hpp"
|
||||
#include "rive/animation/transition_comparator.hpp"
|
||||
#include "rive/animation/transition_property_viewmodel_comparator.hpp"
|
||||
@@ -1480,9 +1482,41 @@ StateMachineInstance::StateMachineInstance(const StateMachine* machine,
|
||||
this);
|
||||
m_hitComponents.push_back(std::move(hc));
|
||||
}
|
||||
// Initialize local instances of ScriptedListenerActions
|
||||
for (std::size_t i = 0; i < machine->listenerCount(); i++)
|
||||
{
|
||||
auto listener = machine->listener(i);
|
||||
|
||||
for (std::size_t j = 0; j < listener->actionCount(); j++)
|
||||
{
|
||||
auto action = listener->action(j);
|
||||
if (action->is<ScriptedListenerAction>())
|
||||
{
|
||||
auto scriptedListenerAction =
|
||||
action->as<ScriptedListenerAction>();
|
||||
auto scriptedListenerActionClone =
|
||||
static_cast<ScriptedListenerAction*>(
|
||||
scriptedListenerAction->clone());
|
||||
scriptedListenerActionClone->reinit();
|
||||
m_scriptedListenerActionsMap[scriptedListenerAction] =
|
||||
scriptedListenerActionClone;
|
||||
}
|
||||
}
|
||||
}
|
||||
sortHitComponents();
|
||||
}
|
||||
|
||||
ScriptedObject* StateMachineInstance::scriptedObject(
|
||||
const ScriptedObject* source)
|
||||
{
|
||||
auto itr = m_scriptedListenerActionsMap.find(source);
|
||||
if (itr != m_scriptedListenerActionsMap.end())
|
||||
{
|
||||
return itr->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StateMachineInstance::~StateMachineInstance()
|
||||
{
|
||||
unbind();
|
||||
@@ -1506,6 +1540,12 @@ StateMachineInstance::~StateMachineInstance()
|
||||
delete listenerViewModel;
|
||||
}
|
||||
m_bindablePropertyInstances.clear();
|
||||
for (auto& pair : m_scriptedListenerActionsMap)
|
||||
{
|
||||
delete pair.second;
|
||||
pair.second = nullptr;
|
||||
}
|
||||
m_scriptedListenerActionsMap.clear();
|
||||
}
|
||||
|
||||
void StateMachineInstance::removeEventListeners()
|
||||
@@ -1816,6 +1856,10 @@ void StateMachineInstance::internalDataContext(DataContext* dataContext)
|
||||
{
|
||||
listenerViewModel->bindFromContext(dataContext);
|
||||
}
|
||||
for (auto& scriptedObjectItr : m_scriptedListenerActionsMap)
|
||||
{
|
||||
scriptedObjectItr.second->dataContext(dataContext);
|
||||
}
|
||||
}
|
||||
|
||||
void StateMachineInstance::rebind()
|
||||
@@ -1955,7 +1999,8 @@ void StateMachineInstance::notifyListenerViewModels(
|
||||
{
|
||||
listenerViewModel->listener()->performChanges(this,
|
||||
Vec2D(),
|
||||
Vec2D());
|
||||
Vec2D(),
|
||||
0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2011,7 +2056,7 @@ void StateMachineInstance::notifyEventListeners(
|
||||
sourceArtboard->resolve(listener->eventId());
|
||||
if (listenerEvent == event.event())
|
||||
{
|
||||
listener->performChanges(this, Vec2D(), Vec2D());
|
||||
listener->performChanges(this, Vec2D(), Vec2D(), 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,11 +44,15 @@ const ListenerAction* StateMachineListener::action(size_t index) const
|
||||
void StateMachineListener::performChanges(
|
||||
StateMachineInstance* stateMachineInstance,
|
||||
Vec2D position,
|
||||
Vec2D previousPosition) const
|
||||
Vec2D previousPosition,
|
||||
int pointerId) const
|
||||
{
|
||||
for (auto& action : m_actions)
|
||||
{
|
||||
action->perform(stateMachineInstance, position, previousPosition);
|
||||
action->perform(stateMachineInstance,
|
||||
position,
|
||||
previousPosition,
|
||||
pointerId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,8 @@ bool OptionalScriptedMethods::verifyImplementation(ScriptedObject* object,
|
||||
if (scriptProtocol == ScriptProtocol::node ||
|
||||
scriptProtocol == ScriptProtocol::layout ||
|
||||
scriptProtocol == ScriptProtocol::converter ||
|
||||
scriptProtocol == ScriptProtocol::pathEffect)
|
||||
scriptProtocol == ScriptProtocol::pathEffect ||
|
||||
scriptProtocol == ScriptProtocol::listenerAction)
|
||||
{
|
||||
if (static_cast<lua_Type>(lua_getfield(state, -1, "update")) ==
|
||||
LUA_TFUNCTION)
|
||||
|
||||
11
src/generated/animation/scripted_listener_action_base.cpp
Normal file
11
src/generated/animation/scripted_listener_action_base.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "rive/generated/animation/scripted_listener_action_base.hpp"
|
||||
#include "rive/animation/scripted_listener_action.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
Core* ScriptedListenerActionBase::clone() const
|
||||
{
|
||||
auto cloned = new ScriptedListenerAction();
|
||||
cloned->copy(*this);
|
||||
return cloned;
|
||||
}
|
||||
@@ -191,7 +191,8 @@ ProcessEventResult ListenerGroup::processEvent(
|
||||
_listener->performChanges(
|
||||
stateMachineInstance,
|
||||
position,
|
||||
Vec2D(previousPosition->x, previousPosition->y));
|
||||
Vec2D(previousPosition->x, previousPosition->y),
|
||||
pointerId);
|
||||
stateMachineInstance->markNeedsAdvance();
|
||||
consume();
|
||||
}
|
||||
@@ -206,7 +207,8 @@ ProcessEventResult ListenerGroup::processEvent(
|
||||
_listener->performChanges(
|
||||
stateMachineInstance,
|
||||
position,
|
||||
Vec2D(previousPosition->x, previousPosition->y));
|
||||
Vec2D(previousPosition->x, previousPosition->y),
|
||||
pointerId);
|
||||
stateMachineInstance->markNeedsAdvance();
|
||||
consume();
|
||||
}
|
||||
@@ -221,7 +223,8 @@ ProcessEventResult ListenerGroup::processEvent(
|
||||
_listener->performChanges(
|
||||
stateMachineInstance,
|
||||
position,
|
||||
Vec2D(previousPosition->x, previousPosition->y));
|
||||
Vec2D(previousPosition->x, previousPosition->y),
|
||||
pointerId);
|
||||
stateMachineInstance->markNeedsAdvance();
|
||||
if (!m_hasDragged)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,14 @@ static int viewmodel_new(lua_State* L)
|
||||
ViewModel* viewModel = (ViewModel*)lua_touserdata(L, lua_upvalueindex(1));
|
||||
if (viewModel)
|
||||
{
|
||||
|
||||
#ifdef WITH_RIVE_TOOLS
|
||||
viewModel->file()->triggerViewModelCreatedCallback(true);
|
||||
#endif
|
||||
auto instance = viewModel->createInstance();
|
||||
#ifdef WITH_RIVE_TOOLS
|
||||
viewModel->file()->triggerViewModelCreatedCallback(false);
|
||||
#endif
|
||||
lua_newrive<ScriptedViewModel>(L, L, ref_rcp(viewModel), instance);
|
||||
return 1;
|
||||
}
|
||||
|
||||
BIN
tests/unit_tests/assets/scripted_listener_action.riv
Normal file
BIN
tests/unit_tests/assets/scripted_listener_action.riv
Normal file
Binary file not shown.
@@ -0,0 +1,46 @@
|
||||
|
||||
#include "catch.hpp"
|
||||
#include "scripting_test_utilities.hpp"
|
||||
#include "rive/animation/state_machine_instance.hpp"
|
||||
#include "rive/lua/rive_lua_libs.hpp"
|
||||
#include "rive/viewmodel/viewmodel_instance_string.hpp"
|
||||
#include "rive_file_reader.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
TEST_CASE("scripted listener action", "[silver]")
|
||||
{
|
||||
rive::SerializingFactory silver;
|
||||
auto file = ReadRiveFile("assets/scripted_listener_action.riv", &silver);
|
||||
auto artboard = file->artboardDefault();
|
||||
|
||||
silver.frameSize(artboard->width(), artboard->height());
|
||||
REQUIRE(artboard != nullptr);
|
||||
auto stateMachine = artboard->stateMachineAt(0);
|
||||
|
||||
auto vmi = file->createViewModelInstance(artboard.get());
|
||||
stateMachine->bindViewModelInstance(vmi);
|
||||
stateMachine->advanceAndApply(0.1f);
|
||||
|
||||
auto renderer = silver.makeRenderer();
|
||||
artboard->draw(renderer.get());
|
||||
|
||||
silver.addFrame();
|
||||
|
||||
stateMachine->pointerDown(rive::Vec2D(200.0f, 20.0f), 1);
|
||||
stateMachine->pointerUp(rive::Vec2D(200.0f, 20.0f), 1);
|
||||
stateMachine->advanceAndApply(0.016f);
|
||||
artboard->draw(renderer.get());
|
||||
|
||||
stateMachine->pointerDown(rive::Vec2D(300.0f, 20.0f), 2);
|
||||
stateMachine->pointerUp(rive::Vec2D(300.0f, 20.0f), 2);
|
||||
stateMachine->advanceAndApply(0.016f);
|
||||
artboard->draw(renderer.get());
|
||||
|
||||
stateMachine->pointerDown(rive::Vec2D(400.0f, 20.0f), 3);
|
||||
stateMachine->pointerUp(rive::Vec2D(400.0f, 20.0f), 3);
|
||||
stateMachine->advanceAndApply(0.016f);
|
||||
artboard->draw(renderer.get());
|
||||
|
||||
CHECK(silver.matches("scripted_listener_action"));
|
||||
}
|
||||
BIN
tests/unit_tests/silvers/scripted_listener_action.sriv
Normal file
BIN
tests/unit_tests/silvers/scripted_listener_action.sriv
Normal file
Binary file not shown.
Reference in New Issue
Block a user