* UFO: Alien Invasion surface plugin
[xonotic/netradiant.git] / plugins / surface_ufoai / surfaceflagsdialog_ufoai.cpp
1 /*
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 #include <gtk/gtk.h>
23 #include <gdk/gdkkeysyms.h>
24
25 #include "surfdlg_plugin.h"
26
27 #include "surfaceflagsdialog_ufoai.h"
28
29 GtkWidget *notebook1;
30
31 // 32 bit is the max
32 #define MAX_BUTTONS 32
33
34 GtkWidget *surface_buttons[MAX_BUTTONS];
35 GtkWidget *content_buttons[MAX_BUTTONS];
36
37 GtkWidget *value_entry;
38 gboolean setup_buttons = TRUE;
39
40 int working_surface_flags;
41 int surface_mask;
42 int working_content_flags;
43 int content_mask;
44 int working_value;
45
46 inline void set_inconsistent(GtkWidget *toggle_button)
47 {
48         gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON (toggle_button), TRUE);
49 }
50
51 inline void clear_inconsistent(GtkWidget *toggle_button)
52 {
53         if ( gtk_toggle_button_get_inconsistent(GTK_TOGGLE_BUTTON (toggle_button)) )
54         {
55                 gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON (toggle_button), FALSE);
56         }
57 }
58
59 void clear_all_inconsistent(void)
60 {
61         int i;
62
63         for (i = 0; i < MAX_BUTTONS; i++) {
64                 clear_inconsistent( surface_buttons[i] );
65                 clear_inconsistent( content_buttons[i] );
66         }
67 }
68
69 void clear_all_buttons_and_values()
70 {
71         int i;
72
73         for (i = 0; i < MAX_BUTTONS; i++) {
74                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON ( surface_buttons[i] ), FALSE);
75                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON ( content_buttons[i] ), FALSE);
76         }
77
78         gtk_entry_set_text( (GtkEntry *)value_entry, "");
79 }
80
81 void SetFlagButtons_UFOAI(texdef_to_face_t *texdef_face_list, bool b_isListEmpty)
82 {
83         int contents = 0;
84         int flags = 0;
85         int value = 0;
86         int diff_contents = 0;
87         int diff_flags = 0;
88         gboolean diff_value = FALSE;
89         char tex_buff[11];
90         texdef_t* tmp_texdef;
91         texdef_to_face_t* temp_texdef_face_list;
92         int i;
93
94         setup_buttons = TRUE;
95         working_surface_flags = 0;
96         surface_mask = 0;
97         working_content_flags = 0;
98         content_mask = 0;
99         working_value = 0;
100
101         if (!b_isListEmpty) {
102                 tmp_texdef = &texdef_face_list->texdef;
103                 contents = tmp_texdef->contents;
104                 flags = tmp_texdef->flags;
105                 value = tmp_texdef->value;
106
107                 Sys_Printf("Surface: %d\tContents: %d\tValue: %d\ttmp_texdef\n",tmp_texdef->flags,tmp_texdef->contents,tmp_texdef->value);
108                 Sys_Printf("Surface: %d\tContents: %d\tValue: %d\n",flags,contents,value);
109
110                 for (temp_texdef_face_list = texdef_face_list->next; temp_texdef_face_list; temp_texdef_face_list = temp_texdef_face_list->next)
111                 {
112                         tmp_texdef = &temp_texdef_face_list->texdef;
113                         diff_contents |= contents ^ tmp_texdef->contents;  // Figure out which buttons are inconsistent
114                         diff_flags |= flags ^ tmp_texdef->flags;
115                         if (tmp_texdef->value != value)
116                                 diff_value = TRUE;
117
118                         Sys_Printf("Surface: %d\tContents: %d\tValue: %d\ttmp_texdef\n",tmp_texdef->flags,tmp_texdef->contents,tmp_texdef->value);
119                         Sys_Printf("Surface: %d\tContents: %d\tValue: %d\n",flags,contents,value);
120                 }
121         }
122
123         clear_all_inconsistent();
124
125         // If no faces/brushes are selected, clear everything and bail
126         if (b_isListEmpty) {
127                 clear_all_buttons_and_values();
128                 setup_buttons = FALSE;
129                 return;
130         }
131
132         for (i = 0; i < MAX_BUTTONS; i++) {
133                 // Set surface buttons to reflect brush/face flags, contents, and values
134                 if(diff_flags & (1 << i))
135                         set_inconsistent(surface_buttons[i]);
136                 else if(flags & (1 << i))
137                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (surface_buttons[i]), TRUE);
138                 else
139                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (surface_buttons[i]), FALSE);
140
141                 if(diff_contents & (1 << i))
142                         set_inconsistent(content_buttons[i]);
143                 else if(contents & (1 << i))
144                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (content_buttons[i]), TRUE);
145                 else
146                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (content_buttons[i]), FALSE);
147         }
148
149         // Set Value
150         if (diff_value)
151                 gtk_entry_set_text( (GtkEntry *)value_entry, "");
152         else {
153                 working_value = value;
154                 sprintf( tex_buff, "%d", value);
155                 gtk_entry_set_text( (GtkEntry *)value_entry, tex_buff);
156         }
157
158         setup_buttons = FALSE;
159 }
160
161 void SetChangeInFlags_Face_UFOAI (texdef_to_face_t *texdef_face_list)
162 {
163         texdef_to_face_t *temp_texdef_face_list;
164         texdef_t *tmp_texdef;
165
166         for (temp_texdef_face_list = texdef_face_list; temp_texdef_face_list; temp_texdef_face_list = temp_texdef_face_list->next)
167         {
168                 tmp_texdef = &temp_texdef_face_list->texdef;
169                 tmp_texdef->flags = (tmp_texdef->flags & ~surface_mask) | working_surface_flags;
170                 tmp_texdef->contents = (tmp_texdef->contents & ~content_mask) | working_content_flags;
171                 tmp_texdef->value = working_value;
172                 Sys_Printf("content_flag: %d     content_mask: %d\n",working_content_flags,content_mask);
173                 Sys_Printf("content: %d\n",tmp_texdef->contents);
174         }
175 }
176
177 inline void change_surfaceflag (GtkWidget *togglebutton, int sur_flag, gboolean change_flag_to)
178 {
179         if (!setup_buttons) // If we're setting up the buttons, we really don't need to
180         {                   // set flags that are already set
181                 if (gtk_toggle_button_get_inconsistent(GTK_TOGGLE_BUTTON (togglebutton))) // Clear out inconsistent, if set
182                         clear_inconsistent(GTK_WIDGET (togglebutton));
183
184                 surface_mask |= sur_flag;
185
186                 if (change_flag_to)
187                         working_surface_flags |= sur_flag;
188                 else
189                         working_surface_flags &= ~sur_flag;
190         }
191 }
192
193 inline void change_contentflag (GtkWidget *togglebutton, int content_flag, gboolean change_flag_to)
194 {
195         if ( (!setup_buttons) )  // If we're setting up the buttons, we really don't need to
196         {                        // set flags that are already set
197                 if (gtk_toggle_button_get_inconsistent(GTK_TOGGLE_BUTTON (togglebutton)))
198                         clear_inconsistent(togglebutton);
199                 //if (g_ptrSelectedFaces.GetSize() == 0)  // Only changing content flags on whole brushes, not faces.
200                 //{
201                 content_mask |= content_flag;
202
203                 if (change_flag_to)
204                         working_content_flags |= content_flag;
205                 else
206                         working_content_flags &= ~content_flag;
207                 //}
208                 Sys_Printf("content_flag: %d     content_mask: %d\n",content_flag,content_mask);
209         }
210 }
211
212 // Surface Flags Callbacks
213 void on_surface_button_toggled (GtkToggleButton *togglebutton, gpointer user_data)
214 {
215         int flag = *(int*)user_data;
216         change_surfaceflag(GTK_WIDGET (togglebutton), flag, (GTK_TOGGLE_BUTTON (togglebutton)->active));
217 }
218
219 // Content Flags Callbacks
220 void on_content_button_toggled (GtkToggleButton *togglebutton, gpointer user_data)
221 {
222         int flag = *(int*)user_data;
223         change_contentflag(GTK_WIDGET (togglebutton), flag, (GTK_TOGGLE_BUTTON (togglebutton)->active));
224 }
225
226 // Value Entry Callback
227 void on_value_entry_changed (GtkEditable *editable, gpointer user_data)
228 {
229         if ( (!setup_buttons) )  // If we're setting up the buttons, don't change value
230         working_value = atoi( gtk_entry_get_text( (GtkEntry*)editable) );
231 }
232
233 void on_value_entry_insert_text (GtkEditable *editable, gchar *new_text, gint new_text_length, gint *position, gpointer user_data)
234 {
235         int i, count=0;
236         gchar *result;
237
238         // Limit input to digits, throwing out anything else
239         // Modified from Gtk FAQ for text filtering of GtkEntry
240         result = g_new (gchar, new_text_length);
241
242         for (i=0; i < new_text_length; i++) {
243                 if (!isdigit(new_text[i]))
244                         continue;
245                 result[count++] = new_text[i];
246         }
247
248         if (count > 0) {
249                 gtk_signal_handler_block_by_func (GTK_OBJECT (editable),
250                                                 GTK_SIGNAL_FUNC (on_value_entry_insert_text),
251                                                 user_data);
252                 gtk_editable_insert_text (editable, result, count, position);
253                 gtk_signal_handler_unblock_by_func (GTK_OBJECT (editable),
254                                                 GTK_SIGNAL_FUNC (on_value_entry_insert_text),
255                                                 user_data);
256         }
257         gtk_signal_emit_stop_by_name (GTK_OBJECT (editable), "insert_text");
258
259         g_free (result);
260 }
261
262 void on_surfacebutton_clicked (GtkButton *button, gpointer user_data)
263 {
264         gtk_notebook_set_page (GTK_NOTEBOOK(notebook1), 0);
265 }
266
267 void on_contentbutton_clicked (GtkButton *button, gpointer user_data)
268 {
269         gtk_notebook_set_page (GTK_NOTEBOOK(notebook1), 1);
270 }
271
272 // FIXME: This should be in the ufoai.game
273 static const char *surfaceFlags[] = {
274         "light",
275         "slick",
276         "",
277         "warp",
278         "trans33",
279         "trans66",
280         "flow",
281         "nodraw",
282         "hint",
283         "skip",
284         "phong",
285         "",
286         "",
287         "",
288         "",
289         "",
290         "",
291         "",
292         "",
293         "",
294         "",
295         "",
296         "",
297         "",
298         "",
299         "alphatest",
300         "",
301         "",
302         "",
303         "",
304         "",
305         ""
306 };
307
308 static const char *contentFlags[] = {
309         "solid",
310         "window",
311         "",
312         "fireaffected",
313         "",
314         "water",
315         "",
316         "",
317         "level1",
318         "level2",
319         "level3",
320         "level4",
321         "level5",
322         "level6",
323         "level7",
324         "level8",
325         "actorclip",
326         "passable",
327         "footstep",
328         "",
329         "",
330         "",
331         "",
332         "",
333         "origin",
334         "weaponclip",
335         "",
336         "detail",
337         "",
338         "",
339         "stepon",
340         ""
341 };
342
343 #define UFOAI_FLAG_BUTTON_BORDER 3
344
345 GtkWidget* Create_UFOAIFlagsDialog (GtkWidget* surfacedialog_widget)
346 {
347         GtkWidget *frame1;
348         GtkWidget *vbox1;
349         GtkWidget *vbox2;
350         GtkWidget *vbox3;
351         GtkWidget *vbox4;
352         GtkWidget *table4;
353         GtkWidget *hbox2;
354         GtkWidget *hbox3;
355         GtkWidget *hseparator1;
356         GtkWidget *value_label;
357         GtkWidget *label5;
358         GtkWidget *table3;
359         GtkWidget *label6;
360         int flag = 0;
361         int i, x, y;
362
363         frame1 = gtk_frame_new ("Flags");
364         gtk_widget_show (frame1);
365         gtk_container_add (GTK_CONTAINER (surfacedialog_widget), frame1);
366
367         vbox1 = gtk_vbox_new (FALSE, 0);
368         gtk_widget_show (vbox1);
369         gtk_container_add (GTK_CONTAINER (frame1), vbox1);
370
371         notebook1 = gtk_notebook_new ();
372         gtk_widget_show (notebook1);
373         gtk_box_pack_start (GTK_BOX (vbox1), notebook1, TRUE, TRUE, 0);
374         gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook1), TRUE);
375         gtk_container_set_border_width (GTK_CONTAINER (notebook1), 5);
376
377         vbox2 = gtk_vbox_new (FALSE, 0);
378         gtk_widget_show (vbox2);
379         gtk_container_add (GTK_CONTAINER (notebook1), vbox2);
380
381         table4 = gtk_table_new (8, 4, FALSE);
382         gtk_widget_show (table4);
383         gtk_box_pack_start (GTK_BOX (vbox2), table4, TRUE, TRUE, 0);
384
385         y = -1;
386         for (i = 0; i < MAX_BUTTONS; i++) {
387                 if (!(i % 4))
388                         y++;
389                 x = i % 4;
390                 flag = (1 << i);
391                 surface_buttons[i] = gtk_toggle_button_new_with_label (surfaceFlags[i]);
392                 gtk_signal_connect(GTK_OBJECT (surface_buttons[i]), "toggled", GTK_SIGNAL_FUNC(on_surface_button_toggled), &flag);
393                 gtk_widget_show(surface_buttons[i]);
394                 gtk_table_attach(GTK_TABLE (table4), surface_buttons[i], 0 + x, 1 + x, (0 + y), (1 + y),
395                                                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
396                                                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
397                 gtk_container_set_border_width (GTK_CONTAINER (surface_buttons[i]), UFOAI_FLAG_BUTTON_BORDER);
398         }
399
400         hseparator1 = gtk_hseparator_new ();
401         gtk_widget_show (hseparator1);
402         gtk_box_pack_start (GTK_BOX (vbox2), hseparator1, FALSE, FALSE, 0);
403         gtk_widget_set_usize (hseparator1, -2, 5);
404
405         hbox2 = gtk_hbox_new (FALSE, 0);
406         gtk_widget_show (hbox2);
407         gtk_box_pack_start (GTK_BOX (vbox2), hbox2, FALSE, FALSE, 0);
408
409         hbox3 = gtk_hbox_new (FALSE, 0);
410         gtk_widget_show (hbox3);
411         gtk_box_pack_start (GTK_BOX (hbox2), hbox3, TRUE, TRUE, 0);
412
413         vbox4 = gtk_vbox_new (FALSE, 0);
414         gtk_widget_show (vbox4);
415         gtk_box_pack_start (GTK_BOX (hbox3), vbox4, TRUE, TRUE, 0);
416
417         value_label = gtk_label_new (" Value: ");
418         gtk_widget_show (value_label);
419         gtk_box_pack_start (GTK_BOX (hbox3), value_label, FALSE, FALSE, 0);
420
421         value_entry = gtk_entry_new ();
422         gtk_signal_connect (GTK_OBJECT (value_entry), "changed",
423                                                 GTK_SIGNAL_FUNC (on_value_entry_changed),
424                                                 NULL);
425         gtk_signal_connect (GTK_OBJECT (value_entry), "insert_text",
426                                                 GTK_SIGNAL_FUNC (on_value_entry_insert_text),
427                                                 NULL);
428         gtk_entry_set_max_length( (GtkEntry *)value_entry, 11);
429         gtk_widget_show (value_entry);
430         gtk_box_pack_start (GTK_BOX (hbox3), value_entry, TRUE, TRUE, 0);
431
432         vbox3 = gtk_vbox_new (FALSE, 0);
433         gtk_widget_show (vbox3);
434         gtk_box_pack_start (GTK_BOX (hbox3), vbox3, TRUE, TRUE, 0);
435
436         label5 = gtk_label_new ("Surface Flags");
437         gtk_widget_show (label5);
438         gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 0), label5);
439
440         table3 = gtk_table_new (8, 4, FALSE);
441         gtk_widget_show (table3);
442         gtk_container_add (GTK_CONTAINER (notebook1), table3);
443
444         y = -1;
445         for (i = 0; i < MAX_BUTTONS; i++) {
446                 if (!(i % 4))
447                         y++;
448                 x = i % 4;
449                 flag = (1 << i);
450                 content_buttons[i] = gtk_toggle_button_new_with_label(contentFlags[i]);
451                 gtk_signal_connect(GTK_OBJECT (content_buttons[i]), "toggled", GTK_SIGNAL_FUNC (on_content_button_toggled), &flag);
452                 gtk_widget_show(content_buttons[i]);
453                 gtk_table_attach(GTK_TABLE (table3), content_buttons[i], 0 + x, 1 + x, (0 + y), (1 + y),
454                                                 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
455                                                 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
456                 gtk_container_set_border_width (GTK_CONTAINER (content_buttons[i]), UFOAI_FLAG_BUTTON_BORDER);
457         }
458
459         label6 = gtk_label_new ("Content Flags");
460         gtk_widget_show (label6);
461         gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 1), label6);
462
463         return frame1;
464 }
465