editor: nine-slicing core data type definitions This PR adds the core data types to support n-slicing. There are three main types: Axis, NSlicer and NSlicerTileMode. 1. Axis: I didn't want to make this super specific, since it could be used for grids later. So rn, it just represents some position in some dimension, and can either be a value in terms of a positional unit (like 10px) or bounds percentage (like 10%). 2. NSlicer: It's as simple as a component gets, we'll just use it to be a parent of all the n-slicer Axes, and have it be a child of Image later. 3. NSlicerTileMode: The main data here is 'style'. We said to use patchX and patchY separately from patchIndex. The last one is persisted in file, while the other two are actually used at runtime. The non-json files are auto generated, with the runtime json files copy pasted from the dev/defs version. I verified that the editor still runs, and the runtime also runs without error. Next up, I'll use these definitions to change editor behavior. Documentation: https://www.notion.so/rive-app/9-Slice-Tech-Proposal-Image-only-50b25ea8e79c4efabb681110e288f064#15f3a49ce3534baeafc31c37fb30cc0b For a rough direction of how to implement nine-slicing, check out this research branch: https://github.com/rive-app/rive/compare/master...susan/nine-slice-research Diffs= ed56d2de6 editor: nine-slicing core data type definitions (#7840) Co-authored-by: Susan Wang <susan@rive.app>
diff --git a/.rive_head b/.rive_head index 2db670f..ac7db82 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -4fb978a9230fc006b5e575364f062907e7dd2afe +ed56d2de61afb05abd99e8bab6775b63ab89f1a3
diff --git a/dev/defs/layout/axis.json b/dev/defs/layout/axis.json new file mode 100644 index 0000000..0703844 --- /dev/null +++ b/dev/defs/layout/axis.json
@@ -0,0 +1,29 @@ +{ + "name": "Axis", + "key": { + "int": 492, + "string": "axis" + }, + "abstract": true, + "extends": "component.json", + "properties": { + "offset": { + "type": "double", + "initialValue": "0", + "animates": true, + "key": { + "int": 675, + "string": "offset" + } + }, + "normalized": { + "type": "bool", + "initialValue": "false", + "key": { + "int": 676, + "string": "normalized" + }, + "description": "true means offset indicates a percentage" + } + } +} \ No newline at end of file
diff --git a/dev/defs/layout/axis_x.json b/dev/defs/layout/axis_x.json new file mode 100644 index 0000000..47774c7 --- /dev/null +++ b/dev/defs/layout/axis_x.json
@@ -0,0 +1,8 @@ +{ + "name": "AxisX", + "key": { + "int": 495, + "string": "axisx" + }, + "extends": "layout/axis.json" +} \ No newline at end of file
diff --git a/dev/defs/layout/axis_y.json b/dev/defs/layout/axis_y.json new file mode 100644 index 0000000..b3bd16e --- /dev/null +++ b/dev/defs/layout/axis_y.json
@@ -0,0 +1,8 @@ +{ + "name": "AxisY", + "key": { + "int": 494, + "string": "axisy" + }, + "extends": "layout/axis.json" +} \ No newline at end of file
diff --git a/dev/defs/layout/n_slicer.json b/dev/defs/layout/n_slicer.json new file mode 100644 index 0000000..d642142 --- /dev/null +++ b/dev/defs/layout/n_slicer.json
@@ -0,0 +1,8 @@ +{ + "name": "NSlicer", + "key": { + "int": 493, + "string": "nslicer" + }, + "extends": "component.json" +} \ No newline at end of file
diff --git a/dev/defs/layout/n_slicer_tile_mode.json b/dev/defs/layout/n_slicer_tile_mode.json new file mode 100644 index 0000000..fae9388 --- /dev/null +++ b/dev/defs/layout/n_slicer_tile_mode.json
@@ -0,0 +1,48 @@ +{ + "name": "NSlicerTileMode", + "key": { + "int": 491, + "string": "nslicertilemode" + }, + "extends": "component.json", + "properties": { + "patchX": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 670, + "string": "patchx" + }, + "description": "the x index of the patch to style", + "runtime": false + }, + "patchY": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 671, + "string": "patchy" + }, + "description": "the y index of the patch to style", + "runtime": false + }, + "patchIndex": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 672, + "string": "patchindex" + }, + "description": "the index of the patch to style, non-negative" + }, + "style": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 673, + "string": "style" + }, + "description": "represents stretch, repeat, hidden, etc." + } + } +} \ No newline at end of file
diff --git a/include/rive/generated/core_registry.hpp b/include/rive/generated/core_registry.hpp index d38b451..fd25b4c 100644 --- a/include/rive/generated/core_registry.hpp +++ b/include/rive/generated/core_registry.hpp
@@ -128,7 +128,12 @@ #include "rive/drawable.hpp" #include "rive/event.hpp" #include "rive/joystick.hpp" +#include "rive/layout/axis.hpp" +#include "rive/layout/axis_x.hpp" +#include "rive/layout/axis_y.hpp" #include "rive/layout/layout_component_style.hpp" +#include "rive/layout/n_slicer.hpp" +#include "rive/layout/n_slicer_tile_mode.hpp" #include "rive/layout_component.hpp" #include "rive/nested_animation.hpp" #include "rive/nested_artboard.hpp" @@ -277,8 +282,16 @@ return new Solo(); case NestedArtboardLayoutBase::typeKey: return new NestedArtboardLayout(); + case NSlicerTileModeBase::typeKey: + return new NSlicerTileMode(); + case AxisYBase::typeKey: + return new AxisY(); case LayoutComponentStyleBase::typeKey: return new LayoutComponentStyle(); + case AxisXBase::typeKey: + return new AxisX(); + case NSlicerBase::typeKey: + return new NSlicer(); case ListenerFireEventBase::typeKey: return new ListenerFireEvent(); case KeyFrameUintBase::typeKey: @@ -554,6 +567,9 @@ case FollowPathConstraintBase::offsetPropertyKey: object->as<FollowPathConstraintBase>()->offset(value); break; + case AxisBase::normalizedPropertyKey: + object->as<AxisBase>()->normalized(value); + break; case LayoutComponentStyleBase::intrinsicallySizedValuePropertyKey: object->as<LayoutComponentStyleBase>()->intrinsicallySizedValue(value); break; @@ -701,6 +717,12 @@ case NestedArtboardLayoutBase::instanceHeightScaleTypePropertyKey: object->as<NestedArtboardLayoutBase>()->instanceHeightScaleType(value); break; + case NSlicerTileModeBase::patchIndexPropertyKey: + object->as<NSlicerTileModeBase>()->patchIndex(value); + break; + case NSlicerTileModeBase::stylePropertyKey: + object->as<NSlicerTileModeBase>()->style(value); + break; case LayoutComponentStyleBase::layoutWidthScaleTypePropertyKey: object->as<LayoutComponentStyleBase>()->layoutWidthScaleType(value); break; @@ -1246,6 +1268,9 @@ case NestedArtboardLayoutBase::instanceHeightPropertyKey: object->as<NestedArtboardLayoutBase>()->instanceHeight(value); break; + case AxisBase::offsetPropertyKey: + object->as<AxisBase>()->offset(value); + break; case LayoutComponentStyleBase::gapHorizontalPropertyKey: object->as<LayoutComponentStyleBase>()->gapHorizontal(value); break; @@ -1732,6 +1757,8 @@ return object->as<FollowPathConstraintBase>()->orient(); case FollowPathConstraintBase::offsetPropertyKey: return object->as<FollowPathConstraintBase>()->offset(); + case AxisBase::normalizedPropertyKey: + return object->as<AxisBase>()->normalized(); case LayoutComponentStyleBase::intrinsicallySizedValuePropertyKey: return object->as<LayoutComponentStyleBase>()->intrinsicallySizedValue(); case LayoutComponentStyleBase::linkCornerRadiusPropertyKey: @@ -1833,6 +1860,10 @@ return object->as<NestedArtboardLayoutBase>()->instanceWidthScaleType(); case NestedArtboardLayoutBase::instanceHeightScaleTypePropertyKey: return object->as<NestedArtboardLayoutBase>()->instanceHeightScaleType(); + case NSlicerTileModeBase::patchIndexPropertyKey: + return object->as<NSlicerTileModeBase>()->patchIndex(); + case NSlicerTileModeBase::stylePropertyKey: + return object->as<NSlicerTileModeBase>()->style(); case LayoutComponentStyleBase::layoutWidthScaleTypePropertyKey: return object->as<LayoutComponentStyleBase>()->layoutWidthScaleType(); case LayoutComponentStyleBase::layoutHeightScaleTypePropertyKey: @@ -2206,6 +2237,8 @@ return object->as<NestedArtboardLayoutBase>()->instanceWidth(); case NestedArtboardLayoutBase::instanceHeightPropertyKey: return object->as<NestedArtboardLayoutBase>()->instanceHeight(); + case AxisBase::offsetPropertyKey: + return object->as<AxisBase>()->offset(); case LayoutComponentStyleBase::gapHorizontalPropertyKey: return object->as<LayoutComponentStyleBase>()->gapHorizontal(); case LayoutComponentStyleBase::gapVerticalPropertyKey: @@ -2521,6 +2554,7 @@ case IKConstraintBase::invertDirectionPropertyKey: case FollowPathConstraintBase::orientPropertyKey: case FollowPathConstraintBase::offsetPropertyKey: + case AxisBase::normalizedPropertyKey: case LayoutComponentStyleBase::intrinsicallySizedValuePropertyKey: case LayoutComponentStyleBase::linkCornerRadiusPropertyKey: case NestedSimpleAnimationBase::isPlayingPropertyKey: @@ -2569,6 +2603,8 @@ case NestedArtboardLayoutBase::instanceHeightUnitsValuePropertyKey: case NestedArtboardLayoutBase::instanceWidthScaleTypePropertyKey: case NestedArtboardLayoutBase::instanceHeightScaleTypePropertyKey: + case NSlicerTileModeBase::patchIndexPropertyKey: + case NSlicerTileModeBase::stylePropertyKey: case LayoutComponentStyleBase::layoutWidthScaleTypePropertyKey: case LayoutComponentStyleBase::layoutHeightScaleTypePropertyKey: case LayoutComponentStyleBase::layoutAlignmentTypePropertyKey: @@ -2749,6 +2785,7 @@ case NodeBase::yArtboardPropertyKey: case NestedArtboardLayoutBase::instanceWidthPropertyKey: case NestedArtboardLayoutBase::instanceHeightPropertyKey: + case AxisBase::offsetPropertyKey: case LayoutComponentStyleBase::gapHorizontalPropertyKey: case LayoutComponentStyleBase::gapVerticalPropertyKey: case LayoutComponentStyleBase::maxWidthPropertyKey: @@ -2947,6 +2984,8 @@ return object->is<FollowPathConstraintBase>(); case FollowPathConstraintBase::offsetPropertyKey: return object->is<FollowPathConstraintBase>(); + case AxisBase::normalizedPropertyKey: + return object->is<AxisBase>(); case LayoutComponentStyleBase::intrinsicallySizedValuePropertyKey: return object->is<LayoutComponentStyleBase>(); case LayoutComponentStyleBase::linkCornerRadiusPropertyKey: @@ -3041,6 +3080,10 @@ return object->is<NestedArtboardLayoutBase>(); case NestedArtboardLayoutBase::instanceHeightScaleTypePropertyKey: return object->is<NestedArtboardLayoutBase>(); + case NSlicerTileModeBase::patchIndexPropertyKey: + return object->is<NSlicerTileModeBase>(); + case NSlicerTileModeBase::stylePropertyKey: + return object->is<NSlicerTileModeBase>(); case LayoutComponentStyleBase::layoutWidthScaleTypePropertyKey: return object->is<LayoutComponentStyleBase>(); case LayoutComponentStyleBase::layoutHeightScaleTypePropertyKey: @@ -3393,6 +3436,8 @@ return object->is<NestedArtboardLayoutBase>(); case NestedArtboardLayoutBase::instanceHeightPropertyKey: return object->is<NestedArtboardLayoutBase>(); + case AxisBase::offsetPropertyKey: + return object->is<AxisBase>(); case LayoutComponentStyleBase::gapHorizontalPropertyKey: return object->is<LayoutComponentStyleBase>(); case LayoutComponentStyleBase::gapVerticalPropertyKey:
diff --git a/include/rive/generated/layout/axis_base.hpp b/include/rive/generated/layout/axis_base.hpp new file mode 100644 index 0000000..b7bf729 --- /dev/null +++ b/include/rive/generated/layout/axis_base.hpp
@@ -0,0 +1,89 @@ +#ifndef _RIVE_AXIS_BASE_HPP_ +#define _RIVE_AXIS_BASE_HPP_ +#include "rive/component.hpp" +#include "rive/core/field_types/core_bool_type.hpp" +#include "rive/core/field_types/core_double_type.hpp" +namespace rive +{ +class AxisBase : public Component +{ +protected: + typedef Component Super; + +public: + static const uint16_t typeKey = 492; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case AxisBase::typeKey: + case ComponentBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t offsetPropertyKey = 675; + static const uint16_t normalizedPropertyKey = 676; + +private: + float m_Offset = 0.0f; + bool m_Normalized = false; + +public: + inline float offset() const { return m_Offset; } + void offset(float value) + { + if (m_Offset == value) + { + return; + } + m_Offset = value; + offsetChanged(); + } + + inline bool normalized() const { return m_Normalized; } + void normalized(bool value) + { + if (m_Normalized == value) + { + return; + } + m_Normalized = value; + normalizedChanged(); + } + + void copy(const AxisBase& object) + { + m_Offset = object.m_Offset; + m_Normalized = object.m_Normalized; + Component::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case offsetPropertyKey: + m_Offset = CoreDoubleType::deserialize(reader); + return true; + case normalizedPropertyKey: + m_Normalized = CoreBoolType::deserialize(reader); + return true; + } + return Component::deserialize(propertyKey, reader); + } + +protected: + virtual void offsetChanged() {} + virtual void normalizedChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/generated/layout/axis_x_base.hpp b/include/rive/generated/layout/axis_x_base.hpp new file mode 100644 index 0000000..0785962 --- /dev/null +++ b/include/rive/generated/layout/axis_x_base.hpp
@@ -0,0 +1,37 @@ +#ifndef _RIVE_AXIS_XBASE_HPP_ +#define _RIVE_AXIS_XBASE_HPP_ +#include "rive/layout/axis.hpp" +namespace rive +{ +class AxisXBase : public Axis +{ +protected: + typedef Axis Super; + +public: + static const uint16_t typeKey = 495; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case AxisXBase::typeKey: + case AxisBase::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/layout/axis_y_base.hpp b/include/rive/generated/layout/axis_y_base.hpp new file mode 100644 index 0000000..e54b22a --- /dev/null +++ b/include/rive/generated/layout/axis_y_base.hpp
@@ -0,0 +1,37 @@ +#ifndef _RIVE_AXIS_YBASE_HPP_ +#define _RIVE_AXIS_YBASE_HPP_ +#include "rive/layout/axis.hpp" +namespace rive +{ +class AxisYBase : public Axis +{ +protected: + typedef Axis Super; + +public: + static const uint16_t typeKey = 494; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case AxisYBase::typeKey: + case AxisBase::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/layout/n_slicer_base.hpp b/include/rive/generated/layout/n_slicer_base.hpp new file mode 100644 index 0000000..23fa548 --- /dev/null +++ b/include/rive/generated/layout/n_slicer_base.hpp
@@ -0,0 +1,36 @@ +#ifndef _RIVE_N_SLICER_BASE_HPP_ +#define _RIVE_N_SLICER_BASE_HPP_ +#include "rive/component.hpp" +namespace rive +{ +class NSlicerBase : public Component +{ +protected: + typedef Component Super; + +public: + static const uint16_t typeKey = 493; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case NSlicerBase::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/layout/n_slicer_tile_mode_base.hpp b/include/rive/generated/layout/n_slicer_tile_mode_base.hpp new file mode 100644 index 0000000..c3673f0 --- /dev/null +++ b/include/rive/generated/layout/n_slicer_tile_mode_base.hpp
@@ -0,0 +1,89 @@ +#ifndef _RIVE_N_SLICER_TILE_MODE_BASE_HPP_ +#define _RIVE_N_SLICER_TILE_MODE_BASE_HPP_ +#include "rive/component.hpp" +#include "rive/core/field_types/core_uint_type.hpp" +namespace rive +{ +class NSlicerTileModeBase : public Component +{ +protected: + typedef Component Super; + +public: + static const uint16_t typeKey = 491; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case NSlicerTileModeBase::typeKey: + case ComponentBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t patchIndexPropertyKey = 672; + static const uint16_t stylePropertyKey = 673; + +private: + uint32_t m_PatchIndex = 0; + uint32_t m_Style = 0; + +public: + inline uint32_t patchIndex() const { return m_PatchIndex; } + void patchIndex(uint32_t value) + { + if (m_PatchIndex == value) + { + return; + } + m_PatchIndex = value; + patchIndexChanged(); + } + + inline uint32_t style() const { return m_Style; } + void style(uint32_t value) + { + if (m_Style == value) + { + return; + } + m_Style = value; + styleChanged(); + } + + Core* clone() const override; + void copy(const NSlicerTileModeBase& object) + { + m_PatchIndex = object.m_PatchIndex; + m_Style = object.m_Style; + Component::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case patchIndexPropertyKey: + m_PatchIndex = CoreUintType::deserialize(reader); + return true; + case stylePropertyKey: + m_Style = CoreUintType::deserialize(reader); + return true; + } + return Component::deserialize(propertyKey, reader); + } + +protected: + virtual void patchIndexChanged() {} + virtual void styleChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/layout/axis.hpp b/include/rive/layout/axis.hpp new file mode 100644 index 0000000..a5eef6e --- /dev/null +++ b/include/rive/layout/axis.hpp
@@ -0,0 +1,13 @@ +#ifndef _RIVE_AXIS_HPP_ +#define _RIVE_AXIS_HPP_ +#include "rive/generated/layout/axis_base.hpp" +#include <stdio.h> +namespace rive +{ +class Axis : public AxisBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/layout/axis_x.hpp b/include/rive/layout/axis_x.hpp new file mode 100644 index 0000000..3cd9a37 --- /dev/null +++ b/include/rive/layout/axis_x.hpp
@@ -0,0 +1,13 @@ +#ifndef _RIVE_AXIS_X_HPP_ +#define _RIVE_AXIS_X_HPP_ +#include "rive/generated/layout/axis_x_base.hpp" +#include <stdio.h> +namespace rive +{ +class AxisX : public AxisXBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/layout/axis_y.hpp b/include/rive/layout/axis_y.hpp new file mode 100644 index 0000000..3f38d83 --- /dev/null +++ b/include/rive/layout/axis_y.hpp
@@ -0,0 +1,13 @@ +#ifndef _RIVE_AXIS_Y_HPP_ +#define _RIVE_AXIS_Y_HPP_ +#include "rive/generated/layout/axis_y_base.hpp" +#include <stdio.h> +namespace rive +{ +class AxisY : public AxisYBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/layout/n_slicer.hpp b/include/rive/layout/n_slicer.hpp new file mode 100644 index 0000000..7f13a61 --- /dev/null +++ b/include/rive/layout/n_slicer.hpp
@@ -0,0 +1,13 @@ +#ifndef _RIVE_N_SLICER_HPP_ +#define _RIVE_N_SLICER_HPP_ +#include "rive/generated/layout/n_slicer_base.hpp" +#include <stdio.h> +namespace rive +{ +class NSlicer : public NSlicerBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/layout/n_slicer_tile_mode.hpp b/include/rive/layout/n_slicer_tile_mode.hpp new file mode 100644 index 0000000..06e7cab --- /dev/null +++ b/include/rive/layout/n_slicer_tile_mode.hpp
@@ -0,0 +1,13 @@ +#ifndef _RIVE_N_SLICER_TILE_MODE_HPP_ +#define _RIVE_N_SLICER_TILE_MODE_HPP_ +#include "rive/generated/layout/n_slicer_tile_mode_base.hpp" +#include <stdio.h> +namespace rive +{ +class NSlicerTileMode : public NSlicerTileModeBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/src/generated/layout/axis_x_base.cpp b/src/generated/layout/axis_x_base.cpp new file mode 100644 index 0000000..172c284 --- /dev/null +++ b/src/generated/layout/axis_x_base.cpp
@@ -0,0 +1,11 @@ +#include "rive/generated/layout/axis_x_base.hpp" +#include "rive/layout/axis_x.hpp" + +using namespace rive; + +Core* AxisXBase::clone() const +{ + auto cloned = new AxisX(); + cloned->copy(*this); + return cloned; +}
diff --git a/src/generated/layout/axis_y_base.cpp b/src/generated/layout/axis_y_base.cpp new file mode 100644 index 0000000..8815cef --- /dev/null +++ b/src/generated/layout/axis_y_base.cpp
@@ -0,0 +1,11 @@ +#include "rive/generated/layout/axis_y_base.hpp" +#include "rive/layout/axis_y.hpp" + +using namespace rive; + +Core* AxisYBase::clone() const +{ + auto cloned = new AxisY(); + cloned->copy(*this); + return cloned; +}
diff --git a/src/generated/layout/n_slicer_base.cpp b/src/generated/layout/n_slicer_base.cpp new file mode 100644 index 0000000..49d6f37 --- /dev/null +++ b/src/generated/layout/n_slicer_base.cpp
@@ -0,0 +1,11 @@ +#include "rive/generated/layout/n_slicer_base.hpp" +#include "rive/layout/n_slicer.hpp" + +using namespace rive; + +Core* NSlicerBase::clone() const +{ + auto cloned = new NSlicer(); + cloned->copy(*this); + return cloned; +}
diff --git a/src/generated/layout/n_slicer_tile_mode_base.cpp b/src/generated/layout/n_slicer_tile_mode_base.cpp new file mode 100644 index 0000000..068c59c --- /dev/null +++ b/src/generated/layout/n_slicer_tile_mode_base.cpp
@@ -0,0 +1,11 @@ +#include "rive/generated/layout/n_slicer_tile_mode_base.hpp" +#include "rive/layout/n_slicer_tile_mode.hpp" + +using namespace rive; + +Core* NSlicerTileModeBase::clone() const +{ + auto cloned = new NSlicerTileMode(); + cloned->copy(*this); + return cloned; +}