Merge branch 'movement' of git://github.com/zinnschlag/openmw.git into collisions

actorid
gugus 14 years ago
commit 1dc452ec91

@ -145,6 +145,7 @@ set(GAMEWORLD_HEADER
mwworld/containerutil.hpp
mwworld/player.hpp
mwworld/doingphysics.hpp
mwworld/cellfunctors.hpp
)
source_group(apps\\openmw\\mwworld FILES ${GAMEWORLD} ${GAMEWORLD_HEADER})
@ -206,6 +207,7 @@ set(GAMEMECHANICS_HEADER
mwmechanics/stat.hpp
mwmechanics/creaturestats.hpp
mwmechanics/magiceffects.hpp
mwmechanics/movement.hpp
)
source_group(apps\\openmw\\mwmechanics FILES ${GAMEMECHANICS} ${GAMEMECHANICS_HEADER})

@ -6,6 +6,8 @@
#include <iostream>
#include <utility>
#include <OgreVector3.h>
#include "components/esm/records.hpp"
#include <components/esm_store/cell_store.hpp>
#include <components/misc/fileops.hpp>
@ -158,7 +160,8 @@ bool OMW::Engine::frameStarted(const Ogre::FrameEvent& evt)
mEnvironment.mWorld->markCellAsUnchanged();
// update actors
mEnvironment.mMechanicsManager->update();
std::vector<std::pair<std::string, Ogre::Vector3> > movement;
mEnvironment.mMechanicsManager->update (movement);
if (focusFrameCounter++ == focusUpdateFrame)
{
@ -179,6 +182,8 @@ bool OMW::Engine::frameStarted(const Ogre::FrameEvent& evt)
focusFrameCounter = 0;
}
mEnvironment.mWorld->doPhysics (movement, mEnvironment.mFrameDuration);
}
catch (const std::exception& e)
{
@ -388,7 +393,7 @@ void OMW::Engine::go()
else
{
pos.pos[0] = pos.pos[1] = 0;
mEnvironment.mWorld->changeCell (mCellName, pos);
mEnvironment.mWorld->changeToInteriorCell (mCellName, pos);
}
// Sets up the input system

@ -23,6 +23,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -26,6 +26,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -26,6 +26,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -26,6 +26,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -26,6 +26,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -23,6 +23,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -35,6 +35,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertActorPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -30,6 +30,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -26,6 +26,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -31,6 +31,7 @@ namespace MWClass
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
// Extract the color and convert to floating point
const int color = ref->base->data.color;

@ -26,6 +26,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -26,6 +26,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -256,8 +256,9 @@ namespace MWClass
cellRender.insertMesh (headModel, Ogre::Vector3( 0, 0, 5), axis, Ogre::Radian(0), npcName + "head", neckandup, neckNumbers);
neckandup[neckNumbers++] = npcName + "head";
cellRender.insertMesh (hairModel, Ogre::Vector3( 0, -1, 0), axis, Ogre::Radian(0), npcName + "hair", neckandup, neckNumbers);
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
cellRender.insertActorPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
void Npc::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
@ -392,7 +393,8 @@ namespace MWClass
{
case Run:
throw std::runtime_error ("run stance not manually setable for NPCs");
stats.mRun = set;
break;
case Sneak:
@ -414,7 +416,10 @@ namespace MWClass
{
case Run:
return ignoreForce ? false : stats.mForceRun;
if (!ignoreForce && stats.mForceRun)
return true;
return stats.mRun;
case Sneak:
@ -436,6 +441,35 @@ namespace MWClass
return getStance (ptr, Run) ? 600 : 300; // TODO calculate these values from stats
}
MWMechanics::Movement& Npc::getMovementSettings (const MWWorld::Ptr& ptr) const
{
if (!ptr.getRefData().getMovement().get())
{
boost::shared_ptr<MWMechanics::Movement> movement (
new MWMechanics::Movement);
ptr.getRefData().getMovement() = movement;
}
return *ptr.getRefData().getMovement();
}
Ogre::Vector3 Npc::getMovementVector (const MWWorld::Ptr& ptr) const
{
Ogre::Vector3 vector (0, 0, 0);
if (ptr.getRefData().getMovement().get())
{
vector.x = - ptr.getRefData().getMovement()->mLeftRight * 200;
vector.z = - ptr.getRefData().getMovement()->mForwardBackward * 200;
if (getStance (ptr, Run, false))
vector *= 2;
}
return vector;
}
void Npc::registerSelf()
{
boost::shared_ptr<Class> instance (new Npc);

@ -56,6 +56,13 @@ namespace MWClass
virtual float getSpeed (const MWWorld::Ptr& ptr) const;
///< Return movement speed.
virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const;
///< Return desired movement.
virtual Ogre::Vector3 getMovementVector (const MWWorld::Ptr& ptr) const;
///< Return desired movement vector (determined based on movement settings,
/// stance and stats).
static void registerSelf();
};
}

@ -26,6 +26,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -26,6 +26,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -26,6 +26,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -21,6 +21,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -26,6 +26,7 @@ namespace MWClass
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}
}

