diff --git a/rts/Game/GameHelper.cpp b/rts/Game/GameHelper.cpp index 5c3616faa7..a1afe7facd 100644 --- a/rts/Game/GameHelper.cpp +++ b/rts/Game/GameHelper.cpp @@ -1283,6 +1283,7 @@ CGameHelper::BuildSquareStatus CGameHelper::TestUnitBuildSquare( // const float buildHeight = GetBuildHeight(testPos, buildInfo.def, synced); // const float modelHeight = (model != nullptr) ? math::fabs(model->height) : 10.0f; + // FIXME this call is probably useless, we can assume that any caller already assigned it correctly sqrPos.y = GetBuildHeight(testPos, buildInfo.def, synced); BuildSquareStatus testStatus = BUILDSQUARE_OPEN; diff --git a/rts/Game/UI/CommandColors.cpp b/rts/Game/UI/CommandColors.cpp index d122b6cf03..2e555b7aca 100644 --- a/rts/Game/UI/CommandColors.cpp +++ b/rts/Game/UI/CommandColors.cpp @@ -77,10 +77,17 @@ CCommandColors::CCommandColors() SETUP_COLOR(rangeSelfDestruct, 0.8f, 0.1f, 0.1f, 0.7f); SETUP_COLOR(rangeInterceptorOn, 1.0f, 1.0f, 1.0f, 0.7f); SETUP_COLOR(rangeInterceptorOff, 0.0f, 0.0f, 0.0f, 0.7f); + SETUP_COLOR(unitBox, 0.0f, 1.0f, 0.0f, 0.9f); SETUP_COLOR(buildBox, 0.0f, 1.0f, 0.0f, 0.9f); SETUP_COLOR(allyBuildBox, 0.8f, 0.8f, 0.2f, 0.9f); SETUP_COLOR(mouseBox, 1.0f, 1.0f, 1.0f, 0.9f); + SETUP_COLOR(buildableSquare, 0.0f, 0.9f, 0.0f, 0.7f); + SETUP_COLOR(unbuildableSquare, 0.9f, 0.8f, 0.0f, 0.7f); + SETUP_COLOR(featureSquare, 0.9f, 0.8f, 0.0f, 0.7f); + SETUP_COLOR(illegalSquare, 0.9f, 0.0f, 0.0f, 0.7f); + SETUP_COLOR(underwaterStart, 0.0f, 0.0f, 1.0f, 0.5f); + SETUP_COLOR(underwaterEnd, 0.0f, 0.5f, 1.0f, 1.0f); } diff --git a/rts/Game/UI/CommandColors.h b/rts/Game/UI/CommandColors.h index e33254f277..5b530be35a 100644 --- a/rts/Game/UI/CommandColors.h +++ b/rts/Game/UI/CommandColors.h @@ -77,6 +77,12 @@ class CCommandColors { const float* buildBox; const float* allyBuildBox; const float* mouseBox; + const float* buildableSquare; + const float* unbuildableSquare; + const float* featureSquare; + const float* illegalSquare; + const float* underwaterStart; + const float* underwaterEnd; // for command queue rendering const float* start; @@ -156,6 +162,12 @@ class CCommandColors { buildBoxIndex, allyBuildBoxIndex, mouseBoxIndex, + buildableSquareIndex, + unbuildableSquareIndex, + featureSquareIndex, + illegalSquareIndex, + underwaterStartIndex, + underwaterEndIndex, ColorCount }; diff --git a/rts/Lua/LuaUnsyncedCtrl.cpp b/rts/Lua/LuaUnsyncedCtrl.cpp index 125838451c..50af7e9206 100644 --- a/rts/Lua/LuaUnsyncedCtrl.cpp +++ b/rts/Lua/LuaUnsyncedCtrl.cpp @@ -171,6 +171,8 @@ bool LuaUnsyncedCtrl::PushEntries(lua_State* L) REGISTER_LUA_CFUNC(AddWorldUnit); REGISTER_LUA_CFUNC(DrawUnitCommands); + REGISTER_LUA_CFUNC(AddBuildSquare); + REGISTER_LUA_CFUNC(RemoveBuildSquare); REGISTER_LUA_CFUNC(SetTeamColor); @@ -3382,6 +3384,93 @@ int LuaUnsyncedCtrl::SetBuildFacing(lua_State* L) } +// FIXME: move to LuaUtils, but currently it produces error +// "error: undefined reference to 'BuildInfo::BuildInfo(int, float3 const&, int)'" +static BuildInfo ParseBuildInfo( + lua_State* L, + const char* caller, + int idx +) { + int unitDefID = luaL_checkinteger(L, idx); + float3 pos = { + luaL_checkfloat(L, idx+1), + luaL_checkfloat(L, idx+2), + luaL_checkfloat(L, idx+3), + }; + int facing = luaL_checkinteger(L, idx+4); + + return BuildInfo(unitDefID, pos, facing); +} + + +static LuaBuildSquareOptions ParseBuildSquareOptions( + lua_State* L, + const char* caller, + const int idx +) { + LuaBuildSquareOptions opts; + if (lua_istable(L, idx)) { + for (lua_pushnil(L); lua_next(L, idx) != 0; lua_pop(L, 1)) { + // "key" = value (table format of CommandNotify) + // ignore the "coded" key; not a boolean value + if (lua_israwstring(L, -2)) { + if (lua_isboolean(L, -1)) { + const bool value = lua_toboolean(L, -1); + switch (hashString(lua_tostring(L, -2))) { + case hashString("unbuildable"): + opts.unbuildable = value; + break; + } + } + } + } + } else if (!lua_isnone(L, idx) && !lua_isnil(L, idx)) { + luaL_error(L, "%s(): bad options-argument type", caller); + } + return opts; +} + + +/*** + * + * @function Spring.AddBuildSquare + * @number unitDefID + * @number x + * @number y + * @number z + * @number facing + * @bool[opt] unbuildable + * @treturn nil + */ +int LuaUnsyncedCtrl::AddBuildSquare(lua_State* L) +{ + BuildInfo buildInfo = ParseBuildInfo(L, __func__, 1); + LuaBuildSquareOptions opts = ParseBuildSquareOptions(L, __func__, 6); + + unitDrawer->AddLuaBuildSquare(buildInfo, opts); + return 0; +} + + +/*** + * + * @function Spring.RemoveBuildSquare + * @number unitDefID + * @number x + * @number y + * @number z + * @number facing + * @treturn nil + */ +int LuaUnsyncedCtrl::RemoveBuildSquare(lua_State* L) +{ + BuildInfo buildInfo = ParseBuildInfo(L, __func__, 1); + + unitDrawer->RemoveLuaBuildSquare(buildInfo); + return 0; +} + + /****************************************************************************** * UI * @section ui diff --git a/rts/Lua/LuaUnsyncedCtrl.h b/rts/Lua/LuaUnsyncedCtrl.h index d388fa9c53..1aeec4a219 100644 --- a/rts/Lua/LuaUnsyncedCtrl.h +++ b/rts/Lua/LuaUnsyncedCtrl.h @@ -48,6 +48,8 @@ class LuaUnsyncedCtrl { static int AddWorldUnit(lua_State* L); static int DrawUnitCommands(lua_State* L); + static int AddBuildSquare(lua_State* L); + static int RemoveBuildSquare(lua_State* L); static int SetTeamColor(lua_State* L); diff --git a/rts/Rendering/CMakeLists.txt b/rts/Rendering/CMakeLists.txt index 98bb32b746..930e5fb567 100644 --- a/rts/Rendering/CMakeLists.txt +++ b/rts/Rendering/CMakeLists.txt @@ -125,6 +125,7 @@ set(sources_engine_Rendering "${CMAKE_CURRENT_SOURCE_DIR}/Features/FeatureDrawerData.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Features/FeatureDrawer.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Units/UnitDrawerData.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Units/UnitDrawerCache.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Units/UnitDrawer.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/ModelsDataUploader.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/UniformConstants.cpp" diff --git a/rts/Rendering/Units/UnitDrawer.cpp b/rts/Rendering/Units/UnitDrawer.cpp index ff26f05661..4a2ad3869a 100644 --- a/rts/Rendering/Units/UnitDrawer.cpp +++ b/rts/Rendering/Units/UnitDrawer.cpp @@ -9,6 +9,7 @@ #include "Game/GameSetup.h" #include "Game/GlobalUnsynced.h" #include "Game/Players/Player.h" +#include "Game/UI/CommandColors.h" #include "Game/UI/MiniMap.h" #include "Map/MapInfo.h" #include "Map/ReadMap.h" @@ -41,6 +42,7 @@ #include "Sim/Units/UnitHandler.h" #include "System/EventHandler.h" +#include "System/Color.h" #include "System/Config/ConfigHandler.h" //#include "System/FileSystem/FileHandler.h" @@ -1183,7 +1185,6 @@ void CUnitDrawerLegacy::DrawIndividualDefAlpha(const SolidObjectDef* objectDef, bool CUnitDrawerLegacy::ShowUnitBuildSquare(const BuildInfo& buildInfo, const std::vector& commands) const { RECOIL_DETAILED_TRACY_ZONE; - //TODO: make this a lua callin! glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -1263,11 +1264,6 @@ bool CUnitDrawerLegacy::ShowUnitBuildSquare(const BuildInfo& buildInfo, const st buildCacheItem.illegalSquares.assign(illegalSquares.begin(), illegalSquares.end()); } - static constexpr std::array buildColorT = { 0.0f, 0.9f, 0.0f, 0.7f }; - static constexpr std::array buildColorF = { 0.9f, 0.8f, 0.0f, 0.7f }; - static constexpr std::array featureColor = { 0.9f, 0.8f, 0.0f, 0.7f }; - static constexpr std::array illegalColor = { 0.9f, 0.0f, 0.0f, 0.7f }; - static auto& rb = RenderBuffer::GetTypedRenderBuffer(); rb.AssertSubmission(); @@ -1275,7 +1271,7 @@ bool CUnitDrawerLegacy::ShowUnitBuildSquare(const BuildInfo& buildInfo, const st sh.Enable(); - const float* color = canBuild ? &buildColorT[0] : &buildColorF[0]; + const float* color = canBuild ? cmdColors.buildableSquare : cmdColors.unbuildableSquare; for (const auto& buildableSquare : buildableSquares) { rb.AddQuadLines( { buildableSquare , color }, @@ -1285,7 +1281,7 @@ bool CUnitDrawerLegacy::ShowUnitBuildSquare(const BuildInfo& buildInfo, const st ); } - color = &featureColor[0]; + color = cmdColors.featureSquare; for (const auto& featureSquare : featureSquares) { rb.AddQuadLines( { featureSquare , color }, @@ -1295,7 +1291,7 @@ bool CUnitDrawerLegacy::ShowUnitBuildSquare(const BuildInfo& buildInfo, const st ); } - color = &illegalColor[0]; + color = cmdColors.illegalSquare; for (const auto& illegalSquare : illegalSquares) { rb.AddQuadLines( { illegalSquare , color }, @@ -1307,19 +1303,19 @@ bool CUnitDrawerLegacy::ShowUnitBuildSquare(const BuildInfo& buildInfo, const st rb.Submit(GL_LINES); if (h < 0.0f) { - constexpr uint8_t s[] = { 0, 0, 255, 128 }; // start color - constexpr uint8_t e[] = { 0, 128, 255, 255 }; // end color + SColor startColor(cmdColors.underwaterStart); + SColor endColor(cmdColors.underwaterEnd); - rb.AddVertex({ float3(x1, h, z1), s }); rb.AddVertex({ float3(x1, 0.f, z1), e }); - rb.AddVertex({ float3(x1, h, z2), s }); rb.AddVertex({ float3(x1, 0.f, z2), e }); - rb.AddVertex({ float3(x2, h, z2), s }); rb.AddVertex({ float3(x2, 0.f, z2), e }); - rb.AddVertex({ float3(x2, h, z1), s }); rb.AddVertex({ float3(x2, 0.f, z1), e }); + rb.AddVertex({ float3(x1, h, z1), startColor }); rb.AddVertex({ float3(x1, 0.f, z1), endColor }); + rb.AddVertex({ float3(x1, h, z2), startColor }); rb.AddVertex({ float3(x1, 0.f, z2), endColor }); + rb.AddVertex({ float3(x2, h, z2), startColor }); rb.AddVertex({ float3(x2, 0.f, z2), endColor }); + rb.AddVertex({ float3(x2, h, z1), startColor }); rb.AddVertex({ float3(x2, 0.f, z1), endColor }); rb.Submit(GL_LINES); - rb.AddVertex({ float3(x1, 0.0f, z1), e }); - rb.AddVertex({ float3(x1, 0.0f, z2), e }); - rb.AddVertex({ float3(x2, 0.0f, z2), e }); - rb.AddVertex({ float3(x2, 0.0f, z1), e }); + rb.AddVertex({ float3(x1, 0.0f, z1), endColor }); + rb.AddVertex({ float3(x1, 0.0f, z2), endColor }); + rb.AddVertex({ float3(x2, 0.0f, z2), endColor }); + rb.AddVertex({ float3(x2, 0.0f, z1), endColor }); rb.Submit(GL_LINE_LOOP); } @@ -1333,6 +1329,159 @@ bool CUnitDrawerLegacy::ShowUnitBuildSquare(const BuildInfo& buildInfo, const st return canBuild; } +void CUnitDrawerLegacy::AddLuaBuildSquare(const BuildInfo& buildInfo, LuaBuildSquareOptions& opts) { + LuaBuildSquareTaskKey buildKey(buildInfo); + auto it = luaBuildSquareTasks.find(buildKey); + + if (it == luaBuildSquareTasks.end()) { + luaBuildSquareTasks.insert(std::make_pair(buildKey, LuaBuildSquareTask(buildInfo, opts))); + } else if (it->second.buildInfo.pos.y != buildInfo.pos.y) { + // already exists but new parameters have invalidated the squares + it->second = LuaBuildSquareTask(buildInfo, opts); + } else { + // udpate options and mark it as used + it->second.opts = opts; + it->second.cacheUntil = 0; + } +} + +void CUnitDrawerLegacy::RemoveLuaBuildSquare(const BuildInfo& buildInfo) { + // the chosen number here is arbitrary, feel free to fine balance. + static constexpr int CACHE_VALIDITY_PERIOD = GAME_SPEED / 5; + + LuaBuildSquareTaskKey buildKey(buildInfo); + auto it = luaBuildSquareTasks.find(buildKey); + LuaBuildSquareTask& task = it->second; + + if (task.cacheUntil < 0) { + // nothing computed yet, no point keeping it in cache + luaBuildSquareTasks.erase(it); + } else if (task.cacheUntil == 0) { + // mark it for later erase + task.cacheUntil = gs->frameNum + CACHE_VALIDITY_PERIOD; + } +} + +void CUnitDrawerLegacy::ShowLuaBuildSquare() { + if (luaBuildSquareTasks.empty()) return; + + RECOIL_DETAILED_TRACY_ZONE; + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_TEXTURE_2D); + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + static auto& rb = RenderBuffer::GetTypedRenderBuffer(); + rb.AssertSubmission(); + + auto& sh = rb.GetShader(); + + sh.Enable(); + + CFeature* feature; + std::vector squares[3]; + std::vector emptyCommands; + + SColor squareColors[4] = { + cmdColors.buildableSquare, + cmdColors.featureSquare, + cmdColors.illegalSquare, + cmdColors.unbuildableSquare, + }; + SColor startColor(cmdColors.underwaterStart); + SColor endColor(cmdColors.underwaterEnd); + + for (auto it = luaBuildSquareTasks.begin(); it != luaBuildSquareTasks.end(); ) { + LuaBuildSquareTask& task = it->second; + // should be uncached + if (task.cacheUntil > gs->frameNum) { + it = luaBuildSquareTasks.erase(it); + continue; + } + it++; // beware to only increment if not erased + // unused but not uncached + if (task.cacheUntil > 0) { + continue; + } + + BuildInfo& buildInfo = task.buildInfo; + float3& pos = task.buildInfo.pos; + + // squares haven't been computed yet, do it now + if (task.cacheUntil < 0) { + // remove previous squares but keep the capacity unchanged + for (int state=0; state<3; state++) squares[state].clear(); + + bool canBuild = CGameHelper::TestUnitBuildSquare( + buildInfo, + feature, + -1, + false, + &squares[0], + &squares[1], + &squares[2], + &emptyCommands + ); + + size_t size = 0; + for (uint8_t state=0; state<3; state++) { + size += squares[state].size(); + } + task.squares.resize(size); + + int index=0; + for (uint8_t state=0; state<3; state++) { + for (float3 pos: squares[state]) { + task.squares[index] = LuaBuildSquare{ + pos: pos, + state: state == uint8_t(0) && !canBuild ? uint8_t(3) : state, + }; + index++; + } + } + + task.cacheUntil = 0; + } + + for (const auto &square: task.squares) { + uint8_t state = square.state; + if (state == uint8_t(0) && task.opts.unbuildable) state = uint8_t(3); + rb.AddQuadLines( + { square.pos , squareColors[state] }, + { square.pos + float3(SQUARE_SIZE, 0, 0 ), squareColors[state] }, + { square.pos + float3(SQUARE_SIZE, 0, SQUARE_SIZE), squareColors[state] }, + { square.pos + float3(0 , 0, SQUARE_SIZE), squareColors[state] } + ); + } + rb.Submit(GL_LINES); + + if (pos.y < 0.0f) { + const float x1 = std::floor(pos.x - (buildInfo.GetXSize() * 0.5f * SQUARE_SIZE)); + const float x2 = x1 + (buildInfo.GetXSize() * SQUARE_SIZE); + const float z1 = std::floor(pos.z - (buildInfo.GetZSize() * 0.5f * SQUARE_SIZE)); + const float z2 = z1 + (buildInfo.GetZSize() * SQUARE_SIZE); + + rb.AddVertex({ float3(x1, pos.y, z1), startColor }); rb.AddVertex({ float3(x1, 0.f, z1), endColor }); + rb.AddVertex({ float3(x1, pos.y, z2), startColor }); rb.AddVertex({ float3(x1, 0.f, z2), endColor }); + rb.AddVertex({ float3(x2, pos.y, z2), startColor }); rb.AddVertex({ float3(x2, 0.f, z2), endColor }); + rb.AddVertex({ float3(x2, pos.y, z1), startColor }); rb.AddVertex({ float3(x2, 0.f, z1), endColor }); + rb.Submit(GL_LINES); + + rb.AddVertex({ float3(x1, 0.0f, z1), endColor }); + rb.AddVertex({ float3(x1, 0.0f, z2), endColor }); + rb.AddVertex({ float3(x2, 0.0f, z2), endColor }); + rb.AddVertex({ float3(x2, 0.0f, z1), endColor }); + rb.Submit(GL_LINE_LOOP); + } + } + sh.Disable(); + + glEnable(GL_DEPTH_TEST); + //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + // glDisable(GL_BLEND); +} + void CUnitDrawerLegacy::DrawBuildIcons(const std::vector& buildIcons) const { RECOIL_DETAILED_TRACY_ZONE; diff --git a/rts/Rendering/Units/UnitDrawer.h b/rts/Rendering/Units/UnitDrawer.h index c38350e694..3e3d3bdf32 100644 --- a/rts/Rendering/Units/UnitDrawer.h +++ b/rts/Rendering/Units/UnitDrawer.h @@ -6,9 +6,11 @@ #include "Rendering/Common/ModelDrawer.h" #include "Rendering/Common/ModelDrawerState.hpp" +#include "Rendering/Units/UnitDrawerCache.h" #include "Rendering/Units/UnitDrawerData.h" #include "Rendering/GL/LightHandler.h" #include "Game/UI/CursorIcons.h" +#include "System/Color.h" #include "System/type2.h" #include "Sim/Units/CommandAI/Command.h" @@ -77,6 +79,10 @@ class CUnitDrawer : public CModelDrawerBase bool ShowUnitBuildSquare(const BuildInfo& buildInfo) const { return ShowUnitBuildSquare(buildInfo, std::vector()); } virtual bool ShowUnitBuildSquare(const BuildInfo& buildInfo, const std::vector& commands) const = 0; + virtual void AddLuaBuildSquare(const BuildInfo& buildInfo, LuaBuildSquareOptions& opts) = 0; + virtual void RemoveLuaBuildSquare(const BuildInfo& buildInfo) = 0; + virtual void ShowLuaBuildSquare() = 0; + virtual void DrawBuildIcons(const std::vector& buildIcons) const = 0; protected: static bool ShouldDrawOpaqueUnit(CUnit* u, uint8_t thisPassMask); @@ -144,6 +150,9 @@ class CUnitDrawerLegacy : public CUnitDrawerBase { void DrawIndividualDefAlpha(const SolidObjectDef* objectDef, int teamID, bool rawState, bool toScreen = false) const override; bool ShowUnitBuildSquare(const BuildInfo& buildInfo, const std::vector& commands) const override; + void AddLuaBuildSquare(const BuildInfo& buildInfo, LuaBuildSquareOptions& opts) override; + void RemoveLuaBuildSquare(const BuildInfo& buildInfo) override; + void ShowLuaBuildSquare() override; void DrawBuildIcons(const std::vector& buildIcons) const override; void DrawUnitMiniMapIcons() const override; @@ -185,7 +194,7 @@ class CUnitDrawerLegacy : public CUnitDrawerBase { void PopIndividualOpaqueState(const S3DModel* model, int teamID, bool deferredPass) const; void PopIndividualAlphaState(const S3DModel* model, int teamID, bool deferredPass) const; protected: - + LuaBuildSquareTasksMap luaBuildSquareTasks; }; class CUnitDrawerFFP final : public CUnitDrawerLegacy {}; diff --git a/rts/Rendering/Units/UnitDrawerCache.cpp b/rts/Rendering/Units/UnitDrawerCache.cpp new file mode 100644 index 0000000000..a9c8e9a0dd --- /dev/null +++ b/rts/Rendering/Units/UnitDrawerCache.cpp @@ -0,0 +1,21 @@ +/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */ + +#include "UnitDrawerCache.h" + +#include "System/HashSpec.h" +#include "System/SpringHash.h" + +std::size_t LuaBuildSquareTaskHash::operator()(const LuaBuildSquareTaskKey& buildKey) const { + std::size_t hashKey = spring::LiteHash(buildKey.unitDefId); + hashKey = spring::hash_combine(spring::LiteHash(buildKey.x), hashKey); + hashKey = spring::hash_combine(spring::LiteHash(buildKey.z), hashKey); + hashKey = spring::hash_combine(spring::LiteHash(buildKey.facing), hashKey); + return hashKey; +} + +bool LuaBuildSquareTaskHash::operator()(const LuaBuildSquareTaskKey& buildKey1, const LuaBuildSquareTaskKey& buildKey2) const { + return buildKey1.unitDefId == buildKey2.unitDefId && + buildKey1.x == buildKey2.x && + buildKey1.z == buildKey2.z && + buildKey1.facing == buildKey2.facing; +} diff --git a/rts/Rendering/Units/UnitDrawerCache.h b/rts/Rendering/Units/UnitDrawerCache.h new file mode 100644 index 0000000000..d9a0f4c618 --- /dev/null +++ b/rts/Rendering/Units/UnitDrawerCache.h @@ -0,0 +1,45 @@ +/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */ +#pragma once + +#include +#include + +#include "Sim/Units/BuildInfo.h" +#include "Sim/Units/UnitDef.h" +#include "System/float3.h" + +struct LuaBuildSquareOptions { + bool unbuildable = false; +}; + +struct LuaBuildSquare { + float3 pos; + uint8_t state; // 0:buildable, 1:feature, 2:illegal, 3:unbuildable +}; + +struct LuaBuildSquareTask { + BuildInfo buildInfo; + int cacheUntil; // -1 if squares are not built yet, 0 if displayed + std::vector squares; + LuaBuildSquareOptions opts; + inline LuaBuildSquareTask(const BuildInfo& buildInfo, const LuaBuildSquareOptions& opts): buildInfo(buildInfo), opts(opts), cacheUntil(-1) {} +}; + +struct LuaBuildSquareTaskKey { + int unitDefId; + float x, z; + int facing; + + inline LuaBuildSquareTaskKey(const BuildInfo& buildInfo): + unitDefId(buildInfo.def->id), + x(buildInfo.pos.x), + z(buildInfo.pos.z), + facing(buildInfo.buildFacing) {} +}; + +struct LuaBuildSquareTaskHash { + std::size_t operator()(const LuaBuildSquareTaskKey& buildKey) const; + bool operator()(const LuaBuildSquareTaskKey& buildKey1, const LuaBuildSquareTaskKey& buildKey2) const; +}; + +using LuaBuildSquareTasksMap = std::unordered_map; diff --git a/rts/Rendering/WorldDrawer.cpp b/rts/Rendering/WorldDrawer.cpp index ea01c6ef78..deb81cc632 100644 --- a/rts/Rendering/WorldDrawer.cpp +++ b/rts/Rendering/WorldDrawer.cpp @@ -462,6 +462,7 @@ void CWorldDrawer::DrawMiscObjects() const mouse->DrawSelectionBox(); guihandler->DrawMapStuff(false); + unitDrawer->ShowLuaBuildSquare(); if (globalRendering->drawMapMarks && !game->hideInterface) { inMapDrawerView->Draw(); diff --git a/rts/Sim/Units/BuildInfo.cpp b/rts/Sim/Units/BuildInfo.cpp index 6436a6e640..2a57a49abb 100644 --- a/rts/Sim/Units/BuildInfo.cpp +++ b/rts/Sim/Units/BuildInfo.cpp @@ -21,6 +21,12 @@ BuildInfo::BuildInfo(const UnitDef* def, const float3& pos, int facing) , buildFacing(std::abs(facing) % NUM_FACINGS) {} +BuildInfo::BuildInfo(int unitDefId, const float3& pos, int facing) + : def(unitDefHandler->GetUnitDefByID(unitDefId)) + , pos(pos) + , buildFacing(std::abs(facing) % NUM_FACINGS) +{} + BuildInfo::BuildInfo(const std::string& name, const float3& pos, int facing) : def(unitDefHandler->GetUnitDefByName(name)) , pos(pos) diff --git a/rts/Sim/Units/BuildInfo.h b/rts/Sim/Units/BuildInfo.h index e3f49f6cfd..4dd06b962e 100644 --- a/rts/Sim/Units/BuildInfo.h +++ b/rts/Sim/Units/BuildInfo.h @@ -20,6 +20,7 @@ struct BuildInfo { BuildInfo(); BuildInfo(const UnitDef* def, const float3& pos, int buildFacing); + BuildInfo(int unitDefId, const float3& pos, int facing); BuildInfo(const std::string& name, const float3& pos, int facing); BuildInfo(const Command& c) { Parse(c); }