diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/game_config.lua b/code/ryzom/client/data/gamedev/interfaces_v3/game_config.lua index 82ca4e48d..b5ed493d7 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/game_config.lua +++ b/code/ryzom/client/data/gamedev/interfaces_v3/game_config.lua @@ -111,7 +111,7 @@ function game:configHideAll() local uiList = { 'explanation', 'general', 'landscape', 'fx', 'char', 'hud', 'language', 'alpha_colors', 'chat_colors', 'entity_colors', 'in_scene_user', 'in_scene_friend', 'in_scene_enemy', - 'in_scene_chat_messages', 'win_colors', 'win_colors_r2', 'mouse', 'keyb', 'sound', 'landmark_colors', 'help' + 'in_scene_chat_messages', 'win_colors', 'win_colors_r2', 'mouse', 'keyb', 'vr', 'sound', 'landmark_colors', 'help' }; for k,v in pairs(uiList) do diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml b/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml index 0a5c3c085..5e9072b93 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml @@ -429,6 +429,9 @@ + @@ -694,6 +697,12 @@ params="game:configShowOne('fx')" fontsize="10" y_decal="-1" /> + + + + + + + + + + + + + + > VRDeviceCache; + /// Ring main page string RingMainURL; diff --git a/code/ryzom/client/src/global.h b/code/ryzom/client/src/global.h index 9e5a294ae..5879eeaec 100644 --- a/code/ryzom/client/src/global.h +++ b/code/ryzom/client/src/global.h @@ -120,6 +120,10 @@ extern bool ConnectionReadySent; extern bool PermanentlyBanned; extern bool IgnoreEntityDbUpdates; +// VR +extern std::vector > VRDeviceCache; + extern std::string Cookie, FSAddr; extern std::string RingMainURL; extern bool FreeTrial; diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index 4c5cd1eca..1c4fe76e9 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -575,6 +575,89 @@ static std::string replaceApplicationDirToken(const std::string &dir) return dir; } +void listStereoDisplayDevices(std::vector &devices) +{ + bool cache = VRDeviceCache.empty(); + nldebug("VR [C]: List devices"); + if (cache) + { + VRDeviceCache.push_back(std::pair("Auto", "0")); + } + IStereoDisplay::listDevices(devices); + for (std::vector::iterator it(devices.begin()), end(devices.end()); it != end; ++it) + { + std::stringstream name; + name << IStereoDisplay::getLibraryName(it->Library) << " - " << it->Manufacturer << " - " << it->ProductName; + std::stringstream fullname; + fullname << std::string("[") << name << "] [" << it->Serial << "]"; + nlinfo("VR [C]: Stereo Display: %s", name.str().c_str()); + if (cache) + { + VRDeviceCache.push_back(std::pair(name.str(), it->Serial)); // VR_CONFIG + } + } +} + +void cacheStereoDisplayDevices() // VR_CONFIG +{ + if (VRDeviceCache.empty()) + { + std::vector devices; + listStereoDisplayDevices(devices); + } +} + +void initStereoDisplayDevice() +{ + if (ClientCfg.VREnable) + { + // VR_CONFIG + nldebug("VR [C]: Enabled"); + std::vector devices; + listStereoDisplayDevices(devices); + CStereoDeviceInfo *deviceInfo = NULL; + if (ClientCfg.VRDisplayDevice == std::string("Auto") + && devices.begin() != devices.end()) + { + deviceInfo = &devices[0]; + } + else + { + for (std::vector::iterator it(devices.begin()), end(devices.end()); it != end; ++it) + { + std::stringstream name; + name << IStereoDisplay::getLibraryName(it->Library) << " - " << it->Manufacturer << " - " << it->ProductName; + if (name.str() == ClientCfg.VRDisplayDevice) + deviceInfo = &(*it); + if (ClientCfg.VRDisplayDeviceId == it->Serial) + break; + } + } + if (deviceInfo) + { + nlinfo("VR [C]: Create VR stereo display device"); + StereoDisplay = IStereoDisplay::createDevice(*deviceInfo); + if (StereoDisplay) + { + if (deviceInfo->Class == CStereoDeviceInfo::StereoHMD) + { + nlinfo("VR [C]: Stereo display device is a HMD"); + StereoHMD = static_cast(StereoDisplay); + } + if (Driver) // VR_DRIVER + { + StereoDisplay->setDriver(Driver); + } + } + } + } + else + { + nldebug("VR [C]: NOT Enabled"); + } + IStereoDisplay::releaseUnusedLibraries(); +} + void addSearchPaths(IProgressCallback &progress) { // Add search path of UI addon. Allow only a subset of files. @@ -797,55 +880,7 @@ void prelogInit() // Initialize the VR devices (even more important than the most important part of the client) nmsg = "Initializing VR devices..."; ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) ); - if (ClientCfg.VREnable) - { - nldebug("VR [C]: Enabled"); - std::vector devices; - IStereoDisplay::listDevices(devices); - for (std::vector::iterator it(devices.begin()), end(devices.end()); it != end; ++it) - { - std::stringstream name; - name << std::string("[") << it->Serial << "] [" << IStereoDisplay::getLibraryName(it->Library) << " - " << it->Manufacturer << " - " << it->ProductName << "]"; - nlinfo("VR [C]: Stereo Display: %s", name.str().c_str()); - } - CStereoDeviceInfo *deviceInfo = NULL; - if (ClientCfg.VRDisplayDevice == std::string("Auto") - && devices.begin() != devices.end()) - { - deviceInfo = &devices[0]; - } - else - { - for (std::vector::iterator it(devices.begin()), end(devices.end()); it != end; ++it) - { - std::stringstream name; - name << IStereoDisplay::getLibraryName(it->Library) << " - " << it->Manufacturer << " - " << it->ProductName; - if (name.str() == ClientCfg.VRDisplayDevice) - deviceInfo = &(*it); - if (ClientCfg.VRDisplayDeviceId == it->Serial) - break; - } - } - if (deviceInfo) - { - nlinfo("VR [C]: Create VR stereo display device"); - StereoDisplay = IStereoDisplay::createDevice(*deviceInfo); - if (StereoDisplay) - { - if (deviceInfo->Class == CStereoDeviceInfo::StereoHMD) - { - nlinfo("VR [C]: Stereo display device is a HMD"); - StereoHMD = static_cast(StereoDisplay); - } - } - } - } - else - { - nldebug("VR [C]: NOT Enabled"); - } - IStereoDisplay::releaseUnusedLibraries(); - + initStereoDisplayDevice(); // VR_CONFIG // Create the driver (most important part of the client). nmsg = "Creating 3d driver..."; @@ -916,7 +951,7 @@ void prelogInit() else Driver->setSwapVBLInterval(0); - if (StereoDisplay) + if (StereoDisplay) // VR_CONFIG // VR_DRIVER { // override mode TODO } @@ -1163,10 +1198,10 @@ void prelogInit() // init bloom effect CBloomEffect::getInstance().init(driver != UDriver::Direct3d); - if (StereoDisplay) + if (StereoDisplay) // VR_CONFIG { // Init stereo display resources - StereoDisplay->setDriver(Driver); + StereoDisplay->setDriver(Driver); // VR_DRIVER } nlinfo ("PROFILE: %d seconds for prelogInit", (uint32)(ryzomGetLocalTime ()-initStart)/1000); diff --git a/code/ryzom/client/src/interface_v3/action_handler_game.cpp b/code/ryzom/client/src/interface_v3/action_handler_game.cpp index 5d886a8ee..63d2c93b7 100644 --- a/code/ryzom/client/src/interface_v3/action_handler_game.cpp +++ b/code/ryzom/client/src/interface_v3/action_handler_game.cpp @@ -19,6 +19,8 @@ #include "stdpch.h" +#include + // Interface includes #include "interface_manager.h" #include "nel/gui/action_handler.h" @@ -2919,6 +2921,11 @@ static vector VideoModes; // We allow only this RGB depth to be taken #define GAME_CONFIG_VIDEO_DEPTH_REQ 32 +// VR_CONFIG +#define GAME_CONFIG_VR_ENABLE_BUTTON "ui:interface:game_config:content:vr:enabler:c" +#define GAME_CONFIG_VR_DEVICES_COMBO "ui:interface:game_config:content:vr:vr_devices" +#define GAME_CONFIG_VR_DEVICE_DB "UI:TEMP:VR_DEVICE" + // The combo for Texture Mode selected #define GAME_CONFIG_TEXTURE_MODE_COMBO "ui:interface:game_config:content:general:texture_mode:combo" #define GAME_CONFIG_TEXTURE_MODE_DB "UI:TEMP:TEXTURE_MODE" @@ -2926,6 +2933,50 @@ static vector VideoModes; // The 3 possible modes editable (NB: do not allow client.cfg HDEntityTexture==1 and DivideTextureSizeBy2=2 enum TTextureMode {LowTextureMode= 0, NormalTextureMode= 1, HighTextureMode= 2}; +void cacheStereoDisplayDevices(); // from init.cpp + +void updateVRDevicesComboUI(bool enable) +{ + // VR_CONFIG + nldebug("Init VR device name list from cache into UI"); + // init vr device name list from cache + CDBGroupComboBox *pCB = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GAME_CONFIG_VR_DEVICES_COMBO)); + if (pCB) + { + pCB->setActive(enable); + if (enable) + { + nldebug("pCB ok"); + cacheStereoDisplayDevices(); + pCB->resetTexts(); + sint32 selectedDevice = -1; + for (uint i = 0; i < VRDeviceCache.size(); ++i) + { + std::stringstream displayname; + displayname << std::string("[") << VRDeviceCache[i].first << "] [" << VRDeviceCache[i].second << "]"; + pCB->addText(ucstring(displayname.str())); + if (ClientCfg.VRDisplayDevice == VRDeviceCache[i].first) + { + if (selectedDevice == -1 || ClientCfg.VRDisplayDeviceId == VRDeviceCache[i].second) + { + selectedDevice = i; + } + } + } + if (selectedDevice == -1) + { + // configured device not found, add a dummy + std::stringstream displayname; + displayname << std::string("[") << ClientCfg.VRDisplayDevice << "] [" << ClientCfg.VRDisplayDeviceId<< "] [DEVICE NOT FOUND]"; + pCB->addText(ucstring(displayname.str())); + selectedDevice = VRDeviceCache.size(); + } + NLGUI::CDBManager::getInstance()->getDbProp(GAME_CONFIG_VR_DEVICE_DB)->setValue32(-1); + NLGUI::CDBManager::getInstance()->getDbProp(GAME_CONFIG_VR_DEVICE_DB)->setValue32(selectedDevice); + } + } +} + // *************************************************************************** class CHandlerGameConfigInit : public IActionHandler { @@ -2975,6 +3026,14 @@ public: pCB->addText(CI18N::get("uigcHighTextureMode")); } + // VR_CONFIG + pBut = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GAME_CONFIG_VR_ENABLE_BUTTON)); + if (pBut) + { + pBut->setPushed(ClientCfg.VREnable); + } + updateVRDevicesComboUI(ClientCfg.VREnable); + // init the mode in DB TTextureMode texMode; if(ClientCfg.DivideTextureSizeBy2) @@ -3025,7 +3084,7 @@ class CHandlerGameConfigMode : public IActionHandler sint oldVideoMode= NLGUI::CDBManager::getInstance()->getDbProp( GAME_CONFIG_VIDEO_MODE_DB )->getOldValue32(); sint nVideModeNb = NLGUI::CDBManager::getInstance()->getDbProp( GAME_CONFIG_VIDEO_MODE_DB )->getValue32(); - if (nVideModeNb == -1) return; + if (nVideModeNb == -1 || oldVideoMode == -1) return; CDBGroupComboBox *pCB= dynamic_cast(CWidgetManager::getInstance()->getElementFromId( GAME_CONFIG_VIDEO_MODES_COMBO )); if( pCB == NULL ) return; @@ -3204,6 +3263,54 @@ class CHandlerGameConfigFullscreen : public IActionHandler }; REGISTER_ACTION_HANDLER (CHandlerGameConfigFullscreen, "game_config_change_vid_fullscreen"); +// *************************************************************************** +class CHandlerGameConfigVREnable : public IActionHandler +{ + virtual void execute (CCtrlBase *pCaller, const string &/* Params */) + { + // VR_CONFIG + + CCtrlBaseButton *pBut = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GAME_CONFIG_VR_ENABLE_BUTTON)); + if (pBut) + { + // hide or show device list depending on enabled or not + updateVRDevicesComboUI(pBut->getPushed()); + } + + if (pCaller) + { + CDDXManager *pDM = CDDXManager::getInstance(); + CInterfaceDDX *pDDX = pDM->get(GAME_CONFIG_DDX); + if(pDDX) + pDDX->validateApplyButton(); + } + } +}; +REGISTER_ACTION_HANDLER (CHandlerGameConfigVREnable, "game_config_change_vr_enable"); + +// *************************************************************************** +class CHandlerGameConfigVRDevice : public IActionHandler +{ + virtual void execute (CCtrlBase *pCaller, const string &/* Params */) + { + // VR_CONFIG + + sint oldDevice = NLGUI::CDBManager::getInstance()->getDbProp(GAME_CONFIG_VR_DEVICE_DB)->getOldValue32(); + sint newDevice = NLGUI::CDBManager::getInstance()->getDbProp(GAME_CONFIG_VR_DEVICE_DB)->getValue32(); + + if (oldDevice != -1 && newDevice != -1 && pCaller) + { + // nldebug("TODO_VR switch vr device (from combo box)"); + + CDDXManager *pDM = CDDXManager::getInstance(); + CInterfaceDDX *pDDX = pDM->get(GAME_CONFIG_DDX); + if(pDDX) + pDDX->validateApplyButton(); + } + } +}; +REGISTER_ACTION_HANDLER (CHandlerGameConfigVRDevice, "game_config_change_vr_device"); + // *************************************************************************** class CHandlerGameConfigApply : public IActionHandler { @@ -3297,6 +3404,23 @@ class CHandlerGameConfigApply : public IActionHandler } } + CCtrlBaseButton *pBut = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GAME_CONFIG_VR_ENABLE_BUTTON)); + if (pBut) + { + // store the new config variables + ClientCfg.VREnable = pBut->getPushed(); + ClientCfg.writeBool("VREnable", pBut->getPushed()); + } + if (ClientCfg.VREnable) + { + // store the new config variables + sint deviceIdx = NLGUI::CDBManager::getInstance()->getDbProp(GAME_CONFIG_VR_DEVICE_DB)->getValue32(); + ClientCfg.VRDisplayDevice = VRDeviceCache[deviceIdx].first; + ClientCfg.VRDisplayDeviceId = VRDeviceCache[deviceIdx].second; + ClientCfg.writeString("VRDisplayDevice", VRDeviceCache[deviceIdx].first); + ClientCfg.writeString("VRDisplayDeviceId", VRDeviceCache[deviceIdx].second); + } + bool requestReboot = false; // **** Apply the texture mode diff --git a/code/ryzom/client/src/main_loop_utilities.cpp b/code/ryzom/client/src/main_loop_utilities.cpp index 7afba0a9f..bca1ccad2 100644 --- a/code/ryzom/client/src/main_loop_utilities.cpp +++ b/code/ryzom/client/src/main_loop_utilities.cpp @@ -38,6 +38,10 @@ using namespace NLMISC; using namespace NL3D; +void updateVRDevicesComboUI(); // from action_handler_game.cpp +void initStereoDisplayDevice(); // from init.cpp +void releaseStereoDisplayDevice(); // from release.cpp + //--------------------------------------------------- // Compare ClientCfg and LastClientCfg to know what we must update //--------------------------------------------------- @@ -45,6 +49,17 @@ void updateFromClientCfg() { CClientConfig::setValues(); ClientCfg.IsInvalidated = false; + + if ((ClientCfg.VREnable != LastClientCfg.VREnable) + || (ClientCfg.VREnable && ( + ClientCfg.VRDisplayDevice != LastClientCfg.VRDisplayDevice + || ClientCfg.VRDisplayDeviceId != LastClientCfg.VRDisplayDeviceId + ))) + { + nldebug("Apply VR device change"); + releaseStereoDisplayDevice(); + initStereoDisplayDevice(); + } // GRAPHICS - GENERAL //--------------------------------------------------- diff --git a/code/ryzom/client/src/release.cpp b/code/ryzom/client/src/release.cpp index dae95767c..b40d68b35 100644 --- a/code/ryzom/client/src/release.cpp +++ b/code/ryzom/client/src/release.cpp @@ -512,6 +512,17 @@ void releaseOutGame() ContinentMngr.reset(); } +void releaseStereoDisplayDevice() +{ + if (StereoDisplay) + { + delete StereoDisplay; + StereoDisplay = NULL; + StereoHMD = NULL; + } + IStereoDisplay::releaseAllLibraries(); +} + // *************************************************************************** // final release : Release before exit. void release() @@ -559,13 +570,7 @@ void release() EAM= NULL; nldebug("VR [C]: VR Shutting down"); - if (StereoDisplay) - { - delete StereoDisplay; - StereoDisplay = NULL; - StereoHMD = NULL; - } - IStereoDisplay::releaseAllLibraries(); + releaseStereoDisplayDevice(); // Delete the driver. if(Driver)