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 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 90 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}
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
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 connect(), and m_d.

◆ ~KisAnimTimelineDocker()

KisAnimTimelineDocker::~KisAnimTimelineDocker ( )
override

Definition at line 330 of file KisAnimTimelineDocker.cpp.

331{
332}

Member Function Documentation

◆ handleFrameRateChange

void KisAnimTimelineDocker::handleFrameRateChange ( )
slot

Definition at line 756 of file KisAnimTimelineDocker.cpp.

757{
758 if (!m_d->canvas || !m_d->canvas->image()) return;
759
760 KisImageAnimationInterface *animInterface = m_d->canvas->image()->animationInterface();
761
762 m_d->titlebar->sbFrameRate->setValue(animInterface->framerate());
763}
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 97 of file KisAnimTimelineDocker.h.

97{ return "TimelineDocker"; }

◆ setAutoKey

void KisAnimTimelineDocker::setAutoKey ( bool value)
slot

Definition at line 742 of file KisAnimTimelineDocker.cpp.

743{
744 {
745 KisImageConfig cfg(false);
746 if (value != cfg.autoKeyEnabled()) {
747 cfg.setAutoKeyEnabled(value);
748 const QIcon icon = cfg.autoKeyEnabled() ? KisIconUtils::loadIcon("auto-key-on") : KisIconUtils::loadIcon("auto-key-off");
749 QAction* action = m_d->titlebar->btnAutoKey->defaultAction();
750 action->setIcon(icon);
751 }
752 }
754}
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
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, connect(), 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 699 of file KisAnimTimelineDocker.cpp.

700{
701 if (!playbackEngine) return;
702
703 // Connect transport controls..
704 connect(m_d->titlebar->transport, SIGNAL(skipBack()), playbackEngine, SLOT(previousKeyframe()), Qt::UniqueConnection);
705 connect(m_d->titlebar->transport, SIGNAL(back()), playbackEngine, SLOT(previousFrame()), Qt::UniqueConnection);
706 connect(m_d->titlebar->transport, SIGNAL(stop()), playbackEngine, SLOT(stop()), Qt::UniqueConnection);
707 connect(m_d->titlebar->transport, SIGNAL(playPause()), this, SLOT(togglePlayback()), Qt::UniqueConnection);
708 connect(m_d->titlebar->transport, SIGNAL(forward()), playbackEngine, SLOT(nextFrame()), Qt::UniqueConnection);
709 connect(m_d->titlebar->transport, SIGNAL(skipForward()), playbackEngine, SLOT(nextKeyframe()), Qt::UniqueConnection);
710
711 connect(m_d->titlebar->frameRegister, SIGNAL(valueChanged(int)), playbackEngine, SLOT(seek(int)), Qt::UniqueConnection);
712
713 m_d->controlsModel.connectPlaybackEngine(playbackEngine);
714
715 m_d->playbackEngine = playbackEngine;
716}
QAction * back(const QObject *recvr, const char *slot, QObject *parent)
QAction * forward(const QObject *recvr, const char *slot, QObject *parent)

References connect(), m_d, and togglePlayback().

◆ setViewManager()

void KisAnimTimelineDocker::setViewManager ( KisViewManager * kisview)
overridevirtual

Implements KisMainwindowObserver.

Definition at line 595 of file KisAnimTimelineDocker.cpp.

