mirror of
https://github.com/OpenMW/openmw.git
synced 2025-12-13 20:43:07 +00:00
deduplication for landbindings.cpp + slight api changes
- remove textureId from return - return plugin name instead of plugin id
This commit is contained in:
parent
dcf0c6e314
commit
4182279f72
2 changed files with 60 additions and 78 deletions
|
|
@ -4,72 +4,67 @@
|
||||||
#include <apps/openmw/mwworld/cellstore.hpp>
|
#include <apps/openmw/mwworld/cellstore.hpp>
|
||||||
#include <apps/openmw/mwworld/worldmodel.hpp>
|
#include <apps/openmw/mwworld/worldmodel.hpp>
|
||||||
|
|
||||||
|
#include <components/esm/util.hpp>
|
||||||
#include <components/esmterrain/storage.hpp>
|
#include <components/esmterrain/storage.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
|
static const ESM::RefId worldspaceAt(const osg::Vec3f& pos, sol::object cellOrName)
|
||||||
|
{
|
||||||
|
ESM::RefId worldspace;
|
||||||
|
if (cellOrName.is<MWLua::GCell>())
|
||||||
|
worldspace = cellOrName.as<MWLua::GCell>().mStore->getCell()->getWorldSpace();
|
||||||
|
else if (cellOrName.is<std::string_view>() && !cellOrName.as<std::string_view>().empty())
|
||||||
|
worldspace = MWBase::Environment::get()
|
||||||
|
.getWorldModel()
|
||||||
|
->getCell(cellOrName.as<std::string_view>())
|
||||||
|
.getCell()
|
||||||
|
->getWorldSpace();
|
||||||
|
else
|
||||||
|
worldspace = ESM::Cell::sDefaultWorldspaceId;
|
||||||
|
|
||||||
|
return worldspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool fillLandData(const MWWorld::Store<ESM::Land>* landStore, const osg::Vec3f& pos, const float cellSize,
|
||||||
|
const ESM::Land** land, const ESM::Land::LandData** landData)
|
||||||
|
{
|
||||||
|
int cellX = static_cast<int>(std::floor(pos.x() / cellSize));
|
||||||
|
int cellY = static_cast<int>(std::floor(pos.y() / cellSize));
|
||||||
|
|
||||||
|
*land = landStore->search(cellX, cellY);
|
||||||
|
|
||||||
|
if (*land != nullptr)
|
||||||
|
*landData = (*land)->getLandData(ESM::Land::DATA_VTEX);
|
||||||
|
|
||||||
|
// If we fail to preload land data, return, we need to be able to get *any* land to know how to correct
|
||||||
|
// the position used to sample terrain
|
||||||
|
if (*landData == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWLua
|
namespace MWLua
|
||||||
{
|
{
|
||||||
sol::table initCoreLandBindings(const Context& context)
|
sol::table initCoreLandBindings(const Context& context)
|
||||||
{
|
{
|
||||||
sol::state_view& lua = context.mLua->sol();
|
auto lua = context.sol();
|
||||||
sol::table landApi(lua, sol::create);
|
sol::table landApi(lua, sol::create);
|
||||||
|
|
||||||
landApi["getHeightAt"] = [](const osg::Vec3f& pos, sol::object cellOrName) {
|
landApi["getHeightAt"] = [](const osg::Vec3f& pos, sol::object cellOrName) {
|
||||||
ESM::RefId worldspace;
|
auto worldspace = worldspaceAt(pos, cellOrName);
|
||||||
if (cellOrName.is<GCell>())
|
return MWBase::Environment::get().getWorld()->getTerrainHeightAt(pos, worldspace);
|
||||||
worldspace = cellOrName.as<GCell>().mStore->getCell()->getWorldSpace();
|
|
||||||
else if (cellOrName.is<std::string_view>() && !cellOrName.as<std::string_view>().empty())
|
|
||||||
worldspace = MWBase::Environment::get()
|
|
||||||
.getWorldModel()
|
|
||||||
->getCell(cellOrName.as<std::string_view>())
|
|
||||||
.getCell()
|
|
||||||
->getWorldSpace();
|
|
||||||
else
|
|
||||||
worldspace = ESM::Cell::sDefaultWorldspaceId;
|
|
||||||
|
|
||||||
const float cellSize = ESM::getCellSize(worldspace);
|
|
||||||
int cellX = static_cast<int>(std::floor(pos.x() / cellSize));
|
|
||||||
int cellY = static_cast<int>(std::floor(pos.y() / cellSize));
|
|
||||||
|
|
||||||
auto store = MWBase::Environment::get().getESMStore();
|
|
||||||
auto landStore = store->get<ESM::Land>();
|
|
||||||
auto land = landStore.search(cellX, cellY);
|
|
||||||
const ESM::Land::LandData* landData = nullptr;
|
|
||||||
if (land != nullptr)
|
|
||||||
{
|
|
||||||
landData = land->getLandData(ESM::Land::DATA_VHGT);
|
|
||||||
}
|
|
||||||
if (landData == nullptr)
|
|
||||||
{
|
|
||||||
// If we failed to load data, return the default height
|
|
||||||
return static_cast<float>(ESM::Land::DEFAULT_HEIGHT);
|
|
||||||
}
|
|
||||||
return ESMTerrain::Storage::getHeightAt(landData->mHeights, landData->sLandSize, pos, cellSize);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
landApi["getTextureAt"] = [lua = context.mLua](const osg::Vec3f& pos, sol::object cellOrName) {
|
landApi["getTextureAt"] = [lua = lua](const osg::Vec3f& pos, sol::object cellOrName) {
|
||||||
sol::variadic_results values;
|
sol::variadic_results values;
|
||||||
ESM::RefId worldspace;
|
|
||||||
if (cellOrName.is<GCell>())
|
|
||||||
worldspace = cellOrName.as<GCell>().mStore->getCell()->getWorldSpace();
|
|
||||||
else if (cellOrName.is<std::string_view>() && !cellOrName.as<std::string_view>().empty())
|
|
||||||
worldspace = MWBase::Environment::get()
|
|
||||||
.getWorldModel()
|
|
||||||
->getCell(cellOrName.as<std::string_view>())
|
|
||||||
.getCell()
|
|
||||||
->getWorldSpace();
|
|
||||||
else
|
|
||||||
worldspace = ESM::Cell::sDefaultWorldspaceId;
|
|
||||||
|
|
||||||
const float cellSize = ESM::getCellSize(worldspace);
|
|
||||||
|
|
||||||
int cellX = static_cast<int>(std::floor(pos.x() / cellSize));
|
|
||||||
int cellY = static_cast<int>(std::floor(pos.y() / cellSize));
|
|
||||||
|
|
||||||
auto store = MWBase::Environment::get().getESMStore();
|
auto store = MWBase::Environment::get().getESMStore();
|
||||||
|
auto landStore = store->get<ESM::Land>();
|
||||||
|
|
||||||
|
const float cellSize = ESM::getCellSize(worldspaceAt(pos, cellOrName));
|
||||||
// We need to read land twice. Once to get the amount of texture samples per cell edge, and the second time
|
// We need to read land twice. Once to get the amount of texture samples per cell edge, and the second time
|
||||||
// to get the actual data
|
// to get the actual data
|
||||||
// This is because the visual land textures are offset with regards to quads that are rendered for terrain.
|
// This is because the visual land textures are offset with regards to quads that are rendered for terrain.
|
||||||
|
|
@ -77,36 +72,22 @@ namespace MWLua
|
||||||
// as it differs between tes3 and tes4. It's equal -
|
// as it differs between tes3 and tes4. It's equal -
|
||||||
// Once we know the value, we will calculate the offset and retrieve a sample again, this time
|
// Once we know the value, we will calculate the offset and retrieve a sample again, this time
|
||||||
// with the offset taken into account.
|
// with the offset taken into account.
|
||||||
auto landStore = store->get<ESM::Land>();
|
const ESM::Land* land = nullptr;
|
||||||
auto land = landStore.search(cellX, cellY);
|
|
||||||
const ESM::Land::LandData* landData = nullptr;
|
const ESM::Land::LandData* landData = nullptr;
|
||||||
if (land != nullptr)
|
|
||||||
{
|
if (!fillLandData(&landStore, pos, cellSize, &land, &landData))
|
||||||
landData = land->getLandData(ESM::Land::DATA_VTEX);
|
|
||||||
}
|
|
||||||
if (landData == nullptr)
|
|
||||||
{
|
|
||||||
// If we fail to preload land data, return, we need to be able to get *any* land to know how to correct
|
|
||||||
// the position used to sample terrain
|
|
||||||
return values;
|
return values;
|
||||||
}
|
|
||||||
|
|
||||||
// Use landData to get amount of sampler per cell edge (sLandTextureSize)
|
// Use landData to get amount of sampler per cell edge (sLandTextureSize)
|
||||||
// and then get the corrected position that will map to the rendered texture
|
// and then get the corrected position that will map to the rendered texture
|
||||||
const osg::Vec3f correctedPos
|
const osg::Vec3f correctedPos
|
||||||
= ESMTerrain::Storage::getTextureCorrectedWorldPos(pos, landData->sLandTextureSize, cellSize);
|
= ESMTerrain::Storage::getTextureCorrectedWorldPos(pos, landData->sLandTextureSize, cellSize);
|
||||||
int correctedCellX = static_cast<int>(std::floor(correctedPos.x() / cellSize));
|
|
||||||
int correctedCellY = static_cast<int>(std::floor(correctedPos.y() / cellSize));
|
const ESM::Land* correctedLand = nullptr;
|
||||||
auto correctedLand = landStore.search(correctedCellX, correctedCellY);
|
|
||||||
const ESM::Land::LandData* correctedLandData = nullptr;
|
const ESM::Land::LandData* correctedLandData = nullptr;
|
||||||
if (correctedLand != nullptr)
|
|
||||||
{
|
if (!fillLandData(&landStore, correctedPos, cellSize, &correctedLand, &correctedLandData))
|
||||||
correctedLandData = correctedLand->getLandData(ESM::Land::DATA_VTEX);
|
|
||||||
}
|
|
||||||
if (correctedLandData == nullptr)
|
|
||||||
{
|
|
||||||
return values;
|
return values;
|
||||||
}
|
|
||||||
|
|
||||||
// We're passing in sLandTextureSize, NOT sLandSize like with getHeightAt
|
// We're passing in sLandTextureSize, NOT sLandSize like with getHeightAt
|
||||||
const ESMTerrain::UniqueTextureId textureId
|
const ESMTerrain::UniqueTextureId textureId
|
||||||
|
|
@ -116,15 +97,17 @@ namespace MWLua
|
||||||
// Need to check for 0, 0 so that we can safely subtract 1 later, as per documentation on UniqueTextureId
|
// Need to check for 0, 0 so that we can safely subtract 1 later, as per documentation on UniqueTextureId
|
||||||
if (textureId.first != 0)
|
if (textureId.first != 0)
|
||||||
{
|
{
|
||||||
values.push_back(sol::make_object<uint16_t>(lua->sol(), textureId.first - 1));
|
auto store = MWBase::Environment::get().getESMStore();
|
||||||
values.push_back(sol::make_object<int>(lua->sol(), textureId.second));
|
|
||||||
|
|
||||||
auto textureStore = store->get<ESM::LandTexture>();
|
auto textureStore = store->get<ESM::LandTexture>();
|
||||||
const std::string* textureString = textureStore.search(textureId.first - 1, textureId.second);
|
const std::string* textureString = textureStore.search(textureId.first - 1, textureId.second);
|
||||||
if (textureString)
|
if (textureString)
|
||||||
{
|
values.push_back(sol::make_object<std::string>(lua, *textureString));
|
||||||
values.push_back(sol::make_object<std::string>(lua->sol(), *textureString));
|
else
|
||||||
}
|
return values;
|
||||||
|
|
||||||
|
const std::vector<std::string>& contentList = MWBase::Environment::get().getWorld()->getContentFiles();
|
||||||
|
if (textureId.second > 0 && textureId.second < contentList.size())
|
||||||
|
values.push_back(sol::make_object<std::string>(lua, contentList[textureId.second]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return values;
|
return values;
|
||||||
|
|
|
||||||
|
|
@ -470,9 +470,8 @@
|
||||||
-- @function [parent=#Land] getTextureAt
|
-- @function [parent=#Land] getTextureAt
|
||||||
-- @param openmw.util#Vector3 position
|
-- @param openmw.util#Vector3 position
|
||||||
-- @param #any cellOrName (optional) cell or cell name in their exterior world space to query
|
-- @param #any cellOrName (optional) cell or cell name in their exterior world space to query
|
||||||
-- @return #nil, #number Land texture index or nil if failed to retrieve the texture. Landscape textures created through editors such as openmw-cs can be assigned an id to differentiate them, that is also used for terrain rendering. The value returned here corresponds to that value. See also LTEX records (https://en.uesp.net/wiki/Morrowind_Mod:Mod_File_Format/LTEX)
|
|
||||||
-- @return #nil, #number Plugin id or nil if failed to retrieve the texture
|
|
||||||
-- @return #nil, #string Texture path or nil if one isn't defined
|
-- @return #nil, #string Texture path or nil if one isn't defined
|
||||||
|
-- @return #nil, #string Plugin name or nil if failed to retrieve the texture
|
||||||
|
|
||||||
--- Possible @{#SpellRange} values
|
--- Possible @{#SpellRange} values
|
||||||
-- @field [parent=#Magic] #SpellRange RANGE
|
-- @field [parent=#Magic] #SpellRange RANGE
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue