Krita Source Code Documentation
Loading...
Searching...
No Matches
KisAnimTimelineDocker Class Reference

Krita's Animation Timeline Docker. This is the GUI heart of Krita's traditional animation workflow, and is where artists can configure, edit, scrub and play their animation. More...

#include <KisAnimTimelineDocker.h>

+ Inheritance diagram for KisAnimTimelineDocker:

Classes

struct  Private
 

Public Slots

void handleFrameRateChange ()
 
void handleThemeChange ()
 
void setAutoKey (bool value)
 
void setImageAnimSettings ()
 
void togglePlayback ()
 
void updateFrameCache ()
 
void updateFrameRegister ()
 
void updatePlaybackStatistics ()
 

Public Member Functions

 KisAnimTimelineDocker ()
 
QString observerName () override
 
void setCanvas (KoCanvasBase *canvas) override
 
void setPlaybackEngine (KisPlaybackEngine *playbackEngine)
 
void setViewManager (KisViewManager *kisview) override
 
void unsetCanvas () override
 
 ~KisAnimTimelineDocker () override
 
- Public Member Functions inherited from KisMainwindowObserver
 KisMainwindowObserver ()
 
 ~KisMainwindowObserver () override
 
- Public Member Functions inherited from KoCanvasObserverBase
 KoCanvasObserverBase ()
 
KoCanvasBaseobservedCanvas () const
 
void setObservedCanvas (KoCanvasBase *canvas)
 
void unsetObservedCanvas ()
 
virtual ~KoCanvasObserverBase ()
 

Private Member Functions

void establishPlaybackEngineConnections (KisPlaybackEngine *playbackEngine, KisActionManager *actionManager=nullptr)
 

Private Attributes

const QScopedPointer< Privatem_d
 

Additional Inherited Members

Detailed Description

Krita's Animation Timeline Docker. This is the GUI heart of Krita's traditional animation workflow, and is where artists can configure, edit, scrub and play their animation.

Currently interacts with the TimelineFramesView/Model as well as the KisImageAnimationInterface. (TODO: Consider refactoring to streamline this interaction towards Docker -> AnimationPlayer -> ImageAnimInterface)

Definition at line 91 of file KisAnimTimelineDocker.h.

Constructor & Destructor Documentation

◆ KisAnimTimelineDocker()

KisAnimTimelineDocker::KisAnimTimelineDocker ( )

Definition at line 300 of file KisAnimTimelineDocker.cpp.

301 : QDockWidget(i18n("Animation Timeline"))
302 , m_d(new Private(this))
303{
304 setWidget(m_d->framesView);
305
306 // Titlebar Widget..
307 setTitleBarWidget(m_d->titlebar);
308
309 connect(m_d->titlebar->btnOnionSkinsMenu, &QToolButton::released, [this](){
310 if (m_d->mainWindow) {
311 QDockWidget *docker = m_d->mainWindow->dockWidget("OnionSkinsDocker");
312 if (docker) {
313 docker->setVisible(!docker->isVisible());
314 }
315 }
316 });
317
318 {
319 using namespace KisWidgetConnectionUtils;
320 connectControl(m_d->titlebar->sbSpeed, &m_d->controlsModel, "playbackSpeedDenorm");
321 }
322
323 // Watch for KisPlaybackEngine changes and initialize current one..
325 setPlaybackEngine(KisPart::instance()->playbackEngine());
326
327 setEnabled(false);
328}
void setPlaybackEngine(KisPlaybackEngine *playbackEngine)
const QScopedPointer< Private > m_d
static KisPart * instance()
Definition KisPart.cpp:131
void playbackEngineChanged(KisPlaybackEngine *newPlaybackEngine)
void connectControl(KisCompositeOpListWidget *widget, QObject *source, const char *property)

References m_d.

◆ ~KisAnimTimelineDocker()

KisAnimTimelineDocker::~KisAnimTimelineDocker ( )
override

Definition at line 330 of file KisAnimTimelineDocker.cpp.

331{
332}

Member Function Documentation

◆ establishPlaybackEngineConnections()

void KisAnimTimelineDocker::establishPlaybackEngineConnections ( KisPlaybackEngine * playbackEngine,
KisActionManager * actionManager = nullptr )
private

Definition at line 515 of file KisAnimTimelineDocker.cpp.

