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

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

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

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

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

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

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

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

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

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

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

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

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

@ -26,6 +26,7 @@ namespace MWClass
{ {
MWRender::Rendering rendering (cellRender, ref->ref); MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model); cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); 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); cellRender.insertMesh (headModel, Ogre::Vector3( 0, 0, 5), axis, Ogre::Radian(0), npcName + "head", neckandup, neckNumbers);
neckandup[neckNumbers++] = npcName + "head"; neckandup[neckNumbers++] = npcName + "head";
cellRender.insertMesh (hairModel, Ogre::Vector3( 0, -1, 0), axis, Ogre::Radian(0), npcName + "hair", neckandup, neckNumbers); 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 void Npc::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
@ -392,7 +393,8 @@ namespace MWClass
{ {
case Run: case Run:
throw std::runtime_error ("run stance not manually setable for NPCs"); stats.mRun = set;
break;
case Sneak: case Sneak:
@ -414,7 +416,10 @@ namespace MWClass
{ {
case Run: case Run:
return ignoreForce ? false : stats.mForceRun; if (!ignoreForce && stats.mForceRun)
return true;
return stats.mRun;
case Sneak: case Sneak:
@ -436,6 +441,35 @@ namespace MWClass
return getStance (ptr, Run) ? 600 : 300; // TODO calculate these values from stats 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() void Npc::registerSelf()
{ {
boost::shared_ptr<Class> instance (new Npc); boost::shared_ptr<Class> instance (new Npc);

@ -56,6 +56,13 @@ namespace MWClass
virtual float getSpeed (const MWWorld::Ptr& ptr) const; virtual float getSpeed (const MWWorld::Ptr& ptr) const;
///< Return movement speed. ///< 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(); static void registerSelf();
}; };
} }

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

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

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

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

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

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

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

@ -2,12 +2,19 @@
#define GAME_MWMECHANICS_MECHANICSMANAGER_H #define GAME_MWMECHANICS_MECHANICSMANAGER_H
#include <set> #include <set>
#include <vector>
#include <string>
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "creaturestats.hpp" #include "creaturestats.hpp"
#include "npcstats.hpp" #include "npcstats.hpp"
namespace Ogre
{
class Vector3;
}
namespace MWWorld namespace MWWorld
{ {
class Environment; class Environment;
@ -53,8 +60,8 @@ namespace MWMechanics
///< On each update look for changes in a previously registered actor and update the ///< On each update look for changes in a previously registered actor and update the
/// GUI accordingly. /// GUI accordingly.
void update(); void update (std::vector<std::pair<std::string, Ogre::Vector3> >& movement);
///< Update actor stats ///< Update actor stats and store desired velocity vectors in \a movement
void setPlayerName (const std::string& name); void setPlayerName (const std::string& name);
///< Set player 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 mForceRun;
bool mForceSneak; bool mForceSneak;
bool mRun;
bool mSneak; bool mSneak;
bool mCombat; 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 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. /// insert a light related to the most recent insertBegin call.
virtual void insertLight(float r, float g, float b, float radius) = 0; 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 // Rotates first around z, then y, then x
mInsert->setOrientation(xr*yr*zr); 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])) if(sceneParent[i] != "" && parent->getChild(sceneParent[i]))
parent = dynamic_cast<Ogre::SceneNode*> (parent->getChild(sceneParent[i])); parent = dynamic_cast<Ogre::SceneNode*> (parent->getChild(sceneParent[i]));
} }
mNpcPart = parent->createChildSceneNode(sceneNodeName); mNpcPart = parent->createChildSceneNode(sceneNodeName);
NIFLoader::load(mesh); NIFLoader::load(mesh);
MovableObject *ent = mScene.getMgr()->createEntity(mesh); MovableObject *ent = mScene.getMgr()->createEntity(mesh);
mNpcPart->translate(vec); mNpcPart->translate(vec);
mNpcPart->rotate(axis, angle); mNpcPart->rotate(axis, angle);
// mNpcPart->translate(vec); // mNpcPart->translate(vec);
//mNpcPart->rotate(axis, angle); //mNpcPart->rotate(axis, angle);
mNpcPart->attachObject(ent); mNpcPart->attachObject(ent);
//mNpcPart-> //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) 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])) if(sceneParent[i] != "" && parent->getChild(sceneParent[i]))
parent = dynamic_cast<Ogre::SceneNode*> (parent->getChild(sceneParent[i])); parent = dynamic_cast<Ogre::SceneNode*> (parent->getChild(sceneParent[i]));
} }
mNpcPart = parent->createChildSceneNode(sceneNodeName); mNpcPart = parent->createChildSceneNode(sceneNodeName);
MeshPtr good2 = NIFLoader::load(mesh); MeshPtr good2 = NIFLoader::load(mesh);
@ -120,7 +122,7 @@ void ExteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec,
mNpcPart->rotate(axis, angle); mNpcPart->rotate(axis, angle);
} }
else{ else{
mNpcPart->rotate(axis, angle); mNpcPart->rotate(axis, angle);
mNpcPart->translate(vec); mNpcPart->translate(vec);
} }
@ -202,6 +204,22 @@ void ExteriorCellRender::insertMesh(const std::string &mesh)
NIFLoader::load(mesh); NIFLoader::load(mesh);
MovableObject *ent = mScene.getMgr()->createEntity(mesh); MovableObject *ent = mScene.getMgr()->createEntity(mesh);
mInsert->attachObject(ent); 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. // insert a light related to the most recent insertBegin call.

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

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

