mirror of https://github.com/stella-emu/stella.git
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:
parent
63acb76911
commit
b11643881a
|
@ -129,6 +129,12 @@ class LinkedObjectPool
|
||||||
*/
|
*/
|
||||||
const_iter next(const_iter i) const { return std::next(i, 1); }
|
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.
|
Answer whether 'current' is at the specified iterator.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -344,7 +344,7 @@ IntArray RewindManager::cyclesList() const
|
||||||
IntArray arr;
|
IntArray arr;
|
||||||
|
|
||||||
uInt64 firstCycle = getFirstCycles();
|
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));
|
arr.push_back(uInt32(it->cycles - firstCycle));
|
||||||
|
|
||||||
return arr;
|
return arr;
|
||||||
|
|
|
@ -25,13 +25,16 @@
|
||||||
|
|
||||||
#include "TimeLineWidget.hxx"
|
#include "TimeLineWidget.hxx"
|
||||||
|
|
||||||
|
// TODO - remove all references to _stepValue__
|
||||||
|
// - fix posToValue to use _stepValue
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
TimeLineWidget::TimeLineWidget(GuiObject* boss, const GUI::Font& font,
|
TimeLineWidget::TimeLineWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
int x, int y, int w, int h,
|
int x, int y, int w, int h,
|
||||||
const string& label, int labelWidth, int cmd)
|
const string& label, int labelWidth, int cmd)
|
||||||
: ButtonWidget(boss, font, x, y, w, h, label, cmd),
|
: ButtonWidget(boss, font, x, y, w, h, label, cmd),
|
||||||
_value(0),
|
_value(0),
|
||||||
_stepValue(1),
|
_stepValue__(1),
|
||||||
_valueMin(0),
|
_valueMin(0),
|
||||||
_valueMax(100),
|
_valueMax(100),
|
||||||
_isDragging(false),
|
_isDragging(false),
|
||||||
|
@ -45,6 +48,8 @@ TimeLineWidget::TimeLineWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
_labelWidth = _font.getStringWidth(_label);
|
_labelWidth = _font.getStringWidth(_label);
|
||||||
|
|
||||||
_w = w + _labelWidth;
|
_w = w + _labelWidth;
|
||||||
|
|
||||||
|
_stepValue.reserve(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -73,13 +78,24 @@ void TimeLineWidget::setMaxValue(int value)
|
||||||
_valueMax = 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)
|
void TimeLineWidget::handleMouseMoved(int x, int y)
|
||||||
|
@ -132,13 +148,13 @@ bool TimeLineWidget::handleEvent(Event::Type e)
|
||||||
case Event::UIDown:
|
case Event::UIDown:
|
||||||
case Event::UILeft:
|
case Event::UILeft:
|
||||||
case Event::UIPgDown:
|
case Event::UIPgDown:
|
||||||
setValue(_value - _stepValue);
|
setValue(_value - _stepValue__);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::UIUp:
|
case Event::UIUp:
|
||||||
case Event::UIRight:
|
case Event::UIRight:
|
||||||
case Event::UIPgUp:
|
case Event::UIPgUp:
|
||||||
setValue(_value + _stepValue);
|
setValue(_value + _stepValue__);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::UIHome:
|
case Event::UIHome:
|
||||||
|
@ -196,9 +212,14 @@ int TimeLineWidget::valueToPos(int value)
|
||||||
{
|
{
|
||||||
if(value < _valueMin) value = _valueMin;
|
if(value < _valueMin) value = _valueMin;
|
||||||
else if(value > _valueMax) value = _valueMax;
|
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;
|
int value = (pos) * (_valueMax - _valueMin) / (_w - _labelWidth - 4) + _valueMin;
|
||||||
|
|
||||||
// Scale the position to the correct interval (according to step value)
|
// Scale the position to the correct interval (according to step value)
|
||||||
return value - (value % _stepValue);
|
return value - (value % _stepValue__);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,12 @@ class TimeLineWidget : public ButtonWidget
|
||||||
int getMinValue() const { return _valueMin; }
|
int getMinValue() const { return _valueMin; }
|
||||||
void setMaxValue(int value);
|
void setMaxValue(int value);
|
||||||
int getMaxValue() const { return _valueMax; }
|
int getMaxValue() const { return _valueMax; }
|
||||||
#if 0
|
|
||||||
void setStepValue(int value);
|
/**
|
||||||
int getStepValue() const { return _stepValue; }
|
Steps are not necessarily linear in a timeline, so we need info
|
||||||
#endif
|
on each interval instead.
|
||||||
|
*/
|
||||||
|
void setStepValues(const IntArray& steps);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void handleMouseMoved(int x, int y) override;
|
void handleMouseMoved(int x, int y) override;
|
||||||
|
@ -52,11 +54,13 @@ class TimeLineWidget : public ButtonWidget
|
||||||
int posToValue(int pos);
|
int posToValue(int pos);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int _value, _stepValue;
|
int _value, _stepValue__;
|
||||||
int _valueMin, _valueMax;
|
int _valueMin, _valueMax;
|
||||||
bool _isDragging;
|
bool _isDragging;
|
||||||
int _labelWidth;
|
int _labelWidth;
|
||||||
|
|
||||||
|
IntArray _stepValue;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
TimeLineWidget() = delete;
|
TimeLineWidget() = delete;
|
||||||
|
|
|
@ -192,6 +192,7 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent,
|
||||||
tl_y = ypos + (myCurrentIdxWidget->getHeight() - tl_h) / 2,
|
tl_y = ypos + (myCurrentIdxWidget->getHeight() - tl_h) / 2,
|
||||||
tl_w = myLastIdxWidget->getAbsX() - tl_x - 8;
|
tl_w = myLastIdxWidget->getAbsX() - tl_x - 8;
|
||||||
myTimeline = new TimeLineWidget(this, font, tl_x, tl_y, tl_w, tl_h, "", 0, kTimeline);
|
myTimeline = new TimeLineWidget(this, font, tl_x, tl_y, tl_w, tl_h, "", 0, kTimeline);
|
||||||
|
myTimeline->setMinValue(0);
|
||||||
ypos += rowHeight;
|
ypos += rowHeight;
|
||||||
|
|
||||||
// Add time info
|
// Add time info
|
||||||
|
@ -252,8 +253,9 @@ void TimeMachineDialog::loadConfig()
|
||||||
RewindManager& r = instance().state().rewindManager();
|
RewindManager& r = instance().state().rewindManager();
|
||||||
IntArray cycles = r.cyclesList();
|
IntArray cycles = r.cyclesList();
|
||||||
|
|
||||||
// Set range for timeline
|
// Set range and intervals for timeline
|
||||||
myTimeline->setMaxValue(std::max(Int32(cycles.size()), 1));
|
myTimeline->setMaxValue(cycles.size() - 1);
|
||||||
|
myTimeline->setStepValues(cycles);
|
||||||
|
|
||||||
// Enable blending (only once is necessary)
|
// Enable blending (only once is necessary)
|
||||||
if(!surface().attributes().blending)
|
if(!surface().attributes().blending)
|
||||||
|
|
Loading…
Reference in New Issue