596{
597 m_d->mainWindow = view->mainWindow();
598 KisActionManager *actionManager = view->actionManager();
599 m_d->framesView->setActionManager(actionManager);
600
601 KisAction *action = 0;
602
603 KisAnimTimelineDockerTitlebar* titleBar = static_cast<KisAnimTimelineDockerTitlebar*>(titleBarWidget());
604
605 action = actionManager->actionByName("add_blank_frame");
606 titleBar->btnAddKeyframe->setDefaultAction(action);
607 titleBar->btnAddKeyframe->setIconSize(QSize(22, 22));
608
609 action = actionManager->actionByName("add_duplicate_frame");
610 titleBar->btnDuplicateKeyframe->setDefaultAction(action);
611 titleBar->btnDuplicateKeyframe->setIconSize(QSize(22, 22));
612
613 action = actionManager->actionByName("remove_frames");
614 titleBar->btnRemoveKeyframe->setDefaultAction(action);
615 titleBar->btnRemoveKeyframe->setIconSize(QSize(22, 22));
616
617 // Connect playback-related actions..
618 action = actionManager->createAction("toggle_playback");
620 connect(action, SIGNAL(triggered(bool)), this, SLOT(togglePlayback()));
621
622 action = actionManager->createAction("stop_playback");
624 connect(action, SIGNAL(triggered(bool)), m_d->playbackEngine, SLOT(stop()));
625
626 action = actionManager->createAction("previous_frame");
628 connect(action, SIGNAL(triggered(bool)), m_d->playbackEngine, SLOT(previousFrame()));
629
630 action = actionManager->createAction("next_frame");
632 connect(action, SIGNAL(triggered(bool)), m_d->playbackEngine, SLOT(nextFrame()));
633
634 action = actionManager->createAction("previous_keyframe");
636 connect(action, SIGNAL(triggered(bool)), m_d->playbackEngine, SLOT(previousKeyframe()));
637
638 action = actionManager->createAction("next_keyframe");
640 connect(action, SIGNAL(triggered(bool)), m_d->playbackEngine, SLOT(nextKeyframe()));
641
642 action = actionManager->createAction("previous_matching_keyframe");
644 connect(action, SIGNAL(triggered(bool)), m_d->playbackEngine, SLOT(previousMatchingKeyframe()));
645
646 action = actionManager->createAction("next_matching_keyframe");
648 connect(action, SIGNAL(triggered(bool)), m_d->playbackEngine, SLOT(nextMatchingKeyframe()));
649
650 action = actionManager->createAction("previous_unfiltered_keyframe");
652 connect(action, SIGNAL(triggered(bool)), m_d->playbackEngine, SLOT(previousUnfilteredKeyframe()));
653
654 action = actionManager->createAction("next_unfiltered_keyframe");
656 connect(action, SIGNAL(triggered(bool)), m_d->playbackEngine, SLOT(nextUnfilteredKeyframe()));
657
658 action = actionManager->createAction("first_frame");
660 connect(action, &KisAction::triggered, this, [this](bool){
661 if (m_d->canvas) {
662 m_d->playbackEngine->firstFrame();
663 }
664 });
665
666 action = actionManager->createAction("last_frame");
668 connect(action, &KisAction::triggered, this, [this](bool){
669 if (m_d->canvas) {
670 m_d->playbackEngine->lastFrame();
671 }
672 });
673
674 {
675 action = actionManager->createAction("auto_key");
676 m_d->titlebar->btnAutoKey->setDefaultAction(action);
677 m_d->titlebar->btnAutoKey->setIconSize(QSize(22, 22));
678 connect(action, SIGNAL(triggered(bool)), SLOT(setAutoKey(bool)));
679
680 KisImageConfig config(true);
681 action->setChecked(config.autoKeyEnabled());
682 action->setIcon(config.autoKeyEnabled() ? KisIconUtils::loadIcon("auto-key-on") : KisIconUtils::loadIcon("auto-key-off"));
683
684 const bool autoKeyModeDuplicate = config.autoKeyModeDuplicate();
685 m_d->titlebar->autoKeyBlank->setChecked(!autoKeyModeDuplicate);
686 m_d->titlebar->autoKeyDuplicate->setChecked(autoKeyModeDuplicate);
687 }
688
689 {
690 action = actionManager->createAction("drop_frames");
691 m_d->titlebar->btnDropFrames->setDefaultAction(action);
692 m_d->titlebar->btnDropFrames->setIconSize(QSize(22, 22));
693
694 using namespace KisWidgetConnectionUtils;
695 connectControl(action, &m_d->controlsModel, "dropFramesMode");
696 }
697}
A KisActionManager class keeps track of KisActions. These actions are always associated with the GUI....
KisAction * createAction(const QString &name)
KisAction * actionByName(const QString &name) const
void setActivationFlags(ActivationFlags flags)
@ ACTIVE_IMAGE
Activate if there is at least one image.
Definition kis_action.h:43
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, connect(), KisActionManager::createAction(), KisIconUtils::loadIcon(), m_d, KisViewManager::mainWindow(), KisAction::setActivationFlags(), setAutoKey(), and togglePlayback().

◆ togglePlayback

