| #ifdef WITH_RIVE_SCRIPTING |
| #include "rive/lua/rive_lua_libs.hpp" |
| #endif |
| #include "rive/component_dirt.hpp" |
| #include "rive/assets/script_asset.hpp" |
| #include "rive/scripted/scripted_path_effect.hpp" |
| #include "rive/shapes/paint/stroke.hpp" |
| |
| using namespace rive; |
| |
| void ScriptedEffectPath::invalidateEffect() { m_path.rewind(); } |
| |
| #ifdef WITH_RIVE_SCRIPTING |
| bool ScriptedPathEffect::scriptInit(lua_State* state) |
| { |
| ScriptedObject::scriptInit(state); |
| addScriptedDirt(ComponentDirt::Paint, true); |
| return true; |
| } |
| |
| void ScriptedPathEffect::updateEffect(PathProvider* pathProvider, |
| const ShapePaintPath* source, |
| const ShapePaint* shapePaint) |
| { |
| if (!updates()) |
| { |
| return; |
| } |
| |
| #ifdef WITH_RIVE_TOOLS |
| if (!hasValidVM()) |
| { |
| return; |
| } |
| #endif |
| auto effectPathIt = m_effectPaths.find(pathProvider); |
| if (effectPathIt != m_effectPaths.end()) |
| { |
| auto trimEffectPath = |
| static_cast<ScriptedEffectPath*>(effectPathIt->second); |
| auto path = trimEffectPath->path(); |
| if (path->hasRenderPath()) |
| { |
| // Previous result hasn't been invalidated, it's still good. |
| return; |
| } |
| |
| path->rewind(source->isLocal(), source->fillRule()); |
| if (m_state == nullptr) |
| { |
| return; |
| } |
| // Stack: [] |
| rive_lua_pushRef(m_state, m_self); |
| // Stack: [self] |
| lua_getfield(m_state, -1, "update"); |
| // Stack: [self, "update"] |
| lua_pushvalue(m_state, -2); |
| // Stack: [self, "update", self] |
| lua_newrive<ScriptedPathData>(m_state, source->rawPath()); |
| // Stack: [self, "update", self, pathData] |
| lua_newrive<ScriptedNode>(m_state, |
| nullptr, |
| shapePaint->parentTransformComponent()); |
| auto scriptedNode = lua_torive<ScriptedNode>(m_state, -1); |
| scriptedNode->shapePaint(shapePaint); |
| // Stack: [self, "update", self, pathData, node] |
| if (static_cast<lua_Status>(rive_lua_pcall(m_state, 3, 1)) != LUA_OK) |
| { |
| fprintf(stderr, "update function failed\n"); |
| } |
| else |
| { |
| // Stack: [self, outputPathData] |
| auto scriptedPath = (ScriptedPathData*)lua_touserdata(m_state, -1); |
| auto rawPath = path->mutableRawPath(); |
| rawPath->addPath(scriptedPath->rawPath); |
| } |
| // Stack: [self, status] or [self, outputPathData] |
| rive_lua_pop(m_state, 2); |
| } |
| } |
| #else |
| void ScriptedPathEffect::updateEffect(PathProvider* pathProvider, |
| const ShapePaintPath* source, |
| const ShapePaint* shapePaint) |
| {} |
| #endif |
| |
| StatusCode ScriptedPathEffect::onAddedDirty(CoreContext* context) |
| { |
| auto code = Super::onAddedDirty(context); |
| if (code != StatusCode::Ok) |
| { |
| return code; |
| } |
| artboard()->addScriptedObject(this); |
| return StatusCode::Ok; |
| } |
| |
| StatusCode ScriptedPathEffect::onAddedClean(CoreContext* context) |
| { |
| auto effectsContainer = EffectsContainer::from(parent()); |
| if (!effectsContainer) |
| { |
| return StatusCode::InvalidObject; |
| } |
| effectsContainer->addStrokeEffect(this); |
| |
| return StatusCode::Ok; |
| } |
| |
| bool ScriptedPathEffect::advanceComponent(float elapsedSeconds, |
| AdvanceFlags flags) |
| { |
| if (elapsedSeconds == 0) |
| { |
| return false; |
| } |
| if ((flags & AdvanceFlags::AdvanceNested) == 0) |
| { |
| elapsedSeconds = 0; |
| } |
| return scriptAdvance(elapsedSeconds); |
| } |
| |
| bool ScriptedPathEffect::addScriptedDirt(ComponentDirt value, bool recurse) |
| { |
| return Component::addDirt(value, recurse); |
| } |
| |
| void ScriptedPathEffect::addProperty(CustomProperty* prop) |
| { |
| auto scriptInput = ScriptInput::from(prop); |
| if (scriptInput != nullptr) |
| { |
| scriptInput->scriptedObject(this); |
| } |
| CustomPropertyContainer::addProperty(prop); |
| } |
| |
| StatusCode ScriptedPathEffect::import(ImportStack& importStack) |
| { |
| auto result = registerReferencer(importStack); |
| if (result != StatusCode::Ok) |
| { |
| return result; |
| } |
| return Super::import(importStack); |
| } |
| |
| Core* ScriptedPathEffect::clone() const |
| { |
| ScriptedPathEffect* twin = |
| ScriptedPathEffectBase::clone()->as<ScriptedPathEffect>(); |
| if (m_fileAsset != nullptr) |
| { |
| twin->setAsset(m_fileAsset); |
| } |
| return twin; |
| } |
| |
| void ScriptedPathEffect::markNeedsUpdate() |
| { |
| addScriptedDirt(ComponentDirt::ScriptUpdate); |
| } |
| |
| EffectsContainer* ScriptedPathEffect::parentPaint() |
| { |
| return EffectsContainer::from(parent()); |
| } |
| |
| EffectPath* ScriptedPathEffect::createEffectPath() |
| { |
| return new ScriptedEffectPath(); |
| } |
| |
| void ScriptedPathEffect::buildDependencies() |
| { |
| Super::buildDependencies(); |
| if (parent()) |
| { |
| parent()->addDependent(this); |
| } |
| } |
| |
| void ScriptedPathEffect::update(ComponentDirt value) |
| { |
| Super::update(value); |
| |
| if (hasDirt(value, ComponentDirt::ScriptUpdate)) |
| { |
| invalidateEffectFromLocal(); |
| } |
| } |