1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-16 17:59:56 +00:00

Initial Lua bindings for ESM4 types; bindings for ESM4Door.

This commit is contained in:
Petr Mikheev 2023-04-10 14:30:25 +02:00
parent 16845aa38e
commit 00beb06391
8 changed files with 196 additions and 14 deletions

View file

@ -1,6 +1,7 @@
#include "types.hpp"
#include <components/esm3/loaddoor.hpp>
#include <components/esm4/loaddoor.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/resource/resourcesystem.hpp>
@ -15,6 +16,11 @@ namespace sol
struct is_automagical<ESM::Door> : std::false_type
{
};
template <>
struct is_automagical<ESM4::Door> : std::false_type
{
};
}
namespace MWLua
@ -25,6 +31,11 @@ namespace MWLua
return verifyType(ESM::REC_DOOR, o.ptr());
}
static const MWWorld::Ptr& door4Ptr(const Object& o)
{
return verifyType(ESM::REC_DOOR4, o.ptr());
}
void addDoorBindings(sol::table door, const Context& context)
{
door["isTeleport"] = [](const Object& o) { return doorPtr(o).getCellRef().getTeleport(); };
@ -62,4 +73,34 @@ namespace MWLua
[](const ESM::Door& rec) -> std::string { return rec.mCloseSound.serializeText(); });
}
void addESM4DoorBindings(sol::table door, const Context& context)
{
door["isTeleport"] = [](const Object& o) { return door4Ptr(o).getCellRef().getTeleport(); };
door["destPosition"]
= [](const Object& o) -> osg::Vec3f { return door4Ptr(o).getCellRef().getDoorDest().asVec3(); };
door["destRotation"]
= [](const Object& o) -> osg::Vec3f { return door4Ptr(o).getCellRef().getDoorDest().asRotationVec3(); };
door["destCell"] = [](sol::this_state lua, const Object& o) -> sol::object {
const MWWorld::CellRef& cellRef = door4Ptr(o).getCellRef();
if (!cellRef.getTeleport())
return sol::nil;
MWWorld::CellStore* cell = MWBase::Environment::get().getWorldModel()->getCell(cellRef.getDestCell());
assert(cell);
return o.getCell(lua, cell);
};
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
addRecordFunctionBinding<ESM4::Door>(door, context, "ESM4Door");
sol::usertype<ESM4::Door> record = context.mLua->sol().new_usertype<ESM4::Door>("ESM4_Door");
record[sol::meta_function::to_string]
= [](const ESM4::Door& rec) -> std::string { return "ESM4_Door[" + rec.mId.toDebugString() + "]"; };
record["id"]
= sol::readonly_property([](const ESM4::Door& rec) -> std::string { return rec.mId.serializeText(); });
record["name"] = sol::readonly_property([](const ESM4::Door& rec) -> std::string { return rec.mFullName; });
record["model"] = sol::readonly_property([vfs](const ESM4::Door& rec) -> std::string {
return Misc::ResourceHelpers::correctMeshPath(rec.mModel, vfs);
});
}
}

View file

@ -32,6 +32,20 @@ namespace MWLua
constexpr std::string_view Probe = "Probe";
constexpr std::string_view Repair = "Repair";
constexpr std::string_view Marker = "Marker";
constexpr std::string_view ESM4Activator = "ESM4Activator";
constexpr std::string_view ESM4Ammunition = "ESM4Ammunition";
constexpr std::string_view ESM4Armor = "ESM4Armor";
constexpr std::string_view ESM4Book = "ESM4Book";
constexpr std::string_view ESM4Clothing = "ESM4Clothing";
constexpr std::string_view ESM4Container = "ESM4Container";
constexpr std::string_view ESM4Door = "ESM4Door";
constexpr std::string_view ESM4Ingredient = "ESM4Ingredient";
constexpr std::string_view ESM4Light = "ESM4Light";
constexpr std::string_view ESM4MiscItem = "ESM4Miscellaneous";
constexpr std::string_view ESM4Potion = "ESM4Potion";
constexpr std::string_view ESM4Static = "ESM4Static";
constexpr std::string_view ESM4Weapon = "ESM4Weapon";
}
namespace
@ -57,6 +71,20 @@ namespace MWLua
{ ESM::REC_LOCK, ObjectTypeName::Lockpick },
{ ESM::REC_PROB, ObjectTypeName::Probe },
{ ESM::REC_REPA, ObjectTypeName::Repair },
{ ESM::REC_ACTI4, ObjectTypeName::ESM4Activator },
{ ESM::REC_AMMO4, ObjectTypeName::ESM4Ammunition },
{ ESM::REC_ARMO4, ObjectTypeName::ESM4Armor },
{ ESM::REC_BOOK4, ObjectTypeName::ESM4Book },
{ ESM::REC_CLOT4, ObjectTypeName::ESM4Clothing },
{ ESM::REC_CONT4, ObjectTypeName::ESM4Container },
{ ESM::REC_DOOR4, ObjectTypeName::ESM4Door },
{ ESM::REC_INGR4, ObjectTypeName::ESM4Ingredient },
{ ESM::REC_LIGH4, ObjectTypeName::ESM4Light },
{ ESM::REC_MISC4, ObjectTypeName::ESM4MiscItem },
{ ESM::REC_ALCH4, ObjectTypeName::ESM4Potion },
{ ESM::REC_STAT4, ObjectTypeName::ESM4Static },
{ ESM::REC_WEAP4, ObjectTypeName::ESM4Weapon },
};
}
@ -175,6 +203,20 @@ namespace MWLua
addDoorBindings(addType(ObjectTypeName::Door, { ESM::REC_DOOR }), context);
addStaticBindings(addType(ObjectTypeName::Static, { ESM::REC_STAT }), context);
addType(ObjectTypeName::ESM4Activator, { ESM::REC_ACTI4 });
addType(ObjectTypeName::ESM4Ammunition, { ESM::REC_AMMO4 });
addType(ObjectTypeName::ESM4Armor, { ESM::REC_ARMO4 });
addType(ObjectTypeName::ESM4Book, { ESM::REC_BOOK4 });
addType(ObjectTypeName::ESM4Clothing, { ESM::REC_CLOT4 });
addType(ObjectTypeName::ESM4Container, { ESM::REC_CONT4 });
addESM4DoorBindings(addType(ObjectTypeName::ESM4Door, { ESM::REC_DOOR4 }), context);
addType(ObjectTypeName::ESM4Ingredient, { ESM::REC_INGR4 });
addType(ObjectTypeName::ESM4Light, { ESM::REC_LIGH4 });
addType(ObjectTypeName::ESM4MiscItem, { ESM::REC_MISC4 });
addType(ObjectTypeName::ESM4Potion, { ESM::REC_ALCH4 });
addType(ObjectTypeName::ESM4Static, { ESM::REC_STAT4 });
addType(ObjectTypeName::ESM4Weapon, { ESM::REC_WEAP4 });
sol::table typeToPackage = getTypeToPackageTable(context.mLua->sol());
sol::table packageToType = getPackageToTypeTable(context.mLua->sol());
for (const auto& [type, name] : luaObjectTypeInfo)

View file

@ -63,8 +63,11 @@ namespace MWLua
void addStaticBindings(sol::table stat, const Context& context);
void addLightBindings(sol::table light, const Context& context);
void addESM4DoorBindings(sol::table door, const Context& context);
template <class T>
void addRecordFunctionBinding(sol::table table, const Context& context)
void addRecordFunctionBinding(
sol::table table, const Context& context, const std::string& recordName = std::string(T::getRecordType()))
{
const MWWorld::Store<T>& store = MWBase::Environment::get().getWorld()->getStore().get<T>();
@ -75,9 +78,9 @@ namespace MWLua
// Provide the interface of a read-only array.
using StoreT = MWWorld::Store<T>;
sol::state_view& lua = context.mLua->sol();
sol::usertype<StoreT> storeT = lua.new_usertype<StoreT>(std::string(T::getRecordType()) + "WorldStore");
storeT[sol::meta_function::to_string] = [](const StoreT& store) {
return "{" + std::to_string(store.getSize()) + " " + std::string(T::getRecordType()) + " records}";
sol::usertype<StoreT> storeT = lua.new_usertype<StoreT>(recordName + "WorldStore");
storeT[sol::meta_function::to_string] = [recordName](const StoreT& store) {
return "{" + std::to_string(store.getSize()) + " " + recordName + " records}";
};
storeT[sol::meta_function::length] = [](const StoreT& store) { return store.getSize(); };
storeT[sol::meta_function::index] = [](const StoreT& store, size_t index) -> const T* {

View file

@ -3,10 +3,15 @@
#include <cassert>
#include <components/debug/debuglog.hpp>
#include <components/esm/refid.hpp>
#include <components/esm3/loadcell.hpp>
#include <components/esm3/objectstate.hpp>
#include <components/esm4/loadrefr.hpp>
#include <apps/openmw/mwbase/environment.hpp>
#include <apps/openmw/mwbase/world.hpp>
#include <apps/openmw/mwworld/cellutils.hpp>
#include <apps/openmw/mwworld/esmstore.hpp>
namespace MWWorld
{
@ -90,13 +95,18 @@ namespace MWWorld
return ESM::RefId::esm3ExteriorCell(index.x(), index.y());
}
};
auto esm4Visit = [&](const ESM4::Reference& ref) -> ESM::RefId {
if (ref.mDoor.destDoor.isZeroOrUnset())
return ESM::RefId::sEmpty;
const ESM4::Reference* refDest
= MWBase::Environment::get().getWorld()->getStore().get<ESM4::Reference>().searchStatic(
ESM::FormIdRefId(ref.mDoor.destDoor));
if (refDest)
return refDest->mParent;
return ESM::RefId::sEmpty;
};
return std::visit(
ESM::VisitOverload{
[&](const ESM4::Reference& ref) -> ESM::RefId { return ESM::RefId::sEmpty; },
esm3Visit,
},
mCellRef.mVariant);
return std::visit(ESM::VisitOverload{ esm3Visit, esm4Visit }, mCellRef.mVariant);
}
void CellRef::setScale(float scale)

View file

@ -55,7 +55,7 @@ namespace MWWorld
struct Visitor
{
bool operator()(const ESM::CellRef& ref) { return ref.mTeleport; }
bool operator()(const ESM4::Reference& ref) { return 0; }
bool operator()(const ESM4::Reference& ref) { return !ref.mDoor.destDoor.isZeroOrUnset(); }
};
return std::visit(Visitor(), mCellRef.mVariant);
}