@ -41,27 +41,25 @@ namespace MWInput
A_MoveLeft, // Move player left / right
A_MoveRight,
A_MoveUp, // Move up / down
A_MoveDown,
A_MoveForward, // Forward / Backward
A_MoveBackward,
A_Activate,
A_Use, //Use weapon, spell, etc.
A_Use, //Use weapon, spell, etc.
A_Jump,
A_AutoMove, //Toggle Auto-move forward
A_Rest, //Rest
A_Journal, //Journal
A_Weapon, //Draw/Sheath weapon
A_Spell, //Ready/Unready Casting
A_AlwaysRun, //Toggle Always Run
A_AutoMove, //Toggle Auto-move forward
A_Rest, //Rest
A_Journal, //Journal
A_Weapon, //Draw/Sheath weapon
A_Spell, //Ready/Unready Casting
A_AlwaysRun, //Toggle Always Run
A_CycleSpellLeft, //cycling through spells
A_CycleSpellRight,
A_CycleWeaponLeft,//Cycling through weapons
A_CycleWeaponRight,
A_ToggleSneak, //Toggles Sneak, add Push-Sneak later
A_ToggleWalk, //Toggle Walking/Running
A_ToggleSneak, //Toggles Sneak, add Push-Sneak later
A_ToggleWalk, //Toggle Walking/Running
A_QuickSave,
A_QuickLoad,
@ -143,24 +141,19 @@ namespace MWInput
void toggleAutoMove()
{
if (player.getAutoMove() == false)
{
player.setAutoMove(true);
} else {
player.setAutoMove(false);
}
player.setAutoMove (!player.getAutoMove());
}
void toggleWalking()
{
player.setisWalking(true);
player.toggleRunning();
}
// Exit program now button (which is disabled in GUI mode)
void exitNow()
{
if(!windows.isGuiMode())
exit.exitNow();
if(!windows.isGuiMode())
exit.exitNow();
}
public:
@ -262,73 +255,54 @@ namespace MWInput
poller.bind(A_MoveRight, KC_D);
poller.bind(A_MoveForward, KC_W);
poller.bind(A_MoveBackward, KC_S);
// Use shift and ctrl for up and down
poller.bind(A_MoveUp, KC_LSHIFT);
poller.bind(A_MoveDown, KC_LCONTROL);
}
//NOTE: Used to check for movement keys
bool frameStarted(const Ogre::FrameEvent &evt)
{
// Tell OIS to handle all input events
input.capture();
// Update windows/gui as a result of input events
// For instance this could mean opening a new window/dialog,
// by doing this after the input events are handled we
// ensure that window/gui changes appear quickly while
// avoiding that window/gui changes does not happen in
// event callbacks (which may crash)
windows.update();
// Disable movement in Gui mode
if(windows.isGuiMode()) return true;
float speed = 300 * evt.timeSinceLastFrame; //placeholder player speed?
//float TESTwalkSpeed = 100 * evt.timeSinceLastFrame; //How about another?
float moveX = 0, moveY = 0, moveZ = 0;
//execute Automove - condition checked in function
player.executeAutoMove((float)evt.timeSinceLastFrame); //or since last frame?
//Poll and execute movement keys - will disable automove if pressed.
if(poller.isDown(A_MoveLeft))
{
player.setAutoMove(false);
moveX -= speed;
}
if(poller.isDown(A_MoveRight))
{
player.setAutoMove(false);
moveX += speed;
}
if(poller.isDown(A_MoveForward))
{
player.setAutoMove(false);
moveZ -= speed;
}
if(poller.isDown(A_MoveBackward))
{
player.setAutoMove(false);
moveZ += speed;
}
// TODO: These should be enabled for floating modes (like
// swimming and levitation) and disabled for everything else.
if(poller.isDown(A_MoveUp)) moveY += speed;
if(poller.isDown(A_MoveDown)) moveY -= speed;
if(moveX != 0 || moveY != 0 || moveZ != 0)
player.moveRel(moveX, moveY, moveZ);
// Tell OIS to handle all input events
input.capture();
// Update windows/gui as a result of input events
// For instance this could mean opening a new window/dialog,
// by doing this after the input events are handled we
// ensure that window/gui changes appear quickly while
// avoiding that window/gui changes does not happen in
// event callbacks (which may crash)
windows.update();
// Disable movement in Gui mode
if (windows.isGuiMode()) return true;
// Configure player movement according to keyboard input. Actual movement will
// be done in the physics system.
if (poller.isDown(A_MoveLeft))
{
player.setAutoMove (false);
player.setLeftRight (1);
}
else if (poller.isDown(A_MoveRight))
{
player.setAutoMove (false);
player.setLeftRight (-1);
}
else
player.setLeftRight (0);
if (poller.isDown(A_MoveForward))
{
player.setAutoMove (false);
player.setForwardBackward (1);
}
else if (poller.isDown(A_MoveBackward))
{
player.setAutoMove (false);
player.setForwardBackward (-1);
}
else
player.setForwardBackward (0);
return true;
return true;
}
// Switch between gui modes. Besides controlling the Gui windows

