Nnnnn provide path node data (#11428) 67006966a5

chore: replace path effect signature to pass full node to scripting

Co-authored-by: hernan <hernan@rive.app>
This commit is contained in:
bodymovin
2026-01-12 19:28:43 +00:00
parent c5fdfdb3d7
commit b974d1f75a
20 changed files with 183 additions and 81 deletions

View File

@@ -1 +1 @@
f810efd11a9d5339e0df76c31016819c5ea8e1ba
67006966a5ea7000971204e0dd9bc03613f2b9bc

View File

@@ -12,6 +12,7 @@
#include "rive/math/contour_measure.hpp"
#include "rive/math/path_measure.hpp"
#include "rive/shapes/paint/image_sampler.hpp"
#include "rive/shapes/paint/shape_paint.hpp"
#include "rive/viewmodel/viewmodel_instance_boolean.hpp"
#include "rive/viewmodel/viewmodel_instance_color.hpp"
#include "rive/viewmodel/viewmodel_instance_enum.hpp"
@@ -195,6 +196,7 @@ enum class LuaAtoms : int16_t
children,
parent,
node,
paint,
// PathMeasure/ContourMeasure
positionAndTangent,
@@ -226,6 +228,8 @@ struct ScriptedMat2D
ScriptedMat2D(const Mat2D& mat) : value(mat) {}
ScriptedMat2D() {}
rive::Mat2D value;
};
@@ -341,63 +345,31 @@ public:
static constexpr bool hasMetatable = false;
};
class ScriptedPaint
class ScriptedPaintData
{
public:
ScriptedPaint(Factory* factory);
ScriptedPaint(Factory* factory, const ScriptedPaint& source);
rcp<RenderPaint> renderPaint;
ScriptedPaintData();
ScriptedPaintData(const ShapePaint* shapePaint);
virtual ~ScriptedPaintData() = default;
static constexpr uint8_t luaTag = LUA_T_COUNT + 8;
static constexpr const char* luaName = "Paint";
static constexpr uint8_t luaTag = LUA_T_COUNT + 33;
static constexpr const char* luaName = "PaintData";
static constexpr bool hasMetatable = true;
void style(RenderPaintStyle style)
{
m_style = style;
renderPaint->style(style);
}
virtual void style(RenderPaintStyle style) { m_style = style; }
void color(ColorInt value)
{
m_color = value;
renderPaint->color(value);
}
void thickness(float value)
{
m_thickness = value;
renderPaint->thickness(value);
}
virtual void color(ColorInt value) { m_color = value; }
virtual void thickness(float value) { m_thickness = value; }
void join(StrokeJoin value)
{
m_join = value;
renderPaint->join(value);
}
virtual void join(StrokeJoin value) { m_join = value; }
void cap(StrokeCap value)
{
m_cap = value;
renderPaint->cap(value);
}
virtual void cap(StrokeCap value) { m_cap = value; }
void feather(float value)
{
m_feather = value;
renderPaint->feather(value);
}
virtual void feather(float value) { m_feather = value; }
void blendMode(BlendMode value)
{
m_blendMode = value;
renderPaint->blendMode(value);
}
virtual void blendMode(BlendMode value) { m_blendMode = value; }
void gradient(rcp<RenderShader> value)
{
m_gradient = value;
renderPaint->shader(value);
}
virtual void gradient(rcp<RenderShader> value) { m_gradient = value; }
void pushStyle(lua_State* L);
void pushJoin(lua_State* L);
@@ -408,7 +380,7 @@ public:
void pushGradient(lua_State* L);
void pushColor(lua_State* L);
private:
protected:
RenderPaintStyle m_style = RenderPaintStyle::fill;
rcp<RenderShader> m_gradient;
float m_thickness = 1;
@@ -419,6 +391,66 @@ private:
ColorInt m_color = 0xFF000000;
};
class ScriptedPaint : public ScriptedPaintData
{
public:
ScriptedPaint(Factory* factory);
ScriptedPaint(Factory* factory, const ScriptedPaint& source);
virtual ~ScriptedPaint() = default;
rcp<RenderPaint> renderPaint;
static constexpr uint8_t luaTag = LUA_T_COUNT + 8;
static constexpr const char* luaName = "Paint";
static constexpr bool hasMetatable = true;
void style(RenderPaintStyle style) override
{
ScriptedPaintData::style(style);
renderPaint->style(style);
}
void color(ColorInt value) override
{
ScriptedPaintData::color(value);
renderPaint->color(value);
}
void thickness(float value) override
{
ScriptedPaintData::thickness(value);
renderPaint->thickness(value);
}
void join(StrokeJoin value) override
{
ScriptedPaintData::join(value);
renderPaint->join(value);
}
void cap(StrokeCap value) override
{
ScriptedPaintData::cap(value);
renderPaint->cap(value);
}
void feather(float value) override
{
ScriptedPaintData::feather(value);
renderPaint->feather(value);
}
void blendMode(BlendMode value) override
{
ScriptedPaintData::blendMode(value);
renderPaint->blendMode(value);
}
void gradient(rcp<RenderShader> value) override
{
ScriptedPaintData::gradient(value);
renderPaint->shader(value);
}
};
class ScriptedRenderer
{
public:
@@ -942,9 +974,13 @@ public:
TransformComponent* component() { return m_component; }
rcp<ScriptReffedArtboard> artboard() { return m_artboard; }
const ShapePaint* shapePaint() { return m_shapePaint; }
void shapePaint(const ShapePaint* shapePaint) { m_shapePaint = shapePaint; }
private:
rcp<ScriptReffedArtboard> m_artboard;
TransformComponent* m_component;
const ShapePaint* m_shapePaint;
};
class ScriptedContourMeasure