View file

@ -18,8 +18,8 @@ namespace ESM
bool hasContentFile() const { return mContentFile >= 0; }
bool isSet() const { return mIndex != 0 || mContentFile != -1; }
// Used in ESM4 as a null reference
bool isZero() const { return mIndex == 0 && mContentFile == 0; }
// Zero is used in ESM4 as a null reference
bool isZeroOrUnset() const { return mIndex == 0 && (mContentFile == 0 || mContentFile == -1); }
std::string toString() const;
FormId32 toUint32() const;

View file

@ -213,7 +213,7 @@ void ESM4::Land::load(ESM4::Reader& reader)
bool missing = false;
for (int i = 0; i < 4; ++i)
{
if (mTextures[i].base.formId.isZero())
if (mTextures[i].base.formId.isZeroOrUnset())
{
// std::cout << "ESM4::LAND " << ESM4::formIdToString(mFormId) << " missing base, quad " << i << std::endl;
// std::cout << "layers " << mTextures[i].layers.size() << std::endl;

View file

@ -1223,4 +1223,90 @@
-- @field #string id Record id
-- @field #string model VFS path to the model
--- Functions for @{#ESM4Activator} objects
-- @field [parent=#types] #ESM4Activator ESM4Activator
--- Functions for @{#ESM4Ammunition} objects
-- @field [parent=#types] #ESM4Ammunition ESM4Ammunition
--- Functions for @{#ESM4Armor} objects
-- @field [parent=#types] #ESM4Armor ESM4Armor
--- Functions for @{#ESM4Book} objects
-- @field [parent=#types] #ESM4Book ESM4Book
--- Functions for @{#ESM4Clothing} objects
-- @field [parent=#types] #ESM4Clothing ESM4Clothing
--- Functions for @{#ESM4Door} objects
-- @field [parent=#types] #ESM4Door ESM4Door
--- Functions for @{#ESM4Ingredient} objects
-- @field [parent=#types] #ESM4Ingredient ESM4Ingredient
--- Functions for @{#ESM4Light} objects
-- @field [parent=#types] #ESM4Light ESM4Light
--- Functions for @{#ESM4Miscellaneous} objects
-- @field [parent=#types] #ESM4Miscellaneous ESM4Miscellaneous
--- Functions for @{#ESM4Potion} objects
-- @field [parent=#types] #ESM4Potion ESM4Potion
--- Functions for @{#ESM4Static} objects
-- @field [parent=#types] #ESM4Static ESM4Static
--- Functions for @{#ESM4Weapon} objects
-- @field [parent=#types] #ESM4Weapon ESM4Weapon
---
-- @type ESM4Door
---
-- Whether the object is a ESM4Door.
-- @function [parent=#ESM4Door] objectIsInstance
-- @param openmw.core#GameObject object
-- @return #boolean
---
-- Whether the door is a teleport.
-- @function [parent=#ESM4Door] isTeleport
-- @param openmw.core#GameObject object
-- @return #boolean
---
-- Destination (only if a teleport door).
-- @function [parent=#ESM4Door] destPosition
-- @param openmw.core#GameObject object
-- @return openmw.util#Vector3
---
-- Destination rotation (only if a teleport door).
-- @function [parent=#ESM4Door] destRotation
-- @param openmw.core#GameObject object
-- @return openmw.util#Vector3
---
-- Destination cell (only if a teleport door).
-- @function [parent=#ESM4Door] destCell
-- @param openmw.core#GameObject object
-- @return openmw.core#Cell
---
-- Returns the read-only @{#ESM4DoorRecord} of a door
-- @function [parent=#ESM4Door] record
-- @param #any objectOrRecordId
-- @return #ESM4DoorRecord
---
-- Returns a read-only list of all @{#ESM4DoorRecord}s in the world database.
-- @function [parent=#ESM4Door] records
-- @return #list<#ESM4DoorRecord>
---
-- @type ESM4DoorRecord
-- @field #string id Record id
-- @field #string name Human-readable name
-- @field #string model VFS path to the model
return nil