@ -234,11 +234,17 @@ namespace MWMechanics
void MechanicsManager::removeActor (const MWWorld::Ptr& ptr)
{
if (ptr==mWatched)
mWatched = MWWorld::Ptr();
mActors.erase (ptr);
}
void MechanicsManager::dropActors (const MWWorld::Ptr::CellStore *cellStore)
{
if (!mWatched.isEmpty() && mWatched.getCell()==cellStore)
mWatched = MWWorld::Ptr();
std::set<MWWorld::Ptr>::iterator iter = mActors.begin();
while (iter!=mActors.end())
@ -255,7 +261,7 @@ namespace MWMechanics
mWatched = ptr;
}
void MechanicsManager::update()
void MechanicsManager::update (std::vector<std::pair<std::string, Ogre::Vector3> >& movement)
{
if (!mWatched.isEmpty())
{
@ -350,6 +356,15 @@ namespace MWMechanics
mEnvironment.mWindowManager->configureSkills (majorSkills, minorSkills);
}
for (std::set<MWWorld::Ptr>::iterator iter (mActors.begin()); iter!=mActors.end();
++iter)
{
Ogre::Vector3 vector = MWWorld::Class::get (*iter).getMovementVector (*iter);
if (vector!=Ogre::Vector3::ZERO)
movement.push_back (std::make_pair (iter->getRefData().getHandle(), vector));
}
}
void MechanicsManager::setPlayerName (const std::string& name)

@ -2,12 +2,19 @@
#define GAME_MWMECHANICS_MECHANICSMANAGER_H
#include <set>
#include <vector>
#include <string>
#include "../mwworld/ptr.hpp"
#include "creaturestats.hpp"
#include "npcstats.hpp"
namespace Ogre
{
class Vector3;
}
namespace MWWorld
{
class Environment;
@ -53,8 +60,8 @@ namespace MWMechanics
///< On each update look for changes in a previously registered actor and update the
/// GUI accordingly.
void update();
///< Update actor stats
void update (std::vector<std::pair<std::string, Ogre::Vector3> >& movement);
///< Update actor stats and store desired velocity vectors in \a movement
void setPlayerName (const std::string& name);
///< Set player name.

@ -0,0 +1,16 @@
#ifndef GAME_MWMECHANICS_MOVEMENT_H
#define GAME_MWMECHANICS_MOVEMENT_H
namespace MWMechanics
{
/// Desired movement for an actor
struct Movement
{
signed char mLeftRight; // 1: wants to move left, -1: wants to move right
signed char mForwardBackward; // 1:wants to move forward, -1: wants to move backward
Movement() : mLeftRight (0), mForwardBackward (0) {}
};
}
#endif

@ -21,10 +21,12 @@ namespace MWMechanics
bool mForceRun;
bool mForceSneak;
bool mRun;
bool mSneak;
bool mCombat;
NpcStats() : mForceRun (false), mForceSneak (false), mSneak (false), mCombat (false) {}
NpcStats() : mForceRun (false), mForceSneak (false), mRun (false), mSneak (false),
mCombat (false) {}
};
}

@ -45,6 +45,9 @@ namespace MWRender
virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements) = 0;
virtual void insertObjectPhysics() = 0;
virtual void insertActorPhysics() = 0;
/// insert a light related to the most recent insertBegin call.
virtual void insertLight(float r, float g, float b, float radius) = 0;

@ -58,6 +58,8 @@ void ExteriorCellRender::insertBegin (ESM::CellRef &ref)
// Rotates first around z, then y, then x
mInsert->setOrientation(xr*yr*zr);
mInsertMesh.clear();
}
@ -81,18 +83,18 @@ void ExteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec,
if(sceneParent[i] != "" && parent->getChild(sceneParent[i]))
parent = dynamic_cast<Ogre::SceneNode*> (parent->getChild(sceneParent[i]));
}
mNpcPart = parent->createChildSceneNode(sceneNodeName);
NIFLoader::load(mesh);
MovableObject *ent = mScene.getMgr()->createEntity(mesh);
mNpcPart->translate(vec);
mNpcPart->rotate(axis, angle);
// mNpcPart->translate(vec);
//mNpcPart->rotate(axis, angle);
mNpcPart->attachObject(ent);
//mNpcPart->
}
*/
void ExteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements)
@ -108,7 +110,7 @@ void ExteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec,
if(sceneParent[i] != "" && parent->getChild(sceneParent[i]))
parent = dynamic_cast<Ogre::SceneNode*> (parent->getChild(sceneParent[i]));
}
mNpcPart = parent->createChildSceneNode(sceneNodeName);
MeshPtr good2 = NIFLoader::load(mesh);
@ -120,7 +122,7 @@ void ExteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec,
mNpcPart->rotate(axis, angle);
}
else{
mNpcPart->rotate(axis, angle);
mNpcPart->translate(vec);
}
@ -202,6 +204,22 @@ void ExteriorCellRender::insertMesh(const std::string &mesh)
NIFLoader::load(mesh);
MovableObject *ent = mScene.getMgr()->createEntity(mesh);
mInsert->attachObject(ent);
if (mInsertMesh.empty())
mInsertMesh = mesh;
}
void ExteriorCellRender::insertObjectPhysics()
{
if (!mInsertMesh.empty())
mScene.addObject (mInsert->getName(), mInsertMesh, mInsert->getOrientation(),
mInsert->getScale().x, mInsert->getPosition());
}
void ExteriorCellRender::insertActorPhysics()
{
if (!mInsertMesh.empty())
mScene.addActor (mInsert->getName(), mInsertMesh, mInsert->getPosition());
}
// insert a light related to the most recent insertBegin call.

