BrushScript.cpp (14939B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, 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 Foobar; 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 #include "stdafx.h" 25 #include "qe3.h" 26 #include "BSInput.h" 27 #include "DialogInfo.h" 28 29 30 // 31 struct SVariableDef 32 { 33 CString m_strName; 34 CString m_strInput; 35 float m_fValue; 36 }; 37 38 struct SVecVariableDef 39 { 40 CString m_strName; 41 CString m_strInput; 42 vec3_t m_vValue; 43 }; 44 45 46 47 const int MAX_VARIABLES = 64; 48 49 brush_t* g_pHold1 = NULL; 50 brush_t* g_pHold2 = NULL; 51 brush_t* g_pHold3 = NULL; 52 bool g_bRotateAroundSelection; 53 int g_nVariableCount; 54 int g_nVecVariableCount; 55 int g_nLoopCounter; 56 float g_fDefault = 9999.9; 57 vec3_t g_vDefault; 58 bool g_bStartLoop; 59 char* g_pLooper; 60 bool g_bKeepGoing; 61 62 SVariableDef g_Variables[MAX_VARIABLES]; 63 SVecVariableDef g_VecVariables[MAX_VARIABLES]; 64 65 void InitForScriptRun() 66 { 67 g_pHold1 = NULL; 68 g_pHold2 = NULL; 69 g_pHold3 = NULL; 70 g_bRotateAroundSelection = true; 71 g_nVariableCount = 0; 72 g_nVecVariableCount = 0; 73 g_nLoopCounter = 0; 74 g_bStartLoop = false; 75 g_pLooper = NULL; 76 g_bKeepGoing = true; 77 } 78 79 void AddVariable(const char* pName, float fValue, const char* pInput = NULL) 80 { 81 if (g_nVariableCount < MAX_VARIABLES) 82 { 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 g_nVariableCount++; 89 } 90 else 91 g_pParentWnd->MessageBox("Maximum script variable limit reached!"); 92 } 93 94 float VariableValue(const char* pName) 95 { 96 CString strName = pName; 97 strName.MakeLower(); 98 for (int n = 0; n < g_nVariableCount; n++) 99 { 100 if (strName == g_Variables[n].m_strName) 101 return g_Variables[n].m_fValue; 102 } 103 //strName.Format("Reference to non-existant varirable %s", pName); 104 //g_pParentWnd->MessageBox(strName); 105 return g_fDefault; 106 } 107 108 void SetVariableValue(const char* pName, float fValue) 109 { 110 CString strName = pName; 111 strName.MakeLower(); 112 for (int n = 0; n < g_nVariableCount; n++) 113 { 114 if (strName == g_Variables[n].m_strName) 115 g_Variables[n].m_fValue = fValue; 116 } 117 } 118 119 120 121 void AddVectorVariable(const char* pName, const char* pInput = NULL) 122 { 123 if (g_nVecVariableCount < MAX_VARIABLES) 124 { 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 g_nVecVariableCount++; 130 } 131 else 132 g_pParentWnd->MessageBox("Maximum script variable limit reached!"); 133 } 134 135 void VectorVariableValue(const char* pName, vec3_t& v) 136 { 137 CString strName = pName; 138 strName.MakeLower(); 139 for (int n = 0; n < g_nVecVariableCount; n++) 140 { 141 if (strName == g_VecVariables[n].m_strName) 142 { 143 VectorCopy(g_VecVariables[n].m_vValue, v); 144 return; 145 } 146 } 147 strName.Format("Reference to non-existant variable %s", pName); 148 g_pParentWnd->MessageBox(strName); 149 } 150 151 void SetVectorVariableValue(const char* pName, vec3_t v) 152 { 153 CString strName = pName; 154 strName.MakeLower(); 155 for (int n = 0; n < g_nVecVariableCount; n++) 156 { 157 if (strName == g_VecVariables[n].m_strName) 158 VectorCopy(v, g_VecVariables[n].m_vValue); 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 { 205 static CString strParam; 206 bool bStringMode = false; 207 208 while (*pBuffer != NULL && isspace(*pBuffer)) // skip and whitespace 209 pBuffer++; 210 211 if (*pBuffer == '(') // if it's an opening paren, skip it 212 pBuffer++; 213 214 if (*pBuffer == '\"') // string ? 215 { 216 pBuffer++; 217 bStringMode = true; 218 } 219 220 strParam = ""; 221 222 if (bStringMode) 223 { 224 while (*pBuffer != NULL && *pBuffer != '\"') 225 strParam += *pBuffer++; 226 } 227 else 228 { 229 while (*pBuffer != NULL && *pBuffer != ' ' && *pBuffer != ')' && *pBuffer != ',') 230 strParam += *pBuffer++; 231 } 232 233 if (*pBuffer != NULL) // skip last char 234 pBuffer++; 235 236 if (strParam.GetLength() > 0) 237 { 238 if (strParam.GetAt(0) == '$') // ? variable name 239 { 240 float f = VariableValue(strParam); 241 if (f != g_fDefault) 242 strParam.Format("%f", f); 243 } 244 } 245 246 return strParam; 247 } 248 249 brush_t* CopyBrush(brush_t* p) 250 { 251 brush_t* pCopy = Brush_Clone(p); 252 //Brush_AddToList (pCopy, &active_brushes); 253 //Entity_LinkBrush (world_entity, pCopy); 254 Brush_Build(pCopy, false); 255 return pCopy; 256 } 257 258 259 void CopySelected(char*& pBuffer) 260 { 261 // expects one param 262 CString strParam = GetParam(pBuffer); 263 int n = atoi(strParam); 264 265 brush_t* pCopy = NULL; 266 if (selected_brushes.next != &selected_brushes && 267 selected_brushes.next->next == &selected_brushes) 268 pCopy = selected_brushes.next; 269 270 if (pCopy) 271 { 272 if (n == 1) 273 { 274 //if (g_pHold1) 275 //Brush_Free(g_pHold1); 276 g_pHold1 = CopyBrush(pCopy); 277 } 278 else if (n == 2) 279 { 280 //if (g_pHold2) 281 //Brush_Free(g_pHold2); 282 g_pHold2 = CopyBrush(pCopy); 283 } 284 else 285 { 286 //if (g_pHold3) 287 //Brush_Free(g_pHold3); 288 g_pHold3 = CopyBrush(pCopy); 289 } 290 } 291 } 292 293 void MoveSelected(char*& pBuffer) 294 { 295 vec3_t v; 296 CString strParam = GetParam(pBuffer); 297 v[0] = atof(strParam); 298 strParam = GetParam(pBuffer); 299 v[1] = atof(strParam); 300 strParam = GetParam(pBuffer); 301 v[2] = atof(strParam); 302 Select_Move(v, false); 303 Sys_UpdateWindows(W_ALL); 304 } 305 306 void RotateSelected(char*& pBuffer) 307 { 308 vec3_t v; 309 310 if (g_bRotateAroundSelection) 311 { 312 Select_GetTrueMid(v); 313 VectorCopy(v, g_pParentWnd->ActiveXY()->RotateOrigin()); 314 } 315 316 CString strParam = GetParam(pBuffer); 317 v[0] = atof(strParam); 318 strParam = GetParam(pBuffer); 319 v[1] = atof(strParam); 320 strParam = GetParam(pBuffer); 321 v[2] = atof(strParam); 322 for (int i = 0; i < 3; i++) 323 if (v[i] != 0.0) 324 Select_RotateAxis(i, v[i], false , true); 325 Sys_UpdateWindows(W_ALL); 326 } 327 328 void MoveHold(char*& pBuffer) 329 { 330 CString strParam = GetParam(pBuffer); 331 brush_t* pBrush = NULL; 332 int nHold = atoi(strParam); 333 if (nHold == 1) 334 pBrush = g_pHold1; 335 else if (nHold == 2) 336 pBrush = g_pHold2; 337 else 338 pBrush = g_pHold3; 339 340 if (pBrush) 341 { 342 vec3_t v; 343 strParam = GetParam(pBuffer); 344 v[0] = atof(strParam); 345 strParam = GetParam(pBuffer); 346 v[1] = atof(strParam); 347 strParam = GetParam(pBuffer); 348 v[2] = atof(strParam); 349 Brush_Move (pBrush, v, false); 350 } 351 } 352 353 void RotateHold(char*& pBuffer) 354 { 355 CString strParam = GetParam(pBuffer); 356 brush_t* pBrush = NULL; 357 int nHold = atoi(strParam); 358 if (nHold == 1) 359 pBrush = g_pHold1; 360 else if (nHold == 2) 361 pBrush = g_pHold2; 362 else 363 pBrush = g_pHold3; 364 365 if (pBrush) 366 { 367 vec3_t v; 368 strParam = GetParam(pBuffer); 369 v[0] = atof(strParam); 370 strParam = GetParam(pBuffer); 371 v[1] = atof(strParam); 372 strParam = GetParam(pBuffer); 373 v[2] = atof(strParam); 374 for (int i = 0; i < 3; i++) 375 if (v[i] != 0.0) 376 Select_RotateAxis(i, v[i]); 377 } 378 } 379 380 void CopyToMap(char*& pBuffer) 381 { 382 CString strParam = GetParam(pBuffer); 383 brush_t* pBrush = NULL; 384 int nHold = atoi(strParam); 385 if (nHold == 1) 386 pBrush = g_pHold1; 387 else if (nHold == 2) 388 pBrush = g_pHold2; 389 else 390 pBrush = g_pHold3; 391 392 if (pBrush) 393 { 394 Brush_AddToList(pBrush, &active_brushes); 395 Entity_LinkBrush (world_entity, pBrush); 396 Brush_Build(pBrush, false); 397 Sys_UpdateWindows(W_ALL); 398 } 399 } 400 401 void CopyAndSelect(char*& pBuffer) 402 { 403 CString strParam = GetParam(pBuffer); 404 brush_t* pBrush = NULL; 405 int nHold = atoi(strParam); 406 if (nHold == 1) 407 pBrush = g_pHold1; 408 else if (nHold == 2) 409 pBrush = g_pHold2; 410 else 411 pBrush = g_pHold3; 412 413 if (pBrush) 414 { 415 Select_Deselect(); 416 Brush_AddToList(pBrush, &active_brushes); 417 Entity_LinkBrush (world_entity, pBrush); 418 Brush_Build(pBrush, false); 419 Select_Brush(pBrush); 420 Sys_UpdateWindows(W_ALL); 421 } 422 } 423 424 void Input(char*& pBuffer) 425 { 426 CBSInput dlg; 427 bool bGo = false; 428 for (int n = 0; n < g_nVariableCount; n++) 429 { 430 if (g_Variables[n].m_strInput.GetLength() > 0) 431 { 432 bGo = true; 433 if (n < 5) 434 { 435 switch (n) 436 { 437 case 0 : dlg.m_strField1 = g_Variables[n].m_strInput; break; 438 case 1 : dlg.m_strField2 = g_Variables[n].m_strInput; break; 439 case 2 : dlg.m_strField3 = g_Variables[n].m_strInput; break; 440 case 3 : dlg.m_strField4 = g_Variables[n].m_strInput; break; 441 case 4 : dlg.m_strField5 = g_Variables[n].m_strInput; break; 442 } 443 } 444 } 445 } 446 if (bGo) 447 { 448 if (dlg.DoModal() == IDOK) 449 { 450 for (int n = 0; n < g_nVariableCount; n++) 451 { 452 if (g_Variables[n].m_strInput.GetLength() > 0) 453 { 454 if (n < 5) 455 { 456 switch (n) 457 { 458 case 0 : g_Variables[n].m_fValue = dlg.m_fField1; break; 459 case 1 : g_Variables[n].m_fValue = dlg.m_fField2; break; 460 case 2 : g_Variables[n].m_fValue = dlg.m_fField3; break; 461 case 3 : g_Variables[n].m_fValue = dlg.m_fField4; break; 462 case 4 : g_Variables[n].m_fValue = dlg.m_fField5; break; 463 } 464 } 465 } 466 } 467 } 468 else g_bKeepGoing = false; 469 } 470 } 471 472 bool g_bWaiting; 473 void _3DPointDone(bool b, int n) 474 { 475 g_bWaiting = false; 476 } 477 478 void _3DPointInput(char*& pBuffer) 479 { 480 CString strParam = GetParam(pBuffer); 481 CString strParam2 = GetParam(pBuffer); 482 ShowInfoDialog(strParam2); 483 AddVectorVariable(strParam, strParam2); 484 g_bWaiting = true; 485 AcquirePath(2, &_3DPointDone); 486 while (g_bWaiting) 487 { 488 MSG msg; 489 if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) 490 { 491 TranslateMessage(&msg); 492 DispatchMessage(&msg); 493 } 494 } 495 HideInfoDialog(); 496 SetVectorVariableValue(strParam, g_PathPoints[0]); 497 } 498 499 void SetRotateOrigin(char*& pBuffer) 500 { 501 vec3_t v; 502 CString strParam = GetParam(pBuffer); 503 VectorVariableValue(strParam, v); 504 VectorCopy(v, g_pParentWnd->ActiveXY()->RotateOrigin()); 505 g_bRotateAroundSelection = false; 506 } 507 508 void InputVar(char*& pBuffer) 509 { 510 CString strParam = GetParam(pBuffer); 511 CString strParam2 = GetParam(pBuffer); 512 AddVariable(strParam, 0.0, strParam2); 513 } 514 515 void LoopCount(char*& pBuffer) 516 { 517 CString strParam = GetParam(pBuffer); 518 g_nLoopCounter = atoi(strParam); 519 if (g_nLoopCounter == 0) 520 g_nLoopCounter = VariableValue(strParam); 521 if (g_nLoopCounter > 0) 522 g_pLooper = pBuffer; 523 } 524 525 void LoopRun(char*& pBuffer) 526 { 527 if (g_bStartLoop == true) 528 { 529 g_nLoopCounter--; 530 if (g_nLoopCounter == 0) 531 { 532 g_bStartLoop = false; 533 GetParam(pBuffer); 534 } 535 else 536 pBuffer = g_pLooper; 537 } 538 else 539 { 540 if (g_pLooper && g_nLoopCounter > 0) 541 { 542 g_bStartLoop = true; 543 pBuffer = g_pLooper; 544 } 545 else 546 { 547 GetParam(pBuffer); 548 } 549 } 550 } 551 552 553 void ConfirmMessage(char*& pBuffer) 554 { 555 CString strParam = GetParam(pBuffer); 556 if (g_pParentWnd->MessageBox(strParam, "Script Info", MB_OKCANCEL) == IDCANCEL) 557 g_bKeepGoing = false; 558 } 559 560 void Spherize(char*& pBuffer) 561 { 562 g_bScreenUpdates = false; 563 for (int n = 0; n < 120; n += 36) 564 { 565 for (int i = 0; i < 360; i += 36) 566 { 567 Select_RotateAxis(0, i, false , true); 568 CSG_Subtract(); 569 } 570 Select_RotateAxis(2, n, false , true); 571 } 572 g_bScreenUpdates = true; 573 } 574 575 void RunIt(char*& pBuffer); 576 SBrushScript g_ScriptCmds[] = 577 { 578 {"_CopySelected", &CopySelected}, 579 {"_MoveSelected", &MoveSelected}, 580 {"_RotateSelected", &RotateSelected}, 581 {"_MoveHold", &MoveHold}, 582 {"_RotateHold", &RotateHold}, 583 {"_CopyToMap", &CopyToMap}, 584 {"_CopyAndSelect", &CopyAndSelect}, 585 {"_Input", &Input}, 586 {"_3DPointInput", &_3DPointInput}, 587 {"_SetRotateOrigin", &SetRotateOrigin}, 588 {"_InputVar", &InputVar}, 589 {"_LoopCount", &LoopCount}, 590 {"_LoopRun", &LoopRun}, 591 {"_ConfirmMessage", &ConfirmMessage}, 592 {"_Spherize", &Spherize}, 593 {"_RunScript", RunIt} 594 }; 595 596 const int g_nScriptCmdCount = sizeof(g_ScriptCmds) / sizeof(SBrushScript); 597 598 void RunScript(char* pBuffer) 599 { 600 g_pHold1 = NULL; 601 g_pHold2 = NULL; 602 g_pHold3 = NULL; 603 604 while (g_bKeepGoing && pBuffer && *pBuffer) 605 { 606 while (*pBuffer != NULL && *pBuffer != '_') 607 pBuffer++; 608 609 char* pTemp = pBuffer; 610 int nLen = 0; 611 while (*pTemp != NULL && *pTemp != '(') 612 { 613 pTemp++; 614 nLen++; 615 } 616 if (*pBuffer != NULL) 617 { 618 bool bFound = false; 619 for (int i = 0; i < g_nScriptCmdCount; i++) 620 { 621 //if (strnicmp(g_ScriptCmds[i].m_pName, pBuffer, strlen(g_ScriptCmds[i].m_pName)) == 0) 622 if (strnicmp(g_ScriptCmds[i].m_pName, pBuffer, nLen) == 0) 623 { 624 pBuffer += strlen(g_ScriptCmds[i].m_pName); 625 g_ScriptCmds[i].m_pProc(pBuffer); 626 if (g_bStartLoop) 627 { 628 } 629 bFound = true; 630 break; 631 } 632 } 633 if (!bFound) 634 pBuffer++; 635 } 636 } 637 } 638 639 640 void RunScriptByName(char* pBuffer, bool bInit) 641 { 642 if (bInit) 643 InitForScriptRun(); 644 char* pScript = new char[4096]; 645 CString strINI = g_strAppPath; 646 strINI += "\\scripts.ini"; 647 GetPrivateProfileSection(pBuffer, pScript, 16384, strINI); 648 CString strScript; 649 char* pWorkScript = pScript; 650 while (*pWorkScript != NULL) 651 { 652 strScript += pWorkScript; 653 pWorkScript += strlen(pWorkScript) + 1; 654 } 655 RunScript(strScript.GetBuffer(0)); 656 } 657 658 659 void RunIt(char*& pBuffer) 660 { 661 brush_t* p1 = g_pHold1; 662 brush_t* p2 = g_pHold2; 663 brush_t* p3 = g_pHold3; 664 665 CString strParam = GetParam(pBuffer); 666 RunScriptByName(strParam.GetBuffer(0), false); 667 668 g_pHold3 = p3; 669 g_pHold2 = p2; 670 g_pHold1 = p1; 671 } 672