2010-06-16 12:13:21 +02:00
# include "engine.hpp"
2013-01-12 17:52:26 -04:00
2014-02-19 18:40:29 +01:00
# include <iomanip>
2020-06-25 21:46:07 +02:00
# include <chrono>
# include <thread>
2022-05-25 18:29:02 +00:00
# include <filesystem>
2010-06-16 12:13:21 +02:00
2015-05-13 15:03:21 +02:00
# include <boost/filesystem/fstream.hpp>
2015-04-12 15:34:50 +02:00
# include <osgViewer/ViewerEventHandlers>
2015-06-03 17:25:18 +02:00
# include <osgDB/WriteFile>
2015-04-12 15:34:50 +02:00
2013-11-16 10:31:46 +01:00
# include <SDL.h>
2018-08-14 23:05:43 +04:00
# include <components/debug/debuglog.hpp>
2018-10-26 15:18:38 +01:00
# include <components/debug/gldebug.hpp>
2018-08-14 23:05:43 +04:00
2015-04-22 17:58:55 +02:00
# include <components/misc/rng.hpp>
2015-03-15 14:07:47 +13:00
2015-04-12 15:34:50 +02:00
# include <components/vfs/manager.hpp>
# include <components/vfs/registerarchives.hpp>
2015-05-13 02:52:04 +02:00
# include <components/sdlutil/sdlgraphicswindow.hpp>
2015-05-13 15:03:21 +02:00
# include <components/sdlutil/imagetosurface.hpp>
2015-05-13 02:52:04 +02:00
2015-04-12 15:34:50 +02:00
# include <components/resource/resourcesystem.hpp>
2016-02-05 18:51:51 +01:00
# include <components/resource/scenemanager.hpp>
2017-02-22 02:18:18 +01:00
# include <components/resource/stats.hpp>
2015-04-12 15:34:50 +02:00
2013-08-07 13:16:20 -04:00
# include <components/compiler/extensions0.hpp>
2013-08-06 20:38:41 -04:00
2022-04-04 22:51:23 +02:00
# include <components/stereo/stereomanager.hpp>
# include <components/stereo/multiview.hpp>
2017-02-14 03:37:45 +01:00
# include <components/sceneutil/workqueue.hpp>
2012-01-21 01:14:35 +01:00
# include <components/files/configurationmanager.hpp>
2015-07-18 03:01:06 +02:00
# include <components/version/version.hpp>
2013-12-05 14:23:39 +01:00
2021-02-11 18:19:55 +01:00
# include <components/misc/frameratelimiter.hpp>
2021-05-24 18:47:23 +02:00
# include <components/sceneutil/screencapture.hpp>
2021-11-21 02:25:05 +00:00
# include <components/sceneutil/depth.hpp>
2022-04-04 22:51:23 +02:00
# include <components/sceneutil/color.hpp>
2021-12-15 22:17:38 +00:00
# include <components/sceneutil/util.hpp>
2022-07-24 20:55:03 +02:00
# include <components/sceneutil/unrefqueue.hpp>
2021-05-24 18:47:23 +02:00
2022-05-13 18:58:00 -07:00
# include <components/settings/shadermanager.hpp>
2015-05-03 17:24:35 +02:00
# include "mwinput/inputmanagerimp.hpp"
2010-07-03 15:41:20 +02:00
2012-08-12 18:11:09 +02:00
# include "mwgui/windowmanagerimp.hpp"
2011-10-09 13:12:44 +02:00
2020-12-18 23:21:10 +01:00
# include "mwlua/luamanagerimp.hpp"
2012-08-08 15:18:55 +02:00
# include "mwscript/scriptmanagerimp.hpp"
2012-11-10 14:31:58 +01:00
# include "mwscript/interpretercontext.hpp"
2010-07-02 09:00:06 +02:00
2012-08-09 14:33:21 +02:00
# include "mwsound/soundmanagerimp.hpp"
2010-07-03 15:17:02 +02:00
2010-08-03 22:06:48 +02:00
# include "mwworld/class.hpp"
2011-01-04 15:58:22 +01:00
# include "mwworld/player.hpp"
2012-07-03 12:30:50 +02:00
# include "mwworld/worldimp.hpp"
2010-08-03 13:17:31 +02:00
2020-04-20 18:47:14 +02:00
# include "mwrender/vismask.hpp"
2010-08-03 13:17:31 +02:00
# include "mwclass/classes.hpp"
2010-06-16 12:13:21 +02:00
2012-08-09 10:35:53 +02:00
# include "mwdialogue/dialoguemanagerimp.hpp"
2012-08-09 12:56:03 +02:00
# include "mwdialogue/journalimp.hpp"
2014-12-13 02:47:04 +01:00
# include "mwdialogue/scripttest.hpp"
2010-08-06 18:01:34 +02:00
2012-08-11 17:30:55 +02:00
# include "mwmechanics/mechanicsmanagerimp.hpp"
2010-07-26 11:15:38 +02:00
2013-11-16 10:31:46 +01:00
# include "mwstate/statemanagerimp.hpp"
2012-01-10 00:34:29 -05:00
2015-06-12 01:08:58 +02:00
namespace
{
void checkSDLError ( int ret )
{
if ( ret ! = 0 )
2018-08-14 23:05:43 +04:00
Log ( Debug : : Error ) < < " SDL error: " < < SDL_GetError ( ) ;
2015-06-12 01:08:58 +02:00
}
2020-06-28 01:44:56 +02:00
struct UserStats
{
const std : : string mLabel ;
const std : : string mBegin ;
const std : : string mEnd ;
const std : : string mTaken ;
UserStats ( const std : : string & label , const std : : string & prefix )
: mLabel ( label ) ,
mBegin ( prefix + " _time_begin " ) ,
mEnd ( prefix + " _time_end " ) ,
mTaken ( prefix + " _time_taken " )
{ }
} ;
enum class UserStatsType : std : : size_t
{
Input ,
Sound ,
State ,
Script ,
Mechanics ,
Physics ,
2020-11-20 13:11:53 +01:00
PhysicsWorker ,
2020-06-28 01:44:56 +02:00
World ,
Gui ,
2020-12-18 23:21:10 +01:00
Lua ,
2022-08-05 16:19:57 +00:00
LuaSyncUpdate ,
2020-06-28 01:44:56 +02:00
Number ,
} ;
template < UserStatsType type >
struct UserStatsValue
{
static const UserStats sValue ;
} ;
template < >
const UserStats UserStatsValue < UserStatsType : : Input > : : sValue { " Input " , " input " } ;
template < >
const UserStats UserStatsValue < UserStatsType : : Sound > : : sValue { " Sound " , " sound " } ;
template < >
const UserStats UserStatsValue < UserStatsType : : State > : : sValue { " State " , " state " } ;
template < >
const UserStats UserStatsValue < UserStatsType : : Script > : : sValue { " Script " , " script " } ;
template < >
const UserStats UserStatsValue < UserStatsType : : Mechanics > : : sValue { " Mech " , " mechanics " } ;
template < >
const UserStats UserStatsValue < UserStatsType : : Physics > : : sValue { " Phys " , " physics " } ;
2020-11-20 13:11:53 +01:00
template < >
const UserStats UserStatsValue < UserStatsType : : PhysicsWorker > : : sValue { " -Async " , " physicsworker " } ;
2020-06-28 01:44:56 +02:00
template < >
const UserStats UserStatsValue < UserStatsType : : World > : : sValue { " World " , " world " } ;
template < >
const UserStats UserStatsValue < UserStatsType : : Gui > : : sValue { " Gui " , " gui " } ;
2020-12-18 23:21:10 +01:00
template < >
const UserStats UserStatsValue < UserStatsType : : Lua > : : sValue { " Lua " , " lua " } ;
2022-08-05 16:19:57 +00:00
template < >
const UserStats UserStatsValue < UserStatsType : : LuaSyncUpdate > : : sValue { " -Sync " , " luasyncupdate " } ;
2020-06-28 01:44:56 +02:00
template < UserStatsType type >
struct ForEachUserStatsValue
{
template < class F >
static void apply ( F & & f )
{
f ( UserStatsValue < type > : : sValue ) ;
using Next = ForEachUserStatsValue < static_cast < UserStatsType > ( static_cast < std : : size_t > ( type ) + 1 ) > ;
Next : : apply ( std : : forward < F > ( f ) ) ;
}
} ;
template < >
struct ForEachUserStatsValue < UserStatsType : : Number >
{
template < class F >
static void apply ( F & & ) { }
} ;
template < class F >
void forEachUserStatsValue ( F & & f )
{
ForEachUserStatsValue < static_cast < UserStatsType > ( 0 ) > : : apply ( std : : forward < F > ( f ) ) ;
}
template < UserStatsType sType >
class ScopedProfile
{
public :
ScopedProfile ( osg : : Timer_t frameStart , unsigned int frameNumber , const osg : : Timer & timer , osg : : Stats & stats )
: mScopeStart ( timer . tick ( ) ) ,
mFrameStart ( frameStart ) ,
mFrameNumber ( frameNumber ) ,
mTimer ( timer ) ,
mStats ( stats )
{
}
ScopedProfile ( const ScopedProfile & ) = delete ;
ScopedProfile & operator = ( const ScopedProfile & ) = delete ;
~ ScopedProfile ( )
{
2021-01-27 08:04:33 +00:00
if ( ! mStats . collectStats ( " engine " ) )
return ;
2020-06-28 01:44:56 +02:00
const osg : : Timer_t end = mTimer . tick ( ) ;
const UserStats & stats = UserStatsValue < sType > : : sValue ;
mStats . setAttribute ( mFrameNumber , stats . mBegin , mTimer . delta_s ( mFrameStart , mScopeStart ) ) ;
mStats . setAttribute ( mFrameNumber , stats . mTaken , mTimer . delta_s ( mScopeStart , end ) ) ;
mStats . setAttribute ( mFrameNumber , stats . mEnd , mTimer . delta_s ( mFrameStart , end ) ) ;
}
private :
const osg : : Timer_t mScopeStart ;
const osg : : Timer_t mFrameStart ;
const unsigned int mFrameNumber ;
const osg : : Timer & mTimer ;
osg : : Stats & mStats ;
} ;
void initStatsHandler ( Resource : : Profiler & profiler )
{
const osg : : Vec4f textColor ( 1.f , 1.f , 1.f , 1.f ) ;
const osg : : Vec4f barColor ( 1.f , 1.f , 1.f , 1.f ) ;
const float multiplier = 1000 ;
const bool average = true ;
const bool averageInInverseSpace = false ;
const float maxValue = 10000 ;
forEachUserStatsValue ( [ & ] ( const UserStats & v )
{
profiler . addUserStatsLine ( v . mLabel , textColor , barColor , v . mTaken , multiplier ,
average , averageInInverseSpace , v . mBegin , v . mEnd , maxValue ) ;
} ) ;
2020-11-20 13:11:53 +01:00
// the forEachUserStatsValue loop is "run" at compile time, hence the settings manager is not available.
// Unconditionnally add the async physics stats, and then remove it at runtime if necessary
if ( Settings : : Manager : : getInt ( " async num threads " , " Physics " ) = = 0 )
profiler . removeUserStatsLine ( " -Async " ) ;
2020-06-28 01:44:56 +02:00
}
2021-05-25 01:49:27 +02:00
struct ScheduleNonDialogMessageBox
{
void operator ( ) ( std : : string message ) const
{
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > scheduleMessageBox ( std : : move ( message ) , MWGui : : ShowInDialogueMode_Never ) ;
}
} ;
2021-05-25 13:58:16 +02:00
struct IgnoreString
{
void operator ( ) ( std : : string ) const { }
} ;
2021-12-15 22:17:38 +00:00
class IdentifyOpenGLOperation : public osg : : GraphicsOperation
{
public :
IdentifyOpenGLOperation ( ) : GraphicsOperation ( " IdentifyOpenGLOperation " , false )
{ }
void operator ( ) ( osg : : GraphicsContext * graphicsContext ) override
{
Log ( Debug : : Info ) < < " OpenGL Vendor: " < < glGetString ( GL_VENDOR ) ;
Log ( Debug : : Info ) < < " OpenGL Renderer: " < < glGetString ( GL_RENDERER ) ;
Log ( Debug : : Info ) < < " OpenGL Version: " < < glGetString ( GL_VERSION ) ;
2022-06-06 22:40:38 +02:00
glGetIntegerv ( GL_MAX_TEXTURE_IMAGE_UNITS , & mMaxTextureImageUnits ) ;
2021-12-15 22:17:38 +00:00
}
2022-06-06 22:40:38 +02:00
int getMaxTextureImageUnits ( ) const
{
if ( mMaxTextureImageUnits = = 0 )
throw std : : logic_error ( " mMaxTextureImageUnits is not initialized " ) ;
return mMaxTextureImageUnits ;
}
private :
int mMaxTextureImageUnits = 0 ;
2021-12-15 22:17:38 +00:00
} ;
2022-04-04 22:51:23 +02:00
class InitializeStereoOperation final : public osg : : GraphicsOperation
{
public :
InitializeStereoOperation ( ) : GraphicsOperation ( " InitializeStereoOperation " , false )
{ }
void operator ( ) ( osg : : GraphicsContext * graphicsContext ) override
{
Stereo : : Manager : : instance ( ) . initializeStereo ( graphicsContext ) ;
}
} ;
2015-06-12 01:08:58 +02:00
}
2010-07-02 16:18:25 +02:00
void OMW : : Engine : : executeLocalScripts ( )
{
2022-05-06 17:46:50 +02:00
MWWorld : : LocalScripts & localScripts = mWorld - > getLocalScripts ( ) ;
2011-10-06 12:29:59 +02:00
localScripts . startIteration ( ) ;
2016-02-03 16:09:20 +01:00
std : : pair < std : : string , MWWorld : : Ptr > script ;
while ( localScripts . getNext ( script ) )
2010-07-02 16:18:25 +02:00
{
2012-04-23 15:27:03 +02:00
MWScript : : InterpreterContext interpreterContext (
2011-10-06 12:29:59 +02:00
& script . second . getRefData ( ) . getLocals ( ) , script . second ) ;
2022-05-06 17:46:50 +02:00
mScriptManager - > run ( script . first , interpreterContext ) ;
2010-07-02 16:18:25 +02:00
}
}
2010-07-01 11:49:00 -07:00
2017-11-16 17:56:44 +01:00
bool OMW : : Engine : : frame ( float frametime )
2010-07-02 17:30:26 +02:00
{
2011-10-06 12:34:13 +02:00
try
2011-02-18 17:46:24 +03:00
{
2020-06-28 01:44:56 +02:00
const osg : : Timer_t frameStart = mViewer - > getStartTick ( ) ;
const unsigned int frameNumber = mViewer - > getFrameStamp ( ) - > getFrameNumber ( ) ;
const osg : : Timer * const timer = osg : : Timer : : instance ( ) ;
osg : : Stats * const stats = mViewer - > getViewerStats ( ) ;
2011-10-08 10:15:03 +02:00
2017-11-16 17:56:44 +01:00
mEnvironment . setFrameDuration ( frametime ) ;
2012-04-05 21:16:51 +02:00
// update input
2020-06-28 01:44:56 +02:00
{
ScopedProfile < UserStatsType : : Input > profile ( frameStart , frameNumber , * timer , * stats ) ;
2022-05-06 17:46:50 +02:00
mInputManager - > update ( frametime , false ) ;
2020-06-28 01:44:56 +02:00
}
2012-04-05 21:16:51 +02:00
2015-09-04 03:44:14 +02:00
// When the window is minimized, pause the game. Currently this *has* to be here to work around a MyGUI bug.
// If we are not currently rendering, then RenderItems will not be reused resulting in a memory leak upon changing widget textures (fixed in MyGUI 3.3.2),
// and destroyed widgets will not be deleted (not fixed yet, https://github.com/MyGUI/mygui/issues/21)
2020-03-31 13:15:26 +04:00
{
2020-06-28 01:44:56 +02:00
ScopedProfile < UserStatsType : : Sound > profile ( frameStart , frameNumber , * timer , * stats ) ;
2014-09-03 04:54:07 +02:00
2022-05-06 17:46:50 +02:00
if ( ! mWindowManager - > isWindowVisible ( ) )
2020-06-28 01:44:56 +02:00
{
2022-05-06 17:46:50 +02:00
mSoundManager - > pausePlayback ( ) ;
2020-06-28 01:44:56 +02:00
return false ;
}
else
2022-05-06 17:46:50 +02:00
mSoundManager - > resumePlayback ( ) ;
2020-06-28 01:44:56 +02:00
// sound
if ( mUseSound )
2022-05-06 17:46:50 +02:00
mSoundManager - > update ( frametime ) ;
2020-06-28 01:44:56 +02:00
}
2010-10-31 12:23:03 -04:00
2014-06-15 00:09:12 +02:00
// Main menu opened? Then scripts are also paused.
2022-05-06 17:46:50 +02:00
bool paused = mWindowManager - > containsMode ( MWGui : : GM_MainMenu ) ;
2022-08-05 16:19:57 +00:00
{
ScopedProfile < UserStatsType : : LuaSyncUpdate > profile ( frameStart , frameNumber , * timer , * stats ) ;
// Should be called after input manager update and before any change to the game world.
// It applies to the game world queued changes from the previous frame.
mLuaManager - > synchronizedUpdate ( ) ;
}
2021-11-17 03:05:50 +01:00
2014-01-25 22:20:46 +01:00
// update game state
2020-06-28 01:44:56 +02:00
{
ScopedProfile < UserStatsType : : State > profile ( frameStart , frameNumber , * timer , * stats ) ;
2022-05-06 17:46:50 +02:00
mStateManager - > update ( frametime ) ;
2020-06-28 01:44:56 +02:00
}
2014-01-25 22:20:46 +01:00
2022-05-06 17:46:50 +02:00
bool guiActive = mWindowManager - > isGuiMode ( ) ;
2015-06-14 15:27:33 +02:00
2013-12-16 21:02:21 +02:00
{
2020-06-28 01:44:56 +02:00
ScopedProfile < UserStatsType : : Script > profile ( frameStart , frameNumber , * timer , * stats ) ;
2022-05-06 17:46:50 +02:00
if ( mStateManager - > getState ( ) ! = MWBase : : StateManager : : State_NoGame )
2014-06-15 00:09:12 +02:00
{
2020-06-28 01:44:56 +02:00
if ( ! paused )
2015-02-10 20:25:57 +01:00
{
2022-05-06 17:46:50 +02:00
if ( mWorld - > getScriptsEnabled ( ) )
2020-06-28 01:44:56 +02:00
{
// local scripts
executeLocalScripts ( ) ;
2010-07-22 12:46:24 +02:00
2020-06-28 01:44:56 +02:00
// global scripts
2022-05-06 17:46:50 +02:00
mScriptManager - > getGlobalScripts ( ) . run ( ) ;
2020-06-28 01:44:56 +02:00
}
2010-08-01 10:25:50 +02:00
2022-05-06 17:46:50 +02:00
mWorld - > markCellAsUnchanged ( ) ;
2020-06-28 01:44:56 +02:00
}
2016-10-13 14:38:35 +02:00
2020-06-28 01:44:56 +02:00
if ( ! guiActive )
{
2022-05-06 17:46:50 +02:00
double hours = ( frametime * mWorld - > getTimeScaleFactor ( ) ) / 3600.0 ;
mWorld - > advanceTime ( hours , true ) ;
mWorld - > rechargeItems ( frametime , true ) ;
2020-06-28 01:44:56 +02:00
}
2015-08-27 14:20:45 -05:00
}
2013-12-16 21:02:21 +02:00
}
2010-08-01 10:25:50 +02:00
2020-06-28 01:44:56 +02:00
// update mechanics
2014-05-16 00:58:12 +02:00
{
2020-06-28 01:44:56 +02:00
ScopedProfile < UserStatsType : : Mechanics > profile ( frameStart , frameNumber , * timer , * stats ) ;
2013-11-28 09:33:50 +01:00
2022-05-06 17:46:50 +02:00
if ( mStateManager - > getState ( ) ! = MWBase : : StateManager : : State_NoGame )
2020-06-28 01:44:56 +02:00
{
2022-05-06 17:46:50 +02:00
mMechanicsManager - > update ( frametime , guiActive ) ;
2020-06-28 01:44:56 +02:00
}
2022-05-06 17:46:50 +02:00
if ( mStateManager - > getState ( ) = = MWBase : : StateManager : : State_Running )
2020-06-28 01:44:56 +02:00
{
2022-05-06 17:46:50 +02:00
MWWorld : : Ptr player = mWorld - > getPlayerPtr ( ) ;
2020-06-28 01:44:56 +02:00
if ( ! guiActive & & player . getClass ( ) . getCreatureStats ( player ) . isDead ( ) )
2022-05-06 17:46:50 +02:00
mStateManager - > endGame ( ) ;
2020-06-28 01:44:56 +02:00
}
2013-11-16 17:46:48 +01:00
}
2010-07-22 12:29:23 +02:00
2019-01-07 14:27:31 +04:00
// update physics
{
2020-06-28 01:44:56 +02:00
ScopedProfile < UserStatsType : : Physics > profile ( frameStart , frameNumber , * timer , * stats ) ;
2022-05-06 17:46:50 +02:00
if ( mStateManager - > getState ( ) ! = MWBase : : StateManager : : State_NoGame )
2020-06-28 01:44:56 +02:00
{
2022-05-06 17:46:50 +02:00
mWorld - > updatePhysics ( frametime , guiActive , frameStart , frameNumber , * stats ) ;
2020-06-28 01:44:56 +02:00
}
2019-01-07 14:27:31 +04:00
}
2012-01-23 14:33:06 +01:00
// update world
2014-05-16 00:58:12 +02:00
{
2020-06-28 01:44:56 +02:00
ScopedProfile < UserStatsType : : World > profile ( frameStart , frameNumber , * timer , * stats ) ;
2022-05-06 17:46:50 +02:00
if ( mStateManager - > getState ( ) ! = MWBase : : StateManager : : State_NoGame )
2020-06-28 01:44:56 +02:00
{
2022-05-06 17:46:50 +02:00
mWorld - > update ( frametime , guiActive ) ;
2020-06-28 01:44:56 +02:00
}
2014-05-16 00:58:12 +02:00
}
2012-01-23 14:33:06 +01:00
2012-04-14 17:47:44 +02:00
// update GUI
2020-06-28 01:44:56 +02:00
{
ScopedProfile < UserStatsType : : Gui > profile ( frameStart , frameNumber , * timer , * stats ) ;
2022-05-06 17:46:50 +02:00
mWindowManager - > update ( frametime ) ;
2020-06-28 01:44:56 +02:00
}
2019-01-07 14:27:31 +04:00
2022-07-24 20:55:03 +02:00
const bool reportResource = stats - > collectStats ( " resource " ) ;
if ( reportResource )
stats - > setAttribute ( frameNumber , " UnrefQueue " , mUnrefQueue - > getSize ( ) ) ;
mUnrefQueue - > flush ( * mWorkQueue ) ;
if ( reportResource )
2017-02-22 02:18:18 +01:00
{
2020-05-22 00:11:23 +02:00
stats - > setAttribute ( frameNumber , " FrameNumber " , frameNumber ) ;
2017-02-22 02:18:18 +01:00
mResourceSystem - > reportStats ( frameNumber , stats ) ;
stats - > setAttribute ( frameNumber , " WorkQueue " , mWorkQueue - > getNumItems ( ) ) ;
stats - > setAttribute ( frameNumber , " WorkThread " , mWorkQueue - > getNumActiveThreads ( ) ) ;
2019-03-17 20:18:53 +03:00
2020-05-22 00:11:23 +02:00
mEnvironment . reportStats ( frameNumber , * stats ) ;
2017-02-22 02:18:18 +01:00
}
2010-09-18 08:39:21 +02:00
}
catch ( const std : : exception & e )
{
2018-08-14 23:05:43 +04:00
Log ( Debug : : Error ) < < " Error in frame: " < < e . what ( ) ;
2010-08-03 20:40:45 +02:00
}
2017-11-16 17:56:44 +01:00
return true ;
2010-07-02 17:30:26 +02:00
}
2012-01-21 01:14:35 +01:00
OMW : : Engine : : Engine ( Files : : ConfigurationManager & configurationManager )
2018-10-09 10:21:12 +04:00
: mWindow ( nullptr )
2015-05-13 02:52:04 +02:00
, mEncoding ( ToUTF8 : : WINDOWS_1252 )
2018-08-01 20:18:37 +04:00
, mScreenCaptureOperation ( nullptr )
2022-04-04 22:51:23 +02:00
, mSelectDepthFormatOperation ( new SceneUtil : : SelectDepthFormatOperation ( ) )
, mSelectColorFormatOperation ( new SceneUtil : : Color : : SelectColorFormatOperation ( ) )
, mStereoManager ( nullptr )
2013-11-16 11:33:20 +01:00
, mSkipMenu ( false )
2010-08-18 11:16:15 +02:00
, mUseSound ( true )
2010-10-06 14:52:53 +02:00
, mCompileAll ( false )
2014-12-13 02:47:04 +01:00
, mCompileAllDialogue ( false )
2014-02-02 14:09:59 +01:00
, mWarningsMode ( 1 )
2012-07-30 11:43:28 +02:00
, mScriptConsoleMode ( false )
2013-07-31 18:46:32 +02:00
, mActivationDistanceOverride ( - 1 )
2013-11-29 20:06:54 +01:00
, mGrab ( true )
2019-03-19 09:12:31 +04:00
, mRandomSeed ( 0 )
2015-04-25 13:37:42 -05:00
, mFSStrict ( false )
, mScriptBlacklistUse ( true )
2014-09-01 11:55:12 +02:00
, mNewGame ( false )
2015-05-23 22:44:00 +02:00
, mCfgMgr ( configurationManager )
2022-07-02 23:25:51 +04:00
, mGlMaxTextureImageUnits ( 0 )
2010-08-01 10:25:50 +02:00
{
2020-03-14 22:24:36 +04:00
SDL_SetHint ( SDL_HINT_ACCELEROMETER_AS_JOYSTICK , " 0 " ) ; // We use only gamepads
Uint32 flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE | SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK | SDL_INIT_SENSOR ;
2013-01-13 21:32:45 -04:00
if ( SDL_WasInit ( flags ) = = 0 )
{
2014-01-11 11:00:34 +01:00
SDL_SetMainReady ( ) ;
2013-01-13 21:32:45 -04:00
if ( SDL_Init ( flags ) ! = 0 )
2013-06-23 16:45:23 -07:00
{
throw std : : runtime_error ( " Could not initialize SDL! " + std : : string ( SDL_GetError ( ) ) ) ;
}
2013-01-13 21:32:45 -04:00
}
2010-06-27 16:44:15 -07:00
}
2010-06-16 12:13:21 +02:00
2010-07-02 13:12:05 +02:00
OMW : : Engine : : ~ Engine ( )
{
2021-07-11 14:43:52 +02:00
if ( mScreenCaptureOperation ! = nullptr )
mScreenCaptureOperation - > stop ( ) ;
2021-05-25 13:44:40 +02:00
2022-05-06 17:46:50 +02:00
mMechanicsManager = nullptr ;
mDialogueManager = nullptr ;
mJournal = nullptr ;
mScriptManager = nullptr ;
mWindowManager = nullptr ;
mWorld = nullptr ;
2022-05-21 17:00:02 +02:00
mStereoManager = nullptr ;
2022-05-06 17:46:50 +02:00
mSoundManager = nullptr ;
mInputManager = nullptr ;
mStateManager = nullptr ;
mLuaManager = nullptr ;
2018-10-09 10:21:12 +04:00
mScriptContext = nullptr ;
2015-05-13 03:36:20 +02:00
2022-07-24 20:55:03 +02:00
mUnrefQueue = nullptr ;
2018-10-09 10:21:12 +04:00
mWorkQueue = nullptr ;
2017-02-14 03:37:45 +01:00
2018-10-09 10:21:12 +04:00
mViewer = nullptr ;
2015-05-13 02:52:04 +02:00
2019-05-06 17:07:22 +04:00
mResourceSystem . reset ( ) ;
2019-02-17 12:07:14 +04:00
mEncoder = nullptr ;
2015-05-15 19:34:18 +02:00
if ( mWindow )
{
SDL_DestroyWindow ( mWindow ) ;
2018-10-09 10:21:12 +04:00
mWindow = nullptr ;
2015-05-15 19:34:18 +02:00
}
2015-05-13 02:52:04 +02:00
2013-01-13 21:32:45 -04:00
SDL_Quit ( ) ;
2010-07-02 13:12:05 +02:00
}
2011-08-19 21:06:09 +02:00
void OMW : : Engine : : enableFSStrict ( bool fsStrict )
2011-05-05 19:56:16 +02:00
{
2011-08-19 21:06:09 +02:00
mFSStrict = fsStrict ;
2011-05-05 19:56:16 +02:00
}
2010-06-16 12:13:21 +02:00
// Set data dir
2011-09-02 22:45:21 +02:00
void OMW : : Engine : : setDataDirs ( const Files : : PathContainer & dataDirs )
2010-06-16 12:13:21 +02:00
{
2012-01-29 20:27:03 +01:00
mDataDirs = dataDirs ;
2019-06-01 15:57:26 +04:00
mDataDirs . insert ( mDataDirs . begin ( ) , ( mResDir / " vfs " ) ) ;
mFileCollections = Files : : Collections ( mDataDirs , ! mFSStrict ) ;
2010-06-16 12:13:21 +02:00
}
2013-03-09 21:08:08 +01:00
// Add BSA archive
void OMW : : Engine : : addArchive ( const std : : string & archive ) {
mArchives . push_back ( archive ) ;
}
2011-01-04 01:34:55 +01:00
// Set resource dir
void OMW : : Engine : : setResourceDir ( const boost : : filesystem : : path & parResDir )
{
2014-05-21 15:39:58 +04:00
mResDir = parResDir ;
2011-01-04 01:34:55 +01:00
}
2017-08-06 15:03:48 +02:00
// Set start cell name
2010-06-16 12:13:21 +02:00
void OMW : : Engine : : setCell ( const std : : string & cellName )
{
mCellName = cellName ;
}
2013-09-29 09:11:57 +02:00
void OMW : : Engine : : addContentFile ( const std : : string & file )
2010-06-16 12:13:21 +02:00
{
2014-01-27 13:27:42 +01:00
mContentFiles . push_back ( file ) ;
2010-06-16 12:13:21 +02:00
}
2020-01-12 11:42:47 +04:00
void OMW : : Engine : : addGroundcoverFile ( const std : : string & file )
{
mGroundcoverFiles . emplace_back ( file ) ;
}
2014-09-01 11:55:12 +02:00
void OMW : : Engine : : setSkipMenu ( bool skipMenu , bool newGame )
2010-07-04 16:00:32 +02:00
{
2013-11-16 11:33:20 +01:00
mSkipMenu = skipMenu ;
2014-09-01 11:55:12 +02:00
mNewGame = newGame ;
2010-07-04 16:00:32 +02:00
}
2022-05-22 02:47:58 +02:00
void OMW : : Engine : : createWindow ( )
2013-01-08 09:45:01 -08:00
{
2022-05-22 02:47:58 +02:00
int screen = Settings : : Manager : : getInt ( " screen " , " Video " ) ;
int width = Settings : : Manager : : getInt ( " resolution x " , " Video " ) ;
int height = Settings : : Manager : : getInt ( " resolution y " , " Video " ) ;
2022-05-03 22:50:31 -07:00
Settings : : WindowMode windowMode = static_cast < Settings : : WindowMode > ( Settings : : Manager : : getInt ( " window mode " , " Video " ) ) ;
2022-05-22 02:47:58 +02:00
bool windowBorder = Settings : : Manager : : getBool ( " window border " , " Video " ) ;
bool vsync = Settings : : Manager : : getBool ( " vsync " , " Video " ) ;
unsigned int antialiasing = std : : max ( 0 , Settings : : Manager : : getInt ( " antialiasing " , " Video " ) ) ;
2015-05-13 02:52:04 +02:00
int pos_x = SDL_WINDOWPOS_CENTERED_DISPLAY ( screen ) ,
pos_y = SDL_WINDOWPOS_CENTERED_DISPLAY ( screen ) ;
2022-05-08 22:56:35 -07:00
if ( windowMode = = Settings : : WindowMode : : Fullscreen | | windowMode = = Settings : : WindowMode : : WindowedFullscreen )
2015-05-13 02:52:04 +02:00
{
pos_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY ( screen ) ;
pos_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY ( screen ) ;
}
2013-11-16 10:31:46 +01:00
2015-05-13 02:52:04 +02:00
Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE ;
2022-05-03 22:50:31 -07:00
if ( windowMode = = Settings : : WindowMode : : Fullscreen )
2015-05-13 02:52:04 +02:00
flags | = SDL_WINDOW_FULLSCREEN ;
2022-05-08 22:56:35 -07:00
else if ( windowMode = = Settings : : WindowMode : : WindowedFullscreen )
2022-05-03 22:50:31 -07:00
flags | = SDL_WINDOW_FULLSCREEN_DESKTOP ;
2015-05-13 02:52:04 +02:00
2021-11-07 20:01:07 -08:00
// Allows for Windows snapping features to properly work in borderless window
SDL_SetHint ( " SDL_BORDERLESS_WINDOWED_STYLE " , " 1 " ) ;
SDL_SetHint ( " SDL_BORDERLESS_RESIZABLE_STYLE " , " 1 " ) ;
2015-05-13 02:52:04 +02:00
if ( ! windowBorder )
flags | = SDL_WINDOW_BORDERLESS ;
2013-01-13 21:32:45 -04:00
2014-03-27 04:15:47 +01:00
SDL_SetHint ( SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS ,
2022-05-22 02:47:58 +02:00
Settings : : Manager : : getBool ( " minimize on focus loss " , " Video " ) ? " 1 " : " 0 " ) ;
2014-03-27 04:15:47 +01:00
2015-06-12 01:08:58 +02:00
checkSDLError ( SDL_GL_SetAttribute ( SDL_GL_RED_SIZE , 8 ) ) ;
checkSDLError ( SDL_GL_SetAttribute ( SDL_GL_GREEN_SIZE , 8 ) ) ;
checkSDLError ( SDL_GL_SetAttribute ( SDL_GL_BLUE_SIZE , 8 ) ) ;
checkSDLError ( SDL_GL_SetAttribute ( SDL_GL_ALPHA_SIZE , 0 ) ) ;
checkSDLError ( SDL_GL_SetAttribute ( SDL_GL_DEPTH_SIZE , 24 ) ) ;
2020-09-19 23:30:34 +01:00
if ( Debug : : shouldDebugOpenGL ( ) )
checkSDLError ( SDL_GL_SetAttribute ( SDL_GL_CONTEXT_FLAGS , SDL_GL_CONTEXT_DEBUG_FLAG ) ) ;
2015-06-12 00:12:12 +02:00
2015-05-13 02:52:04 +02:00
if ( antialiasing > 0 )
{
2015-06-12 01:08:58 +02:00
checkSDLError ( SDL_GL_SetAttribute ( SDL_GL_MULTISAMPLEBUFFERS , 1 ) ) ;
checkSDLError ( SDL_GL_SetAttribute ( SDL_GL_MULTISAMPLESAMPLES , antialiasing ) ) ;
2015-05-13 02:52:04 +02:00
}
2020-09-20 12:22:31 +00:00
osg : : ref_ptr < SDLUtil : : GraphicsWindowSDL2 > graphicsWindow ;
while ( ! graphicsWindow | | ! graphicsWindow - > valid ( ) )
2015-05-13 02:52:04 +02:00
{
2020-09-20 12:22:31 +00:00
while ( ! mWindow )
2015-06-05 02:53:10 +02:00
{
2020-09-20 12:22:31 +00:00
mWindow = SDL_CreateWindow ( " OpenMW " , pos_x , pos_y , width , height , flags ) ;
if ( ! mWindow )
2015-06-05 02:53:10 +02:00
{
2020-09-20 12:22:31 +00:00
// Try with a lower AA
if ( antialiasing > 0 )
{
Log ( Debug : : Warning ) < < " Warning: " < < antialiasing < < " x antialiasing not supported, trying " < < antialiasing / 2 ;
antialiasing / = 2 ;
Settings : : Manager : : setInt ( " antialiasing " , " Video " , antialiasing ) ;
checkSDLError ( SDL_GL_SetAttribute ( SDL_GL_MULTISAMPLESAMPLES , antialiasing ) ) ;
continue ;
}
else
{
std : : stringstream error ;
error < < " Failed to create SDL window: " < < SDL_GetError ( ) ;
throw std : : runtime_error ( error . str ( ) ) ;
}
2015-06-05 02:53:10 +02:00
}
}
2015-05-13 02:52:04 +02:00
2020-09-20 12:22:31 +00:00
setWindowIcon ( ) ;
osg : : ref_ptr < osg : : GraphicsContext : : Traits > traits = new osg : : GraphicsContext : : Traits ;
SDL_GetWindowPosition ( mWindow , & traits - > x , & traits - > y ) ;
SDL_GetWindowSize ( mWindow , & traits - > width , & traits - > height ) ;
traits - > windowName = SDL_GetWindowTitle ( mWindow ) ;
traits - > windowDecoration = ! ( SDL_GetWindowFlags ( mWindow ) & SDL_WINDOW_BORDERLESS ) ;
traits - > screenNum = SDL_GetWindowDisplayIndex ( mWindow ) ;
traits - > vsync = vsync ;
traits - > inheritedWindowData = new SDLUtil : : GraphicsWindowSDL2 : : WindowData ( mWindow ) ;
graphicsWindow = new SDLUtil : : GraphicsWindowSDL2 ( traits ) ;
if ( ! graphicsWindow - > valid ( ) ) throw std : : runtime_error ( " Failed to create GraphicsContext " ) ;
if ( traits - > samples < antialiasing )
{
Log ( Debug : : Warning ) < < " Warning: Framebuffer MSAA level is only " < < traits - > samples < < " x instead of " < < antialiasing < < " x. Trying " < < antialiasing / 2 < < " x instead. " ;
graphicsWindow - > closeImplementation ( ) ;
SDL_DestroyWindow ( mWindow ) ;
mWindow = nullptr ;
antialiasing / = 2 ;
Settings : : Manager : : setInt ( " antialiasing " , " Video " , antialiasing ) ;
checkSDLError ( SDL_GL_SetAttribute ( SDL_GL_MULTISAMPLESAMPLES , antialiasing ) ) ;
continue ;
}
if ( traits - > red < 8 )
Log ( Debug : : Warning ) < < " Warning: Framebuffer only has a " < < traits - > red < < " bit red channel. " ;
if ( traits - > green < 8 )
Log ( Debug : : Warning ) < < " Warning: Framebuffer only has a " < < traits - > green < < " bit green channel. " ;
if ( traits - > blue < 8 )
Log ( Debug : : Warning ) < < " Warning: Framebuffer only has a " < < traits - > blue < < " bit blue channel. " ;
2021-01-09 14:44:15 +00:00
if ( traits - > depth < 24 )
Log ( Debug : : Warning ) < < " Warning: Framebuffer only has " < < traits - > depth < < " bits of depth precision. " ;
2020-09-20 12:22:31 +00:00
traits - > alpha = 0 ; // set to 0 to stop ScreenCaptureHandler reading the alpha channel
}
2015-05-13 02:52:04 +02:00
osg : : ref_ptr < osg : : Camera > camera = mViewer - > getCamera ( ) ;
2015-05-13 15:08:47 +02:00
camera - > setGraphicsContext ( graphicsWindow ) ;
2020-09-20 12:22:31 +00:00
camera - > setViewport ( 0 , 0 , graphicsWindow - > getTraits ( ) - > width , graphicsWindow - > getTraits ( ) - > height ) ;
2015-05-13 02:52:04 +02:00
2021-12-15 22:17:38 +00:00
osg : : ref_ptr < SceneUtil : : OperationSequence > realizeOperations = new SceneUtil : : OperationSequence ( false ) ;
mViewer - > setRealizeOperation ( realizeOperations ) ;
2022-06-06 22:40:38 +02:00
osg : : ref_ptr < IdentifyOpenGLOperation > identifyOp = new IdentifyOpenGLOperation ( ) ;
realizeOperations - > add ( identifyOp ) ;
2021-12-15 22:17:38 +00:00
2020-09-19 23:30:34 +01:00
if ( Debug : : shouldDebugOpenGL ( ) )
2021-12-15 22:17:38 +00:00
realizeOperations - > add ( new Debug : : EnableGLDebugOperation ( ) ) ;
2018-10-25 00:07:01 +01:00
2022-04-04 22:51:23 +02:00
realizeOperations - > add ( mSelectDepthFormatOperation ) ;
realizeOperations - > add ( mSelectColorFormatOperation ) ;
if ( Stereo : : getStereo ( ) )
{
realizeOperations - > add ( new InitializeStereoOperation ( ) ) ;
Stereo : : setVertexBufferHint ( ) ;
}
2015-05-13 02:52:04 +02:00
mViewer - > realize ( ) ;
2022-06-06 22:40:38 +02:00
mGlMaxTextureImageUnits = identifyOp - > getMaxTextureImageUnits ( ) ;
2017-02-22 01:49:54 +01:00
2020-09-20 12:22:31 +00:00
mViewer - > getEventQueue ( ) - > getCurrentEventState ( ) - > setWindowRectangle ( 0 , 0 , graphicsWindow - > getTraits ( ) - > width , graphicsWindow - > getTraits ( ) - > height ) ;
2015-05-13 02:52:04 +02:00
}
2015-05-13 15:03:21 +02:00
void OMW : : Engine : : setWindowIcon ( )
{
2022-05-25 18:29:02 +00:00
std : : ifstream windowIconStream ;
2022-07-09 20:42:18 +04:00
std : : string windowIcon = ( mResDir / " openmw.png " ) . string ( ) ;
2015-07-17 21:41:53 -05:00
windowIconStream . open ( windowIcon , std : : ios_base : : in | std : : ios_base : : binary ) ;
2015-05-13 15:03:21 +02:00
if ( windowIconStream . fail ( ) )
2018-08-14 23:05:43 +04:00
Log ( Debug : : Error ) < < " Error: Failed to open " < < windowIcon ;
2015-05-13 15:03:21 +02:00
osgDB : : ReaderWriter * reader = osgDB : : Registry : : instance ( ) - > getReaderWriterForExtension ( " png " ) ;
2015-06-05 02:57:31 +02:00
if ( ! reader )
{
2018-08-14 23:05:43 +04:00
Log ( Debug : : Error ) < < " Error: Failed to read window icon, no png readerwriter found " ;
2015-06-05 02:57:31 +02:00
return ;
}
2015-05-13 15:03:21 +02:00
osgDB : : ReaderWriter : : ReadResult result = reader - > readImage ( windowIconStream ) ;
if ( ! result . success ( ) )
2018-08-14 23:05:43 +04:00
Log ( Debug : : Error ) < < " Error: Failed to read " < < windowIcon < < " : " < < result . message ( ) < < " code " < < result . status ( ) ;
2015-05-13 15:03:21 +02:00
else
{
osg : : ref_ptr < osg : : Image > image = result . getImage ( ) ;
2018-06-16 12:12:32 +02:00
auto surface = SDLUtil : : imageToSurface ( image , true ) ;
SDL_SetWindowIcon ( mWindow , surface . get ( ) ) ;
2015-05-13 15:03:21 +02:00
}
}
2022-05-22 02:47:58 +02:00
void OMW : : Engine : : prepareEngine ( )
2015-05-13 02:52:04 +02:00
{
2022-05-06 17:46:50 +02:00
mStateManager = std : : make_unique < MWState : : StateManager > ( mCfgMgr . getUserDataPath ( ) / " saves " , mContentFiles ) ;
mEnvironment . setStateManager ( * mStateManager ) ;
2015-05-13 02:52:04 +02:00
2022-04-04 22:51:23 +02:00
mStereoManager = std : : make_unique < Stereo : : Manager > ( mViewer ) ;
2015-05-13 02:52:04 +02:00
2022-04-04 22:51:23 +02:00
osg : : ref_ptr < osg : : Group > rootNode ( new osg : : Group ) ;
2015-04-24 23:30:30 +02:00
mViewer - > setSceneData ( rootNode ) ;
2015-04-12 15:34:50 +02:00
2022-05-22 02:47:58 +02:00
createWindow ( ) ;
2022-04-04 22:51:23 +02:00
2022-01-29 23:21:39 +02:00
mVFS = std : : make_unique < VFS : : Manager > ( mFSStrict ) ;
2015-04-12 15:34:50 +02:00
VFS : : registerArchives ( mVFS . get ( ) , mFileCollections , mArchives , true ) ;
2022-01-29 23:21:39 +02:00
mResourceSystem = std : : make_unique < Resource : : ResourceSystem > ( mVFS . get ( ) ) ;
2022-06-06 22:40:38 +02:00
mResourceSystem - > getSceneManager ( ) - > getShaderManager ( ) . setMaxTextureUnits ( mGlMaxTextureImageUnits ) ;
2016-02-05 23:21:54 +01:00
mResourceSystem - > getSceneManager ( ) - > setUnRefImageDataAfterApply ( false ) ; // keep to Off for now to allow better state sharing
2016-02-05 18:51:51 +01:00
mResourceSystem - > getSceneManager ( ) - > setFilterSettings (
2015-12-13 17:05:19 -08:00
Settings : : Manager : : getString ( " texture mag filter " , " General " ) ,
Settings : : Manager : : getString ( " texture min filter " , " General " ) ,
2015-12-13 16:51:27 -08:00
Settings : : Manager : : getString ( " texture mipmap " , " General " ) ,
2016-02-14 23:14:52 +01:00
Settings : : Manager : : getInt ( " anisotropy " , " General " )
2015-12-13 16:51:27 -08:00
) ;
2022-05-06 17:46:50 +02:00
mEnvironment . setResourceSystem ( * mResourceSystem ) ;
2013-08-27 15:48:13 +02:00
2017-02-14 03:37:45 +01:00
int numThreads = Settings : : Manager : : getInt ( " preload num threads " , " Cells " ) ;
if ( numThreads < = 0 )
throw std : : runtime_error ( " Invalid setting: 'preload num threads' must be >0 " ) ;
mWorkQueue = new SceneUtil : : WorkQueue ( numThreads ) ;
2022-07-24 20:55:03 +02:00
mUnrefQueue = std : : make_unique < SceneUtil : : UnrefQueue > ( ) ;
2017-02-14 03:37:45 +01:00
2021-05-24 19:27:09 +02:00
mScreenCaptureOperation = new SceneUtil : : AsyncScreenCaptureOperation (
mWorkQueue ,
new SceneUtil : : WriteScreenshotToFileOperation (
mCfgMgr . getScreenshotPath ( ) . string ( ) ,
2021-05-25 01:49:27 +02:00
Settings : : Manager : : getString ( " screenshot format " , " General " ) ,
2021-05-25 13:58:16 +02:00
Settings : : Manager : : getBool ( " notify on saved screenshot " , " General " )
2021-07-11 13:22:26 +02:00
? std : : function < void ( std : : string ) > ( ScheduleNonDialogMessageBox { } )
: std : : function < void ( std : : string ) > ( IgnoreString { } )
2021-05-24 19:27:09 +02:00
)
) ;
mScreenCaptureHandler = new osgViewer : : ScreenCaptureHandler ( mScreenCaptureOperation ) ;
mViewer - > addEventHandler ( mScreenCaptureHandler ) ;
2022-05-06 17:46:50 +02:00
mLuaManager = std : : make_unique < MWLua : : LuaManager > ( mVFS . get ( ) , ( mResDir / " lua_libs " ) . string ( ) ) ;
mEnvironment . setLuaManager ( * mLuaManager ) ;
2020-12-18 23:21:10 +01:00
2013-08-27 15:48:13 +02:00
// Create input and UI first to set up a bootstrapping environment for
// showing a loading screen and keeping the window responsive while doing so
2015-01-24 16:03:55 -06:00
std : : string keybinderUser = ( mCfgMgr . getUserConfigPath ( ) / " input_v3.xml " ) . string ( ) ;
2022-05-25 18:29:02 +00:00
bool keybinderUserExists = std : : filesystem : : exists ( keybinderUser ) ;
2015-01-24 16:44:17 -06:00
if ( ! keybinderUserExists )
{
2015-01-26 12:50:44 -06:00
std : : string input2 = ( mCfgMgr . getUserConfigPath ( ) / " input_v2.xml " ) . string ( ) ;
2022-05-25 18:29:02 +00:00
if ( std : : filesystem : : exists ( input2 ) ) {
std : : filesystem : : copy_file ( input2 , keybinderUser ) ;
keybinderUserExists = std : : filesystem : : exists ( keybinderUser ) ;
2019-10-30 15:22:24 +04:00
Log ( Debug : : Info ) < < " Loading keybindings file: " < < keybinderUser ;
2015-01-26 12:50:44 -06:00
}
2015-01-24 16:44:17 -06:00
}
2019-10-30 15:22:24 +04:00
else
Log ( Debug : : Info ) < < " Loading keybindings file: " < < keybinderUser ;
2015-01-19 18:55:17 -06:00
2020-03-14 22:24:36 +04:00
const std : : string userdefault = mCfgMgr . getUserConfigPath ( ) . string ( ) + " /gamecontrollerdb.txt " ;
const std : : string localdefault = mCfgMgr . getLocalPath ( ) . string ( ) + " /gamecontrollerdb.txt " ;
const std : : string globaldefault = mCfgMgr . getGlobalPath ( ) . string ( ) + " /gamecontrollerdb.txt " ;
2019-08-03 19:55:58 +00:00
std : : string userGameControllerdb ;
2022-05-25 18:29:02 +00:00
if ( std : : filesystem : : exists ( userdefault ) )
2019-08-03 19:55:58 +00:00
userGameControllerdb = userdefault ;
2015-01-19 18:55:17 -06:00
std : : string gameControllerdb ;
2022-05-25 18:29:02 +00:00
if ( std : : filesystem : : exists ( localdefault ) )
2015-01-19 18:55:17 -06:00
gameControllerdb = localdefault ;
2022-05-25 18:29:02 +00:00
else if ( std : : filesystem : : exists ( globaldefault ) )
2015-01-19 18:55:17 -06:00
gameControllerdb = globaldefault ;
2022-05-04 22:33:39 +02:00
//else if it doesn't exist, pass in an empty string
2015-01-19 18:55:17 -06:00
2021-07-22 15:55:30 -07:00
// gui needs our shaders path before everything else
mResourceSystem - > getSceneManager ( ) - > setShaderPath ( ( mResDir / " shaders " ) . string ( ) ) ;
osg : : ref_ptr < osg : : GLExtensions > exts = osg : : GLExtensions : : Get ( 0 , false ) ;
bool shadersSupported = exts & & ( exts - > glslLanguageVersion > = 1.2f ) ;
2021-11-06 04:38:43 -07:00
# if OSG_VERSION_LESS_THAN(3, 6, 6)
// hack fix for https://github.com/openscenegraph/OpenSceneGraph/issues/1028
if ( exts )
exts - > glRenderbufferStorageMultisampleCoverageNV = nullptr ;
# endif
2015-04-24 21:55:30 +02:00
osg : : ref_ptr < osg : : Group > guiRoot = new osg : : Group ;
2017-02-02 21:46:25 +01:00
guiRoot - > setName ( " GUI Root " ) ;
2020-04-20 18:47:14 +02:00
guiRoot - > setNodeMask ( MWRender : : Mask_GUI ) ;
2022-04-04 22:51:23 +02:00
mStereoManager - > disableStereoForNode ( guiRoot ) ;
2015-04-24 21:55:30 +02:00
rootNode - > addChild ( guiRoot ) ;
2022-01-29 23:21:39 +02:00
2022-05-06 17:46:50 +02:00
mWindowManager = std : : make_unique < MWGui : : WindowManager > ( mWindow , mViewer , guiRoot , mResourceSystem . get ( ) , mWorkQueue . get ( ) ,
2022-07-09 20:42:18 +04:00
mCfgMgr . getLogPath ( ) . string ( ) + std : : string ( " / " ) ,
2022-07-18 10:40:03 +04:00
mScriptConsoleMode , mTranslationDataStorage , mEncoding ,
2022-07-09 19:58:40 +04:00
Version : : getOpenmwVersionDescription ( mResDir . string ( ) ) , shadersSupported ) ;
2022-05-06 17:46:50 +02:00
mEnvironment . setWindowManager ( * mWindowManager ) ;
2013-08-27 15:48:13 +02:00
2022-05-06 17:46:50 +02:00
mInputManager = std : : make_unique < MWInput : : InputManager > ( mWindow , mViewer , mScreenCaptureHandler ,
mScreenCaptureOperation , keybinderUser , keybinderUserExists , userGameControllerdb , gameControllerdb , mGrab ) ;
mEnvironment . setInputManager ( * mInputManager ) ;
2020-04-16 17:31:20 +04:00
2014-03-27 04:15:47 +01:00
// Create sound system
2022-05-06 17:46:50 +02:00
mSoundManager = std : : make_unique < MWSound : : SoundManager > ( mVFS . get ( ) , mUseSound ) ;
mEnvironment . setSoundManager ( * mSoundManager ) ;
2014-03-27 04:15:47 +01:00
2014-03-27 19:59:33 +01:00
if ( ! mSkipMenu )
{
2019-01-22 10:08:48 +04:00
const std : : string & logo = Fallback : : Map : : getString ( " Movies_Company_Logo " ) ;
2014-03-27 19:59:33 +01:00
if ( ! logo . empty ( ) )
2022-05-06 17:46:50 +02:00
mWindowManager - > playVideo ( logo , true ) ;
2014-03-27 19:59:33 +01:00
}
2014-03-27 04:15:47 +01:00
2010-07-02 09:00:06 +02:00
// Create the world
2022-07-24 20:55:03 +02:00
mWorld = std : : make_unique < MWWorld : : World > ( mViewer , rootNode , mResourceSystem . get ( ) , mWorkQueue . get ( ) , * mUnrefQueue ,
2022-05-22 01:47:06 +02:00
mFileCollections , mContentFiles , mGroundcoverFiles , mEncoder . get ( ) , mActivationDistanceOverride , mCellName ,
2022-05-06 17:46:50 +02:00
mStartupScript , mResDir . string ( ) , mCfgMgr . getUserDataPath ( ) . string ( ) ) ;
mWorld - > setupPlayer ( ) ;
2022-05-11 16:37:16 +03:00
mWorld - > setRandomSeed ( mRandomSeed ) ;
2022-05-06 17:46:50 +02:00
mEnvironment . setWorld ( * mWorld ) ;
2013-08-27 15:48:13 +02:00
2022-05-06 17:46:50 +02:00
mWindowManager - > setStore ( mWorld - > getStore ( ) ) ;
2022-07-04 21:45:44 +04:00
mLuaManager - > initL10n ( ) ;
2022-05-06 17:46:50 +02:00
mWindowManager - > initUI ( ) ;
2011-02-27 00:50:08 +01:00
2012-12-23 23:23:24 +04:00
//Load translation data
2022-05-22 01:47:06 +02:00
mTranslationDataStorage . setEncoder ( mEncoder . get ( ) ) ;
2013-09-29 09:11:57 +02:00
for ( size_t i = 0 ; i < mContentFiles . size ( ) ; i + + )
mTranslationDataStorage . loadTranslationData ( mFileCollections , mContentFiles [ i ] ) ;
2012-12-23 23:23:24 +04:00
2013-11-16 10:31:46 +01:00
Compiler : : registerExtensions ( mExtensions ) ;
2010-07-07 18:48:06 +02:00
2010-07-26 11:15:38 +02:00
// Create script system
2022-05-22 01:47:06 +02:00
mScriptContext = std : : make_unique < MWScript : : CompilerContext > ( MWScript : : CompilerContext : : Type_Full ) ;
2010-07-03 12:12:13 +02:00
mScriptContext - > setExtensions ( & mExtensions ) ;
2010-07-02 17:21:27 +02:00
2022-05-06 17:46:50 +02:00
mScriptManager = std : : make_unique < MWScript : : ScriptManager > ( mWorld - > getStore ( ) , * mScriptContext , mWarningsMode ,
mScriptBlacklistUse ? mScriptBlacklist : std : : vector < std : : string > ( ) ) ;
mEnvironment . setScriptManager ( * mScriptManager ) ;
2010-08-01 10:25:50 +02:00
2010-07-26 11:15:38 +02:00
// Create game mechanics system
2022-05-06 17:46:50 +02:00
mMechanicsManager = std : : make_unique < MWMechanics : : MechanicsManager > ( ) ;
mEnvironment . setMechanicsManager ( * mMechanicsManager ) ;
2010-07-02 17:30:26 +02:00
2010-08-06 18:01:34 +02:00
// Create dialog system
2022-05-06 17:46:50 +02:00
mJournal = std : : make_unique < MWDialogue : : Journal > ( ) ;
mEnvironment . setJournal ( * mJournal ) ;
mDialogueManager = std : : make_unique < MWDialogue : : DialogueManager > ( mExtensions , mTranslationDataStorage ) ;
mEnvironment . setDialogueManager ( * mDialogueManager ) ;
2010-08-06 18:01:34 +02:00
2010-10-06 14:52:53 +02:00
// scripts
if ( mCompileAll )
{
2022-05-06 17:46:50 +02:00
std : : pair < int , int > result = mScriptManager - > compileAll ( ) ;
2011-10-09 12:05:13 +02:00
if ( result . first )
2018-08-14 23:05:43 +04:00
Log ( Debug : : Info )
2011-10-09 12:05:13 +02:00
< < " compiled " < < result . second < < " of " < < result . first < < " scripts ( "
< < 100 * static_cast < double > ( result . second ) / result . first
2018-08-14 23:05:43 +04:00
< < " %) " ;
2010-10-06 14:52:53 +02:00
}
2014-12-13 02:47:04 +01:00
if ( mCompileAllDialogue )
{
2014-12-18 10:20:15 +01:00
std : : pair < int , int > result = MWDialogue : : ScriptTest : : compileAll ( & mExtensions , mWarningsMode ) ;
2014-12-13 02:47:04 +01:00
if ( result . first )
2018-08-14 23:05:43 +04:00
Log ( Debug : : Info )
2014-12-13 02:47:04 +01:00
< < " compiled " < < result . second < < " of " < < result . first < < " dialogue script/actor combinations a( "
< < 100 * static_cast < double > ( result . second ) / result . first
2018-08-14 23:05:43 +04:00
< < " %) " ;
2014-12-13 02:47:04 +01:00
}
2020-12-18 23:21:10 +01:00
mLuaManager - > init ( ) ;
2021-12-14 00:39:01 +01:00
mLuaManager - > loadPermanentStorage ( mCfgMgr . getUserConfigPath ( ) . string ( ) ) ;
2013-01-08 09:45:01 -08:00
}
2021-04-18 16:50:37 +02:00
class OMW : : Engine : : LuaWorker
{
public :
2021-04-23 02:49:12 +02:00
explicit LuaWorker ( Engine * engine ) : mEngine ( engine )
2021-04-18 16:50:37 +02:00
{
2021-04-23 02:49:12 +02:00
if ( Settings : : Manager : : getInt ( " lua num threads " , " Lua " ) > 0 )
2021-04-18 16:50:37 +02:00
mThread = std : : thread ( [ this ] { threadBody ( ) ; } ) ;
} ;
2022-06-21 20:56:19 +02:00
~ LuaWorker ( )
{
if ( mThread & & mThread - > joinable ( ) )
{
Log ( Debug : : Error ) < < " Unexpected destruction of LuaWorker; likely there is an unhandled exception in the main thread. " ;
join ( ) ;
}
}
2021-12-14 00:51:18 +01:00
void allowUpdate ( )
2021-04-18 16:50:37 +02:00
{
2021-04-23 02:49:12 +02:00
if ( ! mThread )
2021-04-18 16:50:37 +02:00
return ;
{
std : : lock_guard < std : : mutex > lk ( mMutex ) ;
mUpdateRequest = true ;
}
mCV . notify_one ( ) ;
}
void finishUpdate ( )
{
2021-04-23 02:49:12 +02:00
if ( mThread )
2021-04-18 16:50:37 +02:00
{
std : : unique_lock < std : : mutex > lk ( mMutex ) ;
mCV . wait ( lk , [ & ] { return ! mUpdateRequest ; } ) ;
}
else
update ( ) ;
} ;
void join ( )
{
2021-04-23 02:49:12 +02:00
if ( mThread )
2021-09-19 10:27:48 +02:00
{
{
std : : lock_guard < std : : mutex > lk ( mMutex ) ;
mJoinRequest = true ;
}
mCV . notify_one ( ) ;
2021-04-23 02:49:12 +02:00
mThread - > join ( ) ;
2021-09-19 10:27:48 +02:00
}
2021-04-18 16:50:37 +02:00
}
private :
void update ( )
{
const auto & viewer = mEngine - > mViewer ;
const osg : : Timer_t frameStart = viewer - > getStartTick ( ) ;
const unsigned int frameNumber = viewer - > getFrameStamp ( ) - > getFrameNumber ( ) ;
ScopedProfile < UserStatsType : : Lua > profile ( frameStart , frameNumber , * osg : : Timer : : instance ( ) , * viewer - > getViewerStats ( ) ) ;
2021-12-14 00:51:18 +01:00
mEngine - > mLuaManager - > update ( ) ;
2021-04-18 16:50:37 +02:00
}
void threadBody ( )
{
2021-09-19 10:27:48 +02:00
while ( true )
2021-04-18 16:50:37 +02:00
{
std : : unique_lock < std : : mutex > lk ( mMutex ) ;
2021-09-19 10:27:48 +02:00
mCV . wait ( lk , [ & ] { return mUpdateRequest | | mJoinRequest ; } ) ;
if ( mJoinRequest )
break ;
2021-04-18 16:50:37 +02:00
update ( ) ;
mUpdateRequest = false ;
lk . unlock ( ) ;
mCV . notify_one ( ) ;
}
}
Engine * mEngine ;
std : : mutex mMutex ;
std : : condition_variable mCV ;
2021-07-12 11:01:32 +02:00
bool mUpdateRequest = false ;
2021-09-19 10:27:48 +02:00
bool mJoinRequest = false ;
2021-04-23 02:49:12 +02:00
std : : optional < std : : thread > mThread ;
2021-04-18 16:50:37 +02:00
} ;
2013-01-08 09:45:01 -08:00
// Initialise and enter main loop.
void OMW : : Engine : : go ( )
{
2013-09-29 09:11:57 +02:00
assert ( ! mContentFiles . empty ( ) ) ;
2015-04-24 23:30:30 +02:00
2018-08-14 23:05:43 +04:00
Log ( Debug : : Info ) < < " OSG version: " < < osgGetVersion ( ) ;
2019-03-15 19:04:47 +03:00
SDL_version sdlVersion ;
SDL_GetVersion ( & sdlVersion ) ;
Log ( Debug : : Info ) < < " SDL version: " < < ( int ) sdlVersion . major < < " . " < < ( int ) sdlVersion . minor < < " . " < < ( int ) sdlVersion . patch ;
2017-02-18 03:15:15 +01:00
2019-02-24 22:41:11 +03:00
Misc : : Rng : : init ( mRandomSeed ) ;
2022-05-13 18:58:00 -07:00
Settings : : ShaderManager : : get ( ) . load ( ( mCfgMgr . getUserConfigPath ( ) / " shaders.yaml " ) . string ( ) ) ;
2020-12-07 19:04:32 +01:00
MWClass : : registerClasses ( ) ;
2018-06-28 18:05:00 +04:00
// Create encoder
2022-05-22 01:47:06 +02:00
mEncoder = std : : make_unique < ToUTF8 : : Utf8Encoder > ( mEncoding ) ;
2018-06-28 18:05:00 +04:00
// Setup viewer
mViewer = new osgViewer : : Viewer ;
mViewer - > setReleaseContextAtEndOfFrameHint ( false ) ;
2019-04-22 21:14:51 +04:00
// Do not try to outsmart the OS thread scheduler (see bug #4785).
mViewer - > setUseConfigureAffinity ( false ) ;
2017-08-30 21:26:30 +00:00
mEnvironment . setFrameRateLimit ( Settings : : Manager : : getFloat ( " framerate limit " , " Video " ) ) ;
2022-05-22 02:47:58 +02:00
prepareEngine ( ) ;
2013-01-08 09:45:01 -08:00
2021-01-27 08:04:33 +00:00
std : : ofstream stats ;
if ( const auto path = std : : getenv ( " OPENMW_OSG_STATS_FILE " ) )
{
stats . open ( path , std : : ios_base : : out ) ;
if ( stats . is_open ( ) )
Log ( Debug : : Info ) < < " Stats will be written to: " < < path ;
else
Log ( Debug : : Warning ) < < " Failed to open file for stats: " < < path ;
}
2018-06-28 18:05:00 +04:00
// Setup profiler
2022-07-07 19:34:18 +04:00
osg : : ref_ptr < Resource : : Profiler > statshandler = new Resource : : Profiler ( stats . is_open ( ) , mVFS . get ( ) ) ;
2018-06-28 18:05:00 +04:00
2020-06-28 01:44:56 +02:00
initStatsHandler ( * statshandler ) ;
2018-06-28 18:05:00 +04:00
mViewer - > addEventHandler ( statshandler ) ;
2022-07-07 19:34:18 +04:00
osg : : ref_ptr < Resource : : StatsHandler > resourceshandler = new Resource : : StatsHandler ( stats . is_open ( ) , mVFS . get ( ) ) ;
2018-06-28 18:05:00 +04:00
mViewer - > addEventHandler ( resourceshandler ) ;
2021-01-27 08:04:33 +00:00
if ( stats . is_open ( ) )
Resource : : CollectStatistics ( mViewer ) ;
2018-06-28 18:05:00 +04:00
// Start the game
2015-01-07 03:03:56 +01:00
if ( ! mSaveGameFile . empty ( ) )
{
2022-05-06 17:46:50 +02:00
mStateManager - > loadGame ( mSaveGameFile ) ;
2015-01-07 03:03:56 +01:00
}
2015-05-07 21:57:02 +02:00
else if ( ! mSkipMenu )
2014-03-27 04:15:47 +01:00
{
2015-01-07 03:03:56 +01:00
// start in main menu
2022-05-06 17:46:50 +02:00
mWindowManager - > pushGuiMode ( MWGui : : GM_MainMenu ) ;
mSoundManager - > playTitleMusic ( ) ;
2019-01-22 10:08:48 +04:00
const std : : string & logo = Fallback : : Map : : getString ( " Movies_Morrowind_Logo " ) ;
2019-03-04 01:31:51 +03:00
if ( ! logo . empty ( ) )
2022-08-01 05:00:06 +03:00
mWindowManager - > playVideo ( logo , /*allowSkipping*/ true , /*overrideSounds*/ false ) ;
2014-03-27 04:15:47 +01:00
}
2013-11-16 12:22:28 +01:00
else
2014-05-20 18:35:17 +02:00
{
2022-05-06 17:46:50 +02:00
mStateManager - > newGame ( ! mNewGame ) ;
2014-05-20 18:35:17 +02:00
}
2014-03-13 13:19:32 +01:00
2022-05-06 17:46:50 +02:00
if ( ! mStartupScript . empty ( ) & & mStateManager - > getState ( ) = = MWState : : StateManager : : State_Running )
2019-02-23 22:39:13 +03:00
{
2022-05-06 17:46:50 +02:00
mWindowManager - > executeInConsole ( mStartupScript ) ;
2019-02-23 22:39:13 +03:00
}
2021-04-18 16:50:37 +02:00
LuaWorker luaWorker ( this ) ; // starts a separate lua thread if "lua num threads" > 0
2020-12-18 23:21:10 +01:00
2010-06-16 12:13:21 +02:00
// Start the main rendering loop
2015-06-14 15:27:33 +02:00
double simulationTime = 0.0 ;
2021-02-11 18:19:55 +01:00
Misc : : FrameRateLimiter frameRateLimiter = Misc : : makeFrameRateLimiter ( mEnvironment . getFrameRateLimit ( ) ) ;
const std : : chrono : : steady_clock : : duration maxSimulationInterval ( std : : chrono : : milliseconds ( 200 ) ) ;
2022-05-06 17:46:50 +02:00
while ( ! mViewer - > done ( ) & & ! mStateManager - > hasQuitRequest ( ) )
2015-04-12 15:34:50 +02:00
{
2021-02-11 18:19:55 +01:00
const double dt = std : : chrono : : duration_cast < std : : chrono : : duration < double > > ( std : : min (
frameRateLimiter . getLastFrameDuration ( ) ,
maxSimulationInterval
2022-07-03 12:51:28 +00:00
) ) . count ( ) * mEnvironment . getWorld ( ) - > getSimulationTimeScale ( ) ;
2015-04-14 15:55:56 +02:00
2015-06-14 15:27:33 +02:00
mViewer - > advance ( simulationTime ) ;
2017-11-16 17:56:44 +01:00
if ( ! frame ( dt ) )
2015-09-04 03:44:14 +02:00
{
2020-06-25 21:46:07 +02:00
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 5 ) ) ;
2015-09-07 16:05:51 +02:00
continue ;
2015-09-04 03:44:14 +02:00
}
else
{
mViewer - > eventTraversal ( ) ;
mViewer - > updateTraversal ( ) ;
2017-07-19 13:05:51 +02:00
2022-05-06 17:46:50 +02:00
mWorld - > updateWindowManager ( ) ;
2017-07-19 13:05:51 +02:00
2021-12-14 00:51:18 +01:00
luaWorker . allowUpdate ( ) ; // if there is a separate Lua thread, it starts the update now
2020-12-18 23:21:10 +01:00
2015-09-04 03:44:14 +02:00
mViewer - > renderingTraversals ( ) ;
2017-11-16 17:56:44 +01:00
2021-04-18 16:50:37 +02:00
luaWorker . finishUpdate ( ) ;
2020-12-18 23:21:10 +01:00
2022-05-06 17:46:50 +02:00
bool guiActive = mWindowManager - > isGuiMode ( ) ;
2017-11-16 17:56:44 +01:00
if ( ! guiActive )
simulationTime + = dt ;
2015-09-04 03:44:14 +02:00
}
2015-09-07 16:05:51 +02:00
2020-05-16 13:45:02 +02:00
if ( stats )
{
const auto frameNumber = mViewer - > getFrameStamp ( ) - > getFrameNumber ( ) ;
2020-07-11 16:16:44 +02:00
if ( frameNumber > = 2 )
{
mViewer - > getViewerStats ( ) - > report ( stats , frameNumber - 2 ) ;
osgViewer : : Viewer : : Cameras cameras ;
mViewer - > getCameras ( cameras ) ;
for ( auto camera : cameras )
camera - > getStats ( ) - > report ( stats , frameNumber - 2 ) ;
}
2020-05-16 13:45:02 +02:00
}
2021-02-11 18:19:55 +01:00
frameRateLimiter . limit ( ) ;
2015-04-12 15:34:50 +02:00
}
2021-04-18 16:50:37 +02:00
luaWorker . join ( ) ;
2020-12-18 23:21:10 +01:00
2012-04-01 18:48:37 +02:00
// Save user settings
2022-05-22 02:47:58 +02:00
Settings : : Manager : : saveUser ( ( mCfgMgr . getUserConfigPath ( ) / " settings.cfg " ) . string ( ) ) ;
2022-05-13 18:58:00 -07:00
Settings : : ShaderManager : : get ( ) . save ( ) ;
2021-12-14 00:39:01 +01:00
mLuaManager - > savePermanentStorage ( mCfgMgr . getUserConfigPath ( ) . string ( ) ) ;
2012-04-01 18:48:37 +02:00
2018-08-14 23:05:43 +04:00
Log ( Debug : : Info ) < < " Quitting peacefully. " ;
2010-06-16 12:13:21 +02:00
}
2010-08-05 13:36:33 +02:00
2010-10-06 14:52:53 +02:00
void OMW : : Engine : : setCompileAll ( bool all )
{
mCompileAll = all ;
}
Added new command line option: "encoding"
Added new command line option: "encoding" which allow to
change font encoding used in game messages.
Currently there are three evailable encodings:
win1250 - Central and Eastern European (languages
that use Latin script, such as Polish,
Czech, Slovak, Hungarian, Slovene, Bosnian,
Croatian, Serbian (Latin script),
Romanian and Albanian)
win1251 - languages that use the Cyrillic alphabet
such as Russian, Bulgarian, Serbian Cyrillic
and others
win1252 - Western European (Latin) - default
Signed-off-by: Lukasz Gromanowski <lgromanowski@gmail.com>
2011-07-17 22:16:50 +02:00
2014-12-13 02:47:04 +01:00
void OMW : : Engine : : setCompileAllDialogue ( bool all )
{
mCompileAllDialogue = all ;
}
Added new command line option: "encoding"
Added new command line option: "encoding" which allow to
change font encoding used in game messages.
Currently there are three evailable encodings:
win1250 - Central and Eastern European (languages
that use Latin script, such as Polish,
Czech, Slovak, Hungarian, Slovene, Bosnian,
Croatian, Serbian (Latin script),
Romanian and Albanian)
win1251 - languages that use the Cyrillic alphabet
such as Russian, Bulgarian, Serbian Cyrillic
and others
win1252 - Western European (Latin) - default
Signed-off-by: Lukasz Gromanowski <lgromanowski@gmail.com>
2011-07-17 22:16:50 +02:00
2011-08-19 21:06:09 +02:00
void OMW : : Engine : : setSoundUsage ( bool soundUsage )
{
mUseSound = soundUsage ;
}
2012-12-23 23:23:24 +04:00
void OMW : : Engine : : setEncoding ( const ToUTF8 : : FromType & encoding )
Added new command line option: "encoding"
Added new command line option: "encoding" which allow to
change font encoding used in game messages.
Currently there are three evailable encodings:
win1250 - Central and Eastern European (languages
that use Latin script, such as Polish,
Czech, Slovak, Hungarian, Slovene, Bosnian,
Croatian, Serbian (Latin script),
Romanian and Albanian)
win1251 - languages that use the Cyrillic alphabet
such as Russian, Bulgarian, Serbian Cyrillic
and others
win1252 - Western European (Latin) - default
Signed-off-by: Lukasz Gromanowski <lgromanowski@gmail.com>
2011-07-17 22:16:50 +02:00
{
mEncoding = encoding ;
2011-08-19 21:06:09 +02:00
}
2012-04-02 20:47:09 +02:00
2012-07-30 11:43:28 +02:00
void OMW : : Engine : : setScriptConsoleMode ( bool enabled )
{
mScriptConsoleMode = enabled ;
}
2012-07-30 12:37:46 +02:00
void OMW : : Engine : : setStartupScript ( const std : : string & path )
{
mStartupScript = path ;
}
2013-01-08 19:52:18 -08:00
void OMW : : Engine : : setActivationDistanceOverride ( int distance )
{
mActivationDistanceOverride = distance ;
2013-08-16 13:01:52 +02:00
}
2014-02-02 14:09:59 +01:00
void OMW : : Engine : : setWarningsMode ( int mode )
{
mWarningsMode = mode ;
2014-02-28 17:23:58 +01:00
}
2014-07-21 09:34:10 +02:00
void OMW : : Engine : : setScriptBlacklist ( const std : : vector < std : : string > & list )
{
mScriptBlacklist = list ;
}
void OMW : : Engine : : setScriptBlacklistUse ( bool use )
{
mScriptBlacklistUse = use ;
2014-08-11 20:37:29 +02:00
}
2015-01-07 03:03:56 +01:00
void OMW : : Engine : : setSaveGameFile ( const std : : string & savegame )
{
mSaveGameFile = savegame ;
}
2019-02-24 22:41:11 +03:00
void OMW : : Engine : : setRandomSeed ( unsigned int seed )
{
mRandomSeed = seed ;
}