@ -54,6 +54,7 @@ namespace MWRender
Ogre::SceneNode *mBase;
Ogre::SceneNode *mInsert;
std::string mInsertMesh;
Ogre::SceneNode *mNpcPart;
// 0 normal, 1 more bright, 2 max
@ -67,11 +68,15 @@ namespace MWRender
/// insert a mesh related to the most recent insertBegin call.
virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements);
virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst);
virtual void insertMesh(const std::string &mesh);
virtual void rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements);
virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements);
virtual void insertObjectPhysics();
virtual void insertActorPhysics();
/// insert a light related to the most recent insertBegin call.
virtual void insertLight(float r, float g, float b, float radius);
@ -85,7 +90,7 @@ namespace MWRender
void configureFog();
void setAmbientMode();
public:

@ -60,6 +60,8 @@ void InteriorCellRender::insertBegin (ESM::CellRef &ref)
// Rotates first around z, then y, then x
insert->setOrientation(xr*yr*zr);
mInsertMesh.clear();
}
// insert a mesh related to the most recent insertBegin call.
@ -100,7 +102,7 @@ void InteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec,
if(sceneParent[i] != "" && parent->getChild(sceneParent[i]))
parent = dynamic_cast<Ogre::SceneNode*> (parent->getChild(sceneParent[i]));
}
npcPart = parent->createChildSceneNode(sceneNodeName);
//npcPart->showBoundingBox(true);
@ -108,7 +110,7 @@ void InteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec,
MovableObject *ent = scene.getMgr()->createEntity(mesh);
//ent->extr
// MovableObject *ent2 = scene.getMgr()->createEntity(bounds
// );
//ent->
@ -119,7 +121,7 @@ void InteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec,
npcPart->rotate(axis, angle);
}
else{
npcPart->rotate(axis, angle);
npcPart->translate(vec);
}
@ -185,6 +187,22 @@ void InteriorCellRender::insertMesh(const std::string &mesh)
NIFLoader::load(mesh);
MovableObject *ent = scene.getMgr()->createEntity(mesh);
insert->attachObject(ent);
if (mInsertMesh.empty())
mInsertMesh = mesh;
}
void InteriorCellRender::insertObjectPhysics()
{
if (!mInsertMesh.empty())
scene.addObject (insert->getName(), mInsertMesh, insert->getOrientation(),
insert->getScale().x, insert->getPosition());
}
void InteriorCellRender::insertActorPhysics()
{
if (!mInsertMesh.empty())
scene.addActor (insert->getName(), mInsertMesh, insert->getPosition());
}
// insert a light related to the most recent insertBegin call.

@ -54,6 +54,7 @@ namespace MWRender
Ogre::SceneNode *base;
Ogre::SceneNode *insert;
std::string mInsertMesh;
Ogre::SceneNode *npcPart;
// 0 normal, 1 more bright, 2 max
@ -69,6 +70,11 @@ namespace MWRender
virtual void insertMesh(const std::string &mesh);
virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements);
virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst);
virtual void insertObjectPhysics();
virtual void insertActorPhysics();
/// insert a light related to the most recent insertBegin call.
virtual void insertLight(float r, float g, float b, float radius);

@ -42,7 +42,10 @@ MWScene::MWScene(OEngine::Render::OgreRenderer &_rend)
//used to obtain ingame information of ogre objects (which are faced or selected)
mRaySceneQuery = rend.getScene()->createRayQuery(Ray());
mPlayer = new MWRender::Player (getCamera());
Ogre::SceneNode *playerNode = mwRoot->createChildSceneNode();
playerNode->attachObject (getCamera());
mPlayer = new MWRender::Player (getCamera(), playerNode->getName());
}
MWScene::~MWScene()
@ -99,16 +102,24 @@ std::pair<std::string, float> MWScene::getFacedHandle (MWWorld::World& world)
return std::pair<std::string, float>(handle, distance);
}
void MWScene::doPhysics (float duration, MWWorld::World& world)
void MWScene::doPhysics (float duration, MWWorld::World& world,
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors)
{
// stop changes to world from being reported back to the physics system
MWWorld::DoingPhysics scopeGuard;
}
// move object directly for now -> TODO replace with physics
for (std::vector<std::pair<std::string, Ogre::Vector3> >::const_iterator iter (actors.begin());
iter!=actors.end(); ++iter)
{
MWWorld::Ptr ptr = world.getPtrViaHandle (iter->first);
void MWScene::setMovement (const std::vector<std::string, Ogre::Vector3>& actors)
{
Ogre::SceneNode *sceneNode = rend.getScene()->getSceneNode (iter->first);
Ogre::Vector3 newPos = sceneNode->getPosition() + sceneNode->getOrientation() * iter->second;
world.moveObject (ptr, newPos.x, newPos.y, newPos.z);
}
}
void MWScene::addObject (const std::string& handle, const std::string& mesh,
@ -128,8 +139,9 @@ void MWScene::removeObject (const std::string& handle)
}
void MWScene::moveObject (const std::string& handle, const Ogre::Vector3& position)
void MWScene::moveObject (const std::string& handle, const Ogre::Vector3& position, bool updatePhysics)
{
rend.getScene()->getSceneNode (handle)->setPosition (position);
}