516{
517 if (actionManager) {
518 // Connect actions..
519 KisAction *action = nullptr;
520
521 action = actionManager->createAction("stop_playback");
523 connect(action, SIGNAL(triggered(bool)), playbackEngine, SLOT(stop()));
524
525 action = actionManager->createAction("previous_frame");
527 connect(action, SIGNAL(triggered(bool)), playbackEngine, SLOT(previousFrame()));
528
529 action = actionManager->createAction("next_frame");
531 connect(action, SIGNAL(triggered(bool)), playbackEngine, SLOT(nextFrame()));
532
533 action = actionManager->createAction("previous_keyframe");
535 connect(action, SIGNAL(triggered(bool)), playbackEngine, SLOT(previousKeyframe()));
536
537 action = actionManager->createAction("next_keyframe");
539 connect(action, SIGNAL(triggered(bool)), playbackEngine, SLOT(nextKeyframe()));
540
541 action = actionManager->createAction("previous_matching_keyframe");
543 connect(action, SIGNAL(triggered(bool)), playbackEngine, SLOT(previousMatchingKeyframe()));
544
545 action = actionManager->createAction("next_matching_keyframe");
547 connect(action, SIGNAL(triggered(bool)), playbackEngine, SLOT(nextMatchingKeyframe()));
548
549 action = actionManager->createAction("previous_unfiltered_keyframe");
551 connect(action, SIGNAL(triggered(bool)), playbackEngine, SLOT(previousUnfilteredKeyframe()));
552
553 action = actionManager->createAction("next_unfiltered_keyframe");
555 connect(action, SIGNAL(triggered(bool)), playbackEngine, SLOT(nextUnfilteredKeyframe()));
556
557 action = actionManager->createAction("first_frame");
559 connect(action, &KisAction::triggered, this, [this, playbackEngine](bool){
560 if (m_d->canvas) {
561 playbackEngine->firstFrame();
562 }
563 });
564
565 action = actionManager->createAction("last_frame");
567 connect(action, &KisAction::triggered, this, [this, playbackEngine](bool){
568 if (m_d->canvas) {
569 playbackEngine->lastFrame();
570 }
571 });
572 }
573
574 // Connect transport controls gui..
575 connect(m_d->titlebar->transport, SIGNAL(skipBack()), playbackEngine, SLOT(previousKeyframe()), Qt::UniqueConnection);
576 connect(m_d->titlebar->transport, SIGNAL(back()), playbackEngine, SLOT(previousFrame()), Qt::UniqueConnection);
577 connect(m_d->titlebar->transport, SIGNAL(stop()), playbackEngine, SLOT(stop()), Qt::UniqueConnection);
578 connect(m_d->titlebar->transport, SIGNAL(playPause()), this, SLOT(togglePlayback()), Qt::UniqueConnection);
579 connect(m_d->titlebar->transport, SIGNAL(forward()), playbackEngine, SLOT(nextFrame()), Qt::UniqueConnection);
580 connect(m_d->titlebar->transport, SIGNAL(skipForward()), playbackEngine, SLOT(nextKeyframe()), Qt::UniqueConnection);
581
582 connect(m_d->titlebar->frameRegister, SIGNAL(valueChanged(int)), playbackEngine, SLOT(seek(int)), Qt::UniqueConnection);
583}
KisAction * createAction(const QString &name)
void setActivationFlags(ActivationFlags flags)
@ ACTIVE_IMAGE
Activate if there is at least one image.
Definition kis_action.h:43
QAction * back(const QObject *recvr, const char *slot, QObject *parent)
QAction * forward(const QObject *recvr, const char *slot, QObject *parent)

References KisAction::ACTIVE_IMAGE, KisActionManager::createAction(), m_d, KisAction::setActivationFlags(), and togglePlayback().

◆ handleFrameRateChange

void KisAnimTimelineDocker::handleFrameRateChange ( )
slot

Definition at line 772 of file KisAnimTimelineDocker.cpp.

773{
774 if (!m_d->canvas || !m_d->canvas->image()) return;
775
776 KisImageAnimationInterface *animInterface = m_d->canvas->image()->animationInterface();
777
778 m_d->titlebar->sbFrameRate->setValue(animInterface->framerate());
779}
KisImageAnimationInterface * animationInterface() const

References KisImage::animationInterface(), KisImageAnimationInterface::framerate(), KisImageAnimationInterface::image(), and m_d.

◆ handleThemeChange

