From 7a06c7404ce4422c5c6be7c986b95d408b840073 Mon Sep 17 00:00:00 2001 From: luigi-rosso Date: Mon, 14 Aug 2023 19:16:17 +0000 Subject: [PATCH] Event triggering Explores an API for triggering events and querying them at runtime. For Flutter we expose an onEvent callback that you can add a callback to on the StateMachineController: ```dart final controller = StateMachineController.fromArtboard(artboard, 'bumpy', onEvent: {); controller.onEvent = (event) { // Do something with event. Like: if(event is OpenURLEvent) { launchUrl(event.url); } }; artboard.addController(controller!); ``` Note that I haven't piped onEvent to the Flutter runtime yet but you'll see it in the StateMachineController in core. In C++: ```c++ auto count = stateMachineInstance->firedEventCount(); for(auto i = 0; i < count; i++) { auto event = stateMachineInstance->firedEventAt(i); if(event->is()) { // Do something with the url. auto url = event->as()->url(); } } ``` You can see some of this in action in the state_machine_event_test.cpp. You can also see the events in the console in the editor: CleanShot 2023-08-10 at 18 03 22@2x In a follow up PR: - Ability to trigger events from State (in/out) and Transition (start/end). - Add custom properties to Events C++ API (currently they are loaded but not tracked against their respective events). Diffs= 8caa7d377 Event triggering (#5793) Co-authored-by: Luigi Rosso --- .rive_head | 2 +- dev/defs/animation/listener_fire_event.json | 21 +++ .../animation/state_machine_component.json | 12 +- .../state_machine_component_folder.json | 9 + .../animation/state_machine_input_folder.json | 9 + .../state_machine_listener_folder.json | 9 + dev/defs/artboard.json | 6 +- dev/defs/assets/font_asset.json | 36 +++- dev/defs/backboard.json | 158 +++++++++++++++++- dev/defs/clipboard_header.json | 40 +++++ dev/defs/component.json | 10 ++ dev/defs/custom_property.json | 9 + dev/defs/custom_property_boolean.json | 19 +++ dev/defs/custom_property_number.json | 19 +++ dev/defs/custom_property_string.json | 19 +++ dev/defs/event.json | 8 + dev/defs/guide.json | 32 ++++ dev/defs/joystick.json | 13 +- dev/defs/open_url_event.json | 28 ++++ dev/defs/tag.json | 57 +++++++ dev/defs/text/text.json | 22 +-- dev/defs/text/text_value_run.json | 2 +- .../rive/animation/listener_fire_event.hpp | 14 ++ .../rive/animation/state_machine_instance.hpp | 15 +- include/rive/custom_property.hpp | 13 ++ include/rive/custom_property_boolean.hpp | 13 ++ include/rive/custom_property_number.hpp | 13 ++ include/rive/custom_property_string.hpp | 13 ++ include/rive/event.hpp | 13 ++ .../animation/listener_fire_event_base.hpp | 71 ++++++++ include/rive/generated/core_registry.hpp | 55 ++++++ .../rive/generated/custom_property_base.hpp | 34 ++++ .../custom_property_boolean_base.hpp | 72 ++++++++ .../generated/custom_property_number_base.hpp | 72 ++++++++ .../generated/custom_property_string_base.hpp | 73 ++++++++ include/rive/generated/event_base.hpp | 37 ++++ .../rive/generated/open_url_event_base.hpp | 93 +++++++++++ include/rive/open_url_event.hpp | 13 ++ src/animation/listener_fire_event.cpp | 15 ++ src/animation/state_machine_instance.cpp | 14 ++ .../animation/listener_fire_event_base.cpp | 11 ++ .../custom_property_boolean_base.cpp | 11 ++ src/generated/custom_property_number_base.cpp | 11 ++ src/generated/custom_property_string_base.cpp | 11 ++ src/generated/event_base.cpp | 11 ++ src/generated/open_url_event_base.cpp | 11 ++ test/assets/event_on_listener.riv | Bin 0 -> 429 bytes test/state_machine_event_test.cpp | 81 +++++++-- 48 files changed, 1292 insertions(+), 38 deletions(-) create mode 100644 dev/defs/animation/listener_fire_event.json create mode 100644 dev/defs/animation/state_machine_component_folder.json create mode 100644 dev/defs/animation/state_machine_input_folder.json create mode 100644 dev/defs/animation/state_machine_listener_folder.json create mode 100644 dev/defs/clipboard_header.json create mode 100644 dev/defs/custom_property.json create mode 100644 dev/defs/custom_property_boolean.json create mode 100644 dev/defs/custom_property_number.json create mode 100644 dev/defs/custom_property_string.json create mode 100644 dev/defs/event.json create mode 100644 dev/defs/guide.json create mode 100644 dev/defs/open_url_event.json create mode 100644 dev/defs/tag.json create mode 100644 include/rive/animation/listener_fire_event.hpp create mode 100644 include/rive/custom_property.hpp create mode 100644 include/rive/custom_property_boolean.hpp create mode 100644 include/rive/custom_property_number.hpp create mode 100644 include/rive/custom_property_string.hpp create mode 100644 include/rive/event.hpp create mode 100644 include/rive/generated/animation/listener_fire_event_base.hpp create mode 100644 include/rive/generated/custom_property_base.hpp create mode 100644 include/rive/generated/custom_property_boolean_base.hpp create mode 100644 include/rive/generated/custom_property_number_base.hpp create mode 100644 include/rive/generated/custom_property_string_base.hpp create mode 100644 include/rive/generated/event_base.hpp create mode 100644 include/rive/generated/open_url_event_base.hpp create mode 100644 include/rive/open_url_event.hpp create mode 100644 src/animation/listener_fire_event.cpp create mode 100644 src/generated/animation/listener_fire_event_base.cpp create mode 100644 src/generated/custom_property_boolean_base.cpp create mode 100644 src/generated/custom_property_number_base.cpp create mode 100644 src/generated/custom_property_string_base.cpp create mode 100644 src/generated/event_base.cpp create mode 100644 src/generated/open_url_event_base.cpp create mode 100644 test/assets/event_on_listener.riv diff --git a/.rive_head b/.rive_head index 4b1e6085..f69ef3f0 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -e71ae68ba09767f246bf3d779f38bb731cf7da9a +8caa7d377f368af8c667ca209a2ce7aef8679be2 diff --git a/dev/defs/animation/listener_fire_event.json b/dev/defs/animation/listener_fire_event.json new file mode 100644 index 00000000..d5baa7d9 --- /dev/null +++ b/dev/defs/animation/listener_fire_event.json @@ -0,0 +1,21 @@ +{ + "name": "ListenerFireEvent", + "key": { + "int": 168, + "string": "listenerfireevent" + }, + "extends": "animation/listener_action.json", + "properties": { + "eventId": { + "type": "Id", + "typeRuntime": "uint", + "initialValue": "Core.missingId", + "initialValueRuntime": "-1", + "key": { + "int": 389, + "string": "eventid" + }, + "description": "Id of the Event referenced." + } + } +} \ No newline at end of file diff --git a/dev/defs/animation/state_machine_component.json b/dev/defs/animation/state_machine_component.json index b3272fb9..22661554 100644 --- a/dev/defs/animation/state_machine_component.json +++ b/dev/defs/animation/state_machine_component.json @@ -34,6 +34,16 @@ }, "description": "Order of this component in the state machine. Exported in order for runtime", "runtime": false + }, + "folderId": { + "type": "Id", + "initialValue": "Core.missingId", + "key": { + "int": 311, + "string": "folderid" + }, + "description": "Id of the folder this state machine component belongs to", + "runtime": false } } -} +} \ No newline at end of file diff --git a/dev/defs/animation/state_machine_component_folder.json b/dev/defs/animation/state_machine_component_folder.json new file mode 100644 index 00000000..ab051877 --- /dev/null +++ b/dev/defs/animation/state_machine_component_folder.json @@ -0,0 +1,9 @@ +{ + "name": "StateMachineComponentFolder", + "key": { + "int": 151, + "string": "statemachinecomponentfolder" + }, + "extends": "animation/state_machine_component.json", + "runtime": false +} \ No newline at end of file diff --git a/dev/defs/animation/state_machine_input_folder.json b/dev/defs/animation/state_machine_input_folder.json new file mode 100644 index 00000000..86e874f9 --- /dev/null +++ b/dev/defs/animation/state_machine_input_folder.json @@ -0,0 +1,9 @@ +{ + "name": "StateMachineInputFolder", + "key": { + "int": 149, + "string": "statemachineinputfolder" + }, + "extends": "animation/state_machine_component_folder.json", + "runtime": false +} \ No newline at end of file diff --git a/dev/defs/animation/state_machine_listener_folder.json b/dev/defs/animation/state_machine_listener_folder.json new file mode 100644 index 00000000..9c59ae2f --- /dev/null +++ b/dev/defs/animation/state_machine_listener_folder.json @@ -0,0 +1,9 @@ +{ + "name": "StateMachineListenerFolder", + "key": { + "int": 150, + "string": "statemachinelistenerfolder" + }, + "extends": "animation/state_machine_component_folder.json", + "runtime": false +} \ No newline at end of file diff --git a/dev/defs/artboard.json b/dev/defs/artboard.json index 53190437..628ce9be 100644 --- a/dev/defs/artboard.json +++ b/dev/defs/artboard.json @@ -102,14 +102,14 @@ "runtime": false, "coop": false }, - "expandedAnimationFolders": { + "expandedFolders": { "type": "List", "initialValue": "[]", "key": { "int": 283, "string": "expandedanimationfolders" }, - "description": "List of expanded animation folders", + "description": "List of expanded folders", "runtime": false, "coop": false }, @@ -125,4 +125,4 @@ "coop": false } } -} +} \ No newline at end of file diff --git a/dev/defs/assets/font_asset.json b/dev/defs/assets/font_asset.json index f10a7907..01a50587 100644 --- a/dev/defs/assets/font_asset.json +++ b/dev/defs/assets/font_asset.json @@ -4,5 +4,37 @@ "int": 141, "string": "fontasset" }, - "extends": "assets/file_asset.json" -} + "extends": "assets/file_asset.json", + "properties": { + "isCustom": { + "type": "bool", + "initialValue": "true", + "key": { + "int": 309, + "string": "iscustom" + }, + "description": "True if the font is a custom font, i.e the user has uploaded it", + "runtime": false + }, + "includeTypeValue": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 360, + "string": "includetypevalue" + }, + "description": "Which characters of the font to include for export: all, used or custom.", + "runtime": false + }, + "includedUnicodes": { + "type": "String", + "initialValue": "''", + "key": { + "int": 361, + "string": "includedunicodes" + }, + "description": "Included unicodes when exporting, in U+0040-0080, format.", + "runtime": false + } + } +} \ No newline at end of file diff --git a/dev/defs/backboard.json b/dev/defs/backboard.json index b194d688..a57597df 100644 --- a/dev/defs/backboard.json +++ b/dev/defs/backboard.json @@ -36,6 +36,17 @@ "description": "The background color.", "runtime": false }, + "animateColorValue": { + "type": "Color", + "initialValue": "0xFF1D1D1D", + "key": { + "int": 354, + "string": "animatecolorvalue" + }, + "description": "The background color while in Animate mode", + "runtime": false, + "coop": false + }, "editorMode": { "type": "uint", "initialValue": "0", @@ -146,6 +157,61 @@ "runtime": false, "coop": false }, + "targetsEnabled": { + "type": "bool", + "initialValue": "true", + "key": { + "int": 379, + "string": "targetsenabled" + }, + "description": "If targets and empty groups are enabled for this file", + "runtime": false, + "coop": false + }, + "motionPathsEnabled": { + "type": "bool", + "initialValue": "true", + "key": { + "int": 351, + "string": "motionpathsenabled" + }, + "description": "If motion paths are enabled for this file", + "runtime": false, + "coop": false + }, + "showFinalPlaybackEnabled": { + "type": "bool", + "initialValue": "true", + "key": { + "int": 355, + "string": "showfinalplaybackenabled" + }, + "description": "If final playback (hiding gizmos during playback) are enabled for this file", + "runtime": false, + "coop": false + }, + "showModifierRange": { + "type": "bool", + "initialValue": "true", + "key": { + "int": 374, + "string": "showmodifierrange" + }, + "description": "Whether text modifier ranges show on the stage", + "runtime": false, + "coop": false + }, + "showModifierRangeValues": { + "type": "bool", + "initialValue": "false", + "key": { + "int": 375, + "string": "showmodifierrangevalues" + }, + "description": "Whether text modifier range values show on the stage", + "runtime": false, + "coop": false + }, "toolbarOutputAction": { "type": "uint", "initialValue": "0", @@ -156,6 +222,96 @@ "description": "Primary output action in the toolbar (share, publish, download)", "runtime": false, "coop": false + }, + "assetsPanelState": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 315, + "string": "assetspanelstate" + }, + "runtime": false, + "coop": false + }, + "defaultFontFamily": { + "type": "String", + "initialValue": "'Inter'", + "key": { + "int": 343, + "string": "defaultfontfamily" + }, + "runtime": false, + "coop": false + }, + "isDefaultFontFamilyCustom": { + "type": "bool", + "initialValue": "false", + "key": { + "int": 352, + "string": "isdefaultfontfamilycustom" + }, + "runtime": false, + "coop": false + }, + "defaultFontStyle": { + "type": "String", + "initialValue": "'Regular'", + "key": { + "int": 344, + "string": "defaultfontstyle" + }, + "runtime": false, + "coop": false + }, + "defaultFontSize": { + "type": "double", + "initialValue": "20.0", + "key": { + "int": 345, + "string": "defaultfontsize" + }, + "runtime": false, + "coop": false + }, + "defaultTextAlign": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 346, + "string": "defaulttextalign" + }, + "runtime": false, + "coop": false + }, + "defaultTextOverflow": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 347, + "string": "defaulttextoverflow" + }, + "runtime": false, + "coop": false + }, + "defaultTextHighlightTextRuns": { + "type": "bool", + "initialValue": "false", + "key": { + "int": 348, + "string": "defaulttexthighlighttextruns" + }, + "runtime": false, + "coop": false + }, + "defaultCollapseTags": { + "type": "bool", + "initialValue": "false", + "key": { + "int": 387, + "string": "defaultcollapsetags" + }, + "runtime": false, + "coop": false } } -} +} \ No newline at end of file diff --git a/dev/defs/clipboard_header.json b/dev/defs/clipboard_header.json new file mode 100644 index 00000000..22ad63bf --- /dev/null +++ b/dev/defs/clipboard_header.json @@ -0,0 +1,40 @@ +{ + "name": "ClipboardHeader", + "key": { + "int": 146, + "string": "clipboardheader" + }, + "runtime": false, + "properties": { + "fileId": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 293, + "string": "fileid" + }, + "description": "File clipboard contents has come from.", + "runtime": false + }, + "projectId": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 294, + "string": "projectid" + }, + "description": "Project clipboard contents has come from.", + "runtime": false + }, + "clipboardTypeValue": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 295, + "string": "clipboardtypevalue" + }, + "description": "Type of clipboard used to read these bytes", + "runtime": false + } + } +} \ No newline at end of file diff --git a/dev/defs/component.json b/dev/defs/component.json index 4d590a6a..75fd1e80 100644 --- a/dev/defs/component.json +++ b/dev/defs/component.json @@ -36,6 +36,16 @@ }, "description": "Identifier used to track parent ContainerComponent." }, + "tagIds": { + "type": "List", + "initialValue": "[]", + "key": { + "int": 382, + "string": "tagids" + }, + "description": "Assigned tag ids.", + "runtime": false + }, "childOrder": { "type": "FractionalIndex", "initialValue": "FractionalIndex.invalid", diff --git a/dev/defs/custom_property.json b/dev/defs/custom_property.json new file mode 100644 index 00000000..98c36840 --- /dev/null +++ b/dev/defs/custom_property.json @@ -0,0 +1,9 @@ +{ + "name": "CustomProperty", + "key": { + "int": 167, + "string": "customproperty" + }, + "abstract": true, + "extends": "component.json" +} \ No newline at end of file diff --git a/dev/defs/custom_property_boolean.json b/dev/defs/custom_property_boolean.json new file mode 100644 index 00000000..d114ca63 --- /dev/null +++ b/dev/defs/custom_property_boolean.json @@ -0,0 +1,19 @@ +{ + "name": "CustomPropertyBoolean", + "key": { + "int": 129, + "string": "custompropertyboolean" + }, + "extends": "custom_property.json", + "properties": { + "propertyValue": { + "type": "bool", + "initialValue": "false", + "animates": true, + "key": { + "int": 245, + "string": "value" + } + } + } +} \ No newline at end of file diff --git a/dev/defs/custom_property_number.json b/dev/defs/custom_property_number.json new file mode 100644 index 00000000..3271b790 --- /dev/null +++ b/dev/defs/custom_property_number.json @@ -0,0 +1,19 @@ +{ + "name": "CustomPropertyNumber", + "key": { + "int": 127, + "string": "custompropertynumber" + }, + "extends": "custom_property.json", + "properties": { + "propertyValue": { + "type": "double", + "initialValue": "0", + "animates": true, + "key": { + "int": 243, + "string": "value" + } + } + } +} \ No newline at end of file diff --git a/dev/defs/custom_property_string.json b/dev/defs/custom_property_string.json new file mode 100644 index 00000000..6f60ac92 --- /dev/null +++ b/dev/defs/custom_property_string.json @@ -0,0 +1,19 @@ +{ + "name": "CustomPropertyString", + "key": { + "int": 130, + "string": "custompropertystring" + }, + "extends": "custom_property.json", + "properties": { + "propertyValue": { + "type": "String", + "initialValue": "''", + "animates": true, + "key": { + "int": 246, + "string": "value" + } + } + } +} \ No newline at end of file diff --git a/dev/defs/event.json b/dev/defs/event.json new file mode 100644 index 00000000..900d71ef --- /dev/null +++ b/dev/defs/event.json @@ -0,0 +1,8 @@ +{ + "name": "Event", + "key": { + "int": 128, + "string": "event" + }, + "extends": "container_component.json" +} \ No newline at end of file diff --git a/dev/defs/guide.json b/dev/defs/guide.json new file mode 100644 index 00000000..87f6d183 --- /dev/null +++ b/dev/defs/guide.json @@ -0,0 +1,32 @@ +{ + "name": "Guide", + "key": { + "int": 140, + "string": "guide" + }, + "extends": "component.json", + "runtime": false, + "properties": { + "axisPosition": { + "type": "double", + "initialValue": "0", + "overrideGet": true, + "group": "axisposition", + "key": { + "int": 276, + "string": "axisposition" + }, + "runtime": false + }, + "axisValue": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 277, + "string": "axisvalue" + }, + "description": "Axis the guide position relates to. 0 for x, 1 for y.", + "runtime": false + } + } +} \ No newline at end of file diff --git a/dev/defs/joystick.json b/dev/defs/joystick.json index 461454eb..f356b79e 100644 --- a/dev/defs/joystick.json +++ b/dev/defs/joystick.json @@ -106,6 +106,17 @@ "string": "joystickflags" } }, + "joystickOrder": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 314, + "string": "joystickorder" + }, + "runtime": false, + "coop": false, + "journal": false + }, "handleSourceId": { "type": "Id", "typeRuntime": "uint", @@ -118,4 +129,4 @@ "description": "Identifier used to track the custom handle source of the joystick." } } -} +} \ No newline at end of file diff --git a/dev/defs/open_url_event.json b/dev/defs/open_url_event.json new file mode 100644 index 00000000..77b57f9a --- /dev/null +++ b/dev/defs/open_url_event.json @@ -0,0 +1,28 @@ +{ + "name": "OpenUrlEvent", + "key": { + "int": 131, + "string": "openurlevent" + }, + "extends": "event.json", + "properties": { + "url": { + "type": "String", + "initialValue": "''", + "key": { + "int": 248, + "string": "url" + }, + "description": "URL to open." + }, + "targetValue": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 249, + "string": "targetvalue" + }, + "description": "Backing value for the target enum." + } + } +} \ No newline at end of file diff --git a/dev/defs/tag.json b/dev/defs/tag.json new file mode 100644 index 00000000..58c6ebff --- /dev/null +++ b/dev/defs/tag.json @@ -0,0 +1,57 @@ +{ + "name": "Tag", + "key": { + "int": 166, + "string": "tag" + }, + "runtime": false, + "properties": { + "name": { + "type": "String", + "initialValue": "''", + "key": { + "int": 383, + "string": "name" + }, + "runtime": false + }, + "colorValue": { + "type": "Color", + "initialValue": "0xFF57A5E0", + "key": { + "int": 384, + "string": "colorvalue" + }, + "runtime": false + }, + "flags": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 385, + "string": "flags" + }, + "runtime": false + }, + "order": { + "type": "FractionalIndex", + "initialValue": "FractionalIndex.invalid", + "key": { + "int": 388, + "string": "order" + }, + "description": "Order this tag shows up in the tags list.", + "runtime": false + }, + "dependentIds": { + "type": "List", + "initialValue": "[]", + "key": { + "int": 386, + "string": "dependentids" + }, + "description": "Object ids assigned to this tag.", + "runtime": false + } + } +} \ No newline at end of file diff --git a/dev/defs/text/text.json b/dev/defs/text/text.json index 8bf0efd6..73163958 100644 --- a/dev/defs/text/text.json +++ b/dev/defs/text/text.json @@ -51,6 +51,17 @@ }, "description": "Height of the text object." }, + "highlightTextRuns": { + "type": "bool", + "initialValue": "true", + "key": { + "int": 310, + "string": "highlighttextruns" + }, + "description": "Whether to draw colored underlines to identify runs.", + "runtime": false, + "coop": false + }, "originX": { "type": "double", "initialValue": "0.0", @@ -71,17 +82,6 @@ }, "description": "Origin y in normalized coordinates (0.5 = center, 0 = top, 1 = bottom)." }, - "highlightTextRuns": { - "type": "bool", - "initialValue": "true", - "key": { - "int": 310, - "string": "highlighttextruns" - }, - "description": "Whether to draw colored underlines to identify runs.", - "runtime": false, - "coop": false - }, "paragraphSpacing": { "type": "double", "initialValue": "0.0", diff --git a/dev/defs/text/text_value_run.json b/dev/defs/text/text_value_run.json index 0dae2403..41b2ac0b 100644 --- a/dev/defs/text/text_value_run.json +++ b/dev/defs/text/text_value_run.json @@ -29,4 +29,4 @@ "description": "The text string value." } } -} +} \ No newline at end of file diff --git a/include/rive/animation/listener_fire_event.hpp b/include/rive/animation/listener_fire_event.hpp new file mode 100644 index 00000000..66c48500 --- /dev/null +++ b/include/rive/animation/listener_fire_event.hpp @@ -0,0 +1,14 @@ +#ifndef _RIVE_LISTENER_FIRE_EVENT_HPP_ +#define _RIVE_LISTENER_FIRE_EVENT_HPP_ +#include "rive/generated/animation/listener_fire_event_base.hpp" + +namespace rive +{ +class ListenerFireEvent : public ListenerFireEventBase +{ +public: + void perform(StateMachineInstance* stateMachineInstance, Vec2D position) const override; +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/animation/state_machine_instance.hpp b/include/rive/animation/state_machine_instance.hpp index 5013b34b..8bd9877f 100644 --- a/include/rive/animation/state_machine_instance.hpp +++ b/include/rive/animation/state_machine_instance.hpp @@ -21,6 +21,7 @@ class Shape; class StateMachineLayerInstance; class HitShape; class NestedArtboard; +class Event; class StateMachineInstance : public Scene { @@ -72,7 +73,7 @@ class StateMachineInstance : public Scene // The number of state changes that occurred across all layers on the // previous advance. - size_t stateChangedCount() const; + std::size_t stateChangedCount() const; // Returns the state name for states that changed in layers on the // previously called advance. If the index of out of range, it returns @@ -92,6 +93,18 @@ class StateMachineInstance : public Scene /// Allow anything referencing a concrete StateMachineInstace access to /// the backing artboard (explicitly not allowed on Scenes). Artboard* artboard() { return m_ArtboardInstance; } + + /// Tracks an event that fired, will be cleared at the end of the next advance. + void fireEvent(Event* event); + + /// Gets the number of events that fired since the last advance. + std::size_t firedEventCount() const; + + /// Gets a fired event at an index < firedEventCount(). + const Event* firedEventAt(std::size_t index) const; + +private: + std::vector m_firedEvents; }; } // namespace rive #endif diff --git a/include/rive/custom_property.hpp b/include/rive/custom_property.hpp new file mode 100644 index 00000000..28639623 --- /dev/null +++ b/include/rive/custom_property.hpp @@ -0,0 +1,13 @@ +#ifndef _RIVE_CUSTOM_PROPERTY_HPP_ +#define _RIVE_CUSTOM_PROPERTY_HPP_ +#include "rive/generated/custom_property_base.hpp" +#include +namespace rive +{ +class CustomProperty : public CustomPropertyBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/custom_property_boolean.hpp b/include/rive/custom_property_boolean.hpp new file mode 100644 index 00000000..260bc0fc --- /dev/null +++ b/include/rive/custom_property_boolean.hpp @@ -0,0 +1,13 @@ +#ifndef _RIVE_CUSTOM_PROPERTY_BOOLEAN_HPP_ +#define _RIVE_CUSTOM_PROPERTY_BOOLEAN_HPP_ +#include "rive/generated/custom_property_boolean_base.hpp" +#include +namespace rive +{ +class CustomPropertyBoolean : public CustomPropertyBooleanBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/custom_property_number.hpp b/include/rive/custom_property_number.hpp new file mode 100644 index 00000000..192351b6 --- /dev/null +++ b/include/rive/custom_property_number.hpp @@ -0,0 +1,13 @@ +#ifndef _RIVE_CUSTOM_PROPERTY_NUMBER_HPP_ +#define _RIVE_CUSTOM_PROPERTY_NUMBER_HPP_ +#include "rive/generated/custom_property_number_base.hpp" +#include +namespace rive +{ +class CustomPropertyNumber : public CustomPropertyNumberBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/custom_property_string.hpp b/include/rive/custom_property_string.hpp new file mode 100644 index 00000000..7efc20e4 --- /dev/null +++ b/include/rive/custom_property_string.hpp @@ -0,0 +1,13 @@ +#ifndef _RIVE_CUSTOM_PROPERTY_STRING_HPP_ +#define _RIVE_CUSTOM_PROPERTY_STRING_HPP_ +#include "rive/generated/custom_property_string_base.hpp" +#include +namespace rive +{ +class CustomPropertyString : public CustomPropertyStringBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/event.hpp b/include/rive/event.hpp new file mode 100644 index 00000000..faa55180 --- /dev/null +++ b/include/rive/event.hpp @@ -0,0 +1,13 @@ +#ifndef _RIVE_EVENT_HPP_ +#define _RIVE_EVENT_HPP_ +#include "rive/generated/event_base.hpp" +#include +namespace rive +{ +class Event : public EventBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/generated/animation/listener_fire_event_base.hpp b/include/rive/generated/animation/listener_fire_event_base.hpp new file mode 100644 index 00000000..33280cd9 --- /dev/null +++ b/include/rive/generated/animation/listener_fire_event_base.hpp @@ -0,0 +1,71 @@ +#ifndef _RIVE_LISTENER_FIRE_EVENT_BASE_HPP_ +#define _RIVE_LISTENER_FIRE_EVENT_BASE_HPP_ +#include "rive/animation/listener_action.hpp" +#include "rive/core/field_types/core_uint_type.hpp" +namespace rive +{ +class ListenerFireEventBase : public ListenerAction +{ +protected: + typedef ListenerAction Super; + +public: + static const uint16_t typeKey = 168; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case ListenerFireEventBase::typeKey: + case ListenerActionBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t eventIdPropertyKey = 389; + +private: + uint32_t m_EventId = -1; + +public: + inline uint32_t eventId() const { return m_EventId; } + void eventId(uint32_t value) + { + if (m_EventId == value) + { + return; + } + m_EventId = value; + eventIdChanged(); + } + + Core* clone() const override; + void copy(const ListenerFireEventBase& object) + { + m_EventId = object.m_EventId; + ListenerAction::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case eventIdPropertyKey: + m_EventId = CoreUintType::deserialize(reader); + return true; + } + return ListenerAction::deserialize(propertyKey, reader); + } + +protected: + virtual void eventIdChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/generated/core_registry.hpp b/include/rive/generated/core_registry.hpp index efc7388b..bf09d27d 100644 --- a/include/rive/generated/core_registry.hpp +++ b/include/rive/generated/core_registry.hpp @@ -30,6 +30,7 @@ #include "rive/animation/listener_action.hpp" #include "rive/animation/listener_align_target.hpp" #include "rive/animation/listener_bool_change.hpp" +#include "rive/animation/listener_fire_event.hpp" #include "rive/animation/listener_input_change.hpp" #include "rive/animation/listener_number_change.hpp" #include "rive/animation/listener_trigger_change.hpp" @@ -86,13 +87,19 @@ #include "rive/constraints/transform_space_constraint.hpp" #include "rive/constraints/translation_constraint.hpp" #include "rive/container_component.hpp" +#include "rive/custom_property.hpp" +#include "rive/custom_property_boolean.hpp" +#include "rive/custom_property_number.hpp" +#include "rive/custom_property_string.hpp" #include "rive/draw_rules.hpp" #include "rive/draw_target.hpp" #include "rive/drawable.hpp" +#include "rive/event.hpp" #include "rive/joystick.hpp" #include "rive/nested_animation.hpp" #include "rive/nested_artboard.hpp" #include "rive/node.hpp" +#include "rive/open_url_event.hpp" #include "rive/shapes/clipping_shape.hpp" #include "rive/shapes/contour_mesh_vertex.hpp" #include "rive/shapes/cubic_asymmetric_vertex.hpp" @@ -146,6 +153,8 @@ class CoreRegistry { case DrawTargetBase::typeKey: return new DrawTarget(); + case CustomPropertyNumberBase::typeKey: + return new CustomPropertyNumber(); case DistanceConstraintBase::typeKey: return new DistanceConstraint(); case IKConstraintBase::typeKey: @@ -166,6 +175,8 @@ class CoreRegistry return new NestedArtboard(); case SoloBase::typeKey: return new Solo(); + case ListenerFireEventBase::typeKey: + return new ListenerFireEvent(); case NestedSimpleAnimationBase::typeKey: return new NestedSimpleAnimation(); case AnimationStateBase::typeKey: @@ -294,14 +305,20 @@ class CoreRegistry return new Image(); case CubicDetachedVertexBase::typeKey: return new CubicDetachedVertex(); + case EventBase::typeKey: + return new Event(); case DrawRulesBase::typeKey: return new DrawRules(); + case CustomPropertyBooleanBase::typeKey: + return new CustomPropertyBoolean(); case ArtboardBase::typeKey: return new Artboard(); case JoystickBase::typeKey: return new Joystick(); case BackboardBase::typeKey: return new Backboard(); + case OpenUrlEventBase::typeKey: + return new OpenUrlEvent(); case WeightBase::typeKey: return new Weight(); case BoneBase::typeKey: @@ -330,6 +347,8 @@ class CoreRegistry return new Text(); case TextValueRunBase::typeKey: return new TextValueRun(); + case CustomPropertyStringBase::typeKey: + return new CustomPropertyString(); case FolderBase::typeKey: return new Folder(); case ImageAssetBase::typeKey: @@ -357,9 +376,15 @@ class CoreRegistry case KeyFrameStringBase::valuePropertyKey: object->as()->value(value); break; + case OpenUrlEventBase::urlPropertyKey: + object->as()->url(value); + break; case TextValueRunBase::textPropertyKey: object->as()->text(value); break; + case CustomPropertyStringBase::propertyValuePropertyKey: + object->as()->propertyValue(value); + break; case AssetBase::namePropertyKey: object->as()->name(value); break; @@ -411,6 +436,9 @@ class CoreRegistry case SoloBase::activeComponentIdPropertyKey: object->as()->activeComponentId(value); break; + case ListenerFireEventBase::eventIdPropertyKey: + object->as()->eventId(value); + break; case ListenerInputChangeBase::inputIdPropertyKey: object->as()->inputId(value); break; @@ -549,6 +577,9 @@ class CoreRegistry case JoystickBase::handleSourceIdPropertyKey: object->as()->handleSourceId(value); break; + case OpenUrlEventBase::targetValuePropertyKey: + object->as()->targetValue(value); + break; case WeightBase::valuesPropertyKey: object->as()->values(value); break; @@ -624,6 +655,9 @@ class CoreRegistry { switch (propertyKey) { + case CustomPropertyNumberBase::propertyValuePropertyKey: + object->as()->propertyValue(value); + break; case ConstraintBase::strengthPropertyKey: object->as()->strength(value); break; @@ -1077,6 +1111,9 @@ class CoreRegistry case ClippingShapeBase::isVisiblePropertyKey: object->as()->isVisible(value); break; + case CustomPropertyBooleanBase::propertyValuePropertyKey: + object->as()->propertyValue(value); + break; case ArtboardBase::clipPropertyKey: object->as()->clip(value); break; @@ -1112,8 +1149,12 @@ class CoreRegistry return object->as()->name(); case KeyFrameStringBase::valuePropertyKey: return object->as()->value(); + case OpenUrlEventBase::urlPropertyKey: + return object->as()->url(); case TextValueRunBase::textPropertyKey: return object->as()->text(); + case CustomPropertyStringBase::propertyValuePropertyKey: + return object->as()->propertyValue(); case AssetBase::namePropertyKey: return object->as()->name(); } @@ -1151,6 +1192,8 @@ class CoreRegistry return object->as()->animationId(); case SoloBase::activeComponentIdPropertyKey: return object->as()->activeComponentId(); + case ListenerFireEventBase::eventIdPropertyKey: + return object->as()->eventId(); case ListenerInputChangeBase::inputIdPropertyKey: return object->as()->inputId(); case AnimationStateBase::animationIdPropertyKey: @@ -1243,6 +1286,8 @@ class CoreRegistry return object->as()->joystickFlags(); case JoystickBase::handleSourceIdPropertyKey: return object->as()->handleSourceId(); + case OpenUrlEventBase::targetValuePropertyKey: + return object->as()->targetValue(); case WeightBase::valuesPropertyKey: return object->as()->values(); case WeightBase::indicesPropertyKey: @@ -1296,6 +1341,8 @@ class CoreRegistry { switch (propertyKey) { + case CustomPropertyNumberBase::propertyValuePropertyKey: + return object->as()->propertyValue(); case ConstraintBase::strengthPropertyKey: return object->as()->strength(); case DistanceConstraintBase::distancePropertyKey: @@ -1601,6 +1648,8 @@ class CoreRegistry return object->as()->linkCornerRadius(); case ClippingShapeBase::isVisiblePropertyKey: return object->as()->isVisible(); + case CustomPropertyBooleanBase::propertyValuePropertyKey: + return object->as()->propertyValue(); case ArtboardBase::clipPropertyKey: return object->as()->clip(); case TextModifierRangeBase::clampPropertyKey: @@ -1629,7 +1678,9 @@ class CoreRegistry case AnimationBase::namePropertyKey: case StateMachineComponentBase::namePropertyKey: case KeyFrameStringBase::valuePropertyKey: + case OpenUrlEventBase::urlPropertyKey: case TextValueRunBase::textPropertyKey: + case CustomPropertyStringBase::propertyValuePropertyKey: case AssetBase::namePropertyKey: return CoreStringType::id; case ComponentBase::parentIdPropertyKey: @@ -1646,6 +1697,7 @@ class CoreRegistry case NestedArtboardBase::artboardIdPropertyKey: case NestedAnimationBase::animationIdPropertyKey: case SoloBase::activeComponentIdPropertyKey: + case ListenerFireEventBase::eventIdPropertyKey: case ListenerInputChangeBase::inputIdPropertyKey: case AnimationStateBase::animationIdPropertyKey: case NestedInputBase::inputIdPropertyKey: @@ -1692,6 +1744,7 @@ class CoreRegistry case JoystickBase::yIdPropertyKey: case JoystickBase::joystickFlagsPropertyKey: case JoystickBase::handleSourceIdPropertyKey: + case OpenUrlEventBase::targetValuePropertyKey: case WeightBase::valuesPropertyKey: case WeightBase::indicesPropertyKey: case TendonBase::boneIdPropertyKey: @@ -1716,6 +1769,7 @@ class CoreRegistry case TextValueRunBase::styleIdPropertyKey: case FileAssetBase::assetIdPropertyKey: return CoreUintType::id; + case CustomPropertyNumberBase::propertyValuePropertyKey: case ConstraintBase::strengthPropertyKey: case DistanceConstraintBase::distancePropertyKey: case TransformComponentConstraintBase::copyFactorPropertyKey: @@ -1866,6 +1920,7 @@ class CoreRegistry case PointsPathBase::isClosedPropertyKey: case RectangleBase::linkCornerRadiusPropertyKey: case ClippingShapeBase::isVisiblePropertyKey: + case CustomPropertyBooleanBase::propertyValuePropertyKey: case ArtboardBase::clipPropertyKey: case TextModifierRangeBase::clampPropertyKey: return CoreBoolType::id; diff --git a/include/rive/generated/custom_property_base.hpp b/include/rive/generated/custom_property_base.hpp new file mode 100644 index 00000000..1e218154 --- /dev/null +++ b/include/rive/generated/custom_property_base.hpp @@ -0,0 +1,34 @@ +#ifndef _RIVE_CUSTOM_PROPERTY_BASE_HPP_ +#define _RIVE_CUSTOM_PROPERTY_BASE_HPP_ +#include "rive/component.hpp" +namespace rive +{ +class CustomPropertyBase : public Component +{ +protected: + typedef Component Super; + +public: + static const uint16_t typeKey = 167; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case CustomPropertyBase::typeKey: + case ComponentBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + +protected: +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/generated/custom_property_boolean_base.hpp b/include/rive/generated/custom_property_boolean_base.hpp new file mode 100644 index 00000000..ebfe5242 --- /dev/null +++ b/include/rive/generated/custom_property_boolean_base.hpp @@ -0,0 +1,72 @@ +#ifndef _RIVE_CUSTOM_PROPERTY_BOOLEAN_BASE_HPP_ +#define _RIVE_CUSTOM_PROPERTY_BOOLEAN_BASE_HPP_ +#include "rive/core/field_types/core_bool_type.hpp" +#include "rive/custom_property.hpp" +namespace rive +{ +class CustomPropertyBooleanBase : public CustomProperty +{ +protected: + typedef CustomProperty Super; + +public: + static const uint16_t typeKey = 129; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case CustomPropertyBooleanBase::typeKey: + case CustomPropertyBase::typeKey: + case ComponentBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t propertyValuePropertyKey = 245; + +private: + bool m_PropertyValue = false; + +public: + inline bool propertyValue() const { return m_PropertyValue; } + void propertyValue(bool value) + { + if (m_PropertyValue == value) + { + return; + } + m_PropertyValue = value; + propertyValueChanged(); + } + + Core* clone() const override; + void copy(const CustomPropertyBooleanBase& object) + { + m_PropertyValue = object.m_PropertyValue; + CustomProperty::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case propertyValuePropertyKey: + m_PropertyValue = CoreBoolType::deserialize(reader); + return true; + } + return CustomProperty::deserialize(propertyKey, reader); + } + +protected: + virtual void propertyValueChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/generated/custom_property_number_base.hpp b/include/rive/generated/custom_property_number_base.hpp new file mode 100644 index 00000000..57d6d2a0 --- /dev/null +++ b/include/rive/generated/custom_property_number_base.hpp @@ -0,0 +1,72 @@ +#ifndef _RIVE_CUSTOM_PROPERTY_NUMBER_BASE_HPP_ +#define _RIVE_CUSTOM_PROPERTY_NUMBER_BASE_HPP_ +#include "rive/core/field_types/core_double_type.hpp" +#include "rive/custom_property.hpp" +namespace rive +{ +class CustomPropertyNumberBase : public CustomProperty +{ +protected: + typedef CustomProperty Super; + +public: + static const uint16_t typeKey = 127; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case CustomPropertyNumberBase::typeKey: + case CustomPropertyBase::typeKey: + case ComponentBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t propertyValuePropertyKey = 243; + +private: + float m_PropertyValue = 0.0f; + +public: + inline float propertyValue() const { return m_PropertyValue; } + void propertyValue(float value) + { + if (m_PropertyValue == value) + { + return; + } + m_PropertyValue = value; + propertyValueChanged(); + } + + Core* clone() const override; + void copy(const CustomPropertyNumberBase& object) + { + m_PropertyValue = object.m_PropertyValue; + CustomProperty::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case propertyValuePropertyKey: + m_PropertyValue = CoreDoubleType::deserialize(reader); + return true; + } + return CustomProperty::deserialize(propertyKey, reader); + } + +protected: + virtual void propertyValueChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/generated/custom_property_string_base.hpp b/include/rive/generated/custom_property_string_base.hpp new file mode 100644 index 00000000..40c57ca2 --- /dev/null +++ b/include/rive/generated/custom_property_string_base.hpp @@ -0,0 +1,73 @@ +#ifndef _RIVE_CUSTOM_PROPERTY_STRING_BASE_HPP_ +#define _RIVE_CUSTOM_PROPERTY_STRING_BASE_HPP_ +#include +#include "rive/core/field_types/core_string_type.hpp" +#include "rive/custom_property.hpp" +namespace rive +{ +class CustomPropertyStringBase : public CustomProperty +{ +protected: + typedef CustomProperty Super; + +public: + static const uint16_t typeKey = 130; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case CustomPropertyStringBase::typeKey: + case CustomPropertyBase::typeKey: + case ComponentBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t propertyValuePropertyKey = 246; + +private: + std::string m_PropertyValue = ""; + +public: + inline const std::string& propertyValue() const { return m_PropertyValue; } + void propertyValue(std::string value) + { + if (m_PropertyValue == value) + { + return; + } + m_PropertyValue = value; + propertyValueChanged(); + } + + Core* clone() const override; + void copy(const CustomPropertyStringBase& object) + { + m_PropertyValue = object.m_PropertyValue; + CustomProperty::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case propertyValuePropertyKey: + m_PropertyValue = CoreStringType::deserialize(reader); + return true; + } + return CustomProperty::deserialize(propertyKey, reader); + } + +protected: + virtual void propertyValueChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/generated/event_base.hpp b/include/rive/generated/event_base.hpp new file mode 100644 index 00000000..b2d4017a --- /dev/null +++ b/include/rive/generated/event_base.hpp @@ -0,0 +1,37 @@ +#ifndef _RIVE_EVENT_BASE_HPP_ +#define _RIVE_EVENT_BASE_HPP_ +#include "rive/container_component.hpp" +namespace rive +{ +class EventBase : public ContainerComponent +{ +protected: + typedef ContainerComponent Super; + +public: + static const uint16_t typeKey = 128; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case EventBase::typeKey: + case ContainerComponentBase::typeKey: + case ComponentBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + Core* clone() const override; + +protected: +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/generated/open_url_event_base.hpp b/include/rive/generated/open_url_event_base.hpp new file mode 100644 index 00000000..ec53ae71 --- /dev/null +++ b/include/rive/generated/open_url_event_base.hpp @@ -0,0 +1,93 @@ +#ifndef _RIVE_OPEN_URL_EVENT_BASE_HPP_ +#define _RIVE_OPEN_URL_EVENT_BASE_HPP_ +#include +#include "rive/core/field_types/core_string_type.hpp" +#include "rive/core/field_types/core_uint_type.hpp" +#include "rive/event.hpp" +namespace rive +{ +class OpenUrlEventBase : public Event +{ +protected: + typedef Event Super; + +public: + static const uint16_t typeKey = 131; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case OpenUrlEventBase::typeKey: + case EventBase::typeKey: + case ContainerComponentBase::typeKey: + case ComponentBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t urlPropertyKey = 248; + static const uint16_t targetValuePropertyKey = 249; + +private: + std::string m_Url = ""; + uint32_t m_TargetValue = 0; + +public: + inline const std::string& url() const { return m_Url; } + void url(std::string value) + { + if (m_Url == value) + { + return; + } + m_Url = value; + urlChanged(); + } + + inline uint32_t targetValue() const { return m_TargetValue; } + void targetValue(uint32_t value) + { + if (m_TargetValue == value) + { + return; + } + m_TargetValue = value; + targetValueChanged(); + } + + Core* clone() const override; + void copy(const OpenUrlEventBase& object) + { + m_Url = object.m_Url; + m_TargetValue = object.m_TargetValue; + Event::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case urlPropertyKey: + m_Url = CoreStringType::deserialize(reader); + return true; + case targetValuePropertyKey: + m_TargetValue = CoreUintType::deserialize(reader); + return true; + } + return Event::deserialize(propertyKey, reader); + } + +protected: + virtual void urlChanged() {} + virtual void targetValueChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/open_url_event.hpp b/include/rive/open_url_event.hpp new file mode 100644 index 00000000..fb8bc0e9 --- /dev/null +++ b/include/rive/open_url_event.hpp @@ -0,0 +1,13 @@ +#ifndef _RIVE_OPEN_URL_EVENT_HPP_ +#define _RIVE_OPEN_URL_EVENT_HPP_ +#include "rive/generated/open_url_event_base.hpp" +#include +namespace rive +{ +class OpenUrlEvent : public OpenUrlEventBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/src/animation/listener_fire_event.cpp b/src/animation/listener_fire_event.cpp new file mode 100644 index 00000000..39d2fd19 --- /dev/null +++ b/src/animation/listener_fire_event.cpp @@ -0,0 +1,15 @@ +#include "rive/animation/listener_fire_event.hpp" +#include "rive/animation/state_machine_instance.hpp" +#include "rive/event.hpp" + +using namespace rive; + +void ListenerFireEvent::perform(StateMachineInstance* stateMachineInstance, Vec2D position) const +{ + auto coreEvent = stateMachineInstance->artboard()->resolve(eventId()); + if (coreEvent == nullptr || !coreEvent->is()) + { + return; + } + stateMachineInstance->fireEvent(coreEvent->as()); +} \ No newline at end of file diff --git a/src/animation/state_machine_instance.cpp b/src/animation/state_machine_instance.cpp index 5a1e00d6..cbccf6da 100644 --- a/src/animation/state_machine_instance.cpp +++ b/src/animation/state_machine_instance.cpp @@ -485,6 +485,7 @@ StateMachineInstance::~StateMachineInstance() bool StateMachineInstance::advance(float seconds) { + m_firedEvents.clear(); m_NeedsAdvance = false; for (size_t i = 0; i < m_LayerCount; i++) { @@ -609,3 +610,16 @@ const LinearAnimationInstance* StateMachineInstance::currentAnimationByIndex(siz } return nullptr; } + +void StateMachineInstance::fireEvent(Event* event) { m_firedEvents.push_back(event); } + +std::size_t StateMachineInstance::firedEventCount() const { return m_firedEvents.size(); } + +const Event* StateMachineInstance::firedEventAt(std::size_t index) const +{ + if (index >= m_firedEvents.size()) + { + return nullptr; + } + return m_firedEvents[index]; +} diff --git a/src/generated/animation/listener_fire_event_base.cpp b/src/generated/animation/listener_fire_event_base.cpp new file mode 100644 index 00000000..e7ae04f2 --- /dev/null +++ b/src/generated/animation/listener_fire_event_base.cpp @@ -0,0 +1,11 @@ +#include "rive/generated/animation/listener_fire_event_base.hpp" +#include "rive/animation/listener_fire_event.hpp" + +using namespace rive; + +Core* ListenerFireEventBase::clone() const +{ + auto cloned = new ListenerFireEvent(); + cloned->copy(*this); + return cloned; +} diff --git a/src/generated/custom_property_boolean_base.cpp b/src/generated/custom_property_boolean_base.cpp new file mode 100644 index 00000000..b999ee83 --- /dev/null +++ b/src/generated/custom_property_boolean_base.cpp @@ -0,0 +1,11 @@ +#include "rive/generated/custom_property_boolean_base.hpp" +#include "rive/custom_property_boolean.hpp" + +using namespace rive; + +Core* CustomPropertyBooleanBase::clone() const +{ + auto cloned = new CustomPropertyBoolean(); + cloned->copy(*this); + return cloned; +} diff --git a/src/generated/custom_property_number_base.cpp b/src/generated/custom_property_number_base.cpp new file mode 100644 index 00000000..e1d0dd8c --- /dev/null +++ b/src/generated/custom_property_number_base.cpp @@ -0,0 +1,11 @@ +#include "rive/generated/custom_property_number_base.hpp" +#include "rive/custom_property_number.hpp" + +using namespace rive; + +Core* CustomPropertyNumberBase::clone() const +{ + auto cloned = new CustomPropertyNumber(); + cloned->copy(*this); + return cloned; +} diff --git a/src/generated/custom_property_string_base.cpp b/src/generated/custom_property_string_base.cpp new file mode 100644 index 00000000..c7e27ec4 --- /dev/null +++ b/src/generated/custom_property_string_base.cpp @@ -0,0 +1,11 @@ +#include "rive/generated/custom_property_string_base.hpp" +#include "rive/custom_property_string.hpp" + +using namespace rive; + +Core* CustomPropertyStringBase::clone() const +{ + auto cloned = new CustomPropertyString(); + cloned->copy(*this); + return cloned; +} diff --git a/src/generated/event_base.cpp b/src/generated/event_base.cpp new file mode 100644 index 00000000..18292282 --- /dev/null +++ b/src/generated/event_base.cpp @@ -0,0 +1,11 @@ +#include "rive/generated/event_base.hpp" +#include "rive/event.hpp" + +using namespace rive; + +Core* EventBase::clone() const +{ + auto cloned = new Event(); + cloned->copy(*this); + return cloned; +} diff --git a/src/generated/open_url_event_base.cpp b/src/generated/open_url_event_base.cpp new file mode 100644 index 00000000..6c7735d6 --- /dev/null +++ b/src/generated/open_url_event_base.cpp @@ -0,0 +1,11 @@ +#include "rive/generated/open_url_event_base.hpp" +#include "rive/open_url_event.hpp" + +using namespace rive; + +Core* OpenUrlEventBase::clone() const +{ + auto cloned = new OpenUrlEvent(); + cloned->copy(*this); + return cloned; +} diff --git a/test/assets/event_on_listener.riv b/test/assets/event_on_listener.riv new file mode 100644 index 0000000000000000000000000000000000000000..6e2000d3dcaec435147b43354ed7bedc0a9bc021 GIT binary patch literal 429 zcmZWmJxc>o5S-O}xhR@|M#Rc%ECfx6B4WUgco+~=#E7k&$&wu0 zQt(e$`va_FDOd}Cvf^|}h5{cnQPn!iWirZdaN3KaOqm1LJR363$x0M_RoBk0k{l`B z60t5>n(G>E5&MTzvh0lp*R(Sy&`bMc^M;vOydb5nYmN*(BP&+a<_sy4y_|vkaoLvz zKVXsUQoQF%H@ybhR_s6q$Dxtm3AkNHN{|6Cxj4A*haC7dcCuJlOcu4L+1d6=)n6%h zMFacFuT)qW!_pPmTVCs@U%oc0R -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "rive/core/binary_reader.hpp" +#include "rive/file.hpp" +#include "rive/event.hpp" +#include "rive/shapes/shape.hpp" +#include "rive/animation/state_machine_bool.hpp" +#include "rive/animation/state_machine_layer.hpp" +#include "rive/animation/state_machine_listener.hpp" +#include "rive/animation/animation_state.hpp" +#include "rive/animation/entry_state.hpp" +#include "rive/animation/state_transition.hpp" +#include "rive/animation/state_machine_instance.hpp" +#include "rive/animation/state_machine_input_instance.hpp" +#include "rive/animation/blend_state_1d.hpp" +#include "rive/animation/blend_animation_1d.hpp" +#include "rive/animation/blend_state_direct.hpp" +#include "rive/animation/blend_state_transition.hpp" +#include "rive/animation/listener_input_change.hpp" +#include "rive/animation/listener_fire_event.hpp" +#include "rive/node.hpp" #include "catch.hpp" #include "rive_file_reader.hpp" #include @@ -115,3 +118,49 @@ TEST_CASE("hit a toggle boolean listener", "[file]") // Got toggled back on after pressing REQUIRE(switchButton->value() == true); } + +TEST_CASE("events load correctly on a listener", "[events]") +{ + auto file = ReadRiveFile("../../test/assets/event_on_listener.riv"); + + auto artboard = file->artboard()->instance(); + REQUIRE(artboard != nullptr); + REQUIRE(artboard->stateMachineCount() == 1); + + auto stateMachineInstance = artboard->stateMachineAt(0); + REQUIRE(stateMachineInstance != nullptr); + + artboard->advance(0.0f); + stateMachineInstance->advance(0.0f); + + auto events = artboard->find(); + REQUIRE(events.size() == 4); + + REQUIRE(stateMachineInstance->stateMachine()->listenerCount() == 1); + auto listener1 = stateMachineInstance->stateMachine()->listener(0); + auto target1 = artboard->resolve(listener1->targetId()); + REQUIRE(target1->is()); + REQUIRE(listener1->actionCount() == 2); + auto fireEvent1 = listener1->action(0); + REQUIRE(fireEvent1 != nullptr); + REQUIRE(fireEvent1->is()); + REQUIRE(fireEvent1->as()->eventId() != 0); + auto event = artboard->resolve(fireEvent1->as()->eventId()); + REQUIRE(event->is()); + REQUIRE(event->as()->name() == "Footstep"); + + REQUIRE(stateMachineInstance->firedEventCount() == 0); + stateMachineInstance->pointerDown(rive::Vec2D(343.0f, 116.0f)); + stateMachineInstance->pointerUp(rive::Vec2D(343.0f, 116.0f)); + + // There are two events on the listener. + REQUIRE(stateMachineInstance->firedEventCount() == 2); + auto firedEvent1 = stateMachineInstance->firedEventAt(0); + REQUIRE(firedEvent1->name() == "Footstep"); + auto firedEvent2 = stateMachineInstance->firedEventAt(1); + REQUIRE(firedEvent2->name() == "Event 3"); + + // After advancing again the firedEventCount should return to 0. + stateMachineInstance->advance(0.0f); + REQUIRE(stateMachineInstance->firedEventCount() == 0); +}