@ -5,6 +5,7 @@
#include <openengine/ogre/renderer.hpp>
#include <vector>
#include <string>
namespace Ogre
{
@ -60,11 +61,8 @@ namespace MWRender
std::pair<std::string, float> getFacedHandle (MWWorld::World& world);
/// Run physics simulation and modify \a world accordingly.
void doPhysics (float duration, MWWorld::World& world);
/// Inform phyiscs system about desired velocity vectors for actors
/// (in Morrowind coordinates).
void setMovement (const std::vector<std::string, Ogre::Vector3>& actors);
void doPhysics (float duration, MWWorld::World& world,
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors);
/// Add object to physics system.
void addObject (const std::string& handle, const std::string& mesh,
@ -78,7 +76,7 @@ namespace MWRender
void removeObject (const std::string& handle);
/// Move object.
void moveObject (const std::string& handle, const Ogre::Vector3& position);
void moveObject (const std::string& handle, const Ogre::Vector3& position, bool updatePhysics);
/// Change object's orientation.
void rotateObject (const std::string& handle, const Ogre::Quaternion& rotation);

@ -3,6 +3,7 @@
namespace MWRender
{
Player::Player (Ogre::Camera *camera) : mCamera (camera)
Player::Player (Ogre::Camera *camera, const std::string& handle)
: mCamera (camera), mHandle (handle)
{}
}

@ -1,6 +1,8 @@
#ifndef GAME_MWRENDER_PLAYER_H
#define GAME_MWRENDER_PLAYER_H
#include <iostream>
namespace Ogre
{
class Camera;
@ -12,12 +14,15 @@ namespace MWRender
class Player
{
Ogre::Camera *mCamera;
std::string mHandle;
public:
Player (Ogre::Camera *camera);
Player (Ogre::Camera *camera, const std::string& handle);
Ogre::Camera *getCamera() { return mCamera; }
std::string getHandle() const { return mHandle; }
};
}

@ -53,7 +53,7 @@ namespace MWScript
else
{
pos.pos[0] = pos.pos[1] = 0;
context.getWorld().changeCell (cell, pos);
context.getWorld().changeToInteriorCell (cell, pos);
}
}
};

@ -16,6 +16,6 @@ namespace MWWorld
if (mCellName.empty())
environment.mWorld->changeToExteriorCell (mPosition);
else
environment.mWorld->changeCell (mCellName, mPosition);
environment.mWorld->changeToInteriorCell (mCellName, mPosition);
}
}

@ -0,0 +1,31 @@
#ifndef GAME_MWWORLD_CELLFUNCTORS_H
#define GAME_MWWORLD_CELLFUNCTORS_H
#include <vector>
#include <string>
#include "refdata.hpp"
namespace ESM
{
class CellRef;
}
namespace MWWorld
{
/// List all (Ogre-)handles.
struct ListHandles
{
std::vector<std::string> mHandles;
bool operator() (ESM::CellRef& ref, RefData& data)
{
std::string handle = data.getHandle();
if (!handle.empty())
mHandles.push_back (handle);
return true;
}
};
}
#endif

