35. 脚本系统

script.spt

# This is an example of a comment.

teapotColor
0.0 0.0 1.0
cameraPosition
0.0 0.0 -5.0

# These are not used but are here to test loading strings and ints.

totalTeapots
1
description This just a teapot
in a 3D scene!

  

PropertyScript.h

#ifndef _UGP_PROPERTY_SCRIPT_H_
#define _UGP_PROPERTY_SCRIPT_H_



enum enVarType { NULL_VAR = 0, INT_VAR, FLOAT_VAR,
STRING_VAR, VECTOR_VAR };


struct stVector
{
stVector() : x(
0), y(0), z(0) {}
float x, y, z;
};

// 用于描述单个属性的类
class CVariable
{
public:
CVariable() : type(
0), floatVal(0), intVal(0), stringVal(0)
{
name[
0] = '\0';
vecVal.x
= vecVal.y = vecVal.z = 0;
}
~CVariable()
{
if(stringVal)
delete[] stringVal;
stringVal
= 0;
}

// @t 属性类型
// @n 属性名字
// @data 属性值
void SetData(int t, char* n, void *data);
// @t 属性类型
// @data 属性值
void SetData(int t, void *data);

char *GetName() { return name; }
int GetType() { return type; }
int GetDataAsInt() { return intVal; }
float GetDataAsFloat() { return floatVal; }
char *GetDataAsString() { return stringVal; }
stVector GetDataAsVector() {
return vecVal; }

private:
char name[128]; // 属性名字
int type; // 属性类型

// 属性值
int intVal;
float floatVal;
char *stringVal;
stVector vecVal;
};


class CPropertyScript
{
public:
CPropertyScript();
~CPropertyScript();

// 增加CVariable类链表数组(增加其长度)
bool IncreaseVariableList();

bool LoadScriptFile(char *filename);

private:
// 获取当前所读取的一行中某个单独文本,并保存在第2个参数中
// @tempLine 当前行的所有字符
// @varName 保存该行中某个单独的文本
void ParseNext(char *tempLine, char *varName);

public:
// 手动增加一个属性到属性列表中
// @name 属性名字
// @t 属性类型
// @val 属性值
bool AddVariable(char *name, int t, void *val);
// 更改列表中的某个属性
bool SetVariable(char *name, int t, void *val);
int GetVariableAsInt(char *name);
float GetVariableAsFloat(char *name);
char *GetVariableAsString(char *name);
stVector GetVariableAsVector(
char *name);

void Shutdown();

private:
CVariable
*variableList; // 属性列表
int m_totalVars; // 属性个数
int currentLineChar; // 正在读取的当前字符的个数的计数器
};

#endif

  

PropertyScript.cpp

#include"PropertyScript.h"
#include
<fstream>

using std::ifstream;


// 全局函数
// 确定要处理的属性类型
int DetermineType(int startIndex, char *buffer)
{
int numComponents = 0;
int type = NULL_VAR;
bool decimalFound = false; // 属性值中是否有点
bool charFound = false;
int index = startIndex;

// Loop through the string and get information about it.
while(index < (int)strlen(buffer))
{
// Since there are no new lines we auto add this if we
// get inside this loop.
// 如果全部是数字不统计个数,只将numComponents变成1
if(numComponents == 0)
numComponents
++;

if(buffer[index] == ' ')
numComponents
++;

if(buffer[index] == '.')
decimalFound
= true;

if((buffer[index] >= 'a' && buffer[index] <= 'z') ||
(buffer[index]
>= 'A' && buffer[index] <= 'Z') || buffer[index] == '_')
charFound
= true;

index
++;
}

// If only one variable is show after the name then it can
// be any type other than vector since vector should have 3.
switch(numComponents)
{
case 1:
// If there are any characters then it is a string.
if(charFound)
type
= STRING_VAR;
else
type
= INT_VAR;

// If there is a decimal and no chars then its a float.
if(decimalFound == true && charFound == false)
type
= FLOAT_VAR;
break;

case 3:
// Since vectors are just floats, if we see any characters
// in the group then it must be a string.
if(charFound)
type
= STRING_VAR;
else type = VECTOR_VAR;
break;

default:
// If there are more than 1 word after the name
// then it must be a string since strings can have spaces.
if(numComponents > 0)
type
= STRING_VAR;
break;
}

return type;
}


void CVariable::SetData(int t, char *n, void *data)
{
if(!name) return;

// Set this variables name then set the type and data.
memcpy(name, n, strlen(n));
name[strlen(n)]
= '\0';
SetData(t, data);
}


