]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/meshtex/GeneralFunctionDialog.cpp
Merge branch 'NateEag-master-patch-12920' into 'master'
[xonotic/netradiant.git] / contrib / meshtex / GeneralFunctionDialog.cpp
1 /**
2  * @file GeneralFunctionDialog.cpp
3  * Implements the GeneralFunctionDialog class.
4  * @ingroup meshtex-ui
5  */
6
7 /*
8  * Copyright 2012 Joel Baxter
9  *
10  * This file is part of MeshTex.
11  *
12  * MeshTex is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * MeshTex is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with MeshTex.  If not, see <http://www.gnu.org/licenses/>.
24  */
25
26 #include <gtk/gtk.h>
27
28 #include "GenericPluginUI.h"
29 #include "GeneralFunctionDialog.h"
30 #include "PluginUIMessages.h"
31
32 #include "iundo.h"
33
34
35 /**
36  * Constructor. See MeshEntity::GeneralFunction for details of how these
37  * arguments are interpreted.
38  *
39  * @param sFactors      Factors to determine the S texture coords; NULL if S
40  *                      axis unaffected.
41  * @param tFactors      Factors to determine the T texture coords; NULL if T
42  *                      axis unaffected.
43  * @param alignRow      Pointer to zero-point row; if NULL, row 0 is assumed.
44  * @param alignCol      Pointer to zero-point column; if NULL, column 0 is
45  *                      assumed.
46  * @param refRow        Pointer to reference row description, including how
47  *                      to use the reference; NULL if no reference.
48  * @param refCol        Pointer to reference column description, including
49  *                      how to use the reference; NULL if no reference.
50  * @param surfaceValues true if calculations are for S/T values on the mesh
51  *                      surface; false if calculations are for S/T values at
52  *                      the control points.
53  */
54 GeneralFunctionDialog::GeneralFunctionVisitor::GeneralFunctionVisitor(
55    const MeshEntity::GeneralFunctionFactors *sFactors,
56    const MeshEntity::GeneralFunctionFactors *tFactors,
57    const MeshEntity::SliceDesignation *alignRow,
58    const MeshEntity::SliceDesignation *alignCol,
59    const MeshEntity::RefSliceDescriptor *refRow,
60    const MeshEntity::RefSliceDescriptor *refCol,
61    bool surfaceValues) :
62    _sFactors(sFactors),
63    _tFactors(tFactors),
64    _alignRow(alignRow),
65    _alignCol(alignCol),
66    _refRow(refRow),
67    _refCol(refCol),
68    _surfaceValues(surfaceValues)
69 {
70 }
71
72 /**
73  * Visitor action; invoke MeshEntity::GeneralFunction on a mesh.
74  *
75  * @param [in,out] meshEntity The mesh.
76  *
77  * @return true.
78  */
79 bool
80 GeneralFunctionDialog::GeneralFunctionVisitor::Execute(MeshEntity& meshEntity) const
81 {
82    meshEntity.GeneralFunction(_sFactors, _tFactors,
83                               _alignRow, _alignCol, _refRow, _refCol,
84                               _surfaceValues);
85    return true;
86 }
87
88 /**
89  * Constructor. Configure the dialog window and create all the contained
90  * widgets. Connect widgets to callbacks as necessary.
91  *
92  * @param key The unique key identifying this dialog.
93  */
94 GeneralFunctionDialog::GeneralFunctionDialog(const std::string& key) :
95    GenericDialog(key),
96    _nullVisitor(new MeshVisitor())
97 {
98    // Enable the usual handling of the close event.
99    CreateWindowCloseCallback();
100
101    // Configure the dialog window.
102    gtk_window_set_resizable(GTK_WINDOW(_dialog), FALSE);
103    gtk_window_set_title(GTK_WINDOW(_dialog), DIALOG_GEN_FUNC_TITLE);
104    gtk_container_set_border_width(GTK_CONTAINER(_dialog), 10);
105
106    // Create the contained widgets.
107
108    GtkWidget *table;
109    GtkWidget *entry;
110    GtkWidget *applybutton, *refbutton, *button;
111    GtkWidget *separator;
112    GtkWidget *label;
113    GtkWidget *mainvbox, *vbox, *hbox, *mainhbox;
114    GtkWidget *frame;
115
116    table = gtk_table_new(6, 13, FALSE);
117    gtk_table_set_row_spacing(GTK_TABLE(table), 0, 5);
118    gtk_table_set_row_spacing(GTK_TABLE(table), 1, 10);
119    gtk_table_set_row_spacing(GTK_TABLE(table), 3, 15);
120    gtk_table_set_row_spacing(GTK_TABLE(table), 4, 15);
121    gtk_container_add(GTK_CONTAINER(_dialog), table);
122    gtk_widget_show(table);
123
124    hbox = gtk_hbox_new(TRUE, 10);
125    gtk_table_attach(GTK_TABLE(table), hbox, 0, 13, 0, 1, GTK_SHRINK, GTK_EXPAND, 0, 0);
126    gtk_widget_show(hbox);
127
128    // Mutually exclusive "Surface values" and "Control values" radio buttons.
129
130    button = gtk_radio_button_new_with_label(NULL,
131                                             DIALOG_GEN_FUNC_SURFACE_VALUES);
132    gtk_object_set_data(GTK_OBJECT(_dialog), "surface", button);
133    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
134    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
135    gtk_widget_show(button);
136
137    button = gtk_radio_button_new_with_label(
138       gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
139                              DIALOG_GEN_FUNC_CONTROL_VALUES);
140    gtk_object_set_data(GTK_OBJECT(_dialog), "control", button);
141    gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
142    gtk_widget_show(button);
143
144    separator = gtk_hseparator_new();
145    gtk_table_attach_defaults(GTK_TABLE(table), separator, 0, 13, 1, 2);
146    gtk_widget_show(separator);
147
148    // Checkbox for the "S" row of factors. All the other widgets on this row
149    // will have a dependence registered on this checkbox; i.e. they will only
150    // be active when it is checked.
151
152    applybutton = gtk_check_button_new();
153    gtk_object_set_data(GTK_OBJECT(_dialog), "s_apply", applybutton);
154    gtk_table_attach_defaults(GTK_TABLE(table), applybutton, 0, 1, 2, 3);
155    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(applybutton), TRUE);
156    gtk_widget_show(applybutton);
157
158    label = gtk_label_new(DIALOG_GEN_FUNC_S_FUNC_LABEL);
159    gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 2, 3);
160    gtk_widget_show(label);
161
162    UIInstance().RegisterWidgetDependence(applybutton, label);
163
164    entry = gtk_entry_new();
165    gtk_object_set_data(GTK_OBJECT(_dialog), "s_oldval", entry);
166    gtk_entry_set_text(GTK_ENTRY(entry), "1.0");
167    gtk_table_attach_defaults(GTK_TABLE(table), entry, 2, 3, 2, 3);
168    gtk_widget_set_usize(entry, 50, -2);
169    gtk_widget_show(entry);
170
171    UIInstance().RegisterWidgetDependence(applybutton, entry);
172
173    label = gtk_label_new(DIALOG_GEN_FUNC_OLD_S_LABEL);
174    gtk_table_attach_defaults(GTK_TABLE(table), label, 3, 4, 2, 3);
175    gtk_widget_show(label);
176
177    UIInstance().RegisterWidgetDependence(applybutton, label);
178
179    entry = gtk_entry_new();
180    gtk_object_set_data(GTK_OBJECT(_dialog), "s_rowdist", entry);
181    gtk_entry_set_text(GTK_ENTRY(entry), "0.0");
182    gtk_table_attach_defaults(GTK_TABLE(table), entry, 4, 5, 2, 3);
183    gtk_widget_set_usize(entry, 50, -2);
184    gtk_widget_show(entry);
185
186    UIInstance().RegisterWidgetDependence(applybutton, entry);
187
188    label = gtk_label_new(DIALOG_GEN_FUNC_ROW_DIST_LABEL);
189    gtk_table_attach_defaults(GTK_TABLE(table), label, 5, 6, 2, 3);
190    gtk_widget_show(label);
191
192    UIInstance().RegisterWidgetDependence(applybutton, label);
193
194    entry = gtk_entry_new();
195    gtk_object_set_data(GTK_OBJECT(_dialog), "s_coldist", entry);
196    gtk_entry_set_text(GTK_ENTRY(entry), "0.0");
197    gtk_table_attach_defaults(GTK_TABLE(table), entry, 6, 7, 2, 3);
198    gtk_widget_set_usize(entry, 50, -2);
199    gtk_widget_show(entry);
200
201    UIInstance().RegisterWidgetDependence(applybutton, entry);
202
203    label = gtk_label_new(DIALOG_GEN_FUNC_COL_DIST_LABEL);
204    gtk_table_attach_defaults(GTK_TABLE(table), label, 7, 8, 2, 3);
205    gtk_widget_show(label);
206
207    UIInstance().RegisterWidgetDependence(applybutton, label);
208
209    entry = gtk_entry_new();
210    gtk_object_set_data(GTK_OBJECT(_dialog), "s_rownum", entry);
211    gtk_entry_set_text(GTK_ENTRY(entry), "0.0");
212    gtk_table_attach_defaults(GTK_TABLE(table), entry, 8, 9, 2, 3);
213    gtk_widget_set_usize(entry, 50, -2);
214    gtk_widget_show(entry);
215
216    UIInstance().RegisterWidgetDependence(applybutton, entry);
217
218    label = gtk_label_new(DIALOG_GEN_FUNC_ROW_NUM_LABEL);
219    gtk_table_attach_defaults(GTK_TABLE(table), label, 9, 10, 2, 3);
220    gtk_widget_show(label);
221
222    UIInstance().RegisterWidgetDependence(applybutton, label);
223
224    entry = gtk_entry_new();
225    gtk_object_set_data(GTK_OBJECT(_dialog), "s_colnum", entry);
226    gtk_entry_set_text(GTK_ENTRY(entry), "0.0");
227    gtk_table_attach_defaults(GTK_TABLE(table), entry, 10, 11, 2, 3);
228    gtk_widget_set_usize(entry, 50, -2);
229    gtk_widget_show(entry);
230
231    UIInstance().RegisterWidgetDependence(applybutton, entry);
232
233    label = gtk_label_new(DIALOG_GEN_FUNC_COL_NUM_LABEL);
234    gtk_table_attach_defaults(GTK_TABLE(table), label, 11, 12, 2, 3);
235    gtk_widget_show(label);
236
237    UIInstance().RegisterWidgetDependence(applybutton, label);
238
239    entry = gtk_entry_new();
240    gtk_object_set_data(GTK_OBJECT(_dialog), "s_constant", entry);
241    gtk_entry_set_text(GTK_ENTRY(entry), "0.0");
242    gtk_table_attach_defaults(GTK_TABLE(table), entry, 12, 13, 2, 3);
243    gtk_widget_set_usize(entry, 50, -2);
244    gtk_widget_show(entry);
245
246    UIInstance().RegisterWidgetDependence(applybutton, entry);
247
248    // Checkbox for the "T" row of factors. All the other widgets on this row
249    // will have a dependence registered on this checkbox; i.e. they will only
250    // be active when it is checked.
251
252    applybutton = gtk_check_button_new();
253    gtk_object_set_data(GTK_OBJECT(_dialog), "t_apply", applybutton);
254    gtk_table_attach_defaults(GTK_TABLE(table), applybutton, 0, 1, 3, 4);
255    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(applybutton), TRUE);
256    gtk_widget_show(applybutton);
257
258    label = gtk_label_new(DIALOG_GEN_FUNC_T_FUNC_LABEL);
259    gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 3, 4);
260    gtk_widget_show(label);
261
262    UIInstance().RegisterWidgetDependence(applybutton, label);
263
264    entry = gtk_entry_new();
265    gtk_object_set_data(GTK_OBJECT(_dialog), "t_oldval", entry);
266    gtk_entry_set_text(GTK_ENTRY(entry), "1.0");
267    gtk_table_attach_defaults(GTK_TABLE(table), entry, 2, 3, 3, 4);
268    gtk_widget_set_usize(entry, 50, -2);
269    gtk_widget_show(entry);
270
271    UIInstance().RegisterWidgetDependence(applybutton, entry);
272
273    label = gtk_label_new(DIALOG_GEN_FUNC_OLD_T_LABEL);
274    gtk_table_attach_defaults(GTK_TABLE(table), label, 3, 4, 3, 4);
275    gtk_widget_show(label);
276
277    UIInstance().RegisterWidgetDependence(applybutton, label);
278
279    entry = gtk_entry_new();
280    gtk_object_set_data(GTK_OBJECT(_dialog), "t_rowdist", entry);
281    gtk_entry_set_text(GTK_ENTRY(entry), "0.0");
282    gtk_table_attach_defaults(GTK_TABLE(table), entry, 4, 5, 3, 4);
283    gtk_widget_set_usize(entry, 50, -2);
284    gtk_widget_show(entry);
285
286    UIInstance().RegisterWidgetDependence(applybutton, entry);
287
288    label = gtk_label_new(DIALOG_GEN_FUNC_ROW_DIST_LABEL);
289    gtk_table_attach_defaults(GTK_TABLE(table), label, 5, 6, 3, 4);
290    gtk_widget_show(label);
291
292    UIInstance().RegisterWidgetDependence(applybutton, label);
293
294    entry = gtk_entry_new();
295    gtk_object_set_data(GTK_OBJECT(_dialog), "t_coldist", entry);
296    gtk_entry_set_text(GTK_ENTRY(entry), "0.0");
297    gtk_table_attach_defaults(GTK_TABLE(table), entry, 6, 7, 3, 4);
298    gtk_widget_set_usize(entry, 50, -2);
299    gtk_widget_show(entry);
300
301    UIInstance().RegisterWidgetDependence(applybutton, entry);
302
303    label = gtk_label_new(DIALOG_GEN_FUNC_COL_DIST_LABEL);
304    gtk_table_attach_defaults(GTK_TABLE(table), label, 7, 8, 3, 4);
305    gtk_widget_show(label);
306
307    UIInstance().RegisterWidgetDependence(applybutton, label);
308
309    entry = gtk_entry_new();
310    gtk_object_set_data(GTK_OBJECT(_dialog), "t_rownum", entry);
311    gtk_entry_set_text(GTK_ENTRY(entry), "0.0");
312    gtk_table_attach_defaults(GTK_TABLE(table), entry, 8, 9, 3, 4);
313    gtk_widget_set_usize(entry, 50, -2);
314    gtk_widget_show(entry);
315
316    UIInstance().RegisterWidgetDependence(applybutton, entry);
317
318    label = gtk_label_new(DIALOG_GEN_FUNC_ROW_NUM_LABEL);
319    gtk_table_attach_defaults(GTK_TABLE(table), label, 9, 10, 3, 4);
320    gtk_widget_show(label);
321
322    UIInstance().RegisterWidgetDependence(applybutton, label);
323
324    entry = gtk_entry_new();
325    gtk_object_set_data(GTK_OBJECT(_dialog), "t_colnum", entry);
326    gtk_entry_set_text(GTK_ENTRY(entry), "0.0");
327    gtk_table_attach_defaults(GTK_TABLE(table), entry, 10, 11, 3, 4);
328    gtk_widget_set_usize(entry, 50, -2);
329    gtk_widget_show(entry);
330
331    UIInstance().RegisterWidgetDependence(applybutton, entry);
332
333    label = gtk_label_new(DIALOG_GEN_FUNC_COL_NUM_LABEL);
334    gtk_table_attach_defaults(GTK_TABLE(table), label, 11, 12, 3, 4);
335    gtk_widget_show(label);
336
337    UIInstance().RegisterWidgetDependence(applybutton, label);
338
339    entry = gtk_entry_new();
340    gtk_object_set_data(GTK_OBJECT(_dialog), "t_constant", entry);
341    gtk_entry_set_text(GTK_ENTRY(entry), "0.0");
342    gtk_table_attach_defaults(GTK_TABLE(table), entry, 12, 13, 3, 4);
343    gtk_widget_set_usize(entry, 50, -2);
344    gtk_widget_show(entry);
345
346    UIInstance().RegisterWidgetDependence(applybutton, entry);
347
348    mainhbox = gtk_hbox_new(TRUE, 0);
349    gtk_table_attach(GTK_TABLE(table), mainhbox, 0, 13, 4, 5, GTK_SHRINK, GTK_EXPAND, 0, 0);
350    gtk_widget_show(mainhbox);
351
352    mainvbox = gtk_vbox_new(FALSE, 0);
353    gtk_box_pack_start(GTK_BOX(mainhbox), mainvbox, FALSE, FALSE, 0);
354    gtk_widget_show(mainvbox);
355
356    hbox = gtk_hbox_new(FALSE, 0);
357    gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 5);
358    gtk_widget_show(hbox);
359
360    frame = gtk_frame_new(DIALOG_GEN_FUNC_COL_ALIGN_FRAME_LABEL);
361    gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5);
362    gtk_widget_show(frame);
363
364    vbox = gtk_vbox_new(FALSE, 0);
365    gtk_container_add(GTK_CONTAINER(frame), vbox);
366    gtk_widget_show(vbox);
367
368    hbox = gtk_hbox_new(FALSE, 0);
369    gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
370    gtk_widget_show(hbox);
371
372    // Widgets for specifying the alignment column.
373
374    button = gtk_radio_button_new(NULL);
375    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
376    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
377    gtk_widget_show(button);
378
379    entry = gtk_entry_new();
380    gtk_object_set_data(GTK_OBJECT(_dialog), "col_num_align", entry);
381    gtk_entry_set_text(GTK_ENTRY(entry), "0");
382    gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
383    gtk_widget_set_usize(entry, 25, -2);
384    gtk_widget_show(entry);
385
386    UIInstance().RegisterWidgetDependence(button, entry);
387
388    button = gtk_radio_button_new_with_label(
389       gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
390                              DIALOG_GEN_FUNC_MAX_OPT_LABEL);
391    gtk_object_set_data(GTK_OBJECT(_dialog), "col_max_align", button);
392    gtk_box_pack_end(GTK_BOX(hbox), button, TRUE, FALSE, 5);
393    gtk_widget_show(button);
394
395    hbox = gtk_hbox_new(FALSE, 0);
396    gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 5);
397    gtk_widget_show(hbox);
398
399    // Widgets for specifying the reference row & usage.
400
401    refbutton = gtk_check_button_new_with_label(DIALOG_GEN_FUNC_REF_ROW_FRAME_LABEL);
402    gtk_object_set_data(GTK_OBJECT(_dialog), "row_ref", refbutton);
403    gtk_widget_show(refbutton);
404
405    frame = gtk_frame_new(NULL);
406    gtk_frame_set_label_widget(GTK_FRAME(frame), refbutton);
407    gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5);
408    gtk_widget_show(frame);
409
410    vbox = gtk_vbox_new(FALSE, 0);
411    gtk_container_add(GTK_CONTAINER(frame), vbox);
412    gtk_widget_show(vbox);
413
414    hbox = gtk_hbox_new(FALSE, 0);
415    gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
416    gtk_widget_show(hbox);
417
418    button = gtk_radio_button_new(NULL);
419    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
420    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
421    gtk_widget_set_sensitive(button, FALSE);
422    gtk_widget_show(button);
423
424    UIInstance().RegisterWidgetDependence(refbutton, button);
425
426    entry = gtk_entry_new();
427    gtk_object_set_data(GTK_OBJECT(_dialog), "row_num_ref", entry);
428    gtk_entry_set_text(GTK_ENTRY(entry), "0");
429    gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
430    gtk_widget_set_usize(entry, 25, -2);
431    gtk_widget_set_sensitive(entry, FALSE);
432    gtk_widget_show(entry);
433
434    UIInstance().RegisterWidgetDependence(refbutton, entry);
435    UIInstance().RegisterWidgetDependence(button, entry);
436
437    button = gtk_radio_button_new_with_label(
438       gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
439                              DIALOG_GEN_FUNC_MAX_OPT_LABEL);
440    gtk_object_set_data(GTK_OBJECT(_dialog), "row_max_ref", button);
441    gtk_box_pack_end(GTK_BOX(hbox), button, TRUE, FALSE, 5);
442    gtk_widget_set_sensitive(button, FALSE);
443    gtk_widget_show(button);
444
445    UIInstance().RegisterWidgetDependence(refbutton, button);
446
447    hbox = gtk_hbox_new(FALSE, 0);
448    gtk_box_pack_end(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
449    gtk_widget_show(hbox);
450
451    button = gtk_check_button_new_with_label(DIALOG_GEN_FUNC_REF_TOTAL_OPT_LABEL);
452    gtk_object_set_data(GTK_OBJECT(_dialog), "row_ref_total", button);
453    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
454    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
455    gtk_widget_set_sensitive(button, FALSE);
456    gtk_widget_show(button);
457
458    UIInstance().RegisterWidgetDependence(refbutton, button);
459
460    mainvbox = gtk_vbox_new(FALSE, 0);
461    gtk_box_pack_end(GTK_BOX(mainhbox), mainvbox, FALSE, FALSE, 0);
462    gtk_widget_show(mainvbox);
463
464    hbox = gtk_hbox_new(FALSE, 0);
465    gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 5);
466    gtk_widget_show(hbox);
467
468    frame = gtk_frame_new(DIALOG_GEN_FUNC_ROW_ALIGN_FRAME_LABEL);
469    gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5);
470    gtk_widget_show(frame);
471
472    vbox = gtk_vbox_new(FALSE, 0);
473    gtk_container_add(GTK_CONTAINER(frame), vbox);
474    gtk_widget_show(vbox);
475
476    hbox = gtk_hbox_new(FALSE, 0);
477    gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
478    gtk_widget_show(hbox);
479
480    // Widgets for specifying the alignment row.
481
482    button = gtk_radio_button_new(NULL);
483    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
484    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
485    gtk_widget_show(button);
486
487    entry = gtk_entry_new();
488    gtk_object_set_data(GTK_OBJECT(_dialog), "row_num_align", entry);
489    gtk_entry_set_text(GTK_ENTRY(entry), "0");
490    gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
491    gtk_widget_set_usize(entry, 25, -2);
492    gtk_widget_show(entry);
493
494    UIInstance().RegisterWidgetDependence(button, entry);
495
496    button = gtk_radio_button_new_with_label(
497       gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
498                              DIALOG_GEN_FUNC_MAX_OPT_LABEL);
499    gtk_object_set_data(GTK_OBJECT(_dialog), "row_max_align", button);
500    gtk_box_pack_end(GTK_BOX(hbox), button, TRUE, FALSE, 5);
501    gtk_widget_show(button);
502
503    hbox = gtk_hbox_new(FALSE, 0);
504    gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 5);
505    gtk_widget_show(hbox);
506
507    // Widgets for specifying the reference column & usage.
508
509    refbutton = gtk_check_button_new_with_label(DIALOG_GEN_FUNC_REF_COL_FRAME_LABEL);
510    gtk_object_set_data(GTK_OBJECT(_dialog), "col_ref", refbutton);
511    gtk_widget_show(refbutton);
512
513    frame = gtk_frame_new(NULL);
514    gtk_frame_set_label_widget(GTK_FRAME(frame), refbutton);
515    gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5);
516    gtk_widget_show(frame);
517
518    vbox = gtk_vbox_new(FALSE, 0);
519    gtk_container_add(GTK_CONTAINER(frame), vbox);
520    gtk_widget_show(vbox);
521
522    hbox = gtk_hbox_new(FALSE, 0);
523    gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
524    gtk_widget_show(hbox);
525
526    button = gtk_radio_button_new(NULL);
527    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
528    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
529    gtk_widget_set_sensitive(button, FALSE);
530    gtk_widget_show(button);
531
532    UIInstance().RegisterWidgetDependence(refbutton, button);
533
534    entry = gtk_entry_new();
535    gtk_object_set_data(GTK_OBJECT(_dialog), "col_num_ref", entry);
536    gtk_entry_set_text(GTK_ENTRY(entry), "0");
537    gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
538    gtk_widget_set_usize(entry, 25, -2);
539    gtk_widget_set_sensitive(entry, FALSE);
540    gtk_widget_show(entry);
541
542    UIInstance().RegisterWidgetDependence(refbutton, entry);
543    UIInstance().RegisterWidgetDependence(button, entry);
544
545    button = gtk_radio_button_new_with_label(
546       gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
547                              DIALOG_GEN_FUNC_MAX_OPT_LABEL);
548    gtk_object_set_data(GTK_OBJECT(_dialog), "col_max_ref", button);
549    gtk_box_pack_end(GTK_BOX(hbox), button, TRUE, FALSE, 5);
550    gtk_widget_set_sensitive(button, FALSE);
551    gtk_widget_show(button);
552
553    UIInstance().RegisterWidgetDependence(refbutton, button);
554
555    hbox = gtk_hbox_new(FALSE, 0);
556    gtk_box_pack_end(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
557    gtk_widget_show(hbox);
558
559    button = gtk_check_button_new_with_label(DIALOG_GEN_FUNC_REF_TOTAL_OPT_LABEL);
560    gtk_object_set_data(GTK_OBJECT(_dialog), "col_ref_total", button);
561    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
562    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
563    gtk_widget_set_sensitive(button, FALSE);
564    gtk_widget_show(button);
565
566    UIInstance().RegisterWidgetDependence(refbutton, button);
567
568    hbox = gtk_hbox_new(FALSE, 0);
569    gtk_table_attach_defaults(GTK_TABLE(table), hbox, 0, 13, 5, 6);
570    gtk_widget_show(hbox);
571
572    // Create Cancel button and hook it to callback.
573
574    button = gtk_button_new_with_label(DIALOG_CANCEL_BUTTON);
575    gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
576    gtk_widget_set_usize(button, 60, -2);
577    gtk_widget_show(button);
578
579    CreateCancelButtonCallback(button);
580
581    // Create Apply button and hook it to callback.
582
583    button = gtk_button_new_with_label(DIALOG_APPLY_BUTTON);
584    gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 10);
585    gtk_widget_set_usize (button, 60, -2);
586    gtk_widget_show(button);
587
588    CreateApplyButtonCallback(button);
589
590    // Create OK button and hook it to callback.
591
592    button = gtk_button_new_with_label(DIALOG_OK_BUTTON);
593    gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
594    gtk_widget_set_usize (button, 60, -2);
595    gtk_widget_show(button);
596
597    CreateOkButtonCallback(button);
598 }
599
600 /**
601  * Destructor.
602  */
603 GeneralFunctionDialog::~GeneralFunctionDialog()
604 {
605 }
606
607 /**
608  * Handler for the Apply logic for this dialog. Apply the specified equations
609  * to the selected mesh entities.
610  *
611  * @return true if any meshes are selected, false otherwise.
612  */
613 bool
614 GeneralFunctionDialog::Apply()
615 {
616    // Before doing anything, check to see if there are some meshes selected.
617    _nullVisitor->ResetVisitedCount();
618    GlobalSelectionSystem().foreachSelected(*_nullVisitor);
619    if (_nullVisitor->GetVisitedCount() == 0)
620    {
621       // Nope. Warn and bail out.
622       GenericPluginUI::WarningReportDialog(DIALOG_WARNING_TITLE,
623                                            DIALOG_NOMESHES_MSG);
624       return false;
625    }
626
627    // See if we're going to be affecting the S and/or T texture axis.
628    bool sApply = NamedToggleWidgetActive("s_apply");
629    bool tApply = NamedToggleWidgetActive("t_apply");
630
631    if (!sApply && !tApply)
632    {
633       // Not affecting either, so bail out.
634       return true;
635    }
636
637    // OK read the remaining info from the widgets.
638
639    MeshEntity::GeneralFunctionFactors s, t;
640    MeshEntity::GeneralFunctionFactors *sFactors = NULL;
641    MeshEntity::GeneralFunctionFactors *tFactors = NULL;
642    if (sApply)
643    {
644       // S axis is affected, so read the S factors.
645       s.oldValue = (float)atof(NamedEntryWidgetText("s_oldval"));
646       s.rowDistance = (float)atof(NamedEntryWidgetText("s_rowdist"));
647       s.colDistance = (float)atof(NamedEntryWidgetText("s_coldist"));
648       s.rowNumber = (float)atof(NamedEntryWidgetText("s_rownum"));
649       s.colNumber = (float)atof(NamedEntryWidgetText("s_colnum"));
650       s.constant = (float)atof(NamedEntryWidgetText("s_constant"));
651       sFactors = &s;
652    }
653    if (tApply)
654    {
655       // T axis is affected, so read the T factors.
656       t.oldValue = (float)atof(NamedEntryWidgetText("t_oldval"));
657       t.rowDistance = (float)atof(NamedEntryWidgetText("t_rowdist"));
658       t.colDistance = (float)atof(NamedEntryWidgetText("t_coldist"));
659       t.rowNumber = (float)atof(NamedEntryWidgetText("t_rownum"));
660       t.colNumber = (float)atof(NamedEntryWidgetText("t_colnum"));
661       t.constant = (float)atof(NamedEntryWidgetText("t_constant"));
662       tFactors = &t;
663    }
664    MeshEntity::SliceDesignation alignRow, alignCol;
665    alignRow.maxSlice = NamedToggleWidgetActive("row_max_align");
666    alignRow.index = atoi(NamedEntryWidgetText("row_num_align"));
667    alignCol.maxSlice = NamedToggleWidgetActive("col_max_align");
668    alignCol.index = atoi(NamedEntryWidgetText("col_num_align"));
669    MeshEntity::RefSliceDescriptor row, col;
670    MeshEntity::RefSliceDescriptor *refRow = NULL;
671    MeshEntity::RefSliceDescriptor *refCol = NULL;
672    if (NamedToggleWidgetActive("row_ref"))
673    {
674       // Reference row is specified, so get that info.
675       row.designation.maxSlice = NamedToggleWidgetActive("row_max_ref");
676       row.designation.index = atoi(NamedEntryWidgetText("row_num_ref"));
677       row.totalLengthOnly = NamedToggleWidgetActive("row_ref_total");
678       refRow = &row;
679    }
680    if (NamedToggleWidgetActive("col_ref"))
681    {
682       // Reference column is specified, so get that info.
683       col.designation.maxSlice = NamedToggleWidgetActive("col_max_ref");
684       col.designation.index = atoi(NamedEntryWidgetText("col_num_ref"));
685       col.totalLengthOnly = NamedToggleWidgetActive("col_ref_total");
686       refCol = &col;
687    }
688    bool surfaceValues = NamedToggleWidgetActive("surface");
689
690    // Let Radiant know the name of the operation responsible for the changes
691    // that are about to happen.
692    UndoableCommand undo(_triggerCommand.c_str());
693
694    // Apply the specified equation to every selected mesh.
695    SmartPointer<GeneralFunctionVisitor> funcVisitor(
696       new GeneralFunctionVisitor(sFactors, tFactors,
697                                  &alignRow, &alignCol, refRow, refCol,
698                                  surfaceValues));
699    GlobalSelectionSystem().foreachSelected(*funcVisitor);
700
701    // Done!
702    return true;
703 }