@ -3,6 +3,8 @@
#include <stdexcept>
#include <OgreVector3.h>
#include "ptr.hpp"
#include "nullaction.hpp"
@ -112,6 +114,16 @@ namespace MWWorld
return 0;
}
MWMechanics::Movement& Class::getMovementSettings (const Ptr& ptr) const
{
throw std::runtime_error ("movement settings not supported by class");
}
Ogre::Vector3 Class::getMovementVector (const Ptr& ptr) const
{
return Ogre::Vector3 (0, 0, 0);
}
const Class& Class::get (const std::string& key)
{
std::map<std::string, boost::shared_ptr<Class> >::const_iterator iter = sClasses.find (key);

@ -10,6 +10,11 @@
#include "containerstore.hpp"
#include "refdata.hpp"
namespace Ogre
{
class Vector3;
}
namespace MWRender
{
class CellRenderImp;
@ -19,6 +24,7 @@ namespace MWMechanics
{
struct CreatureStats;
struct NpcStats;
struct Movement;
}
namespace MWWorld
@ -126,6 +132,13 @@ namespace MWWorld
virtual float getSpeed (const Ptr& ptr) const;
///< Return movement speed.
virtual MWMechanics::Movement& getMovementSettings (const Ptr& ptr) const;
///< Return desired movement.
virtual Ogre::Vector3 getMovementVector (const Ptr& ptr) const;
///< Return desired movement vector (determined based on movement settings,
/// stance and stats).
static const Class& get (const std::string& key);
///< If there is no class for this \a key, an exception is thrown.

@ -4,6 +4,7 @@
namespace MWWorld
{
int DoingPhysics::sCounter = 0;
int DoingPhysics::sSuppress = 0;
DoingPhysics::DoingPhysics()
{
@ -17,6 +18,16 @@ namespace MWWorld
bool DoingPhysics::isDoingPhysics()
{
return sCounter>0;
return sCounter>0 || sSuppress>0;
}
SuppressDoingPhysics::SuppressDoingPhysics()
{
++DoingPhysics::sSuppress;
}
SuppressDoingPhysics::~SuppressDoingPhysics()
{
--DoingPhysics::sSuppress;
}
}

@ -3,10 +3,13 @@
namespace MWWorld
{
///< Scope guard for blocking physics updates during physics simulation.
class SuppressDoingPhysics;
/// Scope guard for blocking physics updates during physics simulation.
class DoingPhysics
{
static int sCounter;
static int sSuppress;
private:
@ -20,6 +23,23 @@ namespace MWWorld
~DoingPhysics();
static bool isDoingPhysics();
friend class SuppressDoingPhysics;
};
/// Scope guard for temporarily lifting the block issues by DoingPhysics
class SuppressDoingPhysics
{
private:
SuppressDoingPhysics (const SuppressDoingPhysics&);
SuppressDoingPhysics& operator= (const SuppressDoingPhysics&);
public:
SuppressDoingPhysics();
~SuppressDoingPhysics();
};
}

@ -4,20 +4,21 @@
#include "../mwrender/player.hpp"
#include "world.hpp"
#include "class.hpp"
namespace MWWorld
{
Player::Player (MWRender::Player *renderer, const ESM::NPC *player, MWWorld::World& world) :
mCellStore (0), mRenderer (renderer), mWorld (world), mClass (0), mCollisionMode (true)
mCellStore (0), mRenderer (renderer), mWorld (world), mClass (0), mCollisionMode (true),
mAutoMove (false), mForwardBackward (0)
{
mPlayer.base = player;
mName = player->name;
mMale = !(player->flags & ESM::NPC::Female);
mRace = player->race;
mPlayer.ref.pos.pos[0] = mPlayer.ref.pos.pos[1] = mPlayer.ref.pos.pos[2] = 0;
mPlayer.mData.setHandle (renderer->getHandle());
mClass = new ESM::Class (*world.getStore().classes.find (player->cls));
mAutoMove = false;
misWalking = false;
}
Player::~Player()
@ -64,4 +65,45 @@ namespace MWWorld
mClass = new_class;
}
void Player::setAutoMove (bool enable)
{
MWWorld::Ptr ptr = getPlayer();
mAutoMove = enable;
int value = mForwardBackward;
if (mAutoMove)
value = 1;
MWWorld::Class::get (ptr).getMovementSettings (ptr).mForwardBackward = value;
}
void Player::setLeftRight (int value)
{
MWWorld::Ptr ptr = getPlayer();
MWWorld::Class::get (ptr).getMovementSettings (ptr).mLeftRight = value;
}
void Player::setForwardBackward (int value)
{
MWWorld::Ptr ptr = getPlayer();
mForwardBackward = value;
if (mAutoMove)
value = 1;
MWWorld::Class::get (ptr).getMovementSettings (ptr).mForwardBackward = value;
}
void Player::toggleRunning()
{
MWWorld::Ptr ptr = getPlayer();
bool running = MWWorld::Class::get (ptr).getStance (ptr, MWWorld::Class::Run, true);
MWWorld::Class::get (ptr).setStance (ptr, MWWorld::Class::Run, !running);
}
}

@ -30,9 +30,8 @@ namespace MWWorld
std::string mBirthsign;
ESM::Class *mClass;
bool mCollisionMode;
bool mAutoMove;
bool misWalking;//Testing...
int mForwardBackward;
public:
@ -117,33 +116,13 @@ namespace MWWorld
return mAutoMove;
}
void setAutoMove(bool setMe)
{
mAutoMove = setMe;
}
void setAutoMove (bool enable);
//NOTE: we don't have speed being calculated yet, so for now this function only requires a frame duration.
/// <param name="duration">float value representing time since last call</param>
void executeAutoMove(float duration)
{
float X_Val = 0.0f;
float Y_Val = 0.0f;
float Z_Val = 300.0f * duration * -1.0f;
if (mAutoMove == true)
{
moveRel(X_Val, Y_Val, Z_Val);
}
}
void setLeftRight (int value);
bool getisWalking()
{
return misWalking;
}
void setForwardBackward (int value);
void setisWalking(bool setMe)
{
misWalking = setMe;
}
void toggleRunning();
};
}
#endif

