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