update scripted drawable clipping to new strategy and remove unused function (#11195) 8002b223a3

* update clipping to new strategy

Co-authored-by: hernan <hernan@rive.app>
This commit is contained in:
bodymovin
2025-12-02 22:54:40 +00:00
parent 3d9ba122b4
commit cbd6691f87
6 changed files with 32 additions and 127 deletions

View File

@@ -1 +1 @@
7fae9fb6c80697fd3d9dcb3dee87fb9922135b4a
8002b223a3709255afb943a52d15eaa27ce72d53

View File

@@ -32,7 +32,6 @@ protected:
public:
BlendMode blendMode() const { return (BlendMode)blendModeValue(); }
ClipResult applyClip(Renderer* renderer) const;
virtual void draw(Renderer* renderer) = 0;
virtual Core* hitTest(HitInfo*, const Mat2D&) = 0;
bool hitTestPoint(const Vec2D& position,

View File

@@ -57,6 +57,7 @@ public:
std::vector<HitComponent*> hitComponents(StateMachineInstance* sm) override;
bool worldToLocal(Vec2D world, Vec2D* local);
void markNeedsUpdate() override;
bool willDraw() override;
Component* component() override { return this; }
};

View File

@@ -43,38 +43,6 @@ void Drawable::addClippingShape(ClippingShape* shape)
m_ClippingShapes.push_back(shape);
}
ClipResult Drawable::applyClip(Renderer* renderer) const
{
if (m_ClippingShapes.size() == 0)
{
return ClipResult::noClip;
}
renderer->save();
for (auto clippingShape : m_ClippingShapes)
{
if (!clippingShape->isVisible())
{
continue;
}
ShapePaintPath* path = clippingShape->path();
if (path == nullptr)
{
return ClipResult::emptyClip;
}
RenderPath* renderPath = path->renderPath(this);
if (renderPath == nullptr)
{
return ClipResult::emptyClip;
}
renderer->clipPath(renderPath);
}
return ClipResult::clip;
}
bool Drawable::willDraw() { return !isHidden(); }
bool Drawable::isChildOfLayout(LayoutComponent* layout)

View File

@@ -17,43 +17,34 @@ bool ScriptedDrawable::scriptInit(LuaState* state)
void ScriptedDrawable::draw(Renderer* renderer)
{
if (m_state == nullptr || !draws())
{
return;
}
auto state = m_state->state;
ClipResult clipResult = applyClip(renderer);
if (clipResult == ClipResult::noClip)
if (m_needsSaveOperation)
{
// We didn't clip, so make sure to save as we'll be doing some
// transformations.
renderer->save();
}
if (clipResult != ClipResult::emptyClip)
{
renderer->transform(worldTransform());
renderer->transform(worldTransform());
rive_lua_pushRef(state, m_self);
if (static_cast<lua_Type>(lua_getfield(state, -1, "draw")) !=
LUA_TFUNCTION)
{
fprintf(stderr, "expected draw to be a function\n");
}
else
{
lua_pushvalue(state, -2);
auto scriptedRenderer =
lua_newrive<ScriptedRenderer>(state, renderer);
if (static_cast<lua_Status>(rive_lua_pcall(state, 2, 0)) != LUA_OK)
{
rive_lua_pop(state, 1);
}
scriptedRenderer->end();
}
rive_lua_pop(state, 1);
rive_lua_pushRef(state, m_self);
if (static_cast<lua_Type>(lua_getfield(state, -1, "draw")) != LUA_TFUNCTION)
{
fprintf(stderr, "expected draw to be a function\n");
}
else
{
lua_pushvalue(state, -2);
auto scriptedRenderer = lua_newrive<ScriptedRenderer>(state, renderer);
if (static_cast<lua_Status>(rive_lua_pcall(state, 2, 0)) != LUA_OK)
{
rive_lua_pop(state, 1);
}
scriptedRenderer->end();
}
rive_lua_pop(state, 1);
if (m_needsSaveOperation)
{
renderer->restore();
}
renderer->restore();
}
std::vector<HitComponent*> ScriptedDrawable::hitComponents(
@@ -111,6 +102,12 @@ HitResult HitScriptedDrawable::processEvent(Vec2D position,
rive_lua_pop(state, 1);
return hitResult;
}
bool ScriptedDrawable::willDraw()
{
return Super::willDraw() && m_state != nullptr && draws();
}
#else
void ScriptedDrawable::draw(Renderer* renderer) {}
@@ -128,6 +125,9 @@ HitResult HitScriptedDrawable::processEvent(Vec2D position,
{
return HitResult::none;
}
bool ScriptedDrawable::willDraw() { return Super::willDraw() && draws(); }
#endif
void ScriptedDrawable::update(ComponentDirt value)

View File

@@ -104,69 +104,6 @@ TEST_CASE("artboard is clipped correctly", "[clipping]")
}
}
TEST_CASE("Shape does not have any clipping paths visible", "[clipping]")
{
ClippingFactory factory;
auto file = ReadRiveFile("assets/clip_tests.riv", &factory);
auto artboard = file->artboard("Empty-Shape");
REQUIRE(artboard != nullptr);
artboard->updateComponents();
auto node = artboard->find("Ellipse-clipper");
REQUIRE(node != nullptr);
REQUIRE(node->is<rive::Shape>());
rive::Shape* shape = static_cast<rive::Shape*>(node);
REQUIRE(shape->isEmpty() == true);
auto clippedNode = artboard->find("Rectangle-clipped");
REQUIRE(clippedNode != nullptr);
REQUIRE(clippedNode->is<rive::Shape>());
rive::Shape* clippedShape = static_cast<rive::Shape*>(clippedNode);
rive::NoOpRenderer renderer;
auto clipResult = clippedShape->applyClip(&renderer);
REQUIRE(clipResult == rive::ClipResult::emptyClip);
}
TEST_CASE("Shape has at least a clipping path visible", "[clipping]")
{
ClippingFactory factory;
auto file = ReadRiveFile("assets/clip_tests.riv", &factory);
auto artboard = file->artboard("Hidden-Path-Visible-Path");
REQUIRE(artboard != nullptr);
artboard->updateComponents();
auto node = artboard->find("Ellipse-clipper");
REQUIRE(node != nullptr);
REQUIRE(node->is<rive::Shape>());
rive::Shape* shape = static_cast<rive::Shape*>(node);
REQUIRE(shape->isEmpty() == false);
auto clippedNode = artboard->find("Rectangle-clipped");
REQUIRE(clippedNode != nullptr);
REQUIRE(clippedNode->is<rive::Shape>());
rive::Shape* clippedShape = static_cast<rive::Shape*>(clippedNode);
rive::NoOpRenderer renderer;
auto clipResult = clippedShape->applyClip(&renderer);
REQUIRE(clipResult == rive::ClipResult::clip);
}
TEST_CASE("Shape returns an empty clip when one clipping shape is empty",
"[clipping]")
{
ClippingFactory factory;
auto file = ReadRiveFile("assets/clip_tests.riv", &factory);
auto artboard = file->artboard("One-Clipping-Shape-Visible-One-Hidden");
REQUIRE(artboard != nullptr);
artboard->updateComponents();
auto node = artboard->find("Rectangle-clipped");
REQUIRE(node != nullptr);
REQUIRE(node->is<rive::Shape>());
rive::Shape* shape = static_cast<rive::Shape*>(node);
rive::NoOpRenderer renderer;
auto clipResult = shape->applyClip(&renderer);
REQUIRE(clipResult == rive::ClipResult::emptyClip);
}
TEST_CASE("Apply clipping to elements that are moved outside their hierarchy",
"[clipping]")
{