Intervals on timeline are now graphically proportional to time:

- intervals are only valid when using key shortcuts
 - using the mouse to select/scroll does not show proper proportions yet
This commit is contained in:
Stephen Anthony 2018-01-28 20:11:21 -03:30
parent 63acb76911
commit b11643881a
5 changed files with 51 additions and 18 deletions

View File

@ -129,6 +129,12 @@ class LinkedObjectPool
*/
const_iter next(const_iter i) const { return std::next(i, 1); }
/**
Canonical iterators from C++ STL.
*/
const_iter cbegin() const { return myList.cbegin(); }
const_iter cend() const { return myList.cend(); }
/**
Answer whether 'current' is at the specified iterator.
*/

View File

@ -344,7 +344,7 @@ IntArray RewindManager::cyclesList() const
IntArray arr;
uInt64 firstCycle = getFirstCycles();
for(auto it = myStateList.first(); it != myStateList.last(); ++it)
for(auto it = myStateList.cbegin(); it != myStateList.cend(); ++it)
arr.push_back(uInt32(it->cycles - firstCycle));
return arr;

View File

@ -25,13 +25,16 @@
#include "TimeLineWidget.hxx"
// TODO - remove all references to _stepValue__
// - fix posToValue to use _stepValue
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TimeLineWidget::TimeLineWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int w, int h,
const string& label, int labelWidth, int cmd)
: ButtonWidget(boss, font, x, y, w, h, label, cmd),
_value(0),
_stepValue(1),
_stepValue__(1),
_valueMin(0),
_valueMax(100),
_isDragging(false),
@ -45,6 +48,8 @@ TimeLineWidget::TimeLineWidget(GuiObject* boss, const GUI::Font& font,
_labelWidth = _font.getStringWidth(_label);
_w = w + _labelWidth;
_stepValue.reserve(100);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -73,13 +78,24 @@ void TimeLineWidget::setMaxValue(int value)
_valueMax = value;
}
#if 0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TimeLineWidget::setStepValue(int value)
void TimeLineWidget::setStepValues(const IntArray& steps)
{
_stepValue = value;
// Try to allocate as infrequently as possible
if(steps.size() > _stepValue.capacity())
_stepValue.reserve(2 * steps.size());
_stepValue.clear();
double scale = (_w - _labelWidth - 4) / double(steps.back());
// Skip the very last value; we take care of it outside the end of the loop
for(uInt32 i = 0; i < steps.size() - 1; ++i)
_stepValue.push_back(int(steps[i] * scale));
// Due to integer <-> double conversion, the last value is sometimes
// slightly less than the maximum value; we assign it manually to fix this
_stepValue.push_back(_w - _labelWidth - 4);
}
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TimeLineWidget::handleMouseMoved(int x, int y)
@ -132,13 +148,13 @@ bool TimeLineWidget::handleEvent(Event::Type e)
case Event::UIDown:
case Event::UILeft:
case Event::UIPgDown:
setValue(_value - _stepValue);
setValue(_value - _stepValue__);
break;
case Event::UIUp:
case Event::UIRight:
case Event::UIPgUp:
setValue(_value + _stepValue);
setValue(_value + _stepValue__);
break;
case Event::UIHome:
@ -196,9 +212,14 @@ int TimeLineWidget::valueToPos(int value)
{
if(value < _valueMin) value = _valueMin;
else if(value > _valueMax) value = _valueMax;
int range = std::max(_valueMax - _valueMin, 1); // don't divide by zero
return ((_w - _labelWidth - 4) * (value - _valueMin) / range);
int real = _stepValue[BSPF::clamp(value, _valueMin, _valueMax)];
#if 0
int range = std::max(_valueMax - _valueMin, 1); // don't divide by zero
int actual = ((_w - _labelWidth - 4) * (value - _valueMin) / range);
cerr << "i=" << value << " real=" << real << endl << "actual=" << actual << endl << endl;
#endif
return real;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -207,5 +228,5 @@ int TimeLineWidget::posToValue(int pos)
int value = (pos) * (_valueMax - _valueMin) / (_w - _labelWidth - 4) + _valueMin;
// Scale the position to the correct interval (according to step value)
return value - (value % _stepValue);
return value - (value % _stepValue__);
}

View File

@ -34,10 +34,12 @@ class TimeLineWidget : public ButtonWidget
int getMinValue() const { return _valueMin; }
void setMaxValue(int value);
int getMaxValue() const { return _valueMax; }
#if 0
void setStepValue(int value);
int getStepValue() const { return _stepValue; }
#endif
/**
Steps are not necessarily linear in a timeline, so we need info
on each interval instead.
*/
void setStepValues(const IntArray& steps);
protected:
void handleMouseMoved(int x, int y) override;
@ -52,11 +54,13 @@ class TimeLineWidget : public ButtonWidget
int posToValue(int pos);
protected:
int _value, _stepValue;
int _value, _stepValue__;
int _valueMin, _valueMax;
bool _isDragging;
int _labelWidth;
IntArray _stepValue;
private:
// Following constructors and assignment operators not supported
TimeLineWidget() = delete;

View File

@ -192,6 +192,7 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent,
tl_y = ypos + (myCurrentIdxWidget->getHeight() - tl_h) / 2,
tl_w = myLastIdxWidget->getAbsX() - tl_x - 8;
myTimeline = new TimeLineWidget(this, font, tl_x, tl_y, tl_w, tl_h, "", 0, kTimeline);
myTimeline->setMinValue(0);
ypos += rowHeight;
// Add time info
@ -252,8 +253,9 @@ void TimeMachineDialog::loadConfig()
RewindManager& r = instance().state().rewindManager();
IntArray cycles = r.cyclesList();
// Set range for timeline
myTimeline->setMaxValue(std::max(Int32(cycles.size()), 1));
// Set range and intervals for timeline
myTimeline->setMaxValue(cycles.size() - 1);
myTimeline->setStepValues(cycles);
// Enable blending (only once is necessary)
if(!surface().attributes().blending)