void KisAnimTimelineDocker::handleThemeChange ( )
slot

Definition at line 486 of file KisAnimTimelineDocker.cpp.

487{
488 if (m_d->framesView) {
489 m_d->framesView->slotUpdateIcons();
490 }
491}

References m_d.

◆ observerName()

QString KisAnimTimelineDocker::observerName ( )
inlineoverridevirtual

Reimplemented from KoCanvasObserverBase.

Definition at line 98 of file KisAnimTimelineDocker.h.

98{ return "TimelineDocker"; }

◆ setAutoKey

void KisAnimTimelineDocker::setAutoKey ( bool value)
slot

Definition at line 758 of file KisAnimTimelineDocker.cpp.

759{
760 {
761 KisImageConfig cfg(false);
762 if (value != cfg.autoKeyEnabled()) {
763 cfg.setAutoKeyEnabled(value);
764 const QIcon icon = cfg.autoKeyEnabled() ? KisIconUtils::loadIcon("auto-key-on") : KisIconUtils::loadIcon("auto-key-off");
765 QAction* action = m_d->titlebar->btnAutoKey->defaultAction();
766 action->setIcon(icon);
767 }
768 }
770}
float value(const T *src, size_t ch)
static KisImageConfigNotifier * instance()
QIcon loadIcon(const QString &name)

References KisImageConfig::autoKeyEnabled(), KisImageConfigNotifier::instance(), KisIconUtils::loadIcon(), m_d, KisImageConfigNotifier::notifyAutoKeyFrameConfigurationChanged(), KisImageConfig::setAutoKeyEnabled(), and value().

◆ setCanvas()

void KisAnimTimelineDocker::setCanvas ( KoCanvasBase * canvas)
overridevirtual

re-implement this method in your canvas observer. It will be called whenever a canvas becomes active. Note that you are responsible for not connecting more than one time to the signals of a canvas or any of the QObjects you can access through the canvas.

Implements KoCanvasObserverBase.

Definition at line 355 of file KisAnimTimelineDocker.cpp.

