got sick with my own gauge implementation using an irrlicht scrollbar(irrlicht has no gauge widget) - it had all kinds of weird side effects. I rewrote it using my Spinner widget instead. Some functionnality is lost but at least it's pretty much bug-free

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3461 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2009-05-04 01:15:12 +00:00
parent 5f96bcf478
commit 911f98fcca
8 changed files with 75 additions and 131 deletions

View File

@ -21,7 +21,7 @@
</div>
<div width="75%" height="30" layout="horizontal-row" >
<spacer proportion="1" height="100%"/>
<gauge id="music_volume" proportion="1" height="100%"/>
<gauge id="music_volume" proportion="1" height="100%" min_value="0" max_value="10"/>
</div>
<spacer height="15" width="10"/>
@ -34,7 +34,7 @@
</div>
<div width="75%" height="30" layout="horizontal-row" >
<spacer proportion="1" height="100%"/>
<gauge id="sfx_volume" proportion="1" height="100%"/>
<gauge id="sfx_volume" proportion="1" height="100%" min_value="0" max_value="10"/>
</div>

View File

@ -19,19 +19,17 @@ Ribbon widgets are of spawn type (<ribbon> ... </ribbon>) and may contain icon-b
Property PROP_SQUARE can be set to tell the engine if the ribbon's contents are rectangular or not (this will
affect the type of highlighting used)
WTYPE_SPINNER "spinner"
WTYPE_SPINNER "spinner", "gauge"
A spinner component (lets you choose numbers). Sprecify PROP_MIN_VALUE and PROP_MAX_VALUE to have control
over values (default will be from 0 to 10). You can specify an icon; then, include a sprintf format string
like %i in the name, and at runtime the current number will be inserted into the given name to find the
right file for each possible value the spinner can take. It may also display arbitrary text instead of
numbers, though this cannot be achieve in the XML file; use the ->addLabel(...) method in code to do this.
The "gauge" variant behaves similarly, but a fill band shows how close to the max the value is.
WTYPE_BUTTON "button"
A plain text buttons.
WTYPE_GAUGE "gauge"
A control that lets users choose a value between a maximal and a minimal value, with a graphical filling bar.
WTYPE_ICON_BUTTON "icon-button", "icon"
A component with an image, and optional text to go under it. The "icon" variant will have no border and will not
be clickable. PROP_ICON is mandatory for this component.

View File

