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