]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/brushscript.cpp
uncrustify! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / radiant / brushscript.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 // BrushScript stuff
23 //
24
25 /*!
26    \todo is this still used / in working state?
27    should we cleanup and remove it for good
28  */
29
30 #include "stdafx.h"
31 #include "gtkmisc.h"
32
33 //
34 struct SVariableDef
35 {
36         CString m_strName;
37         CString m_strInput;
38         float m_fValue;
39 };
40
41 struct SVecVariableDef
42 {
43         CString m_strName;
44         CString m_strInput;
45         vec3_t m_vValue;
46 };
47
48
49
50 const int MAX_VARIABLES = 64;
51
52 brush_t* g_pHold1 = NULL;
53 brush_t* g_pHold2 = NULL;
54 brush_t* g_pHold3 = NULL;
55 bool g_bRotateAroundSelection;
56 int g_nVariableCount;
57 int g_nVecVariableCount;
58 int g_nLoopCounter;
59 float g_fDefault = 9999.9f;
60 vec3_t g_vDefault;
61 bool g_bStartLoop;
62 char* g_pLooper;
63 bool g_bKeepGoing;
64
65 SVariableDef g_Variables[MAX_VARIABLES];
66 SVecVariableDef g_VecVariables[MAX_VARIABLES];
67
68 void InitForScriptRun(){
69         g_pHold1 = NULL;
70         g_pHold2 = NULL;
71         g_pHold3 = NULL;
72         g_bRotateAroundSelection = true;
73         g_nVariableCount = 0;
74         g_nVecVariableCount = 0;
75         g_nLoopCounter = 0;
76         g_bStartLoop = false;
77         g_pLooper = NULL;
78         g_bKeepGoing = true;
79 }
80
81 void AddVariable( const char* pName, float fValue, const char* pInput = NULL ){
82         if ( g_nVariableCount < MAX_VARIABLES ) {
83                 g_Variables[g_nVariableCount].m_strName = pName;
84                 g_Variables[g_nVariableCount].m_strName.MakeLower();
85                 g_Variables[g_nVariableCount].m_fValue = fValue;
86                 if ( pInput ) {
87                         g_Variables[g_nVariableCount].m_strInput = pInput;
88                 }
89                 g_nVariableCount++;
90         }
91         else{
92                 gtk_MessageBox( g_pParentWnd->m_pWidget, "Maximum script variable limit reached!" );
93         }
94 }
95
96 float VariableValue( const char* pName ){
97         CString strName = pName;
98         strName.MakeLower();
99         for ( int n = 0; n < g_nVariableCount; n++ )
100         {
101                 if ( strName == g_Variables[n].m_strName ) {
102                         return g_Variables[n].m_fValue;
103                 }
104         }
105         //strName.Format("Reference to non-existant varirable %s", pName);
106         //g_pParentWnd->MessageBox(strName);
107         return g_fDefault;
108 }
109
110 void SetVariableValue( const char* pName, float fValue ){
111         CString strName = pName;
112         strName.MakeLower();
113         for ( int n = 0; n < g_nVariableCount; n++ )
114         {
115                 if ( strName == g_Variables[n].m_strName ) {
116                         g_Variables[n].m_fValue = fValue;
117                 }
118         }
119 }
120
121
122
123 void AddVectorVariable( const char* pName, const char* pInput = NULL ){
124         if ( g_nVecVariableCount < MAX_VARIABLES ) {
125                 g_VecVariables[g_nVecVariableCount].m_strName = pName;
126                 g_VecVariables[g_nVecVariableCount].m_strName.MakeLower();
127                 if ( pInput ) {
128                         g_VecVariables[g_nVariableCount].m_strInput = pInput;
129                 }
130                 g_nVecVariableCount++;
131         }
132         else{
133                 gtk_MessageBox( g_pParentWnd->m_pWidget, "Maximum script variable limit reached!" );
134         }
135 }
136
137 void VectorVariableValue( const char* pName, vec3_t& v ){
138         CString strName = pName;
139         strName.MakeLower();
140         for ( int n = 0; n < g_nVecVariableCount; n++ )
141         {
142                 if ( strName == g_VecVariables[n].m_strName ) {
143                         VectorCopy( g_VecVariables[n].m_vValue, v );
144                         return;
145                 }
146         }
147         strName.Format( "Reference to non-existant variable %s", pName );
148         gtk_MessageBox( g_pParentWnd->m_pWidget, strName );
149 }
150
151 void SetVectorVariableValue( const char* pName, vec3_t v ){
152         CString strName = pName;
153         strName.MakeLower();
154         for ( int n = 0; n < g_nVecVariableCount; n++ )
155         {
156                 if ( strName == g_VecVariables[n].m_strName ) {
157                         VectorCopy( v, g_VecVariables[n].m_vValue );
158                 }
159         }
160 }
161
162
163
164
165
166 // commands
167 //
168 // _CopySelected(nHoldPos)
169 // copies selected brush to hold spot 1, 2 or 3
170 //
171 // _MoveSelected(x, y, z)
172 // moves selected brush by coords provided
173 //
174 // _RotateSelected(x, y, z)
175 // rotates selected brush by coords provided
176 //
177 // _MoveHold(nHoldPos, x, y, z)
178 // moves brush in hold pos by coords provided
179 //
180 // _RotateHold(nHoldPos, x, y, z)
181 // rotates brush in hold pos by coords provided
182 //
183 // _CopyToMap(nHoldPos)
184 // copies hold brush to map
185 //
186 // _CopyAndSelect(nHoldPos)
187 // copies hold brush to map and selects it
188 //
189 // _Input(VarName1, ... VarNamennn)
190 // inputs a list of values from the user
191 //
192
193 typedef void ( PFNScript )( char*& );
194
195
196 struct SBrushScript
197 {
198         const char* m_pName;
199         PFNScript* m_pProc;
200 };
201
202
203 const char* GetParam( char*& pBuffer ){
204         static CString strParam;
205         bool bStringMode = false;
206
207         while ( *pBuffer != (char)NULL && isspace( *pBuffer ) ) // skip and whitespace
208                 pBuffer++;
209
210         if ( *pBuffer == '(' ) { // if it's an opening paren, skip it
211                 pBuffer++;
212         }
213
214         if ( *pBuffer == '\"' ) { // string ?
215                 pBuffer++;
216                 bStringMode = true;
217         }
218
219         strParam = "";
220
221         if ( bStringMode ) {
222                 while ( *pBuffer != (char)NULL && *pBuffer != '\"' )
223                         strParam += *pBuffer++;
224         }
225         else
226         {
227                 while ( *pBuffer != (char)NULL && *pBuffer != ' ' && *pBuffer != ')' && *pBuffer != ',' )
228                         strParam += *pBuffer++;
229         }
230
231         if ( *pBuffer != (char)NULL ) { // skip last char
232                 pBuffer++;
233         }
234
235         if ( strParam.GetLength() > 0 ) {
236                 if ( strParam.GetAt( 0 ) == '$' ) { // ? variable name
237                         float f = VariableValue( strParam );
238                         if ( f != g_fDefault ) {
239                                 strParam.Format( "%f", f );
240                         }
241                 }
242         }
243
244         return strParam;
245 }
246
247 brush_t* CopyBrush( brush_t* p ){
248         brush_t* pCopy = Brush_Clone( p );
249         //Brush_AddToList (pCopy, &active_brushes);
250         //Entity_LinkBrush (world_entity, pCopy);
251         Brush_Build( pCopy, false );
252
253         return pCopy;
254 }
255
256
257 void CopySelected( char*& pBuffer ){
258         // expects one param
259         CString strParam = GetParam( pBuffer );
260         int n = atoi( strParam );
261
262         brush_t* pCopy = NULL;
263         if ( selected_brushes.next != &selected_brushes &&
264                  selected_brushes.next->next == &selected_brushes ) {
265                 pCopy = selected_brushes.next;
266         }
267
268         if ( pCopy ) {
269                 if ( n == 1 ) {
270                         //if (g_pHold1)
271                         //Brush_Free(g_pHold1);
272                         g_pHold1 = CopyBrush( pCopy );
273                 }
274                 else if ( n == 2 ) {
275                         //if (g_pHold2)
276                         //Brush_Free(g_pHold2);
277                         g_pHold2 = CopyBrush( pCopy );
278                 }
279                 else
280                 {
281                         //if (g_pHold3)
282                         //Brush_Free(g_pHold3);
283                         g_pHold3 = CopyBrush( pCopy );
284                 }
285         }
286 }
287
288 void MoveSelected( char*& pBuffer ){
289         vec3_t v;
290         CString strParam = GetParam( pBuffer );
291         v[0] = atof( strParam );
292         strParam = GetParam( pBuffer );
293         v[1] = atof( strParam );
294         strParam = GetParam( pBuffer );
295         v[2] = atof( strParam );
296         Select_Move( v, false );
297         Sys_UpdateWindows( W_ALL );
298 }
299
300 void RotateSelected( char*& pBuffer ){
301         vec3_t v;
302
303         if ( g_bRotateAroundSelection ) {
304                 Select_GetTrueMid( v );
305                 VectorCopy( v, g_pParentWnd->ActiveXY()->RotateOrigin() );
306         }
307
308         CString strParam = GetParam( pBuffer );
309         v[0] = atof( strParam );
310         strParam = GetParam( pBuffer );
311         v[1] = atof( strParam );
312         strParam = GetParam( pBuffer );
313         v[2] = atof( strParam );
314         for ( int i = 0; i < 3; i++ )
315                 if ( v[i] != 0.0 ) {
316                         Select_RotateAxis( i, v[i], false, true );
317                 }
318         Sys_UpdateWindows( W_ALL );
319 }
320
321 void MoveHold( char*& pBuffer ){
322         CString strParam = GetParam( pBuffer );
323         brush_t* pBrush = NULL;
324         int nHold = atoi( strParam );
325         if ( nHold == 1 ) {
326                 pBrush = g_pHold1;
327         }
328         else if ( nHold == 2 ) {
329                 pBrush = g_pHold2;
330         }
331         else{
332                 pBrush = g_pHold3;
333         }
334
335         if ( pBrush ) {
336                 vec3_t v;
337                 strParam = GetParam( pBuffer );
338                 v[0] = atof( strParam );
339                 strParam = GetParam( pBuffer );
340                 v[1] = atof( strParam );
341                 strParam = GetParam( pBuffer );
342                 v[2] = atof( strParam );
343                 Brush_Move( pBrush, v, false );
344         }
345 }
346
347 void RotateHold( char*& pBuffer ){
348         CString strParam = GetParam( pBuffer );
349         brush_t* pBrush = NULL;
350         int nHold = atoi( strParam );
351         if ( nHold == 1 ) {
352                 pBrush = g_pHold1;
353         }
354         else if ( nHold == 2 ) {
355                 pBrush = g_pHold2;
356         }
357         else{
358                 pBrush = g_pHold3;
359         }
360
361         if ( pBrush ) {
362                 vec3_t v;
363                 strParam = GetParam( pBuffer );
364                 v[0] = atof( strParam );
365                 strParam = GetParam( pBuffer );
366                 v[1] = atof( strParam );
367                 strParam = GetParam( pBuffer );
368                 v[2] = atof( strParam );
369                 for ( int i = 0; i < 3; i++ )
370                         if ( v[i] != 0.0 ) {
371                                 Select_RotateAxis( i, v[i] );
372                         }
373         }
374 }
375
376 void CopyToMap( char*& pBuffer ){
377         CString strParam = GetParam( pBuffer );
378         brush_t* pBrush = NULL;
379         int nHold = atoi( strParam );
380         if ( nHold == 1 ) {
381                 pBrush = g_pHold1;
382         }
383         else if ( nHold == 2 ) {
384                 pBrush = g_pHold2;
385         }
386         else{
387                 pBrush = g_pHold3;
388         }
389
390         if ( pBrush ) {
391                 Brush_AddToList( pBrush, &active_brushes );
392                 Entity_LinkBrush( world_entity, pBrush );
393                 Brush_Build( pBrush, false );
394
395                 Sys_UpdateWindows( W_ALL );
396         }
397 }
398
399 void CopyAndSelect( char*& pBuffer ){
400         CString strParam = GetParam( pBuffer );
401         brush_t* pBrush = NULL;
402         int nHold = atoi( strParam );
403         if ( nHold == 1 ) {
404                 pBrush = g_pHold1;
405         }
406         else if ( nHold == 2 ) {
407                 pBrush = g_pHold2;
408         }
409         else{
410                 pBrush = g_pHold3;
411         }
412
413         if ( pBrush ) {
414                 Select_Deselect();
415                 Brush_AddToList( pBrush, &active_brushes );
416                 Entity_LinkBrush( world_entity, pBrush );
417                 Brush_Build( pBrush, false );
418
419                 Select_Brush( pBrush );
420                 Sys_UpdateWindows( W_ALL );
421         }
422 }
423
424 void Input( char*& pBuffer ){
425         bool bGo = false;
426         const char *fields[5] = { "", "", "", "", "" };
427         float values[5];
428
429         for ( int n = 0; n < g_nVariableCount; n++ )
430         {
431                 if ( g_Variables[n].m_strInput.GetLength() > 0 ) {
432                         bGo = true;
433                         if ( n < 5 ) {
434                                 switch ( n )
435                                 {
436                                 case 0: fields[1] = g_Variables[n].m_strInput.GetBuffer(); break;
437                                 case 1: fields[2] = g_Variables[n].m_strInput.GetBuffer(); break;
438                                 case 2: fields[3] = g_Variables[n].m_strInput.GetBuffer(); break;
439                                 case 3: fields[4] = g_Variables[n].m_strInput.GetBuffer(); break;
440                                 case 4: fields[5] = g_Variables[n].m_strInput.GetBuffer(); break;
441                                 }
442                         }
443                 }
444         }
445
446         if ( bGo ) {
447                 if ( DoBSInputDlg( fields, values ) == IDOK ) {
448                         for ( int n = 0; n < g_nVariableCount; n++ )
449                         {
450                                 if ( g_Variables[n].m_strInput.GetLength() > 0 ) {
451                                         if ( n < 5 ) {
452                                                 switch ( n )
453                                                 {
454                                                 case 0: g_Variables[n].m_fValue = values[1]; break;
455                                                 case 1: g_Variables[n].m_fValue = values[2]; break;
456                                                 case 2: g_Variables[n].m_fValue = values[3]; break;
457                                                 case 3: g_Variables[n].m_fValue = values[4]; break;
458                                                 case 4: g_Variables[n].m_fValue = values[5]; break;
459                                                 }
460                                         }
461                                 }
462                         }
463                 }
464                 else{ g_bKeepGoing = false; }
465         }
466 }
467
468 bool g_bWaiting;
469 void _3DPointDone( bool b, int n ){
470         g_bWaiting = false;
471 }
472
473 void _3DPointInput( char*& pBuffer ){
474         CString strParam = GetParam( pBuffer );
475         CString strParam2 = GetParam( pBuffer );
476         ShowInfoDialog( strParam2 );
477         AddVectorVariable( strParam, strParam2 );
478         g_bWaiting = true;
479         AcquirePath( 2, &_3DPointDone );
480         while ( g_bWaiting )
481                 gtk_main_iteration();
482         HideInfoDialog();
483         SetVectorVariableValue( strParam, g_PathPoints[0] );
484 }
485
486 void SetRotateOrigin( char*& pBuffer ){
487         vec3_t v;
488         CString strParam = GetParam( pBuffer );
489         VectorVariableValue( strParam, v );
490         VectorCopy( v, g_pParentWnd->ActiveXY()->RotateOrigin() );
491         g_bRotateAroundSelection = false;
492 }
493
494 void InputVar( char*& pBuffer ){
495         CString strParam = GetParam( pBuffer );
496         CString strParam2 = GetParam( pBuffer );
497         AddVariable( strParam, 0.0, strParam2 );
498 }
499
500 void LoopCount( char*& pBuffer ){
501         CString strParam = GetParam( pBuffer );
502         g_nLoopCounter = atoi( strParam );
503         if ( g_nLoopCounter == 0 ) {
504                 g_nLoopCounter = (int)VariableValue( strParam );
505         }
506         if ( g_nLoopCounter > 0 ) {
507                 g_pLooper = pBuffer;
508         }
509 }
510
511 void LoopRun( char*& pBuffer ){
512         if ( g_bStartLoop == true ) {
513                 g_nLoopCounter--;
514                 if ( g_nLoopCounter == 0 ) {
515                         g_bStartLoop = false;
516                         GetParam( pBuffer );
517                 }
518                 else{
519                         pBuffer = g_pLooper;
520                 }
521         }
522         else
523         {
524                 if ( g_pLooper && g_nLoopCounter > 0 ) {
525                         g_bStartLoop = true;
526                         pBuffer = g_pLooper;
527                 }
528                 else
529                 {
530                         GetParam( pBuffer );
531                 }
532         }
533 }
534
535
536 void ConfirmMessage( char*& pBuffer ){
537         CString strParam = GetParam( pBuffer );
538         if ( gtk_MessageBox( g_pParentWnd->m_pWidget, strParam, "Script Info", MB_OKCANCEL ) == IDCANCEL ) {
539                 g_bKeepGoing = false;
540         }
541 }
542
543 void Spherize( char*& pBuffer ){
544         g_bScreenUpdates = false;
545         for ( int n = 0; n < 120; n += 36 )
546         {
547                 for ( int i = 0; i < 360; i += 36 )
548                 {
549                         Select_RotateAxis( 0, i, false, true );
550                         CSG_Subtract();
551                 }
552                 Select_RotateAxis( 2, n, false, true );
553         }
554         g_bScreenUpdates = true;
555 }
556
557 void RunIt( char*& pBuffer );
558 SBrushScript g_ScriptCmds[] =
559 {
560         {"_CopySelected", &CopySelected},
561         {"_MoveSelected", &MoveSelected},
562         {"_RotateSelected", &RotateSelected},
563         {"_MoveHold", &MoveHold},
564         {"_RotateHold", &RotateHold},
565         {"_CopyToMap", &CopyToMap},
566         {"_CopyAndSelect", &CopyAndSelect},
567         {"_Input", &Input},
568         {"_3DPointInput", &_3DPointInput},
569         {"_SetRotateOrigin", &SetRotateOrigin},
570         {"_InputVar", &InputVar},
571         {"_LoopCount", &LoopCount},
572         {"_LoopRun", &LoopRun},
573         {"_ConfirmMessage", &ConfirmMessage},
574         {"_Spherize", &Spherize},
575         {"_RunScript", RunIt}
576 };
577
578 const int g_nScriptCmdCount = sizeof( g_ScriptCmds ) / sizeof( SBrushScript );
579
580 void RunScript( char* pBuffer ){
581         g_pHold1 = NULL;
582         g_pHold2 = NULL;
583         g_pHold3 = NULL;
584
585         while ( g_bKeepGoing && pBuffer && *pBuffer )
586         {
587                 while ( *pBuffer != (char)NULL && *pBuffer != '_' )
588                         pBuffer++;
589
590                 char* pTemp = pBuffer;
591                 int nLen = 0;
592                 while ( *pTemp != (char)NULL && *pTemp != '(' )
593                 {
594                         pTemp++;
595                         nLen++;
596                 }
597                 if ( *pBuffer != (char)NULL ) {
598                         bool bFound = false;
599                         for ( int i = 0; i < g_nScriptCmdCount; i++ )
600                         {
601                                 //if (strnicmp(g_ScriptCmds[i].m_pName, pBuffer, strlen(g_ScriptCmds[i].m_pName)) ==  0)
602                                 if ( strnicmp( g_ScriptCmds[i].m_pName, pBuffer, nLen ) ==  0 ) {
603                                         pBuffer += strlen( g_ScriptCmds[i].m_pName );
604                                         g_ScriptCmds[i].m_pProc( pBuffer );
605                                         if ( g_bStartLoop ) {
606                                         }
607                                         bFound = true;
608                                         break;
609                                 }
610                         }
611                         if ( !bFound ) {
612                                 pBuffer++;
613                         }
614                 }
615         }
616 }
617
618
619 void RunScriptByName( char* pBuffer, bool bInit ){
620         if ( bInit ) {
621                 InitForScriptRun();
622         }
623         char* pScript = new char[4096];
624         CString strINI;
625         strINI = g_strGameToolsPath;
626         strINI += "/scripts.ini";
627         CString strScript;
628         FILE *f;
629
630         f = fopen( strINI.GetBuffer(), "rt" );
631         if ( f != NULL ) {
632                 char line[1024], *ptr;
633
634                 // read section names
635                 while ( fgets( line, 1024, f ) != 0 )
636                 {
637                         if ( line[0] != '[' ) {
638                                 continue;
639                         }
640
641                         ptr = strchr( line, ']' );
642                         *ptr = '\0';
643
644                         if ( strcmp( line, pScript ) == 0 ) {
645                                 while ( fgets( line, 1024, f ) != 0 )
646                                 {
647                                         if ( ( strchr( line, '=' ) == NULL ) ||
648                                                  strlen( line ) == 0 ) {
649                                                 break;
650                                         }
651                                         strScript += line;
652                                 }
653                                 break;
654                         }
655                 }
656                 fclose( f );
657         }
658         RunScript( (char*)strScript.GetBuffer() );
659 }
660
661
662 void RunIt( char*& pBuffer ){
663         brush_t* p1 = g_pHold1;
664         brush_t* p2 = g_pHold2;
665         brush_t* p3 = g_pHold3;
666
667         CString strParam = GetParam( pBuffer );
668         RunScriptByName( (char*)strParam.GetBuffer(), false );
669
670         g_pHold3 = p3;
671         g_pHold2 = p2;
672         g_pHold1 = p1;
673 }