User Tools

Site Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
licensing:samplecode [2008-09-02 14:28]
Carsten created
— (current)
Line 1: Line 1:
-====== Ca3D-Engine C++ Sample Source Code ====== 
- 
-This page contains several sections of C++ source code from the Ca3D-Engine. 
-For more ways to evaluate and getting a picture of the Ca3D-Engine,​ please refer to [[licensing:​faqs#​can_i_preview_and_evaluate_the_ca3d-engine|this Licensing FAQ]]. 
- 
- 
-===== Libs/​GuiSys/​GuiImpl.cpp ===== 
- 
-This file is part of the Ca3DE GUI System. It implements a single GUI as e.g. the games Main Menu or a panel on a world entity. 
- 
-<code cpp> 
-#include "​GuiImpl.hpp"​ 
-#include "​GuiMan.hpp"​ 
- 
- 
-using namespace cf::GuiSys; 
- 
- 
-GuiImplT::​GuiImplT(const std::​string&​ GuiScriptName,​ bool IsInlineCode) 
-    : ScriptName(IsInlineCode ? ""​ : GuiScriptName),​ 
-      LuaState(NULL),​ 
-      RootWindow(NULL),​ 
-      FocusWindow(NULL),​ 
-      MouseOverWindow(NULL),​ 
-      IsActive(true),​ 
-      IsInteractive(true),​ 
-      IsFullCover(false),​ 
-      MousePosX(VIRTUAL_SCREEN_SIZE_X/​2.0f), ​  // 320.0f 
-      MousePosY(VIRTUAL_SCREEN_SIZE_Y/​2.0f), ​  // 240.0f 
-      MouseIsShown(true) 
-{ 
-    // Initialize Lua. 
-    LuaState=lua_open();​ 
- 
-    lua_pushcfunction(LuaState,​ luaopen_base); ​   lua_pushstring(LuaState,​ ""​); ​             lua_call(LuaState,​ 1, 0);  // Opens the basic library. 
-    lua_pushcfunction(LuaState,​ luaopen_package);​ lua_pushstring(LuaState,​ LUA_LOADLIBNAME);​ lua_call(LuaState,​ 1, 0);  // Opens the package library. 
-    lua_pushcfunction(LuaState,​ luaopen_table); ​  ​lua_pushstring(LuaState,​ LUA_TABLIBNAME); ​ lua_call(LuaState,​ 1, 0);  // Opens the table library. 
-    lua_pushcfunction(LuaState,​ luaopen_io); ​     lua_pushstring(LuaState,​ LUA_IOLIBNAME); ​  ​lua_call(LuaState,​ 1, 0);  // Opens the I/O library. 
-    lua_pushcfunction(LuaState,​ luaopen_os); ​     lua_pushstring(LuaState,​ LUA_OSLIBNAME); ​  ​lua_call(LuaState,​ 1, 0);  // Opens the OS library. 
-    lua_pushcfunction(LuaState,​ luaopen_string); ​ lua_pushstring(LuaState,​ LUA_STRLIBNAME); ​ lua_call(LuaState,​ 1, 0);  // Opens the string lib. 
-    lua_pushcfunction(LuaState,​ luaopen_math); ​   lua_pushstring(LuaState,​ LUA_MATHLIBNAME);​ lua_call(LuaState,​ 1, 0);  // Opens the math lib. 
- 
-    // Load the console library. (Adds a global table with name "​Console"​ to the LuaState with the functions of the ConsoleI interface.) 
-    cf::​ConsoleI::​RegisterLua(LuaState);​ 
- 
-    // Load the "​ci"​ (console interpreter) library. (Adds a global table with name "​ci"​ to the LuaState with (some of) the functions of the ConsoleInterpreterI interface.) 
-    ConsoleInterpreterI::​RegisterLua(LuaState);​ 
- 
-    // Adds a global (meta-)table with methods for cf::​GuiSys::​GuiTs to the LuaState, to be used as metatable for userdata of type cf::​GuiSys::​GuiT. 
-    GuiImplT::​RegisterLua(LuaState);​ 
- 
- 
-    // For each (window-)class that the TypeInfoMan knows about, add a (meta-)table to the registry of the LuaState. 
-    // The (meta-)table holds the Lua methods that the respective class implements in C++ and is to be used as metatable for instances of this class. 
-    cf::​TypeSys::​TypeInfoManT&​ TIM=GetWindowTIM();​ 
- 
-    // ANALOGY: This code is IDENTICAL WITH that in Games/​DeathMatch/​Code/​ScriptState.cpp. 
-    for (unsigned long RootNr=0; RootNr<​TIM.GetTypeInfoRoots().Size();​ RootNr++) 
-    { 
-        for (const cf::​TypeSys::​TypeInfoT* TI=TIM.GetTypeInfoRoots()[RootNr];​ TI!=NULL; TI=TI->​GetNext()) 
-        { 
-            assert(lua_gettop(LuaState)==0);​ 
- 
-            // Create a new table T and add it into the registry table with TI->​ClassName (e.g. "​cf::​GuiSys::​WindowT"​) as the key and T as the value. 
-            // This also leaves T on top of the stack. See PiL2 chapter 28.2 for more details. 
-            luaL_newmetatable(LuaState,​ TI->​ClassName);​ 
- 
-            // See PiL2 chapter 28.3 for a great explanation on what is going on here. 
-            // Essentially,​ we set T.__index = T (the luaL_newmetatable() function left T on the top of the stack). 
-            lua_pushvalue(LuaState,​ -1);                // Pushes/​duplicates the new table T on the stack. 
-            lua_setfield(LuaState,​ -2, "​__index"​); ​     // T.__index = T; 
- 
-            // Now insert the functions listed in TI->​MethodsList into T (the table on top of the stack). 
-            if (TI->​MethodsList!=NULL) 
-                luaL_register(LuaState,​ NULL, TI->​MethodsList);​ 
- 
-            // If TI has a base class, model that relationship for T, too, by setting the metatable of the base class as the metatable for T. 
-            // Note that this works because the for-loop (over TI) enumerates the base classes always before their child classes! 
-            if (TI->​Base) 
-            { 
-                assert(strcmp(TI->​BaseClassName,​ TI->​Base->​ClassName)==0);​ 
- 
-                // Get the metatable M with name (key) TI->​Base->​ClassName (e.g. "​cf::​GameSys::​BaseEntityT"​) 
-                // from the registry, and set it as metatable of T. 
-                luaL_getmetatable(LuaState,​ TI->​Base->​ClassName);​ 
-                lua_setmetatable(LuaState,​ -2); 
-            } 
- 
-            // Clear the stack. 
-            assert(lua_gettop(LuaState)==1);​ 
-            lua_pop(LuaState,​ 1); 
-        } 
-    } 
- 
- 
-    // Add a global variable with name "​gui"​ to the Lua state. "​gui"​ is a table that scripts can use to call GUI methods. 
-    { 
-        assert(lua_gettop(LuaState)==0);​ 
- 
-        // Stack indices of the table and userdata that we create. 
-        const int USERDATA_INDEX=2;​ 
-        const int TABLE_INDEX ​  =1; 
- 
-        // Create a new table T, which is pushed on the stack and thus at stack index TABLE_INDEX. 
-        lua_newtable(LuaState);​ 
- 
-        // Create a new user datum UD, which is pushed on the stack and thus at stack index USERDATA_INDEX. 
-        GuiImplT** UserData=(GuiImplT**)lua_newuserdata(LuaState,​ sizeof(GuiImplT*));​ 
- 
-        // Initialize the memory allocated by the lua_newuserdata() function. 
-        *UserData=this;​ 
- 
-        // T["​__userdata_cf"​] = UD 
-        lua_pushvalue(LuaState,​ USERDATA_INDEX); ​   // Duplicate the userdata on top of the stack (as the argument for lua_setfield()). 
-        lua_setfield(LuaState,​ TABLE_INDEX,​ "​__userdata_cf"​);​ 
- 
-        // Get the table with name (key) "​cf::​GuiSys::​GuiT"​ from the registry, 
-        // and set it as metatable of the newly created table. 
-        luaL_getmetatable(LuaState,​ "​cf::​GuiSys::​GuiT"​);​ 
-        lua_setmetatable(LuaState,​ TABLE_INDEX);​ 
- 
-        // Get the table with name (key) "​cf::​GuiSys::​GuiT"​ from the registry, 
-        // and set it as metatable of the newly created user data (for user data type safety, see PiL2, chapter 28.2). 
-        luaL_getmetatable(LuaState,​ "​cf::​GuiSys::​GuiT"​);​ 
-        lua_setmetatable(LuaState,​ USERDATA_INDEX);​ 
- 
-        // Remove UD from the stack, so that only the new table T is left on top of the stack. 
-        // Then add it as a global variable whose name is "​gui"​. 
-        // As lua_setglobal() pops the table from the stack, the stack is left empty. 
-        lua_pop(LuaState,​ 1); 
-        lua_setglobal(LuaState,​ "​gui"​);​ 
-        // Could instead do   ​lua_setfield(LuaState,​ LUA_REGISTRYINDEX,​ "​gui"​); ​  as well, 
-        // so that script methods like "​new()"​ and "​thread()"​ could also be called without the "​gui:"​ prefix. 
-    } 
- 
-    // Make sure that everyone dealt properly with the Lua stack so far. 
-    assert(lua_gettop(LuaState)==0);​ 
- 
- 
-    // Add a table with name "​__pending_coroutines_cf"​ to the registry. 
-    // This table will be used to keep track of the pending coroutines, making sure that Lua doesn'​t garbage collect them early. 
-    lua_newtable(LuaState);​ 
-    lua_setfield(LuaState,​ LUA_REGISTRYINDEX,​ "​__pending_coroutines_cf"​);​ 
- 
- 
-    // Run the equivalent to "​wait=coroutine.yield;"​ and "​waitFrame=coroutine.yield;",​ that is, 
-    // provide aliases for coroutine.yield as known from Doom3 map scripting. 
-    lua_getglobal(LuaState,​ "​coroutine"​);​ 
-    lua_getfield(LuaState,​ -1, "​yield"​);​ 
-    lua_setglobal(LuaState,​ "​wait"​);​ 
-    lua_getfield(LuaState,​ -1, "​yield"​);​ 
-    lua_setglobal(LuaState,​ "​waitFrame"​);​ 
-    lua_pop(LuaState,​ 1); 
- 
- 
-    // Load the user script! 
-    const int LoadResult=IsInlineCode ? luaL_loadstring(LuaState,​ GuiScriptName.c_str()) 
-                                      : luaL_loadfile ​ (LuaState, GuiScriptName.c_str());​ 
- 
-    if (LoadResult!=0 || lua_pcall(LuaState,​ 0, 0, 0)!=0) 
-    { 
-        Console->​Warning(std::​string("​Lua script \""​)+GuiScriptName+"​\"​ could not be loaded\n"​);​ 
-        Console->​Print(std::​string("​("​)+lua_tostring(LuaState,​ -1)+"​).\n"​);​ 
-        lua_pop(LuaState,​ 1); 
-    } 
- 
-    // Make sure that everyone dealt properly with the Lua stack so far. 
-    assert(lua_gettop(LuaState)==0);​ 
- 
- 
-    if (RootWindow==NULL) 
-    { 
-        Console->​Warning("​No root window set for GUI \""​+GuiScriptName+"​\"​!\n"​);​ 
- 
-        // Note that just running some Lua code like "​gui:​SetRootWindow(gui:​new('​WindowT'​));"​ 
-        // here in order to save the situation is not as easy as it seems, because running 
-        // this code is not guaranteed to be fail-safe and thus not guaranteed to fix the 
-        // problem. That is, there might still be a case left where we might want to throw. 
-        lua_close(LuaState);​ 
-        throw InitErrorT();​ 
-    } 
- 
- 
-    // Finally call the Lua OnInit() method of each window. 
-    ArrayT<​WindowT*>​ AllChildren;​ 
- 
-    AllChildren.PushBack(RootWindow.GetRaw());​ 
-    RootWindow->​GetChildren(AllChildren,​ true); 
- 
-    for (unsigned long ChildNr=0; ChildNr<​AllChildren.Size();​ ChildNr++) 
-    { 
-        AllChildren[ChildNr]->​CallLuaMethod("​OnInit"​);​ 
-    } 
- 
- 
-    // Make sure that everyone dealt properly with the Lua stack so far. 
-    assert(lua_gettop(LuaState)==0);​ 
-} 
- 
- 
-const std::​string&​ GuiImplT::​GetScriptName() const 
-{ 
-    return ScriptName; 
-} 
- 
- 
-void GuiImplT::​Activate(bool doActivate) 
-{ 
-    IsActive=doActivate;​ 
- 
-    // Call the OnActivate() or OnDeactivate() methods of all windows. 
-    ArrayT<​WindowT*>​ AllChildren;​ 
- 
-    AllChildren.PushBack(RootWindow.GetRaw());​ 
-    RootWindow->​GetChildren(AllChildren,​ true); 
- 
-    for (unsigned long ChildNr=0; ChildNr<​AllChildren.Size();​ ChildNr++) 
-        AllChildren[ChildNr]->​CallLuaMethod(IsActive ? "​OnActivate"​ : "​OnDeactivate"​);​ 
-} 
- 
- 
-void GuiImplT::​SetInteractive(bool IsInteractive_) 
-{ 
-    IsInteractive=IsInteractive_;​ 
-} 
- 
- 
-void GuiImplT::​SetMousePos(float MousePosX_, float MousePosY_) 
-{ 
-    MousePosX=MousePosX_;​ 
-    MousePosY=MousePosY_;​ 
- 
- 
-    // Clip the mouse position to valid coordinates. 
-    if (MousePosX<​0.0f) MousePosX=0.0;​ 
-    if (MousePosX>​VIRTUAL_SCREEN_SIZE_X) MousePosX=VIRTUAL_SCREEN_SIZE_X;​ 
- 
-    if (MousePosY<​0.0f) MousePosY=0.0;​ 
-    if (MousePosY>​VIRTUAL_SCREEN_SIZE_Y) MousePosY=VIRTUAL_SCREEN_SIZE_Y;​ 
- 
- 
-    // Determine if the mouse cursor has been moved into (or "​over"​) another window, 
-    // that is, see if we have to run any OnMouseLeave() and OnMouseEnter() scripts. 
-    WindowT* Win=RootWindow->​Find(MousePosX,​ MousePosY); 
- 
-    if (Win!=MouseOverWindow.GetRaw()) 
-    { 
-        if (MouseOverWindow!=NULL) MouseOverWindow->​CallLuaMethod("​OnMouseLeave"​);​ 
-        MouseOverWindow=Win;​ 
-        if (MouseOverWindow!=NULL) MouseOverWindow->​CallLuaMethod("​OnMouseEnter"​);​ 
-    } 
-} 
- 
- 
-void GuiImplT::​SetShowMouse(bool ShowMouse_) 
-{ 
-    MouseIsShown=ShowMouse_;​ 
-} 
- 
- 
-void GuiImplT::​Render() 
-{ 
-    RootWindow->​Render();​ 
- 
-    if (MouseIsShown) 
-    { 
-        // Render the background. 
-     // MatSys::​Renderer->​SetCurrentAmbientLightColor(BackColor);​ 
-        MatSys::​Renderer->​SetCurrentMaterial(GuiMan->​GetDefaultRM() /​*BackMaterial*/​);​ 
- 
-        static MatSys::​MeshT CrossMesh(MatSys::​MeshT::​Lines);​ 
-        CrossMesh.Vertices.Overwrite();​ 
-        CrossMesh.Vertices.PushBackEmpty(4); ​    // Just a single quad for the background rectangle. 
- 
-        for (unsigned long VertexNr=0; VertexNr<​CrossMesh.Vertices.Size();​ VertexNr++) 
-        { 
-            CrossMesh.Vertices[VertexNr].Color[0]=0.8f;​ 
-            CrossMesh.Vertices[VertexNr].Color[1]=0.0f;​ 
-            CrossMesh.Vertices[VertexNr].Color[2]=0.0f;​ 
-            CrossMesh.Vertices[VertexNr].Color[3]=1.0f;​ 
-        } 
- 
-        const float b=10.0f; ​   // The cursor size. 
- 
-        // The tex-coord currently don't make much sense... 
-        CrossMesh.Vertices[0].SetOrigin(MousePosX-b,​ MousePosY ​ ); CrossMesh.Vertices[0].SetTextureCoord(0.0f,​ 0.0f); 
-        CrossMesh.Vertices[1].SetOrigin(MousePosX+b,​ MousePosY ​ ); CrossMesh.Vertices[1].SetTextureCoord(1.0f,​ 0.0f); 
-        CrossMesh.Vertices[2].SetOrigin(MousePosX, ​  ​MousePosY-b);​ CrossMesh.Vertices[2].SetTextureCoord(1.0f,​ 1.0f); 
-        CrossMesh.Vertices[3].SetOrigin(MousePosX, ​  ​MousePosY+b);​ CrossMesh.Vertices[3].SetTextureCoord(0.0f,​ 1.0f); 
- 
-        MatSys::​Renderer->​RenderMesh(CrossMesh);​ 
-    } 
-} 
- 
- 
-bool GuiImplT::​ProcessDeviceEvent(const CaKeyboardEventT&​ KE) 
-{ 
-    for (WindowT* Win=FocusWindow.GetRaw();​ Win!=NULL; Win=Win->​GetParent()) 
-    { 
-        bool KeyWasProcessed=false;​ 
-        bool ResultOK ​      ​=false;​ 
- 
-        switch (KE.Type) 
-        { 
-            case CaKeyboardEventT::​CKE_KEYDOWN:​ ResultOK=Win->​CallLuaMethod("​OnKeyPress", ​  "​i>​b",​ KE.Key, &​KeyWasProcessed);​ break; 
-            case CaKeyboardEventT::​CKE_CHAR: ​   ResultOK=Win->​CallLuaMethod("​OnChar", ​      "​i>​b",​ KE.Key, &​KeyWasProcessed);​ break; 
-            case CaKeyboardEventT::​CKE_KEYUP: ​  ​ResultOK=Win->​CallLuaMethod("​OnKeyRelease",​ "​i>​b",​ KE.Key, &​KeyWasProcessed);​ break; 
-        } 
- 
-        if (ResultOK && KeyWasProcessed) return true; 
-        if (Win->​OnInputEvent(KE)) return true; 
-    } 
- 
-    return false; 
-} 
- 
- 
-bool GuiImplT::​ProcessDeviceEvent(const CaMouseEventT&​ ME) 
-{ 
-    // Note that the processing of the mouse event is orthogonal to (independent of) MouseIsShown. 
-    // That is, we may be active and interactive even if the mouse cursor is *not* shown, 
-    // as for example with the 3D window of the Ca3D-Engine client, which must receive the 
-    // mouse events even if no mouse cursor is shown! 
- 
-    bool MEWasProcessed=false; ​     // If the Lua script handler consumed the event. 
-    bool ResultOK ​     =false; ​     // If the Lua script handler returned without script error. 
- 
-    switch (ME.Type) 
-    { 
-        case CaMouseEventT::​CM_BUTTON0:​ 
-        case CaMouseEventT::​CM_BUTTON1:​ 
-        case CaMouseEventT::​CM_BUTTON2:​ 
-        case CaMouseEventT::​CM_BUTTON3:​ 
-        { 
-            const bool ButtonDown=(ME.Amount>​0); ​   // Was it a "​button up" or "​button down" event? 
- 
-            if (MouseOverWindow!=NULL) 
-            { 
-                ResultOK=MouseOverWindow->​CallLuaMethod(ButtonDown ? "​OnMouseButtonDown"​ : "​OnMouseButtonUp",​ "​i>​b",​ ME.Type, &​MEWasProcessed);​ 
-            } 
- 
-            // Change the keyboard input focus, but only if the mouse button event was not handled by the script 
-            // (by handling the event the script signals that the default behaviour (focus change) should not take place). 
-            if (!MEWasProcessed && ME.Type==CaMouseEventT::​CM_BUTTON0 && ButtonDown && MouseOverWindow!=FocusWindow.GetRaw()) 
-            { 
-                // Only "​unhandled left mouse button down" events change the keyboard input focus. 
-                if (FocusWindow!=NULL) FocusWindow->​CallLuaMethod("​OnFocusLose"​);​ 
-                FocusWindow=MouseOverWindow;​ 
-                if (FocusWindow!=NULL) FocusWindow->​CallLuaMethod("​OnFocusGain"​);​ 
-            } 
- 
-            break; 
-        } 
- 
-        case CaMouseEventT::​CM_MOVE_X:​ 
-        { 
-            // Update the mouse cursor position according to the ME. 
-            SetMousePos(MousePosX+ME.Amount,​ MousePosY); 
- 
-            // if (MouseOverWindow!=NULL) 
-            // { 
-            //     ​ResultOK=MouseOverWindow->​CallLuaMethod("​OnMouseMove",​ "​ii>​b",​ RelMousePosX,​ RelMousePosY,​ &​MEWasProcessed);​ 
-            // } 
-            break; 
-        } 
- 
-        case CaMouseEventT::​CM_MOVE_Y:​ 
-        { 
-            // Update the mouse cursor position according to the ME. 
-            SetMousePos(MousePosX,​ MousePosY+ME.Amount);​ 
- 
-            // if (MouseOverWindow!=NULL) 
-            // { 
-            //     ​ResultOK=MouseOverWindow->​CallLuaMethod("​OnMouseMove",​ "​ii>​b",​ RelMousePosX,​ RelMousePosY,​ &​MEWasProcessed);​ 
-            // } 
-            break; 
-        } 
- 
-        default: 
-            // Just ignore the other possible ME types. 
-            break; 
-    } 
- 
-    if (ResultOK && MEWasProcessed) return true; 
-    if (MouseOverWindow==NULL) return false; 
- 
-    float AbsWinPosX; 
-    float AbsWinPosY; 
- 
-    MouseOverWindow->​GetAbsolutePos(AbsWinPosX,​ AbsWinPosY);​ 
- 
-    return MouseOverWindow->​OnInputEvent(ME,​ MousePosX-AbsWinPosX,​ MousePosY-AbsWinPosY);​ 
-} 
- 
- 
-void GuiImplT::​DistributeClockTickEvents(float t) 
-{ 
-    ArrayT<​WindowT*>​ AllChildren;​ 
- 
-    AllChildren.PushBack(RootWindow.GetRaw());​ 
-    RootWindow->​GetChildren(AllChildren,​ true); 
- 
-    for (unsigned long ChildNr=0; ChildNr<​AllChildren.Size();​ ChildNr++) 
-    { 
-        AllChildren[ChildNr]->​OnClockTickEvent(t);​ 
-        AllChildren[ChildNr]->​CallLuaMethod("​OnFrame"​);​ 
-    } 
- 
-    RunPendingCoroutines(t);​ 
-} 
- 
- 
-bool GuiImplT::​CallLuaFunc(const char* FuncName, const char* Signature, ...) 
-{ 
-    // Note that when re-entrancy occurs, we do usually NOT have an empty stack here! 
-    // That is, when we first call a Lua function the stack is empty, but when the called Lua function 
-    // in turn calls back into our C++ code (e.g. a console function), and the C++ code in turn gets here, 
-    // we have a case of re-entrancy and the stack is not empty! 
-    // That is, the assert() statement in the next line does not generally hold. 
-    // assert(lua_gettop(LuaState)==0);​ 
- 
-    // Get the desired global function. 
-    lua_getglobal(LuaState,​ FuncName); 
- 
-    if (!lua_isfunction(LuaState,​ -1)) 
-    { 
-        // If we get here, this usually means that the value at -1 is just nil, i.e. the 
-        // function that we would like to call was just not defined in the Lua script. 
-        lua_pop(LuaState,​ 1);   // Pop whatever is not a function. 
-        return false; 
-    } 
- 
-    va_list vl; 
- 
-    va_start(vl,​ Signature); 
-    const bool Result=StartNewCoroutine(0,​ Signature, vl, std::​string("​global function "​)+FuncName+"​()"​);​ 
-    va_end(vl); 
- 
-    return Result; 
-} 
- 
- 
-bool GuiImplT::​CallLuaMethod(WindowPtrT Window, const char* MethodName, const char* Signature, ...) 
-{ 
-    va_list vl; 
- 
-    va_start(vl,​ Signature); 
-    const bool Result=Window->​CallLuaMethod(MethodName,​ Signature, vl); 
-    va_end(vl); 
- 
-    return Result; 
-} 
- 
- 
-void GuiImplT::​SetEntityInfo(const char* EntityName_,​ void* /​*EntityInstancePtr_*/​) 
-{ 
-    EntityName=EntityName_;​ 
- // EntityInstancePtr=EntityInstancePtr_;​ 
-} 
- 
- 
-void GuiImplT::​RegisterScriptLib(const char* LibName, const luaL_Reg Functions[]) 
-{ 
-    luaL_register(LuaState,​ LibName, Functions); 
-    lua_pop(LuaState,​ 1);   // Remove the LibName table from the stack (it was left there by the luaL_register() function). 
-} 
- 
- 
-static void CountHookFunction(lua_State* CrtState, lua_Debug* ar) 
-{ 
-    assert(ar->​event==LUA_HOOKCOUNT);​ 
- 
-    luaL_error(CrtState,​ "​Instruction count exceeds predefined limit (infinite loop error)."​);​ 
-} 
- 
- 
-/** 
- * This method calls a Lua function in the context of the LuaState. 
- * 
- * As a prerequisite,​ the caller must have pushed the Lua function to be called onto the stack of LuaState, 
- * followed by any extra arguments (that is, arguments that are not passed in the Signature/​vl parameters) at subsequent stack positions 
- * (as for example the alter ego instance of a window that is to be used as the "​self"​ or "​this"​ value of an object-oriented method call). 
- * At stack positions "​below"​ the function to be called there may be other stack values that this method will not touch. 
- * Additional parameters to the Lua function are appended from the vl parameter list as described by the Signature. 
- * Return values of the Lua function are returned to the vl parameter list as described by the Signature. 
- * 
- * The function call is implemented as the resumption of a coroutine (the coroutine instance is newly created), 
- * so that the script code can call coroutine.yield() and its derivatives like wait(), waitFrame(),​ etc. 
- */ 
-bool GuiImplT::​StartNewCoroutine(int NumExtraArgs,​ const char* Signature, va_list vl, const std::​string&​ DbgName) 
-{ 
-    // Create a new coroutine for this function call (or else they cannot call coroutine.yield()). 
-    // The new coroutine is pushed onto the stack of LuaState as a value of type "​thread"​. 
-    lua_State* NewThread=lua_newthread(LuaState);​ 
- 
-    // Move the new thread from the top (-1) stack position to the position "​below"​ the function and its extra parameters. 
-    lua_insert(LuaState,​ -(1+NumExtraArgs+1));​ 
- 
-    // Move the function and its extra parameters to the stack of NewThread. 
-    lua_xmove(LuaState,​ NewThread, NumExtraArgs+1);​ 
- 
- 
-    // Put all other arguments for the function onto the stack of NewThread. 
-    // ********************************************************************* 
- 
-    const char* Results="";​ 
- 
-    for (const char* c=Signature;​ *c; c++) 
-    { 
-        if (*c=='>'​) 
-        { 
-            Results=c+1;​ 
-            break; 
-        } 
- 
-        switch (*c) 
-        { 
-            // According to the g++ compiler, bool is promoted to int, and float is promoted to double when passed through '​...',​ 
-            // and therefore we should pass int and double to va_arg() instead of bool and float. 
-            case '​b':​ lua_pushboolean(NewThread,​ va_arg(vl, /​*bool*/​int ​   )); break; 
-            case '​i':​ lua_pushinteger(NewThread,​ va_arg(vl, int            )); break; 
-            case '​f':​ lua_pushnumber (NewThread, va_arg(vl, /​*float*/​double));​ break; 
-            case '​d':​ lua_pushnumber (NewThread, va_arg(vl, double ​        )); break; 
-            case '​s':​ lua_pushstring (NewThread, va_arg(vl, char*          )); break; 
-         // case '​E':​ lua_getglobal ​ (NewThread, va_arg(vl, BaseEntityT*)->​Name.c_str());​ break; 
- 
-            default: 
-                Console->​Warning(std::​string("​Invalid signature \""​)+Signature+"​\"​ in call to "​+DbgName+"​.\n"​);​ 
-                lua_settop(NewThread,​ 0);   // Clear the stack of NewThread (the function and its arguments). 
-                lua_pop(LuaState, ​ 1);      // Pop the thread (it will then be garbage collected). 
-                return false; 
-        } 
- 
-        // WARNING: Do NOT issue a call like   ​lua_tostring(NewThread,​ -1)   here! 
-        // This is because "If the value is a number, then lua_tolstring also changes the actual value in the stack to a string.",​ 
-        // as described at http://​www.lua.org/​manual/​5.1/​manual.html#​lua_tolstring 
-    } 
- 
-    const int ResCount=strlen(Results);​ 
- 
- 
-    // Do the actual function call. 
-    // **************************** 
- 
-    // Set the hook function for the "​count"​ event, so that we can detect and prevent infinite loops. 
-    lua_sethook(NewThread,​ CountHookFunction,​ LUA_MASKCOUNT,​ 10000); ​   // Should have a ConVar for the number of instruction counts!? 
- 
-    // Start the new coroutine. 
-    const int ThreadResult=lua_resume(NewThread,​ lua_gettop(NewThread)-1);​ 
- 
- 
-    // Deal with the results. 
-    // ********************** 
- 
-    if (ThreadResult==0) 
-    { 
-        // The coroutine returned normally, now return the results to the caller. 
-        int StackIndex=1;​ 
- 
-        // If we expect more arguments back than we got, push a single nil that will help to fill-up any number of missing arguments. 
-        if (ResCount>​lua_gettop(NewThread)) lua_pushnil(NewThread);​ 
- 
-        for (const char* c=Results; *c; c++) 
-        { 
-            switch (*c) 
-            { 
-                case '​b':​ *va_arg(vl, bool*  )=lua_toboolean(NewThread,​ StackIndex)!=0;​ break; 
-                case '​i':​ *va_arg(vl, int*   ​)=lua_tointeger(NewThread,​ StackIndex);​ break; 
-                case '​f':​ *va_arg(vl, float* )=float(lua_tonumber(NewThread,​ StackIndex));​ break; 
-                case '​d':​ *va_arg(vl, double*)=lua_tonumber(NewThread,​ StackIndex);​ break; 
-             // case '​E':​ *va_arg(vl, BaseEntityT**)=(BaseEntityT*)ScriptStateT::​GetCheckedObjectParam(NewThread,​ StackIndex, BaseEntityT::​TypeInfo);​ break; 
- 
-                case '​s':​ 
-                { 
-                    const char*        s=lua_tostring(NewThread,​ StackIndex);​ 
-                    static const char* e="";​ 
- 
-                    *va_arg(vl, const char**)=(s!=NULL) ? s : e; 
-                    break; 
-                } 
- 
-                case '​S':​ 
-                { 
-                    const char* s=lua_tostring(NewThread,​ StackIndex);​ 
- 
-                    *va_arg(vl, std::​string*)=(s!=NULL) ? s : "";​ 
-                    break; 
-                } 
- 
-                default: 
-                    Console->​Warning(std::​string("​Invalid results signature \""​)+Signature+"​\"​ in call to "​+DbgName+"​.\n"​);​ 
-                    break; 
-            } 
- 
-            if (StackIndex<​lua_gettop(NewThread)) StackIndex++;​ 
-        } 
- 
-        lua_settop(NewThread,​ 0);   // Pop everything (the results) from the NewThread stack. 
-        lua_pop(LuaState,​ 1);       // Pop the thread (it will then be garbage collected). 
-        return true; 
-    } 
- 
-    if (ThreadResult==LUA_YIELD) 
-    { 
-        // The argument to the coroutine.yield() call is the wait time in seconds until the coroutine is supposed to be resumed. 
-        // If the argument is not given (or not a number), a wait time of 0 is assumed. 
-        // In any case, the earliest when the coroutine will be resumed is in the next (subsequent) server Think() frame. 
- 
-        // Check the argument(s). 
-        if (lua_gettop(NewThread)==0) lua_pushnumber(NewThread,​ 0); 
-        if (!lua_isnumber(NewThread,​ -1)) lua_pushnumber(NewThread,​ 0); 
- 
-        CoroutineMan.PendingCoroutines.PushBack(Crt);​ 
- 
-        // REGISTRY["​__pending_coroutines_cf"​][Crt.ID]=Crt.State;​ 
-        lua_getfield(LuaState,​ LUA_REGISTRYINDEX,​ "​__pending_coroutines_cf"​); ​  // Put REGISTRY["​__pending_coroutines_cf"​] onto the stack (index -1). 
-        assert(lua_istable(LuaState,​ -1));  // Make sure that REGISTRY["​__pending_coroutines_cf"​] really is a table. 
-        lua_pushvalue(LuaState,​ -2);        // Duplicate the "​thread"​ (==Ctr.State) value from index -2 to the top of the stack. 
-        lua_rawseti(LuaState,​ -2, Crt.ID); ​ // table[Crt.ID]=Crt.State; ​   -- Pops the value from the stack. 
-        lua_pop(LuaState,​ 1);               // Pop the table again. 
- 
-        if (ResCount>​0) 
-            Console->​Warning("​The call to "​+DbgName+"​ yielded (expected return values matching signature \""​+Signature+"​\"​ instead).\n"​);​ 
- 
-        lua_settop(NewThread,​ 0);   // Pop everything (the parameters to coroutine.yield()) from the NewThread stack. 
-        lua_pop(LuaState,​ 1);       // Pop the thread (it's kept inside the __pending_coroutines_cf table now). 
-        return ResCount==0;​ 
-    } 
- 
-    // ThreadResult is not 0 and not LUA_YIELD, so an error occurred when running the coroutine. 
-    // Note that we need an extra newline here, because (all?) the Lua error messages don't have one. 
-    Console->​Warning("​Lua error in call to "​+DbgName+":​\n"​);​ 
-    Console->​Print(std::​string(lua_tostring(NewThread,​ -1))+"​\n"​);​ 
- 
-    // Note that the stack of NewThread was not unwound after the error (but we currently have no use for it). 
-    lua_settop(NewThread,​ 0);   // Just pop everything from the NewThread stack. 
-    lua_pop(LuaState,​ 1);       // Pop the thread (it will then be garbage collected). 
-    return false; 
-} 
- 
- 
-/​**********************************************/​ 
-/*** Impementation of Lua binding functions ***/ 
-/​**********************************************/​ 
- 
-static GuiImplT* CheckParams(lua_State* LuaState) 
-{ 
-    luaL_argcheck(LuaState,​ lua_istable(LuaState,​ 1), 1, "​Expected a table that represents a GUI."​);​ 
-    lua_getfield(LuaState,​ 1, "​__userdata_cf"​);​ 
- 
-    GuiImplT** UserData=(GuiImplT**)luaL_checkudata(LuaState,​ -1, "​cf::​GuiSys::​GuiT"​);​ if (UserData==NULL) luaL_error(LuaState,​ "NULL userdata in GUI table."​);​ 
-    GuiImplT* ​ Gui     ​=(*UserData);​ 
- 
-    // Pop the userdata from the stack again. Not necessary though as it doesn'​t hurt there. 
-    // lua_pop(LuaState,​ 1); 
-    return Gui; 
-} 
- 
- 
-int GuiImplT::​Activate(lua_State* LuaState) 
-{ 
-    GuiImplT* Gui=CheckParams(LuaState);​ 
- 
-    // I also want to treat the number 0 as false, not just "​false"​ and "​nil"​. 
-    if (lua_isnumber(LuaState,​ 2)) Gui->​IsActive=lua_tointeger(LuaState,​ 2)!=0; 
-                              else Gui->​IsActive=lua_toboolean(LuaState,​ 2)!=0; 
- 
-    return 0; 
-} 
- 
- 
-int GuiImplT::​Close(lua_State* LuaState) 
-{ 
-    GuiImplT* Gui=CheckParams(LuaState);​ 
- 
-    Gui->​IsActive=false;​ 
-    return 0; 
-} 
- 
- 
-int GuiImplT::​SetInteractive(lua_State* LuaState) 
-{ 
-    GuiImplT* Gui=CheckParams(LuaState);​ 
- 
-    // I also want to treat the number 0 as false, not just "​false"​ and "​nil"​. 
-    if (lua_isnumber(LuaState,​ 2)) Gui->​IsInteractive=lua_tointeger(LuaState,​ 2)!=0; 
-                              else Gui->​IsInteractive=lua_toboolean(LuaState,​ 2)!=0; 
- 
-    return 0; 
-} 
- 
- 
-int GuiImplT::​SetFullCover(lua_State* LuaState) 
-{ 
-    GuiImplT* Gui=CheckParams(LuaState);​ 
- 
-    // I also want to treat the number 0 as false, not just "​false"​ and "​nil"​. 
-    if (lua_isnumber(LuaState,​ 2)) Gui->​IsFullCover=lua_tointeger(LuaState,​ 2)!=0; 
-                              else Gui->​IsFullCover=lua_toboolean(LuaState,​ 2)!=0; 
- 
-    return 0; 
-} 
- 
- 
-int GuiImplT::​SetMousePos(lua_State* LuaState) 
-{ 
-    GuiImplT* Gui=CheckParams(LuaState);​ 
- 
-    Gui->​SetMousePos(float(lua_tonumber(LuaState,​ 2)), 
-                     ​float(lua_tonumber(LuaState,​ 3))); 
- 
-    return 0; 
-} 
- 
- 
-int GuiImplT::​SetMouseIsShown(lua_State* LuaState) 
-{ 
-    GuiImplT* Gui=CheckParams(LuaState);​ 
- 
-    // I also want to treat the number 0 as false, not just "​false"​ and "​nil"​. 
-    if (lua_isnumber(LuaState,​ 2)) Gui->​MouseIsShown=lua_tointeger(LuaState,​ 2)!=0; 
-                              else Gui->​MouseIsShown=lua_toboolean(LuaState,​ 2)!=0; 
- 
-    return 0; 
-} 
- 
- 
-int GuiImplT::​SetFocus(lua_State* LuaState) 
-{ 
-    GuiImplT* Gui=CheckParams(LuaState);​ 
- 
-    if (lua_isstring(LuaState,​ 2)) 
-    { 
-        Gui->​FocusWindow=Gui->​RootWindow->​Find(lua_tostring(LuaState,​ 2)); 
-    } 
-    else if (lua_istable(LuaState,​ 2)) 
-    { 
-        WindowT* Win=(WindowT*)cf::​GuiSys::​GuiImplT::​GetCheckedObjectParam(LuaState,​ 2, WindowT::​TypeInfo);​ 
- 
-        Gui->​FocusWindow=Win;​ 
-    } 
- 
-    // Note that we intentionally did *not* call the Lua OnFocusLose() or OnFocusGain() scripts, 
-    // as is done when the focus changes due to a mouse click: 
-    // the Lua code that calls this method should instead call the desired OnFocus*() script functions itself. 
-    // This behaviour must be explicitly stated in the user documentation! 
-    return 0; 
-} 
- 
- 
-int GuiImplT::​GetEntityName(lua_State* LuaState) 
-{ 
-    GuiImplT* Gui=CheckParams(LuaState);​ 
- 
-    lua_pushstring(LuaState,​ Gui->​EntityName.c_str());​ 
-    return 1; 
-} 
- 
- 
-int GuiImplT::​SetRootWindow(lua_State* LuaState) 
-{ 
-    GuiImplT* Gui=CheckParams(LuaState);​ 
-    WindowT* ​ Win=(WindowT*)cf::​GuiSys::​GuiImplT::​GetCheckedObjectParam(LuaState,​ 2, WindowT::​TypeInfo);​ 
- 
-    // Note that Gui->​RootWindow is a WindowPtrT that makes sure that the Win instance gets 
-    // properly anchored in the Lua state in order to prevent premature garbage collection. 
-    Gui->​RootWindow=Win;​ 
-    return 0; 
-} 
- 
- 
-void GuiImplT::​RegisterLua(lua_State* LuaState) 
-{ 
-    // Create a new table T and add it into the registry table with "​cf::​GuiSys::​GuiT"​ as the key and T as the value. 
-    // This also leaves T on top of the stack. See PiL2 chapter 28.2 for more details. 
-    luaL_newmetatable(LuaState,​ "​cf::​GuiSys::​GuiT"​);​ 
- 
-    // See PiL2 chapter 28.3 for a great explanation on what is going on here. 
-    // Essentially,​ we set T.__index = T (the luaL_newmetatable() function left T on the top of the stack). 
-    lua_pushvalue(LuaState,​ -1);                // Pushes/​duplicates the new table T on the stack. 
-    lua_setfield(LuaState,​ -2, "​__index"​); ​     // T.__index = T; 
- 
-    static const luaL_reg GuiMethods[]= 
-    { 
-        { "​activate", ​      ​Activate }, 
-        { "​close", ​         Close }, 
-        { "​setInteractive",​ SetInteractive }, 
-        { "​setFullCover", ​  ​SetFullCover }, 
-        { "​setMousePos", ​   SetMousePos }, 
-        { "​setMouseMat", ​   SetMouseMat }, 
-        { "​showMouse", ​     SetMouseIsShown }, 
-        { "​setFocus", ​      ​SetFocus }, 
-        { "​hasValidEntity",​ HasValidEntity }, 
-        { "​getEntityName", ​ GetEntityName }, 
-        { "​SetRootWindow", ​ SetRootWindow }, 
-        { "​new", ​           CreateNewWindow }, 
-        { "​FindWindow", ​    ​FindWindow }, 
-        { "​thread", ​        ​RegisterThread }, 
-        { "​__tostring", ​    ​toString }, 
-        { NULL, NULL } 
-    }; 
- 
-    // Now insert the functions listed in GuiMethods into T (the table on top of the stack). 
-    luaL_register(LuaState,​ NULL, GuiMethods);​ 
- 
-    // Clear the stack. 
-    lua_settop(LuaState,​ 0); 
-} 
-</​code>​ 
- 
- 
-===== Libs/​MaterialSystem/​RendererCgARB1/​Shaders/​A_Diff_Light_Norm.cpp ===== 
- 
-This file is part of the Ca3DE Renderer DLL that uses NVidias "​Cg"​ GPU programming language for vertex and pixel shaders. In this case, meshes with diffuse-maps,​ light-maps, normal-maps and optionally specular-maps are rendered. 
- 
-<code cpp> 
-#include <​GL/​gl.h>​ 
-#include <​Cg/​cg.h>​ 
-#include <​Cg/​cgGL.h>​ 
- 
-#include "​../​../​Common/​OpenGLState.hpp"​ 
-#include "​../​../​Mesh.hpp"​ 
-#include "​../​RendererImpl.hpp"​ 
-#include "​../​RenderMaterial.hpp"​ 
-#include "​../​Shader.hpp"​ 
-#include "​../​TextureMapImpl.hpp"​ 
- 
- 
-using namespace MatSys; 
- 
- 
-class Shader_A_Diff_Light_Norm : public ShaderT 
-{ 
-    private: 
- 
-    CGprogram ​    ​VertexShader;​ 
-    CGparameter ​  ​VS_EyePos;​ 
-    CGprogram ​    ​FragmentShader;​ 
- 
-    unsigned long InitCounter;​ 
- 
- 
-    void Initialize() 
-    { 
-        VertexShader=UploadCgProgram(RendererImplT::​GetInstance().GetCgContext(),​ CG_PROFILE_ARBVP1,​ 
-            " void main(in float4 InPos            : POSITION, ​     \n" 
-            " ​          in float3 InNormal ​        : NORMAL, ​       \n" 
-            " ​          in float3 InTangent ​       : TANGENT, ​      ​\n"​ 
-            " ​          in float3 InBiNormal ​      : BINORMAL, ​     \n" 
-            " ​          in float4 InColor ​         : COLOR, ​        ​\n"​ 
-            " ​          in float2 InTexCoord_Diff ​ : TEXCOORD0, ​    ​\n"​ 
-            " ​          in float2 InTexCoord_LiMa ​ : TEXCOORD1, ​    ​\n"​ 
-            " ​         out float4 OutPos ​          : POSITION, ​     \n" 
-            " ​         out float4 OutColor ​        : COLOR, ​        ​\n"​ 
-            " ​         out float2 OutTexCoord_Diff : TEXCOORD0, ​    ​\n"​ 
-            " ​         out float2 OutTexCoord_LiMa : TEXCOORD1, ​    ​\n"​ 
-            " ​         out float3 OutEyeDir ​       : TEXCOORD2, ​    ​\n"​ 
-            " ​     uniform float3 EyePos) ​                          ​\n"​ 
-            " {                                                     ​\n"​ 
-            " ​    const float3x3 RotMat=float3x3(InTangent, ​        ​\n"​ 
-            " ​                                   InBiNormal, ​       \n" 
-            " ​                                   InNormal); ​        ​\n"​ 
-            " ​                                                      ​\n"​ 
-            " ​    ​OutPos ​         =mul(glstate.matrix.mvp,​ InPos); ​ \n" 
-            " ​    ​OutColor ​       =InColor; ​                        ​\n"​ 
-            " ​    ​OutTexCoord_Diff=InTexCoord_Diff; ​                ​\n"​ 
-            " ​    ​OutTexCoord_LiMa=InTexCoord_LiMa; ​                ​\n"​ 
-            " ​    ​OutEyeDir ​      ​=mul(RotMat,​ EyePos-InPos.xyz); ​  ​\n"​ 
-            " }                                                     ​\n"​);​ 
- 
-        VS_EyePos=cgGetNamedParameter(VertexShader,​ "​EyePos"​);​ 
- 
- 
-        FragmentShader=UploadCgProgram(RendererImplT::​GetInstance().GetCgContext(),​ CG_PROFILE_ARBFP1,​ 
-            " void main(in half4    InColor ​          : COLOR, ​                                         \n" 
-            " ​          in half2    InTexCoord_Diff ​  : TEXCOORD0, ​                                     \n" 
-            " ​          in half2    InTexCoord_LiMa ​  : TEXCOORD1, ​                                     \n" 
-            " ​          in half3    EyeDir ​           : TEXCOORD2, ​                                     \n" 
-            " ​         out half4    OutColor ​         : COLOR, ​                                         \n" 
-            " ​     uniform sampler2D DiffuseMapSampler ​ : TEXUNIT0, ​                                    ​\n"​ 
-            " ​     uniform sampler2D LightMapSampler ​   : TEXUNIT1, ​                                    ​\n"​ 
-            " ​     uniform sampler2D LightDirMapSampler : TEXUNIT2, ​                                    ​\n"​ 
-            " ​     uniform sampler2D NormalMapSampler ​  : TEXUNIT3, ​                                    ​\n"​ 
-            " ​     uniform sampler2D SpecMapSampler ​    : TEXUNIT4) ​                                    ​\n"​ 
-            " {                                                                                         ​\n"​ 
-            " ​    const half4 DiffuseC ​   =     ​tex2D(DiffuseMapSampler, ​ InTexCoord_Diff); ​            ​\n"​ 
-            " ​    const half4 SpecularC ​  ​= ​    ​tex2D(SpecMapSampler, ​    ​InTexCoord_Diff); ​            ​\n"​ 
-            " ​    const half4 LightMapC ​  ​= ​    ​tex2D(LightMapSampler, ​   InTexCoord_LiMa); ​            ​\n"​ 
-            " ​    const half4 LightMapDirC= ​    ​tex2D(LightDirMapSampler,​ InTexCoord_LiMa); ​            ​\n"​ 
-            " ​    const half3 LightMapDir =2.0*(LightMapDirC.xyz-0.5); ​                                 \n" 
-            " ​    const half3 Normal ​     =2.0*(tex2D(NormalMapSampler, ​  ​InTexCoord_Diff).xyz-0.5); ​   \n" 
-            " ​                                                                                          ​\n"​ 
-            " ​    const half3 HalfwayDir =normalize(normalize(EyeDir)+LightMapDir); ​                    ​\n"​ 
-            " ​                                                                                          ​\n"​ 
-            " ​    const half4 diff       ​=half4(saturate(dot(LightMapDir,​ Normal)).xxx,​ 1.0);           ​\n"​ 
-            " ​    const half4 spec       ​=half4(pow(saturate(dot(HalfwayDir,​ Normal)), 32.0).xxx, 0.0); \n" 
-            " ​                                                                                          ​\n"​ 
-            " ​    const half4 LightMapCorrectedC=half4(LightMapC.xyz/​LightMapDirC.w,​ 1.0);              \n" 
-            " ​                                                                                          ​\n"​ 
-            " ​    ​OutColor=LightMapCorrectedC*InColor*(diff*DiffuseC + spec*SpecularC); ​                ​\n"​ 
-            " }                                                                                         ​\n"​);​ 
-    } 
- 
- 
-    public: 
- 
-    Shader_A_Diff_Light_Norm() 
-    { 
-        VertexShader ​ =NULL; 
-        VS_EyePos ​    ​=NULL;​ 
-        FragmentShader=NULL;​ 
- 
-        InitCounter=0;​ 
-    } 
- 
-    const std::​string&​ GetName() const 
-    { 
-        static const std::string Name="​A_Diff_Light_Norm";​ 
- 
-        return Name; 
-    } 
- 
-    char CanHandleAmbient(const MaterialT&​ Material) const 
-    { 
-        if (Material.NoDraw) return 0; 
- 
-        if ( Material.DiffMapComp .IsEmpty()) return 0; 
-        if ( Material.LightMapComp.IsEmpty()) return 0; 
-        if ( Material.NormMapComp .IsEmpty()) return 0; 
-        if (!Material.LumaMapComp .IsEmpty()) return 0; 
- 
-        return 255; 
-    } 
- 
-    char CanHandleLighting(const MaterialT&​ /​*Material*/​) const 
-    { 
-        return 0; 
-    } 
- 
-    bool CanHandleStencilShadowVolumes() const 
-    { 
-        return false; 
-    } 
- 
-    void Activate() 
-    { 
-        if (InitCounter<​RendererImplT::​GetInstance().GetInitCounter()) 
-        { 
-            Initialize();​ 
-            InitCounter=RendererImplT::​GetInstance().GetInitCounter();​ 
-        } 
- 
-        // These are very expensive calls! 
-        cgGLBindProgram(VertexShader);​ 
-        cgGLBindProgram(FragmentShader);​ 
-    } 
- 
-    void Deactivate() 
-    { 
-    } 
- 
-    bool NeedsNormals() const 
-    { 
-        return false; 
-    } 
- 
-    bool NeedsTangentSpace() const 
-    { 
-        return false; 
-    } 
- 
-    bool NeedsXYAttrib() const 
-    { 
-        return false; 
-    } 
- 
-    void RenderMesh(const MeshT& Mesh) 
-    { 
-        const RendererImplT& ​        ​Renderer ​  ​=RendererImplT::​GetInstance();​ 
-        RenderMaterialT* ​            ​RM ​        ​=Renderer.GetCurrentRenderMaterial();​ 
-        const MaterialT& ​            ​Material ​  ​=*(RM->​Material);​ 
-        const ExpressionT::​SymbolsT&​ Sym        =Renderer.GetExpressionSymbols();​ 
-        OpenGLStateT* ​               OpenGLState=OpenGLStateT::​GetInstance();​ 
-        const float* ​                ​EyePos ​    ​=Renderer.GetCurrentEyePosition();​ 
- 
-        const float AlphaTestValue=Material.AlphaTestValue.Evaluate(Sym).GetAsFloat();​ 
-        const float RedValue ​     =Material.RedGen ​       .Evaluate(Sym).GetAsFloat();​ 
-        const float GreenValue ​   =Material.GreenGen ​     .Evaluate(Sym).GetAsFloat();​ 
-        const float BlueValue ​    ​=Material.BlueGen ​      ​.Evaluate(Sym).GetAsFloat();​ 
-        const float AlphaValue ​   =Material.AlphaGen ​     .Evaluate(Sym).GetAsFloat();​ 
- 
-        if (InitCounter<​Renderer.GetInitCounter()) 
-        { 
-            Initialize();​ 
-            InitCounter=Renderer.GetInitCounter();​ 
-        } 
- 
- 
-        // Render the diffuse map. 
-        if (AlphaTestValue>​=0.0) 
-        { 
-            OpenGLState->​Enable(GL_ALPHA_TEST);​ 
-            OpenGLState->​AlphaFunc(GL_GREATER,​ AlphaTestValue);​ 
-        } 
-        else OpenGLState->​Disable(GL_ALPHA_TEST);​ 
- 
-        if (Material.BlendFactorSrc!=MaterialT::​None /​*&&​ Material.BlendFactorDst!=MaterialT::​None*/​) 
-        { 
-            OpenGLState->​Enable(GL_BLEND);​ 
-            OpenGLState->​BlendFunc(OpenGLStateT::​BlendFactorToOpenGL[Material.BlendFactorSrc],​ OpenGLStateT::​BlendFactorToOpenGL[Material.BlendFactorDst]);​ 
-        } 
-        else OpenGLState->​Disable(GL_BLEND);​ 
- 
-        if (!Material.TwoSided) 
-        { 
-            OpenGLState->​Enable(GL_CULL_FACE);​ 
-            OpenGLState->​FrontFace(OpenGLStateT::​WindingToOpenGL[Mesh.Winding]);​ 
-            OpenGLState->​CullFace(GL_BACK);​ 
-        } 
-        else OpenGLState->​Disable(GL_CULL_FACE);​ 
- 
-        if (Material.DepthOffset!=0.0f) 
-        { 
-            OpenGLState->​Enable(OpenGLStateT::​PolygonModeToOpenGL_Offset[Material.PolygonMode]);​ 
-            OpenGLState->​PolygonOffset(Material.DepthOffset,​ Material.DepthOffset);​ 
-        } 
-        else OpenGLState->​Disable(OpenGLStateT::​PolygonModeToOpenGL_Offset[Material.PolygonMode]);​ 
- 
-        OpenGLState->​PolygonMode(OpenGLStateT::​PolygonModeToOpenGL[Material.PolygonMode]);​ 
-        OpenGLState->​DepthFunc(GL_LEQUAL);​ 
-        OpenGLState->​ColorMask(Material.AmbientMask[0],​ Material.AmbientMask[1],​ Material.AmbientMask[2],​ Material.AmbientMask[3]);​ 
-        OpenGLState->​DepthMask(Material.AmbientMask[4]);​ 
-        OpenGLState->​Disable(GL_STENCIL_TEST);​ 
-        if (cf::​GL_EXT_stencil_two_side_AVAIL) 
-        { 
-            OpenGLState->​Disable(GL_STENCIL_TEST_TWO_SIDE_EXT);​ 
-            OpenGLState->​ActiveStencilFace(GL_FRONT);​ 
-        } 
- 
-        OpenGLState->​ActiveTextureUnit(GL_TEXTURE0_ARB);​ 
-        OpenGLState->​Enable(GL_TEXTURE_2D);​ 
-        OpenGLState->​BindTexture(GL_TEXTURE_2D,​ RM->​DiffTexMap->​GetOpenGLObject());​ 
- 
-        OpenGLState->​ActiveTextureUnit(GL_TEXTURE1_ARB);​ 
-        OpenGLState->​Enable(GL_TEXTURE_2D);​ 
-        OpenGLState->​BindTexture(GL_TEXTURE_2D,​ RM->​UseDefaultLightMap && Renderer.GetCurrentLightMap()!=NULL ? Renderer.GetCurrentLightMap()->​GetOpenGLObject() : RM->​LightTexMap->​GetOpenGLObject());​ 
- 
-        OpenGLState->​ActiveTextureUnit(GL_TEXTURE2_ARB);​ 
-        OpenGLState->​Enable(GL_TEXTURE_2D);​ 
-        OpenGLState->​BindTexture(GL_TEXTURE_2D,​ RM->​UseDefaultLightMap && Renderer.GetCurrentLightDirMap()!=NULL ? Renderer.GetCurrentLightDirMap()->​GetOpenGLObject() : Renderer.GetHelperLightBlue001Map()->​GetOpenGLObject());​ 
- 
-        OpenGLState->​ActiveTextureUnit(GL_TEXTURE3_ARB);​ 
-        OpenGLState->​Enable(GL_TEXTURE_2D);​ 
-        OpenGLState->​BindTexture(GL_TEXTURE_2D,​ RM->​NormTexMap->​GetOpenGLObject());​ 
- 
-        OpenGLState->​ActiveTextureUnit(GL_TEXTURE4_ARB);​ 
-        OpenGLState->​Enable(GL_TEXTURE_2D);​ 
-        OpenGLState->​BindTexture(GL_TEXTURE_2D,​ Material.SpecMapComp.IsEmpty() ? Renderer.GetHelperBlackMap()->​GetOpenGLObject() : RM->​SpecTexMap->​GetOpenGLObject());​ 
- 
- 
-        // The cgGLSetParameter*() functions are very slow, so cache their parameters in order to call them as little as possible. 
-        static float EyePosCache[3]={ 0.0, 0.0, 0.0 }; 
-        if (EyePos[0]!=EyePosCache[0] || EyePos[1]!=EyePosCache[1] || EyePos[2]!=EyePosCache[2]) 
-        { 
-            cgGLSetParameter3fv(VS_EyePos,​ EyePos); 
-            EyePosCache[0]=EyePos[0];​ 
-            EyePosCache[1]=EyePos[1];​ 
-            EyePosCache[2]=EyePos[2];​ 
-        } 
- 
- 
-        glColor4f(RedValue,​ GreenValue, BlueValue, AlphaValue);​ 
-        glBegin(OpenGLStateT::​MeshToOpenGLType[Mesh.Type]);​ 
-            for (unsigned long VertexNr=0; VertexNr<​Mesh.Vertices.Size();​ VertexNr++) 
-            { 
-                cf::​glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,​ Mesh.Vertices[VertexNr].TextureCoord);​ 
-                cf::​glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,​ Mesh.Vertices[VertexNr].LightMapCoord);​ 
- 
-                glNormal3fv(Mesh.Vertices[VertexNr].Normal); ​                                   // Normal 
-                cf::​glMultiTexCoord3fvARB(GL_TEXTURE6_ARB,​ Mesh.Vertices[VertexNr].Tangent); ​   // Tangent 
-                cf::​glMultiTexCoord3fvARB(GL_TEXTURE7_ARB,​ Mesh.Vertices[VertexNr].BiNormal); ​  // BiNormal 
- 
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);​ 
-            } 
-        glEnd(); 
-    } 
-}; 
- 
- 
-// The constructor of the base class automatically registers this shader with the ShaderRepository. 
-static Shader_A_Diff_Light_Norm MyShader; 
-</​code>​ 
- 
- 
-===== Ca3D-Engine/​Ca3DE/​Client/​Client.cpp ===== 
- 
-This file is part of the Ca3DE game client. The client is implemented with the [[wp>​State|"​State"​ code design pattern]]. The state management and some console functions for changing the client state are implemented in this file. 
- 
-<code cpp> 
-#include "​Client.hpp"​ 
-#include "​ClientStateConnecting.hpp"​ 
-#include "​ClientStateIdle.hpp"​ 
-#include "​ClientStateInGame.hpp"​ 
- 
-#include "​ConsoleCommands/​Console.hpp"​ 
-#include "​ConsoleCommands/​ConFunc.hpp"​ 
-#include "​ConsoleCommands/​ConVar.hpp"​ 
-#include "​GuiSys/​Gui.hpp"​ 
-#include "​../​../​Common/​h/​NetConst.hpp"​ 
- 
-extern "​C"​ 
-{ 
-    #include <​lua.h>​ 
-    #include <​lualib.h>​ 
-    #include <​lauxlib.h>​ 
-} 
- 
- 
-static const char* StateNames[]={ "​idle",​ "​connecting",​ "​ingame"​ }; 
-static ClientT* ​   ClientPtr ​  ​=NULL;​ 
- 
- 
-ClientT::​ClientT() 
-    : CurrentState(NULL),​ 
-      NextState(IDLE),​ 
-      Socket(INVALID_SOCKET),​ 
-      ServerAddress(0,​ 0, 0, 0, 0), 
-      PacketIDConnLess(0),​ 
-      MainMenuGui(NULL) 
-{ 
-    // Cannot do this directly in the initializer list above, because then the 
-    // ClientStateIdleT ctor would try to access the not yet initialized client ("​this"​). 
-    CurrentState=new ClientStateIdleT(*this);​ 
- 
-    assert(ClientPtr==NULL);​ 
-    ClientPtr=this;​ 
-} 
- 
- 
-ClientT::​~ClientT() 
-{ 
-    if (Socket!=INVALID_SOCKET) closesocket(Socket);​ 
- 
-    delete CurrentState;​ 
- 
-    assert(ClientPtr==this);​ 
-    ClientPtr=NULL;​ 
-} 
- 
- 
-void ClientT::​SetMainMenuGui(cf::​GuiSys::​GuiI* MainMenuGui_) 
-{ 
-    MainMenuGui=MainMenuGui_;​ 
- 
-    MainMenuGui->​CallLuaFunc("​OnClientStateChanged",​ "​s",​ StateNames[GetStateID()]);​ 
-} 
- 
- 
-bool ClientT::​ProcessInputEvent(const CaKeyboardEventT&​ KE) 
-{ 
-    UpdateCurrentState();​ 
-    return CurrentState->​ProcessInputEvent(KE);​ 
-} 
- 
- 
-bool ClientT::​ProcessInputEvent(const CaMouseEventT&​ ME) 
-{ 
-    UpdateCurrentState();​ 
-    return CurrentState->​ProcessInputEvent(ME);​ 
-} 
- 
- 
-void ClientT::​Render(float FrameTime) 
-{ 
-    UpdateCurrentState();​ 
-    CurrentState->​Render(FrameTime);​ 
-} 
- 
- 
-void ClientT::​MainLoop(float FrameTime) 
-{ 
-    UpdateCurrentState();​ 
-    CurrentState->​MainLoop(FrameTime);​ 
-} 
- 
- 
-ClientT::​StateIDT ClientT::​GetStateID() const 
-{ 
-    assert(CurrentState!=NULL);​ 
- 
-    return (StateIDT)CurrentState->​GetID();​ 
-} 
- 
- 
-// Some notes about changing the state (CurrentState) of the client: 
-// The state is usually changed from within another state by using a statement like: Client.NextState=IDLE;​ 
-// The client will then make a state instance with ID NextState the CurrentState before the next call to any method of CurrentState. 
-// The advantage of handling state changes like this is that the ctors and dtors of the states are properly run, that is, 
-// the state that is left is properly destructed by its dtor and then the state that is entered is properly constructed by its ctor, 
-// in this order. This is obviously good for the reliable management of (shared) resources. 
-// Moreover, the callers don't need to really "​know"​ the other state classes, i.e. no need for all those #​include'​s everywhere. 
-// Before that, I kept all the states as member objects as private members here, and had CurrentState point to one of them. 
-// That was nice and simple, but required *very* ugly OnEnter() and OnLeave() methods for the resource management, 
-// so that I rather changed to this solution that is slightly more complex but properly employs the ctors and dtors. 
-void ClientT::​UpdateCurrentState() 
-{ 
-    if (GetStateID()!=NextState) 
-    { 
-        // Delete the CurrentState first, then allocate the new state. 
-        // This makes sure that the dtor of the current state is run before the ctor of the next. 
-        delete CurrentState;​ 
- 
-        switch (NextState) 
-        { 
-            case IDLE:       ​CurrentState=new ClientStateIdleT(*this);​ break; 
-            case CONNECTING: CurrentState=new ClientStateConnectingT(*this);​ break; 
-            case INGAME: ​    ​CurrentState=new ClientStateInGameT(*this);​ break; 
-        } 
- 
-        MainMenuGui->​CallLuaFunc("​OnClientStateChanged",​ "​s",​ StateNames[NextState]);​ 
-    } 
- 
-    assert(GetStateID()==NextState);​ 
-} 
- 
- 
-static ConVarT ClientRCPassword("​cl_rc_password",​ "",​ ConVarT::​FLAG_MAIN_EXE,​ "The password with which the client sends remote console commands to the server."​);​ 
- 
- 
-// IMPORTANT NOTE: 
-// This function is actually UNRELATED to the game client, because it's more generic: 
-// It can also be used when the client is disconnected (idle). 
-int ClientT::​ConFunc_rcon_Callback(lua_State* LuaState) 
-{ 
-    if (!ClientPtr) return 0; 
- 
-    // Die Antwort auf ein "​connection-less"​ Packet beginnt mit 0xFFFFFFFF, gefolgt von der PacketID, 
-    // sodaรŸ das Rรผckpacket unten nur noch individuell beendet werden muรŸ. 
-    NetDataT OutData; 
- 
-    OutData.WriteLong(0xFFFFFFFF);​ 
-    OutData.WriteLong(ClientPtr->​PacketIDConnLess++);​ 
-    OutData.WriteByte(CS0_RemoteConsoleCommand);​ 
-    OutData.WriteString(ClientRCPassword.GetValueString());​ 
-    OutData.WriteString(luaL_checkstring(LuaState,​ 1)); 
- 
-    try 
-    { 
-        OutData.Send(ClientPtr->​Socket,​ ClientPtr->​ServerAddress);​ 
-    } 
-    catch (const NetDataT::​WinSockAPIError&​ E) { Console->​Print(cf::​va("​Send failed (WSA error %u)!\n",​ E.Error)); } 
-    catch (const NetDataT::​MessageLength& ​  E) { Console->​Print(cf::​va("​Message too long (wanted %u, actual %u)!\n",​ E.Wanted, E.Actual)); } 
- 
-    return 0; 
-} 
- 
-static ConFuncT ConFunc_rcon("​rcon",​ ClientT::​ConFunc_rcon_Callback,​ ConFuncT::​FLAG_MAIN_EXE,​ "Sends a command to the remote console, e.g.   ​rcon(\"​changeLevel('<​MapName>'​)\"​)"​);​ 
- 
- 
-int ClientT::​ConFunc_connect_Callback(lua_State* LuaState) 
-{ 
-    if (!ClientPtr) return luaL_error(LuaState,​ "The client instance is not available.\n"​);​ 
- 
-    switch (ClientPtr->​GetStateID()) 
-    { 
-        case IDLE: 
-        { 
-            const char* ServerName=luaL_checkstring(LuaState,​ 1); 
-            const int   ​ServerPort=luaL_checkint(LuaState,​ 2); 
- 
-            try 
-            { 
-                // Must set the ServerAddress member before changing into connecting state. 
-                ClientPtr->​ServerAddress=NetAddressT(ServerName,​ ServerPort);​ 
-            } 
-            catch (const NetAddressT::​BadHostName&​ /*E*/) 
-            { 
-                return luaL_error(LuaState,​ "​Unable to resolve server name \"​%s\"​.\n",​ ServerName);​ 
-            } 
- 
-            // Ok, connect to the server. 
-            ClientPtr->​NextState=CONNECTING;​ 
-            return 0; 
-        } 
- 
-        case CONNECTING: return luaL_error(LuaState,​ "The client is already connecting...\n"​);​ 
-        case INGAME: ​    ​return luaL_error(LuaState,​ "The client is already connected.\n"​);​ 
-    } 
- 
-    return luaL_error(LuaState,​ "The client is in an unknown state.\n"​);​ 
-} 
- 
-static ConFuncT ConFunc_connect("​connect",​ ClientT::​ConFunc_connect_Callback,​ ConFuncT::​FLAG_MAIN_EXE,​ "​Connects the client to the server."​);​ 
- 
- 
-int ClientT::​ConFunc_disconnect_Callback(lua_State* LuaState) 
-{ 
-    if (!ClientPtr) return luaL_error(LuaState,​ "The client instance is not available.\n"​);​ 
- 
-    switch (ClientPtr->​GetStateID()) 
-    { 
-        case IDLE:       ​return luaL_error(LuaState,​ "The client is not connected.\n"​);​ 
-        case CONNECTING: ClientPtr->​NextState=IDLE;​ return 0;     // Abort connection attempt (premature timeout). 
-        case INGAME: ​    ​ClientPtr->​NextState=IDLE;​ return 0;     // Ok, disconnect from server. 
-    } 
- 
-    return luaL_error(LuaState,​ "The client is in an unknown state.\n"​);​ 
-} 
- 
-static ConFuncT ConFunc_disconnect("​disconnect",​ ClientT::​ConFunc_disconnect_Callback,​ ConFuncT::​FLAG_MAIN_EXE,​ "​Disconnects the client from the server."​);​ 
-</​code>​ 
- 
- 
-===== Ca3D-Engine/​CaWE/​DialogTerrainEdit.cpp ===== 
- 
-This file is part of CaWE, the Ca3DE World Editor. It implements the "Edit Terrain"​ dialog. 
- 
-<code cpp> 
-#include "​DialogTerrainEdit.hpp"​ 
- 
-#include "​MapDocument.hpp"​ 
-#include "​GameConfig.hpp"​ 
-#include "​ChildFrame.hpp"​ 
-#include "​ToolManager.hpp"​ 
-#include "​ToolTerrainEdit.hpp"​ 
-#include "​DialogTerrainGeneration.hpp"​ 
- 
-#include "​wx/​filedlg.h"​ 
- 
- 
-TerrainEditorDialogT::​TerrainEditorDialogT(wxWindow* Parent, MapDocumentT* MapDoc, ToolTerrainEditorT* ParentTool) 
-    : TerrainEditorDialogFB(Parent),​ 
-      m_MapDoc(MapDoc),​ 
-      m_ParentTool(ParentTool),​ 
-      m_TerrainGenerationDialog(new TerrainGenerationDialogT(this)) 
-{ 
-    m_ToolBar->​ToggleTool(ID_TOOL_RAISE,​ true); 
- 
-    // Notify the parent tool that this is its dialog. 
-    m_ParentTool->​SetToolDialog(this);​ 
-} 
- 
- 
-void TerrainEditorDialogT::​UpdateResolution(unsigned long Resolution) 
-{ 
-    int ResSelection=m_ChoiceResolution->​FindString(wxString::​Format("​%lux%lu",​ Resolution, Resolution),​ true); 
- 
-    if (ResSelection==wxNOT_FOUND) 
-        ResSelection=m_ChoiceResolution->​Append(wxString::​Format("​%lux%lu",​ Resolution, Resolution));​ 
- 
-    m_ChoiceResolution->​Select(ResSelection);​ 
-} 
- 
- 
-int TerrainEditorDialogT::​GetActiveTool() const 
-{ 
-    if (m_ToolBar->​GetToolState(TerrainEditorDialogT::​ID_TOOL_RAISE ​ )) return ID_TOOL_RAISE;​ 
-    if (m_ToolBar->​GetToolState(TerrainEditorDialogT::​ID_TOOL_LOWER ​ )) return ID_TOOL_LOWER;​ 
-    if (m_ToolBar->​GetToolState(TerrainEditorDialogT::​ID_TOOL_FLATTEN)) return ID_TOOL_FLATTEN;​ 
-    if (m_ToolBar->​GetToolState(TerrainEditorDialogT::​ID_TOOL_FILL ​  )) return ID_TOOL_FILL;​ 
-    if (m_ToolBar->​GetToolState(TerrainEditorDialogT::​ID_TOOL_ABLATE )) return ID_TOOL_ABLATE;​ 
-    if (m_ToolBar->​GetToolState(TerrainEditorDialogT::​ID_TOOL_BLUR ​  )) return ID_TOOL_BLUR;​ 
-    if (m_ToolBar->​GetToolState(TerrainEditorDialogT::​ID_TOOL_SHARPEN)) return ID_TOOL_SHARPEN;​ 
-    if (m_ToolBar->​GetToolState(TerrainEditorDialogT::​ID_TOOL_NOISE ​ )) return ID_TOOL_NOISE;​ 
-    if (m_ToolBar->​GetToolState(TerrainEditorDialogT::​ID_TOOL_ROAD ​  )) return ID_TOOL_ROAD;​ 
- 
-    return -1; 
-} 
- 
- 
-bool TerrainEditorDialogT::​OnMMouseUp() 
-{ 
-    wxCommandEvent Event; 
- 
-    if (m_ToolBar->​GetToolState(TerrainEditorDialogT::​ID_TOOL_RAISE)) 
-    { 
-        Event.SetId(ID_TOOL_LOWER);​ 
-        OnToolClicked(Event);​ 
-        return true; 
-    } 
-    if (m_ToolBar->​GetToolState(TerrainEditorDialogT::​ID_TOOL_LOWER)) 
-    { 
-        Event.SetId(ID_TOOL_RAISE);​ 
-        OnToolClicked(Event);​ 
-        return true; 
-    } 
- 
-    return false; 
-} 
- 
- 
-void TerrainEditorDialogT::​OnToolClicked(wxCommandEvent&​ event) 
-{ 
-    // Reactivate "Tool effect"​ controls in case they were disabled. 
-    m_SpinCtrlToolEffect->​Enable();​ 
-    m_SliderToolEffect->​Enable();​ 
- 
-    m_ToolBar->​ToggleTool(ID_TOOL_RAISE, ​  ​false);​ 
-    m_ToolBar->​ToggleTool(ID_TOOL_LOWER, ​  ​false);​ 
-    m_ToolBar->​ToggleTool(ID_TOOL_FLATTEN,​ false); 
-    m_ToolBar->​ToggleTool(ID_TOOL_FILL, ​   false); 
-    m_ToolBar->​ToggleTool(ID_TOOL_ABLATE, ​ false); 
-    m_ToolBar->​ToggleTool(ID_TOOL_BLUR, ​   false); 
-    m_ToolBar->​ToggleTool(ID_TOOL_SHARPEN,​ false); 
-    m_ToolBar->​ToggleTool(ID_TOOL_NOISE, ​  ​false);​ 
-    m_ToolBar->​ToggleTool(ID_TOOL_ROAD, ​  ​false);​ 
- 
-    m_ToolBar->​ToggleTool(event.GetId(),​ true); 
- 
-    // Disable "Tool effect"​ controls for tools that don't use it. 
-    if (event.GetId()==ID_TOOL_FLATTEN || event.GetId()==ID_TOOL_FILL || event.GetId()==ID_TOOL_ABLATE || event.GetId()==ID_TOOL_ROAD) 
-    { 
-        m_SpinCtrlToolEffect->​Enable(false);​ 
-        m_SliderToolEffect->​Enable(false);​ 
-    } 
-} 
- 
- 
-void TerrainEditorDialogT::​OnSpinCtrlRadius(wxSpinEvent&​ event) 
-{ 
-    m_SliderRadius->​SetValue(event.GetPosition());​ 
- 
-    m_ParentTool->​UpdateModifyWeights();​ 
-    m_ParentTool->​UpdateNoiseWeights (); 
-} 
- 
- 
-void TerrainEditorDialogT::​OnSliderScrollRadius(wxScrollEvent&​ event) 
-{ 
-    m_SpinCtrlRadius->​SetValue(event.GetPosition());​ 
- 
-    m_ParentTool->​UpdateModifyWeights();​ 
-    m_ParentTool->​UpdateNoiseWeights (); 
-} 
- 
- 
-void TerrainEditorDialogT::​OnSpinCtrlHardness(wxSpinEvent&​ event) 
-{ 
-    m_SliderHardness->​SetValue(event.GetPosition());​ 
- 
-    m_ParentTool->​UpdateModifyWeights();​ 
-} 
- 
- 
-void TerrainEditorDialogT::​OnSliderScrollHardness(wxScrollEvent&​ event) 
-{ 
-    m_SpinCtrlHardness->​SetValue(event.GetPosition());​ 
- 
-    m_ParentTool->​UpdateModifyWeights();​ 
-} 
- 
- 
-void TerrainEditorDialogT::​OnSpinCtrlToolEffect(wxSpinEvent&​ event) 
-{ 
-    m_SliderToolEffect->​SetValue(event.GetPosition());​ 
- 
-    m_ParentTool->​UpdateGaussWeights();​ 
-} 
- 
- 
-void TerrainEditorDialogT::​OnSliderScrollToolEffect(wxScrollEvent&​ event) 
-{ 
-    m_SpinCtrlToolEffect->​SetValue(event.GetPosition());​ 
- 
-    m_ParentTool->​UpdateGaussWeights();​ 
-} 
- 
- 
-void TerrainEditorDialogT::​OnChoiceResolution(wxCommandEvent&​ event) 
-{ 
-    wxASSERT(m_ChoiceResolution->​GetSelection()!=wxNOT_FOUND);​ 
- 
-    // First translate choice selection into resolution. 
-    unsigned long ChoiceResolution=(1<<​(m_ChoiceResolution->​GetSelection()+6))+1;​ 
- 
-    m_ParentTool->​SetResolution(ChoiceResolution);​ 
-} 
- 
- 
-void TerrainEditorDialogT::​OnButtonImport(wxCommandEvent&​ event) 
-{ 
-    if (!m_ParentTool->​IsTerrainSelected()) 
-    { 
-        wxMessageBox("​You can only import height data into a selected terrain.",​ "No terrain selected"​);​ 
-        return; 
-    } 
- 
-    wxString HeightmapNameStr=wxFileSelector("​Select a heightmap image",​ m_MapDoc->​GetGameConfig()->​ModDir+"/​Terrains/",​ "",​ "",​ "All files (*.*)|*.*",​ wxFD_OPEN | wxFD_FILE_MUST_EXIST);​ 
- 
-    if (HeightmapNameStr!=""​) 
-        m_ParentTool->​ImportHeightMap(HeightmapNameStr);​ 
-} 
- 
- 
-void TerrainEditorDialogT::​OnButtonExport(wxCommandEvent&​ event) 
-{ 
-    if (!m_ParentTool->​IsTerrainSelected()) 
-    { 
-        wxMessageBox("​You can only export height data if a terrain is selected.",​ "No terrain selected"​);​ 
-        return; 
-    } 
- 
-    wxFileDialog ExportDialog(this,​ 
-                              "​Export height data", 
-                              m_MapDoc->​GetGameConfig()->​ModDir+"/​Terrains",​ //​defaultDir 
-                              "", ​                                           //​defaultFile 
-                              "​Bitmap (*.bmp)|*.bmp"​ 
-                              "​|Portable Network Graphic (*.png)|*.png"​ 
-                              "|JPEG (*.jpg)|*.jpg"​ 
-                              "​|Portable Graymap ASCII (*.pgm)|*.pgm"​ 
-                              "​|Portable Graymap binary (*.pgm)|*.pgm"​ 
-                              "​|Terragen file (*.ter)|*.ter",​ 
-                              wxFD_SAVE | wxFD_OVERWRITE_PROMPT);​ 
- 
-    if (ExportDialog.ShowModal()!=wxID_OK) return; 
- 
-    wxString FileName=ExportDialog.GetFilename();​ 
-    ToolTerrainEditorT::​ExportFileTypeE ExportFileType=ToolTerrainEditorT::​BMP;​ 
- 
-    // Since the user can choose the filetype to be exported either by entering a filename without extension and choosing a correct filter or by entering a 
-    // filename with extension (in which case the filter setting is ignored) we need to derive the correct file type here from the extension. 
-    if (FileName.EndsWith("​.bmp"​)) 
-    { 
-       ​ExportFileType=ToolTerrainEditorT::​BMP;​ 
-    } 
-    else if (FileName.EndsWith("​.png"​)) 
-    { 
-       ​ExportFileType=ToolTerrainEditorT::​PNG;​ 
-    } 
-    else if (FileName.EndsWith("​.jpg"​)) 
-    { 
-       ​ExportFileType=ToolTerrainEditorT::​JPG;​ 
-    } 
-    else if (FileName.EndsWith("​.jpeg"​)) 
-    { 
-       ​ExportFileType=ToolTerrainEditorT::​JPG;​ 
-    } 
-    else if (FileName.EndsWith("​.pgm"​)) 
-    { 
-       ​switch (ExportDialog.GetFilterIndex()) 
-       { 
-           case 3: //ASCII 
-               ​ExportFileType=ToolTerrainEditorT::​PGM_ASCII;​ 
-               ​break;​ 
-           case 4: //BINARY 
-               ​ExportFileType=ToolTerrainEditorT::​PGM_BINARY;​ 
-               ​break;​ 
-           ​default:​ 
-               ​ExportFileType=ToolTerrainEditorT::​PGM_ASCII;​ 
-               ​break;​ 
-       } 
-    } 
-    else if (FileName.EndsWith("​.ter"​)) 
-    { 
-       ​ExportFileType=ToolTerrainEditorT::​TER;​ 
-    } 
-    else 
-    { 
-       // Ignore file extension and set the file type according to filter setting. 
-       ​switch (ExportDialog.GetFilterIndex()) 
-       { 
-           case 0: 
-               ​ExportFileType=ToolTerrainEditorT::​BMP;​ 
-               ​break;​ 
-           case 1: 
-               ​ExportFileType=ToolTerrainEditorT::​PNG;​ 
-               ​break;​ 
-           case 2: 
-               ​ExportFileType=ToolTerrainEditorT::​JPG;​ 
-               ​break;​ 
-           case 3: 
-               ​ExportFileType=ToolTerrainEditorT::​PGM_ASCII;​ 
-               ​break;​ 
-           case 4: 
-               ​ExportFileType=ToolTerrainEditorT::​PGM_BINARY;​ 
-               ​break;​ 
-           case 5: 
-               ​ExportFileType=ToolTerrainEditorT::​TER;​ 
-               ​break;​ 
-       } 
-    } 
- 
-    m_ParentTool->​ExportHeightMap(ExportDialog.GetPath(),​ ExportFileType);​ 
-} 
- 
- 
-void TerrainEditorDialogT::​OnButtonGenerate(wxCommandEvent&​ event) 
-{ 
-    if (!m_ParentTool->​IsTerrainSelected()) 
-    { 
-        wxMessageBox("​You can only generate height data for a selected terrain.",​ "No terrain selected"​);​ 
-        return; 
-    } 
- 
-    if (m_TerrainGenerationDialog->​ShowModal(m_ParentTool->​GetResolution())!=wxID_OK) return; 
- 
-    m_ParentTool->​GenerateTerrain(m_TerrainGenerationDialog->​m_SpinCtrlOctaves ​   ->​GetValue(),​ 
-                                  m_TerrainGenerationDialog->​m_SpinCtrlFrequency ​ ->​GetValue(),​ 
-                                  m_TerrainGenerationDialog->​m_SpinCtrlPersistence->​GetValue(),​ 
-                                  m_TerrainGenerationDialog->​m_SpinCtrlLacunarity ->​GetValue(),​ 
-                                  m_TerrainGenerationDialog->​m_SpinCtrlSeed ​      ​->​GetValue());​ 
-} 
- 
- 
-void TerrainEditorDialogT::​OnClose(wxCloseEvent&​ event) 
-{ 
-    m_MapDoc->​GetChildFrame()->​GetToolManager().SetTool(TOOL_SELECTION);​ 
-} 
-</​code>​ 
  
licensing/samplecode.1220358512.txt.gz ยท Last modified: 2013-01-07 12:07 (external edit)