apply misc fixes from Markus Fischer and Rambetter
[xonotic/netradiant.git] / radiant / surfaceplugin.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 //
24 // DESCRIPTION:
25 // implementation of isurfaceplugin-interface specifics
26
27 #include "stdafx.h"
28
29 void QERApp_GetTwoSelectedPatch( patchMesh_t **p1, patchMesh_t **p2 )
30 {
31   *p1 = NULL; *p2 = NULL;
32   for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
33   {
34     if (pb->patchBrush)
35     {
36       if (!(*p1))
37         *p1 = pb->pPatch;
38       else if (!(*p2))
39       {
40         *p2 = pb->pPatch;
41         return;
42       }
43     }
44   }
45 #ifdef _DEBUG
46   Sys_Printf("WARNING: QERApp_GetTwoSelectedPatch failed (did not find two patches)\n");
47 #endif
48   return;
49 }
50
51 // Nurail: The following functions are used by the Surface Inspector module
52
53 // Queries the number of faces from selected brushes
54 int SI_GetSelectedFaceCountfromBrushes(void)
55 {
56   face_t        *f;
57   brush_t       *b;
58   int           num_of_faces = 0;
59
60   if(selected_brushes.next == &selected_brushes)
61     return(0);
62
63   for(b=selected_brushes.next; b!=&selected_brushes; b=b->next)
64     if (!(b->patchBrush))
65       for(f=b->brush_faces; f ; f=f->next, num_of_faces++);
66
67   return num_of_faces;
68 }
69
70 void SI_GetSelFacesTexdef(texdef_to_face_t *allocd_block_texdef)
71 {
72   int           i;
73   face_t        *f;
74   brush_t       *b;
75   texdef_to_face_t *position, *prev_pos;
76   brushprimit_texdef_t bp;
77
78   if(selected_brushes.next != &selected_brushes)
79   {
80     prev_pos = position = allocd_block_texdef;
81     for(b=selected_brushes.next; b!=&selected_brushes; b=b->next)
82     {
83       if ( !(b->patchBrush) )
84       {
85         for(f=b->brush_faces; f ; f = f->next)
86         {
87             position->face = f;
88             position->brush = b;
89                         position->texdef = f->texdef;
90                         if(g_qeglobals.m_bBrushPrimitMode)
91                         {
92                                 ConvertTexMatWithQTexture(&f->brushprimit_texdef, QERApp_Shader_ForName( f->texdef.GetName() )->getTexture(), &bp, NULL);
93                                 TexMatToFakeTexCoords(bp.coords, position->texdef.shift, &position->texdef.rotate, position->texdef.scale);
94                                 position->orig_bp_texdef = bp;
95                         }
96                         position->orig_texdef = position->texdef;
97             prev_pos->next = position;
98             prev_pos = position;
99             position++;
100               }
101               prev_pos->next = NULL;
102       }
103     }
104   }
105   else if(g_ptrSelectedFaces.GetSize() != 0)
106   {
107     f = (face_t *) g_ptrSelectedFaces.GetAt(0);
108     b = (brush_t *) g_ptrSelectedFaceBrushes.GetAt(0);
109     position = (texdef_to_face_t*) allocd_block_texdef;
110     position->face = f;
111     position->brush = b;
112     position->texdef = f->texdef;
113         if(g_qeglobals.m_bBrushPrimitMode)
114         {
115                 ConvertTexMatWithQTexture(&f->brushprimit_texdef, QERApp_Shader_ForName( f->texdef.GetName() )->getTexture(), &bp, NULL);
116                 TexMatToFakeTexCoords(bp.coords, position->texdef.shift, &position->texdef.rotate, position->texdef.scale);
117                 position->orig_bp_texdef = bp;
118         }
119     position->orig_texdef = position->texdef;
120     prev_pos = position;
121     for(i=1; i<g_ptrSelectedFaces.GetSize(); i++)
122     {
123       f = (face_t *) g_ptrSelectedFaces.GetAt(i);
124       b = (brush_t *) g_ptrSelectedFaceBrushes.GetAt(i);
125       position = allocd_block_texdef + i;
126       position->face = f;
127       position->brush = b;
128       position->texdef = f->texdef;
129           if(g_qeglobals.m_bBrushPrimitMode)
130           {
131                   ConvertTexMatWithQTexture(&f->brushprimit_texdef, QERApp_Shader_ForName( f->texdef.GetName() )->getTexture(), &bp, NULL);
132                   TexMatToFakeTexCoords(bp.coords, position->texdef.shift, &position->texdef.rotate, position->texdef.scale);
133                   position->orig_bp_texdef = bp;
134           }
135       position->orig_texdef = position->texdef;
136       prev_pos->next = position;
137       prev_pos = position;
138     }
139     position->next = NULL;
140   }
141
142 }
143
144 /*
145 SetFaceTexdef_Q2
146
147 This doesn't mess with CONTENTS_DETAIL needed for Quake2 content flag
148
149 */
150 void SetFaceTexdef_Q2 (face_t *f, texdef_t *texdef, bool bFitScale)
151 {
152
153   if(strcmp(f->texdef.GetName(), texdef->GetName()) != 0) // set shader here instead of Brush_Build
154     Face_SetShader(f, texdef->GetName());
155
156                 if (bFitScale)
157                 {
158                         f->texdef = *texdef;
159                         // fit the scaling of the texture on the actual plane
160                         vec3_t p1,p2,p3; // absolute coordinates
161                         // compute absolute coordinates
162                         ComputeAbsolute(f,p1,p2,p3);
163                         // compute the scale
164                         vec3_t vx,vy;
165                         VectorSubtract(p2,p1,vx);
166                         VectorNormalize(vx, vx);
167                         VectorSubtract(p3,p1,vy);
168                         VectorNormalize(vy, vy);
169                         // assign scale
170                         VectorScale(vx,texdef->scale[0],vx);
171                         VectorScale(vy,texdef->scale[1],vy);
172                         VectorAdd(p1,vx,p2);
173                         VectorAdd(p1,vy,p3);
174                         // compute back shift scale rot
175                         AbsoluteToLocal(f->plane,f,p1,p2,p3);
176                 }
177                 else
178     {
179                         f->texdef = *texdef;
180     }
181   }
182
183
184
185 void SI_SetTexdef_FaceList(texdef_to_face_t* texdef_face_list, bool b_SetUndoPoint, bool bFit_to_Scale)
186 {
187   texdef_to_face_t* texdef_to_face;
188   bool b_isQuake2;
189
190   if (g_pGameDescription->quake2)
191     b_isQuake2 = true;
192   else
193     b_isQuake2 = false;
194
195   if (!texdef_face_list)
196     return;
197
198  if (b_SetUndoPoint)
199  {
200     if(g_ptrSelectedFaces.GetSize() > 1)
201       Sys_FPrintf(SYS_WRN, "WARNING: Undo NOT supported for multiple face selections\n");
202     else if( (selected_brushes.next != &selected_brushes) || (g_ptrSelectedFaces.GetSize() == 1))
203     {
204       // Give something to undo to
205       for(texdef_to_face = texdef_face_list; texdef_to_face; texdef_to_face = texdef_to_face->next)
206       if (b_isQuake2)
207         SetFaceTexdef_Q2(texdef_to_face->face, &texdef_to_face->orig_texdef, bFit_to_Scale);
208       else
209         SetFaceTexdef(texdef_to_face->face, &texdef_to_face->orig_texdef, &texdef_to_face->orig_bp_texdef, bFit_to_Scale);
210
211       Undo_Start("set facelist texdefs");
212
213       if( selected_brushes.next != &selected_brushes )
214         Undo_AddBrushList(&selected_brushes);
215       else
216         Undo_AddBrush(texdef_face_list->brush);
217
218     }
219  }
220
221   for(texdef_to_face = texdef_face_list; texdef_to_face; texdef_to_face = texdef_to_face->next)
222   {
223     if (b_isQuake2)
224       SetFaceTexdef_Q2(texdef_to_face->face, &texdef_to_face->texdef,  bFit_to_Scale);
225     else
226         {
227           brushprimit_texdef_t brushprimit_texdef;
228           FakeTexCoordsToTexMat(texdef_to_face->texdef.shift, texdef_to_face->texdef.rotate, texdef_to_face->texdef.scale, brushprimit_texdef.coords);
229       SetFaceTexdef(texdef_to_face->face, &texdef_to_face->texdef, &brushprimit_texdef , bFit_to_Scale);
230         }
231     Brush_Build(texdef_to_face->brush);
232     if(bFit_to_Scale)
233       texdef_to_face->texdef = texdef_to_face->face->texdef;
234   }
235
236   if ( b_SetUndoPoint )
237   {
238       if( (selected_brushes.next != &selected_brushes) || (g_ptrSelectedFaces.GetSize() == 1) )
239       {
240         if(selected_brushes.next != &selected_brushes)
241           Undo_EndBrushList(&selected_brushes);
242         else
243           Undo_EndBrush(texdef_face_list->brush);
244
245         Undo_End();
246         // Over-write the orig_texdef list, cementing the change.
247         for(texdef_to_face = texdef_face_list; texdef_to_face; texdef_to_face = texdef_to_face->next)
248         {
249           texdef_to_face->orig_texdef = texdef_to_face->texdef;
250           texdef_to_face->orig_bp_texdef = texdef_to_face->face->brushprimit_texdef;
251         }
252       }
253   }
254
255   Sys_UpdateWindows (W_ALL);
256 }
257
258 void SI_FaceList_FitTexture(texdef_to_face_t* si_texdef_face_list, int nHeight, int nWidth)
259 {
260   texdef_to_face_t* temp_texdef_face_list;
261   brushprimit_texdef_t bp;
262
263   if (!si_texdef_face_list)
264     return;
265
266   for (temp_texdef_face_list = si_texdef_face_list; temp_texdef_face_list; temp_texdef_face_list = temp_texdef_face_list->next)
267   {
268     Face_FitTexture(temp_texdef_face_list->face, nHeight, nWidth);
269     Brush_Build(temp_texdef_face_list->brush,true,true,false,false);
270     // Write changes to our working Texdef list
271         
272         if(g_qeglobals.m_bBrushPrimitMode)
273         {
274                 ConvertTexMatWithQTexture(&temp_texdef_face_list->face->brushprimit_texdef, QERApp_Shader_ForName( temp_texdef_face_list->face->texdef.GetName() )->getTexture(), &bp, NULL);
275                 TexMatToFakeTexCoords(bp.coords, temp_texdef_face_list->face->texdef.shift, &temp_texdef_face_list->face->texdef.rotate, temp_texdef_face_list->face->texdef.scale);
276         }
277     temp_texdef_face_list->texdef = temp_texdef_face_list->face->texdef;
278   }
279
280   Sys_UpdateWindows (W_CAMERA);
281
282 }
283
284 GtkWindow* SI_GetMainWindow(void)
285 {
286   return GTK_WINDOW(g_qeglobals_gui.d_main_window);
287 }
288
289 void SI_SetWinPos_from_Prefs(GtkWidget *win)
290 {
291   load_window_pos (win, g_PrefsDlg.mWindowInfo.posSurfaceWnd);
292 }