mojo_client/src/Client/GUI/PseuGUI.cpp
false_genesis d7d36c544e * implemented realm and character selection from the GUI
* added support for map tile sound emitters (MCSE-chunks) (needs more debugging)
* added MasterSoundVolume=0..1 conf option to /conf/gui.conf
* fixed window resize & added related functions to the scenes (OnResize()). TODO: fix SceneLogin resize.
* implemented "Community Site" button functionality on Win32
* misc stuff
* TODO: fix crypt error on realm change.
* moved linux configure.ac script to PseuWoW root dir instead of /src
2008-08-27 23:41:12 +00:00

367 lines
10 KiB
C++

#include "common.h"
#include "irrlicht/irrlicht.h"
#include "CM2MeshFileLoader.h"
#include "CImageLoaderBLP.h"
#include "Object.h"
#include "DrawObject.h"
#include "PseuWoW.h"
#include "Scene.h"
#include "PseuGUI.h"
PseuGUIRunnable::PseuGUIRunnable()
{
_gui = new PseuGUI();
}
void PseuGUIRunnable::run(void)
{
_gui->Run();
}
PseuGUI *PseuGUIRunnable::GetGUI(void)
{
return _gui;
}
PseuGUIRunnable::~PseuGUIRunnable()
{
delete _gui;
}
PseuGUI::PseuGUI()
{
_xres = 640;
_yres = 480;
_colordepth = 32;
_shadows = false;
_windowed = true;
_vsync = false;
_initialized = false;
_mustdie = false;
_driverType = video::EDT_BURNINGSVIDEO; // nulldevice makes not really a sense to display stuff
_scenestate = _scenestate_new = SCENESTATE_NULL;
_smgr = NULL;
_device = NULL;
_guienv = NULL;
_scene = NULL;
_passtime = _lastpasstime = _passtimediff = 0;
_soundengine = NULL;
_usesound = false;
}
PseuGUI::~PseuGUI()
{
domgr.Clear();
this->Cancel();
_instance->DeleteGUI(); // this makes the instance set its gui ptr to NULL
logdebug("PseuGUI::~PseuGUI()");
}
void PseuGUI::SetDriver(uint8 driverId)
{
switch(driverId)
{
case DIRECTX9: _driverType = video::EDT_DIRECT3D9; break;
case DIRECTX8: _driverType = video::EDT_DIRECT3D8; break;
case OPENGL: _driverType = video::EDT_OPENGL; break;
case SOFTWARE: _driverType = video::EDT_SOFTWARE; break;
case BURNINGSVIDEO: _driverType = video::EDT_BURNINGSVIDEO; break;
case NULLDEVICE: _driverType = video::EDT_NULL; break;
default: _driverType = video::EDT_BURNINGSVIDEO; // if no valid driver detected, use software
}
// TODO: add support for changing driver during runtime?
}
void PseuGUI::SetResolution(uint16 x, uint16 y, uint16 depth)
{
_xres = x;
_yres = y;
_colordepth = depth;
}
void PseuGUI::SetWindowed(bool b)
{
_windowed = b;
// see PseuGUI::Init(): !_windowed == fullscreen
}
void PseuGUI::SetVSync(bool b)
{
_vsync = b;
}
void PseuGUI::UseShadows(bool b)
{
_shadows = b;
}
// if this fuction is called from another thread the device will not work correctly. o_O
void PseuGUI::_Init(void)
{
_device = createDevice(_driverType,dimension2d<s32>(_xres,_yres),_colordepth,!_windowed,_shadows,_vsync);
if(!_device)
{
logerror("PseuGUI: Can't use specified video driver, trying software mode...");
_device = createDevice(video::EDT_SOFTWARE,dimension2d<s32>(_xres,_yres),_colordepth,!_windowed,false,false);
if(!_device)
{
logerror("ERROR: PseuGUI::_Init() failed, no video driver available!");
return;
}
else
{
logerror("PseuGUI: Software mode OK!");
}
}
DEBUG(logdebug("PseuGUI::Init() _device=%X",_device));
_device->setWindowCaption(L"PseuWoW - Initializing");
_device->setResizeAble(true);
_driver = _device->getVideoDriver();
_smgr = _device->getSceneManager();
_guienv = _device->getGUIEnvironment();
_timer = _device->getTimer();
_screendimension = _driver->getScreenSize();
//...
// disable crappy irrlicht logging
_device->getLogger()->setLogLevel(ELL_NONE);
// register external loaders for not supported filetypes
video::CImageLoaderBLP* BLPloader = new video::CImageLoaderBLP();
_driver->addExternalImageLoader(BLPloader);
scene::CM2MeshFileLoader* m2loader = new scene::CM2MeshFileLoader(_device, "./data/texture");
_smgr->addExternalMeshLoader(m2loader);
_throttle=0;
_initialized = true;
// initialize the sound engine
if(_usesound)
{
_soundengine = createIrrKlangDevice();
if(_soundengine)
{
logdetail("PseuGUI: Sound Driver: %s",_soundengine->getDriverName());
_soundengine->setSoundVolume(GetInstance()->GetConf()->masterSoundVolume);
// accept only values between 0 and 1
if(_soundengine->getSoundVolume() < 0.0f || _soundengine->getSoundVolume() >= 1.0f)
_soundengine->setSoundVolume(1.0f);
logdetail("PseuGUI: Master Sound Volume: %.3f",_soundengine->getSoundVolume());
}
else
logerror("PseuGUI: Failed to initialize sound engine!");
}
}
void PseuGUI::Cancel(void)
{
DEBUG(logdebug("PseuGUI::Cancel()"));
if(_scene)
{
_scene->OnDelete();
delete _scene;
_scene = NULL;
}
if(_device)
{
_device->drop();
_device = NULL;
}
if(_soundengine)
{
_soundengine->drop();
_soundengine = NULL;
}
_mustdie = true;
}
void PseuGUI::Shutdown(void)
{
DEBUG(logdebug("PseuGUI::Shutdown()"));
_mustdie = true;
}
void PseuGUI::Run(void)
{
if(!_initialized)
this->_Init();
if(!_initialized) // recheck
{
logerror("PseuGUI: not initialized, using non-GUI mode");
Cancel();
return;
}
DEBUG(logdebug("PseuGUI::Run() _device=%X",_device));
int lastFPS = -1, fps = -1;
while(_device && _device->run() && !_mustdie)
{
_lastpasstime = _passtime;
_passtime = _timer->getTime();
_passtimediff = _passtime - _lastpasstime;
if (!_device->isWindowActive())
{
_device->sleep(10); // save cpu & gpu power if not focused
}
_UpdateSceneState();
if(!_scene)
{
_device->sleep(10);
continue;
}
if(_screendimension != _driver->getScreenSize())
{
_scene->OnResize();
_screendimension = _driver->getScreenSize();
}
if(_updateScene)
{
_updateScene = false;
_scene->OnManualUpdate();
}
_scene->OnUpdate(_passtimediff); // custom: process input, set camera, etc
_driver->beginScene(true, true, _scene->GetBackgroundColor()); // irr: call driver to start drawing
_scene->OnDrawBegin(); // custom: draw everything before irrlicht draws everything by itself
_smgr->drawAll(); // irr: draw all scene nodes
_guienv->drawAll(); // irr: draw gui elements
_scene->OnDraw(); // custom: draw everything that has to be draw late (post-processing also belongs here)
_driver->endScene(); // irr: drawing done
if(_driver->getFPS()>100 && _throttle < 10)//Primitive FPS-Limiter - upper cap hardcoded 100 FPS.
_throttle++; //lowercap 60 (if it drops below, limiting is eased).
if(_driver->getFPS()<60 && _throttle>0) //but honestly, a 10 msec delay is not worth this amount of code.
_throttle--; //If the FPS is down, it will never be because of this
if(_throttle>0) //Thus i opt for dropping the charade and using a fixed conf value of max 10.
_device->sleep(_throttle); //sleeps max 10 msec (=_throttle) here.
fps = _driver->getFPS();
if (lastFPS != fps)
{
core::stringw str = L"PseuWoW [";
str += _driver->getName();
str += "] FPS:";
str += fps;
_device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}
domgr.UnlinkAll(); // At this point the irr::device is probably closed and deleted already, which means it deleted
// all SceneNodes and everything. the ptrs are still stored in the DrawObjects, means they need to be unlinked now not to cause a crash.
DEBUG(logdebug("PseuGUI::Run() finished"));
Cancel(); // already got shut down somehow, we can now safely cancel and drop the device
}
// called from ObjMgr::Remove(guid)
void PseuGUI::NotifyObjectDeletion(uint64 guid)
{
domgr.Delete(guid);
}
// called from ObjMgr::Add(Object*)
void PseuGUI::NotifyObjectCreation(Object *o)
{
DrawObject *d = new DrawObject(_device,o,_instance);
domgr.Add(o->GetGUID(),d);
}
void PseuGUI::NotifyAllObjectsDeletion(void)
{
domgr.Clear();
}
void PseuGUI::SetInstance(PseuInstance* in)
{
_instance = in;
}
void PseuGUI::SetSceneState(SceneState state)
{
_scenestate_new = state; // will be applied at next cycle
}
void PseuGUI::_UpdateSceneState(void)
{
if(_scenestate != _scenestate_new && _smgr)
{
if(_scene)
{
_scene->OnDelete();
delete _scene;
_scene = NULL;
}
_smgr->clear();
_guienv->clear();
logdebug("PseuGUI: switching to SceneState %u", _scenestate_new);
switch (_scenestate_new)
{
case SCENESTATE_GUISTART: _scene = new SceneGuiStart(this); break;
case SCENESTATE_LOGINSCREEN: _scene = new SceneLogin(this); break;
case SCENESTATE_WORLD: _scene = new SceneWorld(this); break;
case SCENESTATE_REALMSELECT:
_scene = new SceneCharSelection(this);
_scene->SetData(ISCENE_CHARSEL_REALMFIRST, 1);
_scene->OnResize();
_scenestate_new = SCENESTATE_CHARSELECT;
break;
case SCENESTATE_CHARSELECT:
_scene = new SceneCharSelection(this);
_scene->SetData(ISCENE_CHARSEL_REALMFIRST, 0);
_scene->OnResize();
break;
default: _scene = new Scene(this); // will draw nothing, just yield the gui
}
_scene->SetState(_scenestate_new);
// current scenestate can be set safely after scene is created and ready
_scenestate = _scenestate_new;
logdebug("PseuGUI: scene created.");
}
}
bool PseuGUI::SetSceneData(uint32 index, uint32 value)
{
if(!_scene)
return false;
_scene->SetData(index, value);
return true;
}
uint32 PseuGUI::GetSceneState(void)
{
/* // not good, not threadsafe! (can crash)
if(!_scene)
return SCENESTATE_NOSCENE;
return _scene->GetState();*/
return _scenestate;
}
// used to get our current WorldPosition
WorldPosition PseuGUI::GetWorldPosition(void)
{
if(_scene && _scene->GetState() == SCENESTATE_WORLD)
{
return ((SceneWorld*)_scene)->GetWorldPosition();
}
return WorldPosition();
}