@ -9,6 +9,7 @@
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwmechanics/movement.hpp"
#include "containerstore.hpp"
@ -36,6 +37,7 @@ namespace MWWorld
// are never copied outside of container operations.
boost::shared_ptr<MWMechanics::CreatureStats> mCreatureStats;
boost::shared_ptr<MWMechanics::NpcStats> mNpcStats;
boost::shared_ptr<MWMechanics::Movement> mMovement;
boost::shared_ptr<ContainerStore<RefData> > mContainerStore;
@ -102,6 +104,11 @@ namespace MWWorld
return mNpcStats;
}
boost::shared_ptr<MWMechanics::Movement>& getMovement()
{
return mMovement;
}
boost::shared_ptr<ContainerStore<RefData> >& getContainerStore()
{
return mContainerStore;

@ -22,6 +22,7 @@
#include "refdata.hpp"
#include "globals.hpp"
#include "doingphysics.hpp"
#include "cellfunctors.hpp"
namespace
{
@ -271,6 +272,15 @@ namespace MWWorld
void World::unloadCell (CellRenderCollection::iterator iter)
{
ListHandles functor;
iter->first->forEach (functor);
{ // silence annoying g++ warning
for (std::vector<std::string>::const_iterator iter (functor.mHandles.begin());
iter!=functor.mHandles.end(); ++iter)
mScene.removeObject (*iter);
}
removeScripts (iter->first);
mEnvironment.mMechanicsManager->dropActors (iter->first);
iter->second->destroy();
@ -295,9 +305,12 @@ namespace MWWorld
}
}
void World::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position)
void World::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position,
bool adjustPlayerPos)
{
mPlayer->setPos (position.pos[0], position.pos[1], position.pos[2], true);
if (adjustPlayerPos)
mPlayer->setPos (position.pos[0], position.pos[1], position.pos[2], true);
mPlayer->setCell (cell);
// TODO orientation
@ -316,8 +329,87 @@ namespace MWWorld
}
}
void World::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos)
{
SuppressDoingPhysics scopeGuard;
// remove active
mEnvironment.mMechanicsManager->removeActor (mPlayer->getPlayer());
CellRenderCollection::iterator active = mActiveCells.begin();
while (active!=mActiveCells.end())
{
if (!(active->first->cell->data.flags & ESM::Cell::Interior))
{
if (std::abs (X-active->first->cell->data.gridX)<=1 &&
std::abs (Y-active->first->cell->data.gridY)<=1)
{
// keep cells within the new 3x3 grid
++active;
continue;
}
}
unloadCell (active++);
}
// Load cells
for (int x=X-1; x<=X+1; ++x)
for (int y=Y-1; y<=Y+1; ++y)
{
CellRenderCollection::iterator iter = mActiveCells.begin();
while (iter!=mActiveCells.end())
{
assert (!(iter->first->cell->data.flags & ESM::Cell::Interior));
if (x==iter->first->cell->data.gridX &&
y==iter->first->cell->data.gridY)
break;
++iter;
}
if (iter==mActiveCells.end())
{
mExteriors[std::make_pair (x, y)].loadExt (x, y, mStore, mEsm);
Ptr::CellStore *cell = &mExteriors[std::make_pair (x, y)];
loadCell (cell, new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene));
}
}
// find current cell
CellRenderCollection::iterator iter = mActiveCells.begin();
while (iter!=mActiveCells.end())
{
assert (!(iter->first->cell->data.flags & ESM::Cell::Interior));
if (X==iter->first->cell->data.gridX &&
Y==iter->first->cell->data.gridY)
break;
++iter;
}
assert (iter!=mActiveCells.end());
mCurrentCell = iter->first;
// adjust player
playerCellChange (&mExteriors[std::make_pair (X, Y)], position, adjustPlayerPos);
// Sky system
adjustSky();
mCellChanged = true;
}
World::World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir,
const std::string& master, const boost::filesystem::path& resDir, bool newGame, Environment& environment)
const std::string& master, const boost::filesystem::path& resDir,
bool newGame, Environment& environment)
: mSkyManager (0), mScene (renderer), mPlayer (0), mCurrentCell (0), mGlobalVariables (0),
mSky (false), mCellChanged (false), mEnvironment (environment)
{
@ -331,6 +423,7 @@ namespace MWWorld
mStore.load (mEsm);
mPlayer = new MWWorld::Player (mScene.getPlayer(), mStore.npcs.find ("player"), *this);
mScene.addActor (mPlayer->getPlayer().getRefData().getHandle(), "", Ogre::Vector3 (0, 0, 0));
// global variables
mGlobalVariables = new Globals (mStore);
@ -418,7 +511,8 @@ namespace MWWorld
Ptr World::getPtrViaHandle (const std::string& handle)
{
// TODO player
if (mPlayer->getPlayer().getRefData().getHandle()==handle)
return mPlayer->getPlayer();
for (CellRenderCollection::iterator iter (mActiveCells.begin());
iter!=mActiveCells.end(); ++iter)
@ -587,8 +681,10 @@ namespace MWWorld
return mGlobalVariables->getInt ("timescale");
}
void World::changeCell (const std::string& cellName, const ESM::Position& position)
void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)
{
SuppressDoingPhysics scopeGuard;
// remove active
CellRenderCollection::iterator active = mActiveCells.begin();
@ -614,89 +710,14 @@ namespace MWWorld
//currentRegion->name = "";
}
void World::changeCell (int X, int Y, const ESM::Position& position)
{
// remove active
CellRenderCollection::iterator active = mActiveCells.begin();
while (active!=mActiveCells.end())
{
if (!(active->first->cell->data.flags & ESM::Cell::Interior))
{
if (std::abs (X-active->first->cell->data.gridX)<=1 &&
std::abs (Y-active->first->cell->data.gridY)<=1)
{
// keep cells within the new 3x3 grid
++active;
continue;
}
}
unloadCell (active++);
}
// Load cells
for (int x=X-1; x<=X+1; ++x)
for (int y=Y-1; y<=Y+1; ++y)
{
CellRenderCollection::iterator iter = mActiveCells.begin();
while (iter!=mActiveCells.end())
{
assert (!(iter->first->cell->data.flags & ESM::Cell::Interior));
if (x==iter->first->cell->data.gridX &&
y==iter->first->cell->data.gridY)
break;
++iter;
}
if (iter==mActiveCells.end())
{
mExteriors[std::make_pair (x, y)].loadExt (x, y, mStore, mEsm);
Ptr::CellStore *cell = &mExteriors[std::make_pair (x, y)];
loadCell (cell, new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene));
}
}
// find current cell
CellRenderCollection::iterator iter = mActiveCells.begin();
while (iter!=mActiveCells.end())
{
assert (!(iter->first->cell->data.flags & ESM::Cell::Interior));
if (X==iter->first->cell->data.gridX &&
Y==iter->first->cell->data.gridY)
break;
++iter;
}
assert (iter!=mActiveCells.end());
mCurrentCell = iter->first;
// adjust player
playerCellChange (&mExteriors[std::make_pair (X, Y)], position);
// Sky system
adjustSky();
mCellChanged = true;
}
void World::changeToExteriorCell (const ESM::Position& position)
void World::changeToExteriorCell (const ESM::Position& position)
{
int x = 0;
int y = 0;
positionToIndex (position.pos[0], position.pos[1], x, y);
changeCell (x, y, position);
changeCell (x, y, position, true);
}
const ESM::Cell *World::getExterior (const std::string& cellName) const
@ -722,6 +743,7 @@ namespace MWWorld
return 0;
}
void World::markCellAsUnchanged()
{
mCellChanged = false;
@ -781,15 +803,16 @@ namespace MWWorld
if (mCurrentCell->cell->data.gridX!=cellX || mCurrentCell->cell->data.gridY!=cellY)
{
changeCell (cellX, cellY, mPlayer->getPlayer().getCellRef().pos);
if (!DoingPhysics::isDoingPhysics())
mScene.moveObject (ptr.getRefData().getHandle(), Ogre::Vector3 (x, y, z));
changeCell (cellX, cellY, mPlayer->getPlayer().getCellRef().pos, false);
}
}
}
}
mScene.moveObject (ptr.getRefData().getHandle(), Ogre::Vector3 (x, y, z),
!DoingPhysics::isDoingPhysics());
// TODO cell change for non-player ref
}
@ -821,4 +844,10 @@ namespace MWWorld
if (y<0)
--cellY;
}
void World::doPhysics (const std::vector<std::pair<std::string, Ogre::Vector3> >& actors,
float duration)
{
mScene.doPhysics (duration, *this, actors);
}
}

