Add support for optional clipping to artboard.
diff --git a/dev/defs/artboard.json b/dev/defs/artboard.json index 25e825d..05782ba 100644 --- a/dev/defs/artboard.json +++ b/dev/defs/artboard.json
@@ -4,8 +4,17 @@ "int": 1, "string": "artboard" }, - "extends": "container_component.json", + "extends": "world_transform_component.json", "properties": { + "clip": { + "type": "bool", + "initialValue": "true", + "key": { + "int": 196, + "string": "clip" + }, + "description": "True when the artboard bounds clip its contents." + }, "width": { "type": "double", "initialValue": "0",
diff --git a/dev/defs/backboard.json b/dev/defs/backboard.json index d2b1519..ea19b83 100644 --- a/dev/defs/backboard.json +++ b/dev/defs/backboard.json
@@ -23,7 +23,7 @@ "int": 44, "string": "mainArtboardId" }, - "description": "Identifier used to track the main artboard (this is the default one that shows up in runtimes unless specified).", + "description": "Identifier used to track the main artboard (this is the default one that shows up in runtimes unless specified).", "runtime": false }, "colorValue": {
diff --git a/dev/defs/transform_component.json b/dev/defs/transform_component.json index 2e1ef05..084705f 100644 --- a/dev/defs/transform_component.json +++ b/dev/defs/transform_component.json
@@ -5,7 +5,7 @@ "string": "transformcomponent" }, "abstract": true, - "extends": "container_component.json", + "extends": "world_transform_component.json", "properties": { "rotation": { "type": "double", @@ -35,15 +35,6 @@ "int": 17, "string": "sy" } - }, - "opacity": { - "type": "double", - "initialValue": "1", - "animates": true, - "key": { - "int": 18, - "string": "opacity" - } } } } \ No newline at end of file
diff --git a/dev/defs/world_transform_component.json b/dev/defs/world_transform_component.json new file mode 100644 index 0000000..249706b --- /dev/null +++ b/dev/defs/world_transform_component.json
@@ -0,0 +1,20 @@ +{ + "name": "WorldTransformComponent", + "key": { + "int": 91, + "string": "worldtransformcomponent" + }, + "abstract": true, + "extends": "container_component.json", + "properties": { + "opacity": { + "type": "double", + "initialValue": "1", + "animates": true, + "key": { + "int": 18, + "string": "opacity" + } + } + } +} \ No newline at end of file
diff --git a/include/rive/generated/artboard_base.hpp b/include/rive/generated/artboard_base.hpp index e6229bb..87b4e2f 100644 --- a/include/rive/generated/artboard_base.hpp +++ b/include/rive/generated/artboard_base.hpp
@@ -1,13 +1,14 @@ #ifndef _RIVE_ARTBOARD_BASE_HPP_ #define _RIVE_ARTBOARD_BASE_HPP_ -#include "rive/container_component.hpp" +#include "rive/core/field_types/core_bool_type.hpp" #include "rive/core/field_types/core_double_type.hpp" +#include "rive/world_transform_component.hpp" namespace rive { - class ArtboardBase : public ContainerComponent + class ArtboardBase : public WorldTransformComponent { protected: - typedef ContainerComponent Super; + typedef WorldTransformComponent Super; public: static const uint16_t typeKey = 1; @@ -19,6 +20,7 @@ switch (typeKey) { case ArtboardBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true; @@ -29,6 +31,7 @@ uint16_t coreType() const override { return typeKey; } + static const uint16_t clipPropertyKey = 196; static const uint16_t widthPropertyKey = 7; static const uint16_t heightPropertyKey = 8; static const uint16_t xPropertyKey = 9; @@ -37,6 +40,7 @@ static const uint16_t originYPropertyKey = 12; private: + bool m_Clip = true; float m_Width = 0.0f; float m_Height = 0.0f; float m_X = 0.0f; @@ -44,6 +48,17 @@ float m_OriginX = 0.0f; float m_OriginY = 0.0f; public: + inline bool clip() const { return m_Clip; } + void clip(bool value) + { + if (m_Clip == value) + { + return; + } + m_Clip = value; + clipChanged(); + } + inline float width() const { return m_Width; } void width(float value) { @@ -113,19 +128,23 @@ Core* clone() const override; void copy(const ArtboardBase& object) { + m_Clip = object.m_Clip; m_Width = object.m_Width; m_Height = object.m_Height; m_X = object.m_X; m_Y = object.m_Y; m_OriginX = object.m_OriginX; m_OriginY = object.m_OriginY; - ContainerComponent::copy(object); + WorldTransformComponent::copy(object); } bool deserialize(uint16_t propertyKey, BinaryReader& reader) override { switch (propertyKey) { + case clipPropertyKey: + m_Clip = CoreBoolType::deserialize(reader); + return true; case widthPropertyKey: m_Width = CoreDoubleType::deserialize(reader); return true; @@ -145,10 +164,11 @@ m_OriginY = CoreDoubleType::deserialize(reader); return true; } - return ContainerComponent::deserialize(propertyKey, reader); + return WorldTransformComponent::deserialize(propertyKey, reader); } protected: + virtual void clipChanged() {} virtual void widthChanged() {} virtual void heightChanged() {} virtual void xChanged() {}
diff --git a/include/rive/generated/bones/bone_base.hpp b/include/rive/generated/bones/bone_base.hpp index e6df26e..b4ce7a5 100644 --- a/include/rive/generated/bones/bone_base.hpp +++ b/include/rive/generated/bones/bone_base.hpp
@@ -21,6 +21,7 @@ case BoneBase::typeKey: case SkeletalComponentBase::typeKey: case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true;
diff --git a/include/rive/generated/bones/root_bone_base.hpp b/include/rive/generated/bones/root_bone_base.hpp index 8c869ef..a7aa313 100644 --- a/include/rive/generated/bones/root_bone_base.hpp +++ b/include/rive/generated/bones/root_bone_base.hpp
@@ -22,6 +22,7 @@ case BoneBase::typeKey: case SkeletalComponentBase::typeKey: case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true;
diff --git a/include/rive/generated/bones/skeletal_component_base.hpp b/include/rive/generated/bones/skeletal_component_base.hpp index f31fe37..73b7ec8 100644 --- a/include/rive/generated/bones/skeletal_component_base.hpp +++ b/include/rive/generated/bones/skeletal_component_base.hpp
@@ -19,6 +19,7 @@ { case SkeletalComponentBase::typeKey: case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true;
diff --git a/include/rive/generated/core_registry.hpp b/include/rive/generated/core_registry.hpp index dde79f7..8c6d1a4 100644 --- a/include/rive/generated/core_registry.hpp +++ b/include/rive/generated/core_registry.hpp
@@ -87,6 +87,7 @@ #include "rive/shapes/straight_vertex.hpp" #include "rive/shapes/triangle.hpp" #include "rive/transform_component.hpp" +#include "rive/world_transform_component.hpp" namespace rive { class CoreRegistry @@ -489,6 +490,9 @@ case TrimPathBase::offsetPropertyKey: object->as<TrimPathBase>()->offset(value); break; + case WorldTransformComponentBase::opacityPropertyKey: + object->as<WorldTransformComponentBase>()->opacity(value); + break; case TransformComponentBase::rotationPropertyKey: object->as<TransformComponentBase>()->rotation(value); break; @@ -498,9 +502,6 @@ case TransformComponentBase::scaleYPropertyKey: object->as<TransformComponentBase>()->scaleY(value); break; - case TransformComponentBase::opacityPropertyKey: - object->as<TransformComponentBase>()->opacity(value); - break; case NodeBase::xPropertyKey: object->as<NodeBase>()->x(value); break; @@ -695,6 +696,9 @@ case ClippingShapeBase::isVisiblePropertyKey: object->as<ClippingShapeBase>()->isVisible(value); break; + case ArtboardBase::clipPropertyKey: + object->as<ArtboardBase>()->clip(value); + break; } } static void setColor(Core* object, int propertyKey, int value) @@ -900,14 +904,14 @@ return object->as<TrimPathBase>()->end(); case TrimPathBase::offsetPropertyKey: return object->as<TrimPathBase>()->offset(); + case WorldTransformComponentBase::opacityPropertyKey: + return object->as<WorldTransformComponentBase>()->opacity(); case TransformComponentBase::rotationPropertyKey: return object->as<TransformComponentBase>()->rotation(); case TransformComponentBase::scaleXPropertyKey: return object->as<TransformComponentBase>()->scaleX(); case TransformComponentBase::scaleYPropertyKey: return object->as<TransformComponentBase>()->scaleY(); - case TransformComponentBase::opacityPropertyKey: - return object->as<TransformComponentBase>()->opacity(); case NodeBase::xPropertyKey: return object->as<NodeBase>()->x(); case NodeBase::yPropertyKey: @@ -1046,6 +1050,8 @@ return object->as<RectangleBase>()->linkCornerRadius(); case ClippingShapeBase::isVisiblePropertyKey: return object->as<ClippingShapeBase>()->isVisible(); + case ArtboardBase::clipPropertyKey: + return object->as<ArtboardBase>()->clip(); } return false; } @@ -1148,10 +1154,10 @@ case TrimPathBase::startPropertyKey: case TrimPathBase::endPropertyKey: case TrimPathBase::offsetPropertyKey: + case WorldTransformComponentBase::opacityPropertyKey: case TransformComponentBase::rotationPropertyKey: case TransformComponentBase::scaleXPropertyKey: case TransformComponentBase::scaleYPropertyKey: - case TransformComponentBase::opacityPropertyKey: case NodeBase::xPropertyKey: case NodeBase::yPropertyKey: case PathVertexBase::xPropertyKey: @@ -1214,6 +1220,7 @@ case PointsPathBase::isClosedPropertyKey: case RectangleBase::linkCornerRadiusPropertyKey: case ClippingShapeBase::isVisiblePropertyKey: + case ArtboardBase::clipPropertyKey: return CoreBoolType::id; case KeyFrameColorBase::valuePropertyKey: case SolidColorBase::colorValuePropertyKey:
diff --git a/include/rive/generated/drawable_base.hpp b/include/rive/generated/drawable_base.hpp index c545f1f..b3ee959 100644 --- a/include/rive/generated/drawable_base.hpp +++ b/include/rive/generated/drawable_base.hpp
@@ -21,6 +21,7 @@ case DrawableBase::typeKey: case NodeBase::typeKey: case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true;
diff --git a/include/rive/generated/node_base.hpp b/include/rive/generated/node_base.hpp index 1bcbb43..fbd26c3 100644 --- a/include/rive/generated/node_base.hpp +++ b/include/rive/generated/node_base.hpp
@@ -20,6 +20,7 @@ { case NodeBase::typeKey: case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true;
diff --git a/include/rive/generated/shapes/ellipse_base.hpp b/include/rive/generated/shapes/ellipse_base.hpp index ad90986..29d3b0f 100644 --- a/include/rive/generated/shapes/ellipse_base.hpp +++ b/include/rive/generated/shapes/ellipse_base.hpp
@@ -22,6 +22,7 @@ case PathBase::typeKey: case NodeBase::typeKey: case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true;
diff --git a/include/rive/generated/shapes/parametric_path_base.hpp b/include/rive/generated/shapes/parametric_path_base.hpp index 1c4ef80..80a84f2 100644 --- a/include/rive/generated/shapes/parametric_path_base.hpp +++ b/include/rive/generated/shapes/parametric_path_base.hpp
@@ -22,6 +22,7 @@ case PathBase::typeKey: case NodeBase::typeKey: case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true;
diff --git a/include/rive/generated/shapes/path_base.hpp b/include/rive/generated/shapes/path_base.hpp index 6138190..12aa10f 100644 --- a/include/rive/generated/shapes/path_base.hpp +++ b/include/rive/generated/shapes/path_base.hpp
@@ -21,6 +21,7 @@ case PathBase::typeKey: case NodeBase::typeKey: case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true;
diff --git a/include/rive/generated/shapes/points_path_base.hpp b/include/rive/generated/shapes/points_path_base.hpp index 5bf78d8..dfa8692 100644 --- a/include/rive/generated/shapes/points_path_base.hpp +++ b/include/rive/generated/shapes/points_path_base.hpp
@@ -22,6 +22,7 @@ case PathBase::typeKey: case NodeBase::typeKey: case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true;
diff --git a/include/rive/generated/shapes/polygon_base.hpp b/include/rive/generated/shapes/polygon_base.hpp index dfb3f84..899f0c9 100644 --- a/include/rive/generated/shapes/polygon_base.hpp +++ b/include/rive/generated/shapes/polygon_base.hpp
@@ -24,6 +24,7 @@ case PathBase::typeKey: case NodeBase::typeKey: case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true;
diff --git a/include/rive/generated/shapes/rectangle_base.hpp b/include/rive/generated/shapes/rectangle_base.hpp index 697f2ed..d37bbaa 100644 --- a/include/rive/generated/shapes/rectangle_base.hpp +++ b/include/rive/generated/shapes/rectangle_base.hpp
@@ -24,6 +24,7 @@ case PathBase::typeKey: case NodeBase::typeKey: case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true;
diff --git a/include/rive/generated/shapes/shape_base.hpp b/include/rive/generated/shapes/shape_base.hpp index a705749..7efb26f 100644 --- a/include/rive/generated/shapes/shape_base.hpp +++ b/include/rive/generated/shapes/shape_base.hpp
@@ -21,6 +21,7 @@ case DrawableBase::typeKey: case NodeBase::typeKey: case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true;
diff --git a/include/rive/generated/shapes/star_base.hpp b/include/rive/generated/shapes/star_base.hpp index ae0d615..c72ff49 100644 --- a/include/rive/generated/shapes/star_base.hpp +++ b/include/rive/generated/shapes/star_base.hpp
@@ -24,6 +24,7 @@ case PathBase::typeKey: case NodeBase::typeKey: case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true;
diff --git a/include/rive/generated/shapes/triangle_base.hpp b/include/rive/generated/shapes/triangle_base.hpp index 1078889..437387d 100644 --- a/include/rive/generated/shapes/triangle_base.hpp +++ b/include/rive/generated/shapes/triangle_base.hpp
@@ -22,6 +22,7 @@ case PathBase::typeKey: case NodeBase::typeKey: case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true;
diff --git a/include/rive/generated/transform_component_base.hpp b/include/rive/generated/transform_component_base.hpp index b85a64f..8ecae51 100644 --- a/include/rive/generated/transform_component_base.hpp +++ b/include/rive/generated/transform_component_base.hpp
@@ -1,13 +1,13 @@ #ifndef _RIVE_TRANSFORM_COMPONENT_BASE_HPP_ #define _RIVE_TRANSFORM_COMPONENT_BASE_HPP_ -#include "rive/container_component.hpp" #include "rive/core/field_types/core_double_type.hpp" +#include "rive/world_transform_component.hpp" namespace rive { - class TransformComponentBase : public ContainerComponent + class TransformComponentBase : public WorldTransformComponent { protected: - typedef ContainerComponent Super; + typedef WorldTransformComponent Super; public: static const uint16_t typeKey = 38; @@ -19,6 +19,7 @@ switch (typeKey) { case TransformComponentBase::typeKey: + case WorldTransformComponentBase::typeKey: case ContainerComponentBase::typeKey: case ComponentBase::typeKey: return true; @@ -32,13 +33,11 @@ static const uint16_t rotationPropertyKey = 15; static const uint16_t scaleXPropertyKey = 16; static const uint16_t scaleYPropertyKey = 17; - static const uint16_t opacityPropertyKey = 18; private: float m_Rotation = 0.0f; float m_ScaleX = 1.0f; float m_ScaleY = 1.0f; - float m_Opacity = 1.0f; public: inline float rotation() const { return m_Rotation; } void rotation(float value) @@ -73,24 +72,12 @@ scaleYChanged(); } - inline float opacity() const { return m_Opacity; } - void opacity(float value) - { - if (m_Opacity == value) - { - return; - } - m_Opacity = value; - opacityChanged(); - } - void copy(const TransformComponentBase& object) { m_Rotation = object.m_Rotation; m_ScaleX = object.m_ScaleX; m_ScaleY = object.m_ScaleY; - m_Opacity = object.m_Opacity; - ContainerComponent::copy(object); + WorldTransformComponent::copy(object); } bool deserialize(uint16_t propertyKey, BinaryReader& reader) override @@ -106,18 +93,14 @@ case scaleYPropertyKey: m_ScaleY = CoreDoubleType::deserialize(reader); return true; - case opacityPropertyKey: - m_Opacity = CoreDoubleType::deserialize(reader); - return true; } - return ContainerComponent::deserialize(propertyKey, reader); + return WorldTransformComponent::deserialize(propertyKey, reader); } protected: virtual void rotationChanged() {} virtual void scaleXChanged() {} virtual void scaleYChanged() {} - virtual void opacityChanged() {} }; } // namespace rive
diff --git a/include/rive/generated/world_transform_component_base.hpp b/include/rive/generated/world_transform_component_base.hpp new file mode 100644 index 0000000..0580642 --- /dev/null +++ b/include/rive/generated/world_transform_component_base.hpp
@@ -0,0 +1,70 @@ +#ifndef _RIVE_WORLD_TRANSFORM_COMPONENT_BASE_HPP_ +#define _RIVE_WORLD_TRANSFORM_COMPONENT_BASE_HPP_ +#include "rive/container_component.hpp" +#include "rive/core/field_types/core_double_type.hpp" +namespace rive +{ + class WorldTransformComponentBase : public ContainerComponent + { + protected: + typedef ContainerComponent Super; + + public: + static const uint16_t typeKey = 91; + + /// Helper to quickly determine if a core object extends another without + /// RTTI at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case WorldTransformComponentBase::typeKey: + case ContainerComponentBase::typeKey: + case ComponentBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t opacityPropertyKey = 18; + + private: + float m_Opacity = 1.0f; + public: + inline float opacity() const { return m_Opacity; } + void opacity(float value) + { + if (m_Opacity == value) + { + return; + } + m_Opacity = value; + opacityChanged(); + } + + void copy(const WorldTransformComponentBase& object) + { + m_Opacity = object.m_Opacity; + ContainerComponent::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case opacityPropertyKey: + m_Opacity = CoreDoubleType::deserialize(reader); + return true; + } + return ContainerComponent::deserialize(propertyKey, reader); + } + + protected: + virtual void opacityChanged() {} + }; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/transform_component.hpp b/include/rive/transform_component.hpp index 80dcf57..4260b24 100644 --- a/include/rive/transform_component.hpp +++ b/include/rive/transform_component.hpp
@@ -6,13 +6,13 @@ namespace rive { class Constraint; + class WorldTransformComponent; class TransformComponent : public TransformComponentBase { private: Mat2D m_Transform; - Mat2D m_WorldTransform; float m_RenderOpacity = 0.0f; - TransformComponent* m_ParentTransformComponent = nullptr; + WorldTransformComponent* m_ParentTransformComponent = nullptr; std::vector<Constraint*> m_Constraints; public: @@ -28,21 +28,17 @@ void updateTransform(); void updateWorldTransform(); void markTransformDirty(); - void markWorldTransformDirty(); - void worldTranslation(Vec2D& result) const; /// Opacity inherited by any child of this transform component. This'll /// later get overridden by effect layers. - virtual float childOpacity() { return m_RenderOpacity; } + float childOpacity() override { return m_RenderOpacity; } float renderOpacity() const { return m_RenderOpacity; } const Mat2D& transform() const; - const Mat2D& worldTransform() const; /// Explicitly dangerous. Use transform/worldTransform when you don't /// need to transform things outside of their hierarchy. Mat2D& mutableTransform(); - Mat2D& mutableWorldTransform(); virtual float x() const = 0; virtual float y() const = 0; @@ -50,7 +46,6 @@ void rotationChanged() override; void scaleXChanged() override; void scaleYChanged() override; - void opacityChanged() override; void addConstraint(Constraint* constraint); };
diff --git a/include/rive/world_transform_component.hpp b/include/rive/world_transform_component.hpp new file mode 100644 index 0000000..c7ab8df --- /dev/null +++ b/include/rive/world_transform_component.hpp
@@ -0,0 +1,26 @@ +#ifndef _RIVE_WORLD_TRANSFORM_COMPONENT_HPP_ +#define _RIVE_WORLD_TRANSFORM_COMPONENT_HPP_ +#include "rive/generated/world_transform_component_base.hpp" +#include "rive/math/mat2d.hpp" + +namespace rive +{ + class TransformComponent; + class WorldTransformComponent : public WorldTransformComponentBase + { + friend class TransformComponent; + + protected: + Mat2D m_WorldTransform; + + public: + void markWorldTransformDirty(); + virtual float childOpacity(); + Mat2D& mutableWorldTransform(); + const Mat2D& worldTransform() const; + void worldTranslation(Vec2D& result) const; + void opacityChanged() override; + }; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/src/artboard.cpp b/src/artboard.cpp index 78b8844..8840a03 100644 --- a/src/artboard.cpp +++ b/src/artboard.cpp
@@ -423,7 +423,10 @@ void Artboard::draw(Renderer* renderer) { renderer->save(); - renderer->clipPath(m_ClipPath->renderPath()); + if (clip()) + { + renderer->clipPath(m_ClipPath->renderPath()); + } Mat2D artboardTransform; artboardTransform[4] = width() * originX();