mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 21:21:17 +01:00
fix: lua error on in-flight path mutation (#11350) 56f08da6b1
* fix: lua error on in-flight path mutation * fix: remove DrawOption * fix: failing tests Co-authored-by: Luigi Rosso <luigi-rosso@users.noreply.github.com>
This commit is contained in:
@@ -1 +1 @@
|
|||||||
923b32059d2ea012fdb47ae141b304f57095a48b
|
56f08da6b1998d346fa791770d7a62a50466e0f7
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ private:
|
|||||||
bool m_didChange = true;
|
bool m_didChange = true;
|
||||||
Artboard* parentArtboard() const;
|
Artboard* parentArtboard() const;
|
||||||
ArtboardHost* m_host = nullptr;
|
ArtboardHost* m_host = nullptr;
|
||||||
|
static uint64_t sm_frameId;
|
||||||
bool sharesLayoutWithHost() const;
|
bool sharesLayoutWithHost() const;
|
||||||
void cloneObjectDataBinds(const Core* object,
|
void cloneObjectDataBinds(const Core* object,
|
||||||
Core* clone,
|
Core* clone,
|
||||||
@@ -128,6 +129,10 @@ private:
|
|||||||
void update(ComponentDirt value) override;
|
void update(ComponentDirt value) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static uint64_t frameId() { return sm_frameId; }
|
||||||
|
#ifdef TESTING
|
||||||
|
static void incFrameId() { sm_frameId++; }
|
||||||
|
#endif
|
||||||
void updateDataBinds(bool applyTargetToSource = true) override;
|
void updateDataBinds(bool applyTargetToSource = true) override;
|
||||||
void host(ArtboardHost* artboardHost);
|
void host(ArtboardHost* artboardHost);
|
||||||
ArtboardHost* host() const;
|
ArtboardHost* host() const;
|
||||||
@@ -229,13 +234,7 @@ public:
|
|||||||
Drawable* firstDrawable() { return m_FirstDrawable; };
|
Drawable* firstDrawable() { return m_FirstDrawable; };
|
||||||
void addScriptedObject(ScriptedObject* object);
|
void addScriptedObject(ScriptedObject* object);
|
||||||
|
|
||||||
enum class DrawOption
|
void drawInternal(Renderer* renderer);
|
||||||
{
|
|
||||||
kNormal,
|
|
||||||
kHideBG,
|
|
||||||
kHideFG,
|
|
||||||
};
|
|
||||||
void draw(Renderer* renderer, DrawOption option);
|
|
||||||
void draw(Renderer* renderer) override;
|
void draw(Renderer* renderer) override;
|
||||||
void addToRenderPath(RenderPath* path, const Mat2D& transform);
|
void addToRenderPath(RenderPath* path, const Mat2D& transform);
|
||||||
void addToRawPath(RawPath& path, const Mat2D* transform);
|
void addToRawPath(RawPath& path, const Mat2D* transform);
|
||||||
|
|||||||
@@ -270,6 +270,7 @@ public:
|
|||||||
static constexpr bool hasMetatable = true;
|
static constexpr bool hasMetatable = true;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uint64_t m_renderFrameId = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScriptedGradient
|
class ScriptedGradient
|
||||||
|
|||||||
114
src/artboard.cpp
114
src/artboard.cpp
@@ -43,6 +43,8 @@
|
|||||||
|
|
||||||
using namespace rive;
|
using namespace rive;
|
||||||
|
|
||||||
|
uint64_t Artboard::sm_frameId = 0;
|
||||||
|
|
||||||
Artboard::Artboard()
|
Artboard::Artboard()
|
||||||
{
|
{
|
||||||
// Artboards need to override default clip value to true.
|
// Artboards need to override default clip value to true.
|
||||||
@@ -1390,9 +1392,13 @@ bool Artboard::hitTestPoint(const Vec2D& position,
|
|||||||
isPrimaryHit);
|
isPrimaryHit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Artboard::draw(Renderer* renderer) { draw(renderer, DrawOption::kNormal); }
|
void Artboard::draw(Renderer* renderer)
|
||||||
|
{
|
||||||
|
sm_frameId++;
|
||||||
|
drawInternal(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
void Artboard::draw(Renderer* renderer, DrawOption option)
|
void Artboard::drawInternal(Renderer* renderer)
|
||||||
{
|
{
|
||||||
RIVE_PROF_SCOPE()
|
RIVE_PROF_SCOPE()
|
||||||
m_didChange = false;
|
m_didChange = false;
|
||||||
@@ -1418,69 +1424,61 @@ void Artboard::draw(Renderer* renderer, DrawOption option)
|
|||||||
renderer->transform(artboardTransform);
|
renderer->transform(artboardTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option != DrawOption::kHideBG)
|
for (auto shapePaint : m_ShapePaints)
|
||||||
{
|
{
|
||||||
for (auto shapePaint : m_ShapePaints)
|
if (!shapePaint->shouldDraw())
|
||||||
{
|
{
|
||||||
if (!shapePaint->shouldDraw())
|
continue;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto shapePaintPath = shapePaint->pickPath(this);
|
|
||||||
if (shapePaintPath == nullptr)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
shapePaint->draw(renderer, shapePaintPath, worldTransform());
|
|
||||||
}
|
}
|
||||||
|
auto shapePaintPath = shapePaint->pickPath(this);
|
||||||
|
if (shapePaintPath == nullptr)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
shapePaint->draw(renderer, shapePaintPath, worldTransform());
|
||||||
}
|
}
|
||||||
|
// Empty clips is a counter for clipping shapes that are empty, for
|
||||||
if (option != DrawOption::kHideFG)
|
// example because they are hidden in a solo. If emptyClips > 0, the
|
||||||
|
// drawables should not be drawn.
|
||||||
|
int emptyClips = 0;
|
||||||
|
// We stack clip operations to avoid calling a save + clip + restore on
|
||||||
|
// clipping that don't have any drawables in between. this is a common
|
||||||
|
// case with drawables in solos where the drawables are not drawn.
|
||||||
|
std::vector<Drawable*> pendingClipOperations;
|
||||||
|
for (auto drawable = m_FirstDrawable; drawable != nullptr;
|
||||||
|
drawable = drawable->prev)
|
||||||
{
|
{
|
||||||
// Empty clips is a counter for clipping shapes that are empty, for
|
auto prevClips = emptyClips;
|
||||||
// example because they are hidden in a solo. If emptyClips > 0, the
|
emptyClips += drawable->emptyClipCount();
|
||||||
// drawables should not be drawn.
|
if (!drawable->willDraw() || emptyClips != prevClips || emptyClips > 0)
|
||||||
int emptyClips = 0;
|
|
||||||
// We stack clip operations to avoid calling a save + clip + restore on
|
|
||||||
// clipping that don't have any drawables in between. this is a common
|
|
||||||
// case with drawables in solos where the drawables are not drawn.
|
|
||||||
std::vector<Drawable*> pendingClipOperations;
|
|
||||||
for (auto drawable = m_FirstDrawable; drawable != nullptr;
|
|
||||||
drawable = drawable->prev)
|
|
||||||
{
|
{
|
||||||
auto prevClips = emptyClips;
|
continue;
|
||||||
emptyClips += drawable->emptyClipCount();
|
|
||||||
if (!drawable->willDraw() || emptyClips != prevClips ||
|
|
||||||
emptyClips > 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (drawable->isClipStart())
|
|
||||||
{
|
|
||||||
pendingClipOperations.push_back(drawable);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (pendingClipOperations.size() > 0)
|
|
||||||
{
|
|
||||||
// If there are clip operations pending and the next drawable is
|
|
||||||
// a clip end, the clipping operation does not clip anything and
|
|
||||||
// both can be skipped.
|
|
||||||
if (drawable->isClipEnd())
|
|
||||||
{
|
|
||||||
pendingClipOperations.pop_back();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (auto& pendingClip : pendingClipOperations)
|
|
||||||
{
|
|
||||||
pendingClip->draw(renderer);
|
|
||||||
}
|
|
||||||
pendingClipOperations.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drawable->draw(renderer);
|
|
||||||
}
|
}
|
||||||
|
if (drawable->isClipStart())
|
||||||
|
{
|
||||||
|
pendingClipOperations.push_back(drawable);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (pendingClipOperations.size() > 0)
|
||||||
|
{
|
||||||
|
// If there are clip operations pending and the next drawable is
|
||||||
|
// a clip end, the clipping operation does not clip anything and
|
||||||
|
// both can be skipped.
|
||||||
|
if (drawable->isClipEnd())
|
||||||
|
{
|
||||||
|
pendingClipOperations.pop_back();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto& pendingClip : pendingClipOperations)
|
||||||
|
{
|
||||||
|
pendingClip->draw(renderer);
|
||||||
|
}
|
||||||
|
pendingClipOperations.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drawable->draw(renderer);
|
||||||
}
|
}
|
||||||
if (save)
|
if (save)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -468,7 +468,7 @@ void ArtboardComponentList::draw(Renderer* renderer)
|
|||||||
renderer->save();
|
renderer->save();
|
||||||
auto transform = m_artboardTransforms[artboard];
|
auto transform = m_artboardTransforms[artboard];
|
||||||
renderer->transform(transform);
|
renderer->transform(transform);
|
||||||
artboard->draw(renderer);
|
artboard->drawInternal(renderer);
|
||||||
renderer->restore();
|
renderer->restore();
|
||||||
}
|
}
|
||||||
if (i == endIndex)
|
if (i == endIndex)
|
||||||
@@ -490,7 +490,7 @@ void ArtboardComponentList::draw(Renderer* renderer)
|
|||||||
renderer->save();
|
renderer->save();
|
||||||
auto transform = m_artboardTransforms[artboard];
|
auto transform = m_artboardTransforms[artboard];
|
||||||
renderer->transform(transform);
|
renderer->transform(transform);
|
||||||
artboard->draw(renderer);
|
artboard->drawInternal(renderer);
|
||||||
renderer->restore();
|
renderer->restore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ RenderPath* ScriptedPath::renderPath(lua_State* L)
|
|||||||
if (m_isRenderPathDirty)
|
if (m_isRenderPathDirty)
|
||||||
{
|
{
|
||||||
m_isRenderPathDirty = false;
|
m_isRenderPathDirty = false;
|
||||||
|
if (m_renderFrameId == Artboard::frameId())
|
||||||
|
{
|
||||||
|
luaL_error(L, "Path was modified between draws in the same frame.");
|
||||||
|
}
|
||||||
|
m_renderFrameId = Artboard::frameId();
|
||||||
if (!m_renderPath)
|
if (!m_renderPath)
|
||||||
{
|
{
|
||||||
ScriptingContext* context =
|
ScriptingContext* context =
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ void NestedArtboard::draw(Renderer* renderer)
|
|||||||
renderer->save();
|
renderer->save();
|
||||||
}
|
}
|
||||||
renderer->transform(worldTransform());
|
renderer->transform(worldTransform());
|
||||||
m_Artboard->draw(renderer);
|
m_Artboard->drawInternal(renderer);
|
||||||
if (m_needsSaveOperation)
|
if (m_needsSaveOperation)
|
||||||
{
|
{
|
||||||
renderer->restore();
|
renderer->restore();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "utils/serializing_factory.hpp"
|
#include "utils/serializing_factory.hpp"
|
||||||
#include "rive/decoders/bitmap_decoder.hpp"
|
#include "rive/decoders/bitmap_decoder.hpp"
|
||||||
#include "rive/core/binary_reader.hpp"
|
#include "rive/core/binary_reader.hpp"
|
||||||
|
#include "rive/artboard.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
@@ -623,6 +624,7 @@ std::unique_ptr<Renderer> SerializingFactory::makeRenderer()
|
|||||||
|
|
||||||
void SerializingFactory::addFrame()
|
void SerializingFactory::addFrame()
|
||||||
{
|
{
|
||||||
|
Artboard::incFrameId();
|
||||||
m_writer.writeVarUint((uint32_t)SerializeOp::frame);
|
m_writer.writeVarUint((uint32_t)SerializeOp::frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user