2020-06-28 16:39:18 +00:00
|
|
|
//
|
|
|
|
// SliderComponent.cpp
|
|
|
|
//
|
|
|
|
// Slider to set value in a predefined range.
|
|
|
|
//
|
|
|
|
|
2014-06-20 01:30:09 +00:00
|
|
|
#include "components/SliderComponent.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
|
2014-06-20 01:30:09 +00:00
|
|
|
#include "resources/Font.h"
|
2013-06-19 01:12:30 +00:00
|
|
|
|
2014-03-22 21:55:18 +00:00
|
|
|
#define MOVE_REPEAT_DELAY 500
|
|
|
|
#define MOVE_REPEAT_RATE 40
|
|
|
|
|
2020-06-28 16:39:18 +00:00
|
|
|
SliderComponent::SliderComponent(
|
|
|
|
Window* window,
|
|
|
|
float min,
|
|
|
|
float max,
|
|
|
|
float increment,
|
|
|
|
const std::string& suffix)
|
|
|
|
: GuiComponent(window),
|
|
|
|
mMin(min),
|
|
|
|
mMax(max),
|
|
|
|
mSingleIncrement(increment),
|
|
|
|
mMoveRate(0),
|
|
|
|
mKnob(window),
|
|
|
|
mSuffix(suffix)
|
2013-06-19 01:12:30 +00:00
|
|
|
{
|
2020-06-28 16:39:18 +00:00
|
|
|
assert((min - max) != 0);
|
2013-06-19 01:12:30 +00:00
|
|
|
|
2020-06-28 16:39:18 +00:00
|
|
|
// Some sane default value.
|
|
|
|
mValue = (max + min) / 2;
|
2013-06-19 01:12:30 +00:00
|
|
|
|
2020-06-28 16:39:18 +00:00
|
|
|
mKnob.setOrigin(0.5f, 0.5f);
|
|
|
|
mKnob.setImage(":/graphics/slider_knob.svg");
|
2019-08-25 15:23:02 +00:00
|
|
|
|
2020-06-28 16:39:18 +00:00
|
|
|
setSize(Renderer::getScreenWidth() * 0.15f, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight());
|
2013-06-19 01:12:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool SliderComponent::input(InputConfig* config, Input input)
|
|
|
|
{
|
2020-06-28 16:39:18 +00:00
|
|
|
if (config->isMappedLike("left", input)) {
|
|
|
|
if (input.value)
|
|
|
|
setValue(mValue - mSingleIncrement);
|
|
|
|
|
|
|
|
mMoveRate = input.value ? -mSingleIncrement : 0;
|
|
|
|
mMoveAccumulator = -MOVE_REPEAT_DELAY;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (config->isMappedLike("right", input)) {
|
|
|
|
if (input.value)
|
|
|
|
setValue(mValue + mSingleIncrement);
|
|
|
|
|
|
|
|
mMoveRate = input.value ? mSingleIncrement : 0;
|
|
|
|
mMoveAccumulator = -MOVE_REPEAT_DELAY;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GuiComponent::input(config, input);
|
2013-06-19 01:12:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SliderComponent::update(int deltaTime)
|
|
|
|
{
|
2020-06-28 16:39:18 +00:00
|
|
|
if (mMoveRate != 0) {
|
|
|
|
mMoveAccumulator += deltaTime;
|
|
|
|
while (mMoveAccumulator >= MOVE_REPEAT_RATE) {
|
|
|
|
setValue(mValue + mMoveRate);
|
|
|
|
mMoveAccumulator -= MOVE_REPEAT_RATE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GuiComponent::update(deltaTime);
|
2013-06-19 01:12:30 +00:00
|
|
|
}
|
|
|
|
|
2017-10-28 20:24:35 +00:00
|
|
|
void SliderComponent::render(const Transform4x4f& parentTrans)
|
2013-06-19 01:12:30 +00:00
|
|
|
{
|
2020-06-28 16:39:18 +00:00
|
|
|
Transform4x4f trans = parentTrans * getTransform();
|
|
|
|
Renderer::setMatrix(trans);
|
2013-07-10 11:29:43 +00:00
|
|
|
|
2020-06-28 16:39:18 +00:00
|
|
|
// Render suffix.
|
|
|
|
if (mValueCache)
|
|
|
|
mFont->renderTextCache(mValueCache.get());
|
2014-03-08 00:16:08 +00:00
|
|
|
|
2020-06-28 16:39:18 +00:00
|
|
|
float width = mSize.x() - mKnob.getSize().x() -
|
|
|
|
(mValueCache ? mValueCache->metrics.size.x() + 4 : 0);
|
2014-01-10 22:01:28 +00:00
|
|
|
|
2020-06-28 16:39:18 +00:00
|
|
|
// Render line.
|
|
|
|
const float lineWidth = 2;
|
|
|
|
Renderer::drawRect(mKnob.getSize().x() / 2, mSize.y() / 2 -
|
|
|
|
lineWidth / 2, width, lineWidth, 0x777777FF, 0x777777FF);
|
2013-06-19 01:12:30 +00:00
|
|
|
|
2020-06-28 16:39:18 +00:00
|
|
|
// Render knob.
|
|
|
|
mKnob.render(trans);
|
2019-08-25 15:23:02 +00:00
|
|
|
|
2020-06-28 16:39:18 +00:00
|
|
|
GuiComponent::renderChildren(trans);
|
2013-06-19 01:12:30 +00:00
|
|
|
}
|
2013-06-19 21:02:42 +00:00
|
|
|
|
|
|
|
void SliderComponent::setValue(float value)
|
|
|
|
{
|
2020-06-28 16:39:18 +00:00
|
|
|
mValue = value;
|
|
|
|
if (mValue < mMin)
|
|
|
|
mValue = mMin;
|
|
|
|
else if (mValue > mMax)
|
|
|
|
mValue = mMax;
|
2014-03-22 21:55:18 +00:00
|
|
|
|
2020-06-28 16:39:18 +00:00
|
|
|
onValueChanged();
|
2013-06-19 21:02:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
float SliderComponent::getValue()
|
|
|
|
{
|
2020-06-28 16:39:18 +00:00
|
|
|
return mValue;
|
2013-06-19 21:02:42 +00:00
|
|
|
}
|
2014-01-10 22:01:28 +00:00
|
|
|
|
|
|
|
void SliderComponent::onSizeChanged()
|
|
|
|
{
|
2020-06-28 16:39:18 +00:00
|
|
|
if (!mSuffix.empty())
|
|
|
|
mFont = Font::get((int)(mSize.y()), FONT_PATH_LIGHT);
|
2019-08-25 15:23:02 +00:00
|
|
|
|
2020-06-28 16:39:18 +00:00
|
|
|
onValueChanged();
|
2014-01-10 22:01:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SliderComponent::onValueChanged()
|
|
|
|
{
|
2020-06-28 16:39:18 +00:00
|
|
|
// Update suffix textcache.
|
|
|
|
if (mFont) {
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << std::fixed;
|
|
|
|
ss.precision(0);
|
|
|
|
ss << mValue;
|
|
|
|
ss << mSuffix;
|
|
|
|
const std::string val = ss.str();
|
|
|
|
|
|
|
|
ss.str("");
|
|
|
|
ss.clear();
|
|
|
|
ss << std::fixed;
|
|
|
|
ss.precision(0);
|
|
|
|
ss << mMax;
|
|
|
|
ss << mSuffix;
|
|
|
|
const std::string max = ss.str();
|
|
|
|
|
|
|
|
Vector2f textSize = mFont->sizeText(max);
|
|
|
|
mValueCache = std::shared_ptr<TextCache>(mFont->buildTextCache(val, mSize.x() -
|
|
|
|
textSize.x(), (mSize.y() - textSize.y()) / 2, 0x777777FF));
|
|
|
|
mValueCache->metrics.size[0] = textSize.x(); // Fudge the width.
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update knob position/size.
|
|
|
|
mKnob.setResize(0, mSize.y() * 0.7f);
|
|
|
|
float lineLength = mSize.x() - mKnob.getSize().x() -
|
|
|
|
(mValueCache ? mValueCache->metrics.size.x() + 4 : 0);
|
2020-08-08 10:33:55 +00:00
|
|
|
mKnob.setPosition((mValue / mMax) * lineLength +
|
2020-06-28 16:39:18 +00:00
|
|
|
mKnob.getSize().x()/2, mSize.y() / 2);
|
2014-01-10 22:01:28 +00:00
|
|
|
}
|
2014-01-25 23:34:29 +00:00
|
|
|
|
|
|
|
std::vector<HelpPrompt> SliderComponent::getHelpPrompts()
|
|
|
|
{
|
2020-06-28 16:39:18 +00:00
|
|
|
std::vector<HelpPrompt> prompts;
|
|
|
|
prompts.push_back(HelpPrompt("left/right", "change value"));
|
|
|
|
return prompts;
|
2014-01-25 23:34:29 +00:00
|
|
|
}
|