356{
357 if (m_d->canvas == canvas) return;
358
359 if (m_d->framesModel->hasConnectionToCanvas()) {
360 m_d->canvasConnections.clear();
361 m_d->framesModel->setDummiesFacade(0, 0, 0);
362 m_d->framesModel->setFrameCache(0);
363 m_d->framesModel->setAnimationPlayer(0);
364 m_d->framesModel->setDocument(0);
365 m_d->framesModel->setNodeManipulationInterface(0);
366 }
367
368 // Deinitialize from previous canvas...
369 if (m_d->canvas) {
370 m_d->canvas->disconnectCanvasObserver(this);
371 m_d->canvas->animationState()->disconnect(this);
372 m_d->titlebar->transport->setPlaying(false);
373
374 m_d->titlebar->btnAudioMenu->setEnabled(false);
375
376 if(m_d->canvas->image()) {
377 m_d->canvas->image()->animationInterface()->disconnect(this);
378 m_d->titlebar->sbStartFrame->disconnect(m_d->canvas->image()->animationInterface());
379 m_d->titlebar->sbEndFrame->disconnect(m_d->canvas->image()->animationInterface());
380 m_d->titlebar->sbFrameRate->disconnect(m_d->canvas->image()->animationInterface());
381 }
382 }
383
384 m_d->canvas = dynamic_cast<KisCanvas2*>(canvas);
385 setEnabled(m_d->canvas != 0);
386 m_d->framesView->slotCanvasUpdate(m_d->canvas);
387
388 // Reinitialize new canvas..
389 if (m_d->canvas) {
390 KisDocument *doc = static_cast<KisDocument*>(m_d->canvas->imageView()->document());
391 KisShapeController *kritaShapeController = dynamic_cast<KisShapeController*>(doc->shapeController());
392 m_d->framesModel->setDummiesFacade(kritaShapeController,
393 m_d->canvas->image(),
394 m_d->canvas->viewManager()->nodeManager()->nodeDisplayModeAdapter());
395
396 m_d->framesModel->setDocument(doc);
397
399
400 { // Titlebar widgets...
401 KisSignalsBlocker blocker(m_d->titlebar->sbStartFrame,
402 m_d->titlebar->sbEndFrame,
403 m_d->titlebar->sbFrameRate,
404 m_d->titlebar->frameRegister);
405
406 KisImageAnimationInterface *animinterface = m_d->canvas->image()->animationInterface();
407 m_d->titlebar->sbStartFrame->setValue(animinterface->documentPlaybackRange().start());
408 m_d->titlebar->sbEndFrame->setValue(animinterface->documentPlaybackRange().end());
409 m_d->titlebar->sbFrameRate->setValue(animinterface->framerate());
410 m_d->titlebar->frameRegister->setValue(animinterface->currentTime());
411
412 m_d->titlebar->btnAudioMenu->setEnabled(true); // Menu is disabled until a canvas is loaded.
413 }
414
415 m_d->framesModel->setAnimationPlayer(m_d->canvas->animationState());
416
417 m_d->framesModel->setNodeManipulationInterface(
418 new NodeManagerInterface(m_d->canvas->viewManager()->nodeManager()));
419
420 m_d->canvasConnections.addConnection(
421 m_d->canvas->viewManager()->nodeManager(), SIGNAL(sigNodeActivated(KisNodeSP)),
422 m_d->framesModel, SLOT(slotCurrentNodeChanged(KisNodeSP)));
423
424 m_d->canvasConnections.addConnection(
425 m_d->framesModel, SIGNAL(requestCurrentNodeChanged(KisNodeSP)),
426 m_d->canvas->viewManager()->nodeManager(), SLOT(slotNonUiActivatedNode(KisNodeSP)));
427
428 m_d->framesModel->slotCurrentNodeChanged(m_d->canvas->viewManager()->activeNode());
429
430 m_d->canvasConnections.addConnection(
431 m_d->canvas->viewManager()->mainWindow(), SIGNAL(themeChanged()),
432 this, SLOT(handleThemeChange()));
433
434 m_d->canvasConnections.addConnection(
435 m_d->canvas, SIGNAL(sigCanvasEngineChanged()),
436 this, SLOT(updateFrameCache()));
437
438 m_d->titlebar->transport->setPlaying(m_d->canvas->animationState()->playbackState() == PlaybackState::PLAYING);
439
440 m_d->titlebar->volumeSlider->setValue(m_d->framesModel->audioVolume() * 100.0);
441
442 connect(m_d->canvas->image()->animationInterface(), SIGNAL(sigFramerateChanged()), SLOT(handleFrameRateChange()));
443
444 connect(m_d->titlebar->sbFrameRate, SIGNAL(valueChanged(int)), this, SLOT(setImageAnimSettings()));
445 connect(m_d->titlebar->sbStartFrame, SIGNAL(valueChanged(int)), this, SLOT(setImageAnimSettings()));
446 connect(m_d->titlebar->sbEndFrame, SIGNAL(valueChanged(int)), this, SLOT(setImageAnimSettings()));
447
448 connect(m_d->canvas->image()->animationInterface(), &KisImageAnimationInterface::sigDocumentRangeChanged, this, [this]() {
449 if (!m_d->canvas || !m_d->canvas->image()) return;
450
451 KisImageAnimationInterface *animInterface = m_d->canvas->image()->animationInterface();
452
453 int start = animInterface->documentPlaybackRange().start();
454 int end = animInterface->documentPlaybackRange().end();
455
456 m_d->titlebar->sbStartFrame->setValue(start);
457 m_d->titlebar->sbEndFrame->setValue(end);
458
459 //Auto zoom Timeline to new document playback range..
460 KisConfig cfg(true);
461 if (cfg.autoZoomTimelineToPlaybackRange()) {
462 m_d->framesView->slotFitViewToFrameRange(0, end); // TODO: fit from start to end, instead of 0 to end.
463 }
464 });
465
466 connect(m_d->canvas->animationState(), SIGNAL(sigFrameChanged()), this, SLOT(updateFrameRegister()));
467 connect(m_d->canvas->animationState(), &KisCanvasAnimationState::sigPlaybackStateChanged, this, [this](PlaybackState state){
468 m_d->titlebar->frameRegister->setDisabled(state == PlaybackState::PLAYING);
469 if (state == PlaybackState::STOPPED) {
470 updateFrameRegister();
471 }
472 });
473 connect(m_d->canvas->animationState(), &KisCanvasAnimationState::sigPlaybackStateChanged, this, [this](PlaybackState state){
474 m_d->titlebar->transport->setPlaying(state == PlaybackState::PLAYING);
475 });
476
477 connect(m_d->canvas->animationState(), &KisCanvasAnimationState::sigPlaybackStatisticsUpdated,
479
480 connect(m_d->canvas->image()->animationInterface(), SIGNAL(sigUiTimeChanged(int)), this, SLOT(updateFrameRegister()));
481
482 m_d->controlsModel.connectAnimationState(m_d->canvas->animationState());
483 }
484}
void sigPlaybackStateChanged(PlaybackState state)
KisShapeController * shapeController
const KisTimeSpan & documentPlaybackRange() const
documentPlaybackRange
int start() const
int end() const

References KisImage::animationInterface(), Private::canvas, KisImageAnimationInterface::currentTime(), KisImageAnimationInterface::documentPlaybackRange(), KisTimeSpan::end(), KisImageAnimationInterface::framerate(), handleFrameRateChange(), handleThemeChange(), KisImageAnimationInterface::image(), KisDummiesFacadeBase::image(), m_d, KisNodeManager::nodeDisplayModeAdapter(), KisViewManager::nodeManager(), PLAYING, setImageAnimSettings(), KisDocument::shapeController, KisImageAnimationInterface::sigDocumentRangeChanged(), KisCanvasAnimationState::sigPlaybackStateChanged(), KisTimeSpan::start(), updateFrameCache(), updateFrameRegister(), and KisCanvas2::viewManager().

◆ setImageAnimSettings

void KisAnimTimelineDocker::setImageAnimSettings ( )
slot

Definition at line 493 of file KisAnimTimelineDocker.cpp.

494{
495 if (!m_d->canvas || !m_d->canvas->image()) return;
496
498 m_d->titlebar->sbFrameRate->value(),
499 m_d->titlebar->sbStartFrame->value(),
500 m_d->titlebar->sbEndFrame->value()
501 };
502
503 KisImageAnimSettingCommand *undoCommand = new KisImageAnimSettingCommand(m_d->canvas->image()->animationInterface(), settings);
504
505 //KisProcessingApplicator::applyCommand(undoCommand);
506 QScopedPointer<KisProcessingApplicator> applicator(
509 undoCommand->text(),
510 0, undoCommand->id()));
511 applicator->applyCommand(undoCommand);
512 applicator->end();
513}
KUndo2MagicString text() const

