User Tools

Site Tools


Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
licensing:samplecode [2008-09-02 14:33]
Carsten Fixed link to Wikipedia wrt. State pattern
— (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_pattern|"​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.1220358809.txt.gz ยท Last modified: 2013-01-07 12:07 (external edit)