View File

@@ -51,7 +51,7 @@ public:
}
void updateEffect(PathProvider* pathProvider,
const ShapePaintPath* source,
ShapePaintType shapePaintType) override;
const ShapePaint* shapePaint) override;
StatusCode import(ImportStack& importStack) override;
Core* clone() const override;
void markNeedsUpdate() override;

View File

@@ -56,7 +56,7 @@ public:
void offsetIsPercentageChanged() override;
void updateEffect(PathProvider* pathProvider,
const ShapePaintPath* source,
ShapePaintType shapePaintType) override;
const ShapePaint* shapePaint) override;
void invalidateDash() override;
EffectsContainer* parentPaint() override;
virtual EffectPath* createEffectPath() override;

View File

@@ -11,7 +11,7 @@ public:
PathFlags pathFlags() const override;
void applyTo(RenderPaint* renderPaint, float opacityModifier) override;
ShapePaintPath* pickPath(ShapePaintContainer* shape) const override;
ShapePaintType paintType() override { return ShapePaintType::fill; }
ShapePaintType paintType() const override { return ShapePaintType::fill; }
void buildDependencies() override;
};
} // namespace rive

View File

@@ -18,7 +18,7 @@ public:
void invalidateEffects() override;
void updateEffect(PathProvider* pathProvider,
const ShapePaintPath* source,
ShapePaintType shapePaintType) override;
const ShapePaint* shapePaint) override;
EffectsContainer* parentPaint() override;
void addPathProvider(PathProvider* component) override;
void addStrokeEffect(StrokeEffect* effect) override;

View File

@@ -23,7 +23,6 @@ class ShapePaint : public ShapePaintBase,
protected:
rcp<RenderPaint> m_RenderPaint;
ShapePaintMutator* m_PaintMutator = nullptr;
virtual ShapePaintType paintType() = 0;
public:
StatusCode onAddedClean(CoreContext* context) override;
@@ -82,6 +81,7 @@ public:
virtual ShapePaintPath* pickPath(ShapePaintContainer* shape) const = 0;
void update(ComponentDirt value) override;
virtual ShapePaintType paintType() const = 0;
private:
Feather* m_feather = nullptr;

