@ -170,10 +170,10 @@ namespace MWWorld
World : : World ( OEngine : : Render : : OgreRenderer & renderer ,
const Files : : Collections & fileCollections ,
const std : : string & master , const boost : : filesystem : : path & resDir , const boost : : filesystem : : path & cacheDir , bool newGame ,
ToUTF8 : : Utf8Encoder * encoder , std : : map < std : : string , std : : string > fallbackMap )
ToUTF8 : : Utf8Encoder * encoder , std : : map < std : : string , std : : string > fallbackMap , int mActivationDistanceOverride )
: mPlayer ( 0 ) , mLocalScripts ( mStore ) , mGlobalVariables ( 0 ) ,
mSky ( true ) , mCells ( mStore , mEsm ) ,
mNumFacing ( 0 )
mNumFacing ( 0 ) , mActivationDistanceOverride ( mActivationDistanceOverride )
{
mPhysics = new PhysicsSystem ( renderer ) ;
mPhysEngine = mPhysics - > getEngine ( ) ;
@ -573,23 +573,55 @@ namespace MWWorld
return mWorldScene - > markCellAsUnchanged ( ) ;
}
std : : string World : : getFacedHandle ( )
float World : : getMaxActivationDistance ( )
{
if ( mActivationDistanceOverride > = 0 )
return mActivationDistanceOverride ;
return ( std : : max ) ( getNpcActivationDistance ( ) , getObjectActivationDistance ( ) ) ;
}
float World : : getNpcActivationDistance ( )
{
if ( mActivationDistanceOverride > = 0 )
return mActivationDistanceOverride ;
return getStore ( ) . get < ESM : : GameSetting > ( ) . find ( " iMaxActivateDist " ) - > getInt ( ) * 5 / 4 ;
}
float World : : getObjectActivationDistance ( )
{
if ( mActivationDistanceOverride > = 0 )
return mActivationDistanceOverride ;
return getStore ( ) . get < ESM : : GameSetting > ( ) . find ( " iMaxActivateDist " ) - > getInt ( ) ;
}
MWWorld : : Ptr World : : getFacedObject ( )
{
std : : pair < float , std : : string > result ;
if ( ! mRendering - > occlusionQuerySupported ( ) )
{
std : : pair < std : : string , float > result = mPhysics - > getFacedHandle ( * this ) ;
result = mPhysics - > getFacedHandle ( * this , getMaxActivationDistance ( ) ) ;
else
result = std : : make_pair ( mFacedDistance , mFacedHandle ) ;
if ( result . first . empty ( ) | |
result . second > getStore ( ) . get < ESM : : GameSetting > ( ) . find ( " iMaxActivateDist " ) - > getInt ( ) )
return " " ;
if ( result . second . empty ( ) )
return MWWorld : : Ptr ( ) ;
return result . first ;
}
MWWorld : : Ptr object = searchPtrViaHandle ( result . second ) ;
float ActivationDistance ;
if ( object . getTypeName ( ) . find ( " NPC " ) ! = std : : string : : npos )
ActivationDistance = getNpcActivationDistance ( ) ;
else
{
// updated every few frames in update()
return mFacedHandle ;
}
ActivationDistance = getObjectActivationDistance ( ) ;
if ( result . first > ActivationDistance )
return MWWorld : : Ptr ( ) ;
return object ;
}
void World : : deleteObject ( const Ptr & ptr )
@ -884,8 +916,6 @@ namespace MWWorld
void World : : update ( float duration , bool paused )
{
/// \todo split this function up into subfunctions
mWorldScene - > update ( duration , paused ) ;
float pitch , yaw ;
@ -895,8 +925,15 @@ namespace MWWorld
mWeatherManager - > update ( duration ) ;
performUpdateSceneQueries ( ) ;
updateWindowManager ( ) ;
}
void World : : updateWindowManager ( )
{
// inform the GUI about focused object
MWWorld : : Ptr object = searchPtrViaHandle ( mFacedHandle ) ;
MWWorld : : Ptr object = getFacedObject ( ) ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > setFocusObject ( object ) ;
@ -918,7 +955,10 @@ namespace MWWorld
screenCoords [ 0 ] , screenCoords [ 1 ] , screenCoords [ 2 ] , screenCoords [ 3 ] ) ;
}
}
}
void World : : performUpdateSceneQueries ( )
{
if ( ! mRendering - > occlusionQuerySupported ( ) )
{
// cast a ray from player to sun to detect if the sun is visible
@ -937,119 +977,152 @@ namespace MWWorld
MWRender : : OcclusionQuery * query = mRendering - > getOcclusionQuery ( ) ;
if ( ! query - > occlusionTestPending ( ) )
{
// get result of last query
if ( mNumFacing = = 0 ) mFacedHandle = " " ;
else if ( mNumFacing = = 1 )
{
bool result = query - > getTestResult ( ) ;
mFacedHandle = result ? mFaced1Name : " " ;
}
else if ( mNumFacing = = 2 )
{
bool result = query - > getTestResult ( ) ;
mFacedHandle = result ? mFaced2Name : mFaced1Name ;
}
processFacedQueryResults ( query ) ;
beginFacedQueryProcess ( query ) ;
}
}
}
// send new query
// figure out which object we want to test against
std : : vector < std : : pair < float , std : : string > > results ;
if ( MWBase : : Environment : : get ( ) . getWindowManager ( ) - > isGuiMode ( ) )
{
float x , y ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getMousePosition ( x , y ) ;
results = mPhysics - > getFacedObjects ( x , y ) ;
}
else
results = mPhysics - > getFacedObjects ( ) ;
void World : : processFacedQueryResults ( MWRender : : OcclusionQuery * query )
{
// get result of last query
if ( mNumFacing = = 0 )
{
mFacedHandle = " " ;
mFacedDistance = FLT_MAX ;
}
else if ( mNumFacing = = 1 )
{
bool result = query - > getTestResult ( ) ;
mFacedHandle = result ? mFaced1Name : " " ;
mFacedDistance = result ? mFaced1Distance : FLT_MAX ;
}
else if ( mNumFacing = = 2 )
{
bool result = query - > getTestResult ( ) ;
mFacedHandle = result ? mFaced2Name : mFaced1Name ;
mFacedDistance = result ? mFaced1Distance : mFaced1Distance ;
}
}
// ignore the player and other things we're not interested in
std : : vector < std : : pair < float , std : : string > > : : iterator it = results . begin ( ) ;
while ( it ! = results . end ( ) )
{
if ( ( * it ) . second . find ( " HeightField " ) ! = std : : string : : npos // not interested in terrain
| | getPtrViaHandle ( ( * it ) . second ) = = mPlayer - > getPlayer ( ) ) // not interested in player (unless you want to talk to yourself)
{
it = results . erase ( it ) ;
}
else
+ + it ;
}
void World : : beginFacedQueryProcess ( MWRender : : OcclusionQuery * query )
{
// send new query
// figure out which object we want to test against
std : : vector < std : : pair < float , std : : string > > results ;
if ( MWBase : : Environment : : get ( ) . getWindowManager ( ) - > isGuiMode ( ) )
{
float x , y ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getMousePosition ( x , y ) ;
results = mPhysics - > getFacedHandles ( x , y , getMaxActivationDistance ( ) ) ;
}
else
{
results = mPhysics - > getFacedHandles ( getMaxActivationDistance ( ) ) ;
}
if ( results . size ( ) = = 0 )
{
mNumFacing = 0 ;
}
else if ( results . size ( ) = = 1 )
{
mFaced1 = getPtrViaHandle ( results . front ( ) . second ) ;
mFaced1Name = results . front ( ) . second ;
mNumFacing = 1 ;
// ignore the player and other things we're not interested in
std : : vector < std : : pair < float , std : : string > > : : iterator it = results . begin ( ) ;
while ( it ! = results . end ( ) )
{
if ( ( * it ) . second . find ( " HeightField " ) ! = std : : string : : npos // not interested in terrain
| | getPtrViaHandle ( ( * it ) . second ) = = mPlayer - > getPlayer ( ) ) // not interested in player (unless you want to talk to yourself)
{
it = results . erase ( it ) ;
}
else
+ + it ;
}
btVector3 p ;
if ( MWBase : : Environment : : get ( ) . getWindowManager ( ) - > isGuiMode ( ) )
{
float x , y ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getMousePosition ( x , y ) ;
p = mPhysics - > getRayPoint ( results . front ( ) . first , x , y ) ;
}
else
p = mPhysics - > getRayPoint ( results . front ( ) . first ) ;
Ogre : : Vector3 pos ( p . x ( ) , p . z ( ) , - p . y ( ) ) ;
Ogre : : SceneNode * node = mFaced1 . getRefData ( ) . getBaseNode ( ) ;
if ( results . size ( ) = = 0 )
{
mNumFacing = 0 ;
}
else if ( results . size ( ) = = 1 )
{
beginSingleFacedQueryProcess ( query , results ) ;
}
else
{
beginDoubleFacedQueryProcess ( query , results ) ;
}
}
//std::cout << "Num facing 1 : " << mFaced1Name << std::endl;
//std::cout << "Type 1 " << mFaced1.getTypeName() << std::endl;
void World : : beginSingleFacedQueryProcess ( MWRender : : OcclusionQuery * query , std : : vector < std : : pair < float , std : : string > > const & results )
{
mFaced1 = getPtrViaHandle ( results . front ( ) . second ) ;
mFaced1Name = results . front ( ) . second ;
mFaced1Distance = results . front ( ) . first ;
mNumFacing = 1 ;
query - > occlusionTest ( pos , node ) ;
}
else
{
mFaced1Name = results . front ( ) . second ;
mFaced2Name = results [ 1 ] . second ;
mFaced1 = getPtrViaHandle ( results . front ( ) . second ) ;
mFaced2 = getPtrViaHandle ( results [ 1 ] . second ) ;
mNumFacing = 2 ;
btVector3 p ;
if ( MWBase : : Environment : : get ( ) . getWindowManager ( ) - > isGuiMode ( ) )
{
float x , y ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getMousePosition ( x , y ) ;
p = mPhysics - > getRayPoint ( results [ 1 ] . first , x , y ) ;
}
else
p = mPhysics - > getRayPoint ( results [ 1 ] . first ) ;
Ogre : : Vector3 pos ( p . x ( ) , p . z ( ) , - p . y ( ) ) ;
Ogre : : SceneNode * node1 = mFaced1 . getRefData ( ) . getBaseNode ( ) ;
Ogre : : SceneNode * node2 = mFaced2 . getRefData ( ) . getBaseNode ( ) ;
btVector3 p ;
if ( MWBase : : Environment : : get ( ) . getWindowManager ( ) - > isGuiMode ( ) )
{
float x , y ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getMousePosition ( x , y ) ;
p = mPhysics - > getRayPoint ( results . front ( ) . first , x , y ) ;
}
else
p = mPhysics - > getRayPoint ( results . front ( ) . first ) ;
Ogre : : Vector3 pos ( p . x ( ) , p . z ( ) , - p . y ( ) ) ;
Ogre : : SceneNode * node = mFaced1 . getRefData ( ) . getBaseNode ( ) ;
// no need to test if the first node is not occluder
if ( ! query - > isPotentialOccluder ( node1 ) & & ( mFaced1 . getTypeName ( ) . find ( " Static " ) = = std : : string : : npos ) )
{
mFacedHandle = mFaced1Name ;
//std::cout << "node1 Not an occluder" << std::endl;
return ;
}
//std::cout << "Num facing 1 : " << mFaced1Name << std::endl;
//std::cout << "Type 1 " << mFaced1.getTypeName() << std::endl;
// no need to test if the second object is static (thus cannot be activated)
if ( mFaced2 . getTypeName ( ) . find ( " Static " ) ! = std : : string : : npos )
{
mFacedHandle = mFaced1Name ;
return ;
}
query - > occlusionTest ( pos , node ) ;
}
// work around door problems
if ( mFaced1 . getTypeName ( ) . find ( " Static " ) ! = std : : string : : npos
& & mFaced2 . getTypeName ( ) . find ( " Door " ) ! = std : : string : : npos )
{
mFacedHandle = mFaced2Name ;
return ;
}
void World : : beginDoubleFacedQueryProcess ( MWRender : : OcclusionQuery * query , std : : vector < std : : pair < float , std : : string > > const & results )
{
mFaced1Name = results . at ( 0 ) . second ;
mFaced2Name = results . at ( 1 ) . second ;
mFaced1Distance = results . at ( 0 ) . first ;
mFaced2Distance = results . at ( 1 ) . first ;
mFaced1 = getPtrViaHandle ( results . at ( 0 ) . second ) ;
mFaced2 = getPtrViaHandle ( results . at ( 1 ) . second ) ;
mNumFacing = 2 ;
query - > occlusionTest ( pos , node2 ) ;
}
}
btVector3 p ;
if ( MWBase : : Environment : : get ( ) . getWindowManager ( ) - > isGuiMode ( ) )
{
float x , y ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getMousePosition ( x , y ) ;
p = mPhysics - > getRayPoint ( results . at ( 1 ) . first , x , y ) ;
}
else
p = mPhysics - > getRayPoint ( results . at ( 1 ) . first ) ;
Ogre : : Vector3 pos ( p . x ( ) , p . z ( ) , - p . y ( ) ) ;
Ogre : : SceneNode * node1 = mFaced1 . getRefData ( ) . getBaseNode ( ) ;
Ogre : : SceneNode * node2 = mFaced2 . getRefData ( ) . getBaseNode ( ) ;
// no need to test if the first node is not occluder
if ( ! query - > isPotentialOccluder ( node1 ) & & ( mFaced1 . getTypeName ( ) . find ( " Static " ) = = std : : string : : npos ) )
{
mFacedHandle = mFaced1Name ;
mFacedDistance = mFaced1Distance ;
//std::cout << "node1 Not an occluder" << std::endl;
return ;
}
// no need to test if the second object is static (thus cannot be activated)
if ( mFaced2 . getTypeName ( ) . find ( " Static " ) ! = std : : string : : npos )
{
mFacedHandle = mFaced1Name ;
mFacedDistance = mFaced1Distance ;
return ;
}
// work around door problems
if ( mFaced1 . getTypeName ( ) . find ( " Static " ) ! = std : : string : : npos
& & mFaced2 . getTypeName ( ) . find ( " Door " ) ! = std : : string : : npos )
{
mFacedHandle = mFaced2Name ;
mFacedDistance = mFaced2Distance ;
return ;
}
query - > occlusionTest ( pos , node2 ) ;
}
bool World : : isCellExterior ( ) const