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);
48 R_RegisterModule("UI", ui_start, ui_shutdown, ui_newmap);
51 void ui_mouseupdate(float x, float y)
55 ui_mouse_x = bound(0, x, vid.conwidth);
56 ui_mouse_y = bound(0, y, vid.conheight);
60 void ui_mouseupdaterelative(float x, float y)
66 ui_mouse_x = bound(0, ui_mouse_x, vid.conwidth);
67 ui_mouse_y = bound(0, ui_mouse_y, vid.conheight);
74 ui = Mem_Alloc(uimempool, sizeof(*ui));
76 Sys_Error("ui_create: unable to allocate memory for new ui\n");
77 memset(ui, 0, sizeof(*ui));
81 void ui_free(ui_t *ui)
87 void ui_clear(ui_t *ui)
94 ui_t *ui, char *basename, int number,
95 float x, float y, char *picname, char *string,
96 float left, float top, float width, float height,
97 void(*leftkey)(void *nativedata1, void *nativedata2, float data1, float data2),
98 void(*rightkey)(void *nativedata1, void *nativedata2, float data1, float data2),
99 void(*enterkey)(void *nativedata1, void *nativedata2, float data1, float data2),
100 void(*mouseclick)(void *nativedata1, void *nativedata2, float data1, float data2, float xfrac, float yfrac),
101 void *nativedata1, void *nativedata2, float data1, float data2
107 snprintf(itemname, sizeof(itemname), "%s%04d", basename, number);
108 for (it = ui->items, i = 0;i < ui->item_count;it++, i++)
109 if (it->name == NULL || !strncmp(itemname, it->name, 32))
111 if (i == ui->item_count)
113 if (i == MAX_UI_ITEMS)
115 Con_Printf("ui_item: ran out of UI item slots\n");
120 memset(it, 0, sizeof(ui_item_t));
121 strncpy(it->name, itemname, 32);
123 if (picname || string)
125 it->flags |= ITEM_DRAWABLE;
126 it->draw_picname = picname;
127 it->draw_string = string;
131 if (leftkey || rightkey || enterkey || mouseclick)
133 it->flags |= ITEM_CLICKABLE;
134 it->click_x = x + left;
135 it->click_y = y + top;
136 it->click_x2 = it->click_x + width;
137 it->click_y2 = it->click_y + height;
138 it->leftkey = leftkey;
139 it->rightkey = rightkey;
140 it->enterkey = enterkey;
141 it->mouseclick = mouseclick;
142 if (it->mouseclick == NULL)
143 it->mouseclick = (void *)it->enterkey;
144 if (it->leftkey == NULL)
145 it->leftkey = it->enterkey;
146 if (it->rightkey == NULL)
147 it->rightkey = it->enterkey;
148 it->nativedata1 = nativedata1;
149 it->nativedata2 = nativedata2;
153 void ui_item_remove(ui_t *ui, char *basename, int number)
158 snprintf(itemname, sizeof(itemname), "%s%04d", basename, number);
159 for (it = ui->items, i = 0;i < ui->item_count;it++, i++)
160 if (it->name && !strncmp(itemname, it->name, 32))
162 if (i < ui->item_count)
166 ui_item_t *ui_hititem(float x, float y)
171 for (j = 0;j < MAX_UI_COUNT;j++)
172 if ((ui = ui_list[j]))
173 for (it = ui->items, i = 0;i < ui->item_count;it++, i++)
174 if (it->name[0] && (it->flags & ITEM_CLICKABLE))
175 if (x >= it->click_x && y >= it->click_y && x < it->click_x2 && y < it->click_y2)
180 int ui_uiactive(ui_t *ui)
183 for (i = 0;i < MAX_UI_COUNT;i++)
184 if (ui_list[i] == ui)
189 void ui_activate(ui_t *ui, int yes)
197 for (i = 0;i < MAX_UI_COUNT;i++)
199 if (ui_list[i] == NULL)
206 Con_Printf("ui_activate: ran out of active ui list items\n");
210 for (i = 0;i < MAX_UI_COUNT;i++)
212 if (ui_list[i] == ui)
221 int ui_isactive(void)
227 for (j = 0;j < MAX_UI_COUNT;j++)
228 if ((ui = ui_list[j]))
235 #define UI_QUEUE_SIZE 256
236 static qbyte ui_keyqueue[UI_QUEUE_SIZE];
237 static int ui_keyqueuepos = 0;
239 void ui_leftkeyupdate(int pressed)
241 static int key = false;
242 if (pressed && !key && ui_keyqueuepos < UI_QUEUE_SIZE)
243 ui_keyqueue[ui_keyqueuepos++] = UIKEY_LEFT;
247 void ui_rightkeyupdate(int pressed)
249 static int key = false;
250 if (pressed && !key && ui_keyqueuepos < UI_QUEUE_SIZE)
251 ui_keyqueue[ui_keyqueuepos++] = UIKEY_RIGHT;
255 void ui_upkeyupdate(int pressed)
257 static int key = false;
258 if (pressed && !key && ui_keyqueuepos < UI_QUEUE_SIZE)
259 ui_keyqueue[ui_keyqueuepos++] = UIKEY_UP;
263 void ui_downkeyupdate(int pressed)
265 static int key = false;
266 if (pressed && !key && ui_keyqueuepos < UI_QUEUE_SIZE)
267 ui_keyqueue[ui_keyqueuepos++] = UIKEY_DOWN;
271 void ui_mousebuttonupdate(int button, int pressed)
273 if (button < 0 || button >= UI_MOUSEBUTTONS)
275 if (button == 0 && ui_mousebutton[button] && !pressed)
276 ui_mouseclick = true;
277 ui_mousebutton[button] = pressed;
282 ui_item_t *startitem, *it;
285 ui_mouse_x = bound(0, ui_mouse_x, vid.conwidth);
286 ui_mouse_y = bound(0, ui_mouse_y, vid.conheight);
288 if ((ui_active = ui_isactive()))
290 // validate currently selected item
291 if(ui_list[ui_keyui] == NULL)
293 while (ui_list[ui_keyui] == NULL)
294 ui_keyui = (ui_keyui + 1) % MAX_UI_COUNT;
297 ui_keyitem = bound(0, ui_keyitem, ui_list[ui_keyui]->item_count - 1);
298 startitem = ui_keyrealitem = &ui_list[ui_keyui]->items[ui_keyitem];
299 if ((ui_keyrealitem->flags & ITEM_CLICKABLE) == 0)
303 // FIXME: cycle through UIs as well as items in a UI
304 ui_keyitem = (ui_keyitem - 1) % ui_list[ui_keyui]->item_count - 1;
305 ui_keyrealitem = &ui_list[ui_keyui]->items[ui_keyitem];
307 while (ui_keyrealitem != startitem && (ui_keyrealitem->flags & ITEM_CLICKABLE) == 0);
313 for (i = 0;i < ui_keyqueuepos;i++)
315 startitem = ui_keyrealitem;
316 switch(ui_keyqueue[i])
325 ui_keyui = (ui_keyui - 1) % MAX_UI_COUNT;
326 while(ui_list[ui_keyui] == NULL);
327 ui_keyitem = ui_list[ui_keyui]->item_count - 1;
329 ui_keyrealitem = &ui_list[ui_keyui]->items[ui_keyitem];
331 while (ui_keyrealitem != startitem && (ui_keyrealitem->flags & ITEM_CLICKABLE) == 0);
337 if (ui_keyitem >= ui_list[ui_keyui]->item_count)
340 ui_keyui = (ui_keyui + 1) % MAX_UI_COUNT;
341 while(ui_list[ui_keyui] == NULL);
344 ui_keyrealitem = &ui_list[ui_keyui]->items[ui_keyitem];
346 while (ui_keyrealitem != startitem && (ui_keyrealitem->flags & ITEM_CLICKABLE) == 0);
349 if (ui_keyrealitem->leftkey)
350 ui_keyrealitem->leftkey(ui_keyrealitem->nativedata1, ui_keyrealitem->nativedata2, ui_keyrealitem->data1, ui_keyrealitem->data2);
353 if (ui_keyrealitem->rightkey)
354 ui_keyrealitem->rightkey(ui_keyrealitem->nativedata1, ui_keyrealitem->nativedata2, ui_keyrealitem->data1, ui_keyrealitem->data2);
357 if (ui_keyrealitem->enterkey)
358 ui_keyrealitem->enterkey(ui_keyrealitem->nativedata1, ui_keyrealitem->nativedata2, ui_keyrealitem->data1, ui_keyrealitem->data2);
365 if (ui_mouseclick && (it = ui_hititem(ui_mouse_x, ui_mouse_y)) && it->mouseclick)
366 it->mouseclick(it->nativedata1, it->nativedata2, it->data1, it->data2, ui_mouse_x - it->click_x, ui_mouse_y - it->click_y);
369 ui_mouseclick = false;
377 if (ui_alive && ui_active)
379 for (j = 0;j < MAX_UI_COUNT;j++)
380 if ((ui = ui_list[j]))
382 for (i = 0, it = ui->items;i < ui->item_count;i++, it++)
383 if (it->flags & ITEM_DRAWABLE)
385 if (it->draw_picname)
386 DrawQ_Pic(it->draw_x, it->draw_y, it->draw_picname, 0, 0, 1, 1, 1, 1, 0);
388 DrawQ_String(it->draw_x, it->draw_y, it->draw_string, 0, 8, 8, 1, 1, 1, 1, 0);
391 if ((it = ui_hititem(ui_mouse_x, ui_mouse_y)))
393 if (it->draw_picname)
394 DrawQ_Pic(it->draw_x, it->draw_y, it->draw_picname, 0, 0, 1, 1, 1, 1, DRAWFLAG_ADDITIVE);
396 DrawQ_String(it->draw_x, it->draw_y, it->draw_string, 0, 8, 8, 1, 1, 1, 1, DRAWFLAG_ADDITIVE);
397 if (ui_showname.integer)
398 DrawQ_String(ui_mouse_x, ui_mouse_y + 16, it->name, 0, 8, 8, 1, 1, 1, 1, 0);
402 if (it->draw_picname)
403 DrawQ_Pic(it->draw_x, it->draw_y, it->draw_picname, 0, 0, 1, 1, 1, 1, DRAWFLAG_ADDITIVE);
405 DrawQ_String(it->draw_x, it->draw_y, it->draw_string, 0, 8, 8, 1, 1, 1, 1, DRAWFLAG_ADDITIVE);
407 DrawQ_Pic(ui_mouse_x, ui_mouse_y, "ui/mousepointer.tga", 0, 0, 1, 1, 1, 1, 0);