openmohaa/code/client/cl_uiview3d.cpp

617 lines
16 KiB
C++
Raw Normal View History

2016-03-27 11:49:47 +02:00
/*
===========================================================================
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 "cl_ui.h"
#include "../qcommon/localization.h"
2016-03-27 11:49:47 +02:00
2023-12-30 17:36:01 +01:00
CLASS_DECLARATION(UIWidget, View3D, NULL) {
{&W_Activated, &View3D::OnActivate },
{&W_Deactivated, &View3D::OnDeactivate},
{&W_LeftMouseDown, &View3D::Pressed },
{NULL, NULL }
2016-03-27 11:49:47 +02:00
};
2023-12-30 17:36:01 +01:00
cvar_t *subs[MAX_SUBTITLES];
cvar_t *teams[MAX_SUBTITLES];
float fadeTime[MAX_SUBTITLES];
float subLife[MAX_SUBTITLES];
float alpha[MAX_SUBTITLES];
char oldStrings[MAX_SUBTITLES][2048];
2016-03-27 11:49:47 +02:00
View3D::View3D()
{
2023-12-30 17:36:01 +01:00
// set as transparent
setBackgroundColor(UClear, true);
// no border
setBorderStyle(border_none);
AllowActivate(true);
m_printfadetime = 0.0;
m_print_mat = NULL;
m_locationprint = qfalse;
2016-03-27 11:49:47 +02:00
}
2024-01-01 00:32:31 +01:00
void View3D::UpdateLocationPrint(int x, int y, const char *s, float alpha)
2016-03-27 11:49:47 +02:00
{
2024-01-01 00:32:31 +01:00
m_printstring = s;
m_printalpha = alpha;
m_printfadetime = 4000.0;
m_x_coord = x;
m_y_coord = y;
m_locationprint = qtrue;
}
void View3D::UpdateCenterPrint(const char *s, float alpha)
{
m_printstring = s;
if (s[0] == '@') {
m_print_mat = uWinMan.RegisterShader(s + 1);
} else {
m_print_mat = NULL;
2023-12-30 17:36:01 +01:00
}
2019-06-25 01:17:10 +02:00
2024-01-01 00:32:31 +01:00
m_printalpha = alpha;
m_printfadetime = 4000.0;
m_locationprint = qfalse;
}
2023-05-15 17:27:31 +02:00
2024-01-01 00:32:31 +01:00
void View3D::PrintSound(int channel, const char *name, float vol, int rvol, float pitch, float base, int& line)
{
char buf[255];
float x;
float xStep;
float height;
height = m_font->getHeight(false);
xStep = height;
x = 0;
2024-09-20 21:53:48 +02:00
Com_sprintf(buf, sizeof(buf), "%d", channel);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
x += xStep + xStep;
2024-09-20 21:53:48 +02:00
Com_sprintf(buf, sizeof(buf), "%s", name);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
x += xStep * 30.0;
2024-09-20 21:53:48 +02:00
Com_sprintf(buf, sizeof(buf), "vol:%.2f", vol);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
x += xStep * 8;
2024-09-20 21:53:48 +02:00
Com_sprintf(buf, sizeof(buf), "rvol:%.2f", (float)(rvol / 128.f));
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
x += xStep * 5;
2024-09-20 21:53:48 +02:00
Com_sprintf(buf, sizeof(buf), "pit:%.2f", pitch);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
x += xStep * 5;
2024-09-20 21:53:48 +02:00
Com_sprintf(buf, sizeof(buf), "base:%d", (int)base);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
line++;
2024-01-01 00:32:31 +01:00
}
2023-05-15 17:27:31 +02:00
2024-01-01 00:32:31 +01:00
void View3D::Pressed(Event *ev)
{
IN_MouseOff();
OnActivate(ev);
}
void View3D::OnDeactivate(Event *ev)
{
Key_SetCatcher(Key_GetCatcher() | KEYCATCH_UI);
2024-01-01 00:32:31 +01:00
}
void View3D::OnActivate(Event *ev)
{
UIWidget *wid;
UList<UIWidget *> widgets;
UI_CloseInventory();
Key_SetCatcher(Key_GetCatcher() & ~KEYCATCH_UI);
2024-01-01 00:32:31 +01:00
for (wid = getParent()->getFirstChild(); wid; wid = getParent()->getNextChild(wid)) {
if (wid->getAlwaysOnBottom() && wid != this) {
widgets.AddTail(wid);
}
}
widgets.IterateFromHead();
while (widgets.IsCurrentValid()) {
widgets.getCurrent()->BringToFrontPropogated();
widgets.IterateNext();
}
}
void View3D::LocationPrint(void)
{
fonthorzjustify_t horiz;
fontvertjustify_t vert;
int x, y;
const char *p;
float alpha;
UIRect2D frame;
if (!m_printfadetime) {
m_locationprint = false;
return;
}
horiz = FONT_JUSTHORZ_LEFT;
vert = FONT_JUSTVERT_TOP;
p = Sys_LV_CL_ConvertString(m_printstring);
if (m_printfadetime > 3250) {
alpha = 1.f - (m_printfadetime - 3250.f) / 750.f * m_printalpha;
} else if (m_printfadetime >= 750) {
alpha = 1.f;
} else {
alpha = m_printfadetime / 750.f * m_printalpha;
}
alpha = Q_clamp_float(alpha, 0, 1);
x = m_x_coord / 640.f * m_screenframe.size.width;
y = (480 - m_font->getHeight(false) - m_y_coord) / 480.f * m_screenframe.size.height;
if (m_x_coord == -1) {
horiz = FONT_JUSTHORZ_CENTER;
x = 0;
}
if (m_y_coord == -1) {
vert = FONT_JUSTVERT_CENTER;
y = 0;
}
m_font->setColor(UColor(0, 0, 0, alpha));
frame = getClientFrame();
m_font->PrintJustified(
UIRect2D(frame.pos.x + x + 1, frame.pos.y + y + 1, frame.size.width, frame.size.height),
horiz,
vert,
p,
2024-01-01 01:53:23 +01:00
m_bVirtual ? m_vVirtualScale : NULL
);
m_font->setColor(UColor(1, 1, 1, alpha));
frame = getClientFrame();
m_font->PrintJustified(
UIRect2D(frame.pos.x + x, frame.pos.y + y, frame.size.width, frame.size.height),
horiz,
vert,
p,
2024-01-01 01:53:23 +01:00
m_bVirtual ? m_vVirtualScale : NULL
);
m_font->setColor(UBlack);
m_printfadetime -= cls.frametime;
if (m_printfadetime < 0) {
m_printfadetime = 0;
}
2024-01-01 00:32:31 +01:00
}
qboolean View3D::LetterboxActive(void)
{
return m_letterbox_active;
}
float avWidth = 0.0;
void View3D::InitSubtitle(void)
{
float totalWidth;
for (int i = 0; i < 4; i++) {
subs[i] = Cvar_Get(va("subtitle%d", i), "", 0);
teams[i] = Cvar_Get(va("subteam%d", i), "0", 0);
2024-09-20 21:53:48 +02:00
Q_strncpyz(oldStrings[i], subs[i]->string, sizeof(oldStrings[i]));
2024-01-01 00:32:31 +01:00
fadeTime[i] = 4000.0;
subLife[i] = 4000.0;
}
totalWidth = 0.0;
for (char j = 'A'; j <= 'Z'; j++) {
totalWidth += m_font->getCharWidth(j);
}
avWidth = totalWidth / 26.0;
}
void View3D::FrameInitialized(void)
{
Connect(this, W_Activated, W_Activated);
Connect(this, W_Deactivated, W_Deactivated);
}
void View3D::DrawSubtitleOverlay(void)
{
cvar_t *subAlpha;
int i;
float minX, maxY;
int line;
subAlpha = Cvar_Get("subAlpha", "0.5", 0);
setFont("facfont-20");
m_font->setColor(URed);
for (i = 0; i < MAX_SUBTITLES; i++) {
if (strcmp(oldStrings[i], subs[i]->string)) {
fadeTime[i] = 2500 * ((strlen(subs[i]->string) / 68) + 1.f) + 1500;
subLife[i] = fadeTime[i];
Q_strncpyz(oldStrings[i], subs[i]->string, sizeof(oldStrings[i]));
}
if (fadeTime[i] > subLife[i] - 750.f) {
alpha[i] = 1.f - (fadeTime[i] - (subLife[i] - 750.f)) / 750.f;
} else if (fadeTime[i] < 750) {
alpha[i] = fadeTime[i] / 750.f;
} else {
alpha[i] = 1.f;
}
fadeTime[i] -= cls.frametime;
if (fadeTime[i] < 0) {
// Clear the subtitle
fadeTime[i] = 0;
oldStrings[i][0] = 0;
if (subs[i]->string && subs[i]->string[0]) {
Cvar_Set(va("subtitle%d", i), "");
}
}
}
minX = m_screenframe.size.height - m_font->getHeight(false) * 10;
maxY = (m_frame.pos.x + m_frame.size.width) - (m_frame.pos.x + m_frame.size.width) * 0.2f;
line = 0;
for (i = 0; i < MAX_SUBTITLES; i++) {
2024-11-05 01:14:21 +01:00
if (fadeTime[i] <= 0) {
continue;
}
if (m_font->getWidth(subs[i]->string, sizeof(oldStrings[i])) > maxY) {
char buf[2048];
char *c;
char *end;
char *start;
float total;
2024-11-05 01:14:21 +01:00
float width;
int blockcount;
2024-11-05 01:14:21 +01:00
c = subs[i]->string;
total = 0;
end = NULL;
start = buf;
2024-11-05 01:14:21 +01:00
while (*c) {
blockcount = m_font->DBCSGetWordBlockCount(c, -1);
if (!blockcount) {
break;
}
2024-11-05 01:14:21 +01:00
width = m_font->getWidth(c, blockcount);
2024-11-05 01:14:21 +01:00
if (total + width > maxY) {
m_font->setColor(UColor(0, 0, 0, alpha[i] * subAlpha->value));
2024-11-05 01:14:21 +01:00
m_font->Print(18, m_font->getHeight(false) * line + minX + 1.f, buf, -1, false);
m_font->setColor(UColor(1, 1, 1, alpha[i] * subAlpha->value));
2024-11-05 01:14:21 +01:00
m_font->Print(20, m_font->getHeight(false) * line + minX, buf, -1, false);
line++;
2024-11-05 01:14:21 +01:00
total = 0;
start = buf;
}
end = start + blockcount + 1;
if (end > buf + MAX_STRING_CHARS) {
Com_DPrintf("ERROR - word longer than possible line\n");
break;
}
2024-11-05 01:14:21 +01:00
memcpy(start, c, blockcount);
start += blockcount;
total += width;
*start = 0;
c += blockcount;
}
m_font->setColor(UColor(0, 0, 0, alpha[i] * subAlpha->value));
2024-11-05 01:14:21 +01:00
m_font->Print(18, m_font->getHeight(false) * line + minX + 1.f, buf, -1, qfalse);
m_font->setColor(UColor(1, 1, 1, alpha[i] * subAlpha->value));
2024-11-05 01:14:21 +01:00
m_font->Print(20, m_font->getHeight(false) * line + minX, buf, -1, qfalse);
line++;
} else {
m_font->setColor(UColor(0, 0, 0, alpha[i] * subAlpha->value));
m_font->Print(18, m_font->getHeight(false) * line + minX + 1.f, subs[i]->string, -1, qfalse);
m_font->setColor(UColor(1, 1, 1, alpha[i] * subAlpha->value));
m_font->Print(20, m_font->getHeight(false) * line + minX, subs[i]->string, -1, qfalse);
line++;
}
}
2024-01-01 00:32:31 +01:00
}
void View3D::DrawSoundOverlay(void)
{
setFont("verdana-14");
m_font->setColor(UWhite);
// FIXME: TODO
2024-01-01 00:32:31 +01:00
if (sound_overlay->integer) {
Com_Printf("sound_overlay isn't supported with OpenAL/SDL right now.\n");
Cvar_Set("sound_overlay", "0");
}
}
void View3D::DrawProf(void)
{
// Normal empty function
2016-03-27 11:49:47 +02:00
}
2023-12-30 17:36:01 +01:00
void View3D::DrawLetterbox(void)
2016-03-27 11:49:47 +02:00
{
2023-12-30 17:36:01 +01:00
float frac;
vec4_t col;
col[0] = col[1] = col[2] = 0;
col[3] = 1;
frac = (float)cl.snap.ps.stats[STAT_LETTERBOX] / MAX_LETTERBOX_SIZE;
if (frac <= 0) {
2023-12-30 17:36:01 +01:00
m_letterbox_active = false;
return;
2023-12-30 17:36:01 +01:00
}
m_letterbox_active = true;
re.SetColor(col);
re.DrawBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height * frac);
re.DrawBox(
0.0,
m_screenframe.size.height - m_screenframe.size.height * frac,
m_screenframe.size.width,
m_screenframe.size.height
);
2016-03-27 11:49:47 +02:00
}
2023-12-30 17:36:01 +01:00
void View3D::DrawFades(void)
2016-03-27 11:49:47 +02:00
{
2023-12-30 17:36:01 +01:00
if (cl.snap.ps.blend[3] > 0) {
re.SetColor(cl.snap.ps.blend);
if (cl.snap.ps.stats[STAT_ADDFADE]) {
re.AddBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height);
} else {
re.DrawBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height);
2023-12-30 17:36:01 +01:00
}
}
2016-03-27 11:49:47 +02:00
}
2023-12-30 17:36:01 +01:00
void View3D::DrawFPS(void)
2016-03-27 11:49:47 +02:00
{
2023-12-30 17:36:01 +01:00
char string[128];
setFont("verdana-14");
if (fps->integer == 2) {
re.SetColor(UBlack);
re.DrawBox(
0.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 4.0,
m_frame.pos.x + m_frame.size.width,
m_font->getHeight(qfalse) * 4.0
);
}
2024-09-20 21:53:48 +02:00
Com_sprintf(string, sizeof(string), "FPS %4.1f", currentfps);
2023-12-30 17:36:01 +01:00
if (currentfps > 23.94) {
if (cl_greenfps->integer) {
m_font->setColor(UGreen);
} else {
m_font->setColor(UWhite);
}
} else if (currentfps > 18.0) {
m_font->setColor(UYellow);
} else {
// low fps
m_font->setColor(URed);
}
m_font->Print(
m_font->getHeight(qfalse) * 10.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 3.0,
string,
-1,
qfalse
);
// Draw elements count
if (cl_greenfps->integer) {
m_font->setColor(UGreen);
} else {
m_font->setColor(UWhite);
}
2024-09-20 21:53:48 +02:00
Com_sprintf(string, sizeof(string), "wt%5d wv%5d cl%d", cls.world_tris, cls.world_verts, cls.character_lights);
2023-12-30 17:36:01 +01:00
m_font->Print(
m_font->getHeight(qfalse) * 10.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 2.0,
string,
-1,
qfalse
);
Com_sprintf(
string,
sizeof(string),
"t%5d v%5d Mtex%5.2f",
cls.total_tris,
cls.total_verts,
(float)cls.total_texels * 0.00000095367432
);
2023-12-30 17:36:01 +01:00
m_font->Print(
m_font->getHeight(qfalse) * 10.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse),
string,
-1,
qfalse
);
m_font->setColor(UBlack);
2016-03-27 11:49:47 +02:00
}
2024-01-01 00:32:31 +01:00
void View3D::Draw2D(void)
2016-03-27 11:49:47 +02:00
{
2024-01-01 00:32:31 +01:00
if (!cls.no_menus) {
DrawFades();
2023-12-30 17:36:01 +01:00
}
2016-03-27 11:49:47 +02:00
2024-01-01 00:32:31 +01:00
DrawLetterbox();
2016-03-27 11:49:47 +02:00
2024-01-01 00:32:31 +01:00
if ((cl_debuggraph->integer || cl_timegraph->integer) && !cls.no_menus) {
SCR_DrawDebugGraph();
} else if (!cls.no_menus) {
if (cge) {
cge->CG_Draw2D();
}
2023-05-10 19:34:21 +02:00
2024-01-01 00:32:31 +01:00
if (m_locationprint) {
LocationPrint();
} else {
CenterPrint();
}
2023-05-10 19:34:21 +02:00
2024-01-01 00:32:31 +01:00
if (!cls.no_menus) {
DrawSoundOverlay();
DrawSubtitleOverlay();
2023-12-30 17:36:01 +01:00
}
}
2024-01-01 00:32:31 +01:00
if (fps->integer && !cls.no_menus) {
DrawFPS();
DrawProf();
2023-12-30 17:36:01 +01:00
}
2016-03-27 11:49:47 +02:00
}
2024-01-01 00:32:31 +01:00
void View3D::Draw(void)
2016-03-27 11:49:47 +02:00
{
2024-01-01 00:32:31 +01:00
if (clc.state != CA_DISCONNECTED) {
SCR_DrawScreenField();
2023-12-30 17:36:01 +01:00
}
2024-01-01 00:32:31 +01:00
set2D();
2023-12-30 17:36:01 +01:00
2024-01-01 00:32:31 +01:00
re.SavePerformanceCounters();
2023-12-30 17:36:01 +01:00
2024-01-01 00:32:31 +01:00
Draw2D();
2016-03-27 11:49:47 +02:00
}
2024-01-01 00:32:31 +01:00
void View3D::ClearCenterPrint(void)
2016-03-27 11:49:47 +02:00
{
2024-01-01 00:32:31 +01:00
m_printfadetime = 0.0;
2016-03-27 11:49:47 +02:00
}
2024-01-01 00:32:31 +01:00
void View3D::CenterPrint(void)
2016-03-27 11:49:47 +02:00
{
float alpha;
const char *p;
qhandle_t mat;
float x, y;
float w, h;
if (!m_printfadetime) {
return;
}
p = Sys_LV_CL_ConvertString(m_printstring);
if (m_printfadetime > 3250) {
alpha = 1.f - (m_printfadetime - 3250.f) / 750.f * m_printalpha;
} else if (m_printfadetime >= 750) {
alpha = 1.f;
} else {
alpha = m_printfadetime / 750.f * m_printalpha;
}
alpha = Q_clamp_float(alpha, 0, 1);
if (!m_print_mat) {
UIRect2D frame;
m_font->setColor(UColor(0, 0, 0, alpha));
frame = getClientFrame();
m_font->PrintJustified(
UIRect2D(frame.pos.x + 1, frame.pos.y + 1, frame.size.width, frame.size.height),
m_iFontAlignmentHorizontal,
m_iFontAlignmentVertical,
p,
2024-01-01 01:53:23 +01:00
m_bVirtual ? m_vVirtualScale : NULL
);
m_font->setColor(UColor(1, 1, 1, alpha));
frame = getClientFrame();
m_font->PrintJustified(
2024-01-01 01:53:23 +01:00
frame, m_iFontAlignmentHorizontal, m_iFontAlignmentVertical, p, m_bVirtual ? m_vVirtualScale : NULL
);
m_font->setColor(UBlack);
} else if ((mat = m_print_mat->GetMaterial())) {
vec4_t col {alpha, alpha, alpha, alpha};
re.SetColor(col);
w = re.GetShaderWidth(mat);
h = re.GetShaderHeight(mat);
x = (m_frame.pos.x + m_frame.size.width - w) * 0.5f;
y = (m_frame.pos.y + m_frame.size.height - h) * 0.5f;
re.DrawStretchPic(x, y, w, h, 0, 0, 1, 1, mat);
}
m_printfadetime -= cls.frametime;
if (m_printfadetime < 0) {
m_printfadetime = 0;
}
2016-03-27 11:49:47 +02:00
}
2023-12-30 17:36:01 +01:00
CLASS_DECLARATION(UIWidget, ConsoleView, NULL) {
{NULL, NULL}
2016-03-27 11:49:47 +02:00
};
2024-01-01 00:32:31 +01:00
void ConsoleView::Draw(void) {}