void CVariable::SetData(int t, void *data)
{
stVector
*vec = NULL;
int len = 0;

// Depending on the type will depend where the
// value is stored.
switch(t)
{
case INT_VAR:
intVal
= (int)data;
break;

case FLOAT_VAR:
floatVal
= *(float*)data;
break;

case STRING_VAR:
len
= strlen((char*)data);
stringVal
= new char[len + 1];
memcpy(stringVal, (
char*)data, len);
stringVal[len]
= '\0';
break;

case VECTOR_VAR:
vec
= (stVector*)data;
vecVal.x
= vec->x;
vecVal.y
= vec->y;
vecVal.z
= vec->z;
break;

default:
// If we get here then it is a NULL variable.
return;
break;
};

type
= t;
}


CPropertyScript::CPropertyScript() : variableList(NULL),
m_totalVars(
0), currentLineChar(0)
{

}


CPropertyScript::
~CPropertyScript()
{
// Release all resources.
Shutdown();
}


bool CPropertyScript::IncreaseVariableList()
{
if(!variableList)
{
variableList
= new CVariable[1];
if(!variableList)
return false;
}
else
{
CVariable
*temp;
temp
= new CVariable[m_totalVars + 1];
if(!temp)
return false;

memcpy(temp, variableList,
sizeof(CVariable) * m_totalVars);

delete[] variableList;
variableList
= temp;
}

return true;
}


bool CPropertyScript::LoadScriptFile(char *filename)
{
int totalScriptLines = 0;
ifstream input, input2;
char tempLine[256];
char varName[128];
char param[3072];
int type = 0;

// Open the file to get the number of lines from it.
input.open(filename);
if(!input.is_open())
return false;

// Clear all previous data.
Shutdown();

// Open and get number of lines.
while(!input.eof())
{
input.getline(tempLine,
256, '\n');
totalScriptLines
++;
}

input.close();

// Open it this time to get the variables out.
input2.open(filename);
if(!input2.is_open())
return false;

// Loop through each line of the script and get all variables.
for(int i = 0; i < totalScriptLines; i++)
{
// Reset line counter to the beginning.
currentLineChar = 0;

// Read the entire line from the file.
input2.getline(tempLine, 256, '\n');
tempLine[strlen(tempLine)]
= '\0';

// 如果不是注释则解析这一行
if(tempLine[0] != '#')
{
// Read the name then determine the type.
// 先将该行总的属性名字读到varName中去,同时移动currentLineChar指针
ParseNext(tempLine, varName);
// 利用改变后的currentLineChar指针,此时它已经指向了属性值的起始位置,
// 判断属性值得类型
type = DetermineType(currentLineChar, tempLine);

// Depending on the type will depend on how many
// words we need to read after the name. For
// ints we need 1, vectors 3, strings 1, etc.
// Once we get the data we convert it to the
// type we need and set it to the variable.
if(type == INT_VAR)
{
if(IncreaseVariableList())
{
// 由于currentLineCha已经指向了属性值的起始位置,此时提取该行的属性值
ParseNext(tempLine, param);
variableList[m_totalVars].SetData(INT_VAR, varName, (
void*)atoi(param));
m_totalVars
++;
}
}
else if(type == FLOAT_VAR)
{
if(IncreaseVariableList())
{
float fVal = 0;
ParseNext(tempLine, param);
fVal
= (float)atof(param);
variableList[m_totalVars].SetData(FLOAT_VAR, varName,
&fVal);
m_totalVars
++;
}
}
else if(type == STRING_VAR)
{
if(IncreaseVariableList())
{
ParseNext(tempLine, param);
variableList[m_totalVars].SetData(STRING_VAR, varName, (
void*)param);
m_totalVars
++;
}
}
else if(type == VECTOR_VAR)
{
if(IncreaseVariableList())
{
stVector vecVal;

// 需要提取3个属性值,每个之间空格隔开
ParseNext(tempLine, param);
vecVal.x
= (float)atof(param);
ParseNext(tempLine, param);
vecVal.y
= (float)atof(param);
ParseNext(tempLine, param);
vecVal.z
= (float)atof(param);

variableList[m_totalVars].SetData(VECTOR_VAR, varName,
&vecVal);
m_totalVars
++;
}
}
}
}

// Close file, return true.
input2.close();
return true;
}


void CPropertyScript::ParseNext(char *tempLine, char *outData)
{
int commandSize = 0;
int paramSize = 0;

// Error checking.
if(!tempLine || !outData) return;

// Init string.
outData[0] = '\0';

// Loop through every character until you find a space or newline.
while(currentLineChar < (int)strlen(tempLine))
{
if(tempLine[currentLineChar] == ' ' || tempLine[currentLineChar] == '\n')
break;

// Save the text in the array.
outData[paramSize] = tempLine[currentLineChar];
paramSize
++;
currentLineChar
++;
}

// End the out string and move the line char past the next space.
// If there is no space then the system will move to the next line.
outData[paramSize] = '\0';
currentLineChar
++;
}


bool CPropertyScript::AddVariable(char *name, int t, void *val)
{
// We can use this to see if the variable exist already.
if(!SetVariable(name, t, val))
{
if(!IncreaseVariableList())
return false;

// Set the variables data then add to the counter.
variableList[m_totalVars].SetData(t, name, val);
m_totalVars
++;
}

return true;
}


bool CPropertyScript::SetVariable(char *name, int t, void *val)
{
// Loop through the list and compare names.
// If we find the variable set its data.
for(int i = 0; i < m_totalVars; i++)
{
if(stricmp(variableList[i].GetName(), name) == 0)
{
variableList[i].SetData(t, val);
return true;
}
}

return false;
}


int CPropertyScript::GetVariableAsInt(char *name)
{
// Loop through the list and compare names.
// If we find the variable return its data.
for(int i = 0; i < m_totalVars; i++)
{
if(stricmp(variableList[i].GetName(), name) == 0)
return variableList[i].GetDataAsInt();
}

return 0;
}


float CPropertyScript::GetVariableAsFloat(char *name)
{
// Loop through the list and compare names.
// If we find the variable return its data.
for(int i = 0; i < m_totalVars; i++)
{
if(stricmp(variableList[i].GetName(), name) == 0)
return variableList[i].GetDataAsFloat();
}

return 0;
}


char *CPropertyScript::GetVariableAsString(char *name)
{
// Loop through the list and compare names.
// If we find the variable return its data.
for(int i = 0; i < m_totalVars; i++)
{
if(stricmp(variableList[i].GetName(), name) == 0)
return variableList[i].GetDataAsString();
}

return NULL;
}


stVector CPropertyScript::GetVariableAsVector(
char *name)
{
stVector
null;

// Loop through the list and compare names.
// If we find the variable return its data.
for(int i = 0; i < m_totalVars; i++)
{
if(stricmp(variableList[i].GetName(), name) == 0)
return variableList[i].GetDataAsVector();
}

return null;
}


void CPropertyScript::Shutdown()
{
// Delete list.
if(variableList)
delete[] variableList;
variableList
= NULL;
}

  

main.cpp

#include<d3d9.h>
#include
<d3dx9.h>
#include
"PropertyScript.h"

#define WINDOW_CLASS "UGPDX"
#define WINDOW_NAME "Property Scripting"
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

// Function Prototypes...
bool InitializeD3D(HWND hWnd, bool fullscreen);
bool InitializeObjects();
void RenderScene();
void Shutdown();


// Direct3D object and device.
LPDIRECT3D9 g_D3D = NULL;
LPDIRECT3DDEVICE9 g_D3DDevice
= NULL;

// Matrices.
D3DXMATRIX g_projection;
D3DXMATRIX g_ViewMatrix;
D3DXMATRIX g_WorldMatrix;

// Mesh objects
LPD3DXMESH g_teapot = NULL;
D3DMATERIAL9 g_material;
// 材质

// Scene light source.
D3DLIGHT9 g_light; // 灯光


LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(
0);
return 0;
break;

case WM_KEYUP:
if(wp == VK_ESCAPE) PostQuitMessage(0);
break;
}

return DefWindowProc(hWnd, msg, wp, lp);
}


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE ph, LPSTR cmd, int s)
{
// Register the window class
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
WINDOW_CLASS, NULL };
RegisterClassEx(
&wc);

// Create the application's window
HWND hWnd = CreateWindow(WINDOW_CLASS, WINDOW_NAME,
WS_OVERLAPPEDWINDOW,
100, 100, WINDOW_WIDTH, WINDOW_HEIGHT,
GetDesktopWindow(), NULL, wc.hInstance, NULL);

// Initialize Direct3D
if(InitializeD3D(hWnd, false))
{
// Show the window
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);

// Enter the message loop
MSG msg;
ZeroMemory(
&msg, sizeof(msg));

while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(
&msg);
DispatchMessage(
&msg);
}
else
RenderScene();
}
}

// Release any and all resources.
Shutdown();

// Unregister our window.
UnregisterClass(WINDOW_CLASS, wc.hInstance);
return 0;
}


