mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-22 20:11:44 +00:00
906b705bf0
fixed non-browser ogg decoding and openal logic. should finally be fixed, I guess. wasted some time on an ezhud plugin, along with ensuring certain info is available to the plugin. this is still a work in progress however. non-web builds are now able to download images from urls. download progress does not display for uri_get/uri_post builtins, nor other non-saved things. q1qvm logic now uses pr_maxedicts cvar. the gamecode api still provides no way to tell how many are permissable, so set at own risk. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4852 fc73d0e0-1445-4013-8a0c-d673dee63da5
1535 lines
33 KiB
C
1535 lines
33 KiB
C
/*
|
|
Copyright (C) 2011 azazello and ezQuake team
|
|
|
|
This program 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.
|
|
|
|
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
//
|
|
// HUD commands
|
|
//
|
|
|
|
#include "../plugin.h"
|
|
#include "ezquakeisms.h"
|
|
//#include "common_draw.h"
|
|
//#include "keys.h"
|
|
#include "hud.h"
|
|
#include "hud_common.h"
|
|
#include "hud_editor.h"
|
|
//#include "utils.h"
|
|
//#include "sbar.h"
|
|
|
|
#define sbar_last_width 320 // yeah yeah I know, *garbage* -> leave it be :>
|
|
|
|
char *align_strings_x[] = {
|
|
"left",
|
|
"center",
|
|
"right",
|
|
"before",
|
|
"after"
|
|
};
|
|
#define num_align_strings_x (sizeof(align_strings_x) / sizeof(align_strings_x[0]))
|
|
|
|
char *align_strings_y[] = {
|
|
"top",
|
|
"center",
|
|
"bottom",
|
|
"before",
|
|
"after",
|
|
"console"
|
|
};
|
|
#define num_align_strings_y (sizeof(align_strings_y) / sizeof(align_strings_y[0]))
|
|
|
|
char *snap_strings[] = {
|
|
"screen",
|
|
"top",
|
|
"view",
|
|
"sbar",
|
|
"ibar",
|
|
"hbar",
|
|
"sfree",
|
|
"ifree",
|
|
"hfree",
|
|
};
|
|
#define num_snap_strings (sizeof(snap_strings) / sizeof(snap_strings[0]))
|
|
|
|
// Hud elements list.
|
|
hud_t *hud_huds = NULL;
|
|
|
|
qbool doreorder;
|
|
|
|
//
|
|
// Hud plus func - show element.
|
|
//
|
|
void HUD_Plus_f(void)
|
|
{
|
|
char *t;
|
|
hud_t *hud;
|
|
|
|
if (Cmd_Argc() < 1)
|
|
return;
|
|
|
|
t = Cmd_Argv(0);
|
|
if (strncmp(t, "+hud_", 5))
|
|
return;
|
|
|
|
hud = HUD_Find(t + 5);
|
|
if (!hud)
|
|
{
|
|
// This should never happen...
|
|
return;
|
|
}
|
|
|
|
if (!hud->show)
|
|
{
|
|
// This should never happen...
|
|
return;
|
|
}
|
|
|
|
Cvar_Set(hud->show, "1");
|
|
}
|
|
|
|
//
|
|
// Hud minus func - hide element.
|
|
//
|
|
void HUD_Minus_f(void)
|
|
{
|
|
char *t;
|
|
hud_t *hud;
|
|
|
|
if (Cmd_Argc() < 1)
|
|
return;
|
|
|
|
t = Cmd_Argv(0);
|
|
if (strncmp(t, "-hud_", 5))
|
|
return;
|
|
|
|
hud = HUD_Find(t + 5);
|
|
if (!hud)
|
|
{
|
|
// this should never happen...
|
|
return;
|
|
}
|
|
|
|
if (!hud->show)
|
|
{
|
|
// this should never happen...
|
|
return;
|
|
}
|
|
|
|
Cvar_Set(hud->show, "0");
|
|
}
|
|
|
|
//
|
|
// Hud element func - describe it
|
|
// this also solves the TAB completion problem
|
|
//
|
|
void HUD_Func_f(void)
|
|
{
|
|
int i;
|
|
hud_t *hud;
|
|
|
|
hud = HUD_Find(Cmd_Argv(0));
|
|
|
|
if (!hud)
|
|
{
|
|
// This should never happen...
|
|
Com_Printf("Hud element not found\n");
|
|
return;
|
|
}
|
|
|
|
if (Cmd_Argc() > 1)
|
|
{
|
|
char buf[512];
|
|
|
|
snprintf(buf, sizeof(buf), "hud_%s_%s", hud->name, Cmd_Argv(1));
|
|
if (Cvar_Find(buf) != NULL)
|
|
{
|
|
Cbuf_AddText(buf);
|
|
if (Cmd_Argc() > 2)
|
|
{
|
|
Cbuf_AddText(" ");
|
|
Cbuf_AddText(Cmd_Argv(2));
|
|
}
|
|
Cbuf_AddText("\n");
|
|
}
|
|
else
|
|
{
|
|
Com_Printf("Trying \"%s\" - no such variable\n", buf);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Description.
|
|
Com_Printf("%s\n\n", hud->description);
|
|
|
|
// Status.
|
|
if (hud->show != NULL)
|
|
{
|
|
Com_Printf("Current status: %s\n", hud->show->value ? "shown" : "hidden");
|
|
}
|
|
|
|
if (hud->frame != NULL)
|
|
{
|
|
Com_Printf("Frame: %s\n\n", hud->frame->string);
|
|
}
|
|
|
|
if (hud->frame_color != NULL)
|
|
{
|
|
Com_Printf("Frame color: %s\n\n", hud->frame_color->string);
|
|
}
|
|
|
|
// Placement.
|
|
Com_Printf("Placement: %s\n", hud->place->string);
|
|
|
|
// Alignment.
|
|
Com_Printf("Alignment (x y): %s %s\n", hud->align_x->string, hud->align_y->string);
|
|
|
|
// Position.
|
|
Com_Printf("Offset (x y): %d %d\n", (int)(hud->pos_x->value), (int)(hud->pos_y->value));
|
|
|
|
// Ordering.
|
|
Com_Printf("Draw Order (z): %d\n", (int)hud->order->value);
|
|
|
|
// Additional parameters.
|
|
if (hud->num_params > 0)
|
|
{
|
|
int prefix_l = strlen(va("hud_%s_", hud->name));
|
|
Com_Printf("\nParameters:\n");
|
|
for (i=0; i < hud->num_params; i++)
|
|
{
|
|
if (strlen(hud->params[i]->name) > prefix_l)
|
|
Com_Printf(" %-15s %s\n", hud->params[i]->name + prefix_l,
|
|
hud->params[i]->string);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Find the elements with the max and min z-order.
|
|
//
|
|
void HUD_FindMaxMinOrder(int *max, int *min)
|
|
{
|
|
hud_t *hud = hud_huds;
|
|
|
|
while(hud)
|
|
{
|
|
(*min) = ((int)hud->order->value < (*min)) ? (int)hud->order->value : (*min);
|
|
(*max) = ((int)hud->order->value > (*max)) ? (int)hud->order->value : (*max);
|
|
|
|
hud = hud->next;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Find hud placement by string
|
|
// return 0 if error
|
|
//
|
|
int HUD_FindPlace(hud_t *hud)
|
|
{
|
|
int i;
|
|
hud_t *par;
|
|
qbool out;
|
|
char *t;
|
|
|
|
// First try standard strings.
|
|
for (i=0; i < num_snap_strings; i++)
|
|
{
|
|
if (!strcasecmp(hud->place->string, snap_strings[i]))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i < num_snap_strings)
|
|
{
|
|
// Found.
|
|
hud->place_num = i+1;
|
|
hud->place_hud = NULL;
|
|
return 1;
|
|
}
|
|
|
|
// then try another HUD element
|
|
out = true;
|
|
t = hud->place->string;
|
|
if (hud->place->string[0] == '@')
|
|
{
|
|
// place inside
|
|
out = false;
|
|
t++;
|
|
}
|
|
|
|
par = hud_huds;
|
|
while (par)
|
|
{
|
|
if (par != hud && !strcmp(t, par->name))
|
|
{
|
|
hud->place_outside = out;
|
|
hud->place_hud = par;
|
|
hud->place_num = HUD_PLACE_SCREEN;
|
|
return 1;
|
|
}
|
|
par = par->next;
|
|
}
|
|
|
|
// No way.
|
|
hud->place_num = HUD_PLACE_SCREEN;
|
|
hud->place_hud = NULL;
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Find hud alignment by strings
|
|
// return 0 if error
|
|
//
|
|
int HUD_FindAlignX(hud_t *hud)
|
|
{
|
|
int i;
|
|
|
|
// First try standard strings.
|
|
for (i=0; i < num_align_strings_x; i++)
|
|
{
|
|
if (!strcasecmp(hud->align_x->string, align_strings_x[i]))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i < num_align_strings_x)
|
|
{
|
|
// Found.
|
|
hud->align_x_num = i+1;
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
// Error.
|
|
hud->align_x_num = HUD_ALIGN_LEFT; // left
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Find the alignment for a hud element.
|
|
//
|
|
int HUD_FindAlignY(hud_t *hud)
|
|
{
|
|
int i;
|
|
|
|
// First try standard strings.
|
|
for (i=0; i < num_align_strings_y; i++)
|
|
{
|
|
if (!strcasecmp(hud->align_y->string, align_strings_y[i]))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i < num_align_strings_y)
|
|
{
|
|
// Found.
|
|
hud->align_y_num = i + 1;
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
// Error.
|
|
hud->align_y_num = HUD_ALIGN_TOP; // Left.
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int Hud_HudCompare (const void *p1, const void *p2)
|
|
{
|
|
return strcmp((*((hud_t **) p1))->name, (*((hud_t **) p2))->name);
|
|
}
|
|
|
|
//
|
|
// List hud elements
|
|
//
|
|
void HUD_List (void)
|
|
{
|
|
static hud_t *sorted_huds[256];
|
|
int i, count;
|
|
hud_t *hud;
|
|
|
|
#define MAX_SORTED_HUDS (sizeof (sorted_huds) / sizeof (sorted_huds[0]))
|
|
|
|
for (hud = hud_huds, count = 0; hud && count < MAX_SORTED_HUDS; hud = hud->next, count++)
|
|
sorted_huds[count] = hud;
|
|
qsort (sorted_huds, count, sizeof (hud_t *), Hud_HudCompare);
|
|
|
|
if (count == MAX_SORTED_HUDS)
|
|
assert(!"count == MAX_SORTED_HUDS");
|
|
|
|
Com_Printf("name status\n");
|
|
Com_Printf("--------------- ------\n");
|
|
for (i = 0; i < count; i++) {
|
|
hud = sorted_huds[i];
|
|
|
|
Com_Printf("%-15s %s\n", hud->name, hud->show->value ? "shown" : "hidden");
|
|
}
|
|
}
|
|
|
|
//
|
|
// Show the specified hud element.
|
|
//
|
|
void HUD_Show_f (void)
|
|
{
|
|
hud_t *hud;
|
|
|
|
if (Cmd_Argc() != 2)
|
|
{
|
|
Com_Printf("Usage: show [<name> | all]\n");
|
|
Com_Printf("Show given HUD element.\n");
|
|
Com_Printf("use \"show all\" to show all elements.\n");
|
|
Com_Printf("Current elements status:\n\n");
|
|
HUD_List();
|
|
return;
|
|
}
|
|
|
|
if (!strcasecmp(Cmd_Argv(1), "all"))
|
|
{
|
|
hud = hud_huds;
|
|
while (hud)
|
|
{
|
|
Cvar_SetValue(hud->show, 1);
|
|
hud = hud->next;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hud = HUD_Find(Cmd_Argv(1));
|
|
|
|
if (!hud)
|
|
{
|
|
Com_Printf("No such element: %s\n", Cmd_Argv(1));
|
|
return;
|
|
}
|
|
|
|
Cvar_SetValue(hud->show, 1);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Hide the specified hud element.
|
|
//
|
|
void HUD_Hide_f (void)
|
|
{
|
|
hud_t *hud;
|
|
|
|
if (Cmd_Argc() != 2)
|
|
{
|
|
Com_Printf("Usage: hide [<name> | all]\n");
|
|
Com_Printf("Hide given HUD element\n");
|
|
Com_Printf("use \"hide all\" to hide all elements.\n");
|
|
Com_Printf("Current elements status:\n\n");
|
|
HUD_List();
|
|
return;
|
|
}
|
|
|
|
if (!strcasecmp(Cmd_Argv(1), "all"))
|
|
{
|
|
hud = hud_huds;
|
|
while (hud)
|
|
{
|
|
Cvar_SetValue(hud->show, 0);
|
|
hud = hud->next;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hud = HUD_Find(Cmd_Argv(1));
|
|
|
|
if (!hud)
|
|
{
|
|
Com_Printf("No such element: %s\n", Cmd_Argv(1));
|
|
return;
|
|
}
|
|
|
|
Cvar_SetValue(hud->show, 0);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Toggles specified hud element.
|
|
//
|
|
void HUD_Toggle_f (void)
|
|
{
|
|
hud_t *hud;
|
|
|
|
if (Cmd_Argc() != 2)
|
|
{
|
|
Com_Printf("Usage: togglehud <name> | <variable>\n");
|
|
Com_Printf("Show/hide given HUD element, or toggles variable value.\n");
|
|
return;
|
|
}
|
|
|
|
hud = HUD_Find(Cmd_Argv(1));
|
|
|
|
if (!hud)
|
|
{
|
|
// look for cvar
|
|
cvar_t *var = Cvar_Find(Cmd_Argv(1));
|
|
if (!var)
|
|
{
|
|
Com_Printf("No such element or variable: %s\n", Cmd_Argv(1));
|
|
return;
|
|
}
|
|
|
|
Cvar_Set (var, var->value ? "0" : "1");
|
|
return;
|
|
}
|
|
|
|
Cvar_Set (hud->show, hud->show->value ? "0" : "1");
|
|
}
|
|
|
|
//
|
|
// Move the specified hud element relative to placement/alignment.
|
|
//
|
|
void HUD_Move_f (void)
|
|
{
|
|
hud_t *hud;
|
|
|
|
if (Cmd_Argc() != 4 && Cmd_Argc() != 2)
|
|
{
|
|
Com_Printf("Usage: move <name> [<x> <y>]\n");
|
|
Com_Printf("Set offset for given HUD element\n");
|
|
return;
|
|
}
|
|
|
|
hud = HUD_Find(Cmd_Argv(1));
|
|
|
|
if (!hud)
|
|
{
|
|
Com_Printf("No such element: %s\n", Cmd_Argv(1));
|
|
return;
|
|
}
|
|
|
|
if (Cmd_Argc() == 2)
|
|
{
|
|
Com_Printf("Current %s offset is:\n", Cmd_Argv(1));
|
|
Com_Printf(" x: %s\n", hud->pos_x->string);
|
|
Com_Printf(" y: %s\n", hud->pos_y->string);
|
|
return;
|
|
}
|
|
|
|
Cvar_SetValue(hud->pos_x, atof(Cmd_Argv(2)));
|
|
Cvar_SetValue(hud->pos_y, atof(Cmd_Argv(3)));
|
|
}
|
|
|
|
//
|
|
// Resets a hud item to the center of the screen.
|
|
//
|
|
void HUD_Reset_f (void)
|
|
{
|
|
hud_t *hud = NULL;
|
|
char *hudname = NULL;
|
|
|
|
if (Cmd_Argc() != 2)
|
|
{
|
|
Com_Printf("Usage: reset <name>\n");
|
|
Com_Printf("Resets the position of the given HUD element to the center of the screen.\n");
|
|
return;
|
|
}
|
|
|
|
hudname = Cmd_Argv(1);
|
|
|
|
hud = HUD_Find(hudname);
|
|
|
|
if (!hud)
|
|
{
|
|
Com_Printf("No such HUD element %s.\n", hudname);
|
|
return;
|
|
}
|
|
|
|
Cbuf_AddText(va("place %s screen\n", hudname));
|
|
Cbuf_AddText(va("move %s 0 0\n", hudname));
|
|
Cbuf_AddText(va("align %s center center\n", hudname));
|
|
}
|
|
|
|
//
|
|
// Reorders children so that they are place infront of their parent.
|
|
//
|
|
void HUD_ReorderChildren(void)
|
|
{
|
|
hud_t *hud = hud_huds;
|
|
|
|
// Give all children a higher Z-order.
|
|
while(hud)
|
|
{
|
|
if(hud->place_hud && hud->order->value <= hud->place_hud->order->value)
|
|
{
|
|
Cvar_SetValue(hud->order, hud->place_hud->order->value + 1);
|
|
}
|
|
|
|
hud = hud->next;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Place the specified hud element.
|
|
//
|
|
void HUD_Place_f (void)
|
|
{
|
|
hud_t *hud;
|
|
char temp[512];
|
|
|
|
if (Cmd_Argc() < 2 || Cmd_Argc() > 3)
|
|
{
|
|
Com_Printf("Usage: move <name> [<area>]\n");
|
|
Com_Printf("Place HUD element at given area.\n");
|
|
Com_Printf("\nPossible areas are:\n");
|
|
Com_Printf(" screen - screen area\n");
|
|
Com_Printf(" top - screen minus status bar\n");
|
|
Com_Printf(" view - view\n");
|
|
Com_Printf(" sbar - status bar\n");
|
|
Com_Printf(" ibar - inventory bar\n");
|
|
Com_Printf(" hbar - health bar\n");
|
|
Com_Printf(" sfree - status bar free area\n");
|
|
Com_Printf(" ifree - inventory bar free area\n");
|
|
Com_Printf(" hfree - health bar free area\n");
|
|
Com_Printf("You can also use any other HUD element as a base alignment. In such case you should specify area as:\n");
|
|
Com_Printf(" @elem - if you want to place\n");
|
|
Com_Printf(" it inside elem\n");
|
|
Com_Printf(" elem - if you want to place\n");
|
|
Com_Printf(" it outside elem\n");
|
|
Com_Printf("Examples:\n");
|
|
Com_Printf(" place fps view\n");
|
|
Com_Printf(" place fps @ping\n");
|
|
return;
|
|
}
|
|
|
|
hud = HUD_Find(Cmd_Argv(1));
|
|
|
|
if (!hud)
|
|
{
|
|
Com_Printf("No such element: %s\n", Cmd_Argv(1));
|
|
return;
|
|
}
|
|
|
|
if (Cmd_Argc() == 2)
|
|
{
|
|
Com_Printf("Current %s placement: %s\n", hud->name, hud->place->string);
|
|
return;
|
|
}
|
|
|
|
// Place with helper.
|
|
strlcpy(temp, hud->place->string, sizeof(temp));
|
|
Cvar_Set(hud->place, Cmd_Argv(2));
|
|
if (!HUD_FindPlace(hud))
|
|
{
|
|
Com_Printf("place: invalid area argument: %s\n", Cmd_Argv(2));
|
|
Cvar_Set(hud->place, temp); // Restore old value.
|
|
}
|
|
else
|
|
{
|
|
HUD_ReorderChildren();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Sets the z-order of a HUD element.
|
|
//
|
|
void HUD_Order_f (void)
|
|
{
|
|
int max = 0;
|
|
int min = 0;
|
|
char *option = NULL;
|
|
hud_t *hud = NULL;
|
|
|
|
if (Cmd_Argc() < 2 || Cmd_Argc() > 3)
|
|
{
|
|
Com_Printf("Usage: order <name> [<option>]\n");
|
|
Com_Printf("Set HUD element draw order\n");
|
|
Com_Printf("\nPossible values for option:\n");
|
|
Com_Printf(" # - An integer representing the order.\n");
|
|
Com_Printf(" backward - Send the element backwards in the order.\n");
|
|
Com_Printf(" forward - Send the element forward in the order.\n");
|
|
Com_Printf(" front - Bring the element to the front.\n");
|
|
Com_Printf(" back - Put the element at the far back.\n");
|
|
return;
|
|
}
|
|
|
|
hud = HUD_Find (Cmd_Argv(1));
|
|
|
|
if (!hud)
|
|
{
|
|
Com_Printf("No such element: %s\n", Cmd_Argv(1));
|
|
return;
|
|
}
|
|
|
|
if (Cmd_Argc() == 2)
|
|
{
|
|
Com_Printf("Current order for %s is:\n", Cmd_Argv(1));
|
|
Com_Printf(" order: %d\n", (int)hud->order->value);
|
|
return;
|
|
}
|
|
|
|
option = Cmd_Argv(2);
|
|
|
|
HUD_FindMaxMinOrder (&max, &min);
|
|
|
|
if (!strncasecmp (option, "backward", 8))
|
|
{
|
|
// Send backward one step.
|
|
Cvar_SetValue(hud->order, (int)hud->order->value - 1);
|
|
}
|
|
else if (!strncasecmp (option, "forward", 7))
|
|
{
|
|
// Move forward one step.
|
|
Cvar_SetValue(hud->order, (int)hud->order->value + 1);
|
|
}
|
|
else if (!strncasecmp (option, "front", 5))
|
|
{
|
|
// Bring to front.
|
|
Cvar_SetValue(hud->order, max + 1);
|
|
}
|
|
else if (!strncasecmp (option, "back", 8))
|
|
{
|
|
// Send to far back.
|
|
Cvar_SetValue(hud->order, min - 1);
|
|
}
|
|
else
|
|
{
|
|
// Order #
|
|
Cvar_SetValue (hud->order, atoi(Cmd_Argv(2)));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Align the specified hud element
|
|
//
|
|
void HUD_Align_f (void)
|
|
{
|
|
hud_t *hud;
|
|
|
|
if (Cmd_Argc() != 4 && Cmd_Argc() != 2)
|
|
{
|
|
Com_Printf("Usage: align <name> [<ax> <ay>]\n");
|
|
Com_Printf("Set HUD element alignment\n");
|
|
Com_Printf("\nPossible values for ax are:\n");
|
|
Com_Printf(" left - left area edge\n");
|
|
Com_Printf(" center - area center\n");
|
|
Com_Printf(" right - right area edge\n");
|
|
Com_Printf(" before - before area (left)\n");
|
|
Com_Printf(" after - after area (right)\n");
|
|
Com_Printf("\nPossible values for ay are:\n");
|
|
Com_Printf(" top - screen top\n");
|
|
Com_Printf(" center - screen center\n");
|
|
Com_Printf(" bottom - screen bottom\n");
|
|
Com_Printf(" before - before area (top)\n");
|
|
Com_Printf(" after - after area (bottom)\n");
|
|
Com_Printf(" console - below console\n");
|
|
return;
|
|
}
|
|
|
|
hud = HUD_Find(Cmd_Argv(1));
|
|
|
|
if (!hud)
|
|
{
|
|
Com_Printf("No such element: %s\n", Cmd_Argv(1));
|
|
return;
|
|
}
|
|
|
|
if (Cmd_Argc() == 2)
|
|
{
|
|
Com_Printf("Current alignment for %s is:\n", Cmd_Argv(1));
|
|
Com_Printf(" horizontal (x): %s\n", hud->align_x->string);
|
|
Com_Printf(" vertical (y): %s\n", hud->align_y->string);
|
|
return;
|
|
}
|
|
|
|
// validate and set
|
|
Cvar_Set(hud->align_x, Cmd_Argv(2));
|
|
if (!HUD_FindAlignX(hud))
|
|
Com_Printf("align: invalid X alignment: %s\n", Cmd_Argv(2));
|
|
|
|
Cvar_Set(hud->align_y, Cmd_Argv(3));
|
|
if (!HUD_FindAlignY(hud))
|
|
Com_Printf("align: invalid Y alignment: %s\n", Cmd_Argv(3));
|
|
}
|
|
|
|
//
|
|
// Recalculate all elements
|
|
// should be called if some HUD parameters (like place)
|
|
// were changed directly by vars, not comands (like place)
|
|
// - after execing cfg or sth
|
|
//
|
|
void HUD_Recalculate(void)
|
|
{
|
|
hud_t *hud = hud_huds;
|
|
|
|
while (hud)
|
|
{
|
|
HUD_FindPlace(hud);
|
|
HUD_FindAlignX(hud);
|
|
HUD_FindAlignY(hud);
|
|
|
|
hud = hud->next;
|
|
}
|
|
}
|
|
void HUD_Recalculate_f(void)
|
|
{
|
|
HUD_Recalculate();
|
|
}
|
|
|
|
//
|
|
// Initialize HUD.
|
|
//
|
|
void HUD_Init(void)
|
|
{
|
|
// from hud.c, doesn't suit anywhere
|
|
void HUD_Inputlag_hit_f(void);
|
|
|
|
// Commands.
|
|
Cmd_AddCommand ("show", HUD_Show_f);
|
|
Cmd_AddCommand ("hide", HUD_Hide_f);
|
|
Cmd_AddCommand ("move", HUD_Move_f);
|
|
Cmd_AddCommand ("place", HUD_Place_f);
|
|
Cmd_AddCommand ("reset", HUD_Reset_f);
|
|
Cmd_AddCommand ("order", HUD_Order_f);
|
|
Cmd_AddCommand ("togglehud", HUD_Toggle_f);
|
|
Cmd_AddCommand ("align", HUD_Align_f);
|
|
Cmd_AddCommand ("hud_recalculate", HUD_Recalculate_f);
|
|
|
|
// Register the hud items.
|
|
CommonDraw_Init();
|
|
|
|
// Sort the elements.
|
|
HUD_Sort();
|
|
}
|
|
|
|
//
|
|
// Calculate frame extents.
|
|
//
|
|
void HUD_CalcFrameExtents(hud_t *hud, int width, int height, // In.
|
|
int *frame_left, int *frame_right, int *frame_top, int *frame_bottom) // Out.
|
|
{
|
|
if ((hud->flags & HUD_NO_GROW) && hud->frame->value != 2)
|
|
{
|
|
*frame_left = *frame_right = *frame_top = *frame_bottom = 0;
|
|
return;
|
|
}
|
|
|
|
if (hud->frame->value == 2) // Treat text box separately.
|
|
{
|
|
int ax = (width % 16);
|
|
int ay = (height % 8);
|
|
*frame_left = 8 + ax / 2;
|
|
*frame_top = 8 + ay / 2;
|
|
*frame_right = 8 + ax - ax / 2;
|
|
*frame_bottom = 8 + ay - ay / 2;
|
|
}
|
|
else if (hud->frame->value > 0 && hud->frame->value <= 1)
|
|
{
|
|
int frame_x, frame_y;
|
|
frame_x = 2;
|
|
frame_y = 2;
|
|
|
|
if (width > 8)
|
|
{
|
|
frame_x <<= 1;
|
|
}
|
|
|
|
if (height > 8)
|
|
{
|
|
frame_y <<= 1;
|
|
}
|
|
|
|
*frame_left = frame_x;
|
|
*frame_right = frame_x;
|
|
*frame_top = frame_y;
|
|
*frame_bottom = frame_y;
|
|
}
|
|
else
|
|
{
|
|
// No frame at all.
|
|
*frame_left = *frame_right = *frame_top = *frame_bottom = 0;
|
|
}
|
|
}
|
|
|
|
void HUD_OnChangeFrameColor(cvar_t *var, char *oldval)
|
|
{
|
|
// Converts "red" into "255 0 0", etc. or returns input as it was.
|
|
char *new_color = ColorNameToRGBString (var->string);
|
|
char buf[256], buf2[128];
|
|
size_t hudname_len;
|
|
hud_t* hud_elem;
|
|
byte* b_colors;
|
|
|
|
hudname_len = min (sizeof (buf), strlen (var->name) - strlen ("_frame_color") - strlen ("hud_") + 1);
|
|
strlcpy (buf, var->name + 4, hudname_len);
|
|
hud_elem = HUD_Find (buf);
|
|
|
|
strlcpy(buf2,new_color,sizeof(buf2));
|
|
b_colors = StringToRGB (buf2);
|
|
|
|
memcpy (hud_elem->frame_color_cache, b_colors, sizeof (byte) * 3);
|
|
}
|
|
|
|
//
|
|
// Draw frame for HUD element.
|
|
//
|
|
void HUD_DrawFrame(hud_t *hud, int x, int y, int width, int height)
|
|
{
|
|
if (!hud->frame->value)
|
|
return;
|
|
|
|
if (hud->frame->value > 0 && hud->frame->value <= 1)
|
|
{
|
|
hud->frame_color_cache[3] = (byte)(255 * hud->frame->value);
|
|
|
|
Draw_AlphaFillRGB(x, y, width, height, hud->frame_color_cache[0], hud->frame_color_cache[1], hud->frame_color_cache[2], hud->frame_color_cache[3]);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
switch ((int)(hud->frame->value))
|
|
{
|
|
case 2: // Text box.
|
|
Draw_TextBox(x, y, width/8-2, height/8-2);
|
|
break;
|
|
default: // More will probably come.
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Calculate element placement.
|
|
//
|
|
qbool HUD_PrepareDrawByName(char *name, int width, int height, // In.
|
|
int *ret_x, int *ret_y) // Out (Position).
|
|
{
|
|
hud_t *hud = HUD_Find(name);
|
|
if (hud == NULL)
|
|
{
|
|
return false; // error in C code
|
|
}
|
|
|
|
return HUD_PrepareDraw(hud, width, height, ret_x, ret_y);
|
|
}
|
|
|
|
//
|
|
// Calculate object extents and draws frame if needed.
|
|
//
|
|
qbool HUD_PrepareDraw(hud_t *hud, int width, int height, // In.
|
|
int *ret_x, int *ret_y) // Out (Position).
|
|
{
|
|
extern vrect_t scr_vrect;
|
|
int x, y;
|
|
int frame_left, frame_right, frame_top, frame_bottom; // Frame left, right, top and bottom.
|
|
int area_x, area_y, area_width, area_height; // Area coordinates & sizes to align.
|
|
int bounds_x, bounds_y, bounds_width, bounds_height; // Bounds to draw within.
|
|
|
|
// Don't show the hud element.
|
|
if (cls.state < hud->min_state || !hud->show->value)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
HUD_CalcFrameExtents(hud, width, height, &frame_left, &frame_right, &frame_top, &frame_bottom);
|
|
|
|
width += frame_left + frame_right;
|
|
height += frame_top + frame_bottom;
|
|
|
|
//
|
|
// Placement.
|
|
//
|
|
switch (hud->place_num)
|
|
{
|
|
default:
|
|
case HUD_PLACE_SCREEN:
|
|
bounds_x = bounds_y = 0;
|
|
bounds_width = vid.width;
|
|
bounds_height = vid.height;
|
|
break;
|
|
case HUD_PLACE_TOP: // Top = screen - sbar
|
|
bounds_x = bounds_y = 0;
|
|
bounds_width = vid.width;
|
|
bounds_height = vid.height - sb_lines;
|
|
break;
|
|
case HUD_PLACE_VIEW:
|
|
bounds_x = scr_vrect.x;
|
|
bounds_y = scr_vrect.y;
|
|
bounds_width = scr_vrect.width;
|
|
bounds_height = scr_vrect.height;
|
|
break;
|
|
case HUD_PLACE_SBAR:
|
|
bounds_x = 0;
|
|
bounds_y = vid.height - sb_lines;
|
|
bounds_width = sbar_last_width;
|
|
bounds_height = sb_lines;
|
|
break;
|
|
case HUD_PLACE_IBAR:
|
|
bounds_width = sbar_last_width;
|
|
bounds_height = max(sb_lines - SBAR_HEIGHT, 0);
|
|
bounds_x = 0;
|
|
bounds_y = vid.height - sb_lines;
|
|
break;
|
|
case HUD_PLACE_HBAR:
|
|
bounds_width = sbar_last_width;
|
|
bounds_height = min(SBAR_HEIGHT, sb_lines);
|
|
bounds_x = 0;
|
|
bounds_y = vid.height - bounds_height;
|
|
break;
|
|
case HUD_PLACE_SFREE:
|
|
bounds_x = sbar_last_width;
|
|
bounds_y = vid.height - sb_lines;
|
|
bounds_width = vid.width - sbar_last_width;
|
|
bounds_height = sb_lines;
|
|
break;
|
|
case HUD_PLACE_IFREE:
|
|
bounds_width = vid.width - sbar_last_width;
|
|
bounds_height = max(sb_lines - SBAR_HEIGHT, 0);
|
|
bounds_x = sbar_last_width;
|
|
bounds_y = vid.height - sb_lines;
|
|
break;
|
|
case HUD_PLACE_HFREE:
|
|
bounds_width = vid.width - sbar_last_width;
|
|
bounds_height = min(SBAR_HEIGHT, sb_lines);
|
|
bounds_x = sbar_last_width;
|
|
bounds_y = vid.height - bounds_height;
|
|
break;
|
|
}
|
|
|
|
if (hud->place_hud == NULL)
|
|
{
|
|
// Accepted boundaries are our area.
|
|
area_x = bounds_x;
|
|
area_y = bounds_y;
|
|
area_width = bounds_width;
|
|
area_height = bounds_height;
|
|
}
|
|
else
|
|
{
|
|
// Out area is our parent area.
|
|
area_x = hud->place_hud->lx;
|
|
area_y = hud->place_hud->ly;
|
|
area_width = hud->place_hud->lw;
|
|
area_height = hud->place_hud->lh;
|
|
|
|
if (hud->place_outside)
|
|
{
|
|
area_x -= hud->place_hud->al;
|
|
area_y -= hud->place_hud->at;
|
|
area_width += hud->place_hud->al + hud->place_hud->ar;
|
|
area_height += hud->place_hud->at + hud->place_hud->ab;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Horizontal pos.
|
|
//
|
|
switch (hud->align_x_num)
|
|
{
|
|
default:
|
|
case HUD_ALIGN_LEFT:
|
|
x = area_x;
|
|
break;
|
|
case HUD_ALIGN_CENTER:
|
|
x = area_x + (area_width - width) / 2;
|
|
break;
|
|
case HUD_ALIGN_RIGHT:
|
|
x = area_x + area_width - width;
|
|
break;
|
|
case HUD_ALIGN_BEFORE:
|
|
x = area_x - width;
|
|
break;
|
|
case HUD_ALIGN_AFTER:
|
|
x = area_x + area_width;
|
|
break;
|
|
}
|
|
|
|
x += hud->pos_x->value;
|
|
|
|
//
|
|
// Vertical pos.
|
|
//
|
|
switch (hud->align_y_num)
|
|
{
|
|
default:
|
|
case HUD_ALIGN_TOP:
|
|
y = area_y;
|
|
break;
|
|
case HUD_ALIGN_CENTER:
|
|
y = area_y + (area_height - height) / 2;
|
|
break;
|
|
case HUD_ALIGN_BOTTOM:
|
|
y = area_y + area_height - height;
|
|
break;
|
|
case HUD_ALIGN_BEFORE:
|
|
y = area_y - height;
|
|
break;
|
|
case HUD_ALIGN_AFTER:
|
|
y = area_y + area_height;
|
|
break;
|
|
case HUD_ALIGN_CONSOLE:
|
|
y = max(area_y, scr_con_current);
|
|
break;
|
|
}
|
|
|
|
y += hud->pos_y->value;
|
|
|
|
// Draw frame.
|
|
HUD_DrawFrame(hud, x, y, width, height);
|
|
|
|
// Assign values.
|
|
*ret_x = x + frame_left;
|
|
*ret_y = y + frame_top;
|
|
|
|
// Remember values for children.
|
|
hud->lx = x + frame_left;
|
|
hud->ly = y + frame_top;
|
|
hud->lw = width - frame_left - frame_right;
|
|
hud->lh = height - frame_top - frame_bottom;
|
|
hud->al = frame_left;
|
|
hud->ar = frame_right;
|
|
hud->at = frame_top;
|
|
hud->ab = frame_bottom;
|
|
|
|
// Check if we're supposed to draw the entire item or just the outline/frame.
|
|
// (If we're in hud editor align/place mode)
|
|
if(!HUD_Editor_ConfirmDraw(hud))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Remember drawing sequence.
|
|
hud->last_draw_sequence = host_screenupdatecount;
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// Creates a HUD variable based on a name.
|
|
//
|
|
cvar_t * HUD_CreateVar(char *hud_name, char *subvar, char *value)
|
|
{
|
|
char buf[128];
|
|
|
|
snprintf (buf, sizeof (buf), "hud_%s_%s", hud_name, subvar);
|
|
|
|
return pCvar_GetNVFDG(buf, value, 0, NULL, "ezhud");
|
|
}
|
|
|
|
//
|
|
// Onchange for when z-order changes for a hud element. Resorts the elements.
|
|
//
|
|
void HUD_OnChangeOrder(cvar_t *var, char *val)
|
|
{
|
|
doreorder = true;
|
|
}
|
|
|
|
//
|
|
// Registers a new HUD element to the list of HUD elements.
|
|
//
|
|
hud_t * HUD_Register(char *name, char *var_alias, char *description,
|
|
int flags, cactive_t min_state, int draw_order,
|
|
hud_func_type draw_func,
|
|
char *show, char *place, char *align_x, char *align_y,
|
|
char *pos_x, char *pos_y, char *frame, char *frame_color,
|
|
char *item_opacity,
|
|
char *params, ...)
|
|
{
|
|
int i;
|
|
va_list argptr;
|
|
hud_t *hud;
|
|
char *subvar;
|
|
|
|
// We want to include Frame, frame_color, item_opacity in the list of
|
|
// available cvar's for the user also. If any additional cvars that
|
|
// common for all hud elements are added this needs to be increased.
|
|
int num_params = 3;
|
|
|
|
// Allocate room for the HUD.
|
|
hud = (hud_t *) Q_malloc(sizeof(hud_t));
|
|
memset(hud, 0, sizeof(hud_t));
|
|
hud->next = hud_huds;
|
|
hud_huds = hud;
|
|
hud->min_state = min_state;
|
|
hud->draw_func = draw_func;
|
|
|
|
// Name.
|
|
hud->name = (char *) Q_malloc(strlen(name)+1);
|
|
strcpy(hud->name, name);
|
|
|
|
// Description.
|
|
hud->description = (char *) Q_malloc(strlen(description)+1);
|
|
strcpy(hud->description, description);
|
|
|
|
// Count the number of params.
|
|
subvar = params;
|
|
va_start (argptr, params);
|
|
while(subvar)
|
|
{
|
|
num_params++;
|
|
subvar = va_arg(argptr, char *);
|
|
}
|
|
va_end (argptr);
|
|
|
|
// Allocate the params array.
|
|
hud->params = Q_calloc(num_params, sizeof(cvar_t *));
|
|
|
|
// Set flags.
|
|
hud->flags = flags;
|
|
|
|
Cmd_AddCommand(name, HUD_Func_f);
|
|
|
|
//
|
|
// Create standard variables.
|
|
//
|
|
|
|
//
|
|
// Ordering
|
|
//
|
|
{
|
|
char order[18];
|
|
snprintf (order, sizeof(order), "%d", draw_order);
|
|
hud->order = HUD_CreateVar(name, "order", order);
|
|
hud->order->callback = HUD_OnChangeOrder;
|
|
}
|
|
|
|
//
|
|
// Place.
|
|
//
|
|
hud->place = HUD_CreateVar(name, "place", place);
|
|
i = HUD_FindPlace(hud);
|
|
if (i == 0)
|
|
{
|
|
// Probably parent should be registered earlier.
|
|
// (This doesn't matter, since we'll re-place all elements after
|
|
// all the elements have been registered)
|
|
hud->place_num = 0;
|
|
hud->place_hud = NULL;
|
|
}
|
|
|
|
//
|
|
// Show.
|
|
//
|
|
if (show)
|
|
{
|
|
hud->show = HUD_CreateVar(name, "show", show);
|
|
|
|
if (flags & HUD_PLUSMINUS)
|
|
{
|
|
// Add plus and minus commands.
|
|
Cmd_AddCommand(Q_strdup(va("+hud_%s", name)), HUD_Plus_f);
|
|
Cmd_AddCommand(Q_strdup(va("-hud_%s", name)), HUD_Minus_f);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hud->flags |= HUD_NO_SHOW;
|
|
}
|
|
|
|
//
|
|
// X align & pos.
|
|
//
|
|
if (pos_x && align_x)
|
|
{
|
|
hud->pos_x = HUD_CreateVar(name, "pos_x", pos_x);
|
|
hud->align_x = HUD_CreateVar(name, "align_x", align_x);
|
|
}
|
|
else
|
|
{
|
|
hud->flags |= HUD_NO_POS_X;
|
|
}
|
|
|
|
//
|
|
// Y align & pos.
|
|
//
|
|
if (pos_y && align_y)
|
|
{
|
|
hud->pos_y = HUD_CreateVar(name, "pos_y", pos_y);
|
|
hud->align_y = HUD_CreateVar(name, "align_y", align_y);
|
|
}
|
|
else
|
|
{
|
|
hud->flags |= HUD_NO_POS_Y;
|
|
}
|
|
|
|
//
|
|
// Frame.
|
|
//
|
|
if (frame)
|
|
{
|
|
hud->frame = HUD_CreateVar(name, "frame", frame);
|
|
hud->params[hud->num_params++] = hud->frame;
|
|
|
|
hud->frame_color = HUD_CreateVar(name, "frame_color", frame_color);
|
|
hud->frame_color->callback = HUD_OnChangeFrameColor;
|
|
hud->params[hud->num_params++] = hud->frame_color;
|
|
}
|
|
else
|
|
{
|
|
hud->flags |= HUD_NO_FRAME;
|
|
}
|
|
|
|
//
|
|
// Item Opacity.
|
|
//
|
|
{
|
|
hud->opacity = HUD_CreateVar(name, "item_opacity", (item_opacity) ? item_opacity : "0.99");
|
|
hud->flags |= HUD_OPACITY;
|
|
hud->params[hud->num_params++] = hud->opacity;
|
|
}
|
|
|
|
//
|
|
// Create parameters.
|
|
//
|
|
subvar = params;
|
|
va_start (argptr, params);
|
|
|
|
while (subvar)
|
|
{
|
|
char *value = va_arg(argptr, char *);
|
|
if (value == NULL || hud->num_params >= HUD_MAX_PARAMS || hud->num_params >= num_params)
|
|
{
|
|
Sys_Error("HUD_Register: HUD_MAX_PARAMS overflow");
|
|
}
|
|
|
|
hud->params[hud->num_params] = HUD_CreateVar(name, subvar, value);
|
|
hud->num_params ++;
|
|
subvar = va_arg(argptr, char *);
|
|
}
|
|
|
|
va_end (argptr);
|
|
|
|
return hud;
|
|
}
|
|
|
|
void HUD_ParamsCleanup(void)
|
|
{
|
|
int i = 0;
|
|
hud_t *hud = hud_huds;
|
|
|
|
while (hud)
|
|
{
|
|
/* for (i=0; i < hud->num_params; i++)
|
|
{
|
|
Cvar_Delete(hud->params[i]->name);
|
|
}
|
|
*/
|
|
Q_free(hud->params);
|
|
|
|
hud = hud->next;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Find element in list.
|
|
//
|
|
hud_t * HUD_Find(char *name)
|
|
{
|
|
hud_t *hud = hud_huds;
|
|
|
|
while (hud)
|
|
{
|
|
if (!strcasecmp(hud->name, name))
|
|
{
|
|
return hud;
|
|
}
|
|
|
|
hud = hud->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Retrieve hud cvar.
|
|
//
|
|
cvar_t *HUD_FindVar(hud_t *hud, char *subvar)
|
|
{
|
|
int i;
|
|
char buf[128];
|
|
|
|
snprintf(buf, sizeof(buf), "hud_%s_%s", hud->name, subvar);
|
|
|
|
for (i=0; i < hud->num_params; i++)
|
|
{
|
|
if (!strcmp(buf, hud->params[i]->name))
|
|
{
|
|
return hud->params[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Draws single HUD element.
|
|
//
|
|
void HUD_DrawObject(hud_t *hud)
|
|
{
|
|
extern qbool sb_showscores, sb_showteamscores;
|
|
|
|
// Already tried to draw this frame.
|
|
if (hud->last_try_sequence == host_screenupdatecount)
|
|
{
|
|
return;
|
|
}
|
|
|
|
hud->last_try_sequence = host_screenupdatecount;
|
|
|
|
// Check if we should draw this.
|
|
if (!hud->show->value)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (cls.state < hud->min_state)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (cl.intermission == 1 && !(hud->flags & HUD_ON_INTERMISSION))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (cl.intermission == 2 && !(hud->flags & HUD_ON_FINALE))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ((sb_showscores || sb_showteamscores) && !(hud->flags & HUD_ON_SCORES))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (hud->place_hud)
|
|
{
|
|
// Parent should be drawn it should be first.
|
|
HUD_DrawObject(hud->place_hud);
|
|
|
|
// If parent was not drawn, we refuse to draw too
|
|
if (hud->place_hud->last_draw_sequence < host_screenupdatecount)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Let the HUD element draw itself - updates last_draw_sequence itself.
|
|
//
|
|
Draw_SetOverallAlpha(hud->opacity->value);
|
|
hud->draw_func(hud);
|
|
Draw_SetOverallAlpha(1.0);
|
|
|
|
// last_draw_sequence is update by HUD_PrepareDraw
|
|
// if object was succesfully drawn (wasn't outside area etc..)
|
|
}
|
|
|
|
//
|
|
// Draw all active elements.
|
|
//
|
|
void HUD_Draw(void)
|
|
{
|
|
hud_t *hud;
|
|
|
|
if (doreorder)
|
|
{
|
|
doreorder = false;
|
|
HUD_ReorderChildren();
|
|
HUD_Sort();
|
|
}
|
|
|
|
// Only draw the hud once in multiview.
|
|
/* if (cl_multiview.integer && cls.mvdplayback)
|
|
{
|
|
if (CURRVIEW != 1)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
*/
|
|
if (mvd_autohud->ival && !autohud_loaded)
|
|
{
|
|
HUD_AutoLoad_MVD(mvd_autohud->ival);
|
|
Com_DPrintf("Loading AUTOHUD...\n");
|
|
autohud_loaded = true;
|
|
}
|
|
|
|
/* if (scr_newHud->value == 0)
|
|
{
|
|
return;
|
|
}
|
|
*/
|
|
hud = hud_huds;
|
|
|
|
HUD_BeforeDraw();
|
|
|
|
while (hud)
|
|
{
|
|
// Draw.
|
|
HUD_DrawObject(hud);
|
|
|
|
// Go to next.
|
|
hud = hud->next;
|
|
}
|
|
|
|
HUD_AfterDraw();
|
|
}
|
|
|
|
//
|
|
// Compares two hud elements.
|
|
//
|
|
int HUD_OrderFunc(const void * p_h1, const void * p_h2)
|
|
{
|
|
const hud_t *h1 = *((hud_t **)p_h1);
|
|
const hud_t *h2 = *((hud_t **)p_h2);
|
|
|
|
return (int)h1->order->value - (int)h2->order->value;
|
|
}
|
|
|
|
//
|
|
// Last phase of initialization.
|
|
//
|
|
void HUD_Sort(void)
|
|
{
|
|
// Sort elements based on their draw order.
|
|
int i;
|
|
hud_t *huds[MAX_HUD_ELEMENTS];
|
|
int count = 0;
|
|
hud_t *hud;
|
|
|
|
// Copy to table.
|
|
hud = hud_huds;
|
|
while (hud)
|
|
{
|
|
huds[count++] = hud;
|
|
hud = hud->next;
|
|
}
|
|
|
|
if (count <= 0)
|
|
return;
|
|
|
|
// Sort table.
|
|
qsort(huds, count, sizeof(huds[0]), HUD_OrderFunc);
|
|
|
|
// Back to list.
|
|
hud_huds = huds[0];
|
|
hud = hud_huds;
|
|
hud->next = NULL;
|
|
for (i=1; i < count; i++)
|
|
{
|
|
hud->next = huds[i];
|
|
hud = hud->next;
|
|
hud->next = NULL;
|
|
}
|
|
|
|
// Recalculate elements so vars are parsed.
|
|
HUD_Recalculate();
|
|
}
|