View File

@@ -17,12 +17,12 @@ public:
void buildDependencies() override;
void invalidateRendering() override;
ShapePaintType paintType() const override { return ShapePaintType::stroke; }
protected:
void thicknessChanged() override;
void capChanged() override;
void joinChanged() override;
ShapePaintType paintType() override { return ShapePaintType::stroke; }
};
} // namespace rive

View File

@@ -40,7 +40,7 @@ public:
virtual ~StrokeEffect();
virtual void updateEffect(PathProvider* pathProvider,
const ShapePaintPath* source,
ShapePaintType shapePaintType) = 0;
const ShapePaint* shapePaint) = 0;
virtual void invalidateEffect(PathProvider* pathProvider);
virtual EffectsContainer* parentPaint() = 0;
virtual void addPathProvider(PathProvider* component)

View File

@@ -21,7 +21,7 @@ public:
void updateEffect(PathProvider* pathProvider,
const ShapePaintPath* source,
ShapePaintType shapePaintType) override;
const ShapePaint* shapePaint) override;
ShapePaintPath* effectPath(PathProvider* pathProvider) override;
EffectsContainer* parentPaint() override;
void addPathProvider(PathProvider* component) override;

View File

@@ -36,7 +36,7 @@ public:
void updateEffect(PathProvider* pathProvider,
const ShapePaintPath* source,
ShapePaintType shapePaintType) override;
const ShapePaint* shapePaint) override;
EffectsContainer* parentPaint() override;
void startChanged() override;

View File

@@ -476,6 +476,19 @@ static int node_index(lua_State* L)
}
return 1;
}
case (int)LuaAtoms::paint:
{
auto shapePaint = scriptedNode->shapePaint();
if (shapePaint)
{
lua_newrive<ScriptedPaintData>(L, shapePaint);
}
else
{
lua_pushnil(L);
}
return 1;
}
default:
switch (key[0])

View File

