📄 ui_shared.c
字号:
menuDef_t *Menus_FindByName(const char *p) {
int i;
for (i = 0; i < menuCount; i++) {
if (Q_stricmp(Menus[i].window.name, p) == 0) {
return &Menus[i];
}
}
return NULL;
}
void Menus_ShowByName(const char *p) {
menuDef_t *menu = Menus_FindByName(p);
if (menu) {
Menus_Activate(menu);
}
}
void Menus_OpenByName(const char *p) {
Menus_ActivateByName(p);
}
static void Menu_RunCloseScript(menuDef_t *menu) {
if (menu && menu->window.flags & WINDOW_VISIBLE && menu->onClose) {
itemDef_t item;
item.parent = menu;
Item_RunScript(&item, menu->onClose);
}
}
void Menus_CloseByName(const char *p) {
menuDef_t *menu = Menus_FindByName(p);
if (menu != NULL) {
Menu_RunCloseScript(menu);
menu->window.flags &= ~(WINDOW_VISIBLE | WINDOW_HASFOCUS);
}
}
void Menus_CloseAll() {
int i;
for (i = 0; i < menuCount; i++) {
Menu_RunCloseScript(&Menus[i]);
Menus[i].window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
}
}
void Script_Show(itemDef_t *item, char **args) {
const char *name;
if (String_Parse(args, &name)) {
Menu_ShowItemByName(item->parent, name, qtrue);
}
}
void Script_Hide(itemDef_t *item, char **args) {
const char *name;
if (String_Parse(args, &name)) {
Menu_ShowItemByName(item->parent, name, qfalse);
}
}
void Script_FadeIn(itemDef_t *item, char **args) {
const char *name;
if (String_Parse(args, &name)) {
Menu_FadeItemByName(item->parent, name, qfalse);
}
}
void Script_FadeOut(itemDef_t *item, char **args) {
const char *name;
if (String_Parse(args, &name)) {
Menu_FadeItemByName(item->parent, name, qtrue);
}
}
void Script_Open(itemDef_t *item, char **args) {
const char *name;
if (String_Parse(args, &name)) {
Menus_OpenByName(name);
}
}
void Script_ConditionalOpen(itemDef_t *item, char **args) {
const char *cvar;
const char *name1;
const char *name2;
float val;
if ( String_Parse(args, &cvar) && String_Parse(args, &name1) && String_Parse(args, &name2) ) {
val = DC->getCVarValue( cvar );
if ( val == 0.f ) {
Menus_OpenByName(name2);
} else {
Menus_OpenByName(name1);
}
}
}
void Script_Close(itemDef_t *item, char **args) {
const char *name;
if (String_Parse(args, &name)) {
Menus_CloseByName(name);
}
}
void Menu_TransitionItemByName(menuDef_t *menu, const char *p, rectDef_t rectFrom, rectDef_t rectTo, int time, float amt) {
itemDef_t *item;
int i;
int count = Menu_ItemsMatchingGroup(menu, p);
for (i = 0; i < count; i++) {
item = Menu_GetMatchingItemByNumber(menu, i, p);
if (item != NULL) {
item->window.flags |= (WINDOW_INTRANSITION | WINDOW_VISIBLE);
item->window.offsetTime = time;
memcpy(&item->window.rectClient, &rectFrom, sizeof(rectDef_t));
memcpy(&item->window.rectEffects, &rectTo, sizeof(rectDef_t));
item->window.rectEffects2.x = abs(rectTo.x - rectFrom.x) / amt;
item->window.rectEffects2.y = abs(rectTo.y - rectFrom.y) / amt;
item->window.rectEffects2.w = abs(rectTo.w - rectFrom.w) / amt;
item->window.rectEffects2.h = abs(rectTo.h - rectFrom.h) / amt;
Item_UpdatePosition(item);
}
}
}
void Script_Transition(itemDef_t *item, char **args) {
const char *name;
rectDef_t rectFrom, rectTo;
int time;
float amt;
if (String_Parse(args, &name)) {
if ( Rect_Parse(args, &rectFrom) && Rect_Parse(args, &rectTo) && Int_Parse(args, &time) && Float_Parse(args, &amt)) {
Menu_TransitionItemByName(item->parent, name, rectFrom, rectTo, time, amt);
}
}
}
void Menu_OrbitItemByName(menuDef_t *menu, const char *p, float x, float y, float cx, float cy, int time) {
itemDef_t *item;
int i;
int count = Menu_ItemsMatchingGroup(menu, p);
for (i = 0; i < count; i++) {
item = Menu_GetMatchingItemByNumber(menu, i, p);
if (item != NULL) {
item->window.flags |= (WINDOW_ORBITING | WINDOW_VISIBLE);
item->window.offsetTime = time;
item->window.rectEffects.x = cx;
item->window.rectEffects.y = cy;
item->window.rectClient.x = x;
item->window.rectClient.y = y;
Item_UpdatePosition(item);
}
}
}
void Script_Orbit(itemDef_t *item, char **args) {
const char *name;
float cx, cy, x, y;
int time;
if (String_Parse(args, &name)) {
if ( Float_Parse(args, &x) && Float_Parse(args, &y) && Float_Parse(args, &cx) && Float_Parse(args, &cy) && Int_Parse(args, &time) ) {
Menu_OrbitItemByName(item->parent, name, x, y, cx, cy, time);
}
}
}
void Script_SetFocus(itemDef_t *item, char **args) {
const char *name;
itemDef_t *focusItem;
if (String_Parse(args, &name)) {
focusItem = Menu_FindItemByName(item->parent, name);
if (focusItem && !(focusItem->window.flags & WINDOW_DECORATION) && !(focusItem->window.flags & WINDOW_HASFOCUS)) {
Menu_ClearFocus(item->parent);
focusItem->window.flags |= WINDOW_HASFOCUS;
if (focusItem->onFocus) {
Item_RunScript(focusItem, focusItem->onFocus);
}
if (DC->Assets.itemFocusSound) {
DC->startLocalSound( DC->Assets.itemFocusSound, CHAN_LOCAL_SOUND );
}
}
}
}
void Script_SetPlayerModel(itemDef_t *item, char **args) {
const char *name;
if (String_Parse(args, &name)) {
DC->setCVar("team_model", name);
}
}
void Script_SetPlayerHead(itemDef_t *item, char **args) {
const char *name;
if (String_Parse(args, &name)) {
DC->setCVar("team_headmodel", name);
}
}
void Script_SetCvar(itemDef_t *item, char **args) {
const char *cvar, *val;
if (String_Parse(args, &cvar) && String_Parse(args, &val)) {
DC->setCVar(cvar, val);
}
}
void Script_Exec(itemDef_t *item, char **args) {
const char *val;
if (String_Parse(args, &val)) {
DC->executeText(EXEC_APPEND, va("%s ; ", val));
}
}
void Script_Play(itemDef_t *item, char **args) {
const char *val;
if (String_Parse(args, &val)) {
DC->startLocalSound(DC->registerSound(val, qfalse), CHAN_LOCAL_SOUND);
}
}
void Script_playLooped(itemDef_t *item, char **args) {
const char *val;
if (String_Parse(args, &val)) {
DC->stopBackgroundTrack();
DC->startBackgroundTrack(val, val);
}
}
commandDef_t commandList[] =
{
{"fadein", &Script_FadeIn}, // group/name
{"fadeout", &Script_FadeOut}, // group/name
{"show", &Script_Show}, // group/name
{"hide", &Script_Hide}, // group/name
{"setcolor", &Script_SetColor}, // works on this
{"open", &Script_Open}, // menu
{"conditionalopen", &Script_ConditionalOpen}, // menu
{"close", &Script_Close}, // menu
{"setasset", &Script_SetAsset}, // works on this
{"setbackground", &Script_SetBackground}, // works on this
{"setitemcolor", &Script_SetItemColor}, // group/name
{"setteamcolor", &Script_SetTeamColor}, // sets this background color to team color
{"setfocus", &Script_SetFocus}, // sets this background color to team color
{"setplayermodel", &Script_SetPlayerModel}, // sets this background color to team color
{"setplayerhead", &Script_SetPlayerHead}, // sets this background color to team color
{"transition", &Script_Transition}, // group/name
{"setcvar", &Script_SetCvar}, // group/name
{"exec", &Script_Exec}, // group/name
{"play", &Script_Play}, // group/name
{"playlooped", &Script_playLooped}, // group/name
{"orbit", &Script_Orbit} // group/name
};
int scriptCommandCount = sizeof(commandList) / sizeof(commandDef_t);
void Item_RunScript(itemDef_t *item, const char *s) {
char script[1024], *p;
int i;
qboolean bRan;
memset(script, 0, sizeof(script));
if (item && s && s[0]) {
Q_strcat(script, 1024, s);
p = script;
while (1) {
const char *command;
// expect command then arguments, ; ends command, NULL ends script
if (!String_Parse(&p, &command)) {
return;
}
if (command[0] == ';' && command[1] == '\0') {
continue;
}
bRan = qfalse;
for (i = 0; i < scriptCommandCount; i++) {
if (Q_stricmp(command, commandList[i].name) == 0) {
(commandList[i].handler(item, &p));
bRan = qtrue;
break;
}
}
// not in our auto list, pass to handler
if (!bRan) {
DC->runScript(&p);
}
}
}
}
qboolean Item_EnableShowViaCvar(itemDef_t *item, int flag) {
char script[1024], *p;
memset(script, 0, sizeof(script));
if (item && item->enableCvar && *item->enableCvar && item->cvarTest && *item->cvarTest) {
char buff[1024];
DC->getCVarString(item->cvarTest, buff, sizeof(buff));
Q_strcat(script, 1024, item->enableCvar);
p = script;
while (1) {
const char *val;
// expect value then ; or NULL, NULL ends list
if (!String_Parse(&p, &val)) {
return (item->cvarFlags & flag) ? qfalse : qtrue;
}
if (val[0] == ';' && val[1] == '\0') {
continue;
}
// enable it if any of the values are true
if (item->cvarFlags & flag) {
if (Q_stricmp(buff, val) == 0) {
return qtrue;
}
} else {
// disable it if any of the values are true
if (Q_stricmp(buff, val) == 0) {
return qfalse;
}
}
}
return (item->cvarFlags & flag) ? qfalse : qtrue;
}
return qtrue;
}
// will optionaly set focus to this item
qboolean Item_SetFocus(itemDef_t *item, float x, float y) {
int i;
itemDef_t *oldFocus;
sfxHandle_t *sfx = &DC->Assets.itemFocusSound;
qboolean playSound = qfalse;
menuDef_t *parent; // bk001206: = (menuDef_t*)item->parent;
// sanity check, non-null, not a decoration and does not already have the focus
if (item == NULL || item->window.flags & WINDOW_DECORATION || item->window.flags & WINDOW_HASFOCUS || !(item->window.flags & WINDOW_VISIBLE)) {
return qfalse;
}
// bk001206 - this can be NULL.
parent = (menuDef_t*)item->parent;
// items can be enabled and disabled based on cvars
if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
return qfalse;
}
if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(item, CVAR_SHOW)) {
return qfalse;
}
oldFocus = Menu_ClearFocus(item->parent);
if (item->type == ITEM_TYPE_TEXT) {
rectDef_t r;
r = item->textRect;
r.y -= r.h;
if (Rect_ContainsPoint(&r, x, y)) {
item->window.flags |= WINDOW_HASFOCUS;
if (item->focusSound) {
sfx = &item->focusSound;
}
playSound = qtrue;
} else {
if (oldFocus) {
oldFocus->window.flags |= WINDOW_HASFOCUS;
if (oldFocus->onFocus) {
Item_RunScript(oldFocus, oldFocus->onFocus);
}
}
}
} else {
item->window.flags |= WINDOW_HASFOCUS;
if (item->onFocus) {
Item_RunScript(item, item->onFocus);
}
if (item->focusSound) {
sfx = &item->focusSound;
}
playSound = qtrue;
}
if (playSound && sfx) {
DC->startLocalSound( *sfx, CHAN_LOCAL_SOUND );
}
for (i = 0; i < parent->itemCount; i++) {
if (parent->items[i] == item) {
parent->cursorItem = i;
break;
}
}
return qtrue;
}
int Item_ListBox_MaxScroll(itemDef_t *item) {
listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
int count = DC->feederCount(item->special);
int max;
if (item->window.flags & WINDOW_HORIZONTAL) {
max = count - (item->window.rect.w / listPtr->elementWidth) + 1;
}
else {
max = count - (item->window.rect.h / listPtr->elementHeight) + 1;
}
if (max < 0) {
return 0;
}
return max;
}
int Item_ListBox_ThumbPosition(itemDef_t *item) {
float max, pos, size;
listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
max = Item_ListBox_MaxScroll(item);
if (item->window.flags & WINDOW_HORIZONTAL) {
size = item->window.rect.w - (SCROLLBAR_SIZE * 2) - 2;
if (max > 0) {
pos = (size-SCROLLBAR_SIZE) / (float) max;
} else {
pos = 0;
}
pos *= listPtr->startPos;
return item->window.rect.x + 1 + SCROLLBAR_SIZE + pos;
}
else {
size = item->window.rect.h - (SCROLLBAR_SIZE * 2) - 2;
if (max > 0) {
pos = (size-SCROLLBAR_SIZE) / (float) max;
} else {
pos = 0;
}
pos *= listPtr->startPos;
return item->window.rect.y + 1 + SCROLLBAR_SIZE + pos;
}
}
int Item_ListBox_ThumbDrawPosition(itemDef_t *item) {
int min, max;
if (itemCapture == item) {
if (item->window.flags & WINDOW_HORIZONTAL) {
min = item->window.rect.x + SCROLLBAR_SIZE + 1;
max = item->window.rect.x + item->window.rect.w - 2*SCROLLBAR_SIZE - 1;
if (DC->cursorx >= min + SCROLLBAR_SIZE/2 && DC->cursorx <= max + SCROLLBAR_SIZE/2) {
return DC->cursorx - SCROLLBAR_SIZE/2;
}
else {
return Item_ListBox_ThumbPosition(item);
}
}
else {
min = item->window.rect.y + SCROLLBAR_SIZE + 1;
max = item->window.rect.y + item->window.rect.h - 2*SCROLLBAR_SIZE - 1;
if (DC->cursory >= min + SCROLLBAR_SIZE/2 && DC->cursory <= max + SCROLLBAR_SIZE/2) {
return DC->cursory - SCROLLBAR_SIZE/2;
}
else {
return Item_ListBox_ThumbPosition(item);
}
}
}
else {
return Item_ListBox_ThumbPosition(item);
}
}
float Item_Slider_ThumbPosition(itemDef_t *item) {
float value, range, x;
editFieldDef_t *editDef = item->typeData;
if (item->text) {
x = item->textRect.x + item->textRect.w + 8;
} else {
x = item->window.rect.x;
}
if (editDef == NULL && item->cvar) {
return x;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -