mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 13:47:58 +03:00

ReregisterMaterial() must register the material if it was registered before, and GetMaterial() must register the material if it hasn't been registered and return it
700 lines
13 KiB
C++
700 lines
13 KiB
C++
/*
|
|
===========================================================================
|
|
Copyright (C) 2015-2023 the OpenMoHAA team
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
OpenMoHAA source code 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 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
OpenMoHAA source code 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 OpenMoHAA source code; if not, write to the Free Software
|
|
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 )
|
|
{
|
|
{&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()
|
|
{
|
|
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
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
// not present in disassembly
|
|
}
|
|
|
|
void UISlider::Pressed
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
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
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
m_prev_arrow_depressed = qfalse;
|
|
m_next_arrow_depressed = qfalse;
|
|
m_thumb_depressed = qfalse;
|
|
}
|
|
|
|
void UISlider::Increment
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
m_value = Q_clamp_float(m_value + m_stepsize, m_minvalue, m_maxvalue);
|
|
UpdateData();
|
|
}
|
|
|
|
void UISlider::Decrement
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
m_value = Q_clamp_float(m_value - m_stepsize, m_minvalue, m_maxvalue);
|
|
UpdateData();
|
|
}
|
|
|
|
void UISlider::AutoIncrement
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
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
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
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
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
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
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
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
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
int buttons = ev->GetInteger(3);
|
|
uWinMan.ActivateControl(this);
|
|
if (buttons & 1) // left mouse button
|
|
{
|
|
Pressed(ev);
|
|
}
|
|
}
|
|
|
|
void UISlider::UpdateData
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
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
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
m_value = UI_GetCvarFloat(m_cvarname, 0.0f);
|
|
}
|
|
|
|
void UISlider::LayoutSetRange
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
float min = ev->GetFloat(1);
|
|
float max = ev->GetFloat(2);
|
|
setRange(min, max);
|
|
}
|
|
|
|
void UISlider::LayoutSetType
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
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
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
m_stepsize = ev->GetFloat(1);
|
|
}
|
|
|
|
void UISlider::LayoutSliderBGShader
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
// not present in disassembly
|
|
}
|
|
|
|
void UISlider::LayoutSliderThumbShader
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
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_sliderwidth = uii.Rend_GetShaderWidth(m_thumbmaterial->GetMaterial());
|
|
m_initialized = qfalse;
|
|
}
|
|
|
|
void UISlider::LayoutSliderLeftShader
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
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_arrow_width = uii.Rend_GetShaderWidth(m_prev_arrow_material->GetMaterial());
|
|
m_initialized = qfalse;
|
|
}
|
|
|
|
void UISlider::LayoutSliderRightShader
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
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_arrow_width = uii.Rend_GetShaderWidth(m_next_arrow_material->GetMaterial());
|
|
m_initialized = qfalse;
|
|
}
|
|
|
|
void UISlider::FrameInitialized
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
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
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
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;
|
|
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);
|
|
|
|
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)
|
|
{
|
|
material = m_prev_arrow_material_pressed->GetMaterial();
|
|
}
|
|
else
|
|
{
|
|
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);
|
|
|
|
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)
|
|
{
|
|
material = m_next_arrow_material_pressed->GetMaterial();
|
|
}
|
|
else
|
|
{
|
|
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
|
|
(
|
|
slidertype_t type
|
|
)
|
|
|
|
{
|
|
m_slidertype = type;
|
|
}
|
|
|
|
qboolean UISlider::KeyEvent
|
|
(
|
|
int key,
|
|
unsigned int time
|
|
)
|
|
|
|
{
|
|
if (key == K_RIGHTARROW)
|
|
{
|
|
Increment();
|
|
}
|
|
else if (key == K_LEFTARROW)
|
|
{
|
|
Decrement();
|
|
}
|
|
else
|
|
{
|
|
return qfalse;
|
|
}
|
|
|
|
return qtrue;
|
|
}
|
|
|
|
void UISlider::setRange
|
|
(
|
|
float min,
|
|
float max
|
|
)
|
|
|
|
{
|
|
m_minvalue = min;
|
|
m_maxvalue = max;
|
|
}
|
|
|
|
void UISlider::setStep
|
|
(
|
|
float value
|
|
)
|
|
|
|
{
|
|
m_stepsize = value;
|
|
}
|
|
|