1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-20 05:53:50 +00:00

Merge remote-tracking branch 'scrawl/doors'

This commit is contained in:
Marc Zinnschlag 2013-04-28 16:44:11 +02:00
commit 116ac05677
11 changed files with 159 additions and 10 deletions

View file

@ -54,7 +54,7 @@ add_openmw_dir (mwworld
containerstore actiontalk actiontake manualref player cellfunctors failedaction
cells localscripts customdata weather inventorystore ptr actionopen actionread
actionequip timestamp actionalchemy cellstore actionapply actioneat
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
)
add_openmw_dir (mwclass

View file

@ -326,6 +326,9 @@ namespace MWBase
virtual void setupPlayer(bool newGame) = 0;
virtual void renderPlayer() = 0;
virtual void activateDoor(const MWWorld::Ptr& door) = 0;
///< activate (open or close) an non-teleport door
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0;
virtual int canRest() = 0;

View file

@ -12,6 +12,7 @@
#include "../mwworld/nullaction.hpp"
#include "../mwworld/failedaction.hpp"
#include "../mwworld/actionteleport.hpp"
#include "../mwworld/actiondoor.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/inventorystore.hpp"
@ -71,7 +72,7 @@ namespace MWClass
ptr.get<ESM::Door>();
const std::string &openSound = ref->mBase->mOpenSound;
//const std::string &closeSound = ref->mBase->closeSound;
const std::string &closeSound = ref->mBase->mCloseSound;
const std::string lockedSound = "LockedDoor";
const std::string trapActivationSound = "Disarm Trap Fail";
@ -139,12 +140,11 @@ namespace MWClass
else
{
// animated door
// TODO return action for rotating the door
// This is a little pointless, but helps with testing
boost::shared_ptr<MWWorld::Action> action(new MWWorld::NullAction);
action->setSound(openSound);
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionDoor(ptr));
if (ptr.getRefData().getLocalRotation().rot[2] == 0)
action->setSound(openSound);
else
action->setSound(closeSound);
return action;
}

View file

@ -0,0 +1,16 @@
#include "actiondoor.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
namespace MWWorld
{
ActionDoor::ActionDoor (const MWWorld::Ptr& object) : Action (false, object)
{
}
void ActionDoor::executeImp (const MWWorld::Ptr& actor)
{
MWBase::Environment::get().getWorld()->activateDoor(getTarget());
}
}

View file

@ -0,0 +1,18 @@
#ifndef GAME_MWWORLD_ACTIONDOOR_H
#define GAME_MWWORLD_ACTIONDOOR_H
#include "action.hpp"
#include "ptr.hpp"
namespace MWWorld
{
class ActionDoor : public Action
{
virtual void executeImp (const MWWorld::Ptr& actor);
public:
ActionDoor (const Ptr& object);
};
}
#endif

View file

@ -131,7 +131,6 @@ namespace MWWorld
return position;
}
static Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time,
bool gravity, OEngine::Physic::PhysicEngine *engine)
{
@ -390,6 +389,11 @@ namespace MWWorld
}
}
std::vector<std::string> PhysicsSystem::getCollisions(const Ptr &ptr)
{
return mEngine->getCollisions(ptr.getRefData().getBaseNode()->getName());
}
Ogre::Vector3 PhysicsSystem::move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time, bool gravity)
{
return MovementSolver::move(ptr, movement, time, gravity, mEngine);

View file

@ -51,6 +51,7 @@ namespace MWWorld
bool toggleCollisionMode();
Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time, bool gravity);
std::vector<std::string> getCollisions(const MWWorld::Ptr &ptr); ///< get handles this object collides with
Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr);
std::pair<float, std::string> getFacedHandle (MWWorld::World& world, float queryDistance);

View file