References KisImageAnimSettingCommand::id(), m_d, KisProcessingApplicator::NONE, and KUndo2Command::text().

◆ setPlaybackEngine()

void KisAnimTimelineDocker::setPlaybackEngine ( KisPlaybackEngine * playbackEngine)

Definition at line 719 of file KisAnimTimelineDocker.cpp.

720{
721 if (!playbackEngine) return;
722
723 m_d->controlsModel.connectPlaybackEngine(playbackEngine);
724
725 m_d->playbackEngine = playbackEngine;
726
727 KisActionManager *actionManager = nullptr;
728 if (m_d->canvas && m_d->canvas->viewManager()) {
729 actionManager = m_d->canvas->viewManager()->actionManager();
730 }
731 establishPlaybackEngineConnections(m_d->playbackEngine, actionManager);
732}
A KisActionManager class keeps track of KisActions. These actions are always associated with the GUI....
void establishPlaybackEngineConnections(KisPlaybackEngine *playbackEngine, KisActionManager *actionManager=nullptr)
KisViewManager * viewManager() const
KisActionManager * actionManager() const
KisCanvas2 * canvas

References KisViewManager::actionManager(), Private::canvas, establishPlaybackEngineConnections(), m_d, and KisCanvas2::viewManager().

◆ setViewManager()

void KisAnimTimelineDocker::setViewManager ( KisViewManager * kisview)
overridevirtual

Implements KisMainwindowObserver.

Definition at line 665 of file KisAnimTimelineDocker.cpp.

