File indexing completed on 2025-02-02 04:11:05

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #include "group.hpp"
0008 
0009 #include <QPainter>
0010 
0011 #include "model/document.hpp"
0012 #include "model/shapes/styler.hpp"
0013 
0014 GLAXNIMATE_OBJECT_IMPL(glaxnimate::model::Group)
0015 
0016 
0017 glaxnimate::model::Group::Group(Document* document)
0018     : Ctor(document)
0019 {
0020     connect(transform.get(), &Object::property_changed,
0021             this, &Group::on_transform_matrix_changed);
0022 }
0023 
0024 void glaxnimate::model::Group::on_paint(QPainter* painter, glaxnimate::model::FrameTime time, glaxnimate::model::VisualNode::PaintMode, glaxnimate::model::Modifier*) const
0025 {
0026     painter->setOpacity(
0027         painter->opacity() * opacity.get_at(time)
0028     );
0029 }
0030 
0031 void glaxnimate::model::Group::on_transform_matrix_changed()
0032 {
0033     propagate_bounding_rect_changed();
0034     Q_EMIT local_transform_matrix_changed(local_transform_matrix(time()));
0035     propagate_transform_matrix_changed(transform_matrix(time()), group_transform_matrix(time()));
0036 }
0037 
0038 void glaxnimate::model::Group::add_shapes(glaxnimate::model::FrameTime t, math::bezier::MultiBezier & bez, const QTransform& parent_transform) const
0039 {
0040     QTransform trans = transform.get()->transform_matrix(t, auto_orient.get()) * parent_transform;
0041     for ( const auto& ch : utils::Range(shapes.begin(), shapes.past_first_modifier()) )
0042     {
0043         ch->add_shapes(t, bez, trans);
0044     }
0045 }
0046 
0047 QRectF glaxnimate::model::Group::local_bounding_rect(FrameTime t) const
0048 {
0049     if ( shapes.empty() )
0050         return owner_composition()->rect();
0051     return shapes.bounding_rect(t);
0052 }
0053 
0054 QTransform glaxnimate::model::Group::local_transform_matrix(glaxnimate::model::FrameTime t) const
0055 {
0056     return transform.get()->transform_matrix(t, auto_orient.get());
0057 }
0058 
0059 
0060 QPainterPath glaxnimate::model::Group::to_painter_path_impl(glaxnimate::model::FrameTime t) const
0061 {
0062     QPainterPath path;
0063     for ( const auto& ch : utils::Range(shapes.begin(), shapes.past_first_modifier()) )
0064     {
0065         if ( ch->is_instance<glaxnimate::model::Styler>() || ch->is_instance<glaxnimate::model::Group>()  )
0066             path.addPath(ch->to_clip(t));
0067     }
0068 
0069     return path;
0070 }
0071 
0072 
0073 QPainterPath glaxnimate::model::Group::to_clip(FrameTime t) const
0074 {
0075     return transform.get()->transform_matrix(t, auto_orient.get()).map(to_painter_path(t));
0076 }
0077 
0078 std::unique_ptr<glaxnimate::model::ShapeElement> glaxnimate::model::Group::to_path() const
0079 {
0080     auto clone = std::make_unique<glaxnimate::model::Group>(document());
0081 
0082     for ( BaseProperty* prop : properties() )
0083     {
0084         if ( prop != &shapes )
0085             clone->get_property(prop->name())->assign_from(prop);
0086     }
0087 
0088     for ( const auto& shape : shapes )
0089     {
0090         clone->shapes.insert(shape->to_path());
0091         if ( shape->is_instance<glaxnimate::model::Modifier>() )
0092             break;
0093     }
0094 
0095     return clone;
0096 }
0097 
0098 void glaxnimate::model::Group::on_graphics_changed()
0099 {
0100     ShapeElement::on_graphics_changed();
0101 
0102     for ( const auto& shape : shapes )
0103     {
0104         if ( shape->is_instance<glaxnimate::model::ShapeOperator>() )
0105             shape->on_graphics_changed();
0106     }
0107 
0108 }
0109 
0110 
0111 void glaxnimate::model::Group::on_composition_changed(model::Composition*, model::Composition* new_comp)
0112 {
0113     for ( const auto& shape : shapes )
0114     {
0115         shape->refresh_owner_composition(new_comp);
0116     }
0117 }