]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/patchdialog.cpp
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / radiant / patchdialog.cpp
1 /*\r
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 */\r
21 \r
22 //\r
23 // Patch Dialog\r
24 //\r
25 // Leonardo Zide (leo@lokigames.com)\r
26 //\r
27 \r
28 #include <gdk/gdkkeysyms.h>\r
29 #include "stdafx.h"\r
30 #include "patchdialog.h"\r
31 \r
32 PatchDialog g_PatchDialog;\r
33 // is the patch inspector currently displayed/active?\r
34 bool l_bIsActive = false;\r
35 // the increment we are using for the patch inspector (this is saved in the prefs)\r
36 texdef_t *l_pPIIncrement = &g_qeglobals.d_savedinfo.m_PIIncrement;\r
37 \r
38 // =============================================================================\r
39 // static functions\r
40 \r
41 static void OnDone (GtkWidget *widget, gpointer data)\r
42 {\r
43   g_PatchDialog.m_Patch = NULL;\r
44   g_PatchDialog.HideDlg ();\r
45 }\r
46 \r
47 // memorize the current state (that is don't try to undo our do before changing something else)\r
48 static void OnApply (GtkWidget *widget, gpointer data)\r
49 {\r
50   g_PatchDialog.UpdateData(TRUE);\r
51   if (g_PatchDialog.m_Patch != NULL)\r
52   {\r
53     int r = g_PatchDialog.m_nRow;\r
54     int c = g_PatchDialog.m_nCol;\r
55     if (r >= 0 && r < g_PatchDialog.m_Patch->height && c >= 0 && c < g_PatchDialog.m_Patch->width)\r
56     {            \r
57       if (g_PatchDialog.m_Patch->pShader)\r
58         g_PatchDialog.m_Patch->pShader->DecRef();\r
59         // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=467\r
60         if (g_PatchDialog.m_strName.Find(' ') >= 0)\r
61         {\r
62           Sys_FPrintf(SYS_WRN, "WARNING: spaces in shader names are not allowed, dropping '%s'\n", g_PatchDialog.m_strName.GetBuffer());\r
63           g_PatchDialog.m_strName = SHADER_NOT_FOUND;\r
64         }\r
65         g_PatchDialog.m_Patch->pShader = QERApp_Shader_ForName(g_PatchDialog.m_strName);\r
66         g_PatchDialog.m_Patch->d_texture = g_PatchDialog.m_Patch->pShader->getTexture();\r
67         g_PatchDialog.m_Patch->ctrl[c][r].xyz[0] = g_PatchDialog.m_fX;\r
68         g_PatchDialog.m_Patch->ctrl[c][r].xyz[1] = g_PatchDialog.m_fY;\r
69         g_PatchDialog.m_Patch->ctrl[c][r].xyz[2] = g_PatchDialog.m_fZ;\r
70         g_PatchDialog.m_Patch->ctrl[c][r].st[0] = g_PatchDialog.m_fS;\r
71         g_PatchDialog.m_Patch->ctrl[c][r].st[1] = g_PatchDialog.m_fT;\r
72         g_PatchDialog.m_Patch->bDirty = true;\r
73         Sys_UpdateWindows(W_ALL);\r
74     }\r
75   }\r
76 }\r
77 \r
78 static void OnSelchangeComboColRow (GtkWidget *widget, gpointer data)\r
79 {\r
80   if (!g_PatchDialog.m_bListenChanged)\r
81     return;\r
82 #ifdef DBG_PI\r
83   Sys_Printf("OnSelchangeComboColRow\n");\r
84 #endif\r
85   // retrieve the current m_nRow and m_nCol, other params are not relevant\r
86   // (NOTE: UpdateData has a mechanism to avoid inifinite looping)\r
87   g_PatchDialog.UpdateData(TRUE);\r
88   // read the changed values ourselves\r
89   g_PatchDialog.UpdateRowColInfo();\r
90   // now reflect our changes\r
91   g_PatchDialog.UpdateData(FALSE);\r
92 }\r
93 \r
94 static void OnBtnPatchdetails (GtkWidget *widget, gpointer data)\r
95 {\r
96   Patch_NaturalizeSelected(true);\r
97   Sys_UpdateWindows(W_ALL);\r
98 }\r
99 \r
100 static void OnBtnPatchfit (GtkWidget *widget, gpointer data)\r
101 {\r
102   Patch_ResetTexturing(1.0, 1.0);\r
103   Sys_UpdateWindows(W_ALL);\r
104 }\r
105 \r
106 static void OnBtnPatchnatural (GtkWidget *widget, gpointer data)\r
107 {\r
108   Patch_NaturalizeSelected();\r
109   Sys_UpdateWindows(W_ALL);\r
110 }\r
111 \r
112 static void OnBtnPatchreset (GtkWidget *widget, gpointer data)\r
113 {\r
114   float fx, fy;\r
115   if (DoTextureLayout (&fx, &fy) == IDOK)\r
116   {\r
117     Patch_ResetTexturing(fx, fy);\r
118   }\r
119   Sys_UpdateWindows(W_ALL);\r
120 }\r
121 \r
122 static void OnSpinChanged (GtkAdjustment *adj, gpointer data)\r
123 {\r
124   texdef_t td;\r
125 \r
126   td.rotate = 0;\r
127   td.scale[0] = td.scale[1] = 0;\r
128   td.shift[0] = td.shift[1] = 0;\r
129   td.contents = 0;\r
130   td.flags = 0;\r
131   td.value = 0;\r
132 \r
133   if (adj->value == 0)\r
134     return;\r
135 \r
136   if (adj == g_object_get_data (G_OBJECT (g_PatchDialog.GetWidget ()), "hshift_adj"))\r
137   {\r
138     l_pPIIncrement->shift[0] = atof (gtk_entry_get_text (GTK_ENTRY (data)));\r
139 \r
140     if (adj->value > 0)\r
141       td.shift[0] = l_pPIIncrement->shift[0];\r
142     else\r
143       td.shift[0] = -l_pPIIncrement->shift[0];\r
144   }\r
145   else if (adj == g_object_get_data (G_OBJECT (g_PatchDialog.GetWidget ()), "vshift_adj"))\r
146   {\r
147     l_pPIIncrement->shift[1] = atof (gtk_entry_get_text (GTK_ENTRY (data)));\r
148 \r
149     if (adj->value > 0)\r
150       td.shift[1] = l_pPIIncrement->shift[1];\r
151     else\r
152       td.shift[1] = -l_pPIIncrement->shift[1];\r
153   }\r
154   else if (adj == g_object_get_data (G_OBJECT (g_PatchDialog.GetWidget ()), "hscale_adj"))\r
155   {\r
156     l_pPIIncrement->scale[0] = atof (gtk_entry_get_text (GTK_ENTRY (data)));\r
157         if (l_pPIIncrement->scale[0] == 0.0f)\r
158                 return;\r
159         // make sure scale factor is always >1 for increases and <1 for decreases\r
160     if (adj->value > 0)\r
161         {\r
162           if (l_pPIIncrement->scale[0] < 1)\r
163         td.scale[0] = l_pPIIncrement->scale[0];\r
164           else\r
165         td.scale[0] = 1.0f / l_pPIIncrement->scale[0];\r
166         }\r
167     else\r
168     {\r
169           if (l_pPIIncrement->scale[0] < 1)\r
170         td.scale[0] = 1.0f / l_pPIIncrement->scale[0];\r
171           else\r
172         td.scale[0] = l_pPIIncrement->scale[0];\r
173         }\r
174   }\r
175   else if (adj == g_object_get_data (G_OBJECT (g_PatchDialog.GetWidget ()), "vscale_adj"))\r
176   {\r
177     l_pPIIncrement->scale[1] = atof (gtk_entry_get_text (GTK_ENTRY (data)));\r
178         if (l_pPIIncrement->scale[1] == 0.0f)\r
179                 return;\r
180         // make sure scale factor is always >1 for increases and <1 for decreases\r
181     if (adj->value > 0)\r
182         {\r
183           if (l_pPIIncrement->scale[1] < 1)\r
184         td.scale[1] = l_pPIIncrement->scale[1];\r
185           else\r
186         td.scale[1] = 1.0f / l_pPIIncrement->scale[1];\r
187         }\r
188     else\r
189     {\r
190           if (l_pPIIncrement->scale[1] < 1)\r
191         td.scale[1] = 1.0f / l_pPIIncrement->scale[1];\r
192           else\r
193         td.scale[1] = l_pPIIncrement->scale[1];\r
194         }\r
195   }\r
196   else if (adj == g_object_get_data (G_OBJECT (g_PatchDialog.GetWidget ()), "rotate_adj"))\r
197   {\r
198     l_pPIIncrement->rotate = atof (gtk_entry_get_text (GTK_ENTRY (data)));\r
199 \r
200     if (adj->value > 0)\r
201       td.rotate = l_pPIIncrement->rotate;\r
202     else\r
203       td.rotate = -l_pPIIncrement->rotate;\r
204   }\r
205 \r
206   adj->value = 0;\r
207 \r
208 #ifdef DBG_PI\r
209         Sys_Printf("Patch_SetTextureInfo: %g %g %g %g %g\n", td.shift[0], td.shift[1],td.scale[0],td.scale[1],td.rotate );\r
210 #endif\r
211   // will scale shift rotate the patch accordingly\r
212   Patch_SetTextureInfo (&td);\r
213   // update the point-by-point view\r
214   OnSelchangeComboColRow(NULL,NULL);\r
215   Sys_UpdateWindows (W_CAMERA);\r
216 }\r
217 \r
218 static gint OnDialogKey (GtkWidget* widget, GdkEventKey* event, gpointer data)\r
219 {\r
220 #ifdef DBG_PI\r
221   Sys_Printf("OnDialogKey\n");\r
222 #endif\r
223   if (event->keyval == GDK_Return)\r
224   {\r
225     OnApply (NULL, NULL);\r
226     return TRUE;\r
227   }\r
228   else if (event->keyval == GDK_Escape)\r
229   {\r
230     OnDone (NULL, NULL);\r
231     return TRUE;\r
232   }\r
233   return FALSE;\r
234 }\r
235 \r
236 // =============================================================================\r
237 // Global Functions\r
238 \r
239 void DoPatchInspector()\r
240 {\r
241   // do we need to create the dialog?\r
242   if (g_PatchDialog.GetWidget() == NULL)\r
243   {\r
244     g_PatchDialog.Create();\r
245     g_PatchDialog.UpdateData (FALSE);\r
246   }\r
247   g_PatchDialog.GetPatchInfo();\r
248   if (!l_bIsActive)\r
249     g_PatchDialog.ShowDlg ();\r
250 }\r
251 \r
252 void UpdatePatchInspector()\r
253 {\r
254   if (l_bIsActive)\r
255     g_PatchDialog.GetPatchInfo();\r
256 }\r
257 \r
258 void TogglePatchInspector()\r
259 {\r
260   if (l_bIsActive)\r
261     OnDone(NULL,NULL);\r
262   else\r
263     DoPatchInspector();\r
264 }\r
265 \r
266 // =============================================================================\r
267 // PatchDialog class\r
268 \r
269 PatchDialog::PatchDialog ()\r
270 {\r
271   m_strName = "";\r
272   m_fS = 0.0f;\r
273   m_fT = 0.0f;\r
274   m_fX = 0.0f;\r
275   m_fY = 0.0f;\r
276   m_fZ = 0.0f;\r
277   m_nCol = 0;\r
278   m_nRow = 0;\r
279   m_Patch = NULL;\r
280   m_bListenChanged = true;\r
281 }\r
282 \r
283 void PatchDialog::InitDefaultIncrement(texdef_t *tex)\r
284 {\r
285   tex->SetName(SHADER_NOT_FOUND);\r
286   tex->scale[0] = 0.5f;\r
287   tex->scale[1] = 0.5f;\r
288   tex->rotate = 45;\r
289   tex->shift[0] = 8.0f;\r
290   tex->shift[1] = 8.0f;\r
291 }\r
292 \r
293 // we plug into HideDlg and ShowDlg to maintain the l_bIsActive flag\r
294 void PatchDialog::HideDlg()\r
295 {\r
296   l_bIsActive = false;\r
297   Dialog::HideDlg();\r
298 }\r
299 \r
300 void PatchDialog::ShowDlg()\r
301 {\r
302   l_bIsActive = true;\r
303   Dialog::ShowDlg();\r
304 }\r
305 \r
306 void PatchDialog::BuildDialog ()\r
307 {\r
308   GtkWidget *dlg, *vbox, *vbox2, *hbox, *hbox2, *frame, *table, *label;\r
309   GtkWidget *button, *entry, *spin, *combo;\r
310   GtkObject *adj;\r
311   char buf[32];\r
312  \r
313   dlg = m_pWidget;\r
314   \r
315   load_window_pos (dlg, g_PrefsDlg.mWindowInfo.posPatchWnd);\r
316 \r
317   gtk_window_set_title (GTK_WINDOW (dlg), "Patch Properties");\r
318   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event", GTK_SIGNAL_FUNC (OnDone), NULL);\r
319   // catch 'Esc' and 'Enter'\r
320   gtk_signal_connect (GTK_OBJECT (dlg), "key_press_event", GTK_SIGNAL_FUNC (OnDialogKey), NULL);\r
321   gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (g_pParentWnd->m_pWidget));\r
322 \r
323 \r
324   vbox = gtk_vbox_new (FALSE, 5);\r
325   gtk_widget_show (vbox);\r
326   gtk_container_add (GTK_CONTAINER (dlg), vbox);\r
327   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); \r
328 \r
329   hbox = gtk_hbox_new (FALSE, 5);\r
330   gtk_widget_show (hbox);\r
331   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);\r
332 \r
333   frame = gtk_frame_new ("Details");\r
334   gtk_widget_show (frame);\r
335   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);\r
336 \r
337   vbox2 = gtk_vbox_new (FALSE, 5);\r
338   gtk_widget_show (vbox2);\r
339   gtk_container_add (GTK_CONTAINER (frame), vbox2);\r
340   gtk_container_set_border_width (GTK_CONTAINER (vbox2), 5);\r
341 \r
342   table = gtk_table_new (2, 2, FALSE);\r
343   gtk_widget_show (table);\r
344   gtk_box_pack_start (GTK_BOX (vbox2), table, TRUE, TRUE, 0);\r
345   gtk_table_set_row_spacings (GTK_TABLE (table), 5);\r
346   gtk_table_set_col_spacings (GTK_TABLE (table), 5);\r
347 \r
348   label = gtk_label_new ("Row:");\r
349   gtk_widget_show (label);\r
350   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,\r
351                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
352                     (GtkAttachOptions) (0), 0, 0);\r
353 \r
354   label = gtk_label_new ("Column:");\r
355   gtk_widget_show (label);\r
356   gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,\r
357                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
358                     (GtkAttachOptions) (0), 0, 0);\r
359 \r
360   combo = gtk_combo_new ();\r
361   gtk_widget_show (combo);\r
362   gtk_table_attach (GTK_TABLE (table), combo, 0, 1, 1, 2,\r
363                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
364                     (GtkAttachOptions) (0), 0, 0);\r
365   gtk_widget_set_usize (combo, 60, -1);\r
366   gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE);\r
367   gtk_signal_connect (GTK_OBJECT (GTK_COMBO (combo)->entry), "changed",\r
368                       GTK_SIGNAL_FUNC (OnSelchangeComboColRow), this);\r
369   AddDialogData (combo, &m_nRow, DLG_COMBO_INT);\r
370   m_pRowCombo = combo;\r
371 \r
372   combo = gtk_combo_new ();\r
373   gtk_widget_show (combo);\r
374   gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 1, 2,\r
375                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
376                     (GtkAttachOptions) (0), 0, 0);\r
377   gtk_widget_set_usize (combo, 60, -1);\r
378   gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE);\r
379   gtk_signal_connect (GTK_OBJECT (GTK_COMBO (combo)->entry), "changed",\r
380                       GTK_SIGNAL_FUNC (OnSelchangeComboColRow), this);\r
381   AddDialogData (combo, &m_nCol, DLG_COMBO_INT);\r
382   m_pColCombo = combo;\r
383 \r
384   table = gtk_table_new (5, 2, FALSE);\r
385   gtk_widget_show (table);\r
386   gtk_box_pack_start (GTK_BOX (vbox2), table, TRUE, TRUE, 0);\r
387   gtk_table_set_row_spacings (GTK_TABLE (table), 5);\r
388   gtk_table_set_col_spacings (GTK_TABLE (table), 5);\r
389 \r
390   label = gtk_label_new ("X:");\r
391   gtk_widget_show (label);\r
392   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,\r
393                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
394                     (GtkAttachOptions) (0), 0, 0);\r
395 \r
396   label = gtk_label_new ("Y:");\r
397   gtk_widget_show (label);\r
398   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,\r
399                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
400                     (GtkAttachOptions) (0), 0, 0);\r
401 \r
402   label = gtk_label_new ("Z:");\r
403   gtk_widget_show (label);\r
404   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,\r
405                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
406                     (GtkAttachOptions) (0), 0, 0);\r
407 \r
408   label = gtk_label_new ("S:");\r
409   gtk_widget_show (label);\r
410   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4,\r
411                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
412                     (GtkAttachOptions) (0), 0, 0);\r
413 \r
414   label = gtk_label_new ("T:");\r
415   gtk_widget_show (label);\r
416   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 4, 5,\r
417                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
418                     (GtkAttachOptions) (0), 0, 0);\r
419 \r
420   entry = gtk_entry_new ();\r
421   gtk_widget_show (entry);\r
422   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,\r
423                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
424                     (GtkAttachOptions) (0), 0, 0);\r
425   AddDialogData (entry, &m_fX, DLG_ENTRY_FLOAT);\r
426 \r
427   entry = gtk_entry_new ();\r
428   gtk_widget_show (entry);\r
429   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2,\r
430                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
431                     (GtkAttachOptions) (0), 0, 0);\r
432   AddDialogData (entry, &m_fY, DLG_ENTRY_FLOAT);\r
433 \r
434   entry = gtk_entry_new ();\r
435   gtk_widget_show (entry);\r
436   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 2, 3,\r
437                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
438                     (GtkAttachOptions) (0), 0, 0);\r
439   AddDialogData (entry, &m_fZ, DLG_ENTRY_FLOAT);\r
440 \r
441   entry = gtk_entry_new ();\r
442   gtk_widget_show (entry);\r
443   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 3, 4,\r
444                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
445                     (GtkAttachOptions) (0), 0, 0);\r
446   AddDialogData (entry, &m_fS, DLG_ENTRY_FLOAT);\r
447 \r
448   entry = gtk_entry_new ();\r
449   gtk_widget_show (entry);\r
450   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 4, 5,\r
451                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
452                     (GtkAttachOptions) (0), 0, 0);\r
453   AddDialogData (entry, &m_fT, DLG_ENTRY_FLOAT);\r
454 \r
455   frame = gtk_frame_new ("Texturing");\r
456   gtk_widget_show (frame);\r
457   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);\r
458 \r
459   vbox2 = gtk_vbox_new (FALSE, 5);\r
460   gtk_widget_show (vbox2);\r
461   gtk_container_add (GTK_CONTAINER (frame), vbox2);\r
462   gtk_container_set_border_width (GTK_CONTAINER (vbox2), 5);\r
463 \r
464   label = gtk_label_new ("Name:");\r
465   gtk_widget_show (label);\r
466   gtk_box_pack_start (GTK_BOX (vbox2), label, TRUE, TRUE, 0);\r
467   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);\r
468   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);\r
469 \r
470   entry = gtk_entry_new ();\r
471 //  gtk_entry_set_editable (GTK_ENTRY (entry), false);\r
472   gtk_widget_show (entry);\r
473   gtk_box_pack_start (GTK_BOX (vbox2), entry, TRUE, TRUE, 0);\r
474   AddDialogData (entry, &m_strName, DLG_ENTRY_TEXT);\r
475 \r
476   table = gtk_table_new (5, 3, FALSE);\r
477   gtk_widget_show (table);\r
478   gtk_box_pack_start (GTK_BOX (vbox2), table, TRUE, TRUE, 0);\r
479   gtk_table_set_row_spacings (GTK_TABLE (table), 5);\r
480   gtk_table_set_col_spacings (GTK_TABLE (table), 5);\r
481 \r
482   label = gtk_label_new ("Horizontal Shift Step");\r
483   gtk_widget_show (label);\r
484   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1,\r
485                     (GtkAttachOptions) (GTK_FILL),\r
486                     (GtkAttachOptions) (0), 0, 0);\r
487   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);\r
488 \r
489   label = gtk_label_new ("Vertical Shift Step");\r
490   gtk_widget_show (label);\r
491   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 1, 2,\r
492                     (GtkAttachOptions) (GTK_FILL),\r
493                     (GtkAttachOptions) (0), 0, 0);\r
494   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);\r
495 \r
496   label = gtk_label_new ("Horizontal Stretch Step");\r
497   gtk_widget_show (label);\r
498   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 2, 3,\r
499                     (GtkAttachOptions) (GTK_FILL),\r
500                     (GtkAttachOptions) (0), 0, 0);\r
501   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);\r
502 \r
503   label = gtk_label_new ("Vertical Stretch Step");\r
504   gtk_widget_show (label);\r
505   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 3, 4,\r
506                     (GtkAttachOptions) (GTK_FILL),\r
507                     (GtkAttachOptions) (0), 0, 0);\r
508   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);\r
509 \r
510   label = gtk_label_new ("Rotate Step");\r
511   gtk_widget_show (label);\r
512   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 4, 5,\r
513                     (GtkAttachOptions) (GTK_FILL),\r
514                     (GtkAttachOptions) (0), 0, 0);\r
515   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);\r
516 \r
517   entry = gtk_entry_new ();\r
518   gtk_widget_show (entry);\r
519   gtk_table_attach (GTK_TABLE (table), entry, 0, 1, 0, 1,\r
520                     (GtkAttachOptions) (GTK_FILL),\r
521                     (GtkAttachOptions) (0), 0, 0);\r
522   gtk_widget_set_usize (entry, 50, -2);\r
523   g_object_set_data (G_OBJECT (m_pWidget), "hshift_entry", entry);\r
524   // we fill in this data, if no patch is selected the widgets are unmodified when the inspector is raised\r
525   // so we need to have at least one initialisation somewhere\r
526   sprintf (buf, "%g", l_pPIIncrement->shift[0]);\r
527   gtk_entry_set_text (GTK_ENTRY (entry), buf);\r
528 \r
529   adj = gtk_adjustment_new (0, -8192, 8192, 1, 1, 1);\r
530   gtk_signal_connect (adj, "value_changed", GTK_SIGNAL_FUNC (OnSpinChanged), entry);\r
531   g_object_set_data (G_OBJECT (m_pWidget), "hshift_adj", adj);\r
532 \r
533   spin = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);\r
534   gtk_widget_show (spin);\r
535   gtk_table_attach (GTK_TABLE (table), spin, 1, 2, 0, 1,\r
536                     (GtkAttachOptions) (0),\r
537                     (GtkAttachOptions) (0), 0, 0);\r
538   gtk_widget_set_usize (spin, 10, -2);\r
539 \r
540   entry = gtk_entry_new ();\r
541   gtk_widget_show (entry);\r
542   gtk_table_attach (GTK_TABLE (table), entry, 0, 1, 1, 2,\r
543                     (GtkAttachOptions) (GTK_FILL),\r
544                     (GtkAttachOptions) (0), 0, 0);\r
545   gtk_widget_set_usize (entry, 50, -2);\r
546   sprintf (buf, "%g", l_pPIIncrement->shift[1]);\r
547   gtk_entry_set_text (GTK_ENTRY (entry), buf);\r
548 \r
549   adj = gtk_adjustment_new (0, -8192, 8192, 1, 1, 1);\r
550   gtk_signal_connect (adj, "value_changed", GTK_SIGNAL_FUNC (OnSpinChanged), entry);\r
551   g_object_set_data (G_OBJECT (m_pWidget), "vshift_adj", adj);\r
552 \r
553   spin = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);\r
554   gtk_widget_show (spin);\r
555   gtk_table_attach (GTK_TABLE (table), spin, 1, 2, 1, 2,\r
556                     (GtkAttachOptions) (0),\r
557                     (GtkAttachOptions) (0), 0, 0);\r
558   gtk_widget_set_usize (spin, 10, -2);\r
559 \r
560   entry = gtk_entry_new ();\r
561   gtk_widget_show (entry);\r
562   gtk_table_attach (GTK_TABLE (table), entry, 0, 1, 2, 3,\r
563                     (GtkAttachOptions) (GTK_FILL),\r
564                     (GtkAttachOptions) (0), 0, 0);\r
565   gtk_widget_set_usize (entry, 50, -2);\r
566   sprintf (buf, "%g", l_pPIIncrement->scale[0]);\r
567   gtk_entry_set_text (GTK_ENTRY (entry), buf);\r
568 \r
569   adj = gtk_adjustment_new (0, -1000, 1000, 1, 1, 1);\r
570   gtk_signal_connect (adj, "value_changed", GTK_SIGNAL_FUNC (OnSpinChanged), entry);\r
571   g_object_set_data (G_OBJECT (m_pWidget), "hscale_adj", adj);\r
572 \r
573   spin = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);\r
574   gtk_widget_show (spin);\r
575   gtk_table_attach (GTK_TABLE (table), spin, 1, 2, 2, 3,\r
576                     (GtkAttachOptions) (0),\r
577                     (GtkAttachOptions) (0), 0, 0);\r
578   gtk_widget_set_usize (spin, 10, -2);\r
579 \r
580   entry = gtk_entry_new ();\r
581   gtk_widget_show (entry);\r
582   gtk_table_attach (GTK_TABLE (table), entry, 0, 1, 3, 4,\r
583                     (GtkAttachOptions) (GTK_FILL),\r
584                     (GtkAttachOptions) (0), 0, 0);\r
585   gtk_widget_set_usize (entry, 50, -2);\r
586   sprintf (buf, "%g", l_pPIIncrement->scale[1]);\r
587   gtk_entry_set_text (GTK_ENTRY (entry), buf);\r
588 \r
589   adj = gtk_adjustment_new (0, -1000, 1000, 1, 1, 1);\r
590   gtk_signal_connect (adj, "value_changed", GTK_SIGNAL_FUNC (OnSpinChanged), entry);\r
591   g_object_set_data (G_OBJECT (m_pWidget), "vscale_adj", adj);\r
592 \r
593   spin = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);\r
594   gtk_widget_show (spin);\r
595   gtk_table_attach (GTK_TABLE (table), spin, 1, 2, 3, 4,\r
596                     (GtkAttachOptions) (0),\r
597                     (GtkAttachOptions) (0), 0, 0);\r
598   gtk_widget_set_usize (spin, 10, -2);\r
599 \r
600   entry = gtk_entry_new ();\r
601   gtk_widget_show (entry);\r
602   gtk_table_attach (GTK_TABLE (table), entry, 0, 1, 4, 5,\r
603                     (GtkAttachOptions) (GTK_FILL),\r
604                     (GtkAttachOptions) (0), 0, 0);\r
605   gtk_widget_set_usize (entry, 50, -2);\r
606   sprintf (buf, "%g", l_pPIIncrement->rotate);\r
607   gtk_entry_set_text (GTK_ENTRY (entry), buf);\r
608 \r
609   adj = gtk_adjustment_new (0, -1000, 1000, 1, 1, 1);   // NOTE: Arnout - this really should be 360 but can't change it anymore as it could break existing maps\r
610   gtk_signal_connect (adj, "value_changed", GTK_SIGNAL_FUNC (OnSpinChanged), entry);\r
611   g_object_set_data (G_OBJECT (m_pWidget), "rotate_adj", adj);\r
612 \r
613   spin = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);\r
614   gtk_widget_show (spin);\r
615   gtk_table_attach (GTK_TABLE (table), spin, 1, 2, 4, 5,\r
616                     (GtkAttachOptions) (0),\r
617                     (GtkAttachOptions) (0), 0, 0);\r
618   gtk_widget_set_usize (spin, 10, -2);\r
619 \r
620   hbox2 = gtk_hbox_new (TRUE, 5);\r
621   gtk_widget_show (hbox2);\r
622   gtk_box_pack_start (GTK_BOX (vbox2), hbox2, TRUE, FALSE, 0);\r
623 \r
624   button = gtk_button_new_with_label ("CAP");\r
625   gtk_widget_show (button);\r
626   gtk_box_pack_end (GTK_BOX (hbox2), button, TRUE, FALSE, 0);\r
627   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnPatchdetails), NULL);\r
628   gtk_widget_set_usize (button, 60, -1);\r
629 \r
630   button = gtk_button_new_with_label ("Set...");\r
631   gtk_widget_show (button);\r
632   gtk_box_pack_end (GTK_BOX (hbox2), button, TRUE, FALSE, 0);\r
633   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnPatchreset), NULL);\r
634   gtk_widget_set_usize (button, 60, -1);\r
635 \r
636   button = gtk_button_new_with_label ("Natural");\r
637   gtk_widget_show (button);\r
638   gtk_box_pack_end (GTK_BOX (hbox2), button, TRUE, FALSE, 0);\r
639   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnPatchnatural), NULL);\r
640   gtk_widget_set_usize (button, 60, -1);\r
641 \r
642   button = gtk_button_new_with_label ("Fit");\r
643   gtk_widget_show (button);\r
644   gtk_box_pack_end (GTK_BOX (hbox2), button, TRUE, FALSE, 0);\r
645   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnPatchfit), NULL);\r
646   gtk_widget_set_usize (button, 60, -1);\r
647 \r
648   hbox = gtk_hbox_new (FALSE, 5);\r
649   gtk_widget_show (hbox);\r
650   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);\r
651 \r
652   button = gtk_button_new_with_label ("Done");\r
653   gtk_widget_show (button);\r
654   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);\r
655   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnDone), NULL);\r
656   gtk_widget_set_usize (button, 60, -1);\r
657 \r
658   button = gtk_button_new_with_label ("Apply");\r
659   gtk_widget_show (button);\r
660   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);\r
661   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnApply), NULL);\r
662   gtk_widget_set_usize (button, 60, -1);\r
663 }\r
664 \r
665 // sync the dialog our internal data structures\r
666 void PatchDialog::UpdateData (bool retrieve)\r
667 {\r
668   if (m_pWidget == NULL)\r
669     return;\r
670 \r
671   m_bListenChanged = false;\r
672   Dialog::UpdateData (retrieve);\r
673   m_bListenChanged = true;\r
674 }\r
675 \r
676 // read the map and feed in the stuff to the dialog box\r
677 void PatchDialog::GetPatchInfo()\r
678 {\r
679   m_Patch = SinglePatchSelected();\r
680   if (m_Patch != NULL)\r
681   {\r
682     m_strName = m_Patch->pShader->getName();\r
683   \r
684     GList *combo_list = NULL;\r
685     int i;\r
686 \r
687     // fill in the numbers for Row / Col selection\r
688     m_bListenChanged = false;\r
689 \r
690     for (i = 0; i < m_Patch->height; i++)\r
691       combo_list = g_list_append (combo_list, g_strdup_printf ("%i", i)); // NOTE: leaving the g_strdup cause we free with g_free later on\r
692     gtk_combo_set_popdown_strings (GTK_COMBO (m_pRowCombo), combo_list);\r
693     gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (m_pRowCombo)->entry), "0");\r
694 \r
695     while (combo_list)\r
696     {\r
697       g_free (combo_list->data);\r
698       combo_list = g_list_remove (combo_list, combo_list->data);\r
699     }\r
700 \r
701     for (i = 0; i < m_Patch->width; i++)\r
702       combo_list = g_list_append (combo_list, g_strdup_printf ("%i", i));\r
703     gtk_combo_set_popdown_strings (GTK_COMBO (m_pColCombo), combo_list);\r
704     gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (m_pColCombo)->entry), "0");\r
705 \r
706     while (combo_list)\r
707     {\r
708       g_free (combo_list->data);\r
709       combo_list = g_list_remove (combo_list, combo_list->data);\r
710     }\r
711     \r
712     m_bListenChanged = true;\r
713     \r
714   }\r
715   else\r
716     Sys_Printf("WARNING: no patch\n");\r
717   // fill in our internal structs\r
718   m_nRow = 0; m_nCol = 0;\r
719   UpdateRowColInfo();\r
720   // now update the dialog box\r
721   UpdateData(false);\r
722 }\r
723 \r
724 // read the current patch on map and initialize m_fX m_fY accordingly\r
725 // NOTE: don't call UpdateData in there, it's not meant for\r
726 void PatchDialog::UpdateRowColInfo()\r
727 {\r
728   m_fX = m_fY = m_fZ = m_fS = m_fT = 0.0;\r
729 \r
730   if (m_Patch != NULL)\r
731   {\r
732     // we rely on whatever active row/column has been set before we get called\r
733     int r = m_nRow;\r
734     int c = m_nCol;\r
735     if (r >= 0 && r < m_Patch->height && c >= 0 && c < m_Patch->width)\r
736     {\r
737       m_fX = m_Patch->ctrl[c][r].xyz[0];\r
738       m_fY = m_Patch->ctrl[c][r].xyz[1];\r
739       m_fZ = m_Patch->ctrl[c][r].xyz[2];\r
740       m_fS = m_Patch->ctrl[c][r].st[0];\r
741       m_fT = m_Patch->ctrl[c][r].st[1];\r
742     }\r
743   }\r
744 }\r
745 \r