666{
667 m_d->mainWindow = view->mainWindow();
668 KisActionManager *actionManager = view->actionManager();
669 m_d->framesView->setActionManager(actionManager);
670
671 KisAction *action = 0;
672
673 KisAnimTimelineDockerTitlebar* titleBar = static_cast<KisAnimTimelineDockerTitlebar*>(titleBarWidget());
674
675 action = actionManager->actionByName("add_blank_frame");
676 titleBar->btnAddKeyframe->setDefaultAction(action);
677 titleBar->btnAddKeyframe->setIconSize(QSize(22, 22));
678
679 action = actionManager->actionByName("add_duplicate_frame");
680 titleBar->btnDuplicateKeyframe->setDefaultAction(action);
681 titleBar->btnDuplicateKeyframe->setIconSize(QSize(22, 22));
682
683 action = actionManager->actionByName("remove_frames");
684 titleBar->btnRemoveKeyframe->setDefaultAction(action);
685 titleBar->btnRemoveKeyframe->setIconSize(QSize(22, 22));
686
687 // Connect playback-related actions..
688 action = actionManager->createAction("toggle_playback");
690 connect(action, SIGNAL(triggered(bool)), this, SLOT(togglePlayback()));
691
692 establishPlaybackEngineConnections(m_d->playbackEngine, actionManager);
693
694 {
695 action = actionManager->createAction("auto_key");
696 m_d->titlebar->btnAutoKey->setDefaultAction(action);
697 m_d->titlebar->btnAutoKey->setIconSize(QSize(22, 22));
698 connect(action, SIGNAL(triggered(bool)), SLOT(setAutoKey(bool)));
699
700 KisImageConfig config(true);
701 action->setChecked(config.autoKeyEnabled());
702 action->setIcon(config.autoKeyEnabled() ? KisIconUtils::loadIcon("auto-key-on") : KisIconUtils::loadIcon("auto-key-off"));
703
704 const bool autoKeyModeDuplicate = config.autoKeyModeDuplicate();
705 m_d->titlebar->autoKeyBlank->setChecked(!autoKeyModeDuplicate);
706 m_d->titlebar->autoKeyDuplicate->setChecked(autoKeyModeDuplicate);
707 }
708
709 {
710 action = actionManager->createAction("drop_frames");
711 m_d->titlebar->btnDropFrames->setDefaultAction(action);
712 m_d->titlebar->btnDropFrames->setIconSize(QSize(22, 22));
713
714 using namespace KisWidgetConnectionUtils;
715 connectControl(action, &m_d->controlsModel, "dropFramesMode");
716 }
717}
KisAction * actionByName(const QString &name) const
A customized titlebar for the Animation Timeline Docker that's packed with useful widgets and menus.

References KisActionManager::actionByName(), KisViewManager::actionManager(), KisAction::ACTIVE_IMAGE, KisImageConfig::autoKeyEnabled(), KisImageConfig::autoKeyModeDuplicate(), KisAnimTimelineDockerTitlebar::btnAddKeyframe, KisAnimTimelineDockerTitlebar::btnDuplicateKeyframe, KisAnimTimelineDockerTitlebar::btnRemoveKeyframe, KisActionManager::createAction(), establishPlaybackEngineConnections(), KisIconUtils::loadIcon(), m_d, KisViewManager::mainWindow(), KisAction::setActivationFlags(), setAutoKey(), and togglePlayback().

◆ togglePlayback

void KisAnimTimelineDocker::togglePlayback ( )
slot

Definition at line 734 of file KisAnimTimelineDocker.cpp.

735{
736 m_d->playbackEngine->playPause();
737
738 KisImageAnimationInterface *animInterface = m_d->canvas->image()->animationInterface();
739 KisCanvasAnimationState *animState = m_d->canvas->animationState();
740
741 if (!animInterface || !animState) return;
742
743 if (animState->playbackState() == PlaybackState::PAUSED) {
744 QModelIndexList selectedIndices = m_d->framesView->selectionModel()->selectedIndexes();
745 QModelIndex currentIndex = m_d->framesView->currentIndex();
746 const int pausedTime = animInterface->currentTime();
747
748 QModelIndex pauseIndex = m_d->framesModel->index(currentIndex.row(), pausedTime);
749
750 if (!pauseIndex.isValid()) return;
751
752 if (!selectedIndices.contains(pauseIndex)) {
753 m_d->framesView->setCurrentIndex(pauseIndex);
754 }
755 }
756}
The KisCanvasAnimationState class stores all of the canvas-specific animation state.

References KisImage::animationInterface(), KisImageAnimationInterface::currentTime(), KisImageAnimationInterface::image(), m_d, PAUSED, and KisCanvasAnimationState::playbackState().

◆ unsetCanvas()

void KisAnimTimelineDocker::unsetCanvas ( )
overridevirtual

Re-implement to notify the observer that its canvas is no longer among the living. The daisies, it is pushing up. This means you don't have to disconnect, it's dead.

