]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/surfacedialog.cpp
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / radiant / surfacedialog.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 // Surface 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 "surfacedialog.h"\r
31 \r
32 SurfaceDlg g_dlgSurface;\r
33 \r
34 /////////////////////////////////////////////////////////////////////////////\r
35 // surface properties plugin\r
36 \r
37 /*\r
38 ===================================================\r
39 \r
40   SURFACE INSPECTOR\r
41 \r
42 ===================================================\r
43 */\r
44 \r
45 // the texdef to switch back to when the OnCancel is called\r
46 texdef_t        g_old_texdef;\r
47 // when != NULL, this thing means the surface inspector is currently being displayed\r
48 // NOTE a boolean flag would have been more explicit, this is totally so ugly\r
49 GtkWidget*  g_surfwin = NULL;\r
50 // turn on/off processing of the "changed" "value_changed" messages\r
51 // (need to turn off when we are feeding data in)\r
52 bool g_bListenChanged = true;\r
53 // the struct used to store the increments (saved in registry)\r
54 texdef_t *l_pIncrement = &g_qeglobals.d_savedinfo.m_SIIncrement;\r
55 // turn on/off listening of the update messages\r
56 bool g_bListenUpdate = true;\r
57 \r
58 #ifdef _DEBUG\r
59 // experimental stuff, work directly on BP\r
60 static void OnTest(GtkWidget *widget, gpointer data) \r
61 {\r
62   if (!g_qeglobals.m_bBrushPrimitMode)\r
63   {\r
64     Sys_FPrintf(SYS_WRN, "BP mode required\n");\r
65     return;\r
66   }\r
67   if (g_ptrSelectedFaces.GetSize() != 1)\r
68   {\r
69     Sys_FPrintf(SYS_WRN, "Expected single face selection\n");\r
70     return;\r
71   }\r
72   brush_t *b = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(0));\r
73   face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));\r
74   // get the ST axis base for the face\r
75   vec3_t texS,texT;\r
76   ComputeAxisBase(selFace->plane.normal, texS, texT);\r
77   // find ST coordinates for the center of the face\r
78   float Os=0,Ot=0;\r
79   int i;\r
80   for (i=0; i<selFace->face_winding->numpoints; i++)\r
81   {\r
82     Os += DotProduct(selFace->face_winding->points[i],texS);\r
83     Ot += DotProduct(selFace->face_winding->points[i],texT);\r
84   }\r
85   Os /= selFace->face_winding->numpoints;\r
86   Ot /= selFace->face_winding->numpoints;\r
87   brushprimit_texdef_t *pBP = &selFace->brushprimit_texdef;\r
88 \r
89   // (FIXME: initial version, before axis base change optimize)\r
90 \r
91   // we need to compute our BP matrix in this new axis base (O,texS,texT)\r
92   // the general case if BPO = M * BP * M^-1\r
93   //   where BPO is transformation expressed in (O,texS,texT)\r
94   //         M is the axis base change from (origin,texS,texT) to (O,texS,texT)\r
95   // here we have a special case, M is a translation and it's inverse is easy\r
96   vec_t BPO[2][3];\r
97   vec_t aux[2][3];\r
98   vec_t m[2][3];\r
99   memset(&m, 0, sizeof(vec_t)*6);\r
100   m[0][0] = 1; m[1][1] = 1; m[0][2] = -Os; m[1][2] = -Ot;\r
101   BPMatMul(m, pBP->coords, aux);\r
102   m[0][2] = Os; m[1][2] = Ot; // now M^-1\r
103   BPMatMul(aux, m, BPO); \r
104 \r
105 #if 0\r
106   // apply a scaling\r
107   // scale factors against S and T axis, we apply on top of the existing matrix\r
108   // <1 will decrease the texel/world resolution, >1 will increase\r
109   float sS = 1.025,sT = 1.025;\r
110   BPMatScale(BPO,sS,sT);\r
111 #endif\r
112 #if 0\r
113   // apply a rotation\r
114   float theta = 5;\r
115   BPMatRotate(BPO,theta);\r
116 #endif\r
117 #if 0\r
118   // read the scale\r
119   ConvertTexMatWithQTexture(BPO, selFace->d_texture, aux, NULL);\r
120   // reset the scale (normalize the matrix)\r
121   vec_t v1,v2;\r
122   v1 = sqrt(aux[0][0]*aux[0][0]+aux[1][0]*aux[1][0]);\r
123   v2 = sqrt(aux[0][1]*aux[0][1]+aux[1][1]*aux[1][1]);\r
124   // if reading the scale values, we have them here:\r
125   Sys_Printf("Current Scale: S: %g T: %g\n", v1, v2);\r
126   return;\r
127 #endif\r
128 #if 1\r
129   // apply a given scale (on S and T)\r
130   ConvertTexMatWithQTexture(BPO, selFace->d_texture, aux, NULL);\r
131   // reset the scale (normalize the matrix)\r
132   vec_t v1,v2;\r
133   v1 = sqrt(aux[0][0]*aux[0][0]+aux[1][0]*aux[1][0]);\r
134   v2 = sqrt(aux[0][1]*aux[0][1]+aux[1][1]*aux[1][1]);\r
135   vec_t sS,sT;\r
136   // put the values for scale on S and T here:\r
137   sS = 1.2 / v1;\r
138   sT = 0.8 / v2;\r
139   aux[0][0] *= sS; aux[1][0] *= sS;\r
140   aux[0][1] *= sT; aux[1][1] *= sT;\r
141   ConvertTexMatWithQTexture(aux, NULL, BPO, selFace->d_texture);\r
142 #endif\r
143 \r
144   // now BPO must be expressed back in (origin,texS,texT) axis base BP = M^-1 * BPO * M\r
145   BPMatMul(m, BPO, aux); // m is M^-1\r
146   m[0][2] = -Os; m[1][2] = -Ot;\r
147   BPMatMul(aux, m, pBP->coords);\r
148 \r
149   // now emit the coordinates on the winding\r
150   EmitBrushPrimitTextureCoordinates(selFace, selFace->face_winding);\r
151   Sys_UpdateWindows(W_CAMERA);\r
152 }\r
153 \r
154 /*\r
155   FIXME: try again, there must be a silly mistake in the formula expansion\r
156   // we need to compute our BP matrix in this new axis base (O,texS,texT)\r
157   // the general case is BPO = M * BP * M^-1\r
158   //   where BPO is transformation expressed in (O,texS,texT)\r
159   //         M is the axis base change from (origin,texS,texT) to (O,texS,texT)\r
160   // here we have a special case, M is a translation and it's inverse is easy\r
161   // the M * BP * M^-1 formula can be expanded and simplified\r
162   vec_t BPO[2][3];\r
163   memcpy(&BPO, &pBP->coords, sizeof(vec_t)*6);\r
164   BPO[0][2] = Os*(pBP->coords[0][0]-1.0) + Ot*pBP->coords[0][1] + pBP->coords[0][2];\r
165   BPO[1][2] = Os*pBP->coords[1][0] + Ot*(pBP->coords[1][1]-1.0) + Ot*pBP->coords[1][2]; \r
166 \r
167   // apply a scaling\r
168   // scale factors against S and T axis, we apply on top of the existing matrix\r
169   // <1 will decrease the texel/world resolution, >1 will increase\r
170   float sS = 1.025,sT = 1.025;\r
171   BPMatScale(BPO,sS,sT);\r
172 \r
173   // now BPO must be expressed back in (origin,texS,texT) axis base BP = M^-1 * BPO * M\r
174   // same expanded formula as above\r
175   memcpy(&pBP->coords, &BPO, sizeof(vec_t)*6);\r
176   pBP->coords[0][2] = Os*(1.0-BPO[0][0]) - Ot*BPO[0][1] + BPO[0][2];\r
177   pBP->coords[1][2] = -Os*BPO[1][0] + Ot*(1.0-BPO[1][1]) + BPO[1][2];\r
178 */\r
179 \r
180 /*\r
181   // initial version, before axis base change optimize\r
182 \r
183   // we need to compute our BP matrix in this new axis base (O,texS,texT)\r
184   // the general case if BPO = M * BP * M^-1\r
185   //   where BPO is transformation expressed in (O,texS,texT)\r
186   //         M is the axis base change from (origin,texS,texT) to (O,texS,texT)\r
187   // here we have a special case, M is a translation and it's inverse is easy\r
188   vec_t BPO[2][3];\r
189   vec_t aux[2][3];\r
190   vec_t m[2][3];\r
191   memset(&m, 0, sizeof(vec_t)*6);\r
192   m[0][0] = 1; m[1][1] = 1; m[0][2] = -Os; m[1][2] = -Ot;\r
193   BPMatMul(m, pBP->coords, aux);\r
194   m[0][2] = Os; m[1][2] = Ot; // now M^-1\r
195   BPMatMul(aux, m, BPO); \r
196 \r
197   // apply a scaling\r
198   // scale factors against S and T axis, we apply on top of the existing matrix\r
199   // <1 will decrease the texel/world resolution, >1 will increase\r
200   float sS = 1.025,sT = 1.025;\r
201   BPMatScale(BPO,sS,sT);\r
202 \r
203   // now BPO must be expressed back in (origin,texS,texT) axis base BP = M^-1 * BPO * M\r
204   BPMatMul(m, BPO, aux); // m is M^-1\r
205   m[0][2] = -Os; m[1][2] = -Ot;\r
206   BPMatMul(aux, m, pBP->coords);\r
207 */\r
208 #endif\r
209 \r
210 static void OnDone(GtkWidget *widget, gpointer data) \r
211 {\r
212   g_dlgSurface.GetTexMods();\r
213   g_dlgSurface.HideDlg ();\r
214   Sys_UpdateWindows(W_ALL);\r
215 }\r
216 \r
217 // OnUpdate is called when something is changed in the dialog\r
218 // and must be reflected in the views. But it's not a change\r
219 // so important, so the system will try to undo our last do before applying the new changes\r
220 static void OnUpdate (GtkWidget *widget, gpointer data)\r
221 {\r
222   if (!g_bListenChanged)\r
223     return;\r
224 \r
225   if (OnlyPatchesSelected())\r
226   {\r
227     //++timo possible bug or misfeature in our gtk_MessageBox here..\r
228 //    gtk_MessageBox("The surface inspector doesn't work for patches, use the patch inspector instead (Shift+S)", "Surface Inspector", MB_OK );\r
229     Sys_Printf("The surface inspector doesn't work for patches, use the patch inspector instead (Shift+S)\n");\r
230     return;\r
231   }\r
232 \r
233   // avoid long delays on slow computers\r
234   while (gtk_events_pending ())\r
235     gtk_main_iteration ();\r
236 \r
237   g_dlgSurface.GetTexMods ();\r
238   Sys_UpdateWindows(W_CAMERA);\r
239 }\r
240 \r
241 // reflect the current changes in the views, and make sure\r
242 // the changes are stored in the undo.\r
243 static void OnApply (GtkWidget *widget, gpointer data) \r
244 {\r
245   if (!g_bListenChanged)\r
246     return;\r
247 \r
248   g_dlgSurface.GetTexMods ();\r
249   g_dlgSurface.m_nUndoId = 0; // that way we are sure we won't call undo\r
250   Sys_UpdateWindows(W_CAMERA);\r
251 }\r
252 \r
253 // we use OnTextureKey to detect when the user edits something in the texture widget\r
254 // in which case next 'Enter' will be interpreted as a OnApply instead of a OnDone\r
255 static gint OnTextureKey (GtkWidget* widget, GdkEventKey* event, gpointer data)\r
256 {\r
257 #ifdef DBG_SI\r
258   Sys_Printf("OnTextureKey\n");\r
259 #endif\r
260   if (event->keyval != GDK_Return)\r
261     g_dlgSurface.m_bEditingTextureWidget = true;\r
262   return FALSE;\r
263 }\r
264 \r
265 static void OnCancel(GtkWidget *widget, gpointer data) \r
266 {\r
267   g_qeglobals.d_texturewin.texdef = g_old_texdef;\r
268   // cancel the last do if we own it\r
269   if (g_dlgSurface.m_nUndoId == Undo_GetUndoId())\r
270   {\r
271 #ifdef DBG_SI\r
272     Sys_Printf("OnCancel calling Undo_Undo\n");\r
273 #endif\r
274     g_bListenUpdate = false;\r
275     Undo_Undo();\r
276     g_bListenUpdate = true;\r
277     g_dlgSurface.m_nUndoId = 0;\r
278   }\r
279   g_dlgSurface.HideDlg ();\r
280 }\r
281 \r
282 static gint OnDialogKey (GtkWidget* widget, GdkEventKey* event, gpointer data)\r
283 {\r
284   if (g_surfwin)\r
285   {\r
286     if (event->keyval == GDK_Return)\r
287     {\r
288       if (g_dlgSurface.m_bEditingTextureWidget)\r
289       {\r
290         OnApply (NULL, NULL);\r
291         g_dlgSurface.m_bEditingTextureWidget = false;\r
292       }\r
293       else\r
294       {\r
295         OnDone (NULL, NULL);\r
296       }\r
297       return TRUE;\r
298     }\r
299     if (event->keyval == GDK_Escape)\r
300     {\r
301       OnCancel (NULL, NULL);\r
302       return TRUE;\r
303     }\r
304   }\r
305   return FALSE;\r
306 }\r
307 \r
308 // the widget can be one of hshift, vshift, hscale, vscale, rotate\r
309 // we use the g_bListenChanged flag to ignore when changing stuff ourselves\r
310 static void OnIncrementChanged(GtkWidget *widget, gpointer data)\r
311 {\r
312   if (!g_bListenChanged)\r
313     return;\r
314 \r
315 #ifdef DBG_SI\r
316   Sys_Printf("OnIncrementChanged\n");\r
317 #endif\r
318 \r
319   gfloat val = 0;\r
320   sscanf( gtk_entry_get_text (GTK_ENTRY (widget)), "%g", &val);\r
321   // now push it into the appropriate spin button\r
322   GtkAdjustment * adjust;\r
323   if (widget == g_dlgSurface.GetDlgWidget ("hshift_inc"))\r
324   {\r
325     l_pIncrement->shift[0] = val;\r
326     adjust = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (g_dlgSurface.GetDlgWidget ("hshift")));\r
327     adjust->step_increment = l_pIncrement->shift[0];\r
328   }\r
329   else if (widget == g_dlgSurface.GetDlgWidget ("vshift_inc"))\r
330   {\r
331     l_pIncrement->shift[1] = val;\r
332     adjust = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (g_dlgSurface.GetDlgWidget ("vshift")));\r
333     adjust->step_increment = l_pIncrement->shift[1];\r
334   }\r
335   else if (widget == g_dlgSurface.GetDlgWidget ("hscale_inc"))\r
336   {\r
337     l_pIncrement->scale[0] = val;\r
338     adjust = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (g_dlgSurface.GetDlgWidget ("hscale")));\r
339     adjust->step_increment = l_pIncrement->scale[0];\r
340   }\r
341   else if (widget == g_dlgSurface.GetDlgWidget ("vscale_inc"))\r
342   {\r
343     l_pIncrement->scale[1] = val;\r
344     adjust = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (g_dlgSurface.GetDlgWidget ("vscale")));\r
345     adjust->step_increment = l_pIncrement->scale[1];\r
346   }\r
347   else if (widget == g_dlgSurface.GetDlgWidget ("rotate_inc"))\r
348   {\r
349     l_pIncrement->rotate = val;\r
350     adjust = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (g_dlgSurface.GetDlgWidget ("rotate")));\r
351     adjust->step_increment = l_pIncrement->rotate;\r
352   }\r
353 }\r
354 \r
355 // make the shift increments match the grid settings\r
356 // the objective being that the shift+arrows shortcuts move the texture by the corresponding grid size\r
357 // this depends on a scale value if you have selected a particular texture on which you want it to work:\r
358 // we move the textures in pixels, not world units. (i.e. increment values are in pixel)\r
359 // depending on the texture scale it doesn't take the same amount of pixels to move of g_qeglobals.d_gridsize\r
360 // increment * scale = gridsize\r
361 // hscale and vscale are optional parameters, if they are zero they will be set to the default scale\r
362 // NOTE: the default scale depends if you are using BP mode or regular.\r
363 // For regular it's 0.5f (128 pixels cover 64 world units), for BP it's simply 1.0f\r
364 // see fenris #2810\r
365 void DoSnapTToGrid(float hscale, float vscale)\r
366 {\r
367   if (hscale == 0.0f) \r
368   {\r
369     (g_qeglobals.m_bBrushPrimitMode) ? hscale = 1.0f : hscale = 0.5f;\r
370   }\r
371   if (vscale == 0.0f)\r
372   {\r
373     (g_qeglobals.m_bBrushPrimitMode) ? vscale = 1.0f : vscale = 0.5f;\r
374   }\r
375 #ifdef _DEBUG\r
376   Sys_Printf ("DoSnapTToGrid: hscale %g vscale %g\n", hscale, vscale);\r
377 #endif\r
378   l_pIncrement->shift[0] = (int) ( (float)g_qeglobals.d_gridsize / hscale );\r
379   l_pIncrement->shift[1] = (int) ( (float)g_qeglobals.d_gridsize / vscale );\r
380   // now some update work\r
381   // FIXME: doesn't look good here, seems to be called several times\r
382   g_dlgSurface.SetTexMods();\r
383 }\r
384 \r
385 // make the shift increments match the grid settings\r
386 // the objective being that the shift+arrows shortcuts move the texture by the corresponding grid size\r
387 // this depends on the current texture scale used?\r
388 // we move the textures in pixels, not world units. (i.e. increment values are in pixel)\r
389 // depending on the texture scale it doesn't take the same amount of pixels to move of g_qeglobals.d_gridsize\r
390 // increment * scale = gridsize\r
391 static void OnBtnMatchGrid(GtkWidget *widget, gpointer data)\r
392 {\r
393   float hscale, vscale;\r
394   hscale = gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON (g_dlgSurface.GetDlgWidget ("hscale")));\r
395   vscale = gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON (g_dlgSurface.GetDlgWidget ("vscale")));\r
396   if (hscale == 0.0f || vscale == 0.0f)\r
397   {\r
398     Sys_Printf("ERROR: unexpected scale == 0.0f\n");\r
399     return;\r
400   }\r
401   DoSnapTToGrid (hscale, vscale);\r
402 }\r
403 \r
404 void UpdateSurfaceDialog()\r
405 {\r
406   if (!g_bListenUpdate)\r
407     return;\r
408 \r
409   g_SurfaceTable.m_pfnUpdateSurfaceDialog();\r
410 }\r
411 \r
412 // DoSurface will always try to show the surface inspector\r
413 // or update it because something new has been selected\r
414 void DoSurface (void)\r
415 {\r
416 #ifdef DBG_SI\r
417   Sys_Printf("DoSurface\n");\r
418 #endif\r
419   g_SurfaceTable.m_pfnDoSurface();\r
420   return;\r
421 }\r
422 \r
423 void ToggleSurface()\r
424 {\r
425   g_SurfaceTable.m_pfnToggleSurface();\r
426   return;\r
427 }\r
428 \r
429 // NOTE: will raise and show the Surface inspector and exec fit for patches and brushes\r
430 void SurfaceDlgFitAll()\r
431 {\r
432   g_SurfaceTable.m_pfnSurfaceDlgFitAll();\r
433   return;\r
434 }\r
435 \r
436 static void OnBtnPatchdetails(GtkWidget *widget, gpointer data) \r
437 {\r
438   Patch_NaturalizeSelected(true);\r
439   Sys_UpdateWindows(W_ALL);\r
440 }\r
441 \r
442 static void OnBtnPatchnatural(GtkWidget *widget, gpointer data) \r
443 {\r
444   Patch_NaturalizeSelected();\r
445   Sys_UpdateWindows(W_ALL);\r
446 }\r
447 \r
448 static void OnBtnPatchreset(GtkWidget *widget, gpointer data) \r
449 {\r
450   float fx, fy;\r
451 \r
452   if (DoTextureLayout (&fx, &fy) == IDOK)\r
453     Patch_ResetTexturing (fx, fy);\r
454   Sys_UpdateWindows(W_ALL);\r
455 }\r
456 \r
457 static void OnBtnPatchFit(GtkWidget *widget, gpointer data) \r
458 {\r
459   Patch_ResetTexturing(1.0, 1.0);\r
460   Sys_UpdateWindows(W_ALL);\r
461 }\r
462 \r
463 static void OnBtnAxial(GtkWidget *widget, gpointer data)\r
464 {\r
465   Select_SetTexture (&g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef, true);\r
466   g_dlgSurface.SetTexMods();\r
467   Sys_UpdateWindows(W_ALL);\r
468 }\r
469 \r
470 static void OnBtnFaceFit(GtkWidget *widget, gpointer data) \r
471 {\r
472   g_dlgSurface.UpdateData(TRUE);\r
473   if (g_ptrSelectedFaces.GetSize() == 0)\r
474   {\r
475     brush_t *b;\r
476     for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)\r
477     {\r
478       for (face_t* pFace = b->brush_faces; pFace; pFace = pFace->next)\r
479       {\r
480         g_ptrSelectedFaces.Add(pFace);\r
481         g_ptrSelectedFaceBrushes.Add(b);\r
482       }\r
483     }\r
484     Select_FitTexture(g_dlgSurface.m_nHeight, g_dlgSurface.m_nWidth);\r
485     g_dlgSurface.SetTexMods();\r
486     g_ptrSelectedFaces.RemoveAll();\r
487   }\r
488   else\r
489   {\r
490     Select_FitTexture(g_dlgSurface.m_nHeight, g_dlgSurface.m_nWidth);\r
491     g_dlgSurface.SetTexMods();\r
492   }\r
493   Sys_UpdateWindows(W_ALL);\r
494 }\r
495 \r
496 // =============================================================================\r
497 // SurfaceDialog class\r
498 \r
499 SurfaceDlg::SurfaceDlg ()\r
500 {\r
501   m_nHeight = 1;\r
502   m_nWidth = 1;\r
503   m_nUndoId = 0;\r
504 }\r
505 \r
506 void SurfaceDlg::ShowDlg()\r
507 {\r
508   Dialog::ShowDlg();\r
509   if(GetWidget() == NULL)\r
510     Create();\r
511   g_surfwin = GetWidget ();\r
512 }\r
513 void SurfaceDlg::HideDlg()\r
514 {\r
515   g_surfwin = NULL;\r
516   Dialog::HideDlg();\r
517 }\r
518 \r
519 GtkWidget* SurfaceDlg::GetWidget()\r
520 {\r
521   return g_SurfaceTable.m_pfnGet_SI_Module_Widget();\r
522 }\r
523 \r
524 // set default values for increments (shift scale and rot)\r
525 // this is called by the prefs code if can't find the values\r
526 void SurfaceDlg::InitDefaultIncrement(texdef_t *tex)\r
527 {\r
528   tex->SetName("foo");\r
529   tex->shift[0] = 8;\r
530   tex->shift[1] = 8;\r
531   tex->scale[0] = 0.25;\r
532   tex->scale[1] = 0.25;\r
533   tex->rotate = 10;      \r
534 }\r
535 \r
536 void SurfaceDlg::BuildDialog ()\r
537 {\r
538   GtkWidget *dlg, *vbox, *hbox2, *frame, *table, *label;\r
539   GtkWidget *button, *entry, *spin;\r
540 \r
541   dlg = m_pWidget;\r
542 \r
543   load_window_pos (dlg, g_PrefsDlg.mWindowInfo.posSurfaceWnd);\r
544 \r
545   gtk_window_set_title (GTK_WINDOW (dlg), "Surface inspector");\r
546   //g_signal_connect (G_OBJECT (dlg), "delete_event", G_CALLBACK (OnCancel), NULL);\r
547   // we catch 'Enter' and interpret is as OnDone\r
548   gtk_signal_connect (GTK_OBJECT (dlg), "key_press_event", GTK_SIGNAL_FUNC (OnDialogKey), NULL);\r
549   gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (g_pParentWnd->m_pWidget));\r
550 \r
551   // replaced by only the vbox:\r
552   vbox = gtk_vbox_new (FALSE, 5);\r
553   gtk_widget_show (vbox);\r
554   gtk_container_add (GTK_CONTAINER (dlg), vbox);\r
555   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);\r
556 \r
557   hbox2 = gtk_hbox_new (FALSE, 5);\r
558   gtk_widget_show (hbox2);\r
559   gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, TRUE, 0);\r
560 \r
561   label = gtk_label_new ("Texture");\r
562   gtk_widget_show (label);\r
563   gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);\r
564 \r
565   entry = gtk_entry_new ();\r
566   gtk_signal_connect (GTK_OBJECT (entry), "key_press_event", GTK_SIGNAL_FUNC (OnTextureKey), NULL);\r
567   gtk_widget_show (entry);\r
568   gtk_box_pack_start (GTK_BOX (hbox2), entry, TRUE, TRUE, 0);\r
569   g_object_set_data (G_OBJECT (m_pWidget), "texture", entry);\r
570 \r
571 //  table = gtk_table_new (5, 4, FALSE);\r
572   table = gtk_table_new (6, 4, FALSE);\r
573   gtk_widget_show (table);\r
574   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);\r
575   gtk_table_set_row_spacings (GTK_TABLE (table), 5);\r
576   gtk_table_set_col_spacings (GTK_TABLE (table), 5);\r
577 \r
578   label = gtk_label_new ("Horizontal shift");\r
579   gtk_widget_show (label);\r
580   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);\r
581   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,\r
582                     (GtkAttachOptions) (GTK_FILL),\r
583                     (GtkAttachOptions) (0), 0, 0);\r
584 \r
585   spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, -8192, 8192, 2, 8, 8)), 0, 0);\r
586   g_object_set_data (G_OBJECT (dlg), "hshift", spin);\r
587   gtk_signal_connect (GTK_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin))), "value_changed",\r
588                       GTK_SIGNAL_FUNC (OnUpdate), NULL);\r
589   gtk_widget_show (spin);\r
590   gtk_table_attach (GTK_TABLE (table), spin, 1, 2, 0, 1,\r
591                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
592                     (GtkAttachOptions) (0), 0, 0);\r
593   gtk_widget_set_usize (spin, 60, -2);\r
594 \r
595   label = gtk_label_new ("Step");\r
596   gtk_widget_show (label);\r
597   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);\r
598   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1,\r
599                     (GtkAttachOptions) (GTK_FILL),\r
600                     (GtkAttachOptions) (0), 0, 0);\r
601   \r
602   entry = gtk_entry_new ();\r
603   g_object_set_data (G_OBJECT (dlg), "hshift_inc", entry);\r
604   gtk_signal_connect (GTK_OBJECT (entry), "changed",\r
605                       GTK_SIGNAL_FUNC (OnIncrementChanged), NULL);\r
606   gtk_widget_show (entry);\r
607   gtk_table_attach (GTK_TABLE (table), entry, 3, 4, 0, 1,\r
608                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
609                     (GtkAttachOptions) (0), 0, 0);\r
610   gtk_widget_set_usize (entry, 50, -2);\r
611 \r
612   label = gtk_label_new ("Vertical shift");\r
613   gtk_widget_show (label);\r
614   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);\r
615   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,\r
616                     (GtkAttachOptions) (GTK_FILL),\r
617                     (GtkAttachOptions) (0), 0, 0);\r
618 \r
619   spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, -8192, 8192, 2, 8, 8)), 0, 0);\r
620   g_object_set_data (G_OBJECT (dlg), "vshift", spin);\r
621   gtk_signal_connect (GTK_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin))), "value_changed",\r
622                       GTK_SIGNAL_FUNC (OnUpdate), NULL);\r
623   gtk_widget_show (spin);\r
624   gtk_table_attach (GTK_TABLE (table), spin, 1, 2, 1, 2,\r
625                     (GtkAttachOptions) (GTK_FILL),\r
626                     (GtkAttachOptions) (0), 0, 0);\r
627   gtk_widget_set_usize (spin, 60, -2);\r
628   \r
629   label = gtk_label_new ("Step");\r
630   gtk_widget_show (label);\r
631   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);\r
632   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 1, 2,\r
633                     (GtkAttachOptions) (GTK_FILL),\r
634                     (GtkAttachOptions) (0), 0, 0);\r
635   \r
636   entry = gtk_entry_new ();\r
637   g_object_set_data (G_OBJECT (dlg), "vshift_inc", entry);\r
638   gtk_signal_connect (GTK_OBJECT (entry), "changed",\r
639                       GTK_SIGNAL_FUNC (OnIncrementChanged), NULL);\r
640   gtk_widget_show (entry);\r
641   gtk_table_attach (GTK_TABLE (table), entry, 3, 4, 1, 2,\r
642                     (GtkAttachOptions) (GTK_FILL),\r
643                     (GtkAttachOptions) (0), 0, 0);\r
644   gtk_widget_set_usize (entry, 50, -2);\r
645 \r
646   label = gtk_label_new ("Horizontal stretch");\r
647   gtk_widget_show (label);\r
648   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);\r
649   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,\r
650                     (GtkAttachOptions) (GTK_FILL),\r
651                     (GtkAttachOptions) (0), 0, 0);\r
652 \r
653   spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, -1000, 1000, 1, 10, 10)), 0, 0);\r
654   g_object_set_data (G_OBJECT (dlg), "hscale", spin);\r
655   gtk_signal_connect (GTK_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin))), "value_changed",\r
656                       GTK_SIGNAL_FUNC (OnUpdate), NULL);\r
657   gtk_widget_show (spin);\r
658   gtk_table_attach (GTK_TABLE (table), spin, 1, 2, 2, 3,\r
659                     (GtkAttachOptions) (GTK_FILL),\r
660                     (GtkAttachOptions) (0), 0, 0);\r
661   gtk_widget_set_usize (spin, 60, -2);\r
662 \r
663   label = gtk_label_new ("Step");\r
664   gtk_widget_show (label);\r
665   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);\r
666   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 2, 3,\r
667                     (GtkAttachOptions) (GTK_FILL),\r
668                     (GtkAttachOptions) (0), 2, 3);\r
669   \r
670   entry = gtk_entry_new ();\r
671   g_object_set_data (G_OBJECT (dlg), "hscale_inc", entry);\r
672   gtk_signal_connect (GTK_OBJECT (entry), "changed",\r
673                       GTK_SIGNAL_FUNC (OnIncrementChanged), NULL);\r
674   gtk_widget_show (entry);\r
675   gtk_table_attach (GTK_TABLE (table), entry, 3, 4, 2, 3,\r
676                     (GtkAttachOptions) (GTK_FILL),\r
677                     (GtkAttachOptions) (0), 2, 3);\r
678   gtk_widget_set_usize (entry, 50, -2);\r
679 \r
680   label = gtk_label_new ("Vertical stretch");\r
681   gtk_widget_show (label);\r
682   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);\r
683   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4,\r
684                     (GtkAttachOptions) (GTK_FILL),\r
685                     (GtkAttachOptions) (0), 0, 0);\r
686 \r
687   spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, -1000, 1000, 1, 10, 10)), 0, 0);\r
688   g_object_set_data (G_OBJECT (dlg), "vscale", spin);\r
689   gtk_signal_connect (GTK_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin))), "value_changed",\r
690                       GTK_SIGNAL_FUNC (OnUpdate), NULL);\r
691   gtk_widget_show (spin);\r
692   gtk_table_attach (GTK_TABLE (table), spin, 1, 2, 3, 4,\r
693                     (GtkAttachOptions) (GTK_FILL),\r
694                     (GtkAttachOptions) (0), 0, 0);\r
695   gtk_widget_set_usize (spin, 60, -2);\r
696   \r
697   label = gtk_label_new ("Step");\r
698   gtk_widget_show (label);\r
699   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);\r
700   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 3, 4,\r
701                     (GtkAttachOptions) (GTK_FILL),\r
702                     (GtkAttachOptions) (0), 0, 0);\r
703   \r
704   entry = gtk_entry_new ();\r
705   g_object_set_data (G_OBJECT (dlg), "vscale_inc", entry);\r
706   gtk_signal_connect (GTK_OBJECT (entry), "changed",\r
707                       GTK_SIGNAL_FUNC (OnIncrementChanged), NULL);\r
708   gtk_widget_show (entry);\r
709   gtk_table_attach (GTK_TABLE (table), entry, 3, 4, 3, 4,\r
710                     (GtkAttachOptions) (GTK_FILL),\r
711                     (GtkAttachOptions) (0), 0, 0);\r
712   gtk_widget_set_usize (entry, 50, -2);\r
713 \r
714   label = gtk_label_new ("Rotate");\r
715   gtk_widget_show (label);\r
716   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);\r
717   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 4, 5,\r
718                     (GtkAttachOptions) (GTK_FILL),\r
719                     (GtkAttachOptions) (0), 0, 0);\r
720 \r
721   spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, -360, 360, 1, 10, 10)), 1, 0);\r
722   g_object_set_data (G_OBJECT (dlg), "rotate", spin);\r
723   gtk_signal_connect (GTK_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin))), "value_changed",\r
724                       GTK_SIGNAL_FUNC (OnUpdate), NULL);\r
725   gtk_widget_show (spin);\r
726   gtk_table_attach (GTK_TABLE (table), spin, 1, 2, 4, 5,\r
727                     (GtkAttachOptions) (GTK_FILL),\r
728                     (GtkAttachOptions) (0), 0, 0);\r
729   gtk_widget_set_usize (spin, 60, -2);\r
730   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spin), TRUE);\r
731 \r
732   label = gtk_label_new ("Step");\r
733   gtk_widget_show (label);\r
734   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);\r
735   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 4, 5,\r
736                     (GtkAttachOptions) (GTK_FILL),\r
737                     (GtkAttachOptions) (0), 0, 0);\r
738   \r
739   entry = gtk_entry_new ();\r
740   g_object_set_data (G_OBJECT (dlg), "rotate_inc", entry);\r
741   gtk_signal_connect (GTK_OBJECT (entry), "changed",\r
742                       GTK_SIGNAL_FUNC (OnIncrementChanged), NULL);\r
743   gtk_widget_show (entry);\r
744   gtk_table_attach (GTK_TABLE (table), entry, 3, 4, 4, 5,\r
745                     (GtkAttachOptions) (GTK_FILL),\r
746                     (GtkAttachOptions) (0), 0, 0);\r
747   gtk_widget_set_usize (entry, 50, -2);\r
748 \r
749   // match grid button\r
750   button = gtk_button_new_with_label ("Match Grid");\r
751   gtk_widget_show (button);\r
752   gtk_table_attach (GTK_TABLE (table), button, 2, 4, 5, 6,\r
753                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
754                     (GtkAttachOptions) (0), 0, 0);\r
755   gtk_signal_connect (GTK_OBJECT (button), "clicked",\r
756                       GTK_SIGNAL_FUNC (OnBtnMatchGrid), NULL);\r
757 \r
758   frame = gtk_frame_new ("Texturing");\r
759   gtk_widget_show (frame);\r
760   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);\r
761 \r
762   table = gtk_table_new (4, 4, FALSE);\r
763   gtk_widget_show (table);\r
764   gtk_container_add (GTK_CONTAINER (frame), table);\r
765   gtk_table_set_row_spacings (GTK_TABLE (table), 5);\r
766   gtk_table_set_col_spacings (GTK_TABLE (table), 5);\r
767   gtk_container_set_border_width (GTK_CONTAINER (table), 5);\r
768 \r
769   label = gtk_label_new ("Brush");\r
770   gtk_widget_show (label);\r
771   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,\r
772                     (GtkAttachOptions) (GTK_FILL),\r
773                     (GtkAttachOptions) (0), 0, 0);\r
774 \r
775   label = gtk_label_new ("Patch");\r
776   gtk_widget_show (label);\r
777   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,\r
778                     (GtkAttachOptions) (GTK_FILL),\r
779                     (GtkAttachOptions) (0), 0, 0);\r
780 \r
781   label = gtk_label_new ("Width");\r
782   gtk_widget_show (label);\r
783   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1,\r
784                     (GtkAttachOptions) (GTK_FILL),\r
785                     (GtkAttachOptions) (0), 0, 0);\r
786 \r
787   label = gtk_label_new ("Height");\r
788   gtk_widget_show (label);\r
789   gtk_table_attach (GTK_TABLE (table), label, 3, 4, 0, 1,\r
790                     (GtkAttachOptions) (GTK_FILL),\r
791                     (GtkAttachOptions) (0), 0, 0);\r
792 \r
793   button = gtk_button_new_with_label ("Axial");\r
794   gtk_widget_show (button);\r
795   gtk_table_attach (GTK_TABLE (table), button, 0, 1, 1, 2,\r
796                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
797                     (GtkAttachOptions) (0), 0, 0);\r
798   gtk_signal_connect (GTK_OBJECT (button), "clicked",\r
799                       GTK_SIGNAL_FUNC (OnBtnAxial), NULL);\r
800   gtk_widget_set_usize (button, 60, -2);\r
801 \r
802   button = gtk_button_new_with_label ("Fit");\r
803   gtk_widget_show (button);\r
804   gtk_table_attach (GTK_TABLE (table), button, 1, 2, 1, 2,\r
805                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
806                     (GtkAttachOptions) (0), 0, 0);\r
807   gtk_signal_connect (GTK_OBJECT (button), "clicked",\r
808                       GTK_SIGNAL_FUNC (OnBtnFaceFit), NULL);\r
809   gtk_widget_set_usize (button, 60, -2);\r
810 \r
811   button = gtk_button_new_with_label ("CAP");\r
812   gtk_widget_show (button);\r
813   gtk_table_attach (GTK_TABLE (table), button, 0, 1, 3, 4,\r
814                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
815                     (GtkAttachOptions) (0), 0, 0);\r
816   gtk_signal_connect (GTK_OBJECT (button), "clicked",\r
817                       GTK_SIGNAL_FUNC (OnBtnPatchdetails), NULL);\r
818   gtk_widget_set_usize (button, 60, -2);\r
819 \r
820   button = gtk_button_new_with_label ("Set...");\r
821   gtk_widget_show (button);\r
822   gtk_table_attach (GTK_TABLE (table), button, 1, 2, 3, 4,\r
823                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
824                     (GtkAttachOptions) (0), 0, 0);\r
825   gtk_signal_connect (GTK_OBJECT (button), "clicked",\r
826                       GTK_SIGNAL_FUNC (OnBtnPatchreset), NULL);\r
827   gtk_widget_set_usize (button, 60, -2);\r
828 \r
829   button = gtk_button_new_with_label ("Natural");\r
830   gtk_widget_show (button);\r
831   gtk_table_attach (GTK_TABLE (table), button, 2, 3, 3, 4,\r
832                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
833                     (GtkAttachOptions) (0), 0, 0);\r
834   gtk_signal_connect (GTK_OBJECT (button), "clicked",\r
835                       GTK_SIGNAL_FUNC (OnBtnPatchnatural), NULL);\r
836   gtk_widget_set_usize (button, 60, -2);\r
837 \r
838   button = gtk_button_new_with_label ("Fit");\r
839   gtk_widget_show (button);\r
840   gtk_table_attach (GTK_TABLE (table), button, 3, 4, 3, 4,\r
841                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
842                     (GtkAttachOptions) (0), 0, 0);\r
843   gtk_signal_connect (GTK_OBJECT (button), "clicked",\r
844                       GTK_SIGNAL_FUNC (OnBtnPatchFit), NULL);\r
845   gtk_widget_set_usize (button, 60, -2);\r
846 \r
847   spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (1, 1, 32, 1, 10, 10)), 1, 0);\r
848   gtk_widget_show (spin);\r
849   gtk_table_attach (GTK_TABLE (table), spin, 2, 3, 1, 2,\r
850                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
851                     (GtkAttachOptions) (0), 0, 0);\r
852   gtk_widget_set_usize (spin, 60, -2);\r
853   AddDialogData (spin, &m_nWidth, DLG_SPIN_INT);\r
854 \r
855   spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (1, 1, 32, 1, 10, 10)), 1, 0);\r
856   gtk_widget_show (spin);\r
857   gtk_table_attach (GTK_TABLE (table), spin, 3, 4, 1, 2,\r
858                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
859                     (GtkAttachOptions) (0), 0, 0);\r
860   gtk_widget_set_usize (spin, 60, -2);\r
861   AddDialogData (spin, &m_nHeight, DLG_SPIN_INT);\r
862 \r
863   hbox2 = gtk_hbox_new (FALSE, 5);\r
864   gtk_widget_show (hbox2);\r
865   gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, TRUE, 0);\r
866 \r
867   button = gtk_button_new_with_label ("Done");\r
868   gtk_widget_show (button);\r
869   gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);\r
870   gtk_signal_connect (GTK_OBJECT (button), "clicked",\r
871                       GTK_SIGNAL_FUNC (OnDone), NULL);\r
872   gtk_widget_set_usize (button, 60, -2);\r
873 \r
874   button = gtk_button_new_with_label ("Apply");\r
875   gtk_widget_show (button);\r
876   gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);\r
877   gtk_signal_connect (GTK_OBJECT (button), "clicked",\r
878                       GTK_SIGNAL_FUNC (OnApply), NULL);\r
879   gtk_widget_set_usize (button, 60, -2);\r
880 \r
881   button = gtk_button_new_with_label ("Cancel");\r
882   gtk_widget_show (button);\r
883   gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);\r
884   gtk_signal_connect (GTK_OBJECT (button), "clicked",\r
885                       GTK_SIGNAL_FUNC (OnCancel), NULL);\r
886   gtk_widget_set_usize (button, 60, -2);\r
887 \r
888   // that's a bit of trashy stuff from Textool-v2 branch\r
889 #ifdef _DEBUG\r
890   // FIXME: testing only, scaling in BP mode\r
891   button = gtk_button_new_with_label ("Test");\r
892   gtk_widget_show (button);\r
893   gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);\r
894   gtk_signal_connect (GTK_OBJECT (button), "clicked",\r
895                       GTK_SIGNAL_FUNC (OnTest), NULL);\r
896   gtk_widget_set_usize (button, 60, -2);\r
897 #endif\r
898 \r
899   // Initialize\r
900   SetTexMods ();\r
901 }\r
902 \r
903 /*\r
904 ==============\r
905 SetTexMods\r
906 \r
907 Set the fields to the current texdef (i.e. map/texdef -> dialog widgets)\r
908 if faces selected (instead of brushes) -> will read this face texdef, else current texdef\r
909 if only patches selected, will read the patch texdef\r
910 ===============\r
911 */\r
912 \r
913 void SurfaceDlg::SetTexMods()\r
914 {\r
915   texdef_t *pt;\r
916   brushprimit_texdef_t  *bpt;\r
917   // local copy if a width=2 height=2 qtetxture_t is needed\r
918   brushprimit_texdef_t  local_bp;\r
919 \r
920 #ifdef DBG_SI\r
921   Sys_Printf("SurfaceDlg::SetTexMods\n");\r
922 #endif\r
923 \r
924   if (!g_surfwin)\r
925     return;\r
926   \r
927   if (g_ptrSelectedFaces.GetSize() > 0)\r
928   {\r
929     face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));\r
930     pt = &selFace->texdef;\r
931     if (g_qeglobals.m_bBrushPrimitMode)\r
932     {\r
933       // compute a texture matrix related to the default matrix width=2 height=2\r
934       ConvertTexMatWithQTexture( &selFace->brushprimit_texdef, selFace->d_texture, &local_bp, NULL );\r
935       bpt = &local_bp;\r
936     }\r
937   }\r
938   else\r
939   {\r
940     pt = &g_qeglobals.d_texturewin.texdef;\r
941     if (g_qeglobals.m_bBrushPrimitMode)\r
942     {\r
943       bpt = &g_qeglobals.d_texturewin.brushprimit_texdef;\r
944     }\r
945   }\r
946   // brush primitive mode : compute fake shift scale rot representation\r
947   if (g_qeglobals.m_bBrushPrimitMode)\r
948     TexMatToFakeTexCoords( bpt->coords, m_shift, &m_rotate, m_scale );\r
949   \r
950   g_bListenChanged = false;\r
951   \r
952   if(strncmp(pt->GetName(), "textures/", 9) != 0)\r
953     pt->SetName(SHADER_NOT_FOUND);\r
954   gtk_entry_set_text (GTK_ENTRY (GetDlgWidget ("texture")), pt->GetName()+9);\r
955 \r
956   GtkSpinButton *spin;\r
957   spin = GTK_SPIN_BUTTON (GetDlgWidget ("hshift"));\r
958     gtk_spin_button_set_digits (spin, 2);\r
959     if (g_qeglobals.m_bBrushPrimitMode)\r
960       gtk_spin_button_set_value (spin, m_shift[0]);\r
961     else\r
962       gtk_spin_button_set_value (spin, pt->shift[0]);\r
963   GtkAdjustment *adjust = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin));\r
964   adjust->step_increment = l_pIncrement->shift[0];\r
965   char buf[10]; // got into snprintf paranoia after BoundChecker detected a stack overrun\r
966 #ifdef _WIN32\r
967   // TTimo: THIS IS UGLY\r
968 #define snprintf _snprintf\r
969 #endif\r
970   snprintf (buf, 10, "%g", l_pIncrement->shift[0]);\r
971   gtk_entry_set_text (GTK_ENTRY (GetDlgWidget ("hshift_inc")), buf);\r
972 \r
973   spin = GTK_SPIN_BUTTON (GetDlgWidget ("vshift"));\r
974     gtk_spin_button_set_digits (spin, 2);\r
975     if (g_qeglobals.m_bBrushPrimitMode)\r
976       gtk_spin_button_set_value (spin, m_shift[1]);\r
977     else\r
978       gtk_spin_button_set_value (spin, pt->shift[1]);\r
979   adjust = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin));\r
980   adjust->step_increment = l_pIncrement->shift[1];\r
981   snprintf (buf, 10, "%g", l_pIncrement->shift[1]);\r
982   gtk_entry_set_text (GTK_ENTRY (GetDlgWidget ("vshift_inc")), buf);\r
983 \r
984   spin = GTK_SPIN_BUTTON (GetDlgWidget ("hscale"));\r
985   gtk_spin_button_set_digits (spin, 5);\r
986   gtk_spin_button_set_value (spin, g_qeglobals.m_bBrushPrimitMode ? m_scale[0] : pt->scale[0]);\r
987 \r
988   adjust = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin));\r
989   adjust->step_increment = l_pIncrement->scale[0];\r
990   snprintf (buf, 10, "%g", l_pIncrement->scale[0]);\r
991   gtk_entry_set_text (GTK_ENTRY (GetDlgWidget ("hscale_inc")), buf);\r
992 \r
993   spin = GTK_SPIN_BUTTON (GetDlgWidget ("vscale"));\r
994   gtk_spin_button_set_digits (spin, 5);\r
995   gtk_spin_button_set_value (spin, g_qeglobals.m_bBrushPrimitMode ? m_scale[1] : pt->scale[1]);\r
996 \r
997   adjust = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin));\r
998   adjust->step_increment = l_pIncrement->scale[1];\r
999   snprintf (buf, 10, "%g", l_pIncrement->scale[1]);\r
1000   gtk_entry_set_text (GTK_ENTRY (GetDlgWidget ("vscale_inc")), buf);\r
1001 \r
1002   //++timo compute BProtate as int ..\r
1003   spin = GTK_SPIN_BUTTON (GetDlgWidget ("rotate"));\r
1004   gtk_spin_button_set_digits (spin, 2);\r
1005   gtk_spin_button_set_value (spin, g_qeglobals.m_bBrushPrimitMode ? m_rotate : pt->rotate);\r
1006 \r
1007   adjust = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin));\r
1008   adjust->step_increment = l_pIncrement->rotate;\r
1009   snprintf (buf, 10, "%g", l_pIncrement->rotate);\r
1010   gtk_entry_set_text (GTK_ENTRY (GetDlgWidget ("rotate_inc")), buf);\r
1011 \r
1012   g_bListenChanged = true;\r
1013   \r
1014   // undo tricks: set the undo id to zero so we don't attempt to undo something that does not belong to us\r
1015   m_nUndoId = 0;\r
1016   // store the current texdef as our escape route if user hits OnCancel\r
1017   g_old_texdef = g_qeglobals.d_texturewin.texdef;\r
1018   // reset the Enter key behaviour flag\r
1019   m_bEditingTextureWidget = false;\r
1020 }\r
1021 \r
1022 /*\r
1023 ==============\r
1024 GetTexMods\r
1025 \r
1026 Reads the fields to get the current texdef (i.e. widgets -> MAP)\r
1027 in brush primitive mode, grab the fake shift scale rot and compute a new texture matrix\r
1028 ===============\r
1029 */\r
1030 void SurfaceDlg::GetTexMods()\r
1031 {\r
1032   char buffer[1024];\r
1033   texdef_t *pt;\r
1034 \r
1035 #ifdef DBG_SI\r
1036   Sys_Printf("SurfaceDlg::GetTexMods\n");\r
1037 #endif\r
1038   \r
1039   if (g_ptrSelectedFaces.GetSize() > 0)\r
1040   {\r
1041     //++timo just a test, we disable the undo when working on selected faces\r
1042     m_nUndoId=0;\r
1043     face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));\r
1044     g_qeglobals.d_texturewin.texdef = selFace->texdef;\r
1045 #ifdef DBG_SI\r
1046     Sys_Printf("g_qeglobals.d_texturewin.texdef = selFace->texdef\n");\r
1047 #endif\r
1048   }\r
1049 //  else\r
1050 //  {\r
1051     pt = &g_qeglobals.d_texturewin.texdef;\r
1052 #ifdef DBG_SI\r
1053     Sys_Printf("pt = &g_qeglobals.d_texturewin.texdef\n");\r
1054 #endif\r
1055 //  }\r
1056   \r
1057   const char* text = gtk_entry_get_text (GTK_ENTRY (GetDlgWidget ("texture")));\r
1058 \r
1059 #ifdef DBG_SI\r
1060   Sys_Printf("pt->SetName(%s)\n", text );\r
1061 #endif\r
1062   \r
1063   // TTimo: detect and refuse invalid texture names (at least the ones with spaces)\r
1064   if (text[0] <= ' ' || strchr(text, ' '))\r
1065   {\r
1066     Sys_FPrintf(SYS_WRN, "WARNING: spaces in shader names are not allowed, ignoring '%s'\n", text);\r
1067     pt->SetName(SHADER_NOT_FOUND);\r
1068     gtk_entry_set_text (GTK_ENTRY (GetDlgWidget ("texture")), pt->GetName());\r
1069   }\r
1070   else\r
1071   {\r
1072     strcpy(buffer, "textures/");\r
1073     strcpy(buffer+9, text);\r
1074     pt->SetName(buffer);\r
1075   }\r
1076 \r
1077 \r
1078   (g_qeglobals.m_bBrushPrimitMode ? m_shift[0] : pt->shift[0]) = \r
1079     gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON (GetDlgWidget ("hshift")));\r
1080   (g_qeglobals.m_bBrushPrimitMode ? m_shift[1] : pt->shift[1]) =\r
1081     gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON (GetDlgWidget ("vshift")));\r
1082   (g_qeglobals.m_bBrushPrimitMode ? m_scale[0] : pt->scale[0]) =\r
1083     gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON (GetDlgWidget ("hscale")));\r
1084   (g_qeglobals.m_bBrushPrimitMode ? m_scale[1] : pt->scale[1]) =\r
1085     gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON (GetDlgWidget ("vscale")));\r
1086   (g_qeglobals.m_bBrushPrimitMode ? m_rotate : pt->rotate) =\r
1087     gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON (GetDlgWidget ("rotate")));\r
1088 \r
1089   // a local copy of the texture matrix, given for a qtexture_t with width=2 height=2\r
1090   brushprimit_texdef_t  local_bp;\r
1091   brushprimit_texdef_t  *bpt;\r
1092   if (g_qeglobals.m_bBrushPrimitMode)\r
1093   {\r
1094     face_t *selFace = NULL;\r
1095     if (g_ptrSelectedFaces.GetSize() > 0)\r
1096     {\r
1097       selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));\r
1098       bpt = &selFace->brushprimit_texdef;\r
1099     }\r
1100     else\r
1101     {\r
1102       bpt = &g_qeglobals.d_texturewin.brushprimit_texdef;\r
1103     }\r
1104     // compute texture matrix\r
1105     // the matrix returned must be understood as a qtexture_t with width=2 height=2\r
1106     FakeTexCoordsToTexMat( m_shift, m_rotate, m_scale, local_bp.coords );\r
1107     // copy the texture matrix in the global struct\r
1108     // fit the qtexture if we have a face selected, otherwise g_qeglobals.d_texturewin.brushprimit_texdef uses the basic qtexture_t with width=2 height=2\r
1109 \r
1110     ConvertTexMatWithQTexture( &local_bp, NULL, bpt, ( (selFace) ? selFace->d_texture : NULL ) );\r
1111   }\r
1112   // we are gonna do stuff, if we own the last do we undo it first\r
1113   if (m_nUndoId != 0)\r
1114   {\r
1115     // check the do we're about to undo is the one we pushed earlier\r
1116                 if (m_nUndoId == Undo_GetUndoId())\r
1117     {\r
1118 #ifdef DBG_SI\r
1119       Sys_Printf("GetTexMods calling Undo_Undo (silent)\n");\r
1120 #endif\r
1121       g_bListenUpdate=false;\r
1122                         Undo_Undo(true);\r
1123       g_bListenUpdate=true;\r
1124     }\r
1125         }\r
1126   Select_SetTexture(pt,&local_bp);\r
1127   m_nUndoId = Undo_GetUndoId();\r
1128 }\r
1129 \r
1130 void SurfaceDlg::FitAll()\r
1131 {\r
1132   OnBtnFaceFit(NULL, NULL);\r
1133   OnBtnPatchFit(NULL, NULL);\r
1134 }\r