mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-16 01:20:59 +00:00
Show full animation length/tag length on status bar (fix #1528)
This commit is contained in:
parent
835941a6d6
commit
744e40b4b7
@ -551,6 +551,7 @@ add_library(app-lib
|
||||
util/pic_file.cpp
|
||||
util/pixel_ratio.cpp
|
||||
util/range_utils.cpp
|
||||
util/readable_time.cpp
|
||||
util/wrap_point.cpp
|
||||
webserver.cpp
|
||||
xml_document.cpp
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "app/ui/timeline/timeline.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "app/util/new_image_from_mask.h"
|
||||
#include "app/util/readable_time.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/pi.h"
|
||||
#include "doc/layer.h"
|
||||
@ -554,9 +555,10 @@ bool StandbyState::onUpdateStatusBar(Editor* editor)
|
||||
|
||||
if (sprite->totalFrames() > 1) {
|
||||
sprintf(
|
||||
buf+std::strlen(buf), " :frame: %d :clock: %d",
|
||||
buf+std::strlen(buf), " :frame: %d :clock: %s/%s",
|
||||
editor->frame()+editor->docPref().timeline.firstFrame(),
|
||||
sprite->frameDuration(editor->frame()));
|
||||
human_readable_time(sprite->frameDuration(editor->frame())).c_str(),
|
||||
human_readable_time(sprite->totalAnimationDuration()).c_str());
|
||||
}
|
||||
|
||||
if (editor->docPref().show.grid()) {
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "app/ui_context.h"
|
||||
#include "app/util/clipboard.h"
|
||||
#include "app/util/layer_boundaries.h"
|
||||
#include "app/util/readable_time.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/convert_to.h"
|
||||
#include "base/memory.h"
|
||||
@ -245,6 +246,7 @@ Timeline::Timeline()
|
||||
m_ctxConn = m_context->AfterCommandExecution.connect(
|
||||
&Timeline::onAfterCommandExecution, this);
|
||||
m_context->documents().add_observer(this);
|
||||
m_context->add_observer(this);
|
||||
|
||||
setDoubleBuffered(true);
|
||||
addChild(&m_aniControls);
|
||||
@ -262,6 +264,7 @@ Timeline::~Timeline()
|
||||
|
||||
detachDocument();
|
||||
m_context->documents().remove_observer(this);
|
||||
m_context->remove_observer(this);
|
||||
delete m_confPopup;
|
||||
}
|
||||
|
||||
@ -1569,6 +1572,13 @@ void Timeline::onAfterCommandExecution(CommandExecutionEvent& ev)
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void Timeline::onActiveSiteChange(const doc::Site& site)
|
||||
{
|
||||
if (hasMouse()) {
|
||||
updateStatusBarForFrame(site.frame(), nullptr, site.cel());
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::onRemoveDocument(doc::Document* document)
|
||||
{
|
||||
if (document == m_document) {
|
||||
@ -3118,7 +3128,7 @@ void Timeline::updateStatusBar(ui::Message* msg)
|
||||
|
||||
StatusBar* sb = StatusBar::instance();
|
||||
|
||||
if (m_state == STATE_MOVING_RANGE) {
|
||||
if (m_state == STATE_MOVING_RANGE && msg) {
|
||||
const char* verb = is_copy_key_pressed(msg) ? "Copy": "Move";
|
||||
|
||||
switch (m_range.type()) {
|
||||
@ -3234,39 +3244,88 @@ void Timeline::updateStatusBar(ui::Message* msg)
|
||||
break;
|
||||
|
||||
case PART_HEADER_FRAME:
|
||||
if (validFrame(m_hot.frame)) {
|
||||
sb->setStatusText(
|
||||
0,
|
||||
":frame: %d :clock: %d",
|
||||
(int)m_hot.frame+docPref().timeline.firstFrame(),
|
||||
m_sprite->frameDuration(m_hot.frame));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case PART_CEL:
|
||||
if (layer) {
|
||||
Cel* cel = (layer->isImage() ? layer->cel(m_hot.frame): NULL);
|
||||
StatusBar::instance()->setStatusText(0,
|
||||
"%s at frame %d"
|
||||
#ifdef _DEBUG
|
||||
" (Image %d)"
|
||||
#endif
|
||||
, cel ? "Cel": "Empty cel"
|
||||
, (int)m_hot.frame+1
|
||||
#ifdef _DEBUG
|
||||
, (cel ? cel->image()->id(): 0)
|
||||
#endif
|
||||
);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case PART_FRAME_TAG: {
|
||||
frame_t frame = m_frame;
|
||||
if (validFrame(m_hot.frame))
|
||||
frame = m_hot.frame;
|
||||
|
||||
updateStatusBarForFrame(
|
||||
frame,
|
||||
m_hot.getFrameTag(),
|
||||
(layer ? layer->cel(frame) : nullptr));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sb->clearText();
|
||||
}
|
||||
|
||||
void Timeline::updateStatusBarForFrame(const frame_t frame,
|
||||
const FrameTag* frameTag,
|
||||
const Cel* cel)
|
||||
{
|
||||
if (!m_sprite)
|
||||
return;
|
||||
|
||||
char buf[256] = { 0 };
|
||||
frame_t base = docPref().timeline.firstFrame();
|
||||
frame_t firstFrame = frame;
|
||||
frame_t lastFrame = frame;
|
||||
|
||||
if (frameTag) {
|
||||
firstFrame = frameTag->fromFrame();
|
||||
lastFrame = frameTag->toFrame();
|
||||
}
|
||||
else if (m_range.enabled() &&
|
||||
m_range.frames() > 1) {
|
||||
firstFrame = m_range.firstFrame();
|
||||
lastFrame = m_range.lastFrame();
|
||||
}
|
||||
|
||||
std::sprintf(
|
||||
buf+std::strlen(buf), ":frame: %d",
|
||||
base+frame);
|
||||
if (firstFrame != lastFrame) {
|
||||
std::sprintf(
|
||||
buf+std::strlen(buf), " [%d...%d]",
|
||||
int(base+firstFrame),
|
||||
int(base+lastFrame));
|
||||
}
|
||||
|
||||
std::sprintf(
|
||||
buf+std::strlen(buf), " :clock: %s",
|
||||
human_readable_time(m_sprite->frameDuration(frame)).c_str());
|
||||
if (firstFrame != lastFrame) {
|
||||
std::sprintf(
|
||||
buf+std::strlen(buf), " [%s]",
|
||||
frameTag ?
|
||||
human_readable_time(tagFramesDuration(frameTag)).c_str():
|
||||
human_readable_time(selectedFramesDuration()).c_str());
|
||||
}
|
||||
if (m_sprite->totalFrames() > 1)
|
||||
std::sprintf(
|
||||
buf+std::strlen(buf), "/%s",
|
||||
human_readable_time(m_sprite->totalAnimationDuration()).c_str());
|
||||
|
||||
if (cel) {
|
||||
std::sprintf(
|
||||
buf+std::strlen(buf), " Cel :pos: %d %d :size: %d %d",
|
||||
cel->bounds().x, cel->bounds().y,
|
||||
cel->bounds().w, cel->bounds().h);
|
||||
|
||||
if (cel->links() > 0) {
|
||||
std::sprintf(
|
||||
buf+std::strlen(buf), " Links %d",
|
||||
int(cel->links()));
|
||||
}
|
||||
}
|
||||
|
||||
StatusBar::instance()
|
||||
->setStatusText(0, buf);
|
||||
}
|
||||
|
||||
void Timeline::showCel(layer_t layer, frame_t frame)
|
||||
{
|
||||
gfx::Point scroll = viewScroll();
|
||||
@ -3841,4 +3900,29 @@ void Timeline::onCancel(Context* ctx)
|
||||
invalidate();
|
||||
}
|
||||
|
||||
int Timeline::tagFramesDuration(const FrameTag* frameTag) const
|
||||
{
|
||||
ASSERT(m_sprite);
|
||||
ASSERT(frameTag);
|
||||
|
||||
int duration = 0;
|
||||
for (frame_t f=frameTag->fromFrame();
|
||||
f<frameTag->toFrame(); ++f) {
|
||||
duration += m_sprite->frameDuration(f);
|
||||
}
|
||||
return duration;
|
||||
}
|
||||
|
||||
int Timeline::selectedFramesDuration() const
|
||||
{
|
||||
ASSERT(m_sprite);
|
||||
|
||||
int duration = 0;
|
||||
for (frame_t f=0; f<m_sprite->totalFrames(); ++f) {
|
||||
if (isFrameActive(f))
|
||||
duration += m_sprite->frameDuration(f);
|
||||
}
|
||||
return duration; // TODO cache this value
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -54,6 +54,7 @@ namespace app {
|
||||
|
||||
class Timeline : public ui::Widget
|
||||
, public ui::ScrollableViewDelegate
|
||||
, public doc::ContextObserver
|
||||
, public doc::DocumentsObserver
|
||||
, public doc::DocumentObserver
|
||||
, public app::EditorObserver
|
||||
@ -138,6 +139,9 @@ namespace app {
|
||||
// app::Context slots.
|
||||
void onAfterCommandExecution(CommandExecutionEvent& ev);
|
||||
|
||||
// ContextObserver impl
|
||||
void onActiveSiteChange(const doc::Site& site) override;
|
||||
|
||||
// DocumentsObserver impl.
|
||||
void onRemoveDocument(doc::Document* document) override;
|
||||
|
||||
@ -288,6 +292,9 @@ namespace app {
|
||||
bool isCelActive(const layer_t layerIdx, const frame_t frame) const;
|
||||
bool isCelLooselyActive(const layer_t layerIdx, const frame_t frame) const;
|
||||
void updateStatusBar(ui::Message* msg);
|
||||
void updateStatusBarForFrame(const frame_t frame,
|
||||
const FrameTag* frameTag,
|
||||
const Cel* cel);
|
||||
void updateDropRange(const gfx::Point& pt);
|
||||
void clearClipboardRange();
|
||||
void clearAndInvalidateRange();
|
||||
@ -326,6 +333,9 @@ namespace app {
|
||||
const bool updatePref);
|
||||
|
||||
double zoom() const;
|
||||
int tagFramesDuration(const FrameTag* frameTag) const;
|
||||
// Calculate the duration of the selected range of frames
|
||||
int selectedFramesDuration() const;
|
||||
|
||||
ui::ScrollBar m_hbar;
|
||||
ui::ScrollBar m_vbar;
|
||||
|
31
src/app/util/readable_time.cpp
Normal file
31
src/app/util/readable_time.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/util/readable_time.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace app {
|
||||
|
||||
std::string human_readable_time(const int t)
|
||||
{
|
||||
char buf[32];
|
||||
if (t < 900)
|
||||
std::sprintf(buf, "%dms", t);
|
||||
else if (t < 1000*59)
|
||||
std::sprintf(buf, "%0.2fs", double(t) / 1000.0);
|
||||
else if (t < 1000*60*59)
|
||||
std::sprintf(buf, "%0.2fm", double(t) / 1000.0 / 60.0);
|
||||
else
|
||||
std::sprintf(buf, "%0.2fh", double(t) / 1000.0 / 60.0 / 60.0);
|
||||
return buf;
|
||||
}
|
||||
|
||||
} // namespace app
|
19
src/app/util/readable_time.h
Normal file
19
src/app/util/readable_time.h
Normal file
@ -0,0 +1,19 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef APP_UTIL_READABLE_TIME_H_INCLUDED
|
||||
#define APP_UTIL_READABLE_TIME_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace app {
|
||||
|
||||
std::string human_readable_time(const int t);
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
@ -376,6 +376,14 @@ int Sprite::frameDuration(frame_t frame) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Sprite::totalAnimationDuration() const
|
||||
{
|
||||
int duration = 0;
|
||||
for (frame_t frame=0; frame<m_frames; ++frame)
|
||||
duration += frameDuration(frame);
|
||||
return duration; // TODO cache this value
|
||||
}
|
||||
|
||||
void Sprite::setFrameDuration(frame_t frame, int msecs)
|
||||
{
|
||||
if (frame >= 0 && frame < m_frames)
|
||||
|
@ -123,6 +123,7 @@ namespace doc {
|
||||
void setTotalFrames(frame_t frames);
|
||||
|
||||
int frameDuration(frame_t frame) const;
|
||||
int totalAnimationDuration() const;
|
||||
void setFrameDuration(frame_t frame, int msecs);
|
||||
void setFrameRangeDuration(frame_t from, frame_t to, int msecs);
|
||||
void setDurationForAllFrames(int msecs);
|
||||
|
Loading…
x
Reference in New Issue
Block a user