diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index df334bbfe8..225e85e103 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -11,6 +11,7 @@ #include <MyGUI_KeyCode.h> +#include "../mwgui/mapwindow.hpp" #include "../mwgui/mode.hpp" #include <components/sdlutil/events.hpp> @@ -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<MWGui::Layout>&& dialog) = 0; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index e51350d19f..63021854f5 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1652,6 +1652,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 052a269188..af33e3bbd2 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<Layout>&& dialog) override; diff --git a/apps/openmw/mwlua/nearbybindings.cpp b/apps/openmw/mwlua/nearbybindings.cpp index df317ffeba..66817ae21a 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<MWLua::CustomMarker> : std::false_type + { + }; + template <> struct is_automagical<MWPhysics::RayCastingResult> : std::false_type { @@ -187,6 +208,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<ESM::ESM3ExteriorCellRefId>()) + { + cell.mStore = &worldModel->getCell(esmCustomMarker.mCell); + } + else if (esmCustomMarker.mCell.is<ESM::StringRefId>()) + { + 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<CustomMarker> customMarkerType = context.mLua->sol().new_usertype<CustomMarker>("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(LuaUtil::tableFromPairs<std::string_view, DetourNavigator::Flag>(lua,