The old canvas should be deleted already, so if you stored a pointer to it, don't touch!

Note that currently there is a bug where in certain specific circumstances unsetCanvas can be called when it shouldn't, see for example KWStatisticsDocker for a workaround for this problem.

Implements KoCanvasObserverBase.

Definition at line 660 of file KisAnimTimelineDocker.cpp.

661{
662 setCanvas(0);
663}
void setCanvas(KoCanvasBase *canvas) override

References setCanvas().

◆ updateFrameCache

void KisAnimTimelineDocker::updateFrameCache ( )
slot

Definition at line 585 of file KisAnimTimelineDocker.cpp.

586{
587 m_d->framesModel->setFrameCache(m_d->canvas->frameCache());
588}

References m_d.

◆ updateFrameRegister

void KisAnimTimelineDocker::updateFrameRegister ( )
slot

Definition at line 590 of file KisAnimTimelineDocker.cpp.

591{
592 if (!m_d->canvas && !m_d->canvas->image()) {
593 return;
594 }
595
596 const int frame = m_d->canvas->animationState()->displayProxy()->activeFrame();
597
598 QSignalBlocker blocker(m_d->titlebar->frameRegister);
599 m_d->titlebar->frameRegister->setValue(frame);
600}

References m_d.

◆ updatePlaybackStatistics

void KisAnimTimelineDocker::updatePlaybackStatistics ( )
slot

NOTE: we update stats on the action, but not on the button itself, so the stats will automatically propagate to all the buttons that use this action, including the one in the curves docker

Definition at line 602 of file KisAnimTimelineDocker.cpp.

603{
604 if (!m_d->playbackEngine) return;
605
606 QString playbackEngineClass = m_d->playbackEngine->metaObject()->className();
607
608 qreal effectiveFps = 0.0;
609 qreal realFps = 0.0;
610 qreal framesDropped = 0.0;
611 bool isPlaying = false;
612
613 {
614 KisPlaybackEngine::PlaybackStats stats = m_d->playbackEngine->playbackStatistics();
615 effectiveFps = stats.expectedFps;
616 realFps = stats.realFps;
617 framesDropped = stats.droppedFramesPortion;
618 isPlaying = effectiveFps > 0.0;
619 }
620
621 KisConfig cfg(true);
622 const bool shouldDropFrames = cfg.animationDropFrames();
623
624 QAction *action = m_d->titlebar->btnDropFrames->defaultAction();
625 const bool droppingFrames = framesDropped > 0.05;
626 action->setIcon(KisIconUtils::loadIcon(droppingFrames ? "droppedframes" : "dropframe"));
627
628 QString actionText;
629 if (!isPlaying) {
630 actionText = QString("%1 (%2)\n"
631 "%3\n"
632 "[PlaybackEngine: %4]")
634 .arg(KritaUtils::toLocalizedOnOff(shouldDropFrames))
635 .arg(i18n("Enable to preserve playback timing."))
636 .arg(playbackEngineClass);
637 } else {
638 actionText = QString("%1 (%2)\n"
639 "%3\n"
640 "%4\n"
641 "%5\n"
642 "[PlaybackEngine: %6]")
644 .arg(KritaUtils::toLocalizedOnOff(shouldDropFrames))
645 .arg(i18n("Effective FPS:\t%1", QString::number(effectiveFps, 'f', 1)))
646 .arg(i18n("Real FPS:\t%1", QString::number(realFps, 'f', 1)))
647 .arg(i18n("Frames dropped:\t%1\%", QString::number(framesDropped * 100, 'f', 1)))
648 .arg(playbackEngineClass);
649 }
650
657 action->setToolTip(actionText);
658}
const QString dropFramesActionName
QString KRITAIMAGE_EXPORT toLocalizedOnOff(bool value)

References KisConfig::animationDropFrames(), KisAnimUtils::dropFramesActionName, KisPlaybackEngine::PlaybackStats::droppedFramesPortion, KisPlaybackEngine::PlaybackStats::expectedFps, KisIconUtils::loadIcon(), m_d, KisPlaybackEngine::PlaybackStats::realFps, and KritaUtils::toLocalizedOnOff().

Member Data Documentation

◆ m_d

const QScopedPointer<Private> KisAnimTimelineDocker::m_d
private

Definition at line 122 of file KisAnimTimelineDocker.h.


The documentation for this class was generated from the following files: