From 1f7d2dfa2256e24b406e64219ed2922264a44227 Mon Sep 17 00:00:00 2001 From: Krzysztof Antoniak Date: Sun, 21 Jul 2024 22:26:06 -0700 Subject: [PATCH] Add proof of concept for custom markers lua API --- apps/openmw/mwbase/windowmanager.hpp | 2 + apps/openmw/mwgui/windowmanagerimp.cpp | 5 ++ apps/openmw/mwgui/windowmanagerimp.hpp | 1 + apps/openmw/mwlua/nearbybindings.cpp | 64 ++++++++++++++++++++++++++ 4 files changed, 72 insertions(+) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 0b2e85f3e1..1106ecf758 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -11,6 +11,7 @@ #include +#include "../mwgui/mapwindow.hpp" #include "../mwgui/mode.hpp" #include @@ -237,6 +238,7 @@ namespace MWBase virtual void notifyInputActionBound() = 0; virtual void addVisitedLocation(const std::string& name, int x, int y) = 0; + virtual MWGui::CustomMarkerCollection::RangeType getCustomMarkers() const = 0; /// Hides dialog and schedules dialog to be deleted. virtual void removeDialog(std::unique_ptr&& dialog) = 0; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 64bb0c66ca..e8f88c91c4 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1649,6 +1649,11 @@ namespace MWGui mMap->addVisitedLocation(name, x, y); } + MWGui::CustomMarkerCollection::RangeType WindowManager::getCustomMarkers() const + { + return std::make_pair(mCustomMarkers.begin(), mCustomMarkers.end()); + } + const Translation::Storage& WindowManager::getTranslationDataStorage() const { return mTranslationDataStorage; diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index f7c778e10a..810f98ccd6 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -255,6 +255,7 @@ namespace MWGui void notifyInputActionBound() override; void addVisitedLocation(const std::string& name, int x, int y) override; + MWGui::CustomMarkerCollection::RangeType getCustomMarkers() const override; /// Hides dialog and schedules dialog to be deleted. void removeDialog(std::unique_ptr&& dialog) override; diff --git a/apps/openmw/mwlua/nearbybindings.cpp b/apps/openmw/mwlua/nearbybindings.cpp index af6980fb7f..1021af4bac 100644 --- a/apps/openmw/mwlua/nearbybindings.cpp +++ b/apps/openmw/mwlua/nearbybindings.cpp @@ -12,6 +12,7 @@ #include "../mwworld/cell.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/scene.hpp" +#include "../mwworld/worldmodel.hpp" #include "luamanagerimp.hpp" #include "objectlists.hpp" @@ -41,8 +42,28 @@ namespace } } +namespace MWLua +{ + struct CustomMarker + { + bool mMutable = false; + + float mWorldX; + float mWorldY; + + LCell mCell; + std::string mNote; + + }; +} + namespace sol { + template <> + struct is_automagical : std::false_type + { + }; + template <> struct is_automagical : std::false_type { @@ -184,6 +205,49 @@ namespace MWLua api["doors"] = LObjectList{ objectLists->getDoorsInScene() }; api["items"] = LObjectList{ objectLists->getItemsInScene() }; api["players"] = LObjectList{ objectLists->getPlayers() }; + + // FIXME: Make `customMarkers` a dynamic property rather than property of `function` type + api["customMarkers"] = sol::readonly_property([context]() { + // FIXME: Performance and list caching + auto worldModel = MWBase::Environment::get().getWorldModel(); + auto esmCustomMarkers = MWBase::Environment::get().getWindowManager()->getCustomMarkers(); + auto luaCustomMarkers = sol::table(context.mLua->sol(), sol::create); + size_t i = 0; + for (auto& it = esmCustomMarkers.first; it != esmCustomMarkers.second; it++, i++) + { + auto& esmCustomMarker = it->second; + + LCell cell{ nullptr }; + if (esmCustomMarker.mCell.is()) + { + cell.mStore = &worldModel->getCell(esmCustomMarker.mCell); + } + else if (esmCustomMarker.mCell.is()) + { + cell.mStore = worldModel->findInterior(esmCustomMarker.mCell.getRefIdString()); + } + else + { + // FIXME: Can it ever happen? What kind of error reporting to use? + } + + luaCustomMarkers[i + 1] = CustomMarker{ + .mWorldX = esmCustomMarker.mWorldX, + .mWorldY = esmCustomMarker.mWorldY, + .mCell = std::move(cell), + .mNote = esmCustomMarker.mNote, + }; + } + + return LuaUtil::makeReadOnly(luaCustomMarkers); + }); + + sol::usertype customMarkerType = context.mLua->sol().new_usertype("CustomMarker"); + customMarkerType[sol::meta_function::to_string] = [](const CustomMarker& m) { return "CustomMarker[x=" + std::to_string(m.mWorldX) + ", y=" + std::to_string(m.mWorldY) + "]"; }; + customMarkerType["worldX"] = sol::readonly_property([](const CustomMarker& m) { return m.mWorldX; }); + customMarkerType["worldY"] = sol::readonly_property([](const CustomMarker& m) { return m.mWorldY; }); + customMarkerType["cell"] = sol::readonly_property([](const CustomMarker& m) { return m.mCell; }); + customMarkerType["note"] = sol::readonly_property([](const CustomMarker& m) { return m.mNote; }); api["NAVIGATOR_FLAGS"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs({