1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-06-26 23:11:33 +00:00

Merge branch 'master' of gitlab.com:openmw/openmw into fix_global_iteration

This commit is contained in:
Zackhasacat 2024-02-07 22:06:34 -06:00
commit 4700fdcfc2
61 changed files with 230 additions and 190 deletions

View file

@ -72,7 +72,7 @@ message(STATUS "Configuring OpenMW...")
set(OPENMW_VERSION_MAJOR 0)
set(OPENMW_VERSION_MINOR 49)
set(OPENMW_VERSION_RELEASE 0)
set(OPENMW_LUA_API_REVISION 52)
set(OPENMW_LUA_API_REVISION 53)
set(OPENMW_POSTPROCESSING_API_REVISION 1)
set(OPENMW_VERSION_COMMITHASH "")

View file

@ -62,7 +62,7 @@ namespace MWClass
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World);
}
std::string Activator::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Activator::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Activator>(ptr);
}
@ -141,15 +141,14 @@ namespace MWClass
ESM::RefId Activator::getSoundIdFromSndGen(const MWWorld::Ptr& ptr, std::string_view name) const
{
const std::string model
= getModel(ptr); // Assume it's not empty, since we wouldn't have gotten the soundgen otherwise
// Assume it's not empty, since we wouldn't have gotten the soundgen otherwise
const std::string_view model = getModel(ptr);
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
const ESM::RefId* creatureId = nullptr;
for (const ESM::Creature& iter : store.get<ESM::Creature>())
{
if (!iter.mModel.empty()
&& Misc::StringUtils::ciEqual(model, Misc::ResourceHelpers::correctMeshPath(iter.mModel)))
if (!iter.mModel.empty() && Misc::StringUtils::ciEqual(model, iter.mModel))
{
creatureId = !iter.mOriginal.empty() ? &iter.mOriginal : &iter.mId;
break;

View file

@ -41,7 +41,7 @@ namespace MWClass
std::unique_ptr<MWWorld::Action> activate(const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const override;
///< Generate action for activation
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
bool useAnim() const override;
///< Whether or not to use animated variant of model (default false)

View file

@ -35,7 +35,7 @@ namespace MWClass
}
}
std::string Apparatus::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Apparatus::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Apparatus>(ptr);
}

View file

@ -49,7 +49,7 @@ namespace MWClass
std::unique_ptr<MWWorld::Action> use(const MWWorld::Ptr& ptr, bool force = false) const override;
///< Generate action for using via inventory menu
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
bool canSell(const MWWorld::ConstPtr& item, int npcServices) const override;
};

View file

@ -44,7 +44,7 @@ namespace MWClass
}
}
std::string Armor::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Armor::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Armor>(ptr);
}

View file

@ -74,7 +74,7 @@ namespace MWClass
std::unique_ptr<MWWorld::Action> use(const MWWorld::Ptr& ptr, bool force = false) const override;
///< Generate action for using via inventory menu
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
int getEnchantmentPoints(const MWWorld::ConstPtr& ptr) const override;

View file

@ -42,7 +42,7 @@ namespace MWClass
return false;
}
std::string BodyPart::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view BodyPart::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::BodyPart>(ptr);
}

View file

@ -25,7 +25,7 @@ namespace MWClass
bool hasToolTip(const MWWorld::ConstPtr& ptr) const override;
///< @return true if this object has a tooltip when focused (default implementation: true)
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
};
}

View file

@ -41,7 +41,7 @@ namespace MWClass
}
}
std::string Book::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Book::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Book>(ptr);
}

View file

@ -54,7 +54,7 @@ namespace MWClass
std::unique_ptr<MWWorld::Action> use(const MWWorld::Ptr& ptr, bool force = false) const override;
///< Generate action for using via inventory menu
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
int getEnchantmentPoints(const MWWorld::ConstPtr& ptr) const override;

View file

@ -4,22 +4,16 @@
#include "../mwworld/livecellref.hpp"
#include "../mwworld/ptr.hpp"
#include <components/misc/resourcehelpers.hpp>
#include <components/resource/resourcesystem.hpp>
#include <string>
#include <string_view>
namespace MWClass
{
template <class Class>
std::string getClassModel(const MWWorld::ConstPtr& ptr)
std::string_view getClassModel(const MWWorld::ConstPtr& ptr)
{
const MWWorld::LiveCellRef<Class>* ref = ptr.get<Class>();
if (!ref->mBase->mModel.empty())
return Misc::ResourceHelpers::correctMeshPath(ref->mBase->mModel);
return {};
return ref->mBase->mModel;
}
}

View file

@ -39,7 +39,7 @@ namespace MWClass
}
}
std::string Clothing::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Clothing::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Clothing>(ptr);
}

View file

@ -66,7 +66,7 @@ namespace MWClass
std::unique_ptr<MWWorld::Action> use(const MWWorld::Ptr& ptr, bool force = false) const override;
///< Generate action for using via inventory menu
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
int getEnchantmentPoints(const MWWorld::ConstPtr& ptr) const override;

View file

@ -126,7 +126,7 @@ namespace MWClass
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World);
}
std::string Container::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Container::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Container>(ptr);
}

View file

@ -85,7 +85,7 @@ namespace MWClass
void respawn(const MWWorld::Ptr& ptr) const override;
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
bool useAnim() const override;

View file

@ -178,14 +178,14 @@ namespace MWClass
objects.insertCreature(ptr, model, hasInventoryStore(ptr));
}
std::string Creature::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Creature::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Creature>(ptr);
}
void Creature::getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector<std::string>& models) const
void Creature::getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector<std::string_view>& models) const
{
std::string model = getModel(ptr);
std::string_view model = getModel(ptr);
if (!model.empty())
models.push_back(model);
@ -651,13 +651,13 @@ namespace MWClass
if (sounds.empty())
{
const std::string model = getModel(ptr);
const std::string_view model = getModel(ptr);
if (!model.empty())
{
for (const ESM::Creature& creature : store.get<ESM::Creature>())
{
if (creature.mId != ourId && creature.mOriginal != ourId && !creature.mModel.empty()
&& Misc::StringUtils::ciEqual(model, Misc::ResourceHelpers::correctMeshPath(creature.mModel)))
&& Misc::StringUtils::ciEqual(model, creature.mModel))
{
const ESM::RefId& fallbackId = !creature.mOriginal.empty() ? creature.mOriginal : creature.mId;
sound = store.get<ESM::SoundGenerator>().begin();

View file

@ -105,9 +105,9 @@ namespace MWClass
float getMaxSpeed(const MWWorld::Ptr& ptr) const override;
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
void getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector<std::string>& models) const override;
void getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector<std::string_view>& models) const override;
///< Get a list of models to preload that this object may use (directly or indirectly). default implementation:
///< list getModel().

View file

@ -94,7 +94,7 @@ namespace MWClass
return true;
}
std::string Door::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Door::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Door>(ptr);
}

View file

@ -51,7 +51,7 @@ namespace MWClass
ESM::RefId getScript(const MWWorld::ConstPtr& ptr) const override;
///< Return name of the script attached to ptr
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
MWWorld::DoorState getDoorState(const MWWorld::ConstPtr& ptr) const override;
/// This does not actually cause the door to move. Use World::activateDoor instead.

View file

@ -96,9 +96,9 @@ namespace MWClass
std::string_view getName(const MWWorld::ConstPtr& ptr) const override { return {}; }
std::string getModel(const MWWorld::ConstPtr& ptr) const override
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override
{
std::string model = getClassModel<Record>(ptr);
std::string_view model = getClassModel<Record>(ptr);
// Hide meshes meshes/marker/* and *LOD.nif in ESM4 cells. It is a temporarty hack.
// Needed because otherwise LOD meshes are rendered on top of normal meshes.

View file

@ -175,17 +175,14 @@ namespace MWClass
return getCustomData(ptr).mIsFemale;
}
std::string ESM4Npc::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view ESM4Npc::getModel(const MWWorld::ConstPtr& ptr) const
{
const ESM4NpcCustomData& data = getCustomData(ptr);
if (data.mTraits == nullptr)
return {};
std::string_view model;
if (data.mTraits->mIsTES4)
model = data.mTraits->mModel;
else
model = data.mIsFemale ? data.mRace->mModelFemale : data.mRace->mModelMale;
return Misc::ResourceHelpers::correctMeshPath(model);
return data.mTraits->mModel;
return data.mIsFemale ? data.mRace->mModelFemale : data.mRace->mModelMale;
}
std::string_view ESM4Npc::getName(const MWWorld::ConstPtr& ptr) const

View file

@ -54,7 +54,7 @@ namespace MWClass
return ESM4Impl::getToolTipInfo(getName(ptr), count);
}
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getName(const MWWorld::ConstPtr& ptr) const override;
static const ESM4::Npc* getTraitsRecord(const MWWorld::Ptr& ptr);

View file

@ -39,7 +39,7 @@ namespace MWClass
}
}
std::string Ingredient::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Ingredient::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Ingredient>(ptr);
}

View file

@ -47,7 +47,7 @@ namespace MWClass
const std::string& getInventoryIcon(const MWWorld::ConstPtr& ptr) const override;
///< Return name of inventory icon.
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
float getWeight(const MWWorld::ConstPtr& ptr) const override;

View file

@ -70,7 +70,7 @@ namespace MWClass
return true;
}
std::string Light::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Light::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Light>(ptr);
}

View file

@ -69,7 +69,7 @@ namespace MWClass
float getRemainingUsageTime(const MWWorld::ConstPtr& ptr) const override;
///< Returns the remaining duration of the object.
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
float getWeight(const MWWorld::ConstPtr& ptr) const override;

View file

@ -38,7 +38,7 @@ namespace MWClass
}
}
std::string Lockpick::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Lockpick::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Lockpick>(ptr);
}

View file

@ -59,7 +59,7 @@ namespace MWClass
std::unique_ptr<MWWorld::Action> use(const MWWorld::Ptr& ptr, bool force = false) const override;
///< Generate action for using via inventory menu
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
bool canSell(const MWWorld::ConstPtr& item, int npcServices) const override;

View file

