| #include "rive/drawable.hpp" |
| #include "rive/artboard.hpp" |
| #include "rive/custom_property.hpp" |
| #include "rive/shapes/clipping_shape.hpp" |
| #include "rive/shapes/path_composer.hpp" |
| #include "rive/shapes/shape.hpp" |
| #include "rive/clip_result.hpp" |
| |
| using namespace rive; |
| |
| bool Drawable::hasCustomProperties() |
| { |
| #ifdef WITH_RIVE_EDITOR |
| // Children change under the editor, so nothing cached stays true. |
| for (auto child : children()) |
| { |
| if (CustomProperty::tagging(child) != nullptr) |
| { |
| return true; |
| } |
| } |
| return false; |
| #else |
| return runtimeFlag(RuntimeFlags::hasCustomProperties); |
| #endif |
| } |
| |
| CustomProperty* Drawable::customProperty(uint32_t nameId) |
| { |
| for (auto child : children()) |
| { |
| // Only tagging ones: the key of a missing name is what every other |
| // property holds, a scripted drawable's inputs among them. |
| auto property = CustomProperty::tagging(child); |
| if (property != nullptr && property->nameId() == nameId) |
| { |
| return property; |
| } |
| } |
| return nullptr; |
| } |
| |
| StatusCode Drawable::onAddedDirty(CoreContext* context) |
| { |
| auto code = Super::onAddedDirty(context); |
| if (code != StatusCode::Ok) |
| { |
| return code; |
| } |
| auto blendMode = static_cast<rive::BlendMode>(blendModeValue()); |
| switch (blendMode) |
| { |
| case rive::BlendMode::srcOver: |
| case rive::BlendMode::screen: |
| case rive::BlendMode::overlay: |
| case rive::BlendMode::darken: |
| case rive::BlendMode::lighten: |
| case rive::BlendMode::colorDodge: |
| case rive::BlendMode::colorBurn: |
| case rive::BlendMode::hardLight: |
| case rive::BlendMode::softLight: |
| case rive::BlendMode::difference: |
| case rive::BlendMode::exclusion: |
| case rive::BlendMode::multiply: |
| case rive::BlendMode::hue: |
| case rive::BlendMode::saturation: |
| case rive::BlendMode::color: |
| case rive::BlendMode::luminosity: |
| return StatusCode::Ok; |
| } |
| return StatusCode::InvalidObject; |
| } |
| |
| void Drawable::addClippingShape(ClippingShape* shape) |
| { |
| m_ClippingShapes.push_back(shape); |
| } |
| |
| bool Drawable::willDraw() { return !isHidden(); } |
| |
| bool Drawable::isChildOfLayout(LayoutComponent* layout) |
| { |
| for (ContainerComponent* parent = this; parent != nullptr; |
| parent = parent->parent()) |
| { |
| if (parent->is<LayoutComponent>() && |
| parent->as<LayoutComponent>() == layout) |
| { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| bool Drawable::hitTestPoint(const Vec2D& position, |
| bool skipOnUnclipped, |
| bool isPrimaryHit) |
| { |
| if (isHidden()) |
| { |
| return false; |
| } |
| auto hComponent = hittableComponent(); |
| if (hComponent != this && hComponent != nullptr) |
| { |
| return hComponent->hitTestPoint(position, |
| skipOnUnclipped, |
| isPrimaryHit); |
| } |
| return Component::hitTestPoint(position, skipOnUnclipped, isPrimaryHit); |
| } |
| |
| Drawable* DrawableProxy::hittableComponent() |
| { |
| return static_cast<LayoutComponent*>(proxyDrawing()); |
| } |
| |
| bool DrawableProxy::isTargetOpaque() |
| { |
| return hittableComponent()->isTargetOpaque(); |
| } |