diff --git a/libs/libkis/Document.h b/libs/libkis/Document.h --- a/libs/libkis/Document.h +++ b/libs/libkis/Document.h @@ -746,6 +746,17 @@ */ QRect bounds() const; + + + + + + + /**** + * Animation Related API + *****/ + + /** * @brief Import an image sequence of files from a directory. This will grab all * images from the directory and import them with a potential offset (firstFrame) @@ -754,6 +765,74 @@ */ bool importAnimation(const QList &files, int firstFrame, int step); + /** + * @brief frames per second of document + * @return the fps of the document + */ + int framesPerSecond(); + + /** + * @brief set frames per second of document + */ + void setFramesPerSecond(int fps); + + /** + * @brief set start time of animation + */ + void setFullClipRangeStartTime(int startTime); + + /** + * @brief get the full clip range start time + * @return full clip range start time + */ + int fullClipRangeStartTime(); + + + /** + * @brief set full clip range end time + */ + void setFullClipRangeEndTime(int endTime); + + /** + * @brief get the full clip range end time + * @return full clip range end time + */ + int fullClipRangeEndTime(); + + /** + * @brief get total frame range for animation + * @return total frame range for animation + */ + int animationLength(); + + /** + * @brief set temporary playback range of document + */ + void setPlayBackRange(int start, int stop); + + /** + * @brief get start time of current playback + * @return start time of current playback + */ + int playBackStartTime(); + + /** + * @brief get end time of current playback + * @return end time of current playback + */ + int playBackEndTime(); + + /** + * @brief get current frame selected of animation + * @return current frame selected of animation + */ + int currentTime(); + + /** + * @brief set current time of document's animation + */ + void setCurrentTime(int time); + private: diff --git a/libs/libkis/Document.cpp b/libs/libkis/Document.cpp --- a/libs/libkis/Document.cpp +++ b/libs/libkis/Document.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -70,6 +71,8 @@ #include #include +#include + struct Document::Private { Private() {} QPointer document; @@ -115,12 +118,14 @@ Q_FOREACH(QPointer view, KisPart::instance()->views()) { if (view && view->document() == d->document) { activeNodes << view->currentNode(); + } } if (activeNodes.size() > 0) { QList nodes = LibKisUtils::createNodeList(activeNodes, d->document->image()); return nodes.first(); } + return 0; } @@ -842,6 +847,8 @@ return d->document; } +/* Animation related function */ + bool Document::importAnimation(const QList &files, int firstFrame, int step) { KisView *activeView = KisPart::instance()->currentMainwindow()->activeView(); @@ -856,3 +863,103 @@ return (status == KisImportExportFilter::OK); } + +int Document::framesPerSecond() +{ + if (!d->document) return false; + if (!d->document->image()) return false; + + return d->document->image()->animationInterface()->framerate(); +} + +void Document::setFramesPerSecond(int fps) +{ + if (!d->document) return; + if (!d->document->image()) return; + + d->document->image()->animationInterface()->setFramerate(fps); +} + +void Document::setFullClipRangeStartTime(int startTime) +{ + if (!d->document) return; + if (!d->document->image()) return; + + d->document->image()->animationInterface()->setFullClipRangeStartTime(startTime); +} + + +int Document::fullClipRangeStartTime() +{ + if (!d->document) return false; + if (!d->document->image()) return false; + + return d->document->image()->animationInterface()->fullClipRange().start(); +} + + +void Document::setFullClipRangeEndTime(int endTime) +{ + if (!d->document) return; + if (!d->document->image()) return; + + d->document->image()->animationInterface()->setFullClipRangeEndTime(endTime); +} + + +int Document::fullClipRangeEndTime() +{ + if (!d->document) return false; + if (!d->document->image()) return false; + + return d->document->image()->animationInterface()->fullClipRange().end(); +} + +int Document::animationLength() +{ + if (!d->document) return false; + if (!d->document->image()) return false; + + return d->document->image()->animationInterface()->totalLength(); +} + +void Document::setPlayBackRange(int start, int stop) +{ + if (!d->document) return; + if (!d->document->image()) return; + + const KisTimeRange newTimeRange = KisTimeRange(start, (stop-start)); + d->document->image()->animationInterface()->setPlaybackRange(newTimeRange); +} + +int Document::playBackStartTime() +{ + if (!d->document) return false; + if (!d->document->image()) return false; + + return d->document->image()->animationInterface()->playbackRange().start(); +} + +int Document::playBackEndTime() +{ + if (!d->document) return false; + if (!d->document->image()) return false; + + return d->document->image()->animationInterface()->playbackRange().end(); +} + +int Document::currentTime() +{ + if (!d->document) return false; + if (!d->document->image()) return false; + + return d->document->image()->animationInterface()->currentTime(); +} + +void Document::setCurrentTime(int time) +{ + if (!d->document) return; + if (!d->document->image()) return; + + return d->document->image()->animationInterface()->requestTimeSwitchWithUndo(time); +} diff --git a/libs/libkis/Node.h b/libs/libkis/Node.h --- a/libs/libkis/Node.h +++ b/libs/libkis/Node.h @@ -185,6 +185,18 @@ */ void enableAnimation() const; + /** + * @brief Should the node be visible in the timeline. It defaults to false + * with new layer + */ + void setShowInTimeline(bool showInTimeline) const; + + /** + * @return is layer is shown in the timeline + */ + bool showInTimeline() const; + + /** * Sets the state of the node to the value of @param collapsed */ diff --git a/libs/libkis/Node.cpp b/libs/libkis/Node.cpp --- a/libs/libkis/Node.cpp +++ b/libs/libkis/Node.cpp @@ -271,6 +271,18 @@ d->node->enableAnimation(); } +void Node::setShowInTimeline(bool showInTimeline) const +{ + if (!d->node) return; + d->node->setUseInTimeline(showInTimeline); +} + +bool Node::showInTimeline() const +{ + if (!d->node) return false; + return d->node->useInTimeline(); +} + bool Node::collapsed() const { if (!d->node) return false; diff --git a/libs/ui/canvas/kis_animation_player.cpp b/libs/ui/canvas/kis_animation_player.cpp --- a/libs/ui/canvas/kis_animation_player.cpp +++ b/libs/ui/canvas/kis_animation_player.cpp @@ -317,7 +317,7 @@ void KisAnimationPlayer::slotUpdatePlaybackTimer() { - m_d->timer->stop(); + m_d->timer->stop(); const KisImageAnimationInterface *animation = m_d->canvas->image()->animationInterface(); const KisTimeRange &playBackRange = animation->playbackRange(); @@ -417,6 +417,7 @@ emit sigPlaybackStarted(); } + void KisAnimationPlayer::Private::stopImpl(bool doUpdates) { if (syncedAudio) { diff --git a/plugins/dockers/animation/animation_docker.h b/plugins/dockers/animation/animation_docker.h --- a/plugins/dockers/animation/animation_docker.h +++ b/plugins/dockers/animation/animation_docker.h @@ -69,6 +69,11 @@ void slotGlobalTimeChanged(); void slotTimeSpinBoxChanged(); + /** Update the frame rate UI field in the case it gets + * out of sync with the data model + */ + void slotFrameRateChanged(); + void updatePlayPauseIcon(); void updateLazyFrameIcon(); void updateDropFramesIcon(); diff --git a/plugins/dockers/animation/animation_docker.cpp b/plugins/dockers/animation/animation_docker.cpp --- a/plugins/dockers/animation/animation_docker.cpp +++ b/plugins/dockers/animation/animation_docker.cpp @@ -106,6 +106,9 @@ connect(animation, SIGNAL(sigUiTimeChanged(int)), this, SLOT(slotGlobalTimeChanged())); + connect(animation, SIGNAL(sigFramerateChanged()), this, SLOT(slotFrameRateChanged())); + + connect(m_canvas->animationPlayer(), SIGNAL(sigFrameChanged()), this, SLOT(slotGlobalTimeChanged())); connect(m_canvas->animationPlayer(), SIGNAL(sigPlaybackStopped()), this, SLOT(slotGlobalTimeChanged())); connect(m_canvas->animationPlayer(), SIGNAL(sigPlaybackStopped()), this, SLOT(updatePlayPauseIcon())); @@ -116,6 +119,7 @@ m_canvas->animationPlayer(), SLOT(slotUpdatePlaybackSpeed(double))); + connect(m_canvas->viewManager()->nodeManager(), SIGNAL(sigNodeActivated(KisNodeSP)), this, SLOT(slotCurrentNodeChanged(KisNodeSP))); @@ -220,6 +224,19 @@ m_animationWidget->intCurrentTime->setToolTip(realTimeString); } +void AnimationDocker::slotFrameRateChanged() +{ + if (!m_canvas || !m_canvas->image()) return; + + int fpsOnUI = m_animationWidget->intFramerate->value(); + KisImageAnimationInterface *animation = m_canvas->image()->animationInterface(); + + if (animation->framerate() != fpsOnUI) { + m_animationWidget->intFramerate->setValue(animation->framerate()); + } + +} + void AnimationDocker::slotTimeSpinBoxChanged() { if (!m_canvas || !m_canvas->image()) return; diff --git a/plugins/extensions/pykrita/sip/krita/Document.sip b/plugins/extensions/pykrita/sip/krita/Document.sip --- a/plugins/extensions/pykrita/sip/krita/Document.sip +++ b/plugins/extensions/pykrita/sip/krita/Document.sip @@ -85,6 +85,19 @@ bool modified() const; QRect bounds() const; bool importAnimation(const QList &files, int firstFrame, int step); + int framesPerSecond(); + void setFramesPerSecond(int fps); + void setFullClipRangeStartTime(int startTime); + int fullClipRangeStartTime(); + void setFullClipRangeEndTime(int endTime); + int fullClipRangeEndTime(); + int animationLength(); + void setPlayBackRange(int start, int stop); + int playBackStartTime(); + int playBackEndTime(); + int currentTime(); + void setCurrentTime(int time); + private: }; diff --git a/plugins/extensions/pykrita/sip/krita/Node.sip b/plugins/extensions/pykrita/sip/krita/Node.sip --- a/plugins/extensions/pykrita/sip/krita/Node.sip +++ b/plugins/extensions/pykrita/sip/krita/Node.sip @@ -23,6 +23,8 @@ QString colorDepth() const; bool animated() const; void enableAnimation() const; + void setShowInTimeline(bool showInTimeline) const; + bool showInTimeline() const; void setCollapsed(bool collapsed); bool collapsed() const; int colorLabel() const;