https://github.com/id-Software/Quake-III-Arena
Tip revision: dbe4ddb10315479fc00086f08e25d968b4b43c49 authored by Travis Bradshaw on 31 January 2012, 19:41:34 UTC
The Quake III Arena sources as originally released under the GPL license on August 20, 2005.
The Quake III Arena sources as originally released under the GPL license on August 20, 2005.
Tip revision: dbe4ddb
BrushScript.cpp
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// BrushScript stuff
//
#include "stdafx.h"
#include "qe3.h"
#include "BSInput.h"
#include "DialogInfo.h"
//
struct SVariableDef
{
CString m_strName;
CString m_strInput;
float m_fValue;
};
struct SVecVariableDef
{
CString m_strName;
CString m_strInput;
vec3_t m_vValue;
};
const int MAX_VARIABLES = 64;
brush_t* g_pHold1 = NULL;
brush_t* g_pHold2 = NULL;
brush_t* g_pHold3 = NULL;
bool g_bRotateAroundSelection;
int g_nVariableCount;
int g_nVecVariableCount;
int g_nLoopCounter;
float g_fDefault = 9999.9;
vec3_t g_vDefault;
bool g_bStartLoop;
char* g_pLooper;
bool g_bKeepGoing;
SVariableDef g_Variables[MAX_VARIABLES];
SVecVariableDef g_VecVariables[MAX_VARIABLES];
void InitForScriptRun()
{
g_pHold1 = NULL;
g_pHold2 = NULL;
g_pHold3 = NULL;
g_bRotateAroundSelection = true;
g_nVariableCount = 0;
g_nVecVariableCount = 0;
g_nLoopCounter = 0;
g_bStartLoop = false;
g_pLooper = NULL;
g_bKeepGoing = true;
}
void AddVariable(const char* pName, float fValue, const char* pInput = NULL)
{
if (g_nVariableCount < MAX_VARIABLES)
{
g_Variables[g_nVariableCount].m_strName = pName;
g_Variables[g_nVariableCount].m_strName.MakeLower();
g_Variables[g_nVariableCount].m_fValue = fValue;
if (pInput)
g_Variables[g_nVariableCount].m_strInput = pInput;
g_nVariableCount++;
}
else
g_pParentWnd->MessageBox("Maximum script variable limit reached!");
}
float VariableValue(const char* pName)
{
CString strName = pName;
strName.MakeLower();
for (int n = 0; n < g_nVariableCount; n++)
{
if (strName == g_Variables[n].m_strName)
return g_Variables[n].m_fValue;
}
//strName.Format("Reference to non-existant varirable %s", pName);
//g_pParentWnd->MessageBox(strName);
return g_fDefault;
}
void SetVariableValue(const char* pName, float fValue)
{
CString strName = pName;
strName.MakeLower();
for (int n = 0; n < g_nVariableCount; n++)
{
if (strName == g_Variables[n].m_strName)
g_Variables[n].m_fValue = fValue;
}
}
void AddVectorVariable(const char* pName, const char* pInput = NULL)
{
if (g_nVecVariableCount < MAX_VARIABLES)
{
g_VecVariables[g_nVecVariableCount].m_strName = pName;
g_VecVariables[g_nVecVariableCount].m_strName.MakeLower();
if (pInput)
g_VecVariables[g_nVariableCount].m_strInput = pInput;
g_nVecVariableCount++;
}
else
g_pParentWnd->MessageBox("Maximum script variable limit reached!");
}
void VectorVariableValue(const char* pName, vec3_t& v)
{
CString strName = pName;
strName.MakeLower();
for (int n = 0; n < g_nVecVariableCount; n++)
{
if (strName == g_VecVariables[n].m_strName)
{
VectorCopy(g_VecVariables[n].m_vValue, v);
return;
}
}
strName.Format("Reference to non-existant variable %s", pName);
g_pParentWnd->MessageBox(strName);
}
void SetVectorVariableValue(const char* pName, vec3_t v)
{
CString strName = pName;
strName.MakeLower();
for (int n = 0; n < g_nVecVariableCount; n++)
{
if (strName == g_VecVariables[n].m_strName)
VectorCopy(v, g_VecVariables[n].m_vValue);
}
}
// commands
//
// _CopySelected(nHoldPos)
// copies selected brush to hold spot 1, 2 or 3
//
// _MoveSelected(x, y, z)
// moves selected brush by coords provided
//
// _RotateSelected(x, y, z)
// rotates selected brush by coords provided
//
// _MoveHold(nHoldPos, x, y, z)
// moves brush in hold pos by coords provided
//
// _RotateHold(nHoldPos, x, y, z)
// rotates brush in hold pos by coords provided
//
// _CopyToMap(nHoldPos)
// copies hold brush to map
//
// _CopyAndSelect(nHoldPos)
// copies hold brush to map and selects it
//
// _Input(VarName1, ... VarNamennn)
// inputs a list of values from the user
//
typedef void (PFNScript)(char*&);
struct SBrushScript
{
const char* m_pName;
PFNScript* m_pProc;
};
const char* GetParam(char*& pBuffer)
{
static CString strParam;
bool bStringMode = false;
while (*pBuffer != NULL && isspace(*pBuffer)) // skip and whitespace
pBuffer++;
if (*pBuffer == '(') // if it's an opening paren, skip it
pBuffer++;
if (*pBuffer == '\"') // string ?
{
pBuffer++;
bStringMode = true;
}
strParam = "";
if (bStringMode)
{
while (*pBuffer != NULL && *pBuffer != '\"')
strParam += *pBuffer++;
}
else
{
while (*pBuffer != NULL && *pBuffer != ' ' && *pBuffer != ')' && *pBuffer != ',')
strParam += *pBuffer++;
}
if (*pBuffer != NULL) // skip last char
pBuffer++;
if (strParam.GetLength() > 0)
{
if (strParam.GetAt(0) == '$') // ? variable name
{
float f = VariableValue(strParam);
if (f != g_fDefault)
strParam.Format("%f", f);
}
}
return strParam;
}
brush_t* CopyBrush(brush_t* p)
{
brush_t* pCopy = Brush_Clone(p);
//Brush_AddToList (pCopy, &active_brushes);
//Entity_LinkBrush (world_entity, pCopy);
Brush_Build(pCopy, false);
return pCopy;
}
void CopySelected(char*& pBuffer)
{
// expects one param
CString strParam = GetParam(pBuffer);
int n = atoi(strParam);
brush_t* pCopy = NULL;
if (selected_brushes.next != &selected_brushes &&
selected_brushes.next->next == &selected_brushes)
pCopy = selected_brushes.next;
if (pCopy)
{
if (n == 1)
{
//if (g_pHold1)
//Brush_Free(g_pHold1);
g_pHold1 = CopyBrush(pCopy);
}
else if (n == 2)
{
//if (g_pHold2)
//Brush_Free(g_pHold2);
g_pHold2 = CopyBrush(pCopy);
}
else
{
//if (g_pHold3)
//Brush_Free(g_pHold3);
g_pHold3 = CopyBrush(pCopy);
}
}
}
void MoveSelected(char*& pBuffer)
{
vec3_t v;
CString strParam = GetParam(pBuffer);
v[0] = atof(strParam);
strParam = GetParam(pBuffer);
v[1] = atof(strParam);
strParam = GetParam(pBuffer);
v[2] = atof(strParam);
Select_Move(v, false);
Sys_UpdateWindows(W_ALL);
}
void RotateSelected(char*& pBuffer)
{
vec3_t v;
if (g_bRotateAroundSelection)
{
Select_GetTrueMid(v);
VectorCopy(v, g_pParentWnd->ActiveXY()->RotateOrigin());
}
CString strParam = GetParam(pBuffer);
v[0] = atof(strParam);
strParam = GetParam(pBuffer);
v[1] = atof(strParam);
strParam = GetParam(pBuffer);
v[2] = atof(strParam);
for (int i = 0; i < 3; i++)
if (v[i] != 0.0)
Select_RotateAxis(i, v[i], false , true);
Sys_UpdateWindows(W_ALL);
}
void MoveHold(char*& pBuffer)
{
CString strParam = GetParam(pBuffer);
brush_t* pBrush = NULL;
int nHold = atoi(strParam);
if (nHold == 1)
pBrush = g_pHold1;
else if (nHold == 2)
pBrush = g_pHold2;
else
pBrush = g_pHold3;
if (pBrush)
{
vec3_t v;
strParam = GetParam(pBuffer);
v[0] = atof(strParam);
strParam = GetParam(pBuffer);
v[1] = atof(strParam);
strParam = GetParam(pBuffer);
v[2] = atof(strParam);
Brush_Move (pBrush, v, false);
}
}
void RotateHold(char*& pBuffer)
{
CString strParam = GetParam(pBuffer);
brush_t* pBrush = NULL;
int nHold = atoi(strParam);
if (nHold == 1)
pBrush = g_pHold1;
else if (nHold == 2)
pBrush = g_pHold2;
else
pBrush = g_pHold3;
if (pBrush)
{
vec3_t v;
strParam = GetParam(pBuffer);
v[0] = atof(strParam);
strParam = GetParam(pBuffer);
v[1] = atof(strParam);
strParam = GetParam(pBuffer);
v[2] = atof(strParam);
for (int i = 0; i < 3; i++)
if (v[i] != 0.0)
Select_RotateAxis(i, v[i]);
}
}
void CopyToMap(char*& pBuffer)
{
CString strParam = GetParam(pBuffer);
brush_t* pBrush = NULL;
int nHold = atoi(strParam);
if (nHold == 1)
pBrush = g_pHold1;
else if (nHold == 2)
pBrush = g_pHold2;
else
pBrush = g_pHold3;
if (pBrush)
{
Brush_AddToList(pBrush, &active_brushes);
Entity_LinkBrush (world_entity, pBrush);
Brush_Build(pBrush, false);
Sys_UpdateWindows(W_ALL);
}
}
void CopyAndSelect(char*& pBuffer)
{
CString strParam = GetParam(pBuffer);
brush_t* pBrush = NULL;
int nHold = atoi(strParam);
if (nHold == 1)
pBrush = g_pHold1;
else if (nHold == 2)
pBrush = g_pHold2;
else
pBrush = g_pHold3;
if (pBrush)
{
Select_Deselect();
Brush_AddToList(pBrush, &active_brushes);
Entity_LinkBrush (world_entity, pBrush);
Brush_Build(pBrush, false);
Select_Brush(pBrush);
Sys_UpdateWindows(W_ALL);
}
}
void Input(char*& pBuffer)
{
CBSInput dlg;
bool bGo = false;
for (int n = 0; n < g_nVariableCount; n++)
{
if (g_Variables[n].m_strInput.GetLength() > 0)
{
bGo = true;
if (n < 5)
{
switch (n)
{
case 0 : dlg.m_strField1 = g_Variables[n].m_strInput; break;
case 1 : dlg.m_strField2 = g_Variables[n].m_strInput; break;
case 2 : dlg.m_strField3 = g_Variables[n].m_strInput; break;
case 3 : dlg.m_strField4 = g_Variables[n].m_strInput; break;
case 4 : dlg.m_strField5 = g_Variables[n].m_strInput; break;
}
}
}
}
if (bGo)
{
if (dlg.DoModal() == IDOK)
{
for (int n = 0; n < g_nVariableCount; n++)
{
if (g_Variables[n].m_strInput.GetLength() > 0)
{
if (n < 5)
{
switch (n)
{
case 0 : g_Variables[n].m_fValue = dlg.m_fField1; break;
case 1 : g_Variables[n].m_fValue = dlg.m_fField2; break;
case 2 : g_Variables[n].m_fValue = dlg.m_fField3; break;
case 3 : g_Variables[n].m_fValue = dlg.m_fField4; break;
case 4 : g_Variables[n].m_fValue = dlg.m_fField5; break;
}
}
}
}
}
else g_bKeepGoing = false;
}
}
bool g_bWaiting;
void _3DPointDone(bool b, int n)
{
g_bWaiting = false;
}
void _3DPointInput(char*& pBuffer)
{
CString strParam = GetParam(pBuffer);
CString strParam2 = GetParam(pBuffer);
ShowInfoDialog(strParam2);
AddVectorVariable(strParam, strParam2);
g_bWaiting = true;
AcquirePath(2, &_3DPointDone);
while (g_bWaiting)
{
MSG msg;
if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
HideInfoDialog();
SetVectorVariableValue(strParam, g_PathPoints[0]);
}
void SetRotateOrigin(char*& pBuffer)
{
vec3_t v;
CString strParam = GetParam(pBuffer);
VectorVariableValue(strParam, v);
VectorCopy(v, g_pParentWnd->ActiveXY()->RotateOrigin());
g_bRotateAroundSelection = false;
}
void InputVar(char*& pBuffer)
{
CString strParam = GetParam(pBuffer);
CString strParam2 = GetParam(pBuffer);
AddVariable(strParam, 0.0, strParam2);
}
void LoopCount(char*& pBuffer)
{
CString strParam = GetParam(pBuffer);
g_nLoopCounter = atoi(strParam);
if (g_nLoopCounter == 0)
g_nLoopCounter = VariableValue(strParam);
if (g_nLoopCounter > 0)
g_pLooper = pBuffer;
}
void LoopRun(char*& pBuffer)
{
if (g_bStartLoop == true)
{
g_nLoopCounter--;
if (g_nLoopCounter == 0)
{
g_bStartLoop = false;
GetParam(pBuffer);
}
else
pBuffer = g_pLooper;
}
else
{
if (g_pLooper && g_nLoopCounter > 0)
{
g_bStartLoop = true;
pBuffer = g_pLooper;
}
else
{
GetParam(pBuffer);
}
}
}
void ConfirmMessage(char*& pBuffer)
{
CString strParam = GetParam(pBuffer);
if (g_pParentWnd->MessageBox(strParam, "Script Info", MB_OKCANCEL) == IDCANCEL)
g_bKeepGoing = false;
}
void Spherize(char*& pBuffer)
{
g_bScreenUpdates = false;
for (int n = 0; n < 120; n += 36)
{
for (int i = 0; i < 360; i += 36)
{
Select_RotateAxis(0, i, false , true);
CSG_Subtract();
}
Select_RotateAxis(2, n, false , true);
}
g_bScreenUpdates = true;
}
void RunIt(char*& pBuffer);
SBrushScript g_ScriptCmds[] =
{
{"_CopySelected", &CopySelected},
{"_MoveSelected", &MoveSelected},
{"_RotateSelected", &RotateSelected},
{"_MoveHold", &MoveHold},
{"_RotateHold", &RotateHold},
{"_CopyToMap", &CopyToMap},
{"_CopyAndSelect", &CopyAndSelect},
{"_Input", &Input},
{"_3DPointInput", &_3DPointInput},
{"_SetRotateOrigin", &SetRotateOrigin},
{"_InputVar", &InputVar},
{"_LoopCount", &LoopCount},
{"_LoopRun", &LoopRun},
{"_ConfirmMessage", &ConfirmMessage},
{"_Spherize", &Spherize},
{"_RunScript", RunIt}
};
const int g_nScriptCmdCount = sizeof(g_ScriptCmds) / sizeof(SBrushScript);
void RunScript(char* pBuffer)
{
g_pHold1 = NULL;
g_pHold2 = NULL;
g_pHold3 = NULL;
while (g_bKeepGoing && pBuffer && *pBuffer)
{
while (*pBuffer != NULL && *pBuffer != '_')
pBuffer++;
char* pTemp = pBuffer;
int nLen = 0;
while (*pTemp != NULL && *pTemp != '(')
{
pTemp++;
nLen++;
}
if (*pBuffer != NULL)
{
bool bFound = false;
for (int i = 0; i < g_nScriptCmdCount; i++)
{
//if (strnicmp(g_ScriptCmds[i].m_pName, pBuffer, strlen(g_ScriptCmds[i].m_pName)) == 0)
if (strnicmp(g_ScriptCmds[i].m_pName, pBuffer, nLen) == 0)
{
pBuffer += strlen(g_ScriptCmds[i].m_pName);
g_ScriptCmds[i].m_pProc(pBuffer);
if (g_bStartLoop)
{
}
bFound = true;
break;
}
}
if (!bFound)
pBuffer++;
}
}
}
void RunScriptByName(char* pBuffer, bool bInit)
{
if (bInit)
InitForScriptRun();
char* pScript = new char[4096];
CString strINI = g_strAppPath;
strINI += "\\scripts.ini";
GetPrivateProfileSection(pBuffer, pScript, 16384, strINI);
CString strScript;
char* pWorkScript = pScript;
while (*pWorkScript != NULL)
{
strScript += pWorkScript;
pWorkScript += strlen(pWorkScript) + 1;
}
RunScript(strScript.GetBuffer(0));
}
void RunIt(char*& pBuffer)
{
brush_t* p1 = g_pHold1;
brush_t* p2 = g_pHold2;
brush_t* p3 = g_pHold3;
CString strParam = GetParam(pBuffer);
RunScriptByName(strParam.GetBuffer(0), false);
g_pHold3 = p3;
g_pHold2 = p2;
g_pHold1 = p1;
}