void KisAnimTimelineDocker::togglePlayback ( )
slot

Definition at line 718 of file KisAnimTimelineDocker.cpp.

719{
720 m_d->playbackEngine->playPause();
721
722 KisImageAnimationInterface *animInterface = m_d->canvas->image()->animationInterface();
723 KisCanvasAnimationState *animState = m_d->canvas->animationState();
724
725 if (!animInterface || !animState) return;
726
727 if (animState->playbackState() == PlaybackState::PAUSED) {
728 QModelIndexList selectedIndices = m_d->framesView->selectionModel()->selectedIndexes();
729 QModelIndex currentIndex = m_d->framesView->currentIndex();
730 const int pausedTime = animInterface->currentTime();
731
732 QModelIndex pauseIndex = m_d->framesModel->index(currentIndex.row(), pausedTime);
733
734 if (!pauseIndex.isValid()) return;
735
736 if (!selectedIndices.contains(pauseIndex)) {
737 m_d->framesView->setCurrentIndex(pauseIndex);
738 }
739 }
740}
The KisCanvasAnimationState class stores all of the canvas-specific animation state.

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

◆ 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 590 of file KisAnimTimelineDocker.cpp.

591{
592 setCanvas(0);
593}
void setCanvas(KoCanvasBase *canvas) override

References setCanvas().

◆ updateFrameCache

void KisAnimTimelineDocker::updateFrameCache ( )
slot

Definition at line 515 of file KisAnimTimelineDocker.cpp.

516{
517 m_d->framesModel->setFrameCache(m_d->canvas->frameCache());
518}

References m_d.

◆ updateFrameRegister

void KisAnimTimelineDocker::updateFrameRegister ( )
slot

Definition at line 520 of file KisAnimTimelineDocker.cpp.

521{
522 if (!m_d->canvas && !m_d->canvas->image()) {
523 return;
524 }
525
526 const int frame = m_d->canvas->animationState()->displayProxy()->activeFrame();
527
528 QSignalBlocker blocker(m_d->titlebar->frameRegister);
529 m_d->titlebar->frameRegister->setValue(frame);
530}

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 532 of file KisAnimTimelineDocker.cpp.

533{
534 if (!m_d->playbackEngine) return;
535
536 QString playbackEngineClass = m_d->playbackEngine->metaObject()->className();
537
538 qreal effectiveFps = 0.0;
539 qreal realFps = 0.0;
540 qreal framesDropped = 0.0;
541 bool isPlaying = false;
542
543 {
544 KisPlaybackEngine::PlaybackStats stats = m_d->playbackEngine->playbackStatistics();
545 effectiveFps = stats.expectedFps;
546 realFps = stats.realFps;
547 framesDropped = stats.droppedFramesPortion;
548 isPlaying = effectiveFps > 0.0;
549 }
550
551 KisConfig cfg(true);
552 const bool shouldDropFrames = cfg.animationDropFrames();
553
554 QAction *action = m_d->titlebar->btnDropFrames->defaultAction();
555 const bool droppingFrames = framesDropped > 0.05;
556 action->setIcon(KisIconUtils::loadIcon(droppingFrames ? "droppedframes" : "dropframe"));
557
558 QString actionText;
559 if (!isPlaying) {
560 actionText = QString("%1 (%2)\n"
561 "%3\n"
562 "[PlaybackEngine: %4]")
564 .arg(KritaUtils::toLocalizedOnOff(shouldDropFrames))
565 .arg(i18n("Enable to preserve playback timing."))
566 .arg(playbackEngineClass);
567 } else {
568 actionText = QString("%1 (%2)\n"
569 "%3\n"
570 "%4\n"
571 "%5\n"
572 "[PlaybackEngine: %6]")
574 .arg(KritaUtils::toLocalizedOnOff(shouldDropFrames))
575 .arg(i18n("Effective FPS:\t%1", QString::number(effectiveFps, 'f', 1)))
576 .arg(i18n("Real FPS:\t%1", QString::number(realFps, 'f', 1)))
577 .arg(i18n("Frames dropped:\t%1\%", QString::number(framesDropped * 100, 'f', 1)))
578 .arg(playbackEngineClass);
579 }
580
587 action->setToolTip(actionText);
588}
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 119 of file KisAnimTimelineDocker.h.


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