@ -54,6 +54,7 @@ namespace MWRender
Ogre::SceneNode *base; Ogre::SceneNode *base;
Ogre::SceneNode *insert; Ogre::SceneNode *insert;
std::string mInsertMesh;
Ogre::SceneNode *npcPart; Ogre::SceneNode *npcPart;
// 0 normal, 1 more bright, 2 max // 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);
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);
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, 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. /// insert a light related to the most recent insertBegin call.
virtual void insertLight(float r, float g, float b, float radius); 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) //used to obtain ingame information of ogre objects (which are faced or selected)
mRaySceneQuery = rend.getScene()->createRayQuery(Ray()); 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() MWScene::~MWScene()
@ -99,16 +102,24 @@ std::pair<std::string, float> MWScene::getFacedHandle (MWWorld::World& world)
return std::pair<std::string, float>(handle, distance); 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 // stop changes to world from being reported back to the physics system
MWWorld::DoingPhysics scopeGuard; 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, 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 <openengine/ogre/renderer.hpp>
#include <vector> #include <vector>
#include <string>
namespace Ogre namespace Ogre
{ {
@ -60,11 +61,8 @@ namespace MWRender
std::pair<std::string, float> getFacedHandle (MWWorld::World& world); std::pair<std::string, float> getFacedHandle (MWWorld::World& world);
/// Run physics simulation and modify \a world accordingly. /// Run physics simulation and modify \a world accordingly.
void doPhysics (float duration, MWWorld::World& world); void doPhysics (float duration, MWWorld::World& world,
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors);
/// Inform phyiscs system about desired velocity vectors for actors
/// (in Morrowind coordinates).
void setMovement (const std::vector<std::string, Ogre::Vector3>& actors);
/// Add object to physics system. /// Add object to physics system.
void addObject (const std::string& handle, const std::string& mesh, void addObject (const std::string& handle, const std::string& mesh,
@ -78,7 +76,7 @@ namespace MWRender
void removeObject (const std::string& handle); void removeObject (const std::string& handle);
/// Move object. /// 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. /// Change object's orientation.
void rotateObject (const std::string& handle, const Ogre::Quaternion& rotation); void rotateObject (const std::string& handle, const Ogre::Quaternion& rotation);

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

@ -53,7 +53,7 @@ namespace MWScript
else else
{ {
pos.pos[0] = pos.pos[1] = 0; 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()) if (mCellName.empty())
environment.mWorld->changeToExteriorCell (mPosition); environment.mWorld->changeToExteriorCell (mPosition);
else 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 <stdexcept>
#include <OgreVector3.h>
#include "ptr.hpp" #include "ptr.hpp"
#include "nullaction.hpp" #include "nullaction.hpp"
@ -112,6 +114,16 @@ namespace MWWorld
return 0; 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) const Class& Class::get (const std::string& key)
{ {
std::map<std::string, boost::shared_ptr<Class> >::const_iterator iter = sClasses.find (key); std::map<std::string, boost::shared_ptr<Class> >::const_iterator iter = sClasses.find (key);

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

@ -4,6 +4,7 @@
namespace MWWorld namespace MWWorld
{ {
int DoingPhysics::sCounter = 0; int DoingPhysics::sCounter = 0;
int DoingPhysics::sSuppress = 0;
DoingPhysics::DoingPhysics() DoingPhysics::DoingPhysics()
{ {
@ -17,6 +18,16 @@ namespace MWWorld
bool DoingPhysics::isDoingPhysics() 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 namespace MWWorld
{ {
///< Scope guard for blocking physics updates during physics simulation. class SuppressDoingPhysics;
/// Scope guard for blocking physics updates during physics simulation.
class DoingPhysics class DoingPhysics
{ {
static int sCounter; static int sCounter;
static int sSuppress;
private: private:
@ -20,6 +23,23 @@ namespace MWWorld
~DoingPhysics(); ~DoingPhysics();
static bool isDoingPhysics(); 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 "../mwrender/player.hpp"
#include "world.hpp" #include "world.hpp"
#include "class.hpp"
namespace MWWorld namespace MWWorld
{ {
Player::Player (MWRender::Player *renderer, const ESM::NPC *player, MWWorld::World& world) : 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; mPlayer.base = player;
mName = player->name; mName = player->name;
mMale = !(player->flags & ESM::NPC::Female); mMale = !(player->flags & ESM::NPC::Female);
mRace = player->race; mRace = player->race;
mPlayer.ref.pos.pos[0] = mPlayer.ref.pos.pos[1] = mPlayer.ref.pos.pos[2] = 0; 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)); mClass = new ESM::Class (*world.getStore().classes.find (player->cls));
mAutoMove = false;
misWalking = false;
} }
Player::~Player() Player::~Player()
@ -64,4 +65,45 @@ namespace MWWorld
mClass = new_class; 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; std::string mBirthsign;
ESM::Class *mClass; ESM::Class *mClass;
bool mCollisionMode; bool mCollisionMode;
bool mAutoMove; bool mAutoMove;
bool misWalking;//Testing... int mForwardBackward;
public: public:
@ -117,33 +116,13 @@ namespace MWWorld
return mAutoMove; return mAutoMove;
} }
void setAutoMove(bool setMe) void setAutoMove (bool enable);
{
mAutoMove = setMe;
}
//NOTE: we don't have speed being calculated yet, so for now this function only requires a frame duration. void setLeftRight (int value);
/// <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);
}
}
bool getisWalking() void setForwardBackward (int value);
{
return misWalking;
}
void setisWalking(bool setMe) void toggleRunning();
{
misWalking = setMe;
}
}; };
} }
#endif #endif

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

@ -22,6 +22,7 @@
#include "refdata.hpp" #include "refdata.hpp"
#include "globals.hpp" #include "globals.hpp"
#include "doingphysics.hpp" #include "doingphysics.hpp"
#include "cellfunctors.hpp"
namespace namespace
{ {
@ -271,6 +272,15 @@ namespace MWWorld
void World::unloadCell (CellRenderCollection::iterator iter) 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); removeScripts (iter->first);
mEnvironment.mMechanicsManager->dropActors (iter->first); mEnvironment.mMechanicsManager->dropActors (iter->first);
iter->second->destroy(); 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); mPlayer->setCell (cell);
// TODO orientation // 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, 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), : mSkyManager (0), mScene (renderer), mPlayer (0), mCurrentCell (0), mGlobalVariables (0),
mSky (false), mCellChanged (false), mEnvironment (environment) mSky (false), mCellChanged (false), mEnvironment (environment)
{ {
@ -331,6 +423,7 @@ namespace MWWorld
mStore.load (mEsm); mStore.load (mEsm);
mPlayer = new MWWorld::Player (mScene.getPlayer(), mStore.npcs.find ("player"), *this); mPlayer = new MWWorld::Player (mScene.getPlayer(), mStore.npcs.find ("player"), *this);
mScene.addActor (mPlayer->getPlayer().getRefData().getHandle(), "", Ogre::Vector3 (0, 0, 0));
// global variables // global variables
mGlobalVariables = new Globals (mStore); mGlobalVariables = new Globals (mStore);
@ -418,7 +511,8 @@ namespace MWWorld
Ptr World::getPtrViaHandle (const std::string& handle) Ptr World::getPtrViaHandle (const std::string& handle)
{ {
// TODO player if (mPlayer->getPlayer().getRefData().getHandle()==handle)
return mPlayer->getPlayer();
for (CellRenderCollection::iterator iter (mActiveCells.begin()); for (CellRenderCollection::iterator iter (mActiveCells.begin());
iter!=mActiveCells.end(); ++iter) iter!=mActiveCells.end(); ++iter)
@ -587,8 +681,10 @@ namespace MWWorld
return mGlobalVariables->getInt ("timescale"); 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 // remove active
CellRenderCollection::iterator active = mActiveCells.begin(); CellRenderCollection::iterator active = mActiveCells.begin();
@ -614,89 +710,14 @@ namespace MWWorld
//currentRegion->name = ""; //currentRegion->name = "";
} }
void World::changeCell (int X, int Y, const ESM::Position& position) void World::changeToExteriorCell (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)
{ {
int x = 0; int x = 0;
int y = 0; int y = 0;
positionToIndex (position.pos[0], position.pos[1], x, y); 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 const ESM::Cell *World::getExterior (const std::string& cellName) const
@ -722,6 +743,7 @@ namespace MWWorld
return 0; return 0;
} }
void World::markCellAsUnchanged() void World::markCellAsUnchanged()
{ {
mCellChanged = false; mCellChanged = false;
@ -781,15 +803,16 @@ namespace MWWorld
if (mCurrentCell->cell->data.gridX!=cellX || mCurrentCell->cell->data.gridY!=cellY) if (mCurrentCell->cell->data.gridX!=cellX || mCurrentCell->cell->data.gridY!=cellY)
{ {
changeCell (cellX, cellY, mPlayer->getPlayer().getCellRef().pos); changeCell (cellX, cellY, mPlayer->getPlayer().getCellRef().pos, false);
if (!DoingPhysics::isDoingPhysics())
mScene.moveObject (ptr.getRefData().getHandle(), Ogre::Vector3 (x, y, z));
} }
} }
} }
} }
mScene.moveObject (ptr.getRefData().getHandle(), Ogre::Vector3 (x, y, z),
!DoingPhysics::isDoingPhysics());
// TODO cell change for non-player ref // TODO cell change for non-player ref
} }
@ -821,4 +844,10 @@ namespace MWWorld
if (y<0) if (y<0)
--cellY; --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 "ptr.hpp"
#include "globals.hpp" #include "globals.hpp"
namespace Ogre
{
class Vector3;
}
namespace ESM namespace ESM
{ {
struct Position; struct Position;
@ -83,14 +88,19 @@ namespace MWWorld
void loadCell (Ptr::CellStore *cell, MWRender::CellRender *render); 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 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: public:
World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir, 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(); ~World();
@ -138,12 +148,11 @@ namespace MWWorld
float getTimeScaleFactor() const; float getTimeScaleFactor() const;
void changeCell (const std::string& cellName, const ESM::Position& position); void changeToInteriorCell (const std::string& cellName, const ESM::Position& position);
///< works only for interior cells currently. ///< Move to interior cell.
void changeCell (int X, int Y, const ESM::Position& position);
void changeToExteriorCell (const ESM::Position& position); void changeToExteriorCell (const ESM::Position& position);
///< Move to exterior cell.
const ESM::Cell *getExterior (const std::string& cellName) const; 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. ///< 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; void positionToIndex (float x, float y, int &cellX, int &cellY) const;
///< Convert position to cell numbers ///< 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); 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: 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) void loadRefs(const ESMStore &store, ESMReader &esm)
{ {
assert (cell); assert (cell);

Loading…
Cancel
Save