@ -49,7 +49,7 @@ namespace MWClass
}
}
std::string Miscellaneous::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Miscellaneous::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Miscellaneous>(ptr);
}

View file

@ -45,7 +45,7 @@ namespace MWClass
const std::string& getInventoryIcon(const MWWorld::ConstPtr& ptr) const override;
///< Return name of inventory icon.
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
std::unique_ptr<MWWorld::Action> use(const MWWorld::Ptr& ptr, bool force = false) const override;
///< Generate action for using via inventory menu

View file

@ -19,6 +19,7 @@
#include <components/esm3/loadsoun.hpp>
#include <components/esm3/npcstate.hpp>
#include <components/settings/values.hpp>
#include <components/vfs/pathutil.hpp>
#include "../mwbase/dialoguemanager.hpp"
#include "../mwbase/environment.hpp"
@ -424,45 +425,51 @@ namespace MWClass
return (ref->mBase->mRecordFlags & ESM::FLAG_Persistent) != 0;
}
std::string Npc::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Npc::getModel(const MWWorld::ConstPtr& ptr) const
{
const MWWorld::LiveCellRef<ESM::NPC>* ref = ptr.get<ESM::NPC>();
std::string_view model = Settings::models().mBaseanim.get();
const ESM::Race* race = MWBase::Environment::get().getESMStore()->get<ESM::Race>().find(ref->mBase->mRace);
if (race->mData.mFlags & ESM::Race::Beast)
model = Settings::models().mBaseanimkna.get();
// Base animations should be in the meshes dir
constexpr std::string_view prefix = "meshes/";
assert(VFS::Path::pathEqual(prefix, model.substr(0, prefix.size())));
return model.substr(prefix.size());
}
std::string Npc::getCorrectedModel(const MWWorld::ConstPtr& ptr) const
{
const MWWorld::LiveCellRef<ESM::NPC>* ref = ptr.get<ESM::NPC>();
std::string model = Settings::models().mBaseanim;
const std::string& model = Settings::models().mBaseanim;
const ESM::Race* race = MWBase::Environment::get().getESMStore()->get<ESM::Race>().find(ref->mBase->mRace);
if (race->mData.mFlags & ESM::Race::Beast)
model = Settings::models().mBaseanimkna;
return Settings::models().mBaseanimkna;
return model;
}
void Npc::getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector<std::string>& models) const
void Npc::getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector<std::string_view>& models) const
{
const MWWorld::LiveCellRef<ESM::NPC>* npc = ptr.get<ESM::NPC>();
const auto& esmStore = MWBase::Environment::get().getESMStore();
const ESM::Race* race = esmStore->get<ESM::Race>().search(npc->mBase->mRace);
if (race && race->mData.mFlags & ESM::Race::Beast)
models.push_back(Settings::models().mBaseanimkna);
// keep these always loaded just in case
models.push_back(Settings::models().mXargonianswimkna);
models.push_back(Settings::models().mXbaseanimfemale);
models.push_back(Settings::models().mXbaseanim);
models.push_back(getModel(ptr));
if (!npc->mBase->mModel.empty())
models.push_back(Misc::ResourceHelpers::correctMeshPath(npc->mBase->mModel));
models.push_back(npc->mBase->mModel);
if (!npc->mBase->mHead.empty())
{
const ESM::BodyPart* head = esmStore->get<ESM::BodyPart>().search(npc->mBase->mHead);
if (head)
models.push_back(Misc::ResourceHelpers::correctMeshPath(head->mModel));
models.push_back(head->mModel);
}
if (!npc->mBase->mHair.empty())
{
const ESM::BodyPart* hair = esmStore->get<ESM::BodyPart>().search(npc->mBase->mHair);
if (hair)
models.push_back(Misc::ResourceHelpers::correctMeshPath(hair->mModel));
models.push_back(hair->mModel);
}
bool female = (npc->mBase->mFlags & ESM::NPC::Female);
@ -486,7 +493,7 @@ namespace MWClass
const ESM::BodyPart* part = esmStore->get<ESM::BodyPart>().search(partname);
if (part && !part->mModel.empty())
models.push_back(Misc::ResourceHelpers::correctMeshPath(part->mModel));
models.push_back(part->mModel);
}
};
if (equipped->getType() == ESM::Clothing::sRecordId)
@ -501,7 +508,7 @@ namespace MWClass
}
else
{
std::string model = equipped->getClass().getModel(*equipped);
std::string_view model = equipped->getClass().getModel(*equipped);
if (!model.empty())
models.push_back(model);
}
@ -510,14 +517,14 @@ namespace MWClass
}
// preload body parts
if (race)
if (const ESM::Race* race = esmStore->get<ESM::Race>().search(npc->mBase->mRace))
{
const std::vector<const ESM::BodyPart*>& parts
= MWRender::NpcAnimation::getBodyParts(race->mId, female, false, false);
for (const ESM::BodyPart* part : parts)
{
if (part && !part->mModel.empty())
models.push_back(Misc::ResourceHelpers::correctMeshPath(part->mModel));
models.push_back(part->mModel);
}
}
}

View file

@ -85,7 +85,7 @@ namespace MWClass
const MWWorld::Ptr& attacker, const osg::Vec3f& hitPosition, bool successful,
const MWMechanics::DamageSourceType sourceType) const override;
void getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector<std::string>& models) const override;
void getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector<std::string_view>& models) const override;
///< Get a list of models to preload that this object may use (directly or indirectly). default implementation:
///< list getModel().
@ -131,7 +131,9 @@ namespace MWClass
ESM::RefId getSoundIdFromSndGen(const MWWorld::Ptr& ptr, std::string_view name) const override;
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
std::string getCorrectedModel(const MWWorld::ConstPtr& ptr) const override;
float getSkill(const MWWorld::Ptr& ptr, ESM::RefId id) const override;

View file

@ -38,7 +38,7 @@ namespace MWClass
}
}
std::string Potion::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Potion::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Potion>(ptr);
}

View file

@ -47,7 +47,7 @@ namespace MWClass
const std::string& getInventoryIcon(const MWWorld::ConstPtr& ptr) const override;
///< Return name of inventory icon.
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
float getWeight(const MWWorld::ConstPtr& ptr) const override;

View file

@ -38,7 +38,7 @@ namespace MWClass
}
}
std::string Probe::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Probe::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Probe>(ptr);
}

View file

@ -54,7 +54,7 @@ namespace MWClass
std::unique_ptr<MWWorld::Action> use(const MWWorld::Ptr& ptr, bool force = false) const override;
///< Generate action for using via inventory menu
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
bool canSell(const MWWorld::ConstPtr& item, int npcServices) const override;

View file

@ -36,7 +36,7 @@ namespace MWClass
}
}
std::string Repair::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Repair::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Repair>(ptr);
}

View file

@ -44,7 +44,7 @@ namespace MWClass
const std::string& getInventoryIcon(const MWWorld::ConstPtr& ptr) const override;
///< Return name of inventory icon.
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
std::unique_ptr<MWWorld::Action> use(const MWWorld::Ptr& ptr, bool force = false) const override;
///< Generate action for using via inventory menu (default implementation: return a

View file

@ -43,7 +43,7 @@ namespace MWClass
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World);
}
std::string Static::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Static::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Static>(ptr);
}

View file

@ -32,7 +32,7 @@ namespace MWClass
bool hasToolTip(const MWWorld::ConstPtr& ptr) const override;
///< @return true if this object has a tooltip when focused (default implementation: true)
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
};
}

View file

@ -43,7 +43,7 @@ namespace MWClass
}
}
std::string Weapon::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Weapon::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Weapon>(ptr);
}

View file

@ -72,7 +72,7 @@ namespace MWClass
std::unique_ptr<MWWorld::Action> use(const MWWorld::Ptr& ptr, bool force = false) const override;
///< Generate action for using via inventory menu
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
std::string_view getModel(const MWWorld::ConstPtr& ptr) const override;
bool canSell(const MWWorld::ConstPtr& item, int npcServices) const override;

View file

@ -71,6 +71,12 @@ namespace MWLua
{
Obj mObj;
};
template <typename Obj>
struct Owner
{
Obj mObj;
};
}
#endif // MWLUA_OBJECT_H

View file