bool InitializeD3D(HWND hWnd, bool fullscreen)
{
D3DDISPLAYMODE displayMode;

// Create the D3D object.
g_D3D = Direct3DCreate9(D3D_SDK_VERSION);
if(g_D3D == NULL) return false;

// Get the desktop display mode.
if(FAILED(g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,
&displayMode))) return false;

// Set up the structure used to create the D3DDevice
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(
&d3dpp, sizeof(d3dpp));

if(fullscreen)
{
d3dpp.Windowed
= FALSE;
d3dpp.BackBufferWidth
= WINDOW_WIDTH;
d3dpp.BackBufferHeight
= WINDOW_HEIGHT;
}
else
d3dpp.Windowed
= TRUE;
d3dpp.SwapEffect
= D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat
= displayMode.Format;

// Create the D3DDevice
if(FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&g_D3DDevice))) return false;

// Set the projection matrix.
D3DXMatrixPerspectiveFovLH(&g_projection, 45.0f,
WINDOW_WIDTH
/WINDOW_HEIGHT, 0.1f, 1000.0f);
g_D3DDevice
->SetTransform(D3DTS_PROJECTION, &g_projection);

// Initialize any objects we will be displaying.
if(!InitializeObjects()) return false;

return true;
}


bool InitializeObjects()
{
// Property scripting system and properties for our object.
CPropertyScript propertyScript;
stVector teapotCol, camPos;

// Load the script.
if(!propertyScript.LoadScriptFile("script.spt"))
return false;

// Get the variables we need.
teapotCol = propertyScript.GetVariableAsVector("teapotColor");
camPos
= propertyScript.GetVariableAsVector("cameraPosition");

// Release all resources. This script only needs to run once.
propertyScript.Shutdown();


// Set default rendering states.
g_D3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
g_D3DDevice
->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_COLORVALUE(0.3f, 0.3f, 0.3f, 1.0f));

// Setup the light source.
g_light.Type = D3DLIGHT_DIRECTIONAL;
g_light.Direction
= D3DXVECTOR3(0.0f, 0.0f, 1.0f);
g_light.Diffuse.r
= g_light.Diffuse.g = 1;
g_light.Diffuse.b
= g_light.Diffuse.a = 1;
g_light.Specular.r
= g_light.Specular.g = 1;
g_light.Specular.b
= g_light.Specular.a = 1;

// Register the light.
g_D3DDevice->SetLight(0, &g_light);
g_D3DDevice
->LightEnable(0, TRUE);

// Setup the material properties for the teapot.
ZeroMemory(&g_material, sizeof(D3DMATERIAL9));
g_material.Ambient.r
= 0.6f;
g_material.Ambient.g
= 0.6f;
g_material.Ambient.b
= 0.7f;
g_material.Diffuse.r
= teapotCol.x;
g_material.Diffuse.g
= teapotCol.y;
g_material.Diffuse.b
= teapotCol.z;
g_material.Specular.r
= 0.4f;
g_material.Specular.g
= 0.4f;
g_material.Specular.b
= 0.4f;
g_material.Power
= 8.0f;

// Create the objects.
if(FAILED(D3DXCreateTeapot(g_D3DDevice, &g_teapot, NULL)))
return false;

// Define camera information.
D3DXVECTOR3 cameraPos(camPos.x, camPos.y, camPos.z);
D3DXVECTOR3 lookAtPos(
0.0f, 0.0f, 0.0f);
D3DXVECTOR3 upDir(
0.0f, 1.0f, 0.0f);

// Build view matrix.
D3DXMatrixLookAtLH(&g_ViewMatrix, &cameraPos, &lookAtPos, &upDir);

return true;
}


void RenderScene()
{
// Clear the backbuffer.
g_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);

// Begin the scene. Start rendering.
g_D3DDevice->BeginScene();

// Apply the view (camera).
g_D3DDevice->SetTransform(D3DTS_VIEW, &g_ViewMatrix);

// Draw teapot.
g_D3DDevice->SetMaterial(&g_material);
g_teapot
->DrawSubset(0);

// End the scene. Stop rendering.
g_D3DDevice->EndScene();

// Display the scene.
g_D3DDevice->Present(NULL, NULL, NULL, NULL);
}


void Shutdown()
{
// Release all resources.
if(g_D3DDevice != NULL) g_D3DDevice->Release();
if(g_D3D != NULL) g_D3D->Release();
if(g_teapot != NULL) { g_teapot->Release(); g_teapot = NULL; }
}

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值