eliminated qbyte type, now uses unsigned char throughout the engine for this purpose
[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 //#define UI_MEM_SIZE (1 << 10) << 9 // 512 KByte
46 #define UI_MEM_SIZE 1
47
48 void UI_Init(void)
49 {
50 }
51
52 #define UI_Alloc(size)  Mem_Alloc(cl_mempool, size)
53 #define UI_Free(ptr)    Mem_Free(ptr)
54
55 void UI_Event(ui_itemlist_t list, ui_message_t *in)
56 {
57         ui_message_queue_t out;
58         ui_item_t  item;
59         int processed = true;
60
61         if(list->list)
62                 for(item = list->list; item != 0 && !processed; item = item->next)
63                 {
64                         unsigned int i;
65
66                         processed = item->eventhandler(list, item, in, &out);
67
68                         // process posted messages
69                         for(i = 0; i < out.used; i++)
70                                 list->eventhandler(list, &out.queue[i]);
71
72                         if(in->type == UI_EVENT_FRAME)
73                                 processed = false;
74                 }
75
76         if(!processed)
77                 list->eventhandler(list, in);
78 }
79
80 void UI_Draw(ui_itemlist_t list)
81 {
82         // firstly we create the frame event here
83         ui_message_t msg;
84         ui_item_t item;
85
86         msg.type = UI_EVENT_FRAME;
87
88         UI_Event(list, &msg);
89
90         // now draw everything
91         if(list->list)
92         {
93                 unsigned int depth = 0, nextdepth = ~0;
94
95                 while(depth != nextdepth)
96                 {
97                         for(item = list->list; item != 0; item = item->next)
98                         {
99                                 if(item->zorder == depth)
100                                         item->draw(list, item);
101                                 if(item->zorder > depth && item->zorder < nextdepth)
102                                         nextdepth = item->zorder;
103                         }
104                         depth = nextdepth;
105                         nextdepth = ~0;
106                 }
107         }
108 }
109
110 void UI_Mouse(ui_itemlist_t list, float x, float y)
111 {
112         ui_message_t msg;
113
114         msg.type = UI_EVENT_MOUSE;
115
116         msg.data.mouse.x = x;
117         msg.data.mouse.y = y;
118
119         UI_Event(list, &msg);
120 }
121
122 void UI_Key(ui_itemlist_t list, int key, int ascii)
123 {
124         ui_message_t msg;
125
126         msg.type = UI_EVENT_KEY;
127
128         msg.data.key.key = key;
129         msg.data.key.ascii = ascii;
130
131         UI_Event(list, &msg);
132 }
133
134
135 // item stuff
136 ui_item_t UI_CloneItem(ui_item_t item)
137 {
138         ui_item_t clone;
139         clone = (ui_item_t)UI_Alloc(item->size);
140         memcpy(clone, item, item->size);
141
142         return clone;
143 }
144
145 ui_item_t UI_FindItemByName(ui_itemlist_t list, const char *name)
146 {
147         ui_item_t item, found = 0;
148
149         if(list->list)
150                 for(item = list->list; item != 0; item = item->next)
151                         if(!strcmp(name, item->name))
152                         {
153                                 found = item;
154                                 break;
155                         }
156
157         return found;
158 }
159
160 void UI_FreeItem(ui_itemlist_t list, ui_item_t item)
161 {
162         if(!item->prev)
163         {
164                 // this is the first item
165                 list->list = item->next;
166         }
167
168         item->prev->next = item->next;
169         item->next->prev = item->prev;
170
171         UI_Free(item);
172 }
173
174 void UI_FreeItemByName(ui_itemlist_t list, const char *name)
175 {
176         ui_item_t item;
177
178         item = UI_FindItemByName(list, name);
179         if(item)
180                 UI_Free(item);
181 }
182
183
184 // itemlist stuff
185 ui_itemlist_t UI_CreateItemList(void)
186 {
187         return (ui_itemlist_t)UI_Alloc(sizeof(ui_itemlist_t));
188 }
189
190 ui_itemlist_t UI_CloneItemList(ui_itemlist_t list)
191 {
192         ui_itemlist_t clone;
193         ui_item_t         item;
194
195         clone = UI_CreateItemList();
196
197         if(list->list)
198                 for(item = list->list; item != 0; item = item->next)
199                         UI_AddItem(clone, UI_CloneItem(item));
200
201         return clone;
202 }
203
204
205 void UI_FreeItemList(ui_itemlist_t list)
206 {
207         UI_Free((void*)list);
208 }
209
210 void UI_AddItem(ui_itemlist_t list, ui_item_t item)
211 {
212         item->prev = 0;
213         item->next = list->list;
214         list->list->prev = item;
215         list->list = item;
216 }
217
218 // controls
219 ui_item_t UI_CreateButton(void)
220 {
221         return NULL;
222 }
223
224 ui_item_t UI_CreateLabel(void)
225 {
226         return NULL;
227 }
228
229 ui_item_t UI_CreateText(void)
230 {
231         return NULL;
232 }
233 // AK: callback system stuff
234 static ui_callback_t ui_callback_list[UI_MAX_CALLBACK_COUNT];
235
236 void UI_Callback_Init(void)
237 {
238         memset(ui_callback_list, 0, sizeof(ui_callback_list));
239 }
240
241 int  UI_Callback_GetFreeSlot(void)
242 {
243         int i;
244         for(i = 0; ui_callback_list[i].flag & UI_SLOTUSED && i < UI_MAX_CALLBACK_COUNT; i++);
245
246         if(i == UI_MAX_CALLBACK_COUNT)
247                 return -1;
248         else
249                 return i;
250 }
251
252 int UI_Callback_IsSlotUsed(int slotnr)
253 {
254         if(slotnr < 0 || slotnr >= UI_MAX_CALLBACK_COUNT)
255                 return false;
256         return (ui_callback_list[slotnr].flag & UI_SLOTUSED);
257 }
258
259 void UI_Callback_SetupSlot(int slotnr, void(*keydownf)(int num, char ascii), void(*drawf)(void))
260 {
261         ui_callback_list[slotnr].flag = UI_SLOTUSED;
262         ui_callback_list[slotnr].draw = drawf;
263         ui_callback_list[slotnr].keydown = keydownf;
264 }
265
266 void UI_Callback_ResetSlot(int slotnr)
267 {
268         ui_callback_list[slotnr].flag = 0;
269 }
270
271 void UI_Callback_Draw(void)
272 {
273         int i;
274         for(i = 0; i < UI_MAX_CALLBACK_COUNT; i++)
275                 if(ui_callback_list[i].flag & UI_SLOTUSED && ui_callback_list[i].draw)
276                         ui_callback_list[i].draw();
277 }
278
279 void UI_Callback_KeyDown(int num, char ascii)
280 {
281         if(ui_callback_list[key_dest - 3].flag & UI_SLOTUSED && ui_callback_list[key_dest - 3].keydown)
282                 ui_callback_list[key_dest - 3].keydown(num, ascii);
283 }