4 /*cvar_t ui_showname = {0, "ui_showname", "0"};
6 #define ITEM_CLICKABLE 1
7 #define ITEM_DRAWABLE 2
15 #define UI_MOUSEBUTTONS 3
17 static int ui_alive, ui_active;
18 static float ui_mouse_x, ui_mouse_y;
19 static int ui_mousebutton[UI_MOUSEBUTTONS], ui_mouseclick;
20 static int ui_keyui, ui_keyitem;
21 static ui_item_t *ui_keyrealitem;
23 static ui_t *ui_list[MAX_UI_COUNT];
25 static void ui_start(void)
27 ui_mouse_x = vid.conwidth * 0.5;
28 ui_mouse_y = vid.conheight * 0.5;
32 static void ui_shutdown(void)
37 static void ui_newmap(void)
41 static mempool_t *uimempool;
45 uimempool = Mem_AllocPool("UI");
47 Cvar_RegisterVariable(&ui_showname);
49 R_RegisterModule("UI", ui_start, ui_shutdown, ui_newmap);
52 void ui_mouseupdate(float x, float y)
56 ui_mouse_x = bound(0, x, vid.conwidth);
57 ui_mouse_y = bound(0, y, vid.conheight);
61 void ui_mouseupdaterelative(float x, float y)
67 ui_mouse_x = bound(0, ui_mouse_x, vid.conwidth);
68 ui_mouse_y = bound(0, ui_mouse_y, vid.conheight);
75 ui = Mem_Alloc(uimempool, sizeof(*ui));
77 Sys_Error("ui_create: unable to allocate memory for new ui\n");
78 memset(ui, 0, sizeof(*ui));
82 void ui_free(ui_t *ui)
88 void ui_clear(ui_t *ui)
95 ui_t *ui, char *basename, int number,
96 float x, float y, char *picname, char *string,
97 float left, float top, float width, float height,
98 void(*leftkey)(void *nativedata1, void *nativedata2, float data1, float data2),
99 void(*rightkey)(void *nativedata1, void *nativedata2, float data1, float data2),
100 void(*enterkey)(void *nativedata1, void *nativedata2, float data1, float data2),
101 void(*mouseclick)(void *nativedata1, void *nativedata2, float data1, float data2, float xfrac, float yfrac),
102 void *nativedata1, void *nativedata2, float data1, float data2
108 snprintf(itemname, sizeof(itemname), "%s%04d", basename, number);
109 for (it = ui->items, i = 0;i < ui->item_count;it++, i++)
110 if (it->name == NULL || !strncmp(itemname, it->name, 32))
112 if (i == ui->item_count)
114 if (i == MAX_UI_ITEMS)
116 Con_Printf("ui_item: ran out of UI item slots\n");
121 memset(it, 0, sizeof(ui_item_t));
122 strlcpy (it->name, itemname, sizeof (it->name));
124 if (picname || string)
126 it->flags |= ITEM_DRAWABLE;
127 it->draw_picname = picname;
128 it->draw_string = string;
132 if (leftkey || rightkey || enterkey || mouseclick)
134 it->flags |= ITEM_CLICKABLE;
135 it->click_x = x + left;
136 it->click_y = y + top;
137 it->click_x2 = it->click_x + width;
138 it->click_y2 = it->click_y + height;
139 it->leftkey = leftkey;
140 it->rightkey = rightkey;
141 it->enterkey = enterkey;
142 it->mouseclick = mouseclick;
143 if (it->mouseclick == NULL)
144 it->mouseclick = (void *)it->enterkey;
145 if (it->leftkey == NULL)
146 it->leftkey = it->enterkey;
147 if (it->rightkey == NULL)
148 it->rightkey = it->enterkey;
149 it->nativedata1 = nativedata1;
150 it->nativedata2 = nativedata2;
154 void ui_item_remove(ui_t *ui, char *basename, int number)
159 snprintf(itemname, sizeof(itemname), "%s%04d", basename, number);
160 for (it = ui->items, i = 0;i < ui->item_count;it++, i++)
161 if (it->name && !strncmp(itemname, it->name, 32))
163 if (i < ui->item_count)
167 ui_item_t *ui_hititem(float x, float y)
172 for (j = 0;j < MAX_UI_COUNT;j++)
173 if ((ui = ui_list[j]))
174 for (it = ui->items, i = 0;i < ui->item_count;it++, i++)
175 if (it->name[0] && (it->flags & ITEM_CLICKABLE))
176 if (x >= it->click_x && y >= it->click_y && x < it->click_x2 && y < it->click_y2)
181 int ui_uiactive(ui_t *ui)
184 for (i = 0;i < MAX_UI_COUNT;i++)
185 if (ui_list[i] == ui)
190 void ui_activate(ui_t *ui, int yes)
198 for (i = 0;i < MAX_UI_COUNT;i++)
200 if (ui_list[i] == NULL)
207 Con_Printf("ui_activate: ran out of active ui list items\n");
211 for (i = 0;i < MAX_UI_COUNT;i++)
213 if (ui_list[i] == ui)
222 int ui_isactive(void)
228 for (j = 0;j < MAX_UI_COUNT;j++)
229 if ((ui = ui_list[j]))
236 #define UI_QUEUE_SIZE 256
237 static qbyte ui_keyqueue[UI_QUEUE_SIZE];
238 static int ui_keyqueuepos = 0;
240 void ui_leftkeyupdate(int pressed)
242 static int key = false;
243 if (pressed && !key && ui_keyqueuepos < UI_QUEUE_SIZE)
244 ui_keyqueue[ui_keyqueuepos++] = UIKEY_LEFT;
248 void ui_rightkeyupdate(int pressed)
250 static int key = false;
251 if (pressed && !key && ui_keyqueuepos < UI_QUEUE_SIZE)
252 ui_keyqueue[ui_keyqueuepos++] = UIKEY_RIGHT;
256 void ui_upkeyupdate(int pressed)
258 static int key = false;
259 if (pressed && !key && ui_keyqueuepos < UI_QUEUE_SIZE)
260 ui_keyqueue[ui_keyqueuepos++] = UIKEY_UP;
264 void ui_downkeyupdate(int pressed)
266 static int key = false;
267 if (pressed && !key && ui_keyqueuepos < UI_QUEUE_SIZE)
268 ui_keyqueue[ui_keyqueuepos++] = UIKEY_DOWN;
272 void ui_mousebuttonupdate(int button, int pressed)
274 if (button < 0 || button >= UI_MOUSEBUTTONS)
276 if (button == 0 && ui_mousebutton[button] && !pressed)
277 ui_mouseclick = true;
278 ui_mousebutton[button] = pressed;
283 ui_item_t *startitem, *it;
286 ui_mouse_x = bound(0, ui_mouse_x, vid.conwidth);
287 ui_mouse_y = bound(0, ui_mouse_y, vid.conheight);
289 if ((ui_active = ui_isactive()))
291 // validate currently selected item
292 if(ui_list[ui_keyui] == NULL)
294 while (ui_list[ui_keyui] == NULL)
295 ui_keyui = (ui_keyui + 1) % MAX_UI_COUNT;
298 ui_keyitem = bound(0, ui_keyitem, ui_list[ui_keyui]->item_count - 1);
299 startitem = ui_keyrealitem = &ui_list[ui_keyui]->items[ui_keyitem];
300 if ((ui_keyrealitem->flags & ITEM_CLICKABLE) == 0)
304 // FIXME: cycle through UIs as well as items in a UI
305 ui_keyitem = (ui_keyitem - 1) % ui_list[ui_keyui]->item_count - 1;
306 ui_keyrealitem = &ui_list[ui_keyui]->items[ui_keyitem];
308 while (ui_keyrealitem != startitem && (ui_keyrealitem->flags & ITEM_CLICKABLE) == 0);
314 for (i = 0;i < ui_keyqueuepos;i++)
316 startitem = ui_keyrealitem;
317 switch(ui_keyqueue[i])
326 ui_keyui = (ui_keyui - 1) % MAX_UI_COUNT;
327 while(ui_list[ui_keyui] == NULL);
328 ui_keyitem = ui_list[ui_keyui]->item_count - 1;
330 ui_keyrealitem = &ui_list[ui_keyui]->items[ui_keyitem];
332 while (ui_keyrealitem != startitem && (ui_keyrealitem->flags & ITEM_CLICKABLE) == 0);
338 if (ui_keyitem >= ui_list[ui_keyui]->item_count)
341 ui_keyui = (ui_keyui + 1) % MAX_UI_COUNT;
342 while(ui_list[ui_keyui] == NULL);
345 ui_keyrealitem = &ui_list[ui_keyui]->items[ui_keyitem];
347 while (ui_keyrealitem != startitem && (ui_keyrealitem->flags & ITEM_CLICKABLE) == 0);
350 if (ui_keyrealitem->leftkey)
351 ui_keyrealitem->leftkey(ui_keyrealitem->nativedata1, ui_keyrealitem->nativedata2, ui_keyrealitem->data1, ui_keyrealitem->data2);
354 if (ui_keyrealitem->rightkey)
355 ui_keyrealitem->rightkey(ui_keyrealitem->nativedata1, ui_keyrealitem->nativedata2, ui_keyrealitem->data1, ui_keyrealitem->data2);
358 if (ui_keyrealitem->enterkey)
359 ui_keyrealitem->enterkey(ui_keyrealitem->nativedata1, ui_keyrealitem->nativedata2, ui_keyrealitem->data1, ui_keyrealitem->data2);
366 if (ui_mouseclick && (it = ui_hititem(ui_mouse_x, ui_mouse_y)) && it->mouseclick)
367 it->mouseclick(it->nativedata1, it->nativedata2, it->data1, it->data2, ui_mouse_x - it->click_x, ui_mouse_y - it->click_y);
370 ui_mouseclick = false;
378 if (ui_alive && ui_active)
380 for (j = 0;j < MAX_UI_COUNT;j++)
381 if ((ui = ui_list[j]))
383 for (i = 0, it = ui->items;i < ui->item_count;i++, it++)
384 if (it->flags & ITEM_DRAWABLE)
386 if (it->draw_picname)
387 DrawQ_Pic(it->draw_x, it->draw_y, it->draw_picname, 0, 0, 1, 1, 1, 1, 0);
389 DrawQ_String(it->draw_x, it->draw_y, it->draw_string, 0, 8, 8, 1, 1, 1, 1, 0);
392 if ((it = ui_hititem(ui_mouse_x, ui_mouse_y)))
394 if (it->draw_picname)
395 DrawQ_Pic(it->draw_x, it->draw_y, it->draw_picname, 0, 0, 1, 1, 1, 1, DRAWFLAG_ADDITIVE);
397 DrawQ_String(it->draw_x, it->draw_y, it->draw_string, 0, 8, 8, 1, 1, 1, 1, DRAWFLAG_ADDITIVE);
398 if (ui_showname.integer)
399 DrawQ_String(ui_mouse_x, ui_mouse_y + 16, it->name, 0, 8, 8, 1, 1, 1, 1, 0);
403 if (it->draw_picname)
404 DrawQ_Pic(it->draw_x, it->draw_y, it->draw_picname, 0, 0, 1, 1, 1, 1, DRAWFLAG_ADDITIVE);
406 DrawQ_String(it->draw_x, it->draw_y, it->draw_string, 0, 8, 8, 1, 1, 1, 1, DRAWFLAG_ADDITIVE);
408 DrawQ_Pic(ui_mouse_x, ui_mouse_y, "ui/mousepointer.tga", 0, 0, 1, 1, 1, 1, 0);
412 #define FRAME_THICKNESS 2
413 #define FRAME_COLOR1 0.2, 0.2, 0.5, 0, 0
414 #define FRAME_COLOR2 0, 0, 0, 0.6, 0
415 #define TEXT_FONTSIZE 10, 10
418 static void UIG_DrawFrame(float x, float y, float w, float h)
421 DrawQ_Fill(x - FRAME_THICKNESS, y - FRAME_THICKNESS, w + 2 * FRAME_THICKNESS, FRAME_THICKNESS, FRAME_COLOR1);
423 DrawQ_Fill(x - FRAME_THICKNESS, y + h, w + 2 * FRAME_THICKNESS, FRAME_THICKNESS, FRAME_COLOR1);
425 DrawQ_Fill(x - FRAME_THICKNESS, y, FRAME_THICKNESS, h, FRAME_COLOR1);
427 DrawQ_Fill(x + w, y, FRAME_THICKNESS, h, FRAME_COLOR1);
429 DrawQ_Fill(x, y, w, h, FRAME_COLOR2);
432 static void UIG_DrawText(const char *text, float x, float y, float w, float h, float r, float g, float b, float a, float f)
435 DrawQ_SetClipArea(x, y, w, h);
436 DrawQ_String(x, y, text, 0, TEXT_FONTSIZE, r, g, b, a , f);
438 DrawQ_ResetClipArea();
446 void UI_Key(ui_itemlist_t list, int key, int ascii)
450 void UI_Draw(ui_itemlist_t list)
454 void UI_SetFocus(ui_itemlist_t list, ui_item_t item)
458 void UI_SetNeighbors(ui_item_t left, ui_item_t right, ui_item_t up, ui_item_t down)
463 ui_item_t UI_CreateButton(const char *caption, float x, float y, void(*action)(ui_item_t))
468 ui_item_t UI_CreateLabel(const char *caption, float x, float y)
473 ui_item_t UI_CreateText(const char *caption, float x, float y, const char *allowed, int maxlen, int scrolllen)
478 void UI_FreeItem(ui_item_t item)
482 const char* UI_GetCaption(ui_item_t item)
487 void UI_SetCaption(ui_item_t item, const char * caption)
492 ui_itemlist_t UI_CreateItemList(float x, float y)
497 void UI_FreeItemList(ui_itemlist_t list)
501 void UI_AddItem(ui_itemlist_t list, ui_item_t item)
505 // AK: callback system stuff
506 static ui_callback_t ui_callback_list[UI_MAX_CALLBACK_COUNT];
508 void UI_Callback_Init(void)
510 memset(ui_callback_list, 0, sizeof(ui_callback_list));
513 int UI_Callback_GetFreeSlot(void)
516 for(i = 0; ui_callback_list[i].flag & UI_SLOTUSED && i < UI_MAX_CALLBACK_COUNT; i++);
518 if(i == UI_MAX_CALLBACK_COUNT)
524 int UI_Callback_IsSlotUsed(int slotnr)
526 if(slotnr < 0 || slotnr >= UI_MAX_CALLBACK_COUNT)
528 return (ui_callback_list[slotnr].flag & UI_SLOTUSED);
531 void UI_Callback_SetupSlot(int slotnr, void(*keydownf)(int num, char ascii), void(*drawf)(void))
533 ui_callback_list[slotnr].flag = UI_SLOTUSED;
534 ui_callback_list[slotnr].draw = drawf;
535 ui_callback_list[slotnr].keydown = keydownf;
538 void UI_Callback_ResetSlot(int slotnr)
540 ui_callback_list[slotnr].flag = 0;
543 void UI_Callback_Draw(void)
546 for(i = 0; i < UI_MAX_CALLBACK_COUNT; i++)
547 if(ui_callback_list[i].flag & UI_SLOTUSED && ui_callback_list[i].draw)
548 ui_callback_list[i].draw();
551 void UI_Callback_KeyDown(int num, char ascii)
553 if(ui_callback_list[key_dest - 3].flag & UI_SLOTUSED && ui_callback_list[key_dest - 3].keydown)
554 ui_callback_list[key_dest - 3].keydown(num, ascii);