From 1905f0bf2dd8bb9000c033f89564ff3cac14f7ed Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 2 Jan 2016 00:49:53 +0100 Subject: [PATCH] Add support for placing BodyParts in a cell (Bug #3118) --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwclass/bodypart.cpp | 52 +++++++++++++++++++++++++++++++ apps/openmw/mwclass/bodypart.hpp | 31 ++++++++++++++++++ apps/openmw/mwclass/classes.cpp | 2 ++ apps/openmw/mwworld/cellstore.cpp | 7 +++++ apps/openmw/mwworld/cellstore.hpp | 10 ++++++ apps/openmw/mwworld/esmstore.cpp | 3 +- apps/openmw/mwworld/manualref.cpp | 1 + 8 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 apps/openmw/mwclass/bodypart.cpp create mode 100644 apps/openmw/mwclass/bodypart.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 0113fed02..02cf6c87d 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -75,7 +75,7 @@ add_openmw_dir (mwphysics add_openmw_dir (mwclass classes activator creature npc weapon armor potion apparatus book clothing container door - ingredient creaturelevlist itemlevlist light lockpick misc probe repair static actor + ingredient creaturelevlist itemlevlist light lockpick misc probe repair static actor bodypart ) add_openmw_dir (mwmechanics diff --git a/apps/openmw/mwclass/bodypart.cpp b/apps/openmw/mwclass/bodypart.cpp new file mode 100644 index 000000000..be2b927cc --- /dev/null +++ b/apps/openmw/mwclass/bodypart.cpp @@ -0,0 +1,52 @@ +#include "bodypart.hpp" + +#include "../mwrender/renderinginterface.hpp" +#include "../mwrender/objects.hpp" + +#include "../mwworld/cellstore.hpp" + +namespace MWClass +{ + + MWWorld::Ptr BodyPart::copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const + { + const MWWorld::LiveCellRef *ref = ptr.get(); + + return MWWorld::Ptr(cell.insert(ref), &cell); + } + + void BodyPart::insertObjectRendering(const MWWorld::Ptr &ptr, const std::string &model, MWRender::RenderingInterface &renderingInterface) const + { + if (!model.empty()) { + renderingInterface.getObjects().insertModel(ptr, model); + } + } + + void BodyPart::insertObject(const MWWorld::Ptr &ptr, const std::string &model, MWPhysics::PhysicsSystem &physics) const + { + } + + std::string BodyPart::getName(const MWWorld::ConstPtr &ptr) const + { + return std::string(); + } + + void BodyPart::registerSelf() + { + boost::shared_ptr instance (new BodyPart); + + registerClass (typeid (ESM::BodyPart).name(), instance); + } + + std::string BodyPart::getModel(const MWWorld::ConstPtr &ptr) const + { + const MWWorld::LiveCellRef *ref = ptr.get(); + + const std::string &model = ref->mBase->mModel; + if (!model.empty()) { + return "meshes\\" + model; + } + return ""; + } + +} diff --git a/apps/openmw/mwclass/bodypart.hpp b/apps/openmw/mwclass/bodypart.hpp new file mode 100644 index 000000000..79c7c860d --- /dev/null +++ b/apps/openmw/mwclass/bodypart.hpp @@ -0,0 +1,31 @@ +#ifndef GAME_MWCLASS_BODYPART_H +#define GAME_MWCLASS_BODYPART_H + +#include "../mwworld/class.hpp" + +namespace MWClass +{ + + class BodyPart : public MWWorld::Class + { + virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + + public: + + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + ///< Add reference into a cell for rendering + + virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + + virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + ///< \return name (the one that is to be presented to the user; not the internal one); + /// can return an empty string. + + static void registerSelf(); + + virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + }; + +} + +#endif diff --git a/apps/openmw/mwclass/classes.cpp b/apps/openmw/mwclass/classes.cpp index c303b23af..a552dfebf 100644 --- a/apps/openmw/mwclass/classes.cpp +++ b/apps/openmw/mwclass/classes.cpp @@ -20,6 +20,7 @@ #include "probe.hpp" #include "repair.hpp" #include "static.hpp" +#include "bodypart.hpp" namespace MWClass { @@ -45,5 +46,6 @@ namespace MWClass Probe::registerSelf(); Repair::registerSelf(); Static::registerSelf(); + BodyPart::registerSelf(); } } diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 08f272ea2..5b53643e8 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -591,6 +591,7 @@ namespace MWWorld case ESM::REC_REPA: mRepairs.load(ref, deleted, store); break; case ESM::REC_STAT: mStatics.load(ref, deleted, store); break; case ESM::REC_WEAP: mWeapons.load(ref, deleted, store); break; + case ESM::REC_BODY: mBodyParts.load(ref, deleted, store); break; case 0: std::cerr << "Cell reference " + ref.mRefID + " not found!\n"; break; @@ -659,6 +660,7 @@ namespace MWWorld writeReferenceCollection (writer, mRepairs); writeReferenceCollection (writer, mStatics); writeReferenceCollection (writer, mWeapons); + writeReferenceCollection (writer, mBodyParts); for (MovedRefTracker::const_iterator it = mMovedToAnotherCell.begin(); it != mMovedToAnotherCell.end(); ++it) { @@ -794,6 +796,11 @@ namespace MWWorld readReferenceCollection (reader, mWeapons, cref, contentFileMap); break; + case ESM::REC_BODY: + + readReferenceCollection (reader, mBodyParts, cref, contentFileMap); + break; + default: throw std::runtime_error ("unknown type in cell reference section"); diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 27fe9ec03..faba76262 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "../mwmechanics/pathgrid.hpp" // TODO: maybe belongs in mwworld @@ -97,6 +98,7 @@ namespace MWWorld CellRefList mRepairs; CellRefList mStatics; CellRefList mWeapons; + CellRefList mBodyParts; typedef std::map MovedRefTracker; // References owned by a different cell that have been moved here. @@ -152,6 +154,7 @@ namespace MWWorld forEachImp (visitor, mRepairs) && forEachImp (visitor, mStatics) && forEachImp (visitor, mWeapons) && + forEachImp (visitor, mBodyParts) && forEachImp (visitor, mCreatures) && forEachImp (visitor, mNpcs) && forEachImp (visitor, mCreatureLists); @@ -518,6 +521,13 @@ namespace MWWorld return mWeapons; } + template<> + inline CellRefList& CellStore::get() + { + mHasState = true; + return mBodyParts; + } + bool operator== (const CellStore& left, const CellStore& right); bool operator!= (const CellStore& left, const CellStore& right); } diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 1882c6e1a..7a1f222c7 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -19,7 +19,8 @@ static bool isCacheableRecord(int id) id == ESM::REC_BOOK || id == ESM::REC_CLOT || id == ESM::REC_CONT || id == ESM::REC_CREA || id == ESM::REC_DOOR || id == ESM::REC_INGR || id == ESM::REC_LEVC || id == ESM::REC_LEVI || id == ESM::REC_LIGH || id == ESM::REC_LOCK || id == ESM::REC_MISC || id == ESM::REC_NPC_ || - id == ESM::REC_PROB || id == ESM::REC_REPA || id == ESM::REC_STAT || id == ESM::REC_WEAP) + id == ESM::REC_PROB || id == ESM::REC_REPA || id == ESM::REC_STAT || id == ESM::REC_WEAP || + id == ESM::REC_BODY) { return true; } diff --git a/apps/openmw/mwworld/manualref.cpp b/apps/openmw/mwworld/manualref.cpp index d6e40ad09..c683f7e03 100644 --- a/apps/openmw/mwworld/manualref.cpp +++ b/apps/openmw/mwworld/manualref.cpp @@ -54,6 +54,7 @@ MWWorld::ManualRef::ManualRef(const MWWorld::ESMStore& store, const std::string& case ESM::REC_REPA: create(store.get(), lowerName, mRef, mPtr); break; case ESM::REC_STAT: create(store.get(), lowerName, mRef, mPtr); break; case ESM::REC_WEAP: create(store.get(), lowerName, mRef, mPtr); break; + case ESM::REC_BODY: create(store.get(), lowerName, mRef, mPtr); break; case 0: throw std::logic_error("failed to create manual cell ref for " + lowerName + " (unknown ID)");