Minor refactor to support future variable frame width in Timeline

This commit is contained in:
David Capello 2017-07-25 15:26:32 -03:00 committed by David Capello
parent 10eaec8a87
commit 37f55fb635
2 changed files with 83 additions and 27 deletions

View File

@ -299,6 +299,9 @@ void Timeline::setZoom(const double zoom)
m_zoom = std::clamp(zoom, 1.0, 10.0); m_zoom = std::clamp(zoom, 1.0, 10.0);
m_thumbnailsOverlayDirection = gfx::Point(int(frameBoxWidth()*1.0), int(frameBoxWidth()*0.5)); m_thumbnailsOverlayDirection = gfx::Point(int(frameBoxWidth()*1.0), int(frameBoxWidth()*0.5));
m_thumbnailsOverlayVisible = false; m_thumbnailsOverlayVisible = false;
if (m_document)
regenerateCols();
} }
void Timeline::setZoomAndUpdate(const double zoom, void Timeline::setZoomAndUpdate(const double zoom,
@ -397,6 +400,7 @@ void Timeline::updateUsingEditor(Editor* editor)
m_onionskinConn = docPref.onionskin.AfterChange.connect([this]{ invalidate(); }); m_onionskinConn = docPref.onionskin.AfterChange.connect([this]{ invalidate(); });
setFocusStop(true); setFocusStop(true);
regenerateCols();
regenerateRows(); regenerateRows();
setViewScroll(view->timelineScroll()); setViewScroll(view->timelineScroll());
showCurrentCel(); showCurrentCel();
@ -556,6 +560,7 @@ void Timeline::prepareToMoveRange()
void Timeline::moveRange(const Range& range) void Timeline::moveRange(const Range& range)
{ {
regenerateCols();
regenerateRows(); regenerateRows();
// We have to change the range before we generate an // We have to change the range before we generate an
@ -1887,6 +1892,7 @@ void Timeline::onAfterCommandExecution(CommandExecutionEvent& ev)
// TODO Improve this: check if the structure of layers/frames has changed // TODO Improve this: check if the structure of layers/frames has changed
const doc::ObjectVersion currentVersion = m_document->sprite()->version(); const doc::ObjectVersion currentVersion = m_document->sprite()->version();
if (m_savedVersion != currentVersion) { if (m_savedVersion != currentVersion) {
regenerateCols();
regenerateRows(); regenerateRows();
showCurrentCel(); showCurrentCel();
invalidate(); invalidate();
@ -1918,6 +1924,7 @@ void Timeline::onAddLayer(DocEvent& ev)
setLayer(ev.layer()); setLayer(ev.layer());
regenerateCols();
regenerateRows(); regenerateRows();
showCurrentCel(); showCurrentCel();
clearClipboardRange(); clearClipboardRange();
@ -1945,6 +1952,7 @@ void Timeline::onBeforeRemoveLayer(DocEvent& ev)
// removed from the sprite. // removed from the sprite.
void Timeline::onAfterRemoveLayer(DocEvent& ev) void Timeline::onAfterRemoveLayer(DocEvent& ev)
{ {
regenerateCols();
regenerateRows(); regenerateRows();
showCurrentCel(); showCurrentCel();
clearClipboardRange(); clearClipboardRange();
@ -1955,6 +1963,7 @@ void Timeline::onAddFrame(DocEvent& ev)
{ {
setFrame(ev.frame(), false); setFrame(ev.frame(), false);
regenerateCols();
showCurrentCel(); showCurrentCel();
clearClipboardRange(); clearClipboardRange();
invalidate(); invalidate();
@ -1979,6 +1988,7 @@ void Timeline::onRemoveFrame(DocEvent& ev)
if (m_range.enabled()) if (m_range.enabled())
clearAndInvalidateRange(); clearAndInvalidateRange();
regenerateCols();
showCurrentCel(); showCurrentCel();
clearClipboardRange(); clearClipboardRange();
invalidate(); invalidate();
@ -2003,7 +2013,9 @@ void Timeline::onAddTag(DocEvent& ev)
{ {
if (m_tagFocusBand >= 0) { if (m_tagFocusBand >= 0) {
m_tagFocusBand = -1; m_tagFocusBand = -1;
regenerateRows();
regenerateTagBands();
updateScrollBars();
layout(); layout();
} }
} }
@ -2052,6 +2064,7 @@ void Timeline::onAfterFrameChanged(Editor* editor)
if (!hasCapture() && !editor->keepTimelineRange()) if (!hasCapture() && !editor->keepTimelineRange())
clearAndInvalidateRange(); clearAndInvalidateRange();
regenerateCols();
showCurrentCel(); showCurrentCel();
} }
@ -2140,9 +2153,10 @@ void Timeline::getDrawableLayers(layer_t* firstDrawableLayer,
void Timeline::getDrawableFrames(frame_t* firstFrame, frame_t* lastFrame) void Timeline::getDrawableFrames(frame_t* firstFrame, frame_t* lastFrame)
{ {
*firstFrame = frame_t(viewScroll().x / frameBoxWidth()); const int availW = (clientBounds().w - m_separator_x);
*lastFrame = frame_t((viewScroll().x
+ getCelsBounds().w) / frameBoxWidth()); *firstFrame = getFrameInXPos(viewScroll().x);
*lastFrame = getFrameInXPos(viewScroll().x + availW);
} }
void Timeline::drawPart(ui::Graphics* g, const gfx::Rect& bounds, void Timeline::drawPart(ui::Graphics* g, const gfx::Rect& bounds,
@ -2992,11 +3006,13 @@ gfx::Rect Timeline::getPartBounds(const Hit& hit) const
return gfx::Rect(bounds.x + headerBoxWidth()*5, bounds.y + y, return gfx::Rect(bounds.x + headerBoxWidth()*5, bounds.y + y,
separatorX() - headerBoxWidth()*5, headerBoxHeight()); separatorX() - headerBoxWidth()*5, headerBoxHeight());
case PART_HEADER_FRAME: case PART_HEADER_FRAME: {
frame_t frame = std::max(firstFrame(), hit.frame);
return gfx::Rect( return gfx::Rect(
bounds.x + separatorX() + m_separator_w - 1 bounds.x + separatorX() + m_separator_w - 1
+ frameBoxWidth()*std::max(firstFrame(), hit.frame) - viewScroll().x, + getFrameXPos(frame) - viewScroll().x,
bounds.y + y, frameBoxWidth(), headerBoxHeight()); bounds.y + y, getFrameWidth(frame), headerBoxHeight());
}
case PART_ROW: case PART_ROW:
if (validLayer(hit.layer)) { if (validLayer(hit.layer)) {
@ -3042,9 +3058,11 @@ gfx::Rect Timeline::getPartBounds(const Hit& hit) const
case PART_CEL: case PART_CEL:
if (validLayer(hit.layer) && hit.frame >= frame_t(0)) { if (validLayer(hit.layer) && hit.frame >= frame_t(0)) {
return gfx::Rect( return gfx::Rect(
bounds.x + separatorX() + m_separator_w - 1 + frameBoxWidth()*hit.frame - viewScroll().x, bounds.x + separatorX() + m_separator_w - 1
bounds.y + y + headerBoxHeight() + layerBoxHeight()*(lastLayer()-hit.layer) - viewScroll().y, + getFrameXPos(hit.frame) - viewScroll().x,
frameBoxWidth(), layerBoxHeight()); bounds.y + y + headerBoxHeight()
+ layerBoxHeight()*(lastLayer()-hit.layer) - viewScroll().y,
getFrameWidth(hit.frame), layerBoxHeight());
} }
break; break;
@ -3192,6 +3210,24 @@ gfx::Rect Timeline::getRangeClipBounds(const Range& range) const
return clipBounds; return clipBounds;
} }
int Timeline::getFrameXPos(const frame_t frame) const
{
if (frame < 0)
return 0;
return frame * frameBoxWidth();
}
int Timeline::getFrameWidth(const frame_t frame) const
{
(void)frame; // TODO receive the frame future different width per frame.
return frameBoxWidth();
}
frame_t Timeline::getFrameInXPos(const int x) const
{
return frame_t(x / frameBoxWidth());
}
void Timeline::invalidateHit(const Hit& hit) void Timeline::invalidateHit(const Hit& hit)
{ {
if (hit.band >= 0) { if (hit.band >= 0) {
@ -3237,6 +3273,15 @@ void Timeline::invalidateFrame(const frame_t frame)
invalidateRect(rc); invalidateRect(rc);
} }
void Timeline::regenerateCols()
{
ASSERT(m_document);
ASSERT(m_sprite);
m_ncols = m_sprite->totalFrames();
m_ncols = std::max(1, m_ncols);
}
void Timeline::regenerateRows() void Timeline::regenerateRows()
{ {
ASSERT(m_document); ASSERT(m_document);
@ -3364,10 +3409,11 @@ Timeline::Hit Timeline::hitTest(ui::Message* msg, const gfx::Point& mousePos)
- headerBoxHeight() - headerBoxHeight()
+ scroll.y) / layerBoxHeight()); + scroll.y) / layerBoxHeight());
hit.frame = frame_t((mousePos.x hit.frame = getFrameInXPos(
- separatorX() mousePos.x
- m_separator_w - separatorX()
+ scroll.x) / frameBoxWidth()); - m_separator_w
+ scroll.x);
// Flag which indicates that we are in the are below the Background layer/last layer area // Flag which indicates that we are in the are below the Background layer/last layer area
if (hit.layer < 0) if (hit.layer < 0)
@ -3580,10 +3626,11 @@ Timeline::Hit Timeline::hitTestCel(const gfx::Point& mousePos)
- headerBoxHeight() - headerBoxHeight()
+ scroll.y) / layerBoxHeight()); + scroll.y) / layerBoxHeight());
hit.frame = frame_t((mousePos.x hit.frame = getFrameInXPos(
- separatorX() mousePos.x
- m_separator_w - separatorX()
+ scroll.x) / frameBoxWidth()); - m_separator_w
+ scroll.x);
hit.layer = std::clamp(hit.layer, firstLayer(), lastLayer()); hit.layer = std::clamp(hit.layer, firstLayer(), lastLayer());
hit.frame = std::max(firstFrame(), hit.frame); hit.frame = std::max(firstFrame(), hit.frame);
@ -3832,9 +3879,9 @@ void Timeline::showCel(layer_t layer, frame_t frame)
viewport.h += m_vbar.getBarWidth(); viewport.h += m_vbar.getBarWidth();
gfx::Rect celBounds( gfx::Rect celBounds(
viewport.x + frameBoxWidth()*frame - scroll.x, viewport.x + getFrameXPos(frame) - scroll.x,
viewport.y + layerBoxHeight()*(lastLayer() - layer) - scroll.y, viewport.y + layerBoxHeight()*(lastLayer() - layer) - scroll.y,
frameBoxWidth(), layerBoxHeight()); getFrameWidth(frame), layerBoxHeight());
const bool isPlaying = m_editor->isPlaying(); const bool isPlaying = m_editor->isPlaying();
@ -3889,7 +3936,7 @@ gfx::Size Timeline::getScrollableSize() const
{ {
if (m_sprite) { if (m_sprite) {
return gfx::Size( return gfx::Size(
m_sprite->totalFrames() * frameBoxWidth() + getCelsBounds().w/2, getFrameXPos(m_sprite->totalFrames()) + getCelsBounds().w/2,
(m_rows.size()+1) * layerBoxHeight()); (m_rows.size()+1) * layerBoxHeight());
} }
else else
@ -4319,12 +4366,14 @@ double Timeline::zoom() const
// Returns the last frame where the frame tag (or frame tag label) // Returns the last frame where the frame tag (or frame tag label)
// is visible in the timeline. // is visible in the timeline.
int Timeline::calcTagVisibleToFrame(Tag* tag) const frame_t Timeline::calcTagVisibleToFrame(Tag* tag) const
{ {
return frame_t frame =
std::max(tag->toFrame(), getFrameInXPos(
tag->fromFrame() + getFrameXPos(tag->fromFrame()) +
font()->textLength(tag->name())/frameBoxWidth()); font()->textLength(tag->name()));
return std::max(frame, tag->toFrame());
} }
int Timeline::topHeight() const int Timeline::topHeight() const

View File

@ -321,10 +321,14 @@ namespace app {
gfx::Rect getPartBounds(const Hit& hit) const; gfx::Rect getPartBounds(const Hit& hit) const;
gfx::Rect getRangeBounds(const Range& range) const; gfx::Rect getRangeBounds(const Range& range) const;
gfx::Rect getRangeClipBounds(const Range& range) const; gfx::Rect getRangeClipBounds(const Range& range) const;
int getFrameXPos(const frame_t frame) const;
int getFrameWidth(const frame_t frame) const;
frame_t getFrameInXPos(const int x) const;
void invalidateHit(const Hit& hit); void invalidateHit(const Hit& hit);
void invalidateLayer(const Layer* layer); void invalidateLayer(const Layer* layer);
void invalidateFrame(const frame_t frame); void invalidateFrame(const frame_t frame);
void invalidateRange(); void invalidateRange();
void regenerateCols();
void regenerateRows(); void regenerateRows();
void regenerateTagBands(); void regenerateTagBands();
int visibleTagBands() const; int visibleTagBands() const;
@ -376,7 +380,7 @@ namespace app {
int frameBoxWidth() const; int frameBoxWidth() const;
int outlineWidth() const; int outlineWidth() const;
int oneTagHeight() const; int oneTagHeight() const;
int calcTagVisibleToFrame(Tag* tag) const; frame_t calcTagVisibleToFrame(Tag* tag) const;
void updateCelOverlayBounds(const Hit& hit); void updateCelOverlayBounds(const Hit& hit);
void drawCelOverlay(ui::Graphics* g); void drawCelOverlay(ui::Graphics* g);
@ -421,6 +425,9 @@ namespace app {
// regenerating all rows if it's not necessary. // regenerating all rows if it's not necessary.
doc::ObjectVersion m_savedVersion; doc::ObjectVersion m_savedVersion;
// Data used to display columns in the timeline
frame_t m_ncols;
// Data used to display each row in the timeline // Data used to display each row in the timeline
std::vector<Row> m_rows; std::vector<Row> m_rows;