@ -978,10 +978,53 @@ namespace MWWorld
!isSwimming(player->first) && !isFlying(player->first));
moveObjectImp(player->first, vec.x, vec.y, vec.z);
}
// the only purpose this has currently is to update the debug drawer
processDoors(duration);
mPhysEngine->stepSimulation (duration);
}
void World::processDoors(float duration)
{
std::map<MWWorld::Ptr, int>::iterator it = mDoorStates.begin();
while (it != mDoorStates.end())
{
if (!mWorldScene->isCellActive(*it->first.getCell()))
mDoorStates.erase(it++);
else
{
float oldRot = Ogre::Radian(it->first.getRefData().getLocalRotation().rot[2]).valueDegrees();
float diff = duration * 90;
float targetRot = std::min(std::max(0.f, oldRot + diff * (it->second ? 1 : -1)), 90.f);
localRotateObject(it->first, 0, 0, targetRot);
std::vector<std::string> collisions = mPhysics->getCollisions(it->first);
for (std::vector<std::string>::iterator cit = collisions.begin(); cit != collisions.end(); ++cit)
{
MWWorld::Ptr ptr = getPtrViaHandle(*cit);
if (MWWorld::Class::get(ptr).isActor())
{
// figure out which side of the door the object we collided with is
Ogre::Vector3 relativePos = it->first.getRefData().getBaseNode()->
convertWorldToLocalPosition(ptr.getRefData().getBaseNode()->_getDerivedPosition());
if(relativePos.y >= 0)
targetRot = std::min(std::max(0.f, oldRot + diff*0.1f), 90.f);
else
targetRot = std::min(std::max(0.f, oldRot - diff*0.1f), 90.f);
localRotateObject(it->first, 0, 0, targetRot);
break;
}
}
if ((targetRot == 90.f && it->second) || targetRot == 0.f)
mDoorStates.erase(it++);
else
++it;
}
}
}
bool World::toggleCollisionMode()
{
return mPhysics->toggleCollisionMode();;
@ -1480,4 +1523,20 @@ namespace MWWorld
{
mRendering->frameStarted(dt);
}
void World::activateDoor(const MWWorld::Ptr& door)
{
if (mDoorStates.find(door) != mDoorStates.end())
{
// if currently opening, then close, if closing, then open
mDoorStates[door] = !mDoorStates[door];
}
else
{
if (door.getRefData().getLocalRotation().rot[2] == 0)
mDoorStates[door] = 1; // open
else
mDoorStates[door] = 0; // close
}
}
}

View file

@ -85,6 +85,9 @@ namespace MWWorld
float mFaced2Distance;
int mNumFacing;
std::map<MWWorld::Ptr, int> mDoorStates;
///< only holds doors that are currently moving. 0 means closing, 1 opening
unsigned long lastTick;
Ogre::Timer mTimer;
@ -269,6 +272,9 @@ namespace MWWorld
virtual void doPhysics(const PtrMovementList &actors, float duration);
///< Run physics simulation and modify \a world accordingly.
virtual void processDoors(float duration);
///< Run physics simulation and modify \a world accordingly.
virtual bool toggleCollisionMode();
///< Toggle collision mode for player. If disabled player object should ignore
/// collisions and gravity.
@ -368,6 +374,9 @@ namespace MWWorld
virtual void setupPlayer(bool newGame);
virtual void renderPlayer();
virtual void activateDoor(const MWWorld::Ptr& door);
///< activate (open or close) an non-teleport door
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering);
virtual int canRest();

View file

@ -509,6 +509,43 @@ namespace Physic
}
}
class ContactTestResultCallback : public btCollisionWorld::ContactResultCallback
{
public:
std::vector<std::string> mResult;
// added in bullet 2.81
// this is just a quick hack, as there does not seem to be a BULLET_VERSION macro?
#if defined(BT_COLLISION_OBJECT_WRAPPER_H)
virtual btScalar addSingleResult(btManifoldPoint& cp,
const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,
const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1)
{
const RigidBody* body = dynamic_cast<const RigidBody*>(colObj0Wrap->m_collisionObject);
if (body)
mResult.push_back(body->mName);
return 0.f;
}
#else
virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObject* col0, int partId0, int index0,
const btCollisionObject* col1, int partId1, int index1)
{
const RigidBody* body = dynamic_cast<const RigidBody*>(col0);
if (body)
mResult.push_back(body->mName);
return 0.f;
}
#endif
};
std::vector<std::string> PhysicEngine::getCollisions(const std::string& name)
{
RigidBody* body = getRigidBody(name);
ContactTestResultCallback callback;
dynamicsWorld->contactTest(body, callback);
return callback.mResult;
}
void PhysicEngine::stepSimulation(double deltaT)
{
// This seems to be needed for character controller objects

View file

@ -298,6 +298,8 @@ namespace Physic
*/
std::vector< std::pair<float, std::string> > rayTest2(btVector3& from, btVector3& to);
std::vector<std::string> getCollisions(const std::string& name);
//event list of non player object
std::list<PhysicEvent> NPEventList;