@ -72,8 +72,10 @@ void parseScreenFileDiv(irr::io::IrrXMLReader* xml, ptr_vector<Widget>& append_t
}
else if (!strcmp("gauge", xml->getNodeName()))
{
type = WTYPE_GAUGE;
append_to.push_back(new GaugeWidget());
//type = WTYPE_GAUGE;
//append_to.push_back(new GaugeWidget());
type = WTYPE_SPINNER;
append_to.push_back(new SpinnerWidget(true));
}
else if (!strcmp("icon-button", xml->getNodeName()))
{

View File

@ -532,12 +532,37 @@ void Skin::drawSpinnerBody(const core::rect< s32 > &rect, const Widget* widget,
params.hborder_out_portion = 0.0f;
drawBoxFromStretchableTexture(rect, (focused || pressed ? m_tex_fspinner : m_tex_spinner), params);
const SpinnerWidget* w = dynamic_cast<const SpinnerWidget*>(widget);
if( w->isGauge() )
{
// the width of an handle is about 0.84 the height in the current skin. FIXME - don't hardcode.
const int handle_size = (int)( widget->h*0.84f );
const float value = (float)(w->getValue() - w->getMin()) / (w->getMax() - w->getMin());
const core::rect< s32 > dest_area = core::rect< s32 >(widget->x + handle_size,
widget->y,
widget->x + handle_size + (int)((widget->w - 2*handle_size)*value),
widget->y + widget->h);
const int texture_w = m_tex_gaugefill->getSize().Width;
const int texture_h = m_tex_gaugefill->getSize().Height;
const core::rect< s32 > source_area = core::rect< s32 >(0, 0, texture_w, texture_h);
GUIEngine::getDriver()->draw2DImage(m_tex_gaugefill, dest_area, source_area,
0 /* no clipping */, 0, true /* alpha */);
}
}
void Skin::drawSpinnerChild(const core::rect< s32 > &rect, Widget* widget, const bool pressed, bool focused)
{
if(pressed)
{
Widget* spinner = widget->m_event_handler;
@ -550,8 +575,8 @@ void Skin::drawSpinnerChild(const core::rect< s32 > &rect, Widget* widget, const
else return;
core::rect< s32 > rect2 = core::rect< s32 >( spinner->x, spinner->y,
spinner->x + spinner->w,
spinner->y + spinner->h );
spinner->x + spinner->w,
spinner->y + spinner->h );
static BoxRenderParams params;
// FIXME - move these numbers to a config file
@ -570,48 +595,6 @@ void Skin::drawSpinnerChild(const core::rect< s32 > &rect, Widget* widget, const
}
void Skin::drawGauge(const core::rect< s32 > &rect, Widget* widget, bool focused)
{
static BoxRenderParams params;
// FIXME - move these numbers to a config file
params.left_border = 110;
params.right_border = 110;
params.top_border = 0;
params.bottom_border = 36;
params.hborder_out_portion = -0.9;
drawBoxFromStretchableTexture(rect, (focused ? m_tex_fspinner : m_tex_spinner), params);
}
void Skin::drawGaugeFill(const core::rect< s32 > &rect, Widget* widget, bool focused)
{
// FIXME - move these numbers to a config file
const int left_border = 110;
//const int right_border = 110;
//const int border_above = 0;
//const int border_below = 36;
GaugeWidget* w = dynamic_cast<GaugeWidget*>(widget);
// the width of an handle is about 0.844 the height in the current skin. FIXME - don't hardcode.
const int handle_size = (int)(widget->h*0.844f) + left_border*0.2;
// the 'rect' argument will be too small, because irrlicht has no suitable gauge component, so i used a scrollbar
const core::rect< s32 > dest_area = core::rect< s32 >(widget->x+handle_size, widget->y,
widget->x + handle_size + (int)((widget->w - 2*handle_size)*w->getValue()),
widget->y + widget->h);
const int texture_w = m_tex_gaugefill->getSize().Width;
const int texture_h = m_tex_gaugefill->getSize().Height;
const core::rect< s32 > source_area = core::rect< s32 >(0, 0, texture_w, texture_h);
GUIEngine::getDriver()->draw2DImage(m_tex_gaugefill, dest_area, source_area,
0 /* no clipping */, 0, true /* alpha */);
}
void Skin::drawCheckBox(const core::rect< s32 > &rect, Widget* widget, bool focused)
{
CheckBoxWidget* w = dynamic_cast<CheckBoxWidget*>(widget);
@ -695,22 +678,15 @@ void Skin::draw2DRectangle (IGUIElement *element, const video::SColor &color, co
{
if(StateManager::isGameState()) return; // ignore in game mode
const bool focused = GUIEngine::getGUIEnv()->hasFocus(element);
//const bool focused = GUIEngine::getGUIEnv()->hasFocus(element);
const int id = element->getID();
Widget* widget = GUIEngine::getCurrentScreen()->getWidget(id);
if(widget == NULL) return;
const WidgetType type = widget->m_type;
// const WidgetType type = widget->m_type;
if(type == WTYPE_GAUGE)
{
drawGauge(rect, widget, focused);
}
//printf("draw rectangle\n");
// GUIEngine::getDriver()->draw2DRectangle( SColor(255, 0, 150, 150), pos );
}
void Skin::process3DPane(IGUIElement *element, const core::rect< s32 > &rect, const bool pressed)
{
@ -754,11 +730,6 @@ void Skin::process3DPane(IGUIElement *element, const core::rect< s32 > &rect, co
{
drawSpinnerBody(rect, widget, pressed, focused);
}
else if(type == WTYPE_GAUGE)
{
if(!pressed)
drawGaugeFill(rect, widget, focused);
}
else if(type == WTYPE_CHECKBOX)
{
drawCheckBox(rect, widget, focused);

View File

@ -54,16 +54,12 @@ namespace GUIEngine
ITexture* m_tex_bubble;
ITexture* m_tex_squarefocus;
ITexture* m_tex_gaugefill;
ITexture* m_tex_gauge;
ITexture* m_tex_checkbox;
ITexture* m_tex_fcheckbox;
ITexture* m_tex_dcheckbox;
ITexture* m_tex_dfcheckbox;
void drawBoxFromStretchableTexture(const core::rect< s32 > &dest, ITexture* source, const BoxRenderParams& params);
public:

View File

@ -277,31 +277,35 @@ namespace StateManager
else if(screen_name == "options_input.stkgui") ribbon->select( "controls" );
}
// init audio-video sub-screen
// ---- init audio-video sub-screen
if(screen_name == "options_av.stkgui")
{
GUIEngine::GaugeWidget* gauge = dynamic_cast<GUIEngine::GaugeWidget*>
(GUIEngine::getCurrentScreen()->getWidget("sfx_volume"));
// ---- sfx volume
GUIEngine::SpinnerWidget* gauge = dynamic_cast<GUIEngine::SpinnerWidget*>
(GUIEngine::getCurrentScreen()->getWidget("sfx_volume"));
assert(gauge != NULL);
gauge->setValue( sfx_manager->getMasterSFXVolume() );
gauge->setValue( sfx_manager->getMasterSFXVolume()*10.0f );
gauge = dynamic_cast<GUIEngine::GaugeWidget*>
(GUIEngine::getCurrentScreen()->getWidget("music_volume"));
gauge = dynamic_cast<GUIEngine::SpinnerWidget*>
(GUIEngine::getCurrentScreen()->getWidget("music_volume"));
assert(gauge != NULL);
gauge->setValue( sound_manager->getMasterMusicVolume() );
gauge->setValue( sound_manager->getMasterMusicVolume()*10.f );
// ---- music volume
GUIEngine::CheckBoxWidget* sfx = dynamic_cast<GUIEngine::CheckBoxWidget*>
(GUIEngine::getCurrentScreen()->getWidget("sfx_enabled"));
GUIEngine::CheckBoxWidget* music = dynamic_cast<GUIEngine::CheckBoxWidget*>
(GUIEngine::getCurrentScreen()->getWidget("music_enabled"));
// ---- audio enables/disables
sfx->setState( user_config->doSFX() );
music->setState( user_config->doMusic() );
// ---- resolutinos
{
GUIEngine::RibbonGridWidget* res = dynamic_cast<GUIEngine::RibbonGridWidget*>
(GUIEngine::getCurrentScreen()->getWidget("resolutions"));
@ -365,25 +369,31 @@ namespace StateManager
}
else if(name == "music_volume")
{
/*
GUIEngine::GaugeWidget* w = dynamic_cast<GUIEngine::GaugeWidget*>(widget);
assert(w != NULL);
sound_manager->setMasterMusicVolume( w->getValue() );
*/
GUIEngine::SpinnerWidget* w = dynamic_cast<GUIEngine::SpinnerWidget*>(widget);
assert(w != NULL);
sound_manager->setMasterMusicVolume( w->getValue()/10.0f );
}
else if(name == "sfx_volume")
{
static SFXBase* sample_sound = NULL;
GUIEngine::GaugeWidget* w = dynamic_cast<GUIEngine::GaugeWidget*>(widget);
// GUIEngine::getCurrentScreen()->getWidget("sfx_volume")
GUIEngine::SpinnerWidget* w = dynamic_cast<GUIEngine::SpinnerWidget*>(widget);
assert(w != NULL);
if(sample_sound == NULL)
sample_sound = sfx_manager->newSFX( SFXManager::SOUND_SKID );
sample_sound->volume(1);
sfx_manager->setMasterSFXVolume( w->getValue() );
user_config->m_sfx_volume = w->getValue();
sfx_manager->setMasterSFXVolume( w->getValue()/10.0f );
user_config->m_sfx_volume = w->getValue()/10.0f;
// std::cout << "w->getValue()=" << w->getValue() << std::endl;
// play a sample sound to show the user what this volume is like

View File

@ -287,42 +287,6 @@ bool CheckBoxWidget::transmitEvent(Widget* w, std::string& originator)
return true;
}
#if 0
#pragma mark -
#pragma mark Gauge Widget
#endif
// -----------------------------------------------------------------------------
void GaugeWidget::add()
{
rect<s32> widget_size = rect<s32>(x, y, x + w, y + h);
IGUIScrollBar* sb = GUIEngine::getGUIEnv()->addScrollBar(true /* horizontal */, widget_size, NULL, ++id_counter);
sb->setMax(100);
sb->setSmallStep(10);
sb->setLargeStep(10);
m_element = sb;
id = m_element->getID();
m_element->setTabOrder(id);
m_element->setTabGroup(false);
}
// -----------------------------------------------------------------------------
float GaugeWidget::getValue()
{
IGUIScrollBar* sb = dynamic_cast<IGUIScrollBar*>(m_element);
assert(sb != NULL);
return (float)sb->getPos() / sb->getMax();
}
// -----------------------------------------------------------------------------
void GaugeWidget::setValue(const float val)
{
IGUIScrollBar* sb = dynamic_cast<IGUIScrollBar*>(m_element);
assert(sb != NULL);
sb->setPos( (int)round(sb->getMax()*val) );
}
#if 0
#pragma mark -
#pragma mark Icon Button
@ -697,6 +661,11 @@ void RibbonWidget::setLabel(const int id, std::string new_name)
#pragma mark Spinner
#endif
SpinnerWidget::SpinnerWidget(const bool gauge)
{
m_gauge = gauge;
}
void SpinnerWidget::add()
{
// retrieve min and max values

View File

@ -17,7 +17,6 @@ namespace GUIEngine
WTYPE_RIBBON,
WTYPE_SPINNER,
WTYPE_BUTTON,
WTYPE_GAUGE,
WTYPE_ICON_BUTTON,
WTYPE_CHECKBOX,
WTYPE_LABEL,
@ -174,30 +173,29 @@ namespace GUIEngine
void setState(const bool enabled) { m_state = enabled; }
};
class GaugeWidget : public Widget
{
void add();
public:
virtual ~GaugeWidget() {}
float getValue();
void setValue(const float value);
};
class SpinnerWidget : public Widget
{
int m_value, m_min, m_max;
std::vector<std::string> m_labels;
bool m_graphical;
bool m_gauge;
bool transmitEvent(Widget* w, std::string& originator);
bool rightPressed();
bool leftPressed();
void add();
public:
SpinnerWidget(const bool gauge=false);
virtual ~SpinnerWidget() {}
void setValue(const int new_value);
void addLabel(std::string label);
bool isGauge() const { return m_gauge; }
int getValue() const { return m_value; }
int getMax() const { return m_max; }
int getMin() const { return m_min; }
};
class IconButtonWidget : public Widget