259 lines
7.9 KiB
C++
259 lines
7.9 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "ultima/ultima4/views/menu.h"
|
|
#include "ultima/ultima4/views/menuitem.h"
|
|
#include "ultima/ultima4/core/settings.h"
|
|
#include "ultima/ultima4/core/utils.h"
|
|
|
|
namespace Ultima {
|
|
namespace Ultima4 {
|
|
|
|
MenuItem::MenuItem(const Common::String &t, short x, short y, int sc) :
|
|
_id(-1), _x(x), _y(y), _text(t), _highlighted(false),
|
|
_selected(false), _visible(true), _scOffset(sc), _closesMenu(false) {
|
|
// if the sc/scOffset is outside the range of the text string, assert
|
|
assertMsg(sc == -1 || (sc >= 0 && sc <= (int)_text.size()), "sc value of %d out of range!", sc);
|
|
if (sc != -1) addShortcutKey(tolower(_text[sc]));
|
|
}
|
|
|
|
int MenuItem::getId() const {
|
|
return _id;
|
|
}
|
|
short MenuItem::getX() const {
|
|
return _x;
|
|
}
|
|
short MenuItem::getY() const {
|
|
return _y;
|
|
}
|
|
int MenuItem::getScOffset() const {
|
|
return _scOffset;
|
|
}
|
|
Common::String MenuItem::getText() const {
|
|
return _text;
|
|
}
|
|
bool MenuItem::isHighlighted() const {
|
|
return _highlighted;
|
|
}
|
|
bool MenuItem::isSelected() const {
|
|
return _selected;
|
|
}
|
|
bool MenuItem::isVisible() const {
|
|
return _visible;
|
|
}
|
|
bool MenuItem::hasShortcutKey(int sc) const {
|
|
Common::Array<int>::const_iterator begin = _shortcutKeys.begin();
|
|
Common::Array<int>::const_iterator end = _shortcutKeys.end();
|
|
return (Common::find(begin, end, sc) != end);
|
|
}
|
|
bool MenuItem::getClosesMenu() const {
|
|
return _closesMenu;
|
|
}
|
|
|
|
void MenuItem::setId(int i) {
|
|
_id = i;
|
|
}
|
|
|
|
void MenuItem::setX(int x) {
|
|
_x = x;
|
|
}
|
|
|
|
void MenuItem::setY(int y) {
|
|
_y = y;
|
|
}
|
|
|
|
void MenuItem::setText(const Common::String &t) {
|
|
_text = t;
|
|
}
|
|
|
|
void MenuItem::setHighlighted(bool h) {
|
|
_highlighted = h;
|
|
}
|
|
|
|
void MenuItem::setSelected(bool s) {
|
|
_selected = s;
|
|
}
|
|
|
|
void MenuItem::setVisible(bool v) {
|
|
_visible = v;
|
|
}
|
|
|
|
void MenuItem::addShortcutKey(int sc) {
|
|
if (!hasShortcutKey(sc))
|
|
_shortcutKeys.push_back(sc);
|
|
}
|
|
|
|
void MenuItem::setClosesMenu(bool closesMenu) {
|
|
this->_closesMenu = closesMenu;
|
|
}
|
|
|
|
BoolMenuItem::BoolMenuItem(const Common::String &text, short xp, short yp, int shortcutKey, bool *val) :
|
|
MenuItem(text, xp, yp, shortcutKey),
|
|
_val(val),
|
|
_on("On"),
|
|
_off("Off") {
|
|
}
|
|
|
|
BoolMenuItem *BoolMenuItem::setValueStrings(const Common::String &onString, const Common::String &offString) {
|
|
_on = onString;
|
|
_off = offString;
|
|
return this;
|
|
}
|
|
|
|
Common::String BoolMenuItem::getText() const {
|
|
char buffer[64];
|
|
snprintf(buffer, sizeof(buffer), _text.c_str(), *_val ? _on.c_str() : _off.c_str());
|
|
return buffer;
|
|
}
|
|
|
|
void BoolMenuItem::activate(MenuEvent &event) {
|
|
if (event.getType() == MenuEvent::DECREMENT ||
|
|
event.getType() == MenuEvent::INCREMENT ||
|
|
event.getType() == MenuEvent::ACTIVATE)
|
|
*_val = !(*_val);
|
|
}
|
|
|
|
StringMenuItem::StringMenuItem(const Common::String &text, short xp, short yp, int shortcutKey,
|
|
Common::String *val, const Std::vector<Common::String> &validSettings) :
|
|
MenuItem(text, xp, yp, shortcutKey),
|
|
_val(val),
|
|
_validSettings(validSettings) {
|
|
}
|
|
|
|
Common::String StringMenuItem::getText() const {
|
|
char buffer[64];
|
|
snprintf(buffer, sizeof(buffer), _text.c_str(), _val->c_str());
|
|
return buffer;
|
|
}
|
|
|
|
void StringMenuItem::activate(MenuEvent &event) {
|
|
Std::vector<Common::String>::const_iterator current =
|
|
find(_validSettings.begin(), _validSettings.end(), *_val);
|
|
|
|
if (current == _validSettings.end())
|
|
error("Error: menu Common::String '%s' not a valid choice", _val->c_str());
|
|
|
|
if (event.getType() == MenuEvent::INCREMENT || event.getType() == MenuEvent::ACTIVATE) {
|
|
/* move to the next valid choice, wrapping if necessary */
|
|
current++;
|
|
if (current == _validSettings.end())
|
|
current = _validSettings.begin();
|
|
*_val = *current;
|
|
|
|
} else if (event.getType() == MenuEvent::DECREMENT) {
|
|
/* move back one, wrapping if necessary */
|
|
if (current == _validSettings.begin())
|
|
current = _validSettings.end();
|
|
current--;
|
|
*_val = *current;
|
|
}
|
|
}
|
|
|
|
IntMenuItem::IntMenuItem(const Common::String &text, short xp, short yp, int shortcutKey, int *val,
|
|
int min, int max, int increment, menuOutputType output) :
|
|
MenuItem(text, xp, yp, shortcutKey),
|
|
_val(val),
|
|
_min(min),
|
|
_max(max),
|
|
_increment(increment),
|
|
_output(output) {
|
|
}
|
|
|
|
Common::String IntMenuItem::getText() const {
|
|
// do custom formatting for some menu entries,
|
|
// and generate a Common::String of the results
|
|
char outputBuffer[20];
|
|
|
|
switch (_output) {
|
|
case MENU_OUTPUT_REAGENT:
|
|
snprintf(outputBuffer, sizeof(outputBuffer), "%2d", static_cast<short>(*_val));
|
|
break;
|
|
case MENU_OUTPUT_GAMMA:
|
|
snprintf(outputBuffer, sizeof(outputBuffer), "%.1f", static_cast<float>(*_val) / 100);
|
|
break;
|
|
case MENU_OUTPUT_SHRINE:
|
|
/*
|
|
* is this code really necessary? the increments/decrements can be handled by IntMenuItem(),
|
|
* as well as the looping once the max is reached. more importantly, the minimum value is
|
|
* inconstant, and based upon another setting that can be changed independent of this one.
|
|
* This variable could be set to it's minimum value, but when the gameCyclesPerSecond setting
|
|
* is changed, the value of this setting could become out of bounds.
|
|
*
|
|
* settings.shrineTime is only used in one function within shrine.cpp, and that code appears
|
|
* to handle the min value, caping the minimum interval at 1.
|
|
*
|
|
// make sure that the setting we're trying for is even possible
|
|
if (event.getType() == MenuEvent::INCREMENT || event.getType() == MenuEvent::ACTIVATE) {
|
|
settingsChanged.shrineTime++;
|
|
if (settingsChanged.shrineTime > MAX_SHRINE_TIME)
|
|
settingsChanged.shrineTime = MEDITATION_MANTRAS_PER_CYCLE / settingsChanged.gameCyclesPerSecond;
|
|
} else if (event.getType() == MenuEvent::DECREMENT) {
|
|
settingsChanged.shrineTime--;
|
|
if (settingsChanged.shrineTime < (MEDITATION_MANTRAS_PER_CYCLE / settingsChanged.gameCyclesPerSecond))
|
|
settingsChanged.shrineTime = MAX_SHRINE_TIME;
|
|
}
|
|
*
|
|
*/
|
|
snprintf(outputBuffer, sizeof(outputBuffer), "%d sec", *_val);
|
|
break;
|
|
case MENU_OUTPUT_SPELL:
|
|
snprintf(outputBuffer, sizeof(outputBuffer), "%3g sec", static_cast<double>(*_val) / 5);
|
|
break;
|
|
case MENU_OUTPUT_VOLUME:
|
|
if (*_val == 0) {
|
|
snprintf(outputBuffer, sizeof(outputBuffer), "Disabled");
|
|
} else if (*_val == MAX_VOLUME) {
|
|
snprintf(outputBuffer, sizeof(outputBuffer), "Full");
|
|
} else {
|
|
snprintf(outputBuffer, sizeof(outputBuffer), "%d%s%s", *_val * 10, "%", "%");
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// the buffer must contain a field character %d or %s depending
|
|
// on the menuOutputType selected. MENU_OUTPUT_INT always uses
|
|
// %d, whereas all others use %s
|
|
char buffer[64];
|
|
if (_output != MENU_OUTPUT_INT)
|
|
snprintf(buffer, sizeof(buffer), _text.c_str(), outputBuffer);
|
|
else
|
|
snprintf(buffer, sizeof(buffer), _text.c_str(), *_val);
|
|
return buffer;
|
|
}
|
|
|
|
void IntMenuItem::activate(MenuEvent &event) {
|
|
if (event.getType() == MenuEvent::INCREMENT || event.getType() == MenuEvent::ACTIVATE) {
|
|
*_val += _increment;
|
|
if (*_val > _max)
|
|
*_val = _min;
|
|
|
|
} else if (event.getType() == MenuEvent::DECREMENT) {
|
|
*_val -= _increment;
|
|
if (*_val < _min)
|
|
*_val = _max;
|
|
}
|
|
}
|
|
|
|
} // End of namespace Ultima4
|
|
} // End of namespace Ultima
|