687af055dbfe0eebc213540617cbdd71875ac1e3
[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 static const int flagBitMasks[] = {
344         1<<0,
345         1<<1,
346         1<<2,
347         1<<3,
348         1<<4,
349         1<<5,
350         1<<6,
351         1<<7,
352         1<<8,
353         1<<9,
354         1<<10,
355         1<<11,
356         1<<12,
357         1<<13,
358         1<<14,
359         1<<15,
360         1<<16,
361         1<<17,
362         1<<18,
363         1<<19,
364         1<<20,
365         1<<21,
366         1<<22,
367         1<<23,
368         1<<24,
369         1<<25,
370         1<<26,
371         1<<27,
372         1<<28,
373         1<<29,
374         1<<30,
375         1<<31,
376 };
377
378 #define UFOAI_FLAG_BUTTON_BORDER 3
379
380 GtkWidget* Create_UFOAIFlagsDialog (GtkWidget* surfacedialog_widget)
381 {
382         GtkWidget *frame1;
383         GtkWidget *vbox1;
384         GtkWidget *vbox2;
385         GtkWidget *vbox3;
386         GtkWidget *vbox4;
387         GtkWidget *table4;
388         GtkWidget *hbox2;
389         GtkWidget *hbox3;
390         GtkWidget *hseparator1;
391         GtkWidget *value_label;
392         GtkWidget *label5;
393         GtkWidget *table3;
394         GtkWidget *label6;
395         int i, x, y;
396
397         frame1 = gtk_frame_new ("Flags");
398         gtk_widget_show (frame1);
399         gtk_container_add (GTK_CONTAINER (surfacedialog_widget), frame1);
400
401         vbox1 = gtk_vbox_new (FALSE, 0);
402         gtk_widget_show (vbox1);
403         gtk_container_add (GTK_CONTAINER (frame1), vbox1);
404
405         notebook1 = gtk_notebook_new ();
406         gtk_widget_show (notebook1);
407         gtk_box_pack_start (GTK_BOX (vbox1), notebook1, TRUE, TRUE, 0);
408         gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook1), TRUE);
409         gtk_container_set_border_width (GTK_CONTAINER (notebook1), 5);
410
411         vbox2 = gtk_vbox_new (FALSE, 0);
412         gtk_widget_show (vbox2);
413         gtk_container_add (GTK_CONTAINER (notebook1), vbox2);
414
415         table4 = gtk_table_new (8, 4, FALSE);
416         gtk_widget_show (table4);
417         gtk_box_pack_start (GTK_BOX (vbox2), table4, TRUE, TRUE, 0);
418
419         y = -1;
420         for (i = 0; i < MAX_BUTTONS; i++) {
421                 if (!(i % 4))
422                         y++;
423                 x = i % 4;
424                 surface_buttons[i] = gtk_toggle_button_new_with_label (surfaceFlags[i]);
425                 gtk_signal_connect(GTK_OBJECT (surface_buttons[i]), "toggled", GTK_SIGNAL_FUNC(on_surface_button_toggled), &flagBitMasks[i]);
426                 gtk_widget_show(surface_buttons[i]);
427                 gtk_table_attach(GTK_TABLE (table4), surface_buttons[i], 0 + x, 1 + x, (0 + y), (1 + y),
428                                                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
429                                                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
430                 gtk_container_set_border_width (GTK_CONTAINER (surface_buttons[i]), UFOAI_FLAG_BUTTON_BORDER);
431         }
432
433         hseparator1 = gtk_hseparator_new ();
434         gtk_widget_show (hseparator1);
435         gtk_box_pack_start (GTK_BOX (vbox2), hseparator1, FALSE, FALSE, 0);
436         gtk_widget_set_usize (hseparator1, -2, 5);
437
438         hbox2 = gtk_hbox_new (FALSE, 0);
439         gtk_widget_show (hbox2);
440         gtk_box_pack_start (GTK_BOX (vbox2), hbox2, FALSE, FALSE, 0);
441
442         hbox3 = gtk_hbox_new (FALSE, 0);
443         gtk_widget_show (hbox3);
444         gtk_box_pack_start (GTK_BOX (hbox2), hbox3, TRUE, TRUE, 0);
445
446         vbox4 = gtk_vbox_new (FALSE, 0);
447         gtk_widget_show (vbox4);
448         gtk_box_pack_start (GTK_BOX (hbox3), vbox4, TRUE, TRUE, 0);
449
450         value_label = gtk_label_new (" Value: ");
451         gtk_widget_show (value_label);
452         gtk_box_pack_start (GTK_BOX (hbox3), value_label, FALSE, FALSE, 0);
453
454         value_entry = gtk_entry_new ();
455         gtk_signal_connect (GTK_OBJECT (value_entry), "changed",
456                                                 GTK_SIGNAL_FUNC (on_value_entry_changed),
457                                                 NULL);
458         gtk_signal_connect (GTK_OBJECT (value_entry), "insert_text",
459                                                 GTK_SIGNAL_FUNC (on_value_entry_insert_text),
460                                                 NULL);
461         gtk_entry_set_max_length( (GtkEntry *)value_entry, 11);
462         gtk_widget_show (value_entry);
463         gtk_box_pack_start (GTK_BOX (hbox3), value_entry, TRUE, TRUE, 0);
464
465         vbox3 = gtk_vbox_new (FALSE, 0);
466         gtk_widget_show (vbox3);
467         gtk_box_pack_start (GTK_BOX (hbox3), vbox3, TRUE, TRUE, 0);
468
469         label5 = gtk_label_new ("Surface Flags");
470         gtk_widget_show (label5);
471         gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 0), label5);
472
473         table3 = gtk_table_new (8, 4, FALSE);
474         gtk_widget_show (table3);
475         gtk_container_add (GTK_CONTAINER (notebook1), table3);
476
477         y = -1;
478         for (i = 0; i < MAX_BUTTONS; i++) {
479                 if (!(i % 4))
480                         y++;
481                 x = i % 4;
482                 content_buttons[i] = gtk_toggle_button_new_with_label(contentFlags[i]);
483                 gtk_signal_connect(GTK_OBJECT (content_buttons[i]), "toggled", GTK_SIGNAL_FUNC (on_content_button_toggled), &flagBitMasks[i]);
484                 gtk_widget_show(content_buttons[i]);
485                 gtk_table_attach(GTK_TABLE (table3), content_buttons[i], 0 + x, 1 + x, (0 + y), (1 + y),
486                                                 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
487                                                 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
488                 gtk_container_set_border_width (GTK_CONTAINER (content_buttons[i]), UFOAI_FLAG_BUTTON_BORDER);
489         }
490
491         label6 = gtk_label_new ("Content Flags");
492         gtk_widget_show (label6);
493         gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 1), label6);
494
495         return frame1;
496 }
497