From 9d62a2f0a1a8d2b8338c612264fd1baa062241fe Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Fri, 21 Aug 2015 22:45:31 -0400 Subject: [PATCH] Buttons: Add CVolumeSlider widget New widget specifically for volume settings. Replace previous implementation using 10 toggle buttons. Enable indicator animation Fix indicator ghosting when drag and releasing Add scroll capability to volume Volume now can be adjusted from 0 - 99 with the mouse or the scroll wheel --- client/CMT.cpp | 2 - client/widgets/Buttons.cpp | 82 ++++++++++++++++++++++++++++++++++++++ client/widgets/Buttons.h | 26 ++++++++++++ 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/client/CMT.cpp b/client/CMT.cpp index edbe184f1..318c60c9d 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -419,8 +419,6 @@ int main(int argc, char** argv) #endif // defined //initializing audio - // Note: because of interface button range, volume can only be a - // multiple of 11, from 0 to 99. CCS->soundh = new CSoundHandler; CCS->soundh->init(); CCS->soundh->setVolume(settings["general"]["sound"].Float()); diff --git a/client/widgets/Buttons.cpp b/client/widgets/Buttons.cpp index 3510ce28f..0fa13fd8d 100644 --- a/client/widgets/Buttons.cpp +++ b/client/widgets/Buttons.cpp @@ -469,6 +469,88 @@ void CToggleGroup::showAll(SDL_Surface * to) CIntObject::showAll(to); } +CVolumeSlider::CVolumeSlider(const Point &position, const std::string &defName, const int value, + const std::pair * const help) : + value(value), + helpHandlers(help) +{ + OBJ_CONSTRUCTION_CAPTURING_ALL; + animImage = new CAnimImage(new CAnimation(defName), 0, 0, position.x, position.y), + assert(!defName.empty()); + addUsedEvents(LCLICK | RCLICK | WHEEL); + pos.x += position.x; + pos.y += position.y; + pos.w = (animImage->pos.w + 1) * animImage->size(); + pos.h = animImage->pos.h; + type |= REDRAW_PARENT; + setVolume(value); +} + +void CVolumeSlider::setVolume(int value_) +{ + value = value_; + moveTo(value * static_cast(animImage->size()) / 100.0); +} + +void CVolumeSlider::moveTo(int id) +{ + vstd::abetween(id, 0, animImage->size() - 1); + animImage->setFrame(id); + animImage->moveTo(Point(pos.x + (animImage->pos.w + 1) * id, pos.y)); + if (active) + redraw(); +} + +void CVolumeSlider::addCallback(std::function callback) +{ + onChange += callback; +} + +void CVolumeSlider::clickLeft(tribool down, bool previousState) +{ + if (down) + { + double px = GH.current->motion.x - pos.x; + double rx = px / static_cast(pos.w); + // setVolume is out of 100 + setVolume(rx * 100); + // Volume config is out of 100, set to increments of 5ish roughly based on the half point of the indicator + // 0.0 -> 0, 0.05 -> 5, 0.09 -> 5,..., + // 0.1 -> 10, ..., 0.19 -> 15, 0.2 -> 20, ..., + // 0.28 -> 25, 0.29 -> 30, 0.3 -> 30, ..., + // 0.85 -> 85, 0.86 -> 90, ..., 0.87 -> 90,..., + // 0.95 -> 95, 0.96 -> 100, 0.99 -> 100 + int volume = 5 * int(rx * (2 * animImage->size() + 1)); + onChange(volume); + } +} + +void CVolumeSlider::clickRight(tribool down, bool previousState) +{ + if (down) + { + double px = GH.current->motion.x - pos.x; + int index = px / static_cast(pos.w) * animImage->size(); + std::string hoverText = helpHandlers[index].first; + std::string helpBox = helpHandlers[index].second; + if(!helpBox.empty()) + CRClickPopup::createAndPush(helpBox); + if(GH.statusbar) + GH.statusbar->setText(helpBox); + } +} + +void CVolumeSlider::wheelScrolled(bool down, bool in) +{ + if (in) + { + int volume = value + 3 * (down ? 1 : -1); + vstd::abetween(volume, 0, 100); + setVolume(volume); + onChange(volume); + } +} + void CSlider::sliderClicked() { if(!(active & MOVE)) diff --git a/client/widgets/Buttons.h b/client/widgets/Buttons.h index e684a192a..78a0d4615 100644 --- a/client/widgets/Buttons.h +++ b/client/widgets/Buttons.h @@ -196,6 +196,32 @@ public: void showAll(SDL_Surface * to); }; +/// A typical slider for volume with an animated indicator +class CVolumeSlider : public CIntObject +{ + int value; + CFunctionList onChange; + CAnimImage * animImage; + const std::pair * const helpHandlers; + void setVolume(const int v); +public: + + /// @param position coordinates of slider + /// @param defName name of def animation for slider + /// @param value initial value for volume + /// @param help pointer to first helptext of slider + CVolumeSlider(const Point &position, const std::string &defName, const int value, + const std::pair * const help); + + void moveTo(int id); + void addCallback(std::function callback); + + + void clickLeft(tribool down, bool previousState) override; + void clickRight(tribool down, bool previousState) override; + void wheelScrolled(bool down, bool in); +}; + /// A typical slider which can be orientated horizontally/vertically. class CSlider : public CIntObject {