BrushScript.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. // BrushScript stuff
  19. //
  20. #include "stdafx.h"
  21. #include "qe3.h"
  22. #include "BSInput.h"
  23. #include "DialogInfo.h"
  24. //
  25. struct SVariableDef
  26. {
  27. CString m_strName;
  28. CString m_strInput;
  29. float m_fValue;
  30. };
  31. struct SVecVariableDef
  32. {
  33. CString m_strName;
  34. CString m_strInput;
  35. vec3_t m_vValue;
  36. };
  37. const int MAX_VARIABLES = 64;
  38. brush_t* g_pHold1 = NULL;
  39. brush_t* g_pHold2 = NULL;
  40. brush_t* g_pHold3 = NULL;
  41. bool g_bRotateAroundSelection;
  42. int g_nVariableCount;
  43. int g_nVecVariableCount;
  44. int g_nLoopCounter;
  45. float g_fDefault = 9999.9;
  46. vec3_t g_vDefault;
  47. bool g_bStartLoop;
  48. char* g_pLooper;
  49. bool g_bKeepGoing;
  50. SVariableDef g_Variables[MAX_VARIABLES];
  51. SVecVariableDef g_VecVariables[MAX_VARIABLES];
  52. void InitForScriptRun()
  53. {
  54. g_pHold1 = NULL;
  55. g_pHold2 = NULL;
  56. g_pHold3 = NULL;
  57. g_bRotateAroundSelection = true;
  58. g_nVariableCount = 0;
  59. g_nVecVariableCount = 0;
  60. g_nLoopCounter = 0;
  61. g_bStartLoop = false;
  62. g_pLooper = NULL;
  63. g_bKeepGoing = true;
  64. }
  65. void AddVariable(const char* pName, float fValue, const char* pInput = NULL)
  66. {
  67. if (g_nVariableCount < MAX_VARIABLES)
  68. {
  69. g_Variables[g_nVariableCount].m_strName = pName;
  70. g_Variables[g_nVariableCount].m_strName.MakeLower();
  71. g_Variables[g_nVariableCount].m_fValue = fValue;
  72. if (pInput)
  73. g_Variables[g_nVariableCount].m_strInput = pInput;
  74. g_nVariableCount++;
  75. }
  76. else
  77. g_pParentWnd->MessageBox("Maximum script variable limit reached!");
  78. }
  79. float VariableValue(const char* pName)
  80. {
  81. CString strName = pName;
  82. strName.MakeLower();
  83. for (int n = 0; n < g_nVariableCount; n++)
  84. {
  85. if (strName == g_Variables[n].m_strName)
  86. return g_Variables[n].m_fValue;
  87. }
  88. //strName.Format("Reference to non-existant varirable %s", pName);
  89. //g_pParentWnd->MessageBox(strName);
  90. return g_fDefault;
  91. }
  92. void SetVariableValue(const char* pName, float fValue)
  93. {
  94. CString strName = pName;
  95. strName.MakeLower();
  96. for (int n = 0; n < g_nVariableCount; n++)
  97. {
  98. if (strName == g_Variables[n].m_strName)
  99. g_Variables[n].m_fValue = fValue;
  100. }
  101. }
  102. void AddVectorVariable(const char* pName, const char* pInput = NULL)
  103. {
  104. if (g_nVecVariableCount < MAX_VARIABLES)
  105. {
  106. g_VecVariables[g_nVecVariableCount].m_strName = pName;
  107. g_VecVariables[g_nVecVariableCount].m_strName.MakeLower();
  108. if (pInput)
  109. g_VecVariables[g_nVariableCount].m_strInput = pInput;
  110. g_nVecVariableCount++;
  111. }
  112. else
  113. g_pParentWnd->MessageBox("Maximum script variable limit reached!");
  114. }
  115. void VectorVariableValue(const char* pName, vec3_t& v)
  116. {
  117. CString strName = pName;
  118. strName.MakeLower();
  119. for (int n = 0; n < g_nVecVariableCount; n++)
  120. {
  121. if (strName == g_VecVariables[n].m_strName)
  122. {
  123. VectorCopy(g_VecVariables[n].m_vValue, v);
  124. return;
  125. }
  126. }
  127. strName.Format("Reference to non-existant variable %s", pName);
  128. g_pParentWnd->MessageBox(strName);
  129. }
  130. void SetVectorVariableValue(const char* pName, vec3_t v)
  131. {
  132. CString strName = pName;
  133. strName.MakeLower();
  134. for (int n = 0; n < g_nVecVariableCount; n++)
  135. {
  136. if (strName == g_VecVariables[n].m_strName)
  137. VectorCopy(v, g_VecVariables[n].m_vValue);
  138. }
  139. }
  140. // commands
  141. //
  142. // _CopySelected(nHoldPos)
  143. // copies selected brush to hold spot 1, 2 or 3
  144. //
  145. // _MoveSelected(x, y, z)
  146. // moves selected brush by coords provided
  147. //
  148. // _RotateSelected(x, y, z)
  149. // rotates selected brush by coords provided
  150. //
  151. // _MoveHold(nHoldPos, x, y, z)
  152. // moves brush in hold pos by coords provided
  153. //
  154. // _RotateHold(nHoldPos, x, y, z)
  155. // rotates brush in hold pos by coords provided
  156. //
  157. // _CopyToMap(nHoldPos)
  158. // copies hold brush to map
  159. //
  160. // _CopyAndSelect(nHoldPos)
  161. // copies hold brush to map and selects it
  162. //
  163. // _Input(VarName1, ... VarNamennn)
  164. // inputs a list of values from the user
  165. //
  166. typedef void (PFNScript)(char*&);
  167. struct SBrushScript
  168. {
  169. const char* m_pName;
  170. PFNScript* m_pProc;
  171. };
  172. const char* GetParam(char*& pBuffer)
  173. {
  174. static CString strParam;
  175. bool bStringMode = false;
  176. while (*pBuffer != NULL && isspace(*pBuffer)) // skip and whitespace
  177. pBuffer++;
  178. if (*pBuffer == '(') // if it's an opening paren, skip it
  179. pBuffer++;
  180. if (*pBuffer == '\"') // string ?
  181. {
  182. pBuffer++;
  183. bStringMode = true;
  184. }
  185. strParam = "";
  186. if (bStringMode)
  187. {
  188. while (*pBuffer != NULL && *pBuffer != '\"')
  189. strParam += *pBuffer++;
  190. }
  191. else
  192. {
  193. while (*pBuffer != NULL && *pBuffer != ' ' && *pBuffer != ')' && *pBuffer != ',')
  194. strParam += *pBuffer++;
  195. }
  196. if (*pBuffer != NULL) // skip last char
  197. pBuffer++;
  198. if (strParam.GetLength() > 0)
  199. {
  200. if (strParam.GetAt(0) == '$') // ? variable name
  201. {
  202. float f = VariableValue(strParam);
  203. if (f != g_fDefault)
  204. strParam.Format("%f", f);
  205. }
  206. }
  207. return strParam;
  208. }
  209. brush_t* CopyBrush(brush_t* p)
  210. {
  211. brush_t* pCopy = Brush_Clone(p);
  212. //Brush_AddToList (pCopy, &active_brushes);
  213. //Entity_LinkBrush (world_entity, pCopy);
  214. Brush_Build(pCopy, false);
  215. return pCopy;
  216. }
  217. void CopySelected(char*& pBuffer)
  218. {
  219. // expects one param
  220. CString strParam = GetParam(pBuffer);
  221. int n = atoi(strParam);
  222. brush_t* pCopy = NULL;
  223. if (selected_brushes.next != &selected_brushes &&
  224. selected_brushes.next->next == &selected_brushes)
  225. pCopy = selected_brushes.next;
  226. if (pCopy)
  227. {
  228. if (n == 1)
  229. {
  230. //if (g_pHold1)
  231. //Brush_Free(g_pHold1);
  232. g_pHold1 = CopyBrush(pCopy);
  233. }
  234. else if (n == 2)
  235. {
  236. //if (g_pHold2)
  237. //Brush_Free(g_pHold2);
  238. g_pHold2 = CopyBrush(pCopy);
  239. }
  240. else
  241. {
  242. //if (g_pHold3)
  243. //Brush_Free(g_pHold3);
  244. g_pHold3 = CopyBrush(pCopy);
  245. }
  246. }
  247. }
  248. void MoveSelected(char*& pBuffer)
  249. {
  250. vec3_t v;
  251. CString strParam = GetParam(pBuffer);
  252. v[0] = atof(strParam);
  253. strParam = GetParam(pBuffer);
  254. v[1] = atof(strParam);
  255. strParam = GetParam(pBuffer);
  256. v[2] = atof(strParam);
  257. Select_Move(v, false);
  258. Sys_UpdateWindows(W_ALL);
  259. }
  260. void RotateSelected(char*& pBuffer)
  261. {
  262. vec3_t v;
  263. if (g_bRotateAroundSelection)
  264. {
  265. Select_GetTrueMid(v);
  266. VectorCopy(v, g_pParentWnd->ActiveXY()->RotateOrigin());
  267. }
  268. CString strParam = GetParam(pBuffer);
  269. v[0] = atof(strParam);
  270. strParam = GetParam(pBuffer);
  271. v[1] = atof(strParam);
  272. strParam = GetParam(pBuffer);
  273. v[2] = atof(strParam);
  274. for (int i = 0; i < 3; i++)
  275. if (v[i] != 0.0)
  276. Select_RotateAxis(i, v[i], false , true);
  277. Sys_UpdateWindows(W_ALL);
  278. }
  279. void MoveHold(char*& pBuffer)
  280. {
  281. CString strParam = GetParam(pBuffer);
  282. brush_t* pBrush = NULL;
  283. int nHold = atoi(strParam);
  284. if (nHold == 1)
  285. pBrush = g_pHold1;
  286. else if (nHold == 2)
  287. pBrush = g_pHold2;
  288. else
  289. pBrush = g_pHold3;
  290. if (pBrush)
  291. {
  292. vec3_t v;
  293. strParam = GetParam(pBuffer);
  294. v[0] = atof(strParam);
  295. strParam = GetParam(pBuffer);
  296. v[1] = atof(strParam);
  297. strParam = GetParam(pBuffer);
  298. v[2] = atof(strParam);
  299. Brush_Move (pBrush, v, false);
  300. }
  301. }
  302. void RotateHold(char*& pBuffer)
  303. {
  304. CString strParam = GetParam(pBuffer);
  305. brush_t* pBrush = NULL;
  306. int nHold = atoi(strParam);
  307. if (nHold == 1)
  308. pBrush = g_pHold1;
  309. else if (nHold == 2)
  310. pBrush = g_pHold2;
  311. else
  312. pBrush = g_pHold3;
  313. if (pBrush)
  314. {
  315. vec3_t v;
  316. 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]);
  325. }
  326. }
  327. void CopyToMap(char*& pBuffer)
  328. {
  329. CString strParam = GetParam(pBuffer);
  330. brush_t* pBrush = NULL;
  331. int nHold = atoi(strParam);
  332. if (nHold == 1)
  333. pBrush = g_pHold1;
  334. else if (nHold == 2)
  335. pBrush = g_pHold2;
  336. else
  337. pBrush = g_pHold3;
  338. if (pBrush)
  339. {
  340. Brush_AddToList(pBrush, &active_brushes);
  341. Entity_LinkBrush (world_entity, pBrush);
  342. Brush_Build(pBrush, false);
  343. Sys_UpdateWindows(W_ALL);
  344. }
  345. }
  346. void CopyAndSelect(char*& pBuffer)
  347. {
  348. CString strParam = GetParam(pBuffer);
  349. brush_t* pBrush = NULL;
  350. int nHold = atoi(strParam);
  351. if (nHold == 1)
  352. pBrush = g_pHold1;
  353. else if (nHold == 2)
  354. pBrush = g_pHold2;
  355. else
  356. pBrush = g_pHold3;
  357. if (pBrush)
  358. {
  359. Select_Deselect();
  360. Brush_AddToList(pBrush, &active_brushes);
  361. Entity_LinkBrush (world_entity, pBrush);
  362. Brush_Build(pBrush, false);
  363. Select_Brush(pBrush);
  364. Sys_UpdateWindows(W_ALL);
  365. }
  366. }
  367. void Input(char*& pBuffer)
  368. {
  369. CBSInput dlg;
  370. bool bGo = false;
  371. for (int n = 0; n < g_nVariableCount; n++)
  372. {
  373. if (g_Variables[n].m_strInput.GetLength() > 0)
  374. {
  375. bGo = true;
  376. if (n < 5)
  377. {
  378. switch (n)
  379. {
  380. case 0 : dlg.m_strField1 = g_Variables[n].m_strInput; break;
  381. case 1 : dlg.m_strField2 = g_Variables[n].m_strInput; break;
  382. case 2 : dlg.m_strField3 = g_Variables[n].m_strInput; break;
  383. case 3 : dlg.m_strField4 = g_Variables[n].m_strInput; break;
  384. case 4 : dlg.m_strField5 = g_Variables[n].m_strInput; break;
  385. }
  386. }
  387. }
  388. }
  389. if (bGo)
  390. {
  391. if (dlg.DoModal() == IDOK)
  392. {
  393. for (int n = 0; n < g_nVariableCount; n++)
  394. {
  395. if (g_Variables[n].m_strInput.GetLength() > 0)
  396. {
  397. if (n < 5)
  398. {
  399. switch (n)
  400. {
  401. case 0 : g_Variables[n].m_fValue = dlg.m_fField1; break;
  402. case 1 : g_Variables[n].m_fValue = dlg.m_fField2; break;
  403. case 2 : g_Variables[n].m_fValue = dlg.m_fField3; break;
  404. case 3 : g_Variables[n].m_fValue = dlg.m_fField4; break;
  405. case 4 : g_Variables[n].m_fValue = dlg.m_fField5; break;
  406. }
  407. }
  408. }
  409. }
  410. }
  411. else g_bKeepGoing = false;
  412. }
  413. }
  414. bool g_bWaiting;
  415. void _3DPointDone(bool b, int n)
  416. {
  417. g_bWaiting = false;
  418. }
  419. void _3DPointInput(char*& pBuffer)
  420. {
  421. CString strParam = GetParam(pBuffer);
  422. CString strParam2 = GetParam(pBuffer);
  423. ShowInfoDialog(strParam2);
  424. AddVectorVariable(strParam, strParam2);
  425. g_bWaiting = true;
  426. AcquirePath(2, &_3DPointDone);
  427. while (g_bWaiting)
  428. {
  429. MSG msg;
  430. if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ))
  431. {
  432. TranslateMessage(&msg);
  433. DispatchMessage(&msg);
  434. }
  435. }
  436. HideInfoDialog();
  437. SetVectorVariableValue(strParam, g_PathPoints[0]);
  438. }
  439. void SetRotateOrigin(char*& pBuffer)
  440. {
  441. vec3_t v;
  442. CString strParam = GetParam(pBuffer);
  443. VectorVariableValue(strParam, v);
  444. VectorCopy(v, g_pParentWnd->ActiveXY()->RotateOrigin());
  445. g_bRotateAroundSelection = false;
  446. }
  447. void InputVar(char*& pBuffer)
  448. {
  449. CString strParam = GetParam(pBuffer);
  450. CString strParam2 = GetParam(pBuffer);
  451. AddVariable(strParam, 0.0, strParam2);
  452. }
  453. void LoopCount(char*& pBuffer)
  454. {
  455. CString strParam = GetParam(pBuffer);
  456. g_nLoopCounter = atoi(strParam);
  457. if (g_nLoopCounter == 0)
  458. g_nLoopCounter = VariableValue(strParam);
  459. if (g_nLoopCounter > 0)
  460. g_pLooper = pBuffer;
  461. }
  462. void LoopRun(char*& pBuffer)
  463. {
  464. if (g_bStartLoop == true)
  465. {
  466. g_nLoopCounter--;
  467. if (g_nLoopCounter == 0)
  468. {
  469. g_bStartLoop = false;
  470. GetParam(pBuffer);
  471. }
  472. else
  473. pBuffer = g_pLooper;
  474. }
  475. else
  476. {
  477. if (g_pLooper && g_nLoopCounter > 0)
  478. {
  479. g_bStartLoop = true;
  480. pBuffer = g_pLooper;
  481. }
  482. else
  483. {
  484. GetParam(pBuffer);
  485. }
  486. }
  487. }
  488. void ConfirmMessage(char*& pBuffer)
  489. {
  490. CString strParam = GetParam(pBuffer);
  491. if (g_pParentWnd->MessageBox(strParam, "Script Info", MB_OKCANCEL) == IDCANCEL)
  492. g_bKeepGoing = false;
  493. }
  494. void Spherize(char*& pBuffer)
  495. {
  496. g_bScreenUpdates = false;
  497. for (int n = 0; n < 120; n += 36)
  498. {
  499. for (int i = 0; i < 360; i += 36)
  500. {
  501. Select_RotateAxis(0, i, false , true);
  502. CSG_Subtract();
  503. }
  504. Select_RotateAxis(2, n, false , true);
  505. }
  506. g_bScreenUpdates = true;
  507. }
  508. void RunIt(char*& pBuffer);
  509. SBrushScript g_ScriptCmds[] =
  510. {
  511. {"_CopySelected", &CopySelected},
  512. {"_MoveSelected", &MoveSelected},
  513. {"_RotateSelected", &RotateSelected},
  514. {"_MoveHold", &MoveHold},
  515. {"_RotateHold", &RotateHold},
  516. {"_CopyToMap", &CopyToMap},
  517. {"_CopyAndSelect", &CopyAndSelect},
  518. {"_Input", &Input},
  519. {"_3DPointInput", &_3DPointInput},
  520. {"_SetRotateOrigin", &SetRotateOrigin},
  521. {"_InputVar", &InputVar},
  522. {"_LoopCount", &LoopCount},
  523. {"_LoopRun", &LoopRun},
  524. {"_ConfirmMessage", &ConfirmMessage},
  525. {"_Spherize", &Spherize},
  526. {"_RunScript", RunIt}
  527. };
  528. const int g_nScriptCmdCount = sizeof(g_ScriptCmds) / sizeof(SBrushScript);
  529. void RunScript(char* pBuffer)
  530. {
  531. g_pHold1 = NULL;
  532. g_pHold2 = NULL;
  533. g_pHold3 = NULL;
  534. while (g_bKeepGoing && pBuffer && *pBuffer)
  535. {
  536. while (*pBuffer != NULL && *pBuffer != '_')
  537. pBuffer++;
  538. char* pTemp = pBuffer;
  539. int nLen = 0;
  540. while (*pTemp != NULL && *pTemp != '(')
  541. {
  542. pTemp++;
  543. nLen++;
  544. }
  545. if (*pBuffer != NULL)
  546. {
  547. bool bFound = false;
  548. for (int i = 0; i < g_nScriptCmdCount; i++)
  549. {
  550. //if (strnicmp(g_ScriptCmds[i].m_pName, pBuffer, strlen(g_ScriptCmds[i].m_pName)) == 0)
  551. if (strnicmp(g_ScriptCmds[i].m_pName, pBuffer, nLen) == 0)
  552. {
  553. pBuffer += strlen(g_ScriptCmds[i].m_pName);
  554. g_ScriptCmds[i].m_pProc(pBuffer);
  555. if (g_bStartLoop)
  556. {
  557. }
  558. bFound = true;
  559. break;
  560. }
  561. }
  562. if (!bFound)
  563. pBuffer++;
  564. }
  565. }
  566. }
  567. void RunScriptByName(char* pBuffer, bool bInit)
  568. {
  569. if (bInit)
  570. InitForScriptRun();
  571. char* pScript = new char[4096];
  572. CString strINI = g_strAppPath;
  573. strINI += "\\scripts.ini";
  574. GetPrivateProfileSection(pBuffer, pScript, 16384, strINI);
  575. CString strScript;
  576. char* pWorkScript = pScript;
  577. while (*pWorkScript != NULL)
  578. {
  579. strScript += pWorkScript;
  580. pWorkScript += strlen(pWorkScript) + 1;
  581. }
  582. RunScript(strScript.GetBuffer(0));
  583. }
  584. void RunIt(char*& pBuffer)
  585. {
  586. brush_t* p1 = g_pHold1;
  587. brush_t* p2 = g_pHold2;
  588. brush_t* p3 = g_pHold3;
  589. CString strParam = GetParam(pBuffer);
  590. RunScriptByName(strParam.GetBuffer(0), false);
  591. g_pHold3 = p3;
  592. g_pHold2 = p2;
  593. g_pHold1 = p1;
  594. }