mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-06 12:11:32 +00:00
Merge branch 'staticsload' into 'master'
Loads statics before actors II (#5379) See merge request OpenMW/openmw!588
This commit is contained in:
commit
4f264af5a9
51 changed files with 345 additions and 338 deletions
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
Bug #3737: Scripts from The Underground 2 .esp do not play (all patched versions)
|
Bug #3737: Scripts from The Underground 2 .esp do not play (all patched versions)
|
||||||
Bug #3846: Strings starting with "-" fail to compile if not enclosed in quotes
|
Bug #3846: Strings starting with "-" fail to compile if not enclosed in quotes
|
||||||
|
Bug #5379: Wandering NPCs falling through cantons
|
||||||
Bug #5453: Magic effect VFX are offset for creatures
|
Bug #5453: Magic effect VFX are offset for creatures
|
||||||
Bug #5483: AutoCalc flag is not used to calculate spells cost
|
Bug #5483: AutoCalc flag is not used to calculate spells cost
|
||||||
Bug #6066: addtopic "return" does not work from within script. No errors thrown
|
Bug #6066: addtopic "return" does not work from within script. No errors thrown
|
||||||
|
|
|
@ -38,10 +38,10 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Activator::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
void Activator::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
|
||||||
{
|
{
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr, model);
|
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Activator::getModel(const MWWorld::ConstPtr &ptr) const
|
std::string Activator::getModel(const MWWorld::ConstPtr &ptr) const
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
|
@ -17,16 +17,12 @@
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
Actor::Actor() {}
|
|
||||||
|
|
||||||
Actor::~Actor() {}
|
|
||||||
|
|
||||||
void Actor::adjustPosition(const MWWorld::Ptr& ptr, bool force) const
|
void Actor::adjustPosition(const MWWorld::Ptr& ptr, bool force) const
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorld()->adjustPosition(ptr, force);
|
MWBase::Environment::get().getWorld()->adjustPosition(ptr, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actor::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
void Actor::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
|
||||||
{
|
{
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,16 +15,16 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
Actor();
|
Actor() = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~Actor();
|
~Actor() override = default;
|
||||||
|
|
||||||
void adjustPosition(const MWWorld::Ptr& ptr, bool force) const override;
|
void adjustPosition(const MWWorld::Ptr& ptr, bool force) const override;
|
||||||
///< Adjust position to stand on ground. Must be called post model load
|
///< Adjust position to stand on ground. Must be called post model load
|
||||||
/// @param force do this even if the ptr is flying
|
/// @param force do this even if the ptr is flying
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
|
||||||
|
|
||||||
bool useAnim() const override;
|
bool useAnim() const override;
|
||||||
|
|
||||||
|
@ -46,8 +46,8 @@ namespace MWClass
|
||||||
float getCurrentSpeed(const MWWorld::Ptr& ptr) const override;
|
float getCurrentSpeed(const MWWorld::Ptr& ptr) const override;
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
Actor(const Actor&);
|
Actor(const Actor&) = delete;
|
||||||
Actor& operator= (const Actor&);
|
Actor& operator= (const Actor&) = delete;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,6 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Apparatus::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
|
||||||
{
|
|
||||||
// TODO: add option somewhere to enable collision for placeable objects
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Apparatus::getModel(const MWWorld::ConstPtr &ptr) const
|
std::string Apparatus::getModel(const MWWorld::ConstPtr &ptr) const
|
||||||
{
|
{
|
||||||
const MWWorld::LiveCellRef<ESM::Apparatus> *ref = ptr.get<ESM::Apparatus>();
|
const MWWorld::LiveCellRef<ESM::Apparatus> *ref = ptr.get<ESM::Apparatus>();
|
||||||
|
|
|
@ -17,8 +17,6 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
||||||
|
|
|
@ -34,11 +34,6 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Armor::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
|
||||||
{
|
|
||||||
// TODO: add option somewhere to enable collision for placeable objects
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Armor::getModel(const MWWorld::ConstPtr &ptr) const
|
std::string Armor::getModel(const MWWorld::ConstPtr &ptr) const
|
||||||
{
|
{
|
||||||
const MWWorld::LiveCellRef<ESM::Armor> *ref = ptr.get<ESM::Armor>();
|
const MWWorld::LiveCellRef<ESM::Armor> *ref = ptr.get<ESM::Armor>();
|
||||||
|
|
|
@ -16,8 +16,6 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,6 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BodyPart::insertObject(const MWWorld::Ptr &ptr, const std::string &model, MWPhysics::PhysicsSystem &physics) const
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string BodyPart::getName(const MWWorld::ConstPtr &ptr) const
|
std::string BodyPart::getName(const MWWorld::ConstPtr &ptr) const
|
||||||
{
|
{
|
||||||
return std::string();
|
return std::string();
|
||||||
|
|
|
@ -15,8 +15,6 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
||||||
|
|
|
@ -31,11 +31,6 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Book::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
|
||||||
{
|
|
||||||
// TODO: add option somewhere to enable collision for placeable objects
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Book::getModel(const MWWorld::ConstPtr &ptr) const
|
std::string Book::getModel(const MWWorld::ConstPtr &ptr) const
|
||||||
{
|
{
|
||||||
const MWWorld::LiveCellRef<ESM::Book> *ref = ptr.get<ESM::Book>();
|
const MWWorld::LiveCellRef<ESM::Book> *ref = ptr.get<ESM::Book>();
|
||||||
|
|
|
@ -14,8 +14,6 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
||||||
|
|
|
@ -29,11 +29,6 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clothing::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
|
||||||
{
|
|
||||||
// TODO: add option somewhere to enable collision for placeable objects
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Clothing::getModel(const MWWorld::ConstPtr &ptr) const
|
std::string Clothing::getModel(const MWWorld::ConstPtr &ptr) const
|
||||||
{
|
{
|
||||||
const MWWorld::LiveCellRef<ESM::Clothing> *ref = ptr.get<ESM::Clothing>();
|
const MWWorld::LiveCellRef<ESM::Clothing> *ref = ptr.get<ESM::Clothing>();
|
||||||
|
|
|
@ -14,8 +14,6 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
||||||
|
|
|
@ -106,10 +106,10 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Container::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
void Container::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
|
||||||
{
|
{
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr, model);
|
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Container::getModel(const MWWorld::ConstPtr &ptr) const
|
std::string Container::getModel(const MWWorld::ConstPtr &ptr) const
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
|
@ -55,10 +55,10 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Door::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
void Door::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
|
||||||
{
|
{
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr, model, MWPhysics::CollisionType_Door);
|
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_Door, skipAnimated);
|
||||||
|
|
||||||
// Resume the door's opening/closing animation if it wasn't finished
|
// Resume the door's opening/closing animation if it wasn't finished
|
||||||
if (ptr.getRefData().getCustomData())
|
if (ptr.getRefData().getCustomData())
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
|
||||||
|
|
||||||
bool isDoor() const override;
|
bool isDoor() const override;
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,6 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ingredient::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
|
||||||
{
|
|
||||||
// TODO: add option somewhere to enable collision for placeable objects
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Ingredient::getModel(const MWWorld::ConstPtr &ptr) const
|
std::string Ingredient::getModel(const MWWorld::ConstPtr &ptr) const
|
||||||
{
|
{
|
||||||
const MWWorld::LiveCellRef<ESM::Ingredient> *ref = ptr.get<ESM::Ingredient>();
|
const MWWorld::LiveCellRef<ESM::Ingredient> *ref = ptr.get<ESM::Ingredient>();
|
||||||
|
|
|
@ -14,8 +14,6 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace MWClass
|
||||||
renderingInterface.getObjects().insertModel(ptr, model, true, !(ref->mBase->mData.mFlags & ESM::Light::OffDefault));
|
renderingInterface.getObjects().insertModel(ptr, model, true, !(ref->mBase->mData.mFlags & ESM::Light::OffDefault));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Light::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
void Light::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Light> *ref =
|
MWWorld::LiveCellRef<ESM::Light> *ref =
|
||||||
ptr.get<ESM::Light>();
|
ptr.get<ESM::Light>();
|
||||||
|
@ -41,7 +41,7 @@ namespace MWClass
|
||||||
|
|
||||||
// TODO: add option somewhere to enable collision for placeable objects
|
// TODO: add option somewhere to enable collision for placeable objects
|
||||||
if (!model.empty() && (ref->mBase->mData.mFlags & ESM::Light::Carry) == 0)
|
if (!model.empty() && (ref->mBase->mData.mFlags & ESM::Light::Carry) == 0)
|
||||||
physics.addObject(ptr, model);
|
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated);
|
||||||
|
|
||||||
if (!ref->mBase->mSound.empty() && !(ref->mBase->mData.mFlags & ESM::Light::OffDefault))
|
if (!ref->mBase->mSound.empty() && !(ref->mBase->mData.mFlags & ESM::Light::OffDefault))
|
||||||
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->mBase->mSound, 1.0, 1.0,
|
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->mBase->mSound, 1.0, 1.0,
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
|
||||||
|
|
||||||
bool useAnim() const override;
|
bool useAnim() const override;
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,6 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lockpick::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
|
||||||
{
|
|
||||||
// TODO: add option somewhere to enable collision for placeable objects
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Lockpick::getModel(const MWWorld::ConstPtr &ptr) const
|
std::string Lockpick::getModel(const MWWorld::ConstPtr &ptr) const
|
||||||
{
|
{
|
||||||
const MWWorld::LiveCellRef<ESM::Lockpick> *ref = ptr.get<ESM::Lockpick>();
|
const MWWorld::LiveCellRef<ESM::Lockpick> *ref = ptr.get<ESM::Lockpick>();
|
||||||
|
|
|
@ -14,8 +14,6 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
||||||
|
|
|
@ -37,11 +37,6 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Miscellaneous::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
|
||||||
{
|
|
||||||
// TODO: add option somewhere to enable collision for placeable objects
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Miscellaneous::getModel(const MWWorld::ConstPtr &ptr) const
|
std::string Miscellaneous::getModel(const MWWorld::ConstPtr &ptr) const
|
||||||
{
|
{
|
||||||
const MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = ptr.get<ESM::Miscellaneous>();
|
const MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = ptr.get<ESM::Miscellaneous>();
|
||||||
|
|
|
@ -14,8 +14,6 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
||||||
|
|
|
@ -30,11 +30,6 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Potion::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
|
||||||
{
|
|
||||||
// TODO: add option somewhere to enable collision for placeable objects
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Potion::getModel(const MWWorld::ConstPtr &ptr) const
|
std::string Potion::getModel(const MWWorld::ConstPtr &ptr) const
|
||||||
{
|
{
|
||||||
const MWWorld::LiveCellRef<ESM::Potion> *ref = ptr.get<ESM::Potion>();
|
const MWWorld::LiveCellRef<ESM::Potion> *ref = ptr.get<ESM::Potion>();
|
||||||
|
|
|
@ -14,8 +14,6 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,6 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Probe::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
|
||||||
{
|
|
||||||
// TODO: add option somewhere to enable collision for placeable objects
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Probe::getModel(const MWWorld::ConstPtr &ptr) const
|
std::string Probe::getModel(const MWWorld::ConstPtr &ptr) const
|
||||||
{
|
{
|
||||||
const MWWorld::LiveCellRef<ESM::Probe> *ref = ptr.get<ESM::Probe>();
|
const MWWorld::LiveCellRef<ESM::Probe> *ref = ptr.get<ESM::Probe>();
|
||||||
|
|
|
@ -14,8 +14,6 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,6 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Repair::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
|
||||||
{
|
|
||||||
// TODO: add option somewhere to enable collision for placeable objects
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Repair::getModel(const MWWorld::ConstPtr &ptr) const
|
std::string Repair::getModel(const MWWorld::ConstPtr &ptr) const
|
||||||
{
|
{
|
||||||
const MWWorld::LiveCellRef<ESM::Repair> *ref = ptr.get<ESM::Repair>();
|
const MWWorld::LiveCellRef<ESM::Repair> *ref = ptr.get<ESM::Repair>();
|
||||||
|
|
|
@ -14,8 +14,6 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,10 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Static::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
void Static::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
|
||||||
{
|
{
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr, model);
|
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Static::getModel(const MWWorld::ConstPtr &ptr) const
|
std::string Static::getModel(const MWWorld::ConstPtr &ptr) const
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
|
@ -34,11 +34,6 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Weapon::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
|
|
||||||
{
|
|
||||||
// TODO: add option somewhere to enable collision for placeable objects
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Weapon::getModel(const MWWorld::ConstPtr &ptr) const
|
std::string Weapon::getModel(const MWWorld::ConstPtr &ptr) const
|
||||||
{
|
{
|
||||||
const MWWorld::LiveCellRef<ESM::Weapon> *ref = ptr.get<ESM::Weapon>();
|
const MWWorld::LiveCellRef<ESM::Weapon> *ref = ptr.get<ESM::Weapon>();
|
||||||
|
|
|
@ -15,8 +15,6 @@ namespace MWClass
|
||||||
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override;
|
||||||
///< Add reference into a cell for rendering
|
///< Add reference into a cell for rendering
|
||||||
|
|
||||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override;
|
|
||||||
|
|
||||||
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
std::string getName (const MWWorld::ConstPtr& ptr) const override;
|
||||||
///< \return name or ID; can return an empty string.
|
///< \return name or ID; can return an empty string.
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, Physic
|
||||||
updateScale();
|
updateScale();
|
||||||
|
|
||||||
if(!mRotationallyInvariant)
|
if(!mRotationallyInvariant)
|
||||||
updateRotation();
|
setRotation(mPtr.getRefData().getBaseNode()->getAttitude());
|
||||||
|
|
||||||
updatePosition();
|
updatePosition();
|
||||||
addCollisionMask(getCollisionMask());
|
addCollisionMask(getCollisionMask());
|
||||||
|
@ -197,10 +197,10 @@ osg::Vec3f Actor::getPreviousPosition() const
|
||||||
return mPreviousPosition;
|
return mPreviousPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actor::updateRotation ()
|
void Actor::setRotation(osg::Quat quat)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(mPositionMutex);
|
std::scoped_lock lock(mPositionMutex);
|
||||||
mRotation = mPtr.getRefData().getBaseNode()->getAttitude();
|
mRotation = quat;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Actor::isRotationallyInvariant() const
|
bool Actor::isRotationallyInvariant() const
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace MWPhysics
|
||||||
void enableCollisionBody(bool collision);
|
void enableCollisionBody(bool collision);
|
||||||
|
|
||||||
void updateScale();
|
void updateScale();
|
||||||
void updateRotation();
|
void setRotation(osg::Quat quat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the collision shape looks the same no matter how its Z rotated.
|
* Return true if the collision shape looks the same no matter how its Z rotated.
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
namespace MWPhysics
|
namespace MWPhysics
|
||||||
{
|
{
|
||||||
Object::Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance, int collisionType, PhysicsTaskScheduler* scheduler)
|
Object::Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance, osg::Quat rotation, int collisionType, PhysicsTaskScheduler* scheduler)
|
||||||
: mShapeInstance(shapeInstance)
|
: mShapeInstance(shapeInstance)
|
||||||
, mSolid(true)
|
, mSolid(true)
|
||||||
, mTaskScheduler(scheduler)
|
, mTaskScheduler(scheduler)
|
||||||
|
@ -27,7 +27,7 @@ namespace MWPhysics
|
||||||
mCollisionObject->setUserPointer(this);
|
mCollisionObject->setUserPointer(this);
|
||||||
|
|
||||||
setScale(ptr.getCellRef().getScale());
|
setScale(ptr.getCellRef().getScale());
|
||||||
setRotation(Misc::Convert::toBullet(ptr.getRefData().getBaseNode()->getAttitude()));
|
setRotation(rotation);
|
||||||
setOrigin(Misc::Convert::toBullet(ptr.getRefData().getPosition().asVec3()));
|
setOrigin(Misc::Convert::toBullet(ptr.getRefData().getPosition().asVec3()));
|
||||||
commitPositionChange();
|
commitPositionChange();
|
||||||
|
|
||||||
|
@ -51,10 +51,10 @@ namespace MWPhysics
|
||||||
mScaleUpdatePending = true;
|
mScaleUpdatePending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::setRotation(const btQuaternion& quat)
|
void Object::setRotation(osg::Quat quat)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(mPositionMutex);
|
std::unique_lock<std::mutex> lock(mPositionMutex);
|
||||||
mLocalTransform.setRotation(quat);
|
mLocalTransform.setRotation(Misc::Convert::toBullet(quat));
|
||||||
mTransformUpdatePending = true;
|
mTransformUpdatePending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
bool Object::isAnimated() const
|
bool Object::isAnimated() const
|
||||||
{
|
{
|
||||||
return !mShapeInstance->mAnimatedShapes.empty();
|
return mShapeInstance->isAnimated();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Object::animateCollisionShapes()
|
bool Object::animateCollisionShapes()
|
||||||
|
|
|
@ -26,12 +26,12 @@ namespace MWPhysics
|
||||||
class Object final : public PtrHolder
|
class Object final : public PtrHolder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance, int collisionType, PhysicsTaskScheduler* scheduler);
|
Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance, osg::Quat rotation, int collisionType, PhysicsTaskScheduler* scheduler);
|
||||||
~Object() override;
|
~Object() override;
|
||||||
|
|
||||||
const Resource::BulletShapeInstance* getShapeInstance() const;
|
const Resource::BulletShapeInstance* getShapeInstance() const;
|
||||||
void setScale(float scale);
|
void setScale(float scale);
|
||||||
void setRotation(const btQuaternion& quat);
|
void setRotation(osg::Quat quat);
|
||||||
void setOrigin(const btVector3& vec);
|
void setOrigin(const btVector3& vec);
|
||||||
void commitPositionChange();
|
void commitPositionChange();
|
||||||
btCollisionObject* getCollisionObject();
|
btCollisionObject* getCollisionObject();
|
||||||
|
|
|
@ -461,13 +461,18 @@ namespace MWPhysics
|
||||||
return heightField->second.get();
|
return heightField->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSystem::addObject (const MWWorld::Ptr& ptr, const std::string& mesh, int collisionType)
|
void PhysicsSystem::addObject (const MWWorld::Ptr& ptr, const std::string& mesh, osg::Quat rotation, int collisionType, bool skipAnimated)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance = mShapeManager->getInstance(mesh);
|
osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance = mShapeManager->getInstance(mesh);
|
||||||
if (!shapeInstance || !shapeInstance->getCollisionShape())
|
if (!shapeInstance || !shapeInstance->getCollisionShape())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto obj = std::make_shared<Object>(ptr, shapeInstance, collisionType, mTaskScheduler.get());
|
if (skipAnimated && shapeInstance->isAnimated())
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(!getObject(ptr));
|
||||||
|
|
||||||
|
auto obj = std::make_shared<Object>(ptr, shapeInstance, rotation, collisionType, mTaskScheduler.get());
|
||||||
mObjects.emplace(ptr, obj);
|
mObjects.emplace(ptr, obj);
|
||||||
|
|
||||||
if (obj->isAnimated())
|
if (obj->isAnimated())
|
||||||
|
@ -625,12 +630,12 @@ namespace MWPhysics
|
||||||
mTaskScheduler->updateSingleAabb(foundProjectile->second);
|
mTaskScheduler->updateSingleAabb(foundProjectile->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSystem::updateRotation(const MWWorld::Ptr &ptr)
|
void PhysicsSystem::updateRotation(const MWWorld::Ptr &ptr, osg::Quat rotate)
|
||||||
{
|
{
|
||||||
ObjectMap::iterator found = mObjects.find(ptr);
|
ObjectMap::iterator found = mObjects.find(ptr);
|
||||||
if (found != mObjects.end())
|
if (found != mObjects.end())
|
||||||
{
|
{
|
||||||
found->second->setRotation(Misc::Convert::toBullet(ptr.getRefData().getBaseNode()->getAttitude()));
|
found->second->setRotation(rotate);
|
||||||
mTaskScheduler->updateSingleAabb(found->second);
|
mTaskScheduler->updateSingleAabb(found->second);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -639,7 +644,7 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
if (!foundActor->second->isRotationallyInvariant())
|
if (!foundActor->second->isRotationallyInvariant())
|
||||||
{
|
{
|
||||||
foundActor->second->updateRotation();
|
foundActor->second->setRotation(rotate);
|
||||||
mTaskScheduler->updateSingleAabb(foundActor->second);
|
mTaskScheduler->updateSingleAabb(foundActor->second);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -122,7 +122,7 @@ namespace MWPhysics
|
||||||
void setWaterHeight(float height);
|
void setWaterHeight(float height);
|
||||||
void disableWater();
|
void disableWater();
|
||||||
|
|
||||||
void addObject (const MWWorld::Ptr& ptr, const std::string& mesh, int collisionType = CollisionType_World);
|
void addObject (const MWWorld::Ptr& ptr, const std::string& mesh, osg::Quat rotation, int collisionType = CollisionType_World, bool skipAnimated = false);
|
||||||
void addActor (const MWWorld::Ptr& ptr, const std::string& mesh);
|
void addActor (const MWWorld::Ptr& ptr, const std::string& mesh);
|
||||||
|
|
||||||
int addProjectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, const std::string& mesh, bool computeRadius, bool canTraverseWater);
|
int addProjectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, const std::string& mesh, bool computeRadius, bool canTraverseWater);
|
||||||
|
@ -143,7 +143,7 @@ namespace MWPhysics
|
||||||
void remove (const MWWorld::Ptr& ptr);
|
void remove (const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
void updateScale (const MWWorld::Ptr& ptr);
|
void updateScale (const MWWorld::Ptr& ptr);
|
||||||
void updateRotation (const MWWorld::Ptr& ptr);
|
void updateRotation (const MWWorld::Ptr& ptr, osg::Quat rotate);
|
||||||
void updatePosition (const MWWorld::Ptr& ptr);
|
void updatePosition (const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
void addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject);
|
void addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject);
|
||||||
|
|
|
@ -18,12 +18,23 @@ namespace MWWorld
|
||||||
if (ptr.getRefData().getBaseNode())
|
if (ptr.getRefData().getBaseNode())
|
||||||
{
|
{
|
||||||
ptr.getRefData().setBaseNode(nullptr);
|
ptr.getRefData().setBaseNode(nullptr);
|
||||||
mObjects.push_back (ptr);
|
|
||||||
}
|
}
|
||||||
|
mObjects.push_back (ptr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ListObjectsVisitor
|
||||||
|
{
|
||||||
|
std::vector<MWWorld::Ptr> mObjects;
|
||||||
|
|
||||||
|
bool operator() (MWWorld::Ptr ptr)
|
||||||
|
{
|
||||||
|
mObjects.push_back (ptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,16 +25,12 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
std::map<std::string, std::shared_ptr<Class> > Class::sClasses;
|
std::map<std::string, std::shared_ptr<Class> > Class::sClasses;
|
||||||
|
|
||||||
Class::Class() {}
|
|
||||||
|
|
||||||
Class::~Class() {}
|
|
||||||
|
|
||||||
void Class::insertObjectRendering (const Ptr& ptr, const std::string& mesh, MWRender::RenderingInterface& renderingInterface) const
|
void Class::insertObjectRendering (const Ptr& ptr, const std::string& mesh, MWRender::RenderingInterface& renderingInterface) const
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Class::insertObject(const Ptr& ptr, const std::string& mesh, MWPhysics::PhysicsSystem& physics) const
|
void Class::insertObject(const Ptr& ptr, const std::string& mesh, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <osg/Quat>
|
||||||
#include <osg/Vec4f>
|
#include <osg/Vec4f>
|
||||||
|
|
||||||
#include "ptr.hpp"
|
#include "ptr.hpp"
|
||||||
|
@ -57,13 +58,9 @@ namespace MWWorld
|
||||||
|
|
||||||
std::string mTypeName;
|
std::string mTypeName;
|
||||||
|
|
||||||
// not implemented
|
|
||||||
Class (const Class&);
|
|
||||||
Class& operator= (const Class&);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
Class();
|
Class() = default;
|
||||||
|
|
||||||
std::shared_ptr<Action> defaultItemActivate(const Ptr &ptr, const Ptr &actor) const;
|
std::shared_ptr<Action> defaultItemActivate(const Ptr &ptr, const Ptr &actor) const;
|
||||||
///< Generate default action for activating inventory items
|
///< Generate default action for activating inventory items
|
||||||
|
@ -72,14 +69,16 @@ namespace MWWorld
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual ~Class();
|
virtual ~Class() = default;
|
||||||
|
Class (const Class&) = delete;
|
||||||
|
Class& operator= (const Class&) = delete;
|
||||||
|
|
||||||
const std::string& getTypeName() const {
|
const std::string& getTypeName() const {
|
||||||
return mTypeName;
|
return mTypeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void insertObjectRendering (const Ptr& ptr, const std::string& mesh, MWRender::RenderingInterface& renderingInterface) const;
|
virtual void insertObjectRendering (const Ptr& ptr, const std::string& mesh, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
virtual void insertObject(const Ptr& ptr, const std::string& mesh, MWPhysics::PhysicsSystem& physics) const;
|
virtual void insertObject(const Ptr& ptr, const std::string& mesh, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const;
|
||||||
///< Add reference into a cell for rendering (default implementation: don't render anything).
|
///< Add reference into a cell for rendering (default implementation: don't render anything).
|
||||||
|
|
||||||
virtual std::string getName (const ConstPtr& ptr) const = 0;
|
virtual std::string getName (const ConstPtr& ptr) const = 0;
|
||||||
|
|
|
@ -73,18 +73,20 @@ namespace
|
||||||
* osg::Quat(xr, osg::Vec3(-1, 0, 0));
|
* osg::Quat(xr, osg::Vec3(-1, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNodeRotation(const MWWorld::Ptr& ptr, MWRender::RenderingManager& rendering, RotationOrder order)
|
osg::Quat makeNodeRotation(const MWWorld::Ptr& ptr, RotationOrder order)
|
||||||
{
|
{
|
||||||
if (!ptr.getRefData().getBaseNode())
|
const auto pos = ptr.getRefData().getPosition();
|
||||||
return;
|
|
||||||
|
|
||||||
rendering.rotateObject(ptr,
|
const auto rot = ptr.getClass().isActor() ? makeActorOsgQuat(pos)
|
||||||
ptr.getClass().isActor()
|
: (order == RotationOrder::inverse ? makeInversedOrderObjectOsgQuat(pos) : makeObjectOsgQuat(pos));
|
||||||
? makeActorOsgQuat(ptr.getRefData().getPosition())
|
|
||||||
: (order == RotationOrder::inverse
|
return rot;
|
||||||
? makeInversedOrderObjectOsgQuat(ptr.getRefData().getPosition())
|
}
|
||||||
: makeObjectOsgQuat(ptr.getRefData().getPosition()))
|
|
||||||
);
|
void setNodeRotation(const MWWorld::Ptr& ptr, MWRender::RenderingManager& rendering, osg::Quat rotation)
|
||||||
|
{
|
||||||
|
if (ptr.getRefData().getBaseNode())
|
||||||
|
rendering.rotateObject(ptr, rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getModel(const MWWorld::Ptr &ptr, const VFS::Manager *vfs)
|
std::string getModel(const MWWorld::Ptr &ptr, const VFS::Manager *vfs)
|
||||||
|
@ -101,7 +103,7 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
void addObject(const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics,
|
void addObject(const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics,
|
||||||
MWRender::RenderingManager& rendering, std::set<ESM::RefNum>& pagedRefs)
|
MWRender::RenderingManager& rendering, std::set<ESM::RefNum>& pagedRefs, bool onlyPhysics)
|
||||||
{
|
{
|
||||||
if (ptr.getRefData().getBaseNode() || physics.getActor(ptr))
|
if (ptr.getRefData().getBaseNode() || physics.getActor(ptr))
|
||||||
{
|
{
|
||||||
|
@ -109,19 +111,23 @@ namespace
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useAnim = ptr.getClass().useAnim();
|
|
||||||
std::string model = getModel(ptr, rendering.getResourceSystem()->getVFS());
|
std::string model = getModel(ptr, rendering.getResourceSystem()->getVFS());
|
||||||
|
const auto rotation = makeNodeRotation(ptr, RotationOrder::direct);
|
||||||
|
if (onlyPhysics && !physics.getObject(ptr) && !ptr.getClass().isActor())
|
||||||
|
{
|
||||||
|
// When we preload physics object we need to skip animated objects. They are dependant on the scene graph which doesn't yet exist.
|
||||||
|
ptr.getClass().insertObject (ptr, model, rotation, physics, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const ESM::RefNum& refnum = ptr.getCellRef().getRefNum();
|
const ESM::RefNum& refnum = ptr.getCellRef().getRefNum();
|
||||||
if (!refnum.hasContentFile() || pagedRefs.find(refnum) == pagedRefs.end())
|
if (!refnum.hasContentFile() || pagedRefs.find(refnum) == pagedRefs.end())
|
||||||
ptr.getClass().insertObjectRendering(ptr, model, rendering);
|
ptr.getClass().insertObjectRendering(ptr, model, rendering);
|
||||||
else
|
else
|
||||||
ptr.getRefData().setBaseNode(new SceneUtil::PositionAttitudeTransform); // FIXME remove this when physics code is fixed not to depend on basenode
|
ptr.getRefData().setBaseNode(new SceneUtil::PositionAttitudeTransform); // FIXME remove this when physics code is fixed not to depend on basenode
|
||||||
setNodeRotation(ptr, rendering, RotationOrder::direct);
|
setNodeRotation(ptr, rendering, rotation);
|
||||||
|
|
||||||
ptr.getClass().insertObject (ptr, model, physics);
|
if (ptr.getClass().useAnim())
|
||||||
|
|
||||||
if (useAnim)
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->add(ptr);
|
MWBase::Environment::get().getMechanicsManager()->add(ptr);
|
||||||
|
|
||||||
if (ptr.getClass().isActor())
|
if (ptr.getClass().isActor())
|
||||||
|
@ -129,6 +135,9 @@ namespace
|
||||||
|
|
||||||
// Restore effect particles
|
// Restore effect particles
|
||||||
MWBase::Environment::get().getWorld()->applyLoopingParticles(ptr);
|
MWBase::Environment::get().getWorld()->applyLoopingParticles(ptr);
|
||||||
|
|
||||||
|
if (!physics.getObject(ptr))
|
||||||
|
ptr.getClass().insertObject (ptr, model, rotation, physics);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addObject(const MWWorld::Ptr& ptr, const MWPhysics::PhysicsSystem& physics, DetourNavigator::Navigator& navigator)
|
void addObject(const MWWorld::Ptr& ptr, const MWPhysics::PhysicsSystem& physics, DetourNavigator::Navigator& navigator)
|
||||||
|
@ -199,11 +208,12 @@ namespace
|
||||||
{
|
{
|
||||||
MWWorld::CellStore& mCell;
|
MWWorld::CellStore& mCell;
|
||||||
Loading::Listener& mLoadingListener;
|
Loading::Listener& mLoadingListener;
|
||||||
|
bool mOnlyObjects;
|
||||||
bool mTest;
|
bool mTest;
|
||||||
|
|
||||||
std::vector<MWWorld::Ptr> mToInsert;
|
std::vector<MWWorld::Ptr> mToInsert;
|
||||||
|
|
||||||
InsertVisitor (MWWorld::CellStore& cell, Loading::Listener& loadingListener, bool test);
|
InsertVisitor (MWWorld::CellStore& cell, Loading::Listener& loadingListener, bool onlyObjects, bool test);
|
||||||
|
|
||||||
bool operator() (const MWWorld::Ptr& ptr);
|
bool operator() (const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
|
@ -211,8 +221,8 @@ namespace
|
||||||
void insert(AddObject&& addObject);
|
void insert(AddObject&& addObject);
|
||||||
};
|
};
|
||||||
|
|
||||||
InsertVisitor::InsertVisitor (MWWorld::CellStore& cell, Loading::Listener& loadingListener, bool test)
|
InsertVisitor::InsertVisitor (MWWorld::CellStore& cell, Loading::Listener& loadingListener, bool onlyObjects, bool test)
|
||||||
: mCell (cell), mLoadingListener (loadingListener), mTest(test)
|
: mCell (cell), mLoadingListener (loadingListener), mOnlyObjects(onlyObjects), mTest(test)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool InsertVisitor::operator() (const MWWorld::Ptr& ptr)
|
bool InsertVisitor::operator() (const MWWorld::Ptr& ptr)
|
||||||
|
@ -228,7 +238,7 @@ namespace
|
||||||
{
|
{
|
||||||
for (MWWorld::Ptr& ptr : mToInsert)
|
for (MWWorld::Ptr& ptr : mToInsert)
|
||||||
{
|
{
|
||||||
if (!ptr.getRefData().isDeleted() && ptr.getRefData().isEnabled())
|
if (!ptr.getRefData().isDeleted() && ptr.getRefData().isEnabled() && (!mOnlyObjects || !ptr.getClass().isActor()))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -261,6 +271,16 @@ namespace
|
||||||
return std::abs(cellPosition.first) + std::abs(cellPosition.second);
|
return std::abs(cellPosition.first) + std::abs(cellPosition.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isCellInCollection(int x, int y, MWWorld::Scene::CellStoreCollection& collection)
|
||||||
|
{
|
||||||
|
for (auto *cell : collection)
|
||||||
|
{
|
||||||
|
assert(cell->getCell()->isExterior());
|
||||||
|
if (x == cell->getCell()->getGridX() && y == cell->getCell()->getGridY())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -274,7 +294,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
if (!ptr.getRefData().getBaseNode()) return;
|
if (!ptr.getRefData().getBaseNode()) return;
|
||||||
ptr.getClass().insertObjectRendering(ptr, getModel(ptr, mRendering.getResourceSystem()->getVFS()), mRendering);
|
ptr.getClass().insertObjectRendering(ptr, getModel(ptr, mRendering.getResourceSystem()->getVFS()), mRendering);
|
||||||
setNodeRotation(ptr, mRendering, RotationOrder::direct);
|
setNodeRotation(ptr, mRendering, makeNodeRotation(ptr, RotationOrder::direct));
|
||||||
reloadTerrain();
|
reloadTerrain();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,8 +310,9 @@ namespace MWWorld
|
||||||
|
|
||||||
void Scene::updateObjectRotation(const Ptr &ptr, RotationOrder order)
|
void Scene::updateObjectRotation(const Ptr &ptr, RotationOrder order)
|
||||||
{
|
{
|
||||||
setNodeRotation(ptr, mRendering, order);
|
const auto rot = makeNodeRotation(ptr, order);
|
||||||
mPhysics->updateRotation(ptr);
|
setNodeRotation(ptr, mRendering, rot);
|
||||||
|
mPhysics->updateRotation(ptr, rot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::updateObjectScale(const Ptr &ptr)
|
void Scene::updateObjectScale(const Ptr &ptr)
|
||||||
|
@ -311,165 +332,213 @@ namespace MWWorld
|
||||||
mRendering.update (duration, paused);
|
mRendering.update (duration, paused);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::unloadCell (CellStoreCollection::iterator iter, bool test)
|
void Scene::unloadInactiveCell (CellStore* cell, bool test)
|
||||||
{
|
{
|
||||||
|
assert(mActiveCells.find(cell) == mActiveCells.end());
|
||||||
|
assert(mInactiveCells.find(cell) != mInactiveCells.end());
|
||||||
if (!test)
|
if (!test)
|
||||||
Log(Debug::Info) << "Unloading cell " << (*iter)->getCell()->getDescription();
|
Log(Debug::Info) << "Unloading cell " << cell->getCell()->getDescription();
|
||||||
|
|
||||||
|
ListObjectsVisitor visitor;
|
||||||
|
|
||||||
|
cell->forEach(visitor);
|
||||||
|
for (const auto& ptr : visitor.mObjects)
|
||||||
|
mPhysics->remove(ptr);
|
||||||
|
|
||||||
|
if (cell->getCell()->isExterior())
|
||||||
|
{
|
||||||
|
const auto cellX = cell->getCell()->getGridX();
|
||||||
|
const auto cellY = cell->getCell()->getGridY();
|
||||||
|
mPhysics->removeHeightField(cellX, cellY);
|
||||||
|
}
|
||||||
|
|
||||||
|
mInactiveCells.erase(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::deactivateCell(CellStore* cell, bool test)
|
||||||
|
{
|
||||||
|
assert(mInactiveCells.find(cell) != mInactiveCells.end());
|
||||||
|
if (mActiveCells.find(cell) == mActiveCells.end())
|
||||||
|
return;
|
||||||
|
if (!test)
|
||||||
|
Log(Debug::Info) << "Deactivate cell " << cell->getCell()->getDescription();
|
||||||
|
|
||||||
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
||||||
ListAndResetObjectsVisitor visitor;
|
ListAndResetObjectsVisitor visitor;
|
||||||
|
|
||||||
(*iter)->forEach(visitor);
|
cell->forEach(visitor);
|
||||||
const auto world = MWBase::Environment::get().getWorld();
|
const auto world = MWBase::Environment::get().getWorld();
|
||||||
for (const auto& ptr : visitor.mObjects)
|
for (const auto& ptr : visitor.mObjects)
|
||||||
{
|
{
|
||||||
if (const auto object = mPhysics->getObject(ptr))
|
if (const auto object = mPhysics->getObject(ptr))
|
||||||
|
{
|
||||||
navigator->removeObject(DetourNavigator::ObjectId(object));
|
navigator->removeObject(DetourNavigator::ObjectId(object));
|
||||||
|
if (object->isAnimated())
|
||||||
|
mPhysics->remove(ptr);
|
||||||
|
}
|
||||||
else if (mPhysics->getActor(ptr))
|
else if (mPhysics->getActor(ptr))
|
||||||
{
|
{
|
||||||
navigator->removeAgent(world->getPathfindingHalfExtents(ptr));
|
navigator->removeAgent(world->getPathfindingHalfExtents(ptr));
|
||||||
mRendering.removeActorPath(ptr);
|
mRendering.removeActorPath(ptr);
|
||||||
|
mPhysics->remove(ptr);
|
||||||
}
|
}
|
||||||
mPhysics->remove(ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto cellX = (*iter)->getCell()->getGridX();
|
const auto cellX = cell->getCell()->getGridX();
|
||||||
const auto cellY = (*iter)->getCell()->getGridY();
|
const auto cellY = cell->getCell()->getGridY();
|
||||||
|
|
||||||
if ((*iter)->getCell()->isExterior())
|
if (cell->getCell()->isExterior())
|
||||||
{
|
{
|
||||||
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
||||||
navigator->removeObject(DetourNavigator::ObjectId(heightField));
|
navigator->removeObject(DetourNavigator::ObjectId(heightField));
|
||||||
mPhysics->removeHeightField(cellX, cellY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*iter)->getCell()->hasWater())
|
if (cell->getCell()->hasWater())
|
||||||
navigator->removeWater(osg::Vec2i(cellX, cellY));
|
navigator->removeWater(osg::Vec2i(cellX, cellY));
|
||||||
|
|
||||||
if (const auto pathgrid = world->getStore().get<ESM::Pathgrid>().search(*(*iter)->getCell()))
|
if (const auto pathgrid = world->getStore().get<ESM::Pathgrid>().search(*cell->getCell()))
|
||||||
navigator->removePathgrid(*pathgrid);
|
navigator->removePathgrid(*pathgrid);
|
||||||
|
|
||||||
const auto player = world->getPlayerPtr();
|
const auto player = world->getPlayerPtr();
|
||||||
navigator->update(player.getRefData().getPosition().asVec3());
|
navigator->update(player.getRefData().getPosition().asVec3());
|
||||||
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->drop (*iter);
|
MWBase::Environment::get().getMechanicsManager()->drop (cell);
|
||||||
|
|
||||||
mRendering.removeCell(*iter);
|
mRendering.removeCell(cell);
|
||||||
MWBase::Environment::get().getWindowManager()->removeCell(*iter);
|
MWBase::Environment::get().getWindowManager()->removeCell(cell);
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->getLocalScripts().clearCell (*iter);
|
MWBase::Environment::get().getWorld()->getLocalScripts().clearCell (cell);
|
||||||
|
|
||||||
MWBase::Environment::get().getSoundManager()->stopSound (*iter);
|
MWBase::Environment::get().getSoundManager()->stopSound (cell);
|
||||||
mActiveCells.erase(*iter);
|
mActiveCells.erase(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::loadCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn, bool test)
|
void Scene::activateCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn, bool test)
|
||||||
{
|
{
|
||||||
std::pair<CellStoreCollection::iterator, bool> result = mActiveCells.insert(cell);
|
assert(mActiveCells.find(cell) == mActiveCells.end());
|
||||||
|
assert(mInactiveCells.find(cell) != mInactiveCells.end());
|
||||||
|
mActiveCells.insert(cell);
|
||||||
|
|
||||||
if(result.second)
|
if (test)
|
||||||
|
Log(Debug::Info) << "Testing cell " << cell->getCell()->getDescription();
|
||||||
|
else
|
||||||
|
Log(Debug::Info) << "Loading cell " << cell->getCell()->getDescription();
|
||||||
|
|
||||||
|
const auto world = MWBase::Environment::get().getWorld();
|
||||||
|
const auto navigator = world->getNavigator();
|
||||||
|
|
||||||
|
const int cellX = cell->getCell()->getGridX();
|
||||||
|
const int cellY = cell->getCell()->getGridY();
|
||||||
|
|
||||||
|
if (!test && cell->getCell()->isExterior())
|
||||||
{
|
{
|
||||||
if (test)
|
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
||||||
Log(Debug::Info) << "Testing cell " << cell->getCell()->getDescription();
|
navigator->addObject(DetourNavigator::ObjectId(heightField), *heightField->getShape(),
|
||||||
else
|
heightField->getCollisionObject()->getWorldTransform());
|
||||||
Log(Debug::Info) << "Loading cell " << cell->getCell()->getDescription();
|
}
|
||||||
|
|
||||||
float verts = ESM::Land::LAND_SIZE;
|
if (const auto pathgrid = world->getStore().get<ESM::Pathgrid>().search(*cell->getCell()))
|
||||||
float worldsize = ESM::Land::REAL_SIZE;
|
navigator->addPathgrid(*cell->getCell(), *pathgrid);
|
||||||
|
|
||||||
const auto world = MWBase::Environment::get().getWorld();
|
// register local scripts
|
||||||
const auto navigator = world->getNavigator();
|
// do this before insertCell, to make sure we don't add scripts from levelled creature spawning twice
|
||||||
|
MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell);
|
||||||
|
|
||||||
const int cellX = cell->getCell()->getGridX();
|
if (respawn)
|
||||||
const int cellY = cell->getCell()->getGridY();
|
cell->respawn();
|
||||||
|
|
||||||
// Load terrain physics first...
|
insertCell (*cell, loadingListener, false, test);
|
||||||
if (!test && cell->getCell()->isExterior())
|
|
||||||
|
mRendering.addCell(cell);
|
||||||
|
if (!test)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->addCell(cell);
|
||||||
|
bool waterEnabled = cell->getCell()->hasWater() || cell->isExterior();
|
||||||
|
float waterLevel = cell->getWaterLevel();
|
||||||
|
mRendering.setWaterEnabled(waterEnabled);
|
||||||
|
if (waterEnabled)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<const ESMTerrain::LandObject> land = mRendering.getLandManager()->getLand(cellX, cellY);
|
mPhysics->enableWater(waterLevel);
|
||||||
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr;
|
mRendering.setWaterHeight(waterLevel);
|
||||||
if (data)
|
|
||||||
|
if (cell->getCell()->isExterior())
|
||||||
{
|
{
|
||||||
mPhysics->addHeightField (data->mHeights, cellX, cellY, worldsize / (verts-1), verts, data->mMinHeight, data->mMaxHeight, land.get());
|
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
||||||
}
|
navigator->addWater(osg::Vec2i(cellX, cellY), ESM::Land::REAL_SIZE,
|
||||||
else
|
|
||||||
{
|
|
||||||
static std::vector<float> defaultHeight;
|
|
||||||
defaultHeight.resize(verts*verts, ESM::Land::DEFAULT_HEIGHT);
|
|
||||||
mPhysics->addHeightField (&defaultHeight[0], cell->getCell()->getGridX(), cell->getCell()->getGridY(), worldsize / (verts-1), verts, ESM::Land::DEFAULT_HEIGHT, ESM::Land::DEFAULT_HEIGHT, land.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
|
||||||
navigator->addObject(DetourNavigator::ObjectId(heightField), *heightField->getShape(),
|
|
||||||
heightField->getCollisionObject()->getWorldTransform());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const auto pathgrid = world->getStore().get<ESM::Pathgrid>().search(*cell->getCell()))
|
|
||||||
navigator->addPathgrid(*cell->getCell(), *pathgrid);
|
|
||||||
|
|
||||||
// register local scripts
|
|
||||||
// do this before insertCell, to make sure we don't add scripts from levelled creature spawning twice
|
|
||||||
MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell);
|
|
||||||
|
|
||||||
if (respawn)
|
|
||||||
cell->respawn();
|
|
||||||
|
|
||||||
// ... then references. This is important for adjustPosition to work correctly.
|
|
||||||
insertCell (*cell, loadingListener, test);
|
|
||||||
|
|
||||||
mRendering.addCell(cell);
|
|
||||||
if (!test)
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getWindowManager()->addCell(cell);
|
|
||||||
bool waterEnabled = cell->getCell()->hasWater() || cell->isExterior();
|
|
||||||
float waterLevel = cell->getWaterLevel();
|
|
||||||
mRendering.setWaterEnabled(waterEnabled);
|
|
||||||
if (waterEnabled)
|
|
||||||
{
|
|
||||||
mPhysics->enableWater(waterLevel);
|
|
||||||
mRendering.setWaterHeight(waterLevel);
|
|
||||||
|
|
||||||
if (cell->getCell()->isExterior())
|
|
||||||
{
|
|
||||||
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
|
||||||
navigator->addWater(osg::Vec2i(cellX, cellY), ESM::Land::REAL_SIZE,
|
|
||||||
cell->getWaterLevel(), heightField->getCollisionObject()->getWorldTransform());
|
cell->getWaterLevel(), heightField->getCollisionObject()->getWorldTransform());
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
navigator->addWater(osg::Vec2i(cellX, cellY), std::numeric_limits<int>::max(),
|
|
||||||
cell->getWaterLevel(), btTransform::getIdentity());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mPhysics->disableWater();
|
|
||||||
|
|
||||||
const auto player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
||||||
|
|
||||||
// By default the player is grounded, with the scene fully loaded, we validate and correct this.
|
|
||||||
if (player.mCell == cell) // Only run once, during initial cell load.
|
|
||||||
{
|
{
|
||||||
mPhysics->traceDown(player, player.getRefData().getPosition().asVec3(), 10.f);
|
navigator->addWater(osg::Vec2i(cellX, cellY), std::numeric_limits<int>::max(),
|
||||||
}
|
cell->getWaterLevel(), btTransform::getIdentity());
|
||||||
|
|
||||||
navigator->update(player.getRefData().getPosition().asVec3());
|
|
||||||
|
|
||||||
if (!cell->isExterior() && !(cell->getCell()->mData.mFlags & ESM::Cell::QuasiEx))
|
|
||||||
{
|
|
||||||
mRendering.configureAmbient(cell->getCell());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
mPhysics->disableWater();
|
||||||
|
|
||||||
|
const auto player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
|
|
||||||
|
// By default the player is grounded, with the scene fully loaded, we validate and correct this.
|
||||||
|
if (player.mCell == cell) // Only run once, during initial cell load.
|
||||||
|
{
|
||||||
|
mPhysics->traceDown(player, player.getRefData().getPosition().asVec3(), 10.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
navigator->update(player.getRefData().getPosition().asVec3());
|
||||||
|
|
||||||
|
if (!cell->isExterior() && !(cell->getCell()->mData.mFlags & ESM::Cell::QuasiEx))
|
||||||
|
mRendering.configureAmbient(cell->getCell());
|
||||||
}
|
}
|
||||||
|
|
||||||
mPreloader->notifyLoaded(cell);
|
mPreloader->notifyLoaded(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scene::loadInactiveCell (CellStore *cell, Loading::Listener* loadingListener, bool test)
|
||||||
|
{
|
||||||
|
assert(mActiveCells.find(cell) == mActiveCells.end());
|
||||||
|
assert(mInactiveCells.find(cell) == mInactiveCells.end());
|
||||||
|
mInactiveCells.insert(cell);
|
||||||
|
|
||||||
|
if (test)
|
||||||
|
Log(Debug::Info) << "Testing inactive cell " << cell->getCell()->getDescription();
|
||||||
|
else
|
||||||
|
Log(Debug::Info) << "Loading inactive cell " << cell->getCell()->getDescription();
|
||||||
|
|
||||||
|
if (!test && cell->getCell()->isExterior())
|
||||||
|
{
|
||||||
|
float verts = ESM::Land::LAND_SIZE;
|
||||||
|
float worldsize = ESM::Land::REAL_SIZE;
|
||||||
|
|
||||||
|
const int cellX = cell->getCell()->getGridX();
|
||||||
|
const int cellY = cell->getCell()->getGridY();
|
||||||
|
|
||||||
|
osg::ref_ptr<const ESMTerrain::LandObject> land = mRendering.getLandManager()->getLand(cellX, cellY);
|
||||||
|
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr;
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
mPhysics->addHeightField (data->mHeights, cellX, cellY, worldsize / (verts-1), verts, data->mMinHeight, data->mMaxHeight, land.get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static std::vector<float> defaultHeight;
|
||||||
|
defaultHeight.resize(verts*verts, ESM::Land::DEFAULT_HEIGHT);
|
||||||
|
mPhysics->addHeightField (&defaultHeight[0], cellX, cellY, worldsize / (verts-1), verts, ESM::Land::DEFAULT_HEIGHT, ESM::Land::DEFAULT_HEIGHT, land.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
insertCell (*cell, loadingListener, true, test);
|
||||||
|
}
|
||||||
|
|
||||||
void Scene::clear()
|
void Scene::clear()
|
||||||
{
|
{
|
||||||
CellStoreCollection::iterator active = mActiveCells.begin();
|
for (auto iter = mInactiveCells.begin(); iter!=mInactiveCells.end(); )
|
||||||
while (active!=mActiveCells.end())
|
{
|
||||||
unloadCell (active++);
|
auto* cell = *iter++;
|
||||||
|
deactivateCell(cell);
|
||||||
|
unloadInactiveCell (cell);
|
||||||
|
}
|
||||||
assert(mActiveCells.empty());
|
assert(mActiveCells.empty());
|
||||||
|
assert(mInactiveCells.empty());
|
||||||
mCurrentCell = nullptr;
|
mCurrentCell = nullptr;
|
||||||
|
|
||||||
mPreloader->clear();
|
mPreloader->clear();
|
||||||
|
@ -512,20 +581,24 @@ namespace MWWorld
|
||||||
|
|
||||||
void Scene::changeCellGrid (const osg::Vec3f &pos, int playerCellX, int playerCellY, bool changeEvent)
|
void Scene::changeCellGrid (const osg::Vec3f &pos, int playerCellX, int playerCellY, bool changeEvent)
|
||||||
{
|
{
|
||||||
CellStoreCollection::iterator active = mActiveCells.begin();
|
for (auto iter = mInactiveCells.begin(); iter != mInactiveCells.end(); )
|
||||||
while (active!=mActiveCells.end())
|
|
||||||
{
|
{
|
||||||
if ((*active)->getCell()->isExterior())
|
auto* cell = *iter++;
|
||||||
|
if (cell->getCell()->isExterior())
|
||||||
{
|
{
|
||||||
if (std::abs (playerCellX-(*active)->getCell()->getGridX())<=mHalfGridSize &&
|
const auto dx = std::abs(playerCellX - cell->getCell()->getGridX());
|
||||||
std::abs (playerCellY-(*active)->getCell()->getGridY())<=mHalfGridSize)
|
const auto dy = std::abs(playerCellY - cell->getCell()->getGridY());
|
||||||
{
|
if (dx > mHalfGridSize || dy > mHalfGridSize)
|
||||||
// keep cells within the new grid
|
deactivateCell(cell);
|
||||||
++active;
|
|
||||||
continue;
|
if (dx > mHalfGridSize+1 || dy > mHalfGridSize+1)
|
||||||
}
|
unloadInactiveCell(cell);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deactivateCell(cell);
|
||||||
|
unloadInactiveCell(cell);
|
||||||
}
|
}
|
||||||
unloadCell (active++);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentGridCenter = osg::Vec2i(playerCellX, playerCellY);
|
mCurrentGridCenter = osg::Vec2i(playerCellX, playerCellY);
|
||||||
|
@ -537,32 +610,24 @@ namespace MWWorld
|
||||||
mRendering.getPagedRefnums(newGrid, mPagedRefs);
|
mRendering.getPagedRefnums(newGrid, mPagedRefs);
|
||||||
|
|
||||||
std::size_t refsToLoad = 0;
|
std::size_t refsToLoad = 0;
|
||||||
std::vector<std::pair<int, int>> cellsPositionsToLoad;
|
const auto cellsToLoad = [&playerCellX,&playerCellY,&refsToLoad](CellStoreCollection& collection, int range) -> std::vector<std::pair<int,int>>
|
||||||
// get the number of refs to load
|
|
||||||
for (int x = playerCellX - mHalfGridSize; x <= playerCellX + mHalfGridSize; ++x)
|
|
||||||
{
|
{
|
||||||
for (int y = playerCellY - mHalfGridSize; y <= playerCellY + mHalfGridSize; ++y)
|
std::vector<std::pair<int, int>> cellsPositionsToLoad;
|
||||||
|
for (int x = playerCellX - range; x <= playerCellX + range; ++x)
|
||||||
{
|
{
|
||||||
CellStoreCollection::iterator iter = mActiveCells.begin();
|
for (int y = playerCellY - range; y <= playerCellY + range; ++y)
|
||||||
|
|
||||||
while (iter!=mActiveCells.end())
|
|
||||||
{
|
{
|
||||||
assert ((*iter)->getCell()->isExterior());
|
if (!isCellInCollection(x, y, collection))
|
||||||
|
{
|
||||||
if (x==(*iter)->getCell()->getGridX() &&
|
refsToLoad += MWBase::Environment::get().getWorld()->getExterior(x, y)->count();
|
||||||
y==(*iter)->getCell()->getGridY())
|
cellsPositionsToLoad.emplace_back(x, y);
|
||||||
break;
|
}
|
||||||
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iter==mActiveCells.end())
|
|
||||||
{
|
|
||||||
refsToLoad += MWBase::Environment::get().getWorld()->getExterior(x, y)->count();
|
|
||||||
cellsPositionsToLoad.emplace_back(x, y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return cellsPositionsToLoad;
|
||||||
|
};
|
||||||
|
auto cellsPositionsToLoad = cellsToLoad(mActiveCells,mHalfGridSize);
|
||||||
|
auto cellsPositionsToLoadInactive = cellsToLoad(mInactiveCells,mHalfGridSize+1);
|
||||||
|
|
||||||
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
||||||
Loading::ScopedLoad load(loadingListener);
|
Loading::ScopedLoad load(loadingListener);
|
||||||
|
@ -585,30 +650,26 @@ namespace MWWorld
|
||||||
return getCellPositionPriority(lhs) < getCellPositionPriority(rhs);
|
return getCellPositionPriority(lhs) < getCellPositionPriority(rhs);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
std::sort(cellsPositionsToLoadInactive.begin(), cellsPositionsToLoadInactive.end(),
|
||||||
|
[&] (const std::pair<int, int>& lhs, const std::pair<int, int>& rhs) {
|
||||||
|
return getCellPositionPriority(lhs) < getCellPositionPriority(rhs);
|
||||||
|
});
|
||||||
|
|
||||||
// Load cells
|
// Load cells
|
||||||
for (const auto& cellPosition : cellsPositionsToLoad)
|
for (const auto& [x,y] : cellsPositionsToLoadInactive)
|
||||||
{
|
{
|
||||||
const auto x = cellPosition.first;
|
if (!isCellInCollection(x, y, mInactiveCells))
|
||||||
const auto y = cellPosition.second;
|
|
||||||
|
|
||||||
CellStoreCollection::iterator iter = mActiveCells.begin();
|
|
||||||
|
|
||||||
while (iter != mActiveCells.end())
|
|
||||||
{
|
|
||||||
assert ((*iter)->getCell()->isExterior());
|
|
||||||
|
|
||||||
if (x == (*iter)->getCell()->getGridX() &&
|
|
||||||
y == (*iter)->getCell()->getGridY())
|
|
||||||
break;
|
|
||||||
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iter == mActiveCells.end())
|
|
||||||
{
|
{
|
||||||
CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(x, y);
|
CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(x, y);
|
||||||
|
loadInactiveCell (cell, loadingListener);
|
||||||
loadCell (cell, loadingListener, changeEvent);
|
}
|
||||||
|
}
|
||||||
|
for (const auto& [x,y] : cellsPositionsToLoad)
|
||||||
|
{
|
||||||
|
if (!isCellInCollection(x, y, mActiveCells))
|
||||||
|
{
|
||||||
|
CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(x, y);
|
||||||
|
activateCell (cell, loadingListener, changeEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,7 +704,8 @@ namespace MWWorld
|
||||||
CellStoreCollection::iterator iter = mActiveCells.begin();
|
CellStoreCollection::iterator iter = mActiveCells.begin();
|
||||||
|
|
||||||
CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(it->mData.mX, it->mData.mY);
|
CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(it->mData.mX, it->mData.mY);
|
||||||
loadCell (cell, loadingListener, false, true);
|
loadInactiveCell (cell, loadingListener, true);
|
||||||
|
activateCell (cell, loadingListener, false, true);
|
||||||
|
|
||||||
iter = mActiveCells.begin();
|
iter = mActiveCells.begin();
|
||||||
while (iter != mActiveCells.end())
|
while (iter != mActiveCells.end())
|
||||||
|
@ -651,7 +713,8 @@ namespace MWWorld
|
||||||
if (it->isExterior() && it->mData.mX == (*iter)->getCell()->getGridX() &&
|
if (it->isExterior() && it->mData.mX == (*iter)->getCell()->getGridX() &&
|
||||||
it->mData.mY == (*iter)->getCell()->getGridY())
|
it->mData.mY == (*iter)->getCell()->getGridY())
|
||||||
{
|
{
|
||||||
unloadCell(iter, true);
|
deactivateCell(*iter, true);
|
||||||
|
unloadInactiveCell (*iter, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,7 +752,8 @@ namespace MWWorld
|
||||||
loadingListener->setLabel("Testing interior cells ("+std::to_string(i)+"/"+std::to_string(cells.getIntSize())+")...");
|
loadingListener->setLabel("Testing interior cells ("+std::to_string(i)+"/"+std::to_string(cells.getIntSize())+")...");
|
||||||
|
|
||||||
CellStore *cell = MWBase::Environment::get().getWorld()->getInterior(it->mName);
|
CellStore *cell = MWBase::Environment::get().getWorld()->getInterior(it->mName);
|
||||||
loadCell (cell, loadingListener, false, true);
|
loadInactiveCell (cell, loadingListener, true);
|
||||||
|
activateCell (cell, loadingListener, false, true);
|
||||||
|
|
||||||
CellStoreCollection::iterator iter = mActiveCells.begin();
|
CellStoreCollection::iterator iter = mActiveCells.begin();
|
||||||
while (iter != mActiveCells.end())
|
while (iter != mActiveCells.end())
|
||||||
|
@ -698,7 +762,8 @@ namespace MWWorld
|
||||||
|
|
||||||
if (it->mName == (*iter)->getCell()->mName)
|
if (it->mName == (*iter)->getCell()->mName)
|
||||||
{
|
{
|
||||||
unloadCell(iter, true);
|
deactivateCell(*iter, true);
|
||||||
|
unloadInactiveCell (*iter, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -820,15 +885,21 @@ namespace MWWorld
|
||||||
Log(Debug::Info) << "Changing to interior";
|
Log(Debug::Info) << "Changing to interior";
|
||||||
|
|
||||||
// unload
|
// unload
|
||||||
CellStoreCollection::iterator active = mActiveCells.begin();
|
for (auto iter = mInactiveCells.begin(); iter!=mInactiveCells.end(); )
|
||||||
while (active!=mActiveCells.end())
|
{
|
||||||
unloadCell (active++);
|
auto* cell = *iter++;
|
||||||
|
deactivateCell(cell);
|
||||||
|
unloadInactiveCell(cell);
|
||||||
|
}
|
||||||
|
assert(mActiveCells.empty());
|
||||||
|
assert(mInactiveCells.empty());
|
||||||
|
|
||||||
loadingListener->setProgressRange(cell->count());
|
loadingListener->setProgressRange(cell->count());
|
||||||
|
|
||||||
// Load cell.
|
// Load cell.
|
||||||
mPagedRefs.clear();
|
mPagedRefs.clear();
|
||||||
loadCell (cell, loadingListener, changeEvent);
|
loadInactiveCell (cell, loadingListener);
|
||||||
|
activateCell (cell, loadingListener, changeEvent);
|
||||||
|
|
||||||
changePlayerCell(cell, position, adjustPlayerPos);
|
changePlayerCell(cell, position, adjustPlayerPos);
|
||||||
|
|
||||||
|
@ -878,23 +949,26 @@ namespace MWWorld
|
||||||
mCellChanged = false;
|
mCellChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::insertCell (CellStore &cell, Loading::Listener* loadingListener, bool test)
|
void Scene::insertCell (CellStore &cell, Loading::Listener* loadingListener, bool onlyObjects, bool test)
|
||||||
{
|
{
|
||||||
InsertVisitor insertVisitor (cell, *loadingListener, test);
|
InsertVisitor insertVisitor (cell, *loadingListener, onlyObjects, test);
|
||||||
cell.forEach (insertVisitor);
|
cell.forEach (insertVisitor);
|
||||||
insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, *mPhysics, mRendering, mPagedRefs); });
|
insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, *mPhysics, mRendering, mPagedRefs, onlyObjects); });
|
||||||
insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, *mPhysics, mNavigator); });
|
if (!onlyObjects)
|
||||||
|
{
|
||||||
|
insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, *mPhysics, mNavigator); });
|
||||||
|
|
||||||
// do adjustPosition (snapping actors to ground) after objects are loaded, so we don't depend on the loading order
|
// do adjustPosition (snapping actors to ground) after objects are loaded, so we don't depend on the loading order
|
||||||
PositionVisitor posVisitor;
|
PositionVisitor posVisitor;
|
||||||
cell.forEach (posVisitor);
|
cell.forEach (posVisitor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::addObjectToScene (const Ptr& ptr)
|
void Scene::addObjectToScene (const Ptr& ptr)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
addObject(ptr, *mPhysics, mRendering, mPagedRefs);
|
addObject(ptr, *mPhysics, mRendering, mPagedRefs, false);
|
||||||
addObject(ptr, *mPhysics, mNavigator);
|
addObject(ptr, *mPhysics, mNavigator);
|
||||||
MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().getScale());
|
MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().getScale());
|
||||||
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
||||||
|
|
|
@ -64,13 +64,13 @@ namespace MWWorld
|
||||||
class Scene
|
class Scene
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using CellStoreCollection = std::set<CellStore *>;
|
||||||
typedef std::set<CellStore *> CellStoreCollection;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
CellStore* mCurrentCell; // the cell the player is in
|
CellStore* mCurrentCell; // the cell the player is in
|
||||||
CellStoreCollection mActiveCells;
|
CellStoreCollection mActiveCells;
|
||||||
|
CellStoreCollection mInactiveCells;
|
||||||
bool mCellChanged;
|
bool mCellChanged;
|
||||||
MWPhysics::PhysicsSystem *mPhysics;
|
MWPhysics::PhysicsSystem *mPhysics;
|
||||||
MWRender::RenderingManager& mRendering;
|
MWRender::RenderingManager& mRendering;
|
||||||
|
@ -91,7 +91,7 @@ namespace MWWorld
|
||||||
|
|
||||||
std::set<ESM::RefNum> mPagedRefs;
|
std::set<ESM::RefNum> mPagedRefs;
|
||||||
|
|
||||||
void insertCell (CellStore &cell, Loading::Listener* loadingListener, bool test = false);
|
void insertCell (CellStore &cell, Loading::Listener* loadingListener, bool onlyObjects, bool test = false);
|
||||||
osg::Vec2i mCurrentGridCenter;
|
osg::Vec2i mCurrentGridCenter;
|
||||||
|
|
||||||
// Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center
|
// Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center
|
||||||
|
@ -107,6 +107,11 @@ namespace MWWorld
|
||||||
osg::Vec4i gridCenterToBounds(const osg::Vec2i ¢erCell) const;
|
osg::Vec4i gridCenterToBounds(const osg::Vec2i ¢erCell) const;
|
||||||
osg::Vec2i getNewGridCenter(const osg::Vec3f &pos, const osg::Vec2i *currentGridCenter = nullptr) const;
|
osg::Vec2i getNewGridCenter(const osg::Vec3f &pos, const osg::Vec2i *currentGridCenter = nullptr) const;
|
||||||
|
|
||||||
|
void unloadInactiveCell (CellStore* cell, bool test = false);
|
||||||
|
void deactivateCell (CellStore* cell, bool test = false);
|
||||||
|
void activateCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn, bool test = false);
|
||||||
|
void loadInactiveCell (CellStore *cell, Loading::Listener* loadingListener, bool test = false);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Scene (MWRender::RenderingManager& rendering, MWPhysics::PhysicsSystem *physics,
|
Scene (MWRender::RenderingManager& rendering, MWPhysics::PhysicsSystem *physics,
|
||||||
|
@ -118,10 +123,6 @@ namespace MWWorld
|
||||||
void preloadTerrain(const osg::Vec3f& pos, bool sync=false);
|
void preloadTerrain(const osg::Vec3f& pos, bool sync=false);
|
||||||
void reloadTerrain();
|
void reloadTerrain();
|
||||||
|
|
||||||
void unloadCell (CellStoreCollection::iterator iter, bool test = false);
|
|
||||||
|
|
||||||
void loadCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn, bool test = false);
|
|
||||||
|
|
||||||
void playerMoved (const osg::Vec3f& pos);
|
void playerMoved (const osg::Vec3f& pos);
|
||||||
|
|
||||||
void changePlayerCell (CellStore* newCell, const ESM::Position& position, bool adjustPlayerPos);
|
void changePlayerCell (CellStore* newCell, const ESM::Position& position, bool adjustPlayerPos);
|
||||||
|
|
|
@ -1421,7 +1421,7 @@ namespace MWWorld
|
||||||
mWorldScene->removeFromPagedRefs(ptr);
|
mWorldScene->removeFromPagedRefs(ptr);
|
||||||
|
|
||||||
mRendering->rotateObject(ptr, rotate);
|
mRendering->rotateObject(ptr, rotate);
|
||||||
mPhysics->updateRotation(ptr);
|
mPhysics->updateRotation(ptr, rotate);
|
||||||
|
|
||||||
if (const auto object = mPhysics->getObject(ptr))
|
if (const auto object = mPhysics->getObject(ptr))
|
||||||
updateNavigatorObject(object);
|
updateNavigatorObject(object);
|
||||||
|
|
|
@ -95,6 +95,11 @@ void BulletShape::setLocalScaling(const btVector3& scale)
|
||||||
mAvoidCollisionShape->setLocalScaling(scale);
|
mAvoidCollisionShape->setLocalScaling(scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BulletShape::isAnimated() const
|
||||||
|
{
|
||||||
|
return !mAnimatedShapes.empty();
|
||||||
|
}
|
||||||
|
|
||||||
osg::ref_ptr<BulletShapeInstance> BulletShape::makeInstance() const
|
osg::ref_ptr<BulletShapeInstance> BulletShape::makeInstance() const
|
||||||
{
|
{
|
||||||
osg::ref_ptr<BulletShapeInstance> instance (new BulletShapeInstance(this));
|
osg::ref_ptr<BulletShapeInstance> instance (new BulletShapeInstance(this));
|
||||||
|
|
|
@ -52,6 +52,8 @@ namespace Resource
|
||||||
|
|
||||||
void setLocalScaling(const btVector3& scale);
|
void setLocalScaling(const btVector3& scale);
|
||||||
|
|
||||||
|
bool isAnimated() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void deleteShape(btCollisionShape* shape);
|
void deleteShape(btCollisionShape* shape);
|
||||||
|
|
Loading…
Reference in a new issue