openmohaa/code/uilib/uilabel.cpp
smallmodel 6fe1e86b31
Automatically scale UI elements for high resolutions
This fixes UI elements being tiny on high resolutions like 4K. Now most UI elements will scale automatically with resolutions above 1920x1080.
2024-11-30 22:40:00 +01:00

427 lines
11 KiB
C++

/*
===========================================================================
Copyright (C) 2015 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 "../qcommon/localization.h"
Event EV_UILabel_LinkString
(
"linkstring",
EV_DEFAULT,
"is",
"value string",
"Creates a link from the specified value to a string. "
"Use this if you want the label to display a string different from the value of the cvar"
);
Event EV_UILabel_LinkCvarToShader
(
"linkcvartoshader",
EV_DEFAULT,
NULL,
NULL,
"Links the label's cvar to its shader"
);
// Added in 2.0
//====
Event EV_UILabel_OneShotSound
(
"oneshotsound",
EV_DEFAULT,
"sf",
"soundName soundTime",
"Set the sound to play"
);
Event EV_UILabel_LoopingSound
(
"loopingsound",
EV_DEFAULT,
"sffff",
"soundName start_volume hold_start_time ending_volume ramp_time",
"Set the sound to play"
);
Event EV_UILabel_OutlinedText
(
"outlinedtext",
EV_DEFAULT,
"i",
"outlined",
"Set/clear outline text"
);
//====
static const char *localizableVars[] = {
"cl_langamerefreshstatus",
"ui_timemessage",
"cg_obj_axistext1",
"cg_obj_axistext2",
"cg_obj_axistext3",
"cg_obj_axistext4",
"cg_obj_axistext5"
"cg_obj_alliedtext1",
"cg_obj_alliedtext2",
"cg_obj_alliedtext3",
"cg_obj_alliedtext4",
"cg_obj_alliedtext5",
"g_gametypestring",
"dm_serverstatus",
"com_errormessage",
NULL};
CLASS_DECLARATION(UIWidget, UILabel, NULL) {
{&W_MouseEntered, &UILabel::MouseEntered },
{&W_MouseExited, &UILabel::MouseExited },
{&EV_UILabel_LinkString, &UILabel::LinkString },
{&EV_UILabel_LinkCvarToShader, &UILabel::SetLinkCvarToShader },
{&EV_UILabel_OneShotSound, &UILabel::OneShotSound },
{&EV_UILabel_LoopingSound, &UILabel::LoopingSound },
{&EV_Layout_Shader, &UILabel::LabelLayoutShader },
{&EV_Layout_TileShader, &UILabel::LabelLayoutTileShader},
{&EV_UILabel_OutlinedText, &UILabel::EventSetOutlinedText },
{NULL, NULL }
};
UILabel::UILabel()
{
AllowActivate(false);
m_bLinkCvarToShader = false;
m_bOneShotTriggered = false;
m_iNextOneShotTime = 0;
m_iNextStateTime = 0;
m_iLastDrawTime = 0;
m_bOutlinedText = false;
}
void UILabel::MouseEntered(Event *ev)
{
SetHovermaterialActive(true);
}
void UILabel::MouseExited(Event *ev)
{
SetHovermaterialActive(false);
SetPressedmaterialActive(false);
}
void UILabel::LinkString(Event *ev)
{
linkstring *ls;
str value;
str string;
value = ev->GetString(1);
string = ev->GetString(2);
ls = new linkstring(value, string);
m_linkstrings.AddObject(ls);
}
void UILabel::SetLabel(str lab)
{
label = lab;
}
int UILabel::FindLinkString(str val)
{
int i;
for (i = 1; i <= m_linkstrings.NumObjects(); i++) {
if (val == m_linkstrings.ObjectAt(i)->value) {
return i;
}
}
return 0;
}
void UILabel::LabelLayoutShader(Event *ev)
{
m_sCurrentShaderName = ev->GetString(1);
setMaterial(uWinMan.RegisterShader(m_sCurrentShaderName));
m_flags &= ~WF_TILESHADER;
}
void UILabel::LabelLayoutTileShader(Event *ev)
{
m_sCurrentShaderName = ev->GetString(1);
if (m_sCurrentShaderName.length() > 1) {
setMaterial(uWinMan.RegisterShader(m_sCurrentShaderName));
} else {
// Added in 2.0
// Don't set the material if the shader name is considered empty
m_sCurrentShaderName = "";
}
m_flags |= WF_TILESHADER;
}
void UILabel::SetLinkCvarToShader(Event *ev)
{
m_bLinkCvarToShader = true;
}
void UILabel::OneShotSound(Event *ev)
{
m_sOneShotSoundName = ev->GetString(1);
m_fOneShotSoundTime = ev->GetFloat(2);
}
void UILabel::LoopingSound(Event *ev)
{
m_sLoopingSoundName = ev->GetString(1);
switch (ev->NumArgs()) {
case 1:
m_fLoopingSoundHoldStartTime = 0.0;
m_fLoopingSoundStartVolume = 1.0;
m_fLoopingSoundEndVolume = 1.0;
m_fLoopingSoundRampTime = 0.0;
break;
case 2:
case 3:
m_fLoopingSoundStartVolume = ev->GetFloat(2);
m_fLoopingSoundHoldStartTime = 0.0;
m_fLoopingSoundEndVolume = ev->GetFloat(2);
m_fLoopingSoundRampTime = 0.0;
break;
case 4:
m_fLoopingSoundStartVolume = ev->GetFloat(2);
m_fLoopingSoundHoldStartTime = ev->GetFloat(3);
m_fLoopingSoundEndVolume = ev->GetFloat(4);
m_fLoopingSoundRampTime = 4.0;
break;
case 5:
m_fLoopingSoundStartVolume = ev->GetFloat(2);
m_fLoopingSoundHoldStartTime = ev->GetFloat(3);
m_fLoopingSoundEndVolume = ev->GetFloat(4);
m_fLoopingSoundRampTime = ev->GetFloat(5);
break;
default:
break;
}
}
void UILabel::EventSetOutlinedText(Event *ev)
{
if (ev->NumArgs() > 0) {
m_bOutlinedText = ev->GetInteger(1) ? true : false;
} else {
m_bOutlinedText = true;
}
}
void UILabel::Draw(void)
{
const char *string;
str val;
ProcessSounds();
m_iLastDrawTime = uii.Sys_Milliseconds();
if (m_cvarname.length()) {
string = uii.Cvar_GetString(m_cvarname, "");
//
// localize the cvar value when possible
//
for (int i = 0; localizableVars[i]; i++) {
if (!strcmp(localizableVars[i], string)) {
string = Sys_LV_CL_ConvertString(localizableVars[i]);
}
}
if (m_linkstrings.NumObjects()) {
cvar_t *cvar = UI_FindCvar(m_cvarname);
if (cvar) {
int ret;
if (cvar->latchedString) {
val = cvar->latchedString;
} else {
val = cvar->string;
}
ret = FindLinkString(val);
if (ret) {
string = m_linkstrings.ObjectAt(ret)->string;
}
}
}
if (m_bLinkCvarToShader) {
if (str::icmp(m_sCurrentShaderName, string)) {
m_sCurrentShaderName = string;
setMaterial(uWinMan.RegisterShader(m_sCurrentShaderName));
if (!m_material->GetMaterial()) {
setMaterial(NULL);
}
}
if (label.length()) {
string = label;
} else if (m_title.length()) {
string = m_title;
} else {
string = "";
}
}
} else {
if (label.length()) {
string = label;
} else if (m_title.length()) {
string = m_title;
} else {
string = "";
}
}
if (*string) {
float nr, ng, nb;
float alpha;
nr = m_foreground_color.r;
ng = m_foreground_color.g;
nb = m_foreground_color.b;
m_font->setColor(UColor(nr, ng, nb, m_foreground_color.a * m_local_alpha));
if (m_bOutlinedText) {
// print the text
m_font->PrintOutlinedJustified(
getClientFrame(),
m_iFontAlignmentHorizontal,
m_iFontAlignmentVertical,
string,
UBlack,
getVirtualScale()
);
} else {
// print the text
m_font->PrintJustified(
getClientFrame(),
m_iFontAlignmentHorizontal,
m_iFontAlignmentVertical,
string,
getVirtualScale()
);
}
}
}
void UILabel::FrameInitialized()
{
if (m_sOneShotSoundName.length() || m_sLoopingSoundName.length()) {
uii.Cmd_Stuff("tmstop\n");
m_bOneShotTriggered = false;
m_iNextOneShotTime = uii.Sys_Milliseconds() + 2000;
m_iNextStateTime = 0;
}
m_iLastDrawTime = 0;
UIWidget::FrameInitialized();
}
void UILabel::ProcessSounds()
{
char buffer[64];
float frac;
if (paused->integer) {
if (m_iNextOneShotTime) {
m_iNextOneShotTime += uii.Sys_Milliseconds() - m_iLastDrawTime;
}
if (m_iNextStateTime) {
m_iNextStateTime += uii.Sys_Milliseconds() - m_iLastDrawTime;
}
}
if (m_iNextOneShotTime && uii.Sys_Milliseconds() > m_iNextOneShotTime) {
if (m_sOneShotSoundName.length() && !m_bOneShotTriggered) {
//
// use the looping sound if the oneshot sound was triggered is non-existent
//
uii.Snd_StopAllSound();
uii.Snd_FadeSound(0);
uii.Snd_PlaySoundDialog(m_sOneShotSoundName);
m_bOneShotTriggered = true;
m_iNextOneShotTime = Sys_Milliseconds() + m_fOneShotSoundTime * 1000.0f;
} else if (m_sLoopingSoundName.length()) {
uii.Cmd_Stuff("tmstartloop " + m_sLoopingSoundName + '\n');
m_iNextOneShotTime = 0;
m_iSoundState = 0;
m_iNextStateTime = uii.Sys_Milliseconds();
} else {
m_iNextOneShotTime = 0;
}
}
if (m_iNextStateTime && uii.Sys_Milliseconds() >= m_iNextStateTime) {
switch (m_iSoundState) {
case 0:
Com_sprintf(buffer, sizeof(buffer), "tmvolume %4.2f\n", m_fLoopingSoundStartVolume);
uii.Cmd_Stuff(buffer);
m_iNextStateTime = uii.Sys_Milliseconds() + m_fLoopingSoundHoldStartTime * 1000;
m_iSoundState = 1;
break;
case 1:
m_iLastEnterTime = m_iNextStateTime;
m_iSoundState = 2;
m_iNextStateTime = uii.Sys_Milliseconds() + 10;
break;
case 2:
if (m_fLoopingSoundRampTime > 0) {
frac = (uii.Sys_Milliseconds() - m_iLastEnterTime) / (m_fLoopingSoundRampTime * 1000);
} else {
frac = 1.0;
}
Com_sprintf(
buffer,
sizeof(buffer),
"tmvolume %4.2f\n",
frac * (m_fLoopingSoundEndVolume - m_fLoopingSoundStartVolume) + m_fLoopingSoundStartVolume
);
uii.Cmd_Stuff(buffer);
m_iNextStateTime = uii.Sys_Milliseconds() + 10;
if (frac > 1.0) {
m_iSoundState = 3;
}
break;
case 3:
m_iNextStateTime = 0;
break;
default:
break;
}
}
}