mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-04 08:46:09 +00:00
Improve handling of overlapping frame tags in the Timeline (fix #768)
This commit is contained in:
parent
2c2f29b87a
commit
27bc151a37
Binary file not shown.
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 14 KiB |
@ -493,7 +493,7 @@
|
||||
<text color="button_hot_text" state="mouse" />
|
||||
<text color="button_selected_text" state="selected" />
|
||||
<text color="background" x="1" y="1" state="disabled" />
|
||||
<newlayer />
|
||||
<newlayer />
|
||||
<text color="disabled" state="disabled" />
|
||||
</style>
|
||||
<style id="check_box" border="2">
|
||||
|
@ -1136,9 +1136,11 @@ void Timeline::onResize(ui::ResizeEvent& ev)
|
||||
|
||||
gfx::Size sz = m_aniControls.sizeHint();
|
||||
m_aniControls.setBounds(
|
||||
gfx::Rect(rc.x, rc.y, MIN(sz.w, m_separator_x),
|
||||
font()->height() +
|
||||
skinTheme()->dimensions.timelineTagsAreaHeight()));
|
||||
gfx::Rect(
|
||||
rc.x,
|
||||
rc.y+MAX(0, m_tagBands-1)*oneTagHeight(),
|
||||
MIN(sz.w, m_separator_x),
|
||||
oneTagHeight()));
|
||||
|
||||
updateScrollBars();
|
||||
}
|
||||
@ -2010,11 +2012,15 @@ void Timeline::drawFrameTags(ui::Graphics* g)
|
||||
clientBounds().w,
|
||||
theme->dimensions.timelineTagsAreaHeight()));
|
||||
|
||||
std::vector<unsigned char> tagsPerFrame(m_sprite->totalFrames(), 0);
|
||||
|
||||
for (FrameTag* frameTag : m_sprite->frameTags()) {
|
||||
gfx::Rect bounds1 = getPartBounds(Hit(PART_HEADER_FRAME, firstLayer(), frameTag->fromFrame()));
|
||||
gfx::Rect bounds2 = getPartBounds(Hit(PART_HEADER_FRAME, firstLayer(), frameTag->toFrame()));
|
||||
gfx::Rect bounds = bounds1.createUnion(bounds2);
|
||||
bounds.y -= theme->dimensions.timelineTagsAreaHeight();
|
||||
gfx::Rect frameTagBounds = getPartBounds(Hit(PART_FRAME_TAG, 0, 0, frameTag->id()));
|
||||
bounds.h = bounds.y2() - frameTagBounds.y2();
|
||||
bounds.y = frameTagBounds.y2();
|
||||
|
||||
{
|
||||
IntersectClip clip(g, bounds);
|
||||
@ -2023,7 +2029,7 @@ void Timeline::drawFrameTags(ui::Graphics* g)
|
||||
}
|
||||
|
||||
{
|
||||
bounds = getPartBounds(Hit(PART_FRAME_TAG, 0, 0, frameTag->id()));
|
||||
bounds = frameTagBounds;
|
||||
|
||||
gfx::Color bg = frameTag->color();
|
||||
if (m_clk.part == PART_FRAME_TAG && m_clk.frameTag == frameTag->id()) {
|
||||
@ -2049,6 +2055,11 @@ void Timeline::drawFrameTags(ui::Graphics* g)
|
||||
gfx::ColorNone,
|
||||
bounds.origin());
|
||||
}
|
||||
|
||||
for (frame_t f=frameTag->fromFrame(); f<=frameTag->toFrame(); ++f) {
|
||||
if (tagsPerFrame[f] < 255)
|
||||
++tagsPerFrame[f];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2335,6 +2346,13 @@ gfx::Rect Timeline::getPartBounds(const Hit& hit) const
|
||||
bounds.x += 3*ui::guiscale();
|
||||
bounds.w = font()->textLength(frameTag->name().c_str()) + 4*ui::guiscale();
|
||||
bounds.h = font()->height() + 2*ui::guiscale();
|
||||
|
||||
auto it = m_tagBand.find(frameTag);
|
||||
if (it != m_tagBand.end()) {
|
||||
int dy = (m_tagBands-it->second-1)*oneTagHeight();
|
||||
bounds.y -= dy;
|
||||
}
|
||||
|
||||
return bounds;
|
||||
}
|
||||
break;
|
||||
@ -2405,9 +2423,46 @@ void Timeline::regenerateLayers()
|
||||
m_layers[i++] = LayerInfo(layer, level, flags);
|
||||
});
|
||||
|
||||
regenerateTagBands();
|
||||
updateScrollBars();
|
||||
}
|
||||
|
||||
void Timeline::regenerateTagBands()
|
||||
{
|
||||
// TODO improve this implementation
|
||||
std::vector<unsigned char> tagsPerFrame(m_sprite->totalFrames(), 0);
|
||||
std::vector<FrameTag*> bands(4, nullptr);
|
||||
m_tagBand.clear();
|
||||
for (FrameTag* frameTag : m_sprite->frameTags()) {
|
||||
frame_t f = frameTag->fromFrame();
|
||||
|
||||
int b=0;
|
||||
for (; b<int(bands.size()); ++b) {
|
||||
if (!bands[b] ||
|
||||
frameTag->fromFrame() > calcTagVisibleToFrame(bands[b])) {
|
||||
bands[b] = frameTag;
|
||||
m_tagBand[frameTag] = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (b == int(bands.size()))
|
||||
m_tagBand[frameTag] = tagsPerFrame[f];
|
||||
|
||||
frame_t toFrame = calcTagVisibleToFrame(frameTag);
|
||||
for (; f<=toFrame; ++f) {
|
||||
if (tagsPerFrame[f] < 255)
|
||||
++tagsPerFrame[f];
|
||||
}
|
||||
}
|
||||
int oldBands = m_tagBands;
|
||||
m_tagBands = 0;
|
||||
for (int i : tagsPerFrame)
|
||||
m_tagBands = MAX(m_tagBands, i);
|
||||
|
||||
if (oldBands != m_tagBands)
|
||||
layout();
|
||||
}
|
||||
|
||||
void Timeline::updateScrollBars()
|
||||
{
|
||||
gfx::Rect rc = bounds();
|
||||
@ -3108,13 +3163,30 @@ int Timeline::outlineWidth() const
|
||||
return skinTheme()->dimensions.timelineOutlineWidth();
|
||||
}
|
||||
|
||||
int Timeline::oneTagHeight() const
|
||||
{
|
||||
return
|
||||
font()->height() +
|
||||
2*ui::guiscale() +
|
||||
skinTheme()->dimensions.timelineTagsAreaHeight();
|
||||
}
|
||||
|
||||
// Returns the last frame where the frame tag (or frame tag label)
|
||||
// is visible in the timeline.
|
||||
int Timeline::calcTagVisibleToFrame(FrameTag* frameTag) const
|
||||
{
|
||||
return
|
||||
MAX(frameTag->toFrame(),
|
||||
frameTag->fromFrame() +
|
||||
font()->textLength(frameTag->name())/frameBoxWidth());
|
||||
}
|
||||
|
||||
int Timeline::topHeight() const
|
||||
{
|
||||
int h = 0;
|
||||
if (m_document && m_sprite) {
|
||||
h += skinTheme()->dimensions.timelineTopBorder();
|
||||
h += font()->height();
|
||||
h += skinTheme()->dimensions.timelineTagsAreaHeight();
|
||||
h += oneTagHeight() * MAX(1, m_tagBands);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
@ -266,6 +266,7 @@ namespace app {
|
||||
gfx::Rect getRangeBounds(const Range& range) const;
|
||||
void invalidateHit(const Hit& hit);
|
||||
void regenerateLayers();
|
||||
void regenerateTagBands();
|
||||
void updateScrollBars();
|
||||
void updateByMousePos(ui::Message* msg, const gfx::Point& mousePos);
|
||||
Hit hitTest(ui::Message* msg, const gfx::Point& mousePos);
|
||||
@ -308,6 +309,8 @@ namespace app {
|
||||
int layerBoxHeight() const;
|
||||
int frameBoxWidth() const;
|
||||
int outlineWidth() const;
|
||||
int oneTagHeight() const;
|
||||
int calcTagVisibleToFrame(FrameTag* frameTag) const;
|
||||
|
||||
void updateCelOverlayBounds(const Hit& hit);
|
||||
void drawCelOverlay(ui::Graphics* g);
|
||||
@ -329,7 +332,14 @@ namespace app {
|
||||
Range m_startRange;
|
||||
Range m_dropRange;
|
||||
State m_state;
|
||||
|
||||
// Data used to display each layer
|
||||
std::vector<LayerInfo> m_layers;
|
||||
|
||||
// Data used to display frame tags
|
||||
int m_tagBands = 0;
|
||||
std::map<FrameTag*, int> m_tagBand;
|
||||
|
||||
int m_separator_x;
|
||||
int m_separator_w;
|
||||
int m_origFrames;
|
||||
|
@ -34,7 +34,9 @@ void FrameTags::add(FrameTag* tag)
|
||||
{
|
||||
auto it = begin(), end = this->end();
|
||||
for (; it != end; ++it) {
|
||||
if ((*it)->fromFrame() > tag->fromFrame())
|
||||
if ((*it)->fromFrame() > tag->fromFrame() ||
|
||||
((*it)->fromFrame() == tag->fromFrame() &&
|
||||
(*it)->toFrame() < tag->toFrame()))
|
||||
break;
|
||||
}
|
||||
m_tags.insert(it, tag);
|
||||
|
Loading…
Reference in New Issue
Block a user