@@ -3,6 +3,10 @@
#include "rive/renderer.hpp"
#include "rive/rive_types.hpp"
#include "rive/shapes/paint/blend_mode.hpp"
#include "rive/shapes/paint/fill.hpp"
#include "rive/shapes/paint/stroke.hpp"
#include "rive/shapes/paint/solid_color.hpp"
#include "rive/shapes/paint/feather.hpp"
#include "lualib.h"
#include "rive/lua/rive_lua_libs.hpp"
#include "rive/factory.hpp"
@@ -151,6 +155,37 @@ static void readBlendMode(lua_State* L, ScriptedPaint* paint, int index)
paint->blendMode(blendMode);
}
ScriptedPaintData::ScriptedPaintData() {}
ScriptedPaintData::ScriptedPaintData(const ShapePaint* shapePaint)
{
if (shapePaint->is<Fill>())
{
style(RenderPaintStyle::fill);
}
else if (shapePaint->is<Stroke>())
{
auto stroke = shapePaint->as<Stroke>();
style(RenderPaintStyle::stroke);
thickness(stroke->thickness());
cap((StrokeCap)stroke->cap());
join((StrokeJoin)stroke->join());
}
for (auto& child : shapePaint->children())
{
if (child->is<SolidColor>())
{
color(child->as<SolidColor>()->colorValue());
break;
}
}
if (shapePaint->feather())
{
feather(shapePaint->feather()->strength());
}
blendMode((BlendMode)shapePaint->blendModeValue());
}
ScriptedPaint::ScriptedPaint(Factory* factory) :
renderPaint(factory->makeRenderPaint())
{}
@@ -284,7 +319,7 @@ static int paint_newindex(lua_State* L)
return 0;
}
void ScriptedPaint::pushStyle(lua_State* L)
void ScriptedPaintData::pushStyle(lua_State* L)
{
switch (m_style)
{
@@ -299,7 +334,7 @@ void ScriptedPaint::pushStyle(lua_State* L)
}
}
void ScriptedPaint::pushJoin(lua_State* L)
void ScriptedPaintData::pushJoin(lua_State* L)
{
switch (m_join)
{
@@ -317,7 +352,7 @@ void ScriptedPaint::pushJoin(lua_State* L)
}
}
void ScriptedPaint::pushCap(lua_State* L)
void ScriptedPaintData::pushCap(lua_State* L)
{
switch (m_cap)
{
@@ -335,12 +370,12 @@ void ScriptedPaint::pushCap(lua_State* L)
}
}
void ScriptedPaint::pushThickness(lua_State* L)
void ScriptedPaintData::pushThickness(lua_State* L)
{
lua_pushnumber(L, m_thickness);
}
void ScriptedPaint::pushBlendMode(lua_State* L)
void ScriptedPaintData::pushBlendMode(lua_State* L)
{
switch (m_blendMode)
{
@@ -397,8 +432,11 @@ void ScriptedPaint::pushBlendMode(lua_State* L)
}
}
void ScriptedPaint::pushFeather(lua_State* L) { lua_pushnumber(L, m_feather); }
void ScriptedPaint::pushGradient(lua_State* L)
void ScriptedPaintData::pushFeather(lua_State* L)
{
lua_pushnumber(L, m_feather);
}
void ScriptedPaintData::pushGradient(lua_State* L)
{
if (m_gradient)
{
@@ -410,7 +448,10 @@ void ScriptedPaint::pushGradient(lua_State* L)
lua_pushnil(L);
}
}
void ScriptedPaint::pushColor(lua_State* L) { lua_pushunsigned(L, m_color); }
void ScriptedPaintData::pushColor(lua_State* L)
{
lua_pushunsigned(L, m_color);
}
static int paint_index(lua_State* L)
{
@@ -422,7 +463,7 @@ static int paint_index(lua_State* L)
return 0;
}
auto scriptedPaint = lua_torive<ScriptedPaint>(L, 1);
auto scriptedPaint = (ScriptedPaintData*)lua_touserdata(L, 1);
switch (atom)
{
case (int)LuaAtoms::style:
@@ -500,6 +541,13 @@ static const luaL_Reg paintStaticMethods[] = {
int luaopen_rive_paint(lua_State* L)
{
lua_register_rive<ScriptedPaintData>(L);
lua_pushcfunction(L, paint_index, nullptr);
lua_setfield(L, -2, "__index");
lua_setreadonly(L, -1, true);
lua_pop(L, 1); // pop the metatable
luaL_register(L, ScriptedPaint::luaName, paintStaticMethods);
lua_register_rive<ScriptedPaint>(L);
@@ -514,6 +562,7 @@ int luaopen_rive_paint(lua_State* L)
lua_setreadonly(L, -1, true);
lua_pop(L, 1); // pop the metatable
return 1;
}

View File

@@ -132,6 +132,7 @@ std::unordered_map<std::string, int16_t> atoms = {
{"children", (int16_t)LuaAtoms::children},
{"parent", (int16_t)LuaAtoms::parent},
{"node", (int16_t)LuaAtoms::node},
{"paint", (int16_t)LuaAtoms::paint},
{"addToPath", (int16_t)LuaAtoms::addToPath},
{"positionAndTangent", (int16_t)LuaAtoms::positionAndTangent},
{"warp", (int16_t)LuaAtoms::warp},

View File

@@ -20,7 +20,7 @@ bool ScriptedPathEffect::scriptInit(LuaState* state)
void ScriptedPathEffect::updateEffect(PathProvider* pathProvider,
const ShapePaintPath* source,
ShapePaintType shapePaintType)
const ShapePaint* shapePaint)
{
if (!updates())
{
@@ -53,10 +53,13 @@ void ScriptedPathEffect::updateEffect(PathProvider* pathProvider,
// Stack: [self, "update", self]
lua_newrive<ScriptedPathData>(state, source->rawPath());
// Stack: [self, "update", self, pathData]
lua_pushstring(state,
shapePaintType == ShapePaintType::stroke ? "stroke"
: "fill");
// Stack: [self, "update", self, pathData, paintType]
lua_newrive<ScriptedNode>(
state,
nullptr,
shapePaint->parent()->as<TransformComponent>());
auto scriptedNode = lua_torive<ScriptedNode>(state, -1);
scriptedNode->shapePaint(shapePaint);
// Stack: [self, "update", self, pathData, node]
if (static_cast<lua_Status>(rive_lua_pcall(state, 3, 1)) != LUA_OK)
{
fprintf(stderr, "update function failed\n");
@@ -75,7 +78,7 @@ void ScriptedPathEffect::updateEffect(PathProvider* pathProvider,
#else
void ScriptedPathEffect::updateEffect(PathProvider* pathProvider,
const ShapePaintPath* source,
ShapePaintType shapePaintType)
const ShapePaint* shapePaint)
{}
#endif

View File

@@ -125,7 +125,7 @@ void DashPath::offsetIsPercentageChanged() { invalidateEffectFromLocal(); }
void DashPath::updateEffect(PathProvider* pathProvider,
const ShapePaintPath* source,
ShapePaintType shapePaintType)
const ShapePaint* shapePaint)
{
auto effectPathIt = m_effectPaths.find(pathProvider);
if (effectPathIt != m_effectPaths.end())
@@ -139,7 +139,7 @@ void DashPath::updateEffect(PathProvider* pathProvider,
}
path->rewind(source->isLocal());
// Dash is not supported on fills so it will use the source as output
if (shapePaintType == ShapePaintType::fill)
if (shapePaint->paintType() == ShapePaintType::fill)
{
path->addPath(source);
}

View File

@@ -5,12 +5,12 @@ using namespace rive;
void GroupEffect::updateEffect(PathProvider* pathProvider,
const ShapePaintPath* source,
ShapePaintType shapePaintType)
const ShapePaint* shapePaint)
{
auto path = source;
for (auto& effect : *effects())
{
effect->updateEffect(pathProvider, path, shapePaintType);
effect->updateEffect(pathProvider, path, shapePaint);
auto newPath = effect->effectPath(pathProvider);
if (newPath)
{

View File

@@ -36,7 +36,7 @@ void ShapePaint::update(ComponentDirt value)
auto path = pickPath(container);
for (auto& effect : *shapeEffects)
{
effect->updateEffect(this, path, paintType());
effect->updateEffect(this, path, this);
auto newPath = effect->effectPath(this);
if (newPath)
{

View File

@@ -33,7 +33,7 @@ StatusCode TargetEffect::onAddedClean(CoreContext* context)
void TargetEffect::updateEffect(PathProvider* pathProvider,
const ShapePaintPath* source,
ShapePaintType shapePaintType)
const ShapePaint* shapePaint)
{
if (!m_groupEffect)
{
@@ -46,7 +46,7 @@ void TargetEffect::updateEffect(PathProvider* pathProvider,
static_cast<TargetEffectPath*>(effectPathIt->second);
m_groupEffect->updateEffect(targetEffectPath->pathProviderProxy(),
source,
shapePaintType);
shapePaint);
}
}

View File

@@ -203,7 +203,7 @@ StatusCode TrimPath::onAddedDirty(CoreContext* context)
void TrimPath::updateEffect(PathProvider* pathProvider,
const ShapePaintPath* source,
ShapePaintType shapePaintType)
const ShapePaint* shapePaint)
{
auto effectPathIt = m_effectPaths.find(pathProvider);
if (effectPathIt != m_effectPaths.end())
@@ -220,7 +220,7 @@ void TrimPath::updateEffect(PathProvider* pathProvider,
trimPath(path,
trimEffectPath->contours(),
source->rawPath(),
shapePaintType);
shapePaint->paintType());
}
}