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