2011-07-31 15:07:11 +00:00
# include "scene.hpp"
2015-06-03 21:04:35 +00:00
# include <limits>
2015-07-24 21:28:36 +00:00
# include <iostream>
2013-08-19 18:30:22 +00:00
2017-04-24 16:46:12 +00:00
/*
Start of tes3mp addition
Include additional headers for multiplayer purposes
*/
2017-01-26 07:02:01 +00:00
# include "../mwmp/Main.hpp"
# include "../mwmp/LocalPlayer.hpp"
2017-04-24 16:46:12 +00:00
/*
End of tes3mp addition
*/
2017-01-26 07:02:01 +00:00
2015-07-09 17:22:04 +00:00
# include <components/loadinglistener/loadinglistener.hpp>
2015-01-12 10:29:56 +00:00
# include <components/misc/resourcehelpers.hpp>
2015-04-01 15:02:15 +00:00
# include <components/settings/settings.hpp>
2015-04-22 17:08:56 +00:00
# include <components/resource/resourcesystem.hpp>
2017-02-14 23:55:35 +00:00
# include <components/resource/scenemanager.hpp>
2015-04-12 13:34:50 +00:00
2012-04-23 13:27:03 +00:00
# include "../mwbase/environment.hpp"
2014-10-02 14:30:23 +00:00
# include "../mwbase/world.hpp"
2012-08-09 12:33:21 +00:00
# include "../mwbase/soundmanager.hpp"
2012-08-11 15:30:55 +00:00
# include "../mwbase/mechanicsmanager.hpp"
2012-08-12 16:11:09 +00:00
# include "../mwbase/windowmanager.hpp"
2012-03-10 15:05:12 +00:00
2015-04-12 13:34:50 +00:00
# include "../mwrender/renderingmanager.hpp"
2017-03-06 18:04:17 +00:00
# include "../mwrender/landmanager.hpp"
2015-04-12 13:34:50 +00:00
2015-05-09 23:09:00 +00:00
# include "../mwphysics/physicssystem.hpp"
2011-07-31 15:07:11 +00:00
# include "player.hpp"
2012-07-03 10:30:50 +00:00
# include "localscripts.hpp"
2012-10-01 15:17:04 +00:00
# include "esmstore.hpp"
2013-01-06 05:12:08 +00:00
# include "class.hpp"
2015-12-06 17:13:04 +00:00
# include "cellvisitors.hpp"
2014-02-23 19:11:05 +00:00
# include "cellstore.hpp"
2016-02-06 23:36:31 +00:00
# include "cellpreloader.hpp"
2011-07-31 15:07:11 +00:00
2012-05-14 15:41:17 +00:00
namespace
2011-08-08 22:05:16 +00:00
{
2015-01-13 16:14:54 +00:00
2017-02-04 14:12:01 +00:00
void setNodeRotation ( const MWWorld : : Ptr & ptr , MWRender : : RenderingManager & rendering , bool inverseRotationOrder )
{
if ( ! ptr . getRefData ( ) . getBaseNode ( ) )
return ;
osg : : Quat worldRotQuat ( ptr . getRefData ( ) . getPosition ( ) . rot [ 2 ] , osg : : Vec3 ( 0 , 0 , - 1 ) ) ;
if ( ! ptr . getClass ( ) . isActor ( ) )
{
float xr = ptr . getRefData ( ) . getPosition ( ) . rot [ 0 ] ;
float yr = ptr . getRefData ( ) . getPosition ( ) . rot [ 1 ] ;
if ( ! inverseRotationOrder )
worldRotQuat = worldRotQuat * osg : : Quat ( yr , osg : : Vec3 ( 0 , - 1 , 0 ) ) *
osg : : Quat ( xr , osg : : Vec3 ( - 1 , 0 , 0 ) ) ;
else
worldRotQuat = osg : : Quat ( xr , osg : : Vec3 ( - 1 , 0 , 0 ) ) * osg : : Quat ( yr , osg : : Vec3 ( 0 , - 1 , 0 ) ) * worldRotQuat ;
}
rendering . rotateObject ( ptr , worldRotQuat ) ;
}
2015-05-09 23:09:00 +00:00
void addObject ( const MWWorld : : Ptr & ptr , MWPhysics : : PhysicsSystem & physics ,
2015-01-13 16:14:54 +00:00
MWRender : : RenderingManager & rendering )
{
2017-06-28 20:40:13 +00:00
if ( ptr . getRefData ( ) . getBaseNode ( ) | | physics . getActor ( ptr ) )
{
std : : cerr < < " Warning: Tried to add " < < ptr . getCellRef ( ) . getRefId ( ) < < " to the scene twice " < < std : : endl ;
return ;
}
2017-02-20 18:04:02 +00:00
bool useAnim = ptr . getClass ( ) . useAnim ( ) ;
std : : string model = ptr . getClass ( ) . getModel ( ptr ) ;
if ( useAnim )
model = Misc : : ResourceHelpers : : correctActorModelPath ( model , rendering . getResourceSystem ( ) - > getVFS ( ) ) ;
2015-12-18 15:58:08 +00:00
std : : string id = ptr . getCellRef ( ) . getRefId ( ) ;
2015-01-13 16:14:54 +00:00
if ( id = = " prisonmarker " | | id = = " divinemarker " | | id = = " templemarker " | | id = = " northmarker " )
2015-01-15 15:05:25 +00:00
model = " " ; // marker objects that have a hardcoded function in the game logic, should be hidden from the player
2017-02-20 18:04:02 +00:00
2015-04-12 13:34:50 +00:00
ptr . getClass ( ) . insertObjectRendering ( ptr , model , rendering ) ;
2017-02-04 14:12:01 +00:00
setNodeRotation ( ptr , rendering , false ) ;
2015-04-25 13:19:17 +00:00
ptr . getClass ( ) . insertObject ( ptr , model , physics ) ;
2015-06-16 18:36:48 +00:00
2017-02-20 18:04:02 +00:00
if ( useAnim )
MWBase : : Environment : : get ( ) . getMechanicsManager ( ) - > add ( ptr ) ;
2015-06-16 18:36:48 +00:00
if ( ptr . getClass ( ) . isActor ( ) )
rendering . addWaterRippleEmitter ( ptr ) ;
2018-03-17 09:41:13 +00:00
// Restore effect particles
MWBase : : Environment : : get ( ) . getWorld ( ) - > applyLoopingParticles ( ptr ) ;
2015-01-13 16:14:54 +00:00
}
2015-11-12 00:44:00 +00:00
void updateObjectRotation ( const MWWorld : : Ptr & ptr , MWPhysics : : PhysicsSystem & physics ,
MWRender : : RenderingManager & rendering , bool inverseRotationOrder )
2014-06-14 15:56:41 +00:00
{
2017-02-04 14:12:01 +00:00
setNodeRotation ( ptr , rendering , inverseRotationOrder ) ;
physics . updateRotation ( ptr ) ;
2014-06-14 15:56:41 +00:00
}
2015-05-09 23:09:00 +00:00
void updateObjectScale ( const MWWorld : : Ptr & ptr , MWPhysics : : PhysicsSystem & physics ,
2015-04-24 12:49:20 +00:00
MWRender : : RenderingManager & rendering )
{
if ( ptr . getRefData ( ) . getBaseNode ( ) ! = NULL )
{
float scale = ptr . getCellRef ( ) . getScale ( ) ;
osg : : Vec3f scaleVec ( scale , scale , scale ) ;
2015-11-01 20:45:58 +00:00
ptr . getClass ( ) . adjustScale ( ptr , scaleVec , true ) ;
2015-04-24 12:49:20 +00:00
rendering . scaleObject ( ptr , scaleVec ) ;
2015-11-20 02:29:58 +00:00
physics . updateScale ( ptr ) ;
2015-04-24 12:49:20 +00:00
}
}
2015-12-06 17:13:04 +00:00
struct InsertVisitor
2014-02-23 20:21:27 +00:00
{
MWWorld : : CellStore & mCell ;
bool mRescale ;
Loading : : Listener & mLoadingListener ;
2015-05-09 23:09:00 +00:00
MWPhysics : : PhysicsSystem & mPhysics ;
2014-02-23 20:21:27 +00:00
MWRender : : RenderingManager & mRendering ;
2016-02-05 17:29:33 +00:00
std : : vector < MWWorld : : Ptr > mToInsert ;
2015-12-06 17:13:04 +00:00
InsertVisitor ( MWWorld : : CellStore & cell , bool rescale , Loading : : Listener & loadingListener ,
2015-05-09 23:09:00 +00:00
MWPhysics : : PhysicsSystem & physics , MWRender : : RenderingManager & rendering ) ;
2014-02-23 20:21:27 +00:00
bool operator ( ) ( const MWWorld : : Ptr & ptr ) ;
2016-02-05 17:29:33 +00:00
void insert ( ) ;
2014-02-23 20:21:27 +00:00
} ;
2015-12-06 17:13:04 +00:00
InsertVisitor : : InsertVisitor ( MWWorld : : CellStore & cell , bool rescale ,
2015-05-09 23:09:00 +00:00
Loading : : Listener & loadingListener , MWPhysics : : PhysicsSystem & physics ,
2014-02-23 20:21:27 +00:00
MWRender : : RenderingManager & rendering )
: mCell ( cell ) , mRescale ( rescale ) , mLoadingListener ( loadingListener ) ,
2015-04-25 13:19:17 +00:00
mPhysics ( physics ) ,
2015-04-12 13:34:50 +00:00
mRendering ( rendering )
2014-02-23 20:21:27 +00:00
{ }
2015-12-06 17:13:04 +00:00
bool InsertVisitor : : operator ( ) ( const MWWorld : : Ptr & ptr )
2014-02-23 20:21:27 +00:00
{
2016-02-05 17:29:33 +00:00
// do not insert directly as we can't modify the cell from within the visitation
// CreatureLevList::insertObjectRendering may spawn a new creature
mToInsert . push_back ( ptr ) ;
return true ;
}
2014-02-23 20:21:27 +00:00
2016-02-05 17:29:33 +00:00
void InsertVisitor : : insert ( )
{
for ( std : : vector < MWWorld : : Ptr > : : iterator it = mToInsert . begin ( ) ; it ! = mToInsert . end ( ) ; + + it )
2014-02-23 20:21:27 +00:00
{
2016-02-05 17:29:33 +00:00
MWWorld : : Ptr ptr = * it ;
if ( mRescale )
2014-02-23 20:21:27 +00:00
{
2016-02-05 17:29:33 +00:00
if ( ptr . getCellRef ( ) . getScale ( ) < 0.5 )
ptr . getCellRef ( ) . setScale ( 0.5 ) ;
else if ( ptr . getCellRef ( ) . getScale ( ) > 2 )
ptr . getCellRef ( ) . setScale ( 2 ) ;
2014-02-23 20:21:27 +00:00
}
2016-02-05 17:29:33 +00:00
if ( ! ptr . getRefData ( ) . isDeleted ( ) & & ptr . getRefData ( ) . isEnabled ( ) )
2014-02-23 20:21:27 +00:00
{
2016-02-05 17:29:33 +00:00
try
{
addObject ( ptr , mPhysics , mRendering ) ;
}
catch ( const std : : exception & e )
{
2017-03-02 21:07:43 +00:00
std : : string error ( " failed to render ' " + ptr . getCellRef ( ) . getRefId ( ) + " ': " ) ;
2016-02-05 17:29:33 +00:00
std : : cerr < < error + e . what ( ) < < std : : endl ;
}
2014-02-23 20:21:27 +00:00
}
2016-02-05 17:29:33 +00:00
mLoadingListener . increaseProgress ( 1 ) ;
}
2014-02-23 20:21:27 +00:00
}
2015-12-04 18:46:02 +00:00
2015-12-06 17:13:04 +00:00
struct AdjustPositionVisitor
2015-12-04 18:46:02 +00:00
{
bool operator ( ) ( const MWWorld : : Ptr & ptr )
{
if ( ! ptr . getRefData ( ) . isDeleted ( ) & & ptr . getRefData ( ) . isEnabled ( ) )
ptr . getClass ( ) . adjustPosition ( ptr , false ) ;
return true ;
}
} ;
2011-08-08 22:05:16 +00:00
}
2011-07-31 15:07:11 +00:00
namespace MWWorld
{
2012-03-19 01:31:31 +00:00
2015-11-12 00:44:00 +00:00
void Scene : : updateObjectRotation ( const Ptr & ptr , bool inverseRotationOrder )
2014-06-14 15:56:41 +00:00
{
2015-11-12 00:44:00 +00:00
: : updateObjectRotation ( ptr , * mPhysics , mRendering , inverseRotationOrder ) ;
2014-06-14 15:56:41 +00:00
}
2015-04-24 12:49:20 +00:00
void Scene : : updateObjectScale ( const Ptr & ptr )
{
2015-04-25 13:19:17 +00:00
: : updateObjectScale ( ptr , * mPhysics , mRendering ) ;
2015-04-24 12:49:20 +00:00
}
2014-10-02 14:30:23 +00:00
void Scene : : getGridCenter ( int & cellX , int & cellY )
{
2014-10-12 21:26:03 +00:00
int maxX = std : : numeric_limits < int > : : min ( ) ;
int maxY = std : : numeric_limits < int > : : min ( ) ;
int minX = std : : numeric_limits < int > : : max ( ) ;
int minY = std : : numeric_limits < int > : : max ( ) ;
2014-10-02 14:30:23 +00:00
CellStoreCollection : : iterator iter = mActiveCells . begin ( ) ;
while ( iter ! = mActiveCells . end ( ) )
{
assert ( ( * iter ) - > getCell ( ) - > isExterior ( ) ) ;
int x = ( * iter ) - > getCell ( ) - > getGridX ( ) ;
int y = ( * iter ) - > getCell ( ) - > getGridY ( ) ;
maxX = std : : max ( x , maxX ) ;
maxY = std : : max ( y , maxY ) ;
minX = std : : min ( x , minX ) ;
minY = std : : min ( y , minY ) ;
+ + iter ;
}
cellX = ( minX + maxX ) / 2 ;
cellY = ( minY + maxY ) / 2 ;
}
2014-05-11 13:17:25 +00:00
void Scene : : update ( float duration , bool paused )
{
2017-03-09 20:45:38 +00:00
mPreloadTimer + = duration ;
if ( mPreloadTimer > 0.1f )
2016-02-07 13:13:46 +00:00
{
2017-03-09 20:45:38 +00:00
preloadCells ( 0.1f ) ;
mPreloadTimer = 0.f ;
2016-02-07 13:13:46 +00:00
}
2015-04-18 23:57:52 +00:00
mRendering . update ( duration , paused ) ;
2016-03-28 22:39:36 +00:00
mPreloader - > updateCache ( mRendering . getReferenceTime ( ) ) ;
2011-12-27 00:23:46 +00:00
}
2012-03-19 01:31:31 +00:00
2011-11-16 04:31:18 +00:00
void Scene : : unloadCell ( CellStoreCollection : : iterator iter )
2011-07-31 15:07:11 +00:00
{
2011-11-25 04:13:34 +00:00
std : : cout < < " Unloading cell \n " ;
2015-12-06 17:13:04 +00:00
ListAndResetObjectsVisitor visitor ;
2013-03-10 09:00:20 +00:00
2018-01-28 19:19:03 +00:00
/*
Start of tes3mp addition
Set a const pointer to the iterator ' s ESM : : Cell here , because
( * iter ) - > getCell ( ) can become invalid later down
*/
const ESM : : Cell * cell = ( * iter ) - > getCell ( ) ;
/*
End of tes3mp addition
*/
2015-12-06 17:13:04 +00:00
( * iter ) - > forEach < ListAndResetObjectsVisitor > ( visitor ) ;
for ( std : : vector < MWWorld : : Ptr > : : const_iterator iter2 ( visitor . mObjects . begin ( ) ) ;
iter2 ! = visitor . mObjects . end ( ) ; + + iter2 )
2011-11-21 11:52:28 +00:00
{
2015-05-12 01:02:15 +00:00
mPhysics - > remove ( * iter2 ) ;
2013-04-17 15:05:54 +00:00
}
2012-03-13 16:09:50 +00:00
2014-02-21 10:35:46 +00:00
if ( ( * iter ) - > getCell ( ) - > isExterior ( ) )
2013-04-17 15:05:54 +00:00
{
2017-02-13 00:29:22 +00:00
const ESM : : Land * land =
2013-04-17 15:05:54 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > getStore ( ) . get < ESM : : Land > ( ) . search (
2014-02-21 10:35:46 +00:00
( * iter ) - > getCell ( ) - > getGridX ( ) ,
( * iter ) - > getCell ( ) - > getGridY ( )
2013-04-17 15:05:54 +00:00
) ;
2015-04-12 13:34:50 +00:00
if ( land & & land - > mDataTypes & ESM : : Land : : DATA_VHGT )
mPhysics - > removeHeightField ( ( * iter ) - > getCell ( ) - > getGridX ( ) , ( * iter ) - > getCell ( ) - > getGridY ( ) ) ;
2011-11-19 06:01:19 +00:00
}
2012-03-19 01:31:31 +00:00
2015-05-21 22:55:43 +00:00
MWBase : : Environment : : get ( ) . getMechanicsManager ( ) - > drop ( * iter ) ;
2015-04-12 13:34:50 +00:00
mRendering . removeCell ( * iter ) ;
2015-05-26 14:40:44 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > removeCell ( * iter ) ;
2012-01-23 13:33:06 +00:00
2012-07-03 10:30:50 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > getLocalScripts ( ) . clearCell ( * iter ) ;
2013-11-30 09:50:02 +00:00
2012-04-23 13:27:03 +00:00
MWBase : : Environment : : get ( ) . getSoundManager ( ) - > stopSound ( * iter ) ;
2012-11-02 20:33:08 +00:00
mActiveCells . erase ( * iter ) ;
2017-01-26 07:02:01 +00:00
2017-02-26 14:59:53 +00:00
/*
Start of tes3mp addition
Store a cell unload for the LocalPlayer
*/
2018-01-28 19:19:03 +00:00
mwmp : : Main : : get ( ) . getLocalPlayer ( ) - > storeCellState ( * cell , mwmp : : CellState : : UNLOAD ) ;
2017-02-26 14:59:53 +00:00
/*
End of tes3mp addition
*/
2011-07-31 15:07:11 +00:00
}
2011-08-01 01:33:02 +00:00
2016-02-27 11:53:07 +00:00
void Scene : : loadCell ( CellStore * cell , Loading : : Listener * loadingListener , bool respawn )
2011-07-31 15:07:11 +00:00
{
2012-11-02 20:33:08 +00:00
std : : pair < CellStoreCollection : : iterator , bool > result = mActiveCells . insert ( cell ) ;
2011-11-21 11:52:28 +00:00
2012-03-13 16:09:50 +00:00
if ( result . second )
{
2015-07-27 21:19:35 +00:00
std : : cout < < " Loading cell " < < cell - > getCell ( ) - > getDescription ( ) < < std : : endl ;
2015-03-02 20:12:21 +00:00
2015-05-02 22:39:01 +00:00
float verts = ESM : : Land : : LAND_SIZE ;
float worldsize = ESM : : Land : : REAL_SIZE ;
2012-03-13 16:09:50 +00:00
2013-04-08 23:24:17 +00:00
// Load terrain physics first...
2014-02-21 10:35:46 +00:00
if ( cell - > getCell ( ) - > isExterior ( ) )
2012-03-28 20:46:29 +00:00
{
2017-03-06 18:04:17 +00:00
int cellX = cell - > getCell ( ) - > getGridX ( ) ;
int cellY = cell - > getCell ( ) - > getGridY ( ) ;
osg : : ref_ptr < const ESMTerrain : : LandObject > land = mRendering . getLandManager ( ) - > getLand ( cellX , cellY ) ;
const ESM : : Land : : LandData * data = land ? land - > getData ( ESM : : Land : : DATA_VHGT ) : 0 ;
if ( data )
{
2017-03-07 14:00:16 +00:00
mPhysics - > addHeightField ( data - > mHeights , cellX , cell - > getCell ( ) - > getGridY ( ) , worldsize / ( verts - 1 ) , verts , data - > mMinHeight , data - > mMaxHeight , land . get ( ) ) ;
2012-11-05 12:07:59 +00:00
}
2016-02-28 15:47:41 +00:00
else
{
static std : : vector < float > defaultHeight ;
2016-02-28 15:49:18 +00:00
defaultHeight . resize ( verts * verts , ESM : : Land : : DEFAULT_HEIGHT ) ;
2017-03-07 14:00:16 +00:00
mPhysics - > addHeightField ( & defaultHeight [ 0 ] , cell - > getCell ( ) - > getGridX ( ) , cell - > getCell ( ) - > getGridY ( ) , worldsize / ( verts - 1 ) , verts , ESM : : Land : : DEFAULT_HEIGHT , ESM : : Land : : DEFAULT_HEIGHT , land . get ( ) ) ;
2016-02-28 15:47:41 +00:00
}
2012-03-28 20:46:29 +00:00
}
2012-03-28 19:46:52 +00:00
2016-02-05 17:29:33 +00:00
// register local scripts
// do this before insertCell, to make sure we don't add scripts from levelled creature spawning twice
MWBase : : Environment : : get ( ) . getWorld ( ) - > getLocalScripts ( ) . addCell ( cell ) ;
2016-02-27 11:53:07 +00:00
if ( respawn )
cell - > respawn ( ) ;
2013-04-08 23:24:17 +00:00
// ... then references. This is important for adjustPosition to work correctly.
2013-04-04 14:51:22 +00:00
/// \todo rescale depending on the state of a new GMST
2017-02-22 02:21:25 +00:00
2018-01-08 00:19:05 +00:00
/*
Start of tes3mp change ( major )
Instead of always rescaling objects as in the original code , never rescale them ,
so they can maintain their server - set scales when their cells are reloaded
*/
2017-02-22 02:21:25 +00:00
insertCell ( * cell , false , loadingListener ) ;
2018-01-08 00:19:05 +00:00
/*
End of tes3mp change ( major )
*/
2017-02-22 02:21:25 +00:00
2013-04-04 14:51:22 +00:00
2015-05-02 20:45:27 +00:00
mRendering . addCell ( cell ) ;
2015-05-10 13:34:07 +00:00
bool waterEnabled = cell - > getCell ( ) - > hasWater ( ) | | cell - > isExterior ( ) ;
2015-12-03 14:16:50 +00:00
float waterLevel = cell - > getWaterLevel ( ) ;
2015-06-02 14:35:35 +00:00
mRendering . setWaterEnabled ( waterEnabled ) ;
2014-10-05 20:24:11 +00:00
if ( waterEnabled )
{
2015-05-10 13:34:07 +00:00
mPhysics - > enableWater ( waterLevel ) ;
2015-06-02 14:35:35 +00:00
mRendering . setWaterHeight ( waterLevel ) ;
2014-10-05 20:24:11 +00:00
}
else
mPhysics - > disableWater ( ) ;
2015-05-12 01:02:15 +00:00
2015-04-12 13:34:50 +00:00
if ( ! cell - > isExterior ( ) & & ! ( cell - > getCell ( ) - > mData . mFlags & ESM : : Cell : : QuasiEx ) )
mRendering . configureAmbient ( cell - > getCell ( ) ) ;
2017-01-26 07:02:01 +00:00
2017-02-26 14:59:53 +00:00
/*
Start of tes3mp addition
Store a cell load for the LocalPlayer
*/
2017-02-18 07:26:11 +00:00
mwmp : : Main : : get ( ) . getLocalPlayer ( ) - > storeCellState ( * cell - > getCell ( ) , mwmp : : CellState : : LOAD ) ;
2017-02-26 14:59:53 +00:00
/*
End of tes3mp addition
*/
2011-07-31 15:07:11 +00:00
}
2016-02-09 17:33:02 +00:00
mPreloader - > notifyLoaded ( cell ) ;
2011-07-31 15:07:11 +00:00
}
2011-08-01 01:33:02 +00:00
2017-02-09 03:03:38 +00:00
void Scene : : clear ( )
2013-05-15 15:54:18 +00:00
{
CellStoreCollection : : iterator active = mActiveCells . begin ( ) ;
while ( active ! = mActiveCells . end ( ) )
unloadCell ( active + + ) ;
assert ( mActiveCells . empty ( ) ) ;
mCurrentCell = NULL ;
2017-02-09 03:03:38 +00:00
mPreloader - > clear ( ) ;
2013-05-15 15:54:18 +00:00
}
2015-04-12 13:34:50 +00:00
void Scene : : playerMoved ( const osg : : Vec3f & pos )
2014-10-02 14:30:23 +00:00
{
if ( ! mCurrentCell | | ! mCurrentCell - > isExterior ( ) )
return ;
// figure out the center of the current cell grid (*not* necessarily mCurrentCell, which is the cell the player is in)
int cellX , cellY ;
getGridCenter ( cellX , cellY ) ;
float centerX , centerY ;
MWBase : : Environment : : get ( ) . getWorld ( ) - > indexToPosition ( cellX , cellY , centerX , centerY , true ) ;
2016-02-07 15:37:56 +00:00
const float maxDistance = 8192 / 2 + mCellLoadingThreshold ; // 1/2 cell size + threshold
2015-04-12 13:34:50 +00:00
float distance = std : : max ( std : : abs ( centerX - pos . x ( ) ) , std : : abs ( centerY - pos . y ( ) ) ) ;
2014-10-02 14:30:23 +00:00
if ( distance > maxDistance )
{
int newX , newY ;
2015-04-12 13:34:50 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > positionToIndex ( pos . x ( ) , pos . y ( ) , newX , newY ) ;
2014-10-02 14:30:23 +00:00
changeCellGrid ( newX , newY ) ;
}
}
2016-02-27 11:53:07 +00:00
void Scene : : changeCellGrid ( int X , int Y , bool changeEvent )
2011-07-31 15:07:11 +00:00
{
2013-08-27 13:48:13 +00:00
Loading : : Listener * loadingListener = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getLoadingScreen ( ) ;
Loading : : ScopedLoad load ( loadingListener ) ;
2012-03-14 19:44:06 +00:00
2013-08-27 13:48:13 +00:00
std : : string loadingExteriorText = " #{sLoadingMessage3} " ;
loadingListener - > setLabel ( loadingExteriorText ) ;
2013-02-28 16:54:42 +00:00
2011-11-16 04:31:18 +00:00
CellStoreCollection : : iterator active = mActiveCells . begin ( ) ;
2011-07-31 15:07:11 +00:00
while ( active ! = mActiveCells . end ( ) )
{
2014-02-21 10:35:46 +00:00
if ( ( * active ) - > getCell ( ) - > isExterior ( ) )
2011-07-31 15:07:11 +00:00
{
2016-02-07 13:27:19 +00:00
if ( std : : abs ( X - ( * active ) - > getCell ( ) - > getGridX ( ) ) < = mHalfGridSize & &
std : : abs ( Y - ( * active ) - > getCell ( ) - > getGridY ( ) ) < = mHalfGridSize )
2011-07-31 15:07:11 +00:00
{
2015-01-06 22:54:53 +00:00
// keep cells within the new grid
2011-07-31 15:07:11 +00:00
+ + active ;
continue ;
}
}
unloadCell ( active + + ) ;
}
2013-08-27 13:48:13 +00:00
int refsToLoad = 0 ;
// get the number of refs to load
2016-02-07 13:27:19 +00:00
for ( int x = X - mHalfGridSize ; x < = X + mHalfGridSize ; + + x )
2014-10-02 14:30:23 +00:00
{
2016-02-07 13:27:19 +00:00
for ( int y = Y - mHalfGridSize ; y < = Y + mHalfGridSize ; + + y )
2012-09-11 14:37:54 +00:00
{
CellStoreCollection : : iterator iter = mActiveCells . begin ( ) ;
while ( iter ! = mActiveCells . end ( ) )
{
2014-02-21 10:35:46 +00:00
assert ( ( * iter ) - > getCell ( ) - > isExterior ( ) ) ;
2012-09-11 14:37:54 +00:00
2014-02-21 10:35:46 +00:00
if ( x = = ( * iter ) - > getCell ( ) - > getGridX ( ) & &
y = = ( * iter ) - > getCell ( ) - > getGridY ( ) )
2012-09-11 14:37:54 +00:00
break ;
+ + iter ;
}
if ( iter = = mActiveCells . end ( ) )
2014-02-23 20:21:27 +00:00
refsToLoad + = MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( x , y ) - > count ( ) ;
2012-09-11 14:37:54 +00:00
}
2014-10-02 14:30:23 +00:00
}
2012-09-11 14:37:54 +00:00
2013-08-27 13:48:13 +00:00
loadingListener - > setProgressRange ( refsToLoad ) ;
2011-07-31 15:07:11 +00:00
// Load cells
2016-02-07 13:27:19 +00:00
for ( int x = X - mHalfGridSize ; x < = X + mHalfGridSize ; + + x )
2014-10-02 14:30:23 +00:00
{
2016-02-07 13:27:19 +00:00
for ( int y = Y - mHalfGridSize ; y < = Y + mHalfGridSize ; + + y )
2011-07-31 15:07:11 +00:00
{
2011-11-16 04:31:18 +00:00
CellStoreCollection : : iterator iter = mActiveCells . begin ( ) ;
2011-07-31 15:07:11 +00:00
while ( iter ! = mActiveCells . end ( ) )
{
2014-02-21 10:35:46 +00:00
assert ( ( * iter ) - > getCell ( ) - > isExterior ( ) ) ;
2011-07-31 15:07:11 +00:00
2014-02-21 10:35:46 +00:00
if ( x = = ( * iter ) - > getCell ( ) - > getGridX ( ) & &
y = = ( * iter ) - > getCell ( ) - > getGridY ( ) )
2011-07-31 15:07:11 +00:00
break ;
+ + iter ;
}
if ( iter = = mActiveCells . end ( ) )
{
2012-07-03 10:30:50 +00:00
CellStore * cell = MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( x , y ) ;
2011-07-31 15:07:11 +00:00
2016-02-27 11:53:07 +00:00
loadCell ( cell , loadingListener , changeEvent ) ;
2011-07-31 15:07:11 +00:00
}
}
2014-10-02 14:30:23 +00:00
}
2011-07-31 15:07:11 +00:00
2017-02-26 14:59:53 +00:00
/*
Start of tes3mp addition
Send an ID_PLAYER_CELL_STATE packet with all cell states stored in LocalPlayer
and then clear them , but only if the player has finished character generation
*/
2017-02-03 18:27:40 +00:00
if ( mwmp : : Main : : get ( ) . getLocalPlayer ( ) - > hasFinishedCharGen ( ) )
2017-02-04 07:13:15 +00:00
{
2017-02-03 18:27:40 +00:00
mwmp : : Main : : get ( ) . getLocalPlayer ( ) - > sendCellStates ( ) ;
2017-02-04 07:13:15 +00:00
mwmp : : Main : : get ( ) . getLocalPlayer ( ) - > clearCellStates ( ) ;
}
2017-02-26 14:59:53 +00:00
/*
End of tes3mp addition
*/
2017-02-03 18:27:40 +00:00
2014-10-02 14:30:23 +00:00
CellStore * current = MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( X , Y ) ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > changeCell ( current ) ;
2011-07-31 15:07:11 +00:00
2016-02-27 11:53:07 +00:00
if ( changeEvent )
mCellChanged = true ;
2014-10-02 14:30:23 +00:00
}
2011-07-31 15:07:11 +00:00
2014-10-02 14:30:23 +00:00
void Scene : : changePlayerCell ( CellStore * cell , const ESM : : Position & pos , bool adjustPlayerPos )
{
mCurrentCell = cell ;
2011-07-31 15:07:11 +00:00
2017-03-09 01:17:25 +00:00
mRendering . enableTerrain ( cell - > isExterior ( ) ) ;
2014-10-02 14:30:23 +00:00
MWBase : : World * world = MWBase : : Environment : : get ( ) . getWorld ( ) ;
MWWorld : : Ptr old = world - > getPlayerPtr ( ) ;
world - > getPlayer ( ) . setCell ( cell ) ;
2011-07-31 15:07:11 +00:00
2014-10-02 14:30:23 +00:00
MWWorld : : Ptr player = world - > getPlayerPtr ( ) ;
2015-05-21 21:54:39 +00:00
mRendering . updatePlayerPtr ( player ) ;
2011-07-31 15:07:11 +00:00
2014-10-02 14:30:23 +00:00
if ( adjustPlayerPos ) {
world - > moveObject ( player , pos . pos [ 0 ] , pos . pos [ 1 ] , pos . pos [ 2 ] ) ;
2011-07-31 15:07:11 +00:00
2015-11-12 00:08:31 +00:00
float x = pos . rot [ 0 ] ;
float y = pos . rot [ 1 ] ;
float z = pos . rot [ 2 ] ;
2014-10-02 14:30:23 +00:00
world - > rotateObject ( player , x , y , z ) ;
2011-07-31 15:07:11 +00:00
Some PVS-Studio and cppcheck fixes
cppcheck:
[apps/esmtool/record.cpp:697]: (performance) Prefer prefix ++/-- operators for non-primitive types.
[apps/esmtool/record.cpp:1126]: (performance) Prefer prefix ++/-- operators for non-primitive types.
[apps/esmtool/record.cpp:1138]: (performance) Prefer prefix ++/-- operators for non-primitive types.
[apps/niftest/niftest.cpp:36]: (performance) Function parameter 'filename' should be passed by reference.
[apps/niftest/niftest.cpp:41]: (performance) Function parameter 'filename' should be passed by reference.
[apps/opencs/model/prefs/boolsetting.cpp:25]: (warning) Possible leak in public function. The pointer 'mWidget' is not deallocated before it is allocated.
[apps/opencs/model/prefs/shortcuteventhandler.cpp:52]: (warning) Return value of std::remove() ignored. Elements remain in container.
[apps/openmw/mwstate/quicksavemanager.cpp:5]: (performance) Variable 'mSaveName' is assigned in constructor body. Consider performing initialization in initialization list.
PVS-Studio:
apps/opencs/model/filter/parser.cpp 582 warn V560 A part of conditional expression is always true: allowPredefined.
apps/opencs/view/world/referencecreator.cpp 67 warn V547 Expression '!errors.empty()' is always false.
apps/opencs/view/world/referencecreator.cpp 74 warn V547 Expression '!errors.empty()' is always false.
apps/opencs/view/doc/loader.cpp 170 warn V560 A part of conditional expression is always true: !completed.
apps/opencs/view/doc/loader.cpp 170 warn V560 A part of conditional expression is always true: !error.empty().
apps/opencs/model/tools/pathgridcheck.cpp 32 err V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 32, 34.
apps/opencs/model/world/refidadapterimp.cpp 1376 err V547 Expression 'subColIndex < 3' is always true.
apps/openmw/mwgui/widgets.hpp 318 warn V703 It is odd that the 'mEnableRepeat' field in derived class 'MWScrollBar' overwrites field in base class 'ScrollBar'. Check lines: widgets.hpp:318, MyGUI_ScrollBar.h:179.
apps/openmw/mwgui/widgets.hpp 319 warn V703 It is odd that the 'mRepeatTriggerTime' field in derived class 'MWScrollBar' overwrites field in base class 'ScrollBar'. Check lines: widgets.hpp:319, MyGUI_ScrollBar.h:180.
apps/openmw/mwgui/widgets.hpp 320 warn V703 It is odd that the 'mRepeatStepTime' field in derived class 'MWScrollBar' overwrites field in base class 'ScrollBar'. Check lines: widgets.hpp:320, MyGUI_ScrollBar.h:181
apps/openmw/mwmechanics/actors.cpp 1425 warn V547 Expression '!detected' is always true.
apps/openmw/mwmechanics/character.cpp 2155 err V547 Expression 'mode == 0' is always true.
apps/openmw/mwmechanics/character.cpp 1192 warn V592 The expression was enclosed by parentheses twice: ((expression)). One pair of parentheses is unnecessary or misprint is present.
apps/openmw/mwmechanics/character.cpp 521 warn V560 A part of conditional expression is always true: (idle == mIdleState).
apps/openmw/mwmechanics/pathfinding.cpp 317 err V547 Expression 'mPath.size() >= 2' is always true.
apps/openmw/mwscript/interpretercontext.cpp 409 warn V560 A part of conditional expression is always false: rank > 9.
apps/openmw/mwgui/windowbase.cpp 28 warn V560 A part of conditional expression is always true: !visible.
apps/openmw/mwgui/journalwindow.cpp 561 warn V547 Expression '!mAllQuests' is always false.
apps/openmw/mwgui/referenceinterface.cpp 18 warn V571 Recurring check. The '!mPtr.isEmpty()' condition was already verified in line 16.
apps/openmw/mwworld/scene.cpp 463 warn V547 Expression 'adjustPlayerPos' is always true.
apps/openmw/mwworld/worldimp.cpp 409 err V766 An item with the same key '"sCompanionShare"' has already been added.
apps/openmw/mwworld/cellstore.cpp 691 warn V519 The 'state.mWaterLevel' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 689, 691.
apps/openmw/mwworld/weather.cpp 1125 warn V519 The 'mResult.mParticleEffect' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 1123, 1125.
apps/openmw/mwworld/weather.cpp 1137 warn V519 The 'mResult.mParticleEffect' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 1135, 1137.
apps/wizard/unshield/unshieldworker.cpp 475 warn V728 An excessive check can be simplified. The '(A && B) || (!A && !B)' expression is equivalent to the 'bool(A) == bool(B)' expression.
apps/wizard/installationpage.cpp 163 warn V735 Possibly an incorrect HTML. The "</p" closing tag was encountered, while the "</span" tag was expected.
components/fontloader/fontloader.cpp 427 err V547 Expression 'i == 1' is always true.
components/nifosg/nifloader.cpp 282 warn V519 The 'created' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 278, 282.
components/esm/loadregn.cpp 119 err V586 The 'clear' function is called twice for deallocation of the same resource. Check lines: 112, 119.
components/esm/cellref.cpp 178 warn V581 The conditional expressions of the 'if' statements situated alongside each other are identical. Check lines: 175, 178.
components/esmterrain/storage.cpp 235 warn V560 A part of conditional expression is always true: colStart == 0.
components/esmterrain/storage.cpp 237 warn V560 A part of conditional expression is always true: rowStart == 0.
2018-04-09 15:55:16 +00:00
player . getClass ( ) . adjustPosition ( player , true ) ;
2014-10-02 14:30:23 +00:00
}
MWBase : : MechanicsManager * mechMgr =
MWBase : : Environment : : get ( ) . getMechanicsManager ( ) ;
mechMgr - > updateCell ( old , player ) ;
mechMgr - > watchActor ( player ) ;
2017-06-25 10:47:57 +00:00
mPhysics - > updatePtr ( old , player ) ;
2014-10-02 14:30:23 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > adjustSky ( ) ;
2017-02-09 00:24:13 +00:00
mLastPlayerPos = pos . asVec3 ( ) ;
2011-07-31 15:07:11 +00:00
}
2011-08-01 01:33:02 +00:00
2015-05-09 23:09:00 +00:00
Scene : : Scene ( MWRender : : RenderingManager & rendering , MWPhysics : : PhysicsSystem * physics )
2016-02-04 23:39:52 +00:00
: mCurrentCell ( 0 ) , mCellChanged ( false ) , mPhysics ( physics ) , mRendering ( rendering )
2016-02-07 13:13:46 +00:00
, mPreloadTimer ( 0.f )
2016-02-07 13:27:19 +00:00
, mHalfGridSize ( Settings : : Manager : : getInt ( " exterior cell load distance " , " Cells " ) )
2016-02-07 15:37:56 +00:00
, mCellLoadingThreshold ( 1024.f )
2016-02-07 17:01:14 +00:00
, mPreloadDistance ( Settings : : Manager : : getInt ( " preload distance " , " Cells " ) )
, mPreloadEnabled ( Settings : : Manager : : getBool ( " preload enabled " , " Cells " ) )
2016-02-09 00:58:07 +00:00
, mPreloadExteriorGrid ( Settings : : Manager : : getBool ( " preload exterior grid " , " Cells " ) )
, mPreloadDoors ( Settings : : Manager : : getBool ( " preload doors " , " Cells " ) )
, mPreloadFastTravel ( Settings : : Manager : : getBool ( " preload fast travel " , " Cells " ) )
2017-07-19 14:43:29 +00:00
, mPredictionTime ( Settings : : Manager : : getFloat ( " prediction time " , " Cells " ) )
2011-08-01 01:33:02 +00:00
{
2017-03-06 18:04:17 +00:00
mPreloader . reset ( new CellPreloader ( rendering . getResourceSystem ( ) , physics - > getShapeManager ( ) , rendering . getTerrain ( ) , rendering . getLandManager ( ) ) ) ;
2016-02-09 00:02:40 +00:00
mPreloader - > setWorkQueue ( mRendering . getWorkQueue ( ) ) ;
2016-02-07 18:05:55 +00:00
2017-02-04 01:36:44 +00:00
mPreloader - > setUnrefQueue ( rendering . getUnrefQueue ( ) ) ;
2016-02-09 18:04:59 +00:00
mPhysics - > setUnrefQueue ( rendering . getUnrefQueue ( ) ) ;
2016-02-18 16:47:10 +00:00
rendering . getResourceSystem ( ) - > setExpiryDelay ( Settings : : Manager : : getFloat ( " cache expiry delay " , " Cells " ) ) ;
mPreloader - > setExpiryDelay ( Settings : : Manager : : getFloat ( " preload cell expiry delay " , " Cells " ) ) ;
mPreloader - > setMinCacheSize ( Settings : : Manager : : getInt ( " preload cell cache min " , " Cells " ) ) ;
mPreloader - > setMaxCacheSize ( Settings : : Manager : : getInt ( " preload cell cache max " , " Cells " ) ) ;
2016-03-29 21:28:53 +00:00
mPreloader - > setPreloadInstances ( Settings : : Manager : : getBool ( " preload instances " , " Cells " ) ) ;
2011-08-01 01:33:02 +00:00
}
Scene : : ~ Scene ( )
{
}
bool Scene : : hasCellChanged ( ) const
{
return mCellChanged ;
}
2011-08-09 07:56:09 +00:00
2011-11-16 04:31:18 +00:00
const Scene : : CellStoreCollection & Scene : : getActiveCells ( ) const
2011-08-01 02:06:38 +00:00
{
return mActiveCells ;
}
2011-08-09 07:56:09 +00:00
2016-03-24 16:18:08 +00:00
void Scene : : changeToInteriorCell ( const std : : string & cellName , const ESM : : Position & position , bool adjustPlayerPos , bool changeEvent )
2011-07-31 15:07:11 +00:00
{
2014-08-07 14:37:03 +00:00
CellStore * cell = MWBase : : Environment : : get ( ) . getWorld ( ) - > getInterior ( cellName ) ;
bool loadcell = ( mCurrentCell = = NULL ) ;
if ( ! loadcell )
loadcell = * mCurrentCell ! = * cell ;
2014-08-01 14:25:41 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > fadeScreenOut ( 0.5 ) ;
2013-02-28 16:54:42 +00:00
2013-08-27 13:48:13 +00:00
Loading : : Listener * loadingListener = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getLoadingScreen ( ) ;
std : : string loadingInteriorText = " #{sLoadingMessage2} " ;
loadingListener - > setLabel ( loadingInteriorText ) ;
2014-08-07 14:37:03 +00:00
Loading : : ScopedLoad load ( loadingListener ) ;
2013-02-28 16:54:42 +00:00
2012-11-03 19:29:55 +00:00
if ( ! loadcell )
2012-09-11 14:37:54 +00:00
{
2012-11-04 23:22:30 +00:00
MWBase : : World * world = MWBase : : Environment : : get ( ) . getWorld ( ) ;
2014-01-08 17:39:44 +00:00
world - > moveObject ( world - > getPlayerPtr ( ) , position . pos [ 0 ] , position . pos [ 1 ] , position . pos [ 2 ] ) ;
2012-11-04 23:22:30 +00:00
2015-11-12 00:08:31 +00:00
float x = position . rot [ 0 ] ;
float y = position . rot [ 1 ] ;
float z = position . rot [ 2 ] ;
2014-01-08 17:39:44 +00:00
world - > rotateObject ( world - > getPlayerPtr ( ) , x , y , z ) ;
2013-04-03 21:55:57 +00:00
2016-03-24 16:18:08 +00:00
if ( adjustPlayerPos )
world - > getPlayerPtr ( ) . getClass ( ) . adjustPosition ( world - > getPlayerPtr ( ) , true ) ;
2014-08-01 14:25:41 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > fadeScreenIn ( 0.5 ) ;
2012-11-04 23:22:30 +00:00
return ;
2012-09-11 14:37:54 +00:00
}
2013-03-10 09:00:20 +00:00
2012-11-04 23:22:30 +00:00
std : : cout < < " Changing to interior \n " ;
2011-07-31 15:07:11 +00:00
2012-11-04 23:22:30 +00:00
// unload
2014-09-26 15:12:48 +00:00
CellStoreCollection : : iterator active = mActiveCells . begin ( ) ;
2012-11-04 23:22:30 +00:00
while ( active ! = mActiveCells . end ( ) )
unloadCell ( active + + ) ;
2012-04-23 13:27:03 +00:00
2014-02-23 20:21:27 +00:00
int refsToLoad = cell - > count ( ) ;
2013-08-27 13:48:13 +00:00
loadingListener - > setProgressRange ( refsToLoad ) ;
2012-11-04 23:22:30 +00:00
// Load cell.
2016-02-27 11:53:07 +00:00
loadCell ( cell , loadingListener , changeEvent ) ;
2011-07-31 15:07:11 +00:00
2017-02-26 14:59:53 +00:00
/*
Start of tes3mp addition
Send an ID_PLAYER_CELL_STATE packet with all cell states stored in LocalPlayer
and then clear them , but only if the player has finished character generation
*/
2017-02-03 18:27:40 +00:00
if ( mwmp : : Main : : get ( ) . getLocalPlayer ( ) - > hasFinishedCharGen ( ) )
2017-02-04 07:13:15 +00:00
{
2017-02-03 18:27:40 +00:00
mwmp : : Main : : get ( ) . getLocalPlayer ( ) - > sendCellStates ( ) ;
2017-02-04 07:13:15 +00:00
mwmp : : Main : : get ( ) . getLocalPlayer ( ) - > clearCellStates ( ) ;
}
2017-02-26 14:59:53 +00:00
/*
End of tes3mp addition
*/
2017-02-03 18:27:40 +00:00
2016-03-29 23:54:03 +00:00
changePlayerCell ( cell , position , adjustPlayerPos ) ;
2012-11-03 19:29:55 +00:00
2012-11-04 23:22:30 +00:00
// adjust fog
2015-04-21 21:27:26 +00:00
mRendering . configureFog ( mCurrentCell - > getCell ( ) ) ;
2013-03-10 09:00:20 +00:00
2011-07-31 15:07:11 +00:00
// Sky system
2012-07-03 10:30:50 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > adjustSky ( ) ;
2011-07-31 15:07:11 +00:00
2016-02-27 11:53:07 +00:00
if ( changeEvent )
mCellChanged = true ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > fadeScreenIn ( 0.5 ) ;
2014-10-02 14:30:23 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > changeCell ( mCurrentCell ) ;
2011-07-31 15:07:11 +00:00
}
2011-08-01 01:33:02 +00:00
2016-02-27 11:53:07 +00:00
void Scene : : changeToExteriorCell ( const ESM : : Position & position , bool adjustPlayerPos , bool changeEvent )
2011-07-31 15:07:11 +00:00
{
int x = 0 ;
int y = 0 ;
2012-07-03 10:30:50 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > positionToIndex ( position . pos [ 0 ] , position . pos [ 1 ] , x , y ) ;
2011-07-31 15:07:11 +00:00
2017-10-05 16:39:28 +00:00
if ( changeEvent )
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > fadeScreenOut ( 0.5 ) ;
2016-02-27 11:53:07 +00:00
changeCellGrid ( x , y , changeEvent ) ;
2014-10-02 14:30:23 +00:00
CellStore * current = MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( x , y ) ;
changePlayerCell ( current , position , adjustPlayerPos ) ;
2017-10-05 16:39:28 +00:00
if ( changeEvent )
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > fadeScreenIn ( 0.5 ) ;
2011-07-31 15:07:11 +00:00
}
2011-08-09 07:56:09 +00:00
2013-12-05 12:21:26 +00:00
CellStore * Scene : : getCurrentCell ( )
2011-08-01 02:06:38 +00:00
{
return mCurrentCell ;
}
2011-08-01 01:33:02 +00:00
void Scene : : markCellAsUnchanged ( )
{
mCellChanged = false ;
}
2011-08-27 08:30:38 +00:00
2013-12-05 12:21:26 +00:00
void Scene : : insertCell ( CellStore & cell , bool rescale , Loading : : Listener * loadingListener )
2012-05-14 15:41:17 +00:00
{
2015-12-06 17:13:04 +00:00
InsertVisitor insertVisitor ( cell , rescale , * loadingListener , * mPhysics , mRendering ) ;
cell . forEach ( insertVisitor ) ;
2016-02-05 17:29:33 +00:00
insertVisitor . insert ( ) ;
2015-12-04 18:46:02 +00:00
// do adjustPosition (snapping actors to ground) after objects are loaded, so we don't depend on the loading order
2015-12-06 17:13:04 +00:00
AdjustPositionVisitor adjustPosVisitor ;
cell . forEach ( adjustPosVisitor ) ;
2012-05-14 15:41:17 +00:00
}
2011-08-08 22:05:16 +00:00
2012-05-25 15:28:27 +00:00
void Scene : : addObjectToScene ( const Ptr & ptr )
{
2015-01-31 18:21:16 +00:00
try
{
2015-04-25 13:19:17 +00:00
addObject ( ptr , * mPhysics , mRendering ) ;
2015-04-23 21:50:46 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > scaleObject ( ptr , ptr . getCellRef ( ) . getScale ( ) ) ;
2015-01-31 18:21:16 +00:00
}
catch ( std : : exception & e )
{
2017-03-02 21:07:43 +00:00
std : : cerr < < " failed to render ' " < < ptr . getCellRef ( ) . getRefId ( ) < < " ': " < < e . what ( ) < < std : : endl ;
2015-01-31 18:21:16 +00:00
}
2012-05-25 15:28:27 +00:00
}
2012-08-09 12:33:21 +00:00
2012-05-25 15:28:27 +00:00
void Scene : : removeObjectFromScene ( const Ptr & ptr )
{
2013-01-29 07:39:11 +00:00
MWBase : : Environment : : get ( ) . getMechanicsManager ( ) - > remove ( ptr ) ;
2012-05-25 15:28:27 +00:00
MWBase : : Environment : : get ( ) . getSoundManager ( ) - > stopSound3D ( ptr ) ;
2015-05-12 01:02:15 +00:00
mPhysics - > remove ( ptr ) ;
2015-05-21 22:55:43 +00:00
mRendering . removeObject ( ptr ) ;
2015-06-16 18:36:48 +00:00
if ( ptr . getClass ( ) . isActor ( ) )
mRendering . removeWaterRippleEmitter ( ptr ) ;
2012-05-25 15:28:27 +00:00
}
2012-07-26 12:14:11 +00:00
bool Scene : : isCellActive ( const CellStore & cell )
{
CellStoreCollection : : iterator active = mActiveCells . begin ( ) ;
while ( active ! = mActiveCells . end ( ) ) {
2012-08-08 10:51:33 +00:00
if ( * * active = = cell ) {
2012-07-26 12:14:11 +00:00
return true ;
}
+ + active ;
}
return false ;
}
2014-04-29 13:27:49 +00:00
Ptr Scene : : searchPtrViaActorId ( int actorId )
{
for ( CellStoreCollection : : const_iterator iter ( mActiveCells . begin ( ) ) ;
iter ! = mActiveCells . end ( ) ; + + iter )
if ( Ptr ptr = ( * iter ) - > searchViaActorId ( actorId ) )
return ptr ;
return Ptr ( ) ;
}
2016-02-07 13:13:46 +00:00
2017-02-14 23:55:35 +00:00
class PreloadMeshItem : public SceneUtil : : WorkItem
{
public :
PreloadMeshItem ( const std : : string & mesh , Resource : : SceneManager * sceneManager )
: mMesh ( mesh ) , mSceneManager ( sceneManager )
{
}
virtual void doWork ( )
{
try
{
mSceneManager - > getTemplate ( mMesh ) ;
}
catch ( std : : exception & e )
{
}
}
private :
std : : string mMesh ;
Resource : : SceneManager * mSceneManager ;
} ;
2017-02-20 18:58:00 +00:00
void Scene : : preload ( const std : : string & mesh , bool useAnim )
2017-02-14 23:55:35 +00:00
{
2017-02-20 18:58:00 +00:00
std : : string mesh_ = mesh ;
if ( useAnim )
mesh_ = Misc : : ResourceHelpers : : correctActorModelPath ( mesh_ , mRendering . getResourceSystem ( ) - > getVFS ( ) ) ;
if ( ! mRendering . getResourceSystem ( ) - > getSceneManager ( ) - > checkLoaded ( mesh_ , mRendering . getReferenceTime ( ) ) )
mRendering . getWorkQueue ( ) - > addWorkItem ( new PreloadMeshItem ( mesh_ , mRendering . getResourceSystem ( ) - > getSceneManager ( ) ) ) ;
2017-02-14 23:55:35 +00:00
}
2017-02-09 00:24:13 +00:00
void Scene : : preloadCells ( float dt )
2016-02-07 15:37:56 +00:00
{
2017-03-09 03:18:35 +00:00
std : : vector < osg : : Vec3f > exteriorPositions ;
2017-02-09 00:24:13 +00:00
const MWWorld : : ConstPtr player = MWBase : : Environment : : get ( ) . getWorld ( ) - > getPlayerPtr ( ) ;
osg : : Vec3f playerPos = player . getRefData ( ) . getPosition ( ) . asVec3 ( ) ;
osg : : Vec3f moved = playerPos - mLastPlayerPos ;
2017-07-19 14:43:29 +00:00
osg : : Vec3f predictedPos = playerPos + moved / dt * mPredictionTime ;
2017-02-09 00:24:13 +00:00
2017-03-09 03:18:35 +00:00
if ( mCurrentCell - > isExterior ( ) )
exteriorPositions . push_back ( predictedPos ) ;
2017-02-09 00:24:13 +00:00
mLastPlayerPos = playerPos ;
2017-03-09 20:45:38 +00:00
if ( mPreloadEnabled )
{
if ( mPreloadDoors )
preloadTeleportDoorDestinations ( playerPos , predictedPos , exteriorPositions ) ;
if ( mPreloadExteriorGrid )
preloadExteriorGrid ( playerPos , predictedPos ) ;
if ( mPreloadFastTravel )
2017-03-11 23:47:06 +00:00
preloadFastTravelDestinations ( playerPos , predictedPos , exteriorPositions ) ;
2017-03-09 20:45:38 +00:00
}
2017-03-09 03:18:35 +00:00
mPreloader - > setTerrainPreloadPositions ( exteriorPositions ) ;
2016-02-07 15:37:56 +00:00
}
2017-03-09 03:18:35 +00:00
void Scene : : preloadTeleportDoorDestinations ( const osg : : Vec3f & playerPos , const osg : : Vec3f & predictedPos , std : : vector < osg : : Vec3f > & exteriorPositions )
2016-02-07 13:13:46 +00:00
{
std : : vector < MWWorld : : ConstPtr > teleportDoors ;
for ( CellStoreCollection : : const_iterator iter ( mActiveCells . begin ( ) ) ;
iter ! = mActiveCells . end ( ) ; + + iter )
{
const MWWorld : : CellStore * cellStore = * iter ;
typedef MWWorld : : CellRefList < ESM : : Door > : : List DoorList ;
const DoorList & doors = cellStore - > getReadOnlyDoors ( ) . mList ;
for ( DoorList : : const_iterator doorIt = doors . begin ( ) ; doorIt ! = doors . end ( ) ; + + doorIt )
{
if ( ! doorIt - > mRef . getTeleport ( ) ) {
continue ;
}
teleportDoors . push_back ( MWWorld : : ConstPtr ( & * doorIt , cellStore ) ) ;
}
}
for ( std : : vector < MWWorld : : ConstPtr > : : iterator it = teleportDoors . begin ( ) ; it ! = teleportDoors . end ( ) ; + + it )
{
const MWWorld : : ConstPtr & door = * it ;
2017-02-09 00:24:13 +00:00
float sqrDistToPlayer = ( playerPos - door . getRefData ( ) . getPosition ( ) . asVec3 ( ) ) . length2 ( ) ;
sqrDistToPlayer = std : : min ( sqrDistToPlayer , ( predictedPos - door . getRefData ( ) . getPosition ( ) . asVec3 ( ) ) . length2 ( ) ) ;
2016-02-07 13:13:46 +00:00
2016-02-07 15:37:56 +00:00
if ( sqrDistToPlayer < mPreloadDistance * mPreloadDistance )
2016-02-07 13:13:46 +00:00
{
try
{
if ( ! door . getCellRef ( ) . getDestCell ( ) . empty ( ) )
2016-02-09 00:51:23 +00:00
preloadCell ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getInterior ( door . getCellRef ( ) . getDestCell ( ) ) ) ;
2016-02-07 13:13:46 +00:00
else
{
2017-03-09 03:18:35 +00:00
osg : : Vec3f pos = door . getCellRef ( ) . getDoorDest ( ) . asVec3 ( ) ;
2016-02-07 13:13:46 +00:00
int x , y ;
2017-03-09 03:18:35 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > positionToIndex ( pos . x ( ) , pos . y ( ) , x , y ) ;
2016-02-09 00:51:23 +00:00
preloadCell ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( x , y ) , true ) ;
2017-03-09 03:18:35 +00:00
exteriorPositions . push_back ( pos ) ;
2016-02-07 13:13:46 +00:00
}
}
catch ( std : : exception & e )
{
// ignore error for now, would spam the log too much
}
}
}
}
2016-02-07 15:37:56 +00:00
2017-02-09 00:24:13 +00:00
void Scene : : preloadExteriorGrid ( const osg : : Vec3f & playerPos , const osg : : Vec3f & predictedPos )
2016-02-07 15:37:56 +00:00
{
if ( ! MWBase : : Environment : : get ( ) . getWorld ( ) - > isCellExterior ( ) )
return ;
int halfGridSizePlusOne = mHalfGridSize + 1 ;
int cellX , cellY ;
getGridCenter ( cellX , cellY ) ;
float centerX , centerY ;
MWBase : : Environment : : get ( ) . getWorld ( ) - > indexToPosition ( cellX , cellY , centerX , centerY , true ) ;
for ( int dx = - halfGridSizePlusOne ; dx < = halfGridSizePlusOne ; + + dx )
{
for ( int dy = - halfGridSizePlusOne ; dy < = halfGridSizePlusOne ; + + dy )
{
if ( dy ! = halfGridSizePlusOne & & dy ! = - halfGridSizePlusOne & & dx ! = halfGridSizePlusOne & & dx ! = - halfGridSizePlusOne )
continue ; // only care about the outer (not yet loaded) part of the grid
float thisCellCenterX , thisCellCenterY ;
MWBase : : Environment : : get ( ) . getWorld ( ) - > indexToPosition ( cellX + dx , cellY + dy , thisCellCenterX , thisCellCenterY , true ) ;
float dist = std : : max ( std : : abs ( thisCellCenterX - playerPos . x ( ) ) , std : : abs ( thisCellCenterY - playerPos . y ( ) ) ) ;
2017-02-09 00:24:13 +00:00
dist = std : : min ( dist , std : : max ( std : : abs ( thisCellCenterX - predictedPos . x ( ) ) , std : : abs ( thisCellCenterY - predictedPos . y ( ) ) ) ) ;
2016-02-07 15:37:56 +00:00
float loadDist = 8192 / 2 + 8192 - mCellLoadingThreshold + mPreloadDistance ;
if ( dist < loadDist )
2016-02-09 00:51:23 +00:00
preloadCell ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( cellX + dx , cellY + dy ) ) ;
}
}
}
void Scene : : preloadCell ( CellStore * cell , bool preloadSurrounding )
{
if ( preloadSurrounding & & cell - > isExterior ( ) )
{
int x = cell - > getCell ( ) - > getGridX ( ) ;
int y = cell - > getCell ( ) - > getGridY ( ) ;
2016-03-28 22:48:47 +00:00
unsigned int numpreloaded = 0 ;
2016-02-09 00:51:23 +00:00
for ( int dx = - mHalfGridSize ; dx < = mHalfGridSize ; + + dx )
{
for ( int dy = - mHalfGridSize ; dy < = mHalfGridSize ; + + dy )
{
mPreloader - > preload ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( x + dx , y + dy ) , mRendering . getReferenceTime ( ) ) ;
2016-03-28 22:48:47 +00:00
if ( + + numpreloaded > = mPreloader - > getMaxCacheSize ( ) )
break ;
2016-02-09 00:51:23 +00:00
}
}
}
else
mPreloader - > preload ( cell , mRendering . getReferenceTime ( ) ) ;
}
2017-03-12 21:38:50 +00:00
void Scene : : preloadTerrain ( const osg : : Vec3f & pos )
{
std : : vector < osg : : Vec3f > vec ;
vec . push_back ( pos ) ;
mPreloader - > setTerrainPreloadPositions ( vec ) ;
}
2016-02-09 00:51:23 +00:00
struct ListFastTravelDestinationsVisitor
{
ListFastTravelDestinationsVisitor ( float preloadDist , const osg : : Vec3f & playerPos )
: mPreloadDist ( preloadDist )
, mPlayerPos ( playerPos )
{
}
bool operator ( ) ( const MWWorld : : Ptr & ptr )
{
if ( ( ptr . getRefData ( ) . getPosition ( ) . asVec3 ( ) - mPlayerPos ) . length2 ( ) > mPreloadDist * mPreloadDist )
return true ;
if ( ptr . getClass ( ) . isNpc ( ) )
{
const std : : vector < ESM : : Transport : : Dest > & transport = ptr . get < ESM : : NPC > ( ) - > mBase - > mTransport . mList ;
mList . insert ( mList . begin ( ) , transport . begin ( ) , transport . end ( ) ) ;
}
else
{
const std : : vector < ESM : : Transport : : Dest > & transport = ptr . get < ESM : : Creature > ( ) - > mBase - > mTransport . mList ;
mList . insert ( mList . begin ( ) , transport . begin ( ) , transport . end ( ) ) ;
}
return true ;
}
float mPreloadDist ;
osg : : Vec3f mPlayerPos ;
std : : vector < ESM : : Transport : : Dest > mList ;
} ;
2017-03-11 23:47:06 +00:00
void Scene : : preloadFastTravelDestinations ( const osg : : Vec3f & playerPos , const osg : : Vec3f & /*predictedPos*/ , std : : vector < osg : : Vec3f > & exteriorPositions ) // ignore predictedPos here since opening dialogue with travel service takes extra time
2016-02-09 00:51:23 +00:00
{
const MWWorld : : ConstPtr player = MWBase : : Environment : : get ( ) . getWorld ( ) - > getPlayerPtr ( ) ;
ListFastTravelDestinationsVisitor listVisitor ( mPreloadDistance , player . getRefData ( ) . getPosition ( ) . asVec3 ( ) ) ;
for ( CellStoreCollection : : const_iterator iter ( mActiveCells . begin ( ) ) ; iter ! = mActiveCells . end ( ) ; + + iter )
{
MWWorld : : CellStore * cellStore = * iter ;
cellStore - > forEachType < ESM : : NPC > ( listVisitor ) ;
cellStore - > forEachType < ESM : : Creature > ( listVisitor ) ;
}
for ( std : : vector < ESM : : Transport : : Dest > : : const_iterator it = listVisitor . mList . begin ( ) ; it ! = listVisitor . mList . end ( ) ; + + it )
{
if ( ! it - > mCellName . empty ( ) )
preloadCell ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getInterior ( it - > mCellName ) ) ;
else
{
2017-03-11 23:47:06 +00:00
osg : : Vec3f pos = it - > mPos . asVec3 ( ) ;
2016-02-09 00:51:23 +00:00
int x , y ;
2017-03-11 23:47:06 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > positionToIndex ( pos . x ( ) , pos . y ( ) , x , y ) ;
2016-02-09 00:51:23 +00:00
preloadCell ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( x , y ) , true ) ;
2017-03-11 23:47:06 +00:00
exteriorPositions . push_back ( pos ) ;
2016-02-07 15:37:56 +00:00
}
}
}
2011-07-31 15:07:11 +00:00
}