]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - ui.c
use sys_ticrate timing on dedicated servers
[xonotic/darkplaces.git] / ui.c
1
2 #include "quakedef.h"
3
4 // here is the real ui drawing engine 
5
6 #define FRAME_THICKNESS 2
7 #define FRAME_COLOR1    0.2, 0.2, 0.5, 0, 0
8 #define FRAME_COLOR2    0, 0, 0, 0.6, 0
9 #define TEXT_FONTSIZE_X 10
10 #define TEXT_FONTSIZE_Y 10
11
12 static void UIG_DrawFrame(float x, float y, float w, float h)
13 {
14         // bottom
15         DrawQ_Fill(x - FRAME_THICKNESS, y - FRAME_THICKNESS, w + 2 * FRAME_THICKNESS, FRAME_THICKNESS, FRAME_COLOR1);
16         // top
17         DrawQ_Fill(x - FRAME_THICKNESS, y + h, w + 2 * FRAME_THICKNESS, FRAME_THICKNESS, FRAME_COLOR1);
18         // left
19         DrawQ_Fill(x - FRAME_THICKNESS, y, FRAME_THICKNESS, h, FRAME_COLOR1);
20         // right
21         DrawQ_Fill(x + w, y, FRAME_THICKNESS, h, FRAME_COLOR1);
22         // area
23         DrawQ_Fill(x, y, w, h, FRAME_COLOR2);
24
25
26 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)
27 {
28         if(w != 0 && h != 0)
29                 DrawQ_SetClipArea(x, y, w, h);
30         DrawQ_String(x, y, text, 0, TEXT_FONTSIZE_X, TEXT_FONTSIZE_Y, r, g, b, a, f);
31         if(w != 0 && h != 0)    
32                 DrawQ_ResetClipArea();
33 }
34
35 #define UIG_DrawPicture         DrawQ_Pic
36 #define UIG_Fill                        DrawQ_Fill
37
38 static void UIG_DrawCursor(float x, float y, float r, float g, float b, float a, float f)
39 {
40         DrawQ_Fill(x,y,1, TEXT_FONTSIZE_Y, r, g, b, a, f);
41 }
42
43 static mempool_t *ui_mem;
44
45 //#define UI_MEM_SIZE (1 << 10) << 9 // 512 KByte
46 #define UI_MEM_SIZE 1
47
48 void UI_Init(void)
49 {
50         ui_mem = Mem_AllocPool("Intern UI Memory");
51 }
52
53 #define UI_Alloc(size)  Mem_Alloc(ui_mem, size)
54 #define UI_Free(ptr)    Mem_Free(ptr)
55
56 void UI_Event(ui_itemlist_t list, ui_message_t *in)
57 {
58         ui_message_queue_t out;
59         ui_item_t  item;
60         int processed = true;
61
62         if(list->list)
63                 for(item = list->list; item != 0 && !processed; item = item->next)
64                 {
65                         unsigned int i;
66                 
67                         processed = item->eventhandler(list, item, in, &out);
68                 
69                         // process posted messages
70                         for(i = 0; i < out.used; i++)
71                                 list->eventhandler(list, &out.queue[i]);
72
73                         if(in->type == UI_EVENT_FRAME)
74                                 processed = false;
75                 }
76
77         if(!processed)
78                 list->eventhandler(list, in);           
79 }
80
81 void UI_Draw(ui_itemlist_t list)
82 {
83         // firstly we create the frame event here
84         ui_message_t msg;
85         ui_item_t item;
86
87         msg.type = UI_EVENT_FRAME;
88
89         UI_Event(list, &msg);
90
91         // now draw everything
92         if(list->list)
93         {
94                 unsigned int depth = 0, nextdepth = ~0;
95
96                 while(depth != nextdepth) 
97                 {
98                         for(item = list->list; item != 0; item = item->next)
99                         {
100                                 if(item->zorder == depth)
101                                         item->draw(list, item);
102                                 if(item->zorder > depth && item->zorder < nextdepth)
103                                         nextdepth = item->zorder;
104                         }
105                         depth = nextdepth;
106                         nextdepth = ~0;
107                 }
108         }
109 }
110
111 void UI_Mouse(ui_itemlist_t list, float x, float y)
112 {
113         ui_message_t msg;
114
115         msg.type = UI_EVENT_MOUSE;
116
117         msg.data.mouse.x = x;
118         msg.data.mouse.y = y;
119
120         UI_Event(list, &msg);
121 }
122
123 void UI_Key(ui_itemlist_t list, int key, int ascii)
124 {
125         ui_message_t msg;
126
127         msg.type = UI_EVENT_KEY;
128
129         msg.data.key.key = key;
130         msg.data.key.ascii = ascii;
131
132         UI_Event(list, &msg);
133 }
134
135
136 // item stuff
137 ui_item_t UI_CloneItem(ui_item_t item)
138 {
139         ui_item_t clone;
140         clone = UI_Alloc(item->size);
141         clone = memcpy(clone, item, item->size);
142
143         return clone;
144 }
145
146 ui_item_t UI_FindItemByName(ui_itemlist_t list, const char *name)
147 {
148         ui_item_t item, found = 0;
149
150         if(list->list)
151                 for(item = list->list; item != 0; item = item->next)
152                         if(!strcmp(name, item->name))
153                         {
154                                 found = item;
155                                 break;
156                         }
157
158         return found;
159 }
160
161 void UI_FreeItem(ui_itemlist_t list, ui_item_t item)
162 {
163         if(!item->prev)
164         {
165                 // this is the first item
166                 list->list = item->next;
167         }
168
169         item->prev->next = item->next;
170         item->next->prev = item->prev;
171
172         UI_Free(item);
173 }
174
175 void UI_FreeItemByName(ui_itemlist_t list, const char *name)
176 {
177         ui_item_t item;
178
179         item = UI_FindItemByName(list, name);
180         if(item)
181                 UI_Free(item);
182 }
183
184
185 // itemlist stuff
186 ui_itemlist_t UI_CreateItemList(void)
187 {
188         return UI_Alloc(sizeof(ui_itemlist_t));
189 }
190
191 ui_itemlist_t UI_CloneItemList(ui_itemlist_t list)
192 {
193         ui_itemlist_t clone;
194         ui_item_t         item;
195
196         clone = UI_CreateItemList();
197
198         if(list->list)
199                 for(item = list->list; item != 0; item = item->next)
200                         UI_AddItem(clone, UI_CloneItem(item));
201
202         return clone;
203 }
204
205
206 void UI_FreeItemList(ui_itemlist_t list)
207 {
208         UI_Free((void*)list);
209 }
210
211 void UI_AddItem(ui_itemlist_t list, ui_item_t item)
212 {
213         item->prev = 0;
214         item->next = list->list;
215         list->list->prev = item;
216         list->list = item;
217 }
218
219 // controls
220 ui_item_t UI_CreateButton(void)
221 {
222         return NULL;
223 }
224
225 ui_item_t UI_CreateLabel(void)
226 {
227         return NULL;
228 }
229
230 ui_item_t UI_CreateText(void)
231 {
232         return NULL;
233 }
234 // AK: callback system stuff
235 static ui_callback_t ui_callback_list[UI_MAX_CALLBACK_COUNT];
236
237 void UI_Callback_Init(void)
238 {
239         memset(ui_callback_list, 0, sizeof(ui_callback_list));
240 }
241
242 int  UI_Callback_GetFreeSlot(void)
243 {
244         int i;
245         for(i = 0; ui_callback_list[i].flag & UI_SLOTUSED && i < UI_MAX_CALLBACK_COUNT; i++);
246
247         if(i == UI_MAX_CALLBACK_COUNT)
248                 return -1;
249         else
250                 return i;
251 }
252
253 int UI_Callback_IsSlotUsed(int slotnr)
254 {
255         if(slotnr < 0 || slotnr >= UI_MAX_CALLBACK_COUNT)
256                 return false;
257         return (ui_callback_list[slotnr].flag & UI_SLOTUSED);
258 }
259
260 void UI_Callback_SetupSlot(int slotnr, void(*keydownf)(int num, char ascii), void(*drawf)(void))
261 {
262         ui_callback_list[slotnr].flag = UI_SLOTUSED;
263         ui_callback_list[slotnr].draw = drawf;
264         ui_callback_list[slotnr].keydown = keydownf;
265 }
266
267 void UI_Callback_ResetSlot(int slotnr)
268 {
269         ui_callback_list[slotnr].flag = 0;
270 }
271
272 void UI_Callback_Draw(void)
273 {
274         int i;
275         for(i = 0; i < UI_MAX_CALLBACK_COUNT; i++)
276                 if(ui_callback_list[i].flag & UI_SLOTUSED && ui_callback_list[i].draw)
277                         ui_callback_list[i].draw();
278 }
279
280 void UI_Callback_KeyDown(int num, char ascii)
281 {
282         if(ui_callback_list[key_dest - 3].flag & UI_SLOTUSED && ui_callback_list[key_dest - 3].keydown)
283                 ui_callback_list[key_dest - 3].keydown(num, ascii);
284 }