@ -14,6 +14,11 @@
#include "ptr.hpp"
#include "globals.hpp"
namespace Ogre
{
class Vector3;
}
namespace ESM
{
struct Position;
@ -83,14 +88,19 @@ namespace MWWorld
void loadCell (Ptr::CellStore *cell, MWRender::CellRender *render);
void playerCellChange (Ptr::CellStore *cell, const ESM::Position& position);
void playerCellChange (Ptr::CellStore *cell, const ESM::Position& position,
bool adjustPlayerPos = true);
void adjustSky();
void changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos);
///< Move from exterior to interior or from interior cell to a different
/// interior cell.
public:
World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir,
const std::string& master, const boost::filesystem::path& resDir, bool newGame, Environment& environment);
const std::string& master, const boost::filesystem::path& resDir, bool newGame,
Environment& environment);
~World();
@ -138,12 +148,11 @@ namespace MWWorld
float getTimeScaleFactor() const;
void changeCell (const std::string& cellName, const ESM::Position& position);
///< works only for interior cells currently.
void changeCell (int X, int Y, const ESM::Position& position);
void changeToInteriorCell (const std::string& cellName, const ESM::Position& position);
///< Move to interior cell.
void changeToExteriorCell (const ESM::Position& position);
///< Move to exterior cell.
const ESM::Cell *getExterior (const std::string& cellName) const;
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.
@ -162,6 +171,10 @@ namespace MWWorld
void positionToIndex (float x, float y, int &cellX, int &cellY) const;
///< Convert position to cell numbers
void doPhysics (const std::vector<std::pair<std::string, Ogre::Vector3> >& actors,
float duration);
///< Run physics simulation and modify \a world accordingly.
};
}

@ -133,7 +133,48 @@ namespace ESMS
loadRefs(store, esm);
}
/// Call functor (ref) for each reference. functor must return a bool. Returning
/// false will abort the iteration.
/// \return Iteration completed?
template<class Functor>
bool forEach (Functor& functor)
{
return
forEachImp (functor, activators) &&
forEachImp (functor, potions) &&
forEachImp (functor, appas) &&
forEachImp (functor, armors) &&
forEachImp (functor, books) &&
forEachImp (functor, clothes) &&
forEachImp (functor, containers) &&
forEachImp (functor, creatures) &&
forEachImp (functor, doors) &&
forEachImp (functor, ingreds) &&
forEachImp (functor, creatureLists) &&
forEachImp (functor, itemLists) &&
forEachImp (functor, lights) &&
forEachImp (functor, lockpicks) &&
forEachImp (functor, miscItems) &&
forEachImp (functor, npcs) &&
forEachImp (functor, probes) &&
forEachImp (functor, repairs) &&
forEachImp (functor, statics) &&
forEachImp (functor, weapons);
}
private:
template<class Functor, class List>
bool forEachImp (Functor& functor, List& list)
{
for (typename List::List::iterator iter (list.list.begin()); iter!=list.list.end();
++iter)
if (!functor (iter->ref, iter->mData))
return false;
return true;
}
void loadRefs(const ESMStore &store, ESMReader &esm)
{
assert (cell);

Loading…
Cancel
Save