@ -200,6 +200,80 @@ namespace MWLua
return Misc::Convert::makeOsgQuat(pos.rot);
}
template <class ObjectT>
void addOwnerbindings(sol::usertype<ObjectT>& objectT, const std::string& prefix, const Context& context)
{
using OwnerT = Owner<ObjectT>;
sol::usertype<OwnerT> ownerT = context.mLua->sol().new_usertype<OwnerT>(prefix + "Owner");
ownerT[sol::meta_function::to_string] = [](const OwnerT& o) { return "Owner[" + o.mObj.toString() + "]"; };
auto getOwnerRecordId = [](const OwnerT& o) -> sol::optional<std::string> {
ESM::RefId owner = o.mObj.ptr().getCellRef().getOwner();
if (owner.empty())
return sol::nullopt;
else
return owner.serializeText();
};
auto setOwnerRecordId = [](const OwnerT& o, sol::optional<std::string_view> ownerId) {
if (std::is_same_v<ObjectT, LObject> && !dynamic_cast<const SelfObject*>(&o.mObj))
throw std::runtime_error("Local scripts can set an owner only on self");
const MWWorld::Ptr& ptr = o.mObj.ptr();
if (!ownerId)
{
ptr.getCellRef().setOwner(ESM::RefId());
return;
}
ESM::RefId owner = ESM::RefId::deserializeText(*ownerId);
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
if (!store.get<ESM::NPC>().search(owner))
throw std::runtime_error("Invalid owner record id");
ptr.getCellRef().setOwner(owner);
};
ownerT["recordId"] = sol::property(getOwnerRecordId, setOwnerRecordId);
auto getOwnerFactionId = [](const OwnerT& o) -> sol::optional<std::string> {
ESM::RefId owner = o.mObj.ptr().getCellRef().getFaction();
if (owner.empty())
return sol::nullopt;
else
return owner.serializeText();
};
auto setOwnerFactionId = [](const OwnerT& o, sol::optional<std::string> ownerId) {
ESM::RefId ownerFac;
if (std::is_same_v<ObjectT, LObject> && !dynamic_cast<const SelfObject*>(&o.mObj))
throw std::runtime_error("Local scripts can set an owner faction only on self");
if (!ownerId)
{
o.mObj.ptr().getCellRef().setFaction(ESM::RefId());
return;
}
ownerFac = ESM::RefId::deserializeText(*ownerId);
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
if (!store.get<ESM::Faction>().search(ownerFac))
throw std::runtime_error("Invalid owner faction id");
o.mObj.ptr().getCellRef().setFaction(ownerFac);
};
ownerT["factionId"] = sol::property(getOwnerFactionId, setOwnerFactionId);
auto getOwnerFactionRank = [](const OwnerT& o) -> sol::optional<int> {
int rank = o.mObj.ptr().getCellRef().getFactionRank();
if (rank < 0)
return sol::nullopt;
else
return rank;
};
auto setOwnerFactionRank = [](const OwnerT& o, sol::optional<int> factionRank) {
if (std::is_same_v<ObjectT, LObject> && !dynamic_cast<const SelfObject*>(&o.mObj))
throw std::runtime_error("Local scripts can set an owner faction rank only on self");
o.mObj.ptr().getCellRef().setFactionRank(factionRank.value_or(-1));
};
ownerT["factionRank"] = sol::property(getOwnerFactionRank, setOwnerFactionRank);
objectT["owner"] = sol::readonly_property([](const ObjectT& object) { return OwnerT{ object }; });
}
template <class ObjectT>
void addBasicBindings(sol::usertype<ObjectT>& objectT, const Context& context)
{
@ -266,68 +340,6 @@ namespace MWLua
context.mLuaEvents->addLocalEvent(
{ dest.id(), std::move(eventName), LuaUtil::serialize(eventData, context.mSerializer) });
};
auto getOwnerRecordId = [](const ObjectT& o) -> sol::optional<std::string> {
ESM::RefId owner = o.ptr().getCellRef().getOwner();
if (owner.empty())
return sol::nullopt;
else
return owner.serializeText();
};
auto setOwnerRecordId = [](const ObjectT& obj, sol::optional<std::string_view> ownerId) {
if (std::is_same_v<ObjectT, LObject> && !dynamic_cast<const SelfObject*>(&obj))
throw std::runtime_error("Local scripts can set an owner only on self");
const MWWorld::Ptr& ptr = obj.ptr();
if (!ownerId)
{
ptr.getCellRef().setOwner(ESM::RefId());
return;
}
ESM::RefId owner = ESM::RefId::deserializeText(*ownerId);
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
if (!store.get<ESM::NPC>().search(owner))
throw std::runtime_error("Invalid owner record id");
ptr.getCellRef().setOwner(owner);
};
objectT["ownerRecordId"] = sol::property(getOwnerRecordId, setOwnerRecordId);
auto getOwnerFactionId = [](const ObjectT& o) -> sol::optional<std::string> {
ESM::RefId owner = o.ptr().getCellRef().getFaction();
if (owner.empty())
return sol::nullopt;
else
return owner.serializeText();
};
auto setOwnerFactionId = [](const ObjectT& object, sol::optional<std::string> ownerId) {
ESM::RefId ownerFac;
if (std::is_same_v<ObjectT, LObject> && !dynamic_cast<const SelfObject*>(&object))
throw std::runtime_error("Local scripts can set an owner faction only on self");
if (!ownerId)
{
object.ptr().getCellRef().setFaction(ESM::RefId());
return;
}
ownerFac = ESM::RefId::deserializeText(*ownerId);
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
if (!store.get<ESM::Faction>().search(ownerFac))
throw std::runtime_error("Invalid owner faction id");
object.ptr().getCellRef().setFaction(ownerFac);
};
objectT["ownerFactionId"] = sol::property(getOwnerFactionId, setOwnerFactionId);
auto getOwnerFactionRank = [](const ObjectT& o) -> sol::optional<int> {
int rank = o.ptr().getCellRef().getFactionRank();
if (rank < 0)
return sol::nullopt;
else
return rank;
};
auto setOwnerFactionRank = [](const ObjectT& object, sol::optional<int> factionRank) {
if (std::is_same_v<ObjectT, LObject> && !dynamic_cast<const SelfObject*>(&object))
throw std::runtime_error("Local scripts can set an owner faction rank only on self");
object.ptr().getCellRef().setFactionRank(factionRank.value_or(-1));
};
objectT["ownerFactionRank"] = sol::property(getOwnerFactionRank, setOwnerFactionRank);
objectT["activateBy"] = [](const ObjectT& object, const ObjectT& actor) {
const MWWorld::Ptr& objPtr = object.ptr();
@ -672,6 +684,7 @@ namespace MWLua
= context.mLua->sol().new_usertype<ObjectT>(prefix + "Object", sol::base_classes, sol::bases<Object>());
addBasicBindings<ObjectT>(objectT, context);
addInventoryBindings<ObjectT>(objectT, prefix, context);
addOwnerbindings<ObjectT>(objectT, prefix, context);
registerObjectList<ObjectT>(prefix, context);
}

View file

