• 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; }
    }

      

  • 相关阅读:
    深度聚类算法浅谈
    最优运输(Optimal Transfort):从理论到填补的应用
    《Javscript实用教程》目录
    再见,深圳~长沙,我又来啦
    vue中手写table的升降序
    Linux离线安装Python3.6.8
    Python3的threading模块 lock、Rlock的使用
    Python3的multiprocessing多进程-示例
    Python3的multiprocessing多进程-Lock、Rlock进程同步
    Python3的multiprocessing多进程-Queue、Pipe进程间通信
  • 原文地址:https://www.cnblogs.com/kex1n/p/2172924.html
Copyright © 2020-2023  润新知