void frmMain::_onSaveMenuSave(wxCommandEvent& evt)
{
    if(m_sFilename.empty())
    {
        _onSaveMenuSaveAs(evt);
        return;
    }

    map_save_t oSave;
    if(oSave.fFile.Open(m_sFilename, wxFile::write))
    {
        lua_State* L = m_pGamePanel->getLua();
        luaT_execute(L, "return TheApp.world.map.th");
        THMap *pMap = reinterpret_cast<THMap*>(lua_touserdata(L, -1));
        lua_pop(L, 1);
        THMapWrapper::autoSetHelipad(pMap);
        luaT_execute(L, "return TheApp.ui:ScreenToWorld(...)",
            m_pGamePanel->GetSize().GetWidth() / 2,
            m_pGamePanel->GetSize().GetHeight() / 2);
        int iCameraX = (int)lua_tointeger(L, -2);
        int iCameraY = (int)lua_tointeger(L, -1);
        lua_pop(L, 2);
        pMap->setPlayerCameraTile(0, iCameraX, iCameraY);
        pMap->save(map_save_t::writer, reinterpret_cast<void*>(&oSave));
        ::wxMessageBox(wxT("Map saved."), wxT("Save"), wxOK | wxCENTER |
            wxICON_INFORMATION, this);
    }
}
int ScrollableGamePanel::_l_init_with_app(lua_State *L)
{
    // Call the original MapEditorInitWithLuaApp function
    lua_pushvalue(L, lua_upvalueindex(1));
    if(lua_type(L, -1) == LUA_TNIL)
        lua_pop(L, 1);
    else
    {
        lua_insert(L, 1);
        lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
    }

    // Wrap our _l_on_ui_scroll_map function around GameUI:scrollMap()
    // 1st upvalue: original GameUI:scrollMap() function
    // 2nd upvalue: light userdata this
    // This has to be done with the Lua App initialisation as we need for
    // dofile() to be the custom dofile() used by CorsixTH, rather than the
    // default one present at Lua initialisation time.
    luaT_execute(L, "dofile [[game_ui]]");
    lua_getglobal(L, "GameUI");
    lua_getfield(L, -1, "scrollMap");
    lua_pushvalue(L, lua_upvalueindex(2));
    lua_pushcclosure(L, _l_on_ui_scroll_map, 2);
    lua_setfield(L, -2, "scrollMap");

    return lua_gettop(L);
}
void frmMain::_applyViewOverlay()
{
    if(m_bViewFlags || m_bViewParcels)
    {
        lua_State *L = m_pGamePanel->getLua();
        luaT_execute(L, "return TheApp.gfx:loadBuiltinFont(), TheApp.map.cell_outline");
        THFont *pFont = reinterpret_cast<THFont*>(lua_touserdata(L, -2));
        THSpriteSheet *pSprites = reinterpret_cast<THSpriteSheet*>(lua_touserdata(L, -1));
        lua_pop(L, 2);

        THMapTypicalOverlay *pFlags = NULL;
        THMapTypicalOverlay *pParcels = NULL;
        if(m_bViewFlags)
        {
            pFlags = new THMapFlagsOverlay;
            pFlags->setFont(pFont, false);
            pFlags->setSprites(pSprites, false);
        }
        if(m_bViewParcels)
        {
            pParcels = new THMapParcelsOverlay;
            pParcels->setFont(pFont, false);
            pParcels->setSprites(pSprites, false);
        }
        THMapOverlayPair *pOverlays = new THMapOverlayPair;
        pOverlays->setFirst(pParcels, true);
        pOverlays->setSecond(pFlags, true);
        m_pGamePanel->getMap()->setOverlay(pOverlays, true);
    }
    else
        m_pGamePanel->getMap()->setOverlay(NULL, false);
}
int frmMain::_l_init(lua_State *L)
{
    frmMain *pThis = reinterpret_cast<frmMain*>(lua_touserdata(L, 1));

    THMapWrapper::wrap(L);

    // Create a new environment table: {
    //   [1] = <light userdata pThis>,
    // }
    lua_newtable(L);
    lua_insert(L, 1);
    lua_rawseti(L, 1, 1);
    lua_replace(L, LUA_ENVIRONINDEX);
    // NB: Following functions registered with above environment table

    luaT_execute(L, "MapEditorSetBlocks = ...", _l_set_blocks);
    luaT_execute(L, "MapEditorSetBlockBrush = ...", _l_set_block_brush);
    luaT_execute(L, "MapEditorInitWithLuaApp = ...", _l_init_with_lua_app);

    return 0;
}
Beispiel #5
0
int CorsixTH_lua_main_no_eval(lua_State *L)
{
    // assert(_VERSION == LUA_VERSION)
    size_t iLength;
    lua_getglobal(L, "_VERSION");
    const char* sVersion = lua_tolstring(L, -1, &iLength);
    if(iLength != strlen(LUA_VERSION) || strcmp(sVersion, LUA_VERSION) != 0)
    {
        lua_pushliteral(L, "Linked against a version of Lua different to the "
            "one used when compiling.\nPlease recompile CorsixTH against the "
            "same Lua version it is linked against.");
        return lua_error(L);
    }
    lua_pop(L, 1);

    // registry._CLEANUP = {}
    lua_newtable(L);
    lua_setfield(L, LUA_REGISTRYINDEX, "_CLEANUP");

    // math.random* = Mersenne twister variant
    luaT_cpcall(L, luaopen_random, NULL);

    // package.preload["jit.opt"] = load(jit_opt_lua)
    // package.preload["jit.opt_inline"] = load(jit_opt_inline_lua)
    lua_getglobal(L, "package");
    lua_getfield(L, -1, "preload");
    luaL_loadbuffer(L, (const char*)jit_opt_lua, sizeof(jit_opt_lua),
        "jit/opt.luac");
    lua_setfield(L, -2, "jit.opt");
    luaL_loadbuffer(L, (const char*)jit_opt_inline_lua,
        sizeof(jit_opt_inline_lua), "jit/opt_inline.luac");
    lua_setfield(L, -2, "jit.opt_inline");
    lua_pop(L, 2);

    // if registry._LOADED.jit then
    // require"jit.opt".start()
    // else
    // print "Notice: ..."
    // end
    // (this could be done in Lua rather than here, but ideally the optimiser
    // should be turned on before any Lua code is loaded)
    lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
    lua_getfield(L, -1, "jit");
    if(lua_type(L, -1) == LUA_TNIL)
    {
        lua_pop(L, 2);
        lua_getglobal(L, "print");
        lua_pushliteral(L, "Notice: LuaJIT not being used.\nConsider replacing"
            " Lua with LuaJIT to improve performance.");
#ifdef CORSIX_TH_64BIT
        lua_pushliteral(L, " Note that there is not currently a 64 bit version"
            " of LuaJIT.");
        lua_concat(L, 2);
#endif
        lua_call(L, 1, 0);
    }
    else
    {
        lua_pop(L, 2);
        lua_getglobal(L, "require");
        lua_pushliteral(L, "jit.opt");
        lua_call(L, 1, 1);
        lua_getfield(L, -1, "start");
        lua_call(L, 0, 0);
        lua_pop(L, 1);
    }

    // Fill in package.preload table so that calls to require("X") from Lua
    // will call the appropriate luaopen_X function in C.
#define PRELOAD(name, fn) \
    luaT_execute(L, "package.preload." name " = ...", fn)
    PRELOAD("lfs", luaopen_lfs_ext);
    PRELOAD("lpeg", luaopen_lpeg);
    PRELOAD("rnc", luaopen_rnc);
    PRELOAD("TH", luaopen_th);
    PRELOAD("ISO_FS", luaopen_iso_fs);
    PRELOAD("persist", luaopen_persist);
    PRELOAD("sdl", luaopen_sdl);
#undef PRELOAD

    // require "debug" (Harmless in Lua 5.1, useful in 5.2 for compatbility)
    luaT_execute(L, "require \"debug\"");

    // Check for --interpreter and run that instead of CorsixTH.lua
    bool bGotScriptFile = false;
    int iNArgs = lua_gettop(L);
    for(int i = 1; i <= iNArgs; ++i)
    {
        if(lua_type(L, i) == LUA_TSTRING)
        {
            size_t iLen;
            const char* sCmd = lua_tolstring(L, i, &iLen);
            if(iLen > 14 && memcmp(sCmd, "--interpreter=", 14) == 0)
            {
                lua_getglobal(L, "assert");
                lua_getglobal(L, "loadfile");
                lua_pushlstring(L, sCmd + 14, iLen - 14);
                bGotScriptFile = true;
                break;
            }
        }
    }

    // Code to try several variations on finding CorsixTH.lua:
    // CorsixTH.lua
    // CorsixTH/CorsixTH.lua
    // ../CorsixTH.lua
    // ../CorsixTH/CorsixTH.lua
    // ../../CorsixTH.lua
    // ../../CorsixTH/CorsixTH.lua
    // ../../../CorsixTH.lua
    // ../../../CorsixTH/CorsixTH.lua
    // It is simpler to write this in Lua than in C.
    const char sLuaCorsixTHLuaOld[] =
    "local name, sep, code = \"CorsixTH.lua\", package.config:sub(1, 1)\n"
    "local root = (... or \"\"):match(\"^(.*[\"..sep..\"])\") or \"\"\n"
	"code = loadfile(\"%s\"..name)\n"
    "if code then return code end\n"
#ifdef __APPLE__ // Darrell: Search inside the bundle first.
                 // There's probably a better way of doing this.
#if defined(IS_CORSIXTH_APP)
    "code = loadfile(\"CorsixTH.app/Contents/Resources/\"..name)\n"
    "if code then return code end\n"
#elif defined(IS_MAPEDIT_APP)
    "code = loadfile(\"MapEdit.app/Contents/Resources/\"..name)\n"
    "if code then return code end\n"
#endif
#endif
    "for num_dotdot = 0, 3 do\n"
    "  for num_dir = 0, 1 do\n"
    "    code = loadfile(root..(\"..\"..sep):rep(num_dotdot)..\n"
    "                    (\"CorsixTH\"..sep):rep(num_dir)..name)\n"
    "    if code then return code end \n"
    "  end \n"
    "end \n"
    "return loadfile(name)";
	char sLuaCorsixTHLua[sizeof(sLuaCorsixTHLuaOld) + sizeof(path)];
    sprintf(sLuaCorsixTHLua, sLuaCorsixTHLuaOld, path);
    //LOGI(sLuaCorsixTHLua);
	
    // return assert(loadfile"CorsixTH.lua")(...)
    if(!bGotScriptFile)
    {
        lua_getglobal(L, "assert");
        luaL_loadbuffer(L, sLuaCorsixTHLua, strlen(sLuaCorsixTHLua),
            "@main.cpp (l_main bootstrap)");
        if(lua_gettop(L) == 2)
            lua_pushnil(L);
        else
            lua_pushvalue(L, 1);
    }
    lua_call(L, 1, 2);
    lua_call(L, 2, 1);
    lua_insert(L, 1);
    return lua_gettop(L);
}
void frmMain::_setLuaBlockBrush(int iBlockF, int iBlockW1, int iBlockW2)
{
    lua_State *L = m_pGamePanel->getLua();
    luaT_execute(L, "_MAP_EDITOR:setBlockBrush(...)",
        iBlockF, iBlockW1, iBlockW2);
}
void frmMain::_setLuaParcelBrush(int iParcel)
{
    m_iParcelBrush = iParcel;
    lua_State *L = m_pGamePanel->getLua();
    luaT_execute(L, "_MAP_EDITOR:setBlockBrushParcel(...)", iParcel);
}
void frmMain::_populateParcelGallery(wxRibbonGallery* pGallery)
{
    THSpriteSheet *pBlocksSheet;
    THSpriteSheet *pOutlineSheet;
    THSpriteSheet *pFontSheet;
    {
        lua_State *L = m_pGamePanel->getLua();
        luaT_execute(L, "return TheApp.map.blocks");
        pBlocksSheet = reinterpret_cast<THSpriteSheet*>(lua_touserdata(L, -1));
        luaT_execute(L, "return TheApp.map.cell_outline");
        pOutlineSheet = reinterpret_cast<THSpriteSheet*>(lua_touserdata(L, -1));
        luaT_execute(L, "return TheApp.gfx:loadBuiltinFont()");
        pFontSheet = reinterpret_cast<THBitmapFont*>(lua_touserdata(L, -1))
            ->getSpriteSheet();
        lua_pop(L, 3);
    }

    wxBitmap bmOutline(_asBitmap(pBlocksSheet, 74));
    wxMemoryDC dcMem;
    dcMem.SelectObject(bmOutline);
    for(int i = 0; i < 4; ++i)
    {
        dcMem.DrawBitmap(_asBitmap(pOutlineSheet, 18 + i), 0, 0);
    }
    dcMem.SelectObject(wxNullBitmap);

    wxBitmap bmNumbers[10];
    for(int i = 0; i < 10; ++i)
    {
        bmNumbers[i] = _asBitmap(pFontSheet, '0' + i - 31);
    }

    for(intptr_t iParcel = 0; iParcel < 32; ++iParcel)
    {
        wxBitmap bmParcel(bmOutline);
        dcMem.SelectObject(bmParcel);

        char sMsg[8];
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4996)
#endif
        sprintf(sMsg, "%i", iParcel);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
        int iX = 0, iY = 0;
        for(char* s = sMsg; *s; ++s)
        {
            wxBitmap& bm = bmNumbers[*s - '0'];
            iX += bm.GetWidth();
            iY = std::max(iY, bm.GetHeight());
        }
        iX = (bmParcel.GetWidth() - iX) / 2;
        iY = (bmParcel.GetHeight() - iY) / 2;

        for(char* s = sMsg; *s; ++s)
        {
            wxBitmap& bm = bmNumbers[*s - '0'];
            dcMem.DrawBitmap(bm, iX, iY);
            iX += bm.GetWidth();
        }

        dcMem.SelectObject(wxNullBitmap);
        pGallery->SetItemClientData(pGallery->Append(bmParcel, iParcel),
            reinterpret_cast<void*>(iParcel));
    }
}
Beispiel #9
0
bool EmbeddedGamePanel::loadLua()
{
    // Create state
    m_L = luaL_newstate();
    lua_atpanic(m_L, _l_panic);

    // Save a pointer to ourselves in the registry
    lua_pushliteral(m_L, "wxWindow");
    lua_pushlightuserdata(m_L, reinterpret_cast<wxWindow*>(this));
    lua_settable(m_L, LUA_REGISTRYINDEX);

    // Open default libraries, and override appropriate bits
    luaL_openlibs(m_L);
    luaT_execute(m_L, "print = ...", _l_print);

    // Set _MAP_EDITOR to true, to allow scripts to notice that they are
    // running inside this component, rather than standalone.
    luaT_execute(m_L, "_MAP_EDITOR = true");

    // Load CorsixTH.lua and perform other initialisation needed by it
    lua_settop(m_L, 0);
    lua_pushcfunction(m_L, CorsixTH_lua_stacktrace);
    lua_pushcfunction(m_L, CorsixTH_lua_main_no_eval);
    lua_checkstack(m_L, wxTheApp->argc);
    for(int i = 0; i < wxTheApp->argc; ++ i)
        lua_pushstring(m_L, wxTheApp->argv[i]);
    if(lua_pcall(m_L, wxTheApp->argc, 1, 1))
    {
        if(m_pPrintTarget)
        {
            m_pPrintTarget->AppendText(L"Error initialising Lua: ");
            m_pPrintTarget->AppendText(lua_tostring(m_L, -1));
            m_pPrintTarget->AppendText(L"\n");
        }
        return false;
    }
    // NB: CorsixTH_lua_main_no_eval will have loaded CorsixTH.lua and left it
    // as the top value on the stack, but will not have executed it.
    // The stack will hence have two things on it: the stacktrace function,
    // and the loaded CorsixTH.lua

    // Overwrite what CorsixTH_lua_main_no_eval registered for require("sdl")
    // with our own function that uses wxWidgets to do what SDL would have.
    luaT_execute(m_L, "package.preload.sdl = ...", _l_open_sdl);

    // Replace the Surface:endFrame() function with our own
    lua_getglobal(m_L, "require");
    lua_pushliteral(m_L, "TH");
    lua_call(m_L, 1, 1);
    lua_getfield(m_L, -1, "surface");
    lua_getfield(m_L, -1, "endFrame");
    lua_pushcclosure(m_L, _l_end_frame, 1);
    lua_setfield(m_L, -2, "endFrame");
    lua_pop(m_L, 2);

    // Perform extra initialisation
    if(m_fnExtraLuaInit)
    {
        if(lua_cpcall(m_L, m_fnExtraLuaInit, m_pExtraLuaInitArg) != 0)
            lua_pop(m_L, 1);
    }

    // Execute CorsixTH.lua in a coroutine
    lua_getglobal(m_L, "coroutine");
    lua_getfield(m_L, -1, "create");
    lua_replace(m_L, -2);
    lua_insert(m_L, -2);
    lua_call(m_L, 1, 1);
    lua_State *L = lua_tothread(m_L, -1);
    if(lua_resume(L, 0) != LUA_YIELD)
    {
        if(m_pPrintTarget)
        {
            // Push debug.traceback onto m_L
            lua_getglobal(m_L, "debug");
            lua_getfield(m_L, -1, "traceback");
            lua_replace(m_L, -2);
            // Push the thread onto m_L
            lua_pushvalue(m_L, -2);
            // Push tostring(errmsg) onto m_L
            lua_getglobal(m_L, "tostring");
            lua_xmove(L, m_L, 1);
            lua_call(m_L, 1, 1);
            // Push constant 1 onto m_L
            lua_pushinteger(m_L, 1);
            // Call debug.traceback(thread, tostring(err), 1)
            lua_call(m_L, 3, 1);
            // Display resulting string and pop it
            m_pPrintTarget->AppendText(L"Error initialising Lua: ");
            m_pPrintTarget->AppendText(lua_tostring(m_L, -1));
            m_pPrintTarget->AppendText(L"\n");
            lua_pop(m_L, 1);
        }
        return false;
    }
    lua_settop(L, 1);
    m_Lthread = L;

    // The stack of the Lua states is now as follows:
    // m_L: stacktrace function, m_Lthread <top
    // m_Lthread: event dispatch coroutine <top

    return true;
}