@ -241,7 +241,7 @@ namespace MWLua
for (unsigned i = 0; i < newStack.size(); ++i)
newStack[i] = nameToMode.at(LuaUtil::cast<std::string_view>(modes[i + 1]));
luaManager->addAction(
[windowManager, newStack = std::move(newStack), arg]() {
[windowManager, newStack = std::move(newStack), arg = std::move(arg)]() {
MWWorld::Ptr ptr;
if (arg.has_value())
ptr = arg->ptr();

View file

@ -134,7 +134,7 @@ namespace MWRender
}
}
}
return shield.getClass().getModel(shield);
return shield.getClass().getCorrectedModel(shield);
}
std::string ActorAnimation::getSheathedShieldMesh(const MWWorld::ConstPtr& shield) const
@ -339,7 +339,7 @@ namespace MWRender
if (MWMechanics::getWeaponType(type)->mWeaponClass == ESM::WeaponType::Thrown)
showHolsteredWeapons = false;
std::string mesh = weapon->getClass().getModel(*weapon);
std::string mesh = weapon->getClass().getCorrectedModel(*weapon);
std::string scabbardName = mesh;
std::string_view boneName = getHolsteredWeaponBoneName(*weapon);
@ -409,7 +409,7 @@ namespace MWRender
if (weapon == inv.end() || weapon->getType() != ESM::Weapon::sRecordId)
return;
std::string mesh = weapon->getClass().getModel(*weapon);
std::string_view mesh = weapon->getClass().getModel(*weapon);
std::string_view boneName = getHolsteredWeaponBoneName(*weapon);
if (mesh.empty() || boneName.empty())
return;
@ -466,7 +466,7 @@ namespace MWRender
// Add new ones
osg::Vec4f glowColor = ammo->getClass().getEnchantmentColor(*ammo);
std::string model = ammo->getClass().getModel(*ammo);
std::string model = ammo->getClass().getCorrectedModel(*ammo);
for (unsigned int i = 0; i < ammoCount; ++i)
{
osg::ref_ptr<osg::Group> arrowNode = ammoNode->getChild(i)->asGroup();

View file

@ -110,7 +110,7 @@ namespace MWRender
MWWorld::ConstPtr item = *it;
std::string_view bonename;
std::string itemModel = item.getClass().getModel(item);
std::string itemModel = item.getClass().getCorrectedModel(item);
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
{
if (item.getType() == ESM::Weapon::sRecordId)

View file

@ -22,7 +22,7 @@ namespace MWRender
const MWWorld::Ptr& ptr, osg::ref_ptr<osg::Group> parentNode, Resource::ResourceSystem* resourceSystem)
: Animation(ptr, std::move(parentNode), resourceSystem)
{
setObjectRoot(mPtr.getClass().getModel(mPtr), true, true, false);
setObjectRoot(mPtr.getClass().getCorrectedModel(mPtr), true, true, false);
updateParts();
}

View file

@ -952,7 +952,7 @@ namespace MWRender
if (weapon != inv.end())
{
osg::Vec4f glowColor = weapon->getClass().getEnchantmentColor(*weapon);
std::string mesh = weapon->getClass().getModel(*weapon);
std::string mesh = weapon->getClass().getCorrectedModel(*weapon);
addOrReplaceIndividualPart(ESM::PRT_Weapon, MWWorld::InventoryStore::Slot_CarriedRight, 1, mesh,
!weapon->getClass().getEnchantment(*weapon).empty(), &glowColor);
@ -1012,7 +1012,7 @@ namespace MWRender
if (show && iter != inv.end())
{
osg::Vec4f glowColor = iter->getClass().getEnchantmentColor(*iter);
std::string mesh = iter->getClass().getModel(*iter);
std::string mesh = iter->getClass().getCorrectedModel(*iter);
// For shields we must try to use the body part model
if (iter->getType() == ESM::Armor::sRecordId)
{

View file

@ -1497,7 +1497,7 @@ namespace MWRender
osg::Vec3f RenderingManager::getHalfExtents(const MWWorld::ConstPtr& object) const
{
osg::Vec3f halfExtents(0, 0, 0);
std::string modelName = object.getClass().getModel(object);
std::string modelName = object.getClass().getCorrectedModel(object);
if (modelName.empty())
return halfExtents;
@ -1519,7 +1519,7 @@ namespace MWRender
osg::BoundingBox RenderingManager::getCullSafeBoundingBox(const MWWorld::Ptr& ptr) const
{
const std::string model = ptr.getClass().getModel(ptr);
const std::string model = ptr.getClass().getCorrectedModel(ptr);
if (model.empty())
return {};

View file

@ -86,7 +86,7 @@ namespace MWRender
MWWorld::ConstContainerStoreIterator ammo = inv.getSlot(MWWorld::InventoryStore::Slot_Ammunition);
if (ammo == inv.end())
return;
std::string model = ammo->getClass().getModel(*ammo);
std::string model = ammo->getClass().getCorrectedModel(*ammo);
osg::ref_ptr<osg::Node> arrow = getResourceSystem()->getSceneManager()->getInstance(model, parent);

View file

@ -1435,7 +1435,7 @@ namespace MWScript
msg << "Coordinates: " << pos.x() << " " << pos.y() << " " << pos.z() << std::endl;
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
std::string model
= ::Misc::ResourceHelpers::correctActorModelPath(ptr.getClass().getModel(ptr), vfs);
= ::Misc::ResourceHelpers::correctActorModelPath(ptr.getClass().getCorrectedModel(ptr), vfs);
msg << "Model: " << model << std::endl;
if (!model.empty())
{
@ -1711,7 +1711,7 @@ namespace MWScript
for (const T& record : store.get<T>())
{
MWWorld::ManualRef ref(store, record.mId);
std::string model = ref.getPtr().getClass().getModel(ref.getPtr());
std::string model = ref.getPtr().getClass().getCorrectedModel(ref.getPtr());
if (!model.empty())
{
sceneManager->getTemplate(model);

View file

@ -9,6 +9,7 @@
#include <components/loadinglistener/reporter.hpp>
#include <components/misc/constants.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/lower.hpp>
#include <components/resource/bulletshapemanager.hpp>
#include <components/resource/keyframemanager.hpp>
@ -59,7 +60,7 @@ namespace MWWorld
return true;
}
std::vector<std::string>& mOut;
std::vector<std::string_view>& mOut;
};
/// Worker thread item: preload models in a cell.
@ -105,30 +106,30 @@ namespace MWWorld
}
}
for (std::string& mesh : mMeshes)
std::string mesh;
std::string kfname;
for (std::string_view path : mMeshes)
{
if (mAbort)
break;
try
{
mesh = Misc::ResourceHelpers::correctMeshPath(path);
mesh = Misc::ResourceHelpers::correctActorModelPath(mesh, mSceneManager->getVFS());
size_t slashpos = mesh.find_last_of("/\\");
if (slashpos != std::string::npos && slashpos != mesh.size() - 1)
{
Misc::StringUtils::lowerCaseInPlace(mesh);
if (mesh[slashpos + 1] == 'x')
if (Misc::StringUtils::toLower(mesh[slashpos + 1]) == 'x'
&& Misc::StringUtils::ciEndsWith(mesh, ".nif"))
{
if (mesh.size() > 4 && mesh.ends_with(".nif"))
{
std::string kfname = mesh;
kfname = mesh;
kfname.replace(kfname.size() - 4, 4, ".kf");
if (mSceneManager->getVFS()->exists(kfname))
mPreloadedObjects.insert(mKeyframeManager->get(kfname));
}
}
}
mPreloadedObjects.insert(mSceneManager->getTemplate(mesh));
if (mPreloadInstances)
mPreloadedObjects.insert(mBulletShapeManager->cacheInstance(mesh));
@ -144,11 +145,10 @@ namespace MWWorld
}
private:
typedef std::vector<std::string> MeshList;
bool mIsExterior;
int mX;
int mY;
MeshList mMeshes;
std::vector<std::string_view> mMeshes;
Resource::SceneManager* mSceneManager;
Resource::BulletShapeManager* mBulletShapeManager;
Resource::KeyframeManager* mKeyframeManager;

View file

@ -6,6 +6,7 @@
#include <components/esm3/loadench.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadsoun.hpp>
#include <components/misc/resourcehelpers.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
@ -305,19 +306,27 @@ namespace MWWorld
void Class::adjustScale(const MWWorld::ConstPtr& ptr, osg::Vec3f& scale, bool rendering) const {}
std::string Class::getModel(const MWWorld::ConstPtr& ptr) const
std::string_view Class::getModel(const MWWorld::ConstPtr& ptr) const
{
return {};
}
std::string Class::getCorrectedModel(const MWWorld::ConstPtr& ptr) const
{
std::string_view model = getModel(ptr);
if (!model.empty())
return Misc::ResourceHelpers::correctMeshPath(model);
return {};
}
bool Class::useAnim() const
{
return false;
}
void Class::getModelsToPreload(const ConstPtr& ptr, std::vector<std::string>& models) const
void Class::getModelsToPreload(const ConstPtr& ptr, std::vector<std::string_view>& models) const
{
std::string model = getModel(ptr);
std::string_view model = getModel(ptr);
if (!model.empty())
models.push_back(model);
}

View file

@ -275,12 +275,14 @@ namespace MWWorld
virtual int getServices(const MWWorld::ConstPtr& actor) const;
virtual std::string getModel(const MWWorld::ConstPtr& ptr) const;
virtual std::string_view getModel(const MWWorld::ConstPtr& ptr) const;
virtual std::string getCorrectedModel(const MWWorld::ConstPtr& ptr) const;
virtual bool useAnim() const;
///< Whether or not to use animated variant of model (default false)
virtual void getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector<std::string>& models) const;
virtual void getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector<std::string_view>& models) const;
///< Get a list of models to preload that this object may use (directly or indirectly). default implementation:
///< list getModel().

View file

@ -311,7 +311,7 @@ namespace MWWorld
osg::Vec4 lightDiffuseColor = getMagicBoltLightDiffuseColor(state.mEffects);
auto model = ptr.getClass().getModel(ptr);
auto model = ptr.getClass().getCorrectedModel(ptr);
createModel(state, model, pos, orient, true, true, lightDiffuseColor, texture);
MWBase::SoundManager* sndMgr = MWBase::Environment::get().getSoundManager();
@ -351,7 +351,7 @@ namespace MWWorld
MWWorld::ManualRef ref(*MWBase::Environment::get().getESMStore(), projectile.getCellRef().getRefId());
MWWorld::Ptr ptr = ref.getPtr();
const auto model = ptr.getClass().getModel(ptr);
const auto model = ptr.getClass().getCorrectedModel(ptr);
createModel(state, model, pos, orient, false, false, osg::Vec4(0, 0, 0, 0));
if (!ptr.getClass().getEnchantment(ptr).empty())
SceneUtil::addEnchantedGlow(state.mNode, mResourceSystem, ptr.getClass().getEnchantmentColor(ptr));
@ -696,7 +696,7 @@ namespace MWWorld
{
MWWorld::ManualRef ref(*MWBase::Environment::get().getESMStore(), esm.mId);
MWWorld::Ptr ptr = ref.getPtr();
model = ptr.getClass().getModel(ptr);
model = ptr.getClass().getCorrectedModel(ptr);
int weaponType = ptr.get<ESM::Weapon>()->mBase->mData.mType;
state.mThrown = MWMechanics::getWeaponType(weaponType)->mWeaponClass == ESM::WeaponType::Thrown;
@ -749,7 +749,7 @@ namespace MWWorld
{
MWWorld::ManualRef ref(*MWBase::Environment::get().getESMStore(), state.mIdMagic.at(0));
MWWorld::Ptr ptr = ref.getPtr();
model = ptr.getClass().getModel(ptr);
model = ptr.getClass().getCorrectedModel(ptr);
}
catch (...)
{

View file

@ -96,7 +96,7 @@ namespace
{
if (Misc::ResourceHelpers::isHiddenMarker(ptr.getCellRef().getRefId()))
return {};
return ptr.getClass().getModel(ptr);
return ptr.getClass().getCorrectedModel(ptr);
}
void addObject(const MWWorld::Ptr& ptr, const MWWorld::World& world, const std::vector<ESM::RefNum>& pagedRefs,

View file

@ -2306,7 +2306,7 @@ namespace MWWorld
MWBase::Environment::get().getWindowManager()->watchActor(getPlayerPtr());
mPhysics->remove(getPlayerPtr());
mPhysics->addActor(getPlayerPtr(), getPlayerPtr().getClass().getModel(getPlayerPtr()));
mPhysics->addActor(getPlayerPtr(), getPlayerPtr().getClass().getCorrectedModel(getPlayerPtr()));
applyLoopingParticles(player);
@ -3696,7 +3696,7 @@ namespace MWWorld
try
{
MWWorld::ManualRef ref(store, obj);
std::string model = ref.getPtr().getClass().getModel(ref.getPtr());
std::string model = ref.getPtr().getClass().getCorrectedModel(ref.getPtr());
if (!model.empty())
scene->preload(model, ref.getPtr().getClass().useAnim());
}

View file

@ -10,18 +10,23 @@ set(LUA_API_FILES
string.doclua
table.doclua
openmw/ambient.lua
openmw/animation.lua
openmw/async.lua
openmw/camera.lua
openmw/core.lua
openmw/debug.lua
openmw/input.lua
openmw/interfaces.lua
openmw/menu.lua
openmw/nearby.lua
openmw/postprocessing.lua
openmw/self.lua
openmw/storage.lua
openmw/types.lua
openmw/ui.lua
openmw/util.lua
openmw/vfs.lua
openmw/world.lua
openmw/menu.lua
)
foreach (f ${LUA_API_FILES})

View file

@ -164,9 +164,7 @@
-- @field openmw.util#Transform rotation Object rotation.
-- @field openmw.util#Vector3 startingPosition The object original position
-- @field openmw.util#Transform startingRotation The object original rotation
-- @field #string ownerRecordId NPC who owns the object (nil if missing). Global and self scripts can set the value.
-- @field #string ownerFactionId Faction who owns the object (nil if missing). Global and self scripts can set the value.
-- @field #number ownerFactionRank Rank required to be allowed to pick up the object (`nil` if any rank is allowed). Global and self scripts can set the value.
-- @field #ObjectOwner owner Ownership information
-- @field #Cell cell The cell where the object currently is. During loading a game and for objects in an inventory or a container `cell` is nil.
-- @field #GameObject parentContainer Container or actor that contains (or has in inventory) this object. It is nil if the object is in a cell.
-- @field #any type Type of the object (one of the tables from the package @{openmw.types#types}).
@ -174,6 +172,14 @@
-- @field #string recordId Returns record ID of the object in lowercase.
-- @field #string globalVariable Global Variable associated with this object(read only).
---
-- Object owner information
-- @type ObjectOwner
-- @field #string recordId NPC who owns the object (nil if missing). Global and self scripts can set the value.
-- @field #string factionId Faction who owns the object (nil if missing). Global and self scripts can set the value.
-- @field #number factionRank Rank required to be allowed to pick up the object (`nil` if any rank is allowed). Global and self scripts can set the value.
---
-- Does the object still exist and is available.
-- Returns true if the object exists and loaded, and false otherwise. If false, then every