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

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 "precomp_layer.hpp"
0008 
0009 #include <QPainter>
0010 
0011 #include "model/document.hpp"
0012 #include "model/assets/composition.hpp"
0013 #include "model/assets/assets.hpp"
0014 
0015 GLAXNIMATE_OBJECT_IMPL(glaxnimate::model::PreCompLayer)
0016 
0017 glaxnimate::model::PreCompLayer::PreCompLayer(Document* document)
0018     : ShapeElement(document)
0019 {
0020     connect(transform.get(), &Object::property_changed, this, &PreCompLayer::on_transform_matrix_changed);
0021 }
0022 
0023 QIcon glaxnimate::model::PreCompLayer::tree_icon() const
0024 {
0025     return QIcon::fromTheme("component");
0026 }
0027 
0028 QString glaxnimate::model::PreCompLayer::type_name_human() const
0029 {
0030     return i18n("Composition Layer");
0031 }
0032 
0033 glaxnimate::model::FrameTime glaxnimate::model::PreCompLayer::relative_time(glaxnimate::model::FrameTime time) const
0034 {
0035     return timing->time_to_local(time);
0036 }
0037 
0038 void glaxnimate::model::PreCompLayer::set_time(glaxnimate::model::FrameTime t)
0039 {
0040     ShapeElement::set_time(relative_time(t));
0041     Q_EMIT document()->graphics_invalidated();
0042 }
0043 
0044 std::vector<glaxnimate::model::DocumentNode *> glaxnimate::model::PreCompLayer::valid_precomps() const
0045 {
0046     auto comps = document()->comp_graph().possible_descendants(owner_composition(), document());
0047     return std::vector<glaxnimate::model::DocumentNode *>(comps.begin(), comps.end());
0048 }
0049 
0050 bool glaxnimate::model::PreCompLayer::is_valid_precomp(glaxnimate::model::DocumentNode* node) const
0051 {
0052     auto owncomp = owner_composition();
0053     if ( auto precomp = qobject_cast<glaxnimate::model::Composition*>(node) )
0054         return !document()->comp_graph().is_ancestor_of(precomp, owncomp);
0055     return false;
0056 }
0057 
0058 void glaxnimate::model::PreCompLayer::on_paint(QPainter* painter, glaxnimate::model::FrameTime time, glaxnimate::model::VisualNode::PaintMode mode, glaxnimate::model::Modifier*) const
0059 {
0060     if ( composition.get() )
0061     {
0062         time = timing->time_to_local(time);
0063         painter->setOpacity(
0064             painter->opacity() * opacity.get_at(time)
0065         );
0066         painter->setClipRect(QRectF(QPointF(0, 0), size.get()), Qt::IntersectClip);
0067         composition->paint(painter, time, mode);
0068     }
0069 }
0070 
0071 void glaxnimate::model::PreCompLayer::on_transform_matrix_changed()
0072 {
0073     propagate_bounding_rect_changed();
0074     Q_EMIT local_transform_matrix_changed(local_transform_matrix(time()));
0075     propagate_transform_matrix_changed(transform_matrix(time()), group_transform_matrix(time()));
0076 }
0077 
0078 QRectF glaxnimate::model::PreCompLayer::local_bounding_rect(FrameTime) const
0079 {
0080     return QRectF(QPointF(0, 0), size.get());
0081 }
0082 
0083 QTransform glaxnimate::model::PreCompLayer::local_transform_matrix(glaxnimate::model::FrameTime t) const
0084 {
0085     return transform.get()->transform_matrix(t);
0086 }
0087 
0088 void glaxnimate::model::PreCompLayer::add_shapes(glaxnimate::model::FrameTime, math::bezier::MultiBezier&, const QTransform&) const
0089 {
0090 }
0091 
0092 void glaxnimate::model::PreCompLayer::on_composition_changed(model::Composition* old_comp, model::Composition* new_comp)
0093 {
0094     if ( old_comp )
0095         document()->comp_graph().remove_connection(old_comp, this);
0096 
0097     if ( new_comp )
0098         document()->comp_graph().add_connection(new_comp, this);
0099 
0100     if ( composition.get() )
0101     {
0102         if ( !new_comp )
0103             composition->remove_user(&composition);
0104         else if ( !old_comp )
0105             composition->add_user(&composition);
0106     }
0107 }
0108 
0109 QPainterPath glaxnimate::model::PreCompLayer::to_painter_path_impl(glaxnimate::model::FrameTime time) const
0110 {
0111     QPainterPath p;
0112     if ( composition.get() )
0113     {
0114         time = timing->time_to_local(time);
0115         for ( const auto& sh : composition->shapes )
0116             p.addPath(sh->to_clip(time));
0117     }
0118     return p;
0119 }
0120 
0121 QPainterPath glaxnimate::model::PreCompLayer::to_clip(glaxnimate::model::FrameTime time) const
0122 {
0123     return transform.get()->transform_matrix(time).map(to_painter_path(time));
0124 }