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<OpenURLEvent>()) {
// Do something with the url.
auto url = event->as<OpenURLEvent>()->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:
<img width="717" alt="CleanShot 2023-08-10 at 18 03 22@2x" src="https://github.com/rive-app/rive/assets/454182/af21902a-424d-435b-b5b0-2a43701fe186">
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 <luigi-rosso@users.noreply.github.com>
diff --git a/.rive_head b/.rive_head
index 4b1e608..f69ef3f 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 0000000..d5baa7d
--- /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 b3272fb..2266155 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 0000000..ab05187
--- /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 0000000..86e874f
--- /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 0000000..9c59ae2
--- /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 5319043..628ce9b 100644
--- a/dev/defs/artboard.json
+++ b/dev/defs/artboard.json
@@ -102,14 +102,14 @@
"runtime": false,
"coop": false
},
- "expandedAnimationFolders": {
+ "expandedFolders": {
"type": "List<Id>",
"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 f10a790..01a5058 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 b194d68..a57597d 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 0000000..22ad63b
--- /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 4d590a6..75fd1e8 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<Id>",
+ "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 0000000..98c3684
--- /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 0000000..d114ca6
--- /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 0000000..3271b79
--- /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 0000000..6f60ac9
--- /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 0000000..900d71e
--- /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 0000000..87f6d18
--- /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 461454e..f356b79 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 0000000..77b57f9
--- /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 0000000..58c6ebf
--- /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<Id>",
+ "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 8bf0efd..7316395 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 0dae240..41b2ac0 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 0000000..66c4850
--- /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 5013b34..8bd9877 100644
--- a/include/rive/animation/state_machine_instance.hpp
+++ b/include/rive/animation/state_machine_instance.hpp
@@ -21,6 +21,7 @@
class StateMachineLayerInstance;
class HitShape;
class NestedArtboard;
+class Event;
class StateMachineInstance : public Scene
{
@@ -72,7 +73,7 @@
// 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 @@
/// 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<Event*> m_firedEvents;
};
} // namespace rive
#endif
diff --git a/include/rive/custom_property.hpp b/include/rive/custom_property.hpp
new file mode 100644
index 0000000..2863962
--- /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 <stdio.h>
+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 0000000..260bc0f
--- /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 <stdio.h>
+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 0000000..192351b
--- /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 <stdio.h>
+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 0000000..7efc20e
--- /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 <stdio.h>
+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 0000000..faa5518
--- /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 <stdio.h>
+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 0000000..33280cd
--- /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 efc7388..bf09d27 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 @@
{
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 @@
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 @@
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 @@
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 @@
case KeyFrameStringBase::valuePropertyKey:
object->as<KeyFrameStringBase>()->value(value);
break;
+ case OpenUrlEventBase::urlPropertyKey:
+ object->as<OpenUrlEventBase>()->url(value);
+ break;
case TextValueRunBase::textPropertyKey:
object->as<TextValueRunBase>()->text(value);
break;
+ case CustomPropertyStringBase::propertyValuePropertyKey:
+ object->as<CustomPropertyStringBase>()->propertyValue(value);
+ break;
case AssetBase::namePropertyKey:
object->as<AssetBase>()->name(value);
break;
@@ -411,6 +436,9 @@
case SoloBase::activeComponentIdPropertyKey:
object->as<SoloBase>()->activeComponentId(value);
break;
+ case ListenerFireEventBase::eventIdPropertyKey:
+ object->as<ListenerFireEventBase>()->eventId(value);
+ break;
case ListenerInputChangeBase::inputIdPropertyKey:
object->as<ListenerInputChangeBase>()->inputId(value);
break;
@@ -549,6 +577,9 @@
case JoystickBase::handleSourceIdPropertyKey:
object->as<JoystickBase>()->handleSourceId(value);
break;
+ case OpenUrlEventBase::targetValuePropertyKey:
+ object->as<OpenUrlEventBase>()->targetValue(value);
+ break;
case WeightBase::valuesPropertyKey:
object->as<WeightBase>()->values(value);
break;
@@ -624,6 +655,9 @@
{
switch (propertyKey)
{
+ case CustomPropertyNumberBase::propertyValuePropertyKey:
+ object->as<CustomPropertyNumberBase>()->propertyValue(value);
+ break;
case ConstraintBase::strengthPropertyKey:
object->as<ConstraintBase>()->strength(value);
break;
@@ -1077,6 +1111,9 @@
case ClippingShapeBase::isVisiblePropertyKey:
object->as<ClippingShapeBase>()->isVisible(value);
break;
+ case CustomPropertyBooleanBase::propertyValuePropertyKey:
+ object->as<CustomPropertyBooleanBase>()->propertyValue(value);
+ break;
case ArtboardBase::clipPropertyKey:
object->as<ArtboardBase>()->clip(value);
break;
@@ -1112,8 +1149,12 @@
return object->as<StateMachineComponentBase>()->name();
case KeyFrameStringBase::valuePropertyKey:
return object->as<KeyFrameStringBase>()->value();
+ case OpenUrlEventBase::urlPropertyKey:
+ return object->as<OpenUrlEventBase>()->url();
case TextValueRunBase::textPropertyKey:
return object->as<TextValueRunBase>()->text();
+ case CustomPropertyStringBase::propertyValuePropertyKey:
+ return object->as<CustomPropertyStringBase>()->propertyValue();
case AssetBase::namePropertyKey:
return object->as<AssetBase>()->name();
}
@@ -1151,6 +1192,8 @@
return object->as<NestedAnimationBase>()->animationId();
case SoloBase::activeComponentIdPropertyKey:
return object->as<SoloBase>()->activeComponentId();
+ case ListenerFireEventBase::eventIdPropertyKey:
+ return object->as<ListenerFireEventBase>()->eventId();
case ListenerInputChangeBase::inputIdPropertyKey:
return object->as<ListenerInputChangeBase>()->inputId();
case AnimationStateBase::animationIdPropertyKey:
@@ -1243,6 +1286,8 @@
return object->as<JoystickBase>()->joystickFlags();
case JoystickBase::handleSourceIdPropertyKey:
return object->as<JoystickBase>()->handleSourceId();
+ case OpenUrlEventBase::targetValuePropertyKey:
+ return object->as<OpenUrlEventBase>()->targetValue();
case WeightBase::valuesPropertyKey:
return object->as<WeightBase>()->values();
case WeightBase::indicesPropertyKey:
@@ -1296,6 +1341,8 @@
{
switch (propertyKey)
{
+ case CustomPropertyNumberBase::propertyValuePropertyKey:
+ return object->as<CustomPropertyNumberBase>()->propertyValue();
case ConstraintBase::strengthPropertyKey:
return object->as<ConstraintBase>()->strength();
case DistanceConstraintBase::distancePropertyKey:
@@ -1601,6 +1648,8 @@
return object->as<RectangleBase>()->linkCornerRadius();
case ClippingShapeBase::isVisiblePropertyKey:
return object->as<ClippingShapeBase>()->isVisible();
+ case CustomPropertyBooleanBase::propertyValuePropertyKey:
+ return object->as<CustomPropertyBooleanBase>()->propertyValue();
case ArtboardBase::clipPropertyKey:
return object->as<ArtboardBase>()->clip();
case TextModifierRangeBase::clampPropertyKey:
@@ -1629,7 +1678,9 @@
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 @@
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 @@
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 @@
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 @@
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 0000000..1e21815
--- /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 0000000..ebfe524
--- /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 0000000..57d6d2a
--- /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 0000000..40c57ca
--- /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 <string>
+#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 0000000..b2d4017
--- /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 0000000..ec53ae7
--- /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 <string>
+#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 0000000..fb8bc0e
--- /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 <stdio.h>
+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 0000000..39d2fd1
--- /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<Event>())
+ {
+ return;
+ }
+ stateMachineInstance->fireEvent(coreEvent->as<Event>());
+}
\ No newline at end of file
diff --git a/src/animation/state_machine_instance.cpp b/src/animation/state_machine_instance.cpp
index 5a1e00d..cbccf6d 100644
--- a/src/animation/state_machine_instance.cpp
+++ b/src/animation/state_machine_instance.cpp
@@ -485,6 +485,7 @@
bool StateMachineInstance::advance(float seconds)
{
+ m_firedEvents.clear();
m_NeedsAdvance = false;
for (size_t i = 0; i < m_LayerCount; i++)
{
@@ -609,3 +610,16 @@
}
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 0000000..e7ae04f
--- /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 0000000..b999ee8
--- /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 0000000..e1d0dd8
--- /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 0000000..c7e27ec
--- /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 0000000..1829228
--- /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 0000000..6c7735d
--- /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 0000000..6e2000d
--- /dev/null
+++ b/test/assets/event_on_listener.riv
Binary files differ
diff --git a/test/state_machine_event_test.cpp b/test/state_machine_event_test.cpp
index 00586c0..9ddab3d 100644
--- a/test/state_machine_event_test.cpp
+++ b/test/state_machine_event_test.cpp
@@ -1,19 +1,22 @@
-#include <rive/core/binary_reader.hpp>
-#include <rive/file.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/node.hpp>
+#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 <cstdio>
@@ -115,3 +118,49 @@
// 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<rive::Event>();
+ REQUIRE(events.size() == 4);
+
+ REQUIRE(stateMachineInstance->stateMachine()->listenerCount() == 1);
+ auto listener1 = stateMachineInstance->stateMachine()->listener(0);
+ auto target1 = artboard->resolve(listener1->targetId());
+ REQUIRE(target1->is<rive::Shape>());
+ REQUIRE(listener1->actionCount() == 2);
+ auto fireEvent1 = listener1->action(0);
+ REQUIRE(fireEvent1 != nullptr);
+ REQUIRE(fireEvent1->is<rive::ListenerFireEvent>());
+ REQUIRE(fireEvent1->as<rive::ListenerFireEvent>()->eventId() != 0);
+ auto event = artboard->resolve(fireEvent1->as<rive::ListenerFireEvent>()->eventId());
+ REQUIRE(event->is<rive::Event>());
+ REQUIRE(event->as<rive::Event>()->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);
+}