Implement UISlider (#79)

* Implement UISlider

* Use proper enum type for the left and right arrow key constants
This commit is contained in:
pryon 2023-11-12 17:39:22 +01:00 committed by GitHub
parent 64429232f8
commit 177702d027
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 484 additions and 36 deletions

View file

@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2015-2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@ -21,15 +21,128 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "ui_local.h"
#include <string.h>
Event EV_AutoIncrement
(
"autoinc",
EV_DEFAULT,
NULL,
NULL,
"Used to auto increment the slider"
);
Event EV_AutoDecrement
(
"autodec",
EV_DEFAULT,
NULL,
NULL,
"Used to auto decrement the slider"
);
Event EV_Layout_Range
(
"setrange",
EV_DEFAULT,
"ff",
"min max",
"Used to set the range of a slider"
);
Event EV_Layout_SliderType
(
"slidertype",
EV_DEFAULT,
"s",
"sliderType(float|integer)",
"Set the slider type to be floating point or integral"
);
Event EV_Layout_SliderStep
(
"stepsize",
EV_DEFAULT,
"f",
"stepsize",
"Set the step size of the slider"
);
Event EV_Layout_SliderThumbShader
(
"thumbshader",
EV_DEFAULT,
"sS",
"shader depressed_shader",
"Set the shader of the slider's thumb"
);
Event EV_Layout_SliderLeftShader
(
"leftshader",
EV_DEFAULT,
"sS",
"shader depressed_shader",
"Set the shader of the slider's left arrow"
);
Event EV_Layout_SliderRightShader
(
"rightshader",
EV_DEFAULT,
"sS",
"shader depressed_shader",
"Set the shader of the slider's right arrow"
);
CLASS_DECLARATION( UIWidget, UISlider, NULL )
{
{ NULL, NULL }
{&W_LeftMouseDown, &UISlider::Pressed },
{&W_LeftMouseDragged, &UISlider::MouseDragged },
{&W_LeftMouseUp, &UISlider::Released },
{&W_MouseExited, &UISlider::MouseExited },
{&W_MouseEntered, &UISlider::MouseEntered },
{&EV_AutoIncrement, &UISlider::AutoIncrement },
{&EV_AutoDecrement, &UISlider::AutoDecrement },
{&EV_Layout_Range, &UISlider::LayoutSetRange },
{&EV_Layout_SliderType, &UISlider::LayoutSetType },
{&EV_Layout_SliderStep, &UISlider::LayoutSetStep },
// possible FAKK2 remnants below, not used currently
{&EV_Layout_SliderThumbShader, &UISlider::LayoutSliderThumbShader },
{&EV_Layout_SliderLeftShader, &UISlider::LayoutSliderLeftShader },
{&EV_Layout_SliderRightShader, &UISlider::LayoutSliderRightShader },
{NULL, NULL }
};
UISlider::UISlider()
{
// FIXME: stub
m_sliderregion = {};
m_prev_arrow_region = {};
m_next_arrow_region = {};
m_minvalue = 0.0f;
m_maxvalue = 100.0f;
m_value = 0.0f;
m_oldvalue = 0.0f;
m_sliderwidth = 10.0f;
m_stepsize = 1.0f;
m_slidertype = SLIDER_INTEGER;
m_arrow_width = 15;
m_prev_arrow_depressed = qfalse;
m_next_arrow_depressed = qfalse;
m_thumb_depressed = qfalse;
m_initialized = qfalse;
m_prev_arrow_material = uWinMan.RegisterShader("textures/menu/arrow_left");
m_prev_arrow_material_pressed = uWinMan.RegisterShader("textures/menu/arrow_left_sel");
m_next_arrow_material = uWinMan.RegisterShader("textures/menu/arrow_right");
m_next_arrow_material_pressed = uWinMan.RegisterShader("textures/menu/arrow_right_sel");
m_thumbmaterial = uWinMan.RegisterShader("textures/menu/slider_thumb");
m_thumbmaterial_pressed = uWinMan.RegisterShader("textures/menu/slider_thumb_sel");
// these are not initialized in the original game
m_bar_material = NULL; // seems to be unused
m_maxx = 0;
m_minx = 0;
}
void UISlider::setThumb
@ -38,7 +151,7 @@ void UISlider::setThumb
)
{
// FIXME: stub
// not present in disassembly
}
void UISlider::Pressed
@ -47,7 +160,47 @@ void UISlider::Pressed
)
{
// FIXME: stub
float xpos = ev->GetFloat(1);
float ypos = ev->GetFloat(2);
if (m_prev_arrow_region.contains(xpos, ypos)) // click left arrow
{
Decrement();
m_prev_arrow_depressed = qtrue;
CancelEventsOfType(&EV_AutoDecrement);
Event* newEv = new Event(EV_AutoDecrement);
PostEvent(newEv, 0.2f);
return;
}
else if (m_next_arrow_region.contains(xpos, ypos)) // click right arrow
{
Increment();
m_next_arrow_depressed = qtrue;
CancelEventsOfType(&EV_AutoIncrement);
Event* newEv = new Event(EV_AutoIncrement);
PostEvent(newEv, 0.2f);
return;
}
// click thumb
m_oldvalue = m_value;
m_thumb_depressed = qtrue;
if (xpos <= m_minx)
{
m_value = m_minvalue;
}
else if (xpos >= m_maxx)
{
m_value = m_maxvalue;
}
else
{
// calculate value based on thumb position
m_value = (xpos - m_minx) / (m_maxx - m_minx) * (m_maxvalue - m_minvalue) + m_minvalue;
}
UpdateData();
}
void UISlider::Released
@ -56,7 +209,9 @@ void UISlider::Released
)
{
// FIXME: stub
m_prev_arrow_depressed = qfalse;
m_next_arrow_depressed = qfalse;
m_thumb_depressed = qfalse;
}
void UISlider::Increment
@ -65,7 +220,8 @@ void UISlider::Increment
)
{
// FIXME: stub
m_value = Q_clamp_float(m_value + m_stepsize, m_minvalue, m_maxvalue);
UpdateData();
}
void UISlider::Decrement
@ -74,7 +230,8 @@ void UISlider::Decrement
)
{
// FIXME: stub
m_value = Q_clamp_float(m_value - m_stepsize, m_minvalue, m_maxvalue);
UpdateData();
}
void UISlider::AutoIncrement
@ -83,7 +240,19 @@ void UISlider::AutoIncrement
)
{
// FIXME: stub
if (m_next_arrow_depressed)
{
if (m_next_arrow_region.contains(uid.mouseX, uid.mouseY))
{
Increment();
Event *event = new Event(EV_AutoIncrement);
PostEvent(event, 0.1f);
}
else
{
Released(NULL);
}
}
}
void UISlider::AutoDecrement
@ -92,7 +261,19 @@ void UISlider::AutoDecrement
)
{
// FIXME: stub
if (m_prev_arrow_depressed)
{
if (m_prev_arrow_region.contains(uid.mouseX, uid.mouseY))
{
Decrement();
Event *event = new Event(EV_AutoDecrement);
PostEvent(event, 0.1f);
}
else
{
Released(NULL);
}
}
}
void UISlider::MouseExited
@ -101,7 +282,15 @@ void UISlider::MouseExited
)
{
// FIXME: stub
if (m_thumb_depressed)
{
m_value = m_oldvalue;
UpdateData();
}
m_thumb_depressed = qfalse;
m_prev_arrow_depressed = qfalse;
m_next_arrow_depressed = qfalse;
}
void UISlider::MouseDragged
@ -110,7 +299,34 @@ void UISlider::MouseDragged
)
{
// FIXME: stub
float xpos = ev->GetFloat(1);
float ypos = ev->GetFloat(2);
if (m_thumb_depressed)
{
if (xpos <= m_minx)
{
m_value = m_minvalue;
}
else if (xpos >= m_maxx)
{
m_value = m_maxvalue;
}
else
{
// calculate value based on position
m_value = (xpos - m_minx) / (m_maxx - m_minx) * (m_maxvalue - m_minvalue) + m_minvalue;
}
UpdateData();
return;
}
if ((!m_prev_arrow_depressed && m_prev_arrow_region.contains(xpos, ypos))
|| (!m_next_arrow_depressed && m_next_arrow_region.contains(xpos, ypos)))
{
Pressed(ev);
}
}
void UISlider::MouseEntered
@ -119,7 +335,12 @@ void UISlider::MouseEntered
)
{
// FIXME: stub
int buttons = ev->GetInteger(3);
uWinMan.ActivateControl(this);
if (buttons & 1) // left mouse button
{
Pressed(ev);
}
}
void UISlider::UpdateData
@ -128,7 +349,35 @@ void UISlider::UpdateData
)
{
// FIXME: stub
if (m_cvarname.length())
{
if (m_slidertype == SLIDER_INTEGER)
{
UI_SetCvarInt(m_cvarname, m_value);
}
else
{
UI_SetCvarFloat(m_cvarname, m_value);
}
}
if (m_command.length())
{
char text[32];
if (m_slidertype == SLIDER_INTEGER)
{
Q_snprintf(text, 32, "%d", (int)m_value);
}
else
{
Q_snprintf(text, 32, "%.3f", m_value);
}
m_command.append(' ');
m_command.append(text);
m_command.append('\n');
Cbuf_AddText(m_command);
}
}
void UISlider::UpdateUIElement
@ -137,7 +386,7 @@ void UISlider::UpdateUIElement
)
{
// FIXME: stub
m_value = UI_GetCvarFloat(m_cvarname, 0.0f);
}
void UISlider::LayoutSetRange
@ -146,7 +395,9 @@ void UISlider::LayoutSetRange
)
{
// FIXME: stub
float min = ev->GetFloat(1);
float max = ev->GetFloat(2);
setRange(min, max);
}
void UISlider::LayoutSetType
@ -155,7 +406,15 @@ void UISlider::LayoutSetType
)
{
// FIXME: stub
str type = ev->GetString(1);
if (!Q_stricmp(type, "float"))
{
setType(SLIDER_FLOAT);
}
else if (!Q_stricmp(type, "integer"))
{
setType(SLIDER_INTEGER);
}
}
void UISlider::LayoutSetStep
@ -164,7 +423,7 @@ void UISlider::LayoutSetStep
)
{
// FIXME: stub
m_stepsize = ev->GetFloat(1);
}
void UISlider::LayoutSliderBGShader
@ -173,7 +432,7 @@ void UISlider::LayoutSliderBGShader
)
{
// FIXME: stub
// not present in disassembly
}
void UISlider::LayoutSliderThumbShader
@ -182,7 +441,22 @@ void UISlider::LayoutSliderThumbShader
)
{
// FIXME: stub
str shader = ev->GetString(1);
m_thumbmaterial = uWinMan.RegisterShader(shader);
if (ev->NumArgs() <= 1)
{
m_thumbmaterial_pressed = m_thumbmaterial;
}
else
{
str pressedShader = ev->GetString(2);
m_thumbmaterial_pressed = uWinMan.RegisterShader(pressedShader);
}
m_thumbmaterial->ReregisterMaterial();
m_sliderwidth = uii.Rend_GetShaderWidth(m_thumbmaterial->GetMaterial());
m_initialized = qfalse;
}
void UISlider::LayoutSliderLeftShader
@ -191,7 +465,22 @@ void UISlider::LayoutSliderLeftShader
)
{
// FIXME: stub
str shader = ev->GetString(1);
m_prev_arrow_material = uWinMan.RegisterShader(shader);
if (ev->NumArgs() <= 1)
{
m_prev_arrow_material_pressed = m_prev_arrow_material;
}
else
{
str pressedShader = ev->GetString(2);
m_prev_arrow_material_pressed = uWinMan.RegisterShader(pressedShader);
}
m_prev_arrow_material->ReregisterMaterial();
m_arrow_width = uii.Rend_GetShaderWidth(m_prev_arrow_material->GetMaterial());
m_initialized = qfalse;
}
void UISlider::LayoutSliderRightShader
@ -200,7 +489,22 @@ void UISlider::LayoutSliderRightShader
)
{
// FIXME: stub
str shader = ev->GetString(1);
m_next_arrow_material = uWinMan.RegisterShader(shader);
if (ev->NumArgs() <= 1)
{
m_next_arrow_material_pressed = m_next_arrow_material;
}
else
{
str pressedShader = ev->GetString(2);
m_next_arrow_material_pressed = uWinMan.RegisterShader(pressedShader);
}
m_next_arrow_material->ReregisterMaterial();
m_arrow_width = uii.Rend_GetShaderWidth(m_next_arrow_material->GetMaterial());
m_initialized = qfalse;
}
void UISlider::FrameInitialized
@ -209,7 +513,35 @@ void UISlider::FrameInitialized
)
{
// FIXME: stub
float cframeX = m_clippedframe.pos.x;
float cframeY = m_clippedframe.pos.y;
float cframeWidth = m_clippedframe.size.width;
float frameHeight = m_frame.size.height;
float scaledArrowWidth = m_arrow_width * m_vVirtualScale[0];
float scaledThumbWidth = m_sliderwidth * m_vVirtualScale[0];
m_prev_arrow_region.pos.x = cframeX;
m_prev_arrow_region.pos.y = cframeY;
m_prev_arrow_region.size.height = frameHeight;
m_prev_arrow_region.size.width = scaledArrowWidth;
m_next_arrow_region.pos.x = cframeX + cframeWidth - scaledArrowWidth;
m_next_arrow_region.pos.y = cframeY;
m_next_arrow_region.size.height = frameHeight;
m_next_arrow_region.size.width = scaledArrowWidth;
m_sliderregion.pos.x = cframeX + scaledArrowWidth;
m_sliderregion.pos.y = cframeY;
m_sliderregion.size.height = frameHeight;
// Bug in original game, width calculation was wrong:
//m_sliderregion.size.width = scaledThumbWidth - scaledArrowWidth;
m_sliderregion.size.width = cframeWidth - scaledArrowWidth * 2;
// width of the "dead zone" of the slider where the thumb cannot reach
float unreachableEdgeWidth = scaledArrowWidth + scaledThumbWidth * 0.5f;
m_minx = cframeX + unreachableEdgeWidth;
m_maxx = cframeX + m_frame.size.width - unreachableEdgeWidth;
}
void UISlider::Draw
@ -218,7 +550,110 @@ void UISlider::Draw
)
{
// FIXME: stub
if (!m_initialized)
{
m_initialized = qtrue;
FrameInitialized();
}
UpdateUIElement();
// current horizontal position of the thumb
float sliderpos = (m_value - m_minvalue) / (m_maxvalue - m_minvalue);
sliderpos = Q_clamp_float(sliderpos, 0.0f, 1.0f);
float scaledArrowWidth = m_arrow_width * m_vVirtualScale[0];
float scaledThumbWidth = m_sliderwidth * m_vVirtualScale[0];
float x = (m_maxx - m_minx) * sliderpos + scaledArrowWidth;
// draw the thumb
if (m_thumbmaterial)
{
UIReggedMaterial* material = m_thumb_depressed ? m_thumbmaterial_pressed : m_thumbmaterial;
material->ReregisterMaterial();
uii.Rend_DrawPicStretched(x, 0.0f, scaledThumbWidth, m_frame.size.height, 0.0f, 0.0f, 1.0f, 1.0f, material->GetMaterial());
}
else
{
Draw3DBox(x, 0.0f, scaledThumbWidth, m_frame.size.height, qfalse, m_border_color, m_local_alpha);
}
if (m_prev_arrow_material == m_prev_arrow_material_pressed)
{
Draw3DBox(0.0f, 0.0f, scaledArrowWidth, m_frame.size.height, m_prev_arrow_depressed, m_border_color, m_local_alpha);
m_prev_arrow_material->ReregisterMaterial();
uii.Rend_DrawPicStretched(
2.0f,
2.0f,
scaledArrowWidth - 4.0f,
m_frame.size.height - 4.0f,
0.0f,
0.0f,
1.0f,
1.0f,
m_prev_arrow_material->GetMaterial()
);
}
else
{
uihandle_t material;
if (m_prev_arrow_depressed)
{
m_prev_arrow_material_pressed->ReregisterMaterial();
material = m_prev_arrow_material_pressed->GetMaterial();
}
else
{
m_prev_arrow_material->ReregisterMaterial();
material = m_prev_arrow_material->GetMaterial();
}
uii.Rend_DrawPicStretched(0.0f, 0.0f, scaledArrowWidth, m_frame.size.height, 0.0f, 0.0f, 1.0f, 1.0f, material);
}
if (m_next_arrow_material == m_next_arrow_material_pressed)
{
Draw3DBox(m_frame.size.width - scaledArrowWidth, 0.0f, scaledArrowWidth, m_frame.size.height, m_next_arrow_depressed, m_border_color, m_local_alpha);
m_next_arrow_material->ReregisterMaterial();
uii.Rend_DrawPicStretched(
m_frame.size.width - scaledArrowWidth + 2.0f,
2.0f,
scaledArrowWidth - 4.0f,
m_frame.size.height - 4.0f,
0.0f,
0.0f,
1.0f,
1.0f,
m_next_arrow_material->GetMaterial()
);
}
else
{
uihandle_t material;
if (m_next_arrow_depressed)
{
m_next_arrow_material_pressed->ReregisterMaterial();
material = m_next_arrow_material_pressed->GetMaterial();
}
else
{
m_next_arrow_material->ReregisterMaterial();
material = m_next_arrow_material->GetMaterial();
}
uii.Rend_DrawPicStretched(
m_frame.size.width - scaledArrowWidth,
0.0f,
scaledArrowWidth,
m_frame.size.height,
0.0f,
0.0f,
1.0f,
1.0f,
material
);
}
}
void UISlider::setType
@ -227,7 +662,7 @@ void UISlider::setType
)
{
// FIXME: stub
m_slidertype = type;
}
qboolean UISlider::KeyEvent
@ -237,8 +672,20 @@ qboolean UISlider::KeyEvent
)
{
// FIXME: stub
return qfalse;
if (key == K_RIGHTARROW)
{
Increment();
}
else if (key == K_LEFTARROW)
{
Decrement();
}
else
{
return qfalse;
}
return qtrue;
}
void UISlider::setRange
@ -248,7 +695,8 @@ void UISlider::setRange
)
{
// FIXME: stub
m_minvalue = min;
m_maxvalue = max;
}
void UISlider::setStep
@ -257,6 +705,6 @@ void UISlider::setStep
)
{
// FIXME: stub
m_stepsize = value;
}