diff --git a/.hgtags b/.hgtags index 38ed6cd84..5f0958f4c 100644 --- a/.hgtags +++ b/.hgtags @@ -1,27 +1,28 @@ -4eddbaff0c5e5d685db96ee3e8427aa0fd96ac83 v0.8.0 -00d9b6e29e95f56785fbf85abe60afd34674f402 v0.9.0 -79776c337176dd5b02e1a74fe5dfb703b91747aa v0.9.1 -fedf2aa443d09707beed814b0f499c6a5519cc84 v0.10.0 -edaa3624a56420b02ccc64c26059801a389927ee v0.11.0 -e3fe4855f22c3e75722e015dc33c091c340b3ad7 v0.11.1 -9e583b717fd63be0be9fd60b99087abf1691ea49 v0.11.2 -bfe5628e14a024ba7ea32e4b326ae433a07856b9 v0.11.3 -9a6120735daa97c96ac5d85ca35c7f21f607bd87 v0.12.0 -3e92c7104c20d6bc6c2147b4b5fc289e8621d322 v1.0.0 -8eb94c3549be898fdc4a7c6d791d2477bdc11a18 v1.0.1 -3e17907af67e8d66d80e6b714707bbf912607f2a ryzom/3.0.0 -153e0b605c9e0c83ba05b6428c62838b49cc84b2 ryzom/3.0.1 -9d41f2994d44b9aad92b83f945f114e4b6bed44a ryzom/3.0.2 -4300cc14aad098b1f86ea4c55577b7fa4a4cb5d2 ryzom/3.1.0 -d4060f217f4f834cc62a33f2f1ccdf3c28298066 ryzom/3.1.0-hotfix -043aaeb3d8a2a54177581b57bda87a9deaad510e ryzom/3.1.0-april_patch -4036ecf59e83960f03acebc2089eb2ff5eeaed0a ryzom/3.2.0 -18403bb9485da3d9742c6f007a16d5619ebfb196 ryzom/3.2.1 -822ff8f8917ad66e09e2c21c983282f6f693b9f6 ryzom/3.3.0 -00dde390a394fce9da06c2f3264140282158d39f ryzom/3.3.0 -dcd4c4d161ef775136e18c7e8f5072b75dede27e ryzom/3.3.1 -fc4be8ebec5ca754ef4453bc6a9faef90837c674 ryzom/3.4.0 -70eba02e8eab6920586dbabf74e9e8180c729980 ryzom/3.4.0-steam_fix -3941482843f9cd130cfc16634efc08d34a98ed35 ryzom/3.4.0-atysmas -ecae9feb4cceb78103e5d7236caccaf450796cdb ryzom/3.5.0 -95783afa226f241062134eb62f4323295d29ac84 ryzom/3.5.0.9637 +4eddbaff0c5e5d685db96ee3e8427aa0fd96ac83 ryzomcore/v0.8.0 +00d9b6e29e95f56785fbf85abe60afd34674f402 ryzomcore/v0.9.0 +79776c337176dd5b02e1a74fe5dfb703b91747aa ryzomcore/v0.9.1 +fedf2aa443d09707beed814b0f499c6a5519cc84 ryzomcore/v0.10.0 +edaa3624a56420b02ccc64c26059801a389927ee ryzomcore/v0.11.0 +e3fe4855f22c3e75722e015dc33c091c340b3ad7 ryzomcore/v0.11.1 +9e583b717fd63be0be9fd60b99087abf1691ea49 ryzomcore/v0.11.2 +bfe5628e14a024ba7ea32e4b326ae433a07856b9 ryzomcore/v0.11.3 +9a6120735daa97c96ac5d85ca35c7f21f607bd87 ryzomcore/v0.12.0 +3e17907af67e8d66d80e6b714707bbf912607f2a ryzom-patch-3.0.0 +153e0b605c9e0c83ba05b6428c62838b49cc84b2 ryzom-patch-3.0.1 +9d41f2994d44b9aad92b83f945f114e4b6bed44a ryzom-patch-3.0.2 +4300cc14aad098b1f86ea4c55577b7fa4a4cb5d2 ryzom-patch-3.1.0 +d4060f217f4f834cc62a33f2f1ccdf3c28298066 ryzom-patch-3.1.0-hotfix +043aaeb3d8a2a54177581b57bda87a9deaad510e ryzom-patch-3.1.0-april_patch +4036ecf59e83960f03acebc2089eb2ff5eeaed0a ryzom-patch-3.2.0 +18403bb9485da3d9742c6f007a16d5619ebfb196 ryzom-patch-3.2.1 +822ff8f8917ad66e09e2c21c983282f6f693b9f6 ryzom-patch-3.3.0 +00dde390a394fce9da06c2f3264140282158d39f ryzom-patch-3.3.0 +dcd4c4d161ef775136e18c7e8f5072b75dede27e ryzom-patch-3.3.1 +fc4be8ebec5ca754ef4453bc6a9faef90837c674 ryzom-patch-3.4.0 +70eba02e8eab6920586dbabf74e9e8180c729980 ryzom-patch-3.4.0 Steam Fix +3941482843f9cd130cfc16634efc08d34a98ed35 ryzom-patch-3.4.0 Atysmas +ecae9feb4cceb78103e5d7236caccaf450796cdb ryzom-patch-3.5.0 +95783afa226f241062134eb62f4323295d29ac84 ryzom-patch-3.5.0.9637 +2102fb276eb69d49ed4923042215312a63c47c08 Live-746 +8eb94c3549be898fdc4a7c6d791d2477bdc11a18 ryzomcore/v1.0.1 +3e92c7104c20d6bc6c2147b4b5fc289e8621d322 ryzomcore/v1.0.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c962537c..3225dc1b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,9 +177,16 @@ IF(WITH_STATIC) ENDIF() # under Linux and OS X, recent libxml2 versions are linked against libicu - FIND_PACKAGE(Icu) - IF(ICU_LIBRARIES) - SET(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} ${ICU_LIBRARIES} ${ICU_DATA_LIBRARIES}) + # FIND_PACKAGE(Icu) + FIND_LIBRARY(ICU_LIBRARY icuuc) + IF(ICU_LIBRARY) + FIND_LIBRARY(ICU_DATA_LIBRARY icudata) + IF(ICU_LIBRARY) + MESSAGE(STATUS "ICU UC was found: ${ICU_LIBRARY}") + ELSE() + MESSAGE(STATUS "ICU UC was NOT found") + ENDIF() + SET(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} ${ICU_DATA_LIBRARY} ${ICU_LIBRARY}) ENDIF() ENDIF() diff --git a/nel/include/nel/gui/ctrl_scroll.h b/nel/include/nel/gui/ctrl_scroll.h index 76827dd29..4052e6cea 100644 --- a/nel/include/nel/gui/ctrl_scroll.h +++ b/nel/include/nel/gui/ctrl_scroll.h @@ -177,6 +177,7 @@ namespace NLGUI bool _MouseDown : 1; bool _CallingAH : 1; bool _Cancelable : 1; // true if the slider may be cancelled when pressed on the mouse right button + bool _Keyboard : 1; bool _Frozen : 1; bool _Scale : 1; diff --git a/nel/include/nel/gui/ctrl_text_button.h b/nel/include/nel/gui/ctrl_text_button.h index 25fc9eeac..9bae24ad5 100644 --- a/nel/include/nel/gui/ctrl_text_button.h +++ b/nel/include/nel/gui/ctrl_text_button.h @@ -127,6 +127,16 @@ namespace NLGUI void setTexturePushed(const std::string &l, const std::string &m, const std::string &r); void setTextureOver(const std::string &l, const std::string &m, const std::string &r); + // lua + void setTextureLua (const std::string &name); + void setTexturePushedLua (const std::string &name); + void setTextureOverLua (const std::string &name); + + // return texture _l.tga + std::string getTexture () const; + std::string getTexturePushed () const; + std::string getTextureOver() const; + int luaGetViewText(CLuaState &ls); REFLECT_EXPORT_START(CCtrlTextButton, CCtrlBaseButton) @@ -137,6 +147,9 @@ namespace NLGUI REFLECT_SINT32("wmin", getWMin, setWMin) REFLECT_SINT32("hmin", getHMin, setHMin) REFLECT_LUA_METHOD("getViewText", luaGetViewText) + REFLECT_STRING("texture", getTexture, setTextureLua); + REFLECT_STRING("texture_pushed", getTexturePushed, setTexturePushedLua); + REFLECT_STRING("texture_over", getTextureOver, setTextureOverLua); REFLECT_EXPORT_END void onRemoved(); diff --git a/nel/include/nel/gui/view_renderer.h b/nel/include/nel/gui/view_renderer.h index aefbb315f..4498a436a 100644 --- a/nel/include/nel/gui/view_renderer.h +++ b/nel/include/nel/gui/view_renderer.h @@ -444,9 +444,13 @@ namespace NLGUI SGlobalTexture () { FromGlobaleTexture = true; + Scale = 1.f; } uint32 Width, Height; uint32 DefaultWidth, DefaultHeight; + // used by texture atlas to unscale individual texture + // getTextureSizeFromId() calls to return 1x size for GUI. + float Scale; NL3D::UTexture *Texture; std::string Name; bool FromGlobaleTexture; diff --git a/nel/src/3d/driver/opengl/driver_opengl_extension.cpp b/nel/src/3d/driver/opengl/driver_opengl_extension.cpp index c81ab9e1e..4bdd7ca97 100644 --- a/nel/src/3d/driver/opengl/driver_opengl_extension.cpp +++ b/nel/src/3d/driver/opengl/driver_opengl_extension.cpp @@ -1275,7 +1275,7 @@ static bool setupNVFragmentProgram2(const char *glext) { H_AUTO_OGL(setupNVFragmentProgram2); CHECK_EXT("GL_NV_fragment_program2"); - + return true; } @@ -1284,7 +1284,7 @@ static bool setupARBFragmentShader(const char *glext) { H_AUTO_OGL(setupNVFragmentProgram2); CHECK_EXT("GL_ARB_fragment_shader"); - + return true; } @@ -1584,6 +1584,14 @@ void registerGlExtensions(CGlExtensions &ext) { H_AUTO_OGL(registerGlExtensions); +#ifdef NL_OS_MAC + CGLContextObj ctx = CGLGetCurrentContext(); + if (ctx == NULL) + { + nlerror("No OpenGL context set"); + } +#endif + // OpenGL 1.2 ?? const char *nglVersion = (const char *)glGetString (GL_VERSION); @@ -1691,12 +1699,12 @@ void registerGlExtensions(CGlExtensions &ext) ext.EXTVertexShader = false; ext.ARBVertexProgram = false; } - + // Check pixel program // Disable feature ??? if (!ext.DisableHardwarePixelProgram) { - ext.ARBFragmentProgram = setupARBFragmentProgram(glext); + ext.ARBFragmentProgram = setupARBFragmentProgram(glext); ext.NVFragmentProgram2 = setupNVFragmentProgram2(glext); ext.ARBFragmentShader = setupARBFragmentShader(glext); } diff --git a/nel/src/3d/driver/opengl/driver_opengl_window.cpp b/nel/src/3d/driver/opengl/driver_opengl_window.cpp index 293cb28bb..6537c289f 100644 --- a/nel/src/3d/driver/opengl/driver_opengl_window.cpp +++ b/nel/src/3d/driver/opengl/driver_opengl_window.cpp @@ -1072,6 +1072,9 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re [_ctx flushBuffer]; [_glView display]; + // Set context as thread context + CGLSetCurrentContext((CGLContextObj)[_ctx CGLContextObj]); + _EventEmitter.init(this, _glView, _DestroyWindow); #elif defined(NL_OS_UNIX) diff --git a/nel/src/gui/ctrl_scroll.cpp b/nel/src/gui/ctrl_scroll.cpp index 14caa75f4..6b2a5d066 100644 --- a/nel/src/gui/ctrl_scroll.cpp +++ b/nel/src/gui/ctrl_scroll.cpp @@ -57,6 +57,7 @@ namespace NLGUI _MouseDown = false; _CallingAH = false; _Cancelable = false; + _Keyboard = false; _Target = NULL; _Inverted = false; _IsDBLink = false; @@ -225,6 +226,11 @@ namespace NLGUI return toString( _Cancelable ); } else + if( name == "keyboard" ) + { + return toString( _Keyboard ); + } + else if( name == "frozen" ) { return toString( _Frozen ); @@ -405,6 +411,14 @@ namespace NLGUI return; } else + if( name == "keyboard" ) + { + bool b; + if( fromString( value, b ) ) + _Keyboard = b; + return; + } + else if( name == "frozen" ) { bool b; @@ -474,6 +488,7 @@ namespace NLGUI xmlSetProp( node, BAD_CAST "target_stepy", BAD_CAST toString( _TargetStepY ).c_str() ); xmlSetProp( node, BAD_CAST "step_value", BAD_CAST toString( _StepValue ).c_str() ); xmlSetProp( node, BAD_CAST "cancelable", BAD_CAST toString( _Cancelable ).c_str() ); + xmlSetProp( node, BAD_CAST "keyboard", BAD_CAST toString( _Keyboard ).c_str() ); xmlSetProp( node, BAD_CAST "frozen", BAD_CAST toString( _Frozen ).c_str() ); return node; @@ -589,6 +604,9 @@ namespace NLGUI prop = (char*) xmlGetProp( node, (xmlChar*)"cancelable" ); if (prop) _Cancelable = convertBool(prop); + prop = (char*) xmlGetProp( node, (xmlChar*)"keyboard" ); + if (prop) _Keyboard = convertBool(prop); + prop= (char*) xmlGetProp (node, (xmlChar*)"frozen"); _Frozen = false; if (prop) @@ -854,6 +872,7 @@ namespace NLGUI if (CCtrlBase::handleEvent(event)) return true; if (!_Active || _Frozen) return false; + if (event.getType() == NLGUI::CEventDescriptor::mouse) { const NLGUI::CEventDescriptorMouse &eventDesc = (const NLGUI::CEventDescriptorMouse &)event; @@ -912,6 +931,30 @@ namespace NLGUI return true; } } + else if (event.getType() == NLGUI::CEventDescriptor::key) + { + const NLGUI::CEventDescriptorKey &eventDesc = (const NLGUI::CEventDescriptorKey &)event; + + if (eventDesc.getKeyEventType() == NLGUI::CEventDescriptorKey::keydown) + { + if (_Keyboard) + { + sint32 i = 0; + // direction + if (eventDesc.getKey() == KeyNEXT) i++; + else if (eventDesc.getKey() == KeyPRIOR) i--; + else + return false; + + if (_Vertical) + moveTrackY(-(i * _TargetStepY)); + else + moveTrackX(-(i * _TargetStepX)); + + return true; + } + } + } return false; } @@ -1213,6 +1256,7 @@ namespace NLGUI if(wReal <= maxWReal) return; + // compute the new ofsX. sint32 ofsX= _Target->getOfsX(); ofsX+= dx; diff --git a/nel/src/gui/ctrl_text_button.cpp b/nel/src/gui/ctrl_text_button.cpp index de01174ed..d7902c166 100644 --- a/nel/src/gui/ctrl_text_button.cpp +++ b/nel/src/gui/ctrl_text_button.cpp @@ -1077,6 +1077,69 @@ namespace NLGUI // *************************************************************************** + void CCtrlTextButton::setTextureLua(const std::string &name) + { + _TextureIdNormal[0].setTexture(std::string(name + "_l.tga").c_str()); + _TextureIdNormal[1].setTexture(std::string(name + "_m.tga").c_str()); + _TextureIdNormal[2].setTexture(std::string(name + "_r.tga").c_str()); + } + + // *************************************************************************** + + void CCtrlTextButton::setTexturePushedLua(const std::string &name) + { + _TextureIdPushed[0].setTexture(std::string(name + "_l.tga").c_str()); + _TextureIdPushed[1].setTexture(std::string(name + "_m.tga").c_str()); + _TextureIdPushed[2].setTexture(std::string(name + "_r.tga").c_str()); + } + + // *************************************************************************** + + void CCtrlTextButton::setTextureOverLua(const std::string &name) + { + _TextureIdOver[0].setTexture(std::string(name + "_l.tga").c_str()); + _TextureIdOver[1].setTexture(std::string(name + "_m.tga").c_str()); + _TextureIdOver[2].setTexture(std::string(name + "_r.tga").c_str()); + } + + // *************************************************************************** + + std::string CCtrlTextButton::getTexture() const + { + std::string tx = CViewRenderer::getInstance()->getTextureNameFromId(_TextureIdNormal[0]); + std::string::size_type i = tx.rfind("_l.tga"); + if (i != std::string::npos) + tx = tx.substr(0, i); + + return tx; + } + + // *************************************************************************** + + std::string CCtrlTextButton::getTexturePushed() const + { + std::string tx = CViewRenderer::getInstance()->getTextureNameFromId(_TextureIdOver[0]); + std::string::size_type i = tx.rfind("_l.tga"); + if (i != std::string::npos) + tx = tx.substr(0, i); + + return tx; + } + + // *************************************************************************** + + std::string CCtrlTextButton::getTextureOver() const + { + std::string tx = CViewRenderer::getInstance()->getTextureNameFromId(_TextureIdPushed[0]); + std::string::size_type i = tx.rfind("_l.tga"); + if (i != std::string::npos) + tx = tx.substr(0, i); + + return tx; + } + + // *************************************************************************** + int CCtrlTextButton::luaGetViewText(CLuaState &ls) { const char *funcName = "getViewText"; diff --git a/nel/src/gui/view_renderer.cpp b/nel/src/gui/view_renderer.cpp index 82716de4a..6a7d86eef 100644 --- a/nel/src/gui/view_renderer.cpp +++ b/nel/src/gui/view_renderer.cpp @@ -621,9 +621,7 @@ namespace NLGUI return; sint32 txw, txh; - SImage &rImage = *getSImage(nTxId); - txw = (sint32)((rImage.UVMax.U - rImage.UVMin.U)*rImage.GlobalTexturePtr->Width+0.5f); - txh = (sint32)((rImage.UVMax.V - rImage.UVMin.V)*rImage.GlobalTexturePtr->Height+0.5f); + getTextureSizeFromId(nTxId, txw, txh); drawRotFlipBitmap (layerId, x, y, txw, txh, rot, flipv, nTxId, col); } @@ -859,6 +857,14 @@ namespace NLGUI CIFile ifTmp; if (ifTmp.open(filename)) CBitmap::loadSize (ifTmp, gt.Width, gt.Height); + + // extract textures scale from filename + // texture_interface_v3_2x.tga / texture_interface_v3_4x.tga + if (textureFileName.find("_2x.") != std::string::npos) + gt.Scale = 2.f; + else if (textureFileName.find("_4x.") != std::string::npos) + gt.Scale = 4.f; + gt.Texture = driver->createTextureFile (filename); // Force to generate the texture now. This way we can extract the mouse bitmaps from it now without having to load it again. // Its why we don't release it at the end, because it is likely to be uploaded soon) @@ -932,6 +938,10 @@ namespace NLGUI CBitmap curs; curs.resize(x1 - x0, y1 - y0); curs.blit(*texDatas, x0, y0, (x1 - x0), (y1 - y0), 0, 0); + // TODO: scaled cursors not supported + if (gt.Scale > 1.f) { + curs.resample((sint)(curs.getWidth() / gt.Scale), (sint)(curs.getHeight() / gt.Scale)); + } driver->addCursor(image.Name, curs); } } @@ -1357,8 +1367,8 @@ namespace NLGUI else { SImage &rImage = *getSImage(id); - width = (sint32)((rImage.UVMax.U - rImage.UVMin.U)*rImage.GlobalTexturePtr->Width+0.5f); - height = (sint32)((rImage.UVMax.V - rImage.UVMin.V)*rImage.GlobalTexturePtr->Height+0.5f); + width = (sint32)(((rImage.UVMax.U - rImage.UVMin.U)*rImage.GlobalTexturePtr->Width / rImage.GlobalTexturePtr->Scale)+0.5f); + height = (sint32)(((rImage.UVMax.V - rImage.UVMin.V)*rImage.GlobalTexturePtr->Height / rImage.GlobalTexturePtr->Scale)+0.5f); } } /* @@ -1373,9 +1383,11 @@ namespace NLGUI SImage &rImage = *getSImage(id); SGlobalTexture &rGT = *rImage.GlobalTexturePtr; + // get (possibly) scaled width/height sint32 width, height; - width = (sint32)((rImage.UVMax.U - rImage.UVMin.U)*rGT.Width+0.5f); - height = (sint32)((rImage.UVMax.V - rImage.UVMin.V)*rGT.Height+0.5f); + getTextureSizeFromId(id, width, height); + if (width == 0 || height == 0) + return CRGBA(255,255,255); float xRatio = ((float)x) / ((float)(width)); float yRatio = ((float)y) / ((float)(height)); UTexture *pTF = rGT.Texture; diff --git a/nel/src/gui/widget_manager.cpp b/nel/src/gui/widget_manager.cpp index 864e4ef5b..a1da03b2e 100644 --- a/nel/src/gui/widget_manager.cpp +++ b/nel/src/gui/widget_manager.cpp @@ -2296,7 +2296,7 @@ namespace NLGUI // Hide menu if the key is pushed // if ((eventDesc.getKeyEventType() == CEventDescriptorKey::keydown) && !_ModalStack.empty() && !eventDesc.getKeyAlt() && !eventDesc.getKeyCtrl() && !eventDesc.getKeyShift()) // Hide menu (or popup menu) is ESCAPE pressed - if( eventDesc.getKeyEventType() == CEventDescriptorKey::keychar && eventDesc.getChar() == NLMISC::KeyESCAPE ) + if( eventDesc.getKeyEventType() == CEventDescriptorKey::keydown && eventDesc.getKey() == NLMISC::KeyESCAPE ) { if( hasModal() ) { @@ -2307,7 +2307,7 @@ namespace NLGUI } // Manage "quit window" If the Key is ESCAPE, no captureKeyboard - if( eventDesc.getKeyEventType() == CEventDescriptorKey::keychar && eventDesc.getChar() == NLMISC::KeyESCAPE ) + if( eventDesc.getKeyEventType() == CEventDescriptorKey::keydown && eventDesc.getKey() == NLMISC::KeyESCAPE ) { // Get the last escapable active top window. NB: this is ergonomically better. CInterfaceGroup *win= getLastEscapableTopWindow(); diff --git a/ryzom/client/CMakeLists.txt b/ryzom/client/CMakeLists.txt index 7a6cf7424..2e17c230e 100644 --- a/ryzom/client/CMakeLists.txt +++ b/ryzom/client/CMakeLists.txt @@ -8,7 +8,7 @@ IF(WITH_RYZOM_CLIENT) ADD_SUBDIRECTORY(unix) ENDIF() - INSTALL(FILES client_default.cfg DESTINATION ${RYZOM_ETC_PREFIX}) + #INSTALL(FILES client_default.cfg DESTINATION ${RYZOM_ETC_PREFIX}) IF(WITH_RYZOM_PATCH) IF(APPLE) diff --git a/ryzom/client/src/CMakeLists.txt b/ryzom/client/src/CMakeLists.txt index 99b9a6773..7e1f89348 100644 --- a/ryzom/client/src/CMakeLists.txt +++ b/ryzom/client/src/CMakeLists.txt @@ -82,7 +82,7 @@ IF(WITH_RYZOM_CLIENT) ADD_CUSTOM_COMMAND(TARGET ryzom_client PRE_BUILD COMMAND mkdir -p ${RYZOM_RESOURCES_DIR}) ADD_CUSTOM_COMMAND(TARGET ryzom_client POST_BUILD COMMAND cp ARGS -p ${MAC_RESOURCES_DIR}/PkgInfo ${RYZOM_CONTENTS_DIR}) ADD_CUSTOM_COMMAND(TARGET ryzom_client POST_BUILD COMMAND cp ARGS -p ${MAC_RESOURCES_DIR}/ryzom.icns ${RYZOM_RESOURCES_DIR}) - ADD_CUSTOM_COMMAND(TARGET ryzom_client POST_BUILD COMMAND cp ARGS -p ${CMAKE_SOURCE_DIR}/ryzom/client/client_default.cfg ${RYZOM_RESOURCES_DIR}) + #ADD_CUSTOM_COMMAND(TARGET ryzom_client POST_BUILD COMMAND cp ARGS -p ${CMAKE_SOURCE_DIR}/ryzom/client/client_default.cfg ${RYZOM_RESOURCES_DIR}) # remove any present installscript_osx.vdf before signing ADD_CUSTOM_COMMAND(TARGET ryzom_client POST_BUILD COMMAND rm -f ${RYZOM_OUTPUT_DIR}/installscript_osx.vdf) diff --git a/ryzom/client/src/client_cfg.cpp b/ryzom/client/src/client_cfg.cpp index fae93c3fb..9d030cdca 100644 --- a/ryzom/client/src/client_cfg.cpp +++ b/ryzom/client/src/client_cfg.cpp @@ -439,8 +439,8 @@ CClientConfig::CClientConfig() CurlMaxConnections = 5; CurlCABundle.clear(); - RingReleaseNotePath = WebIgMainDomain + "/releasenotes_ring/index.php"; - ReleaseNotePath = WebIgMainDomain + "/releasenotes/index.php"; + RingReleaseNotePath = WebIgMainDomain + "/app_releasenotes/index.php"; + ReleaseNotePath = WebIgMainDomain + "/app_releasenotes/index.php"; /////////////// diff --git a/ryzom/client/src/connection.cpp b/ryzom/client/src/connection.cpp index 7c746499d..ee1be3318 100644 --- a/ryzom/client/src/connection.cpp +++ b/ryzom/client/src/connection.cpp @@ -33,6 +33,7 @@ #include "nel/misc/time_nl.h" #include "nel/misc/algo.h" #include "nel/misc/system_utils.h" +#include "nel/misc/stream.h" // 3D Interface. #include "nel/3d/u_driver.h" #include "nel/3d/u_text_context.h" @@ -149,6 +150,7 @@ ucstring PlayerSelectedHomeShardName; ucstring PlayerSelectedHomeShardNameWithParenthesis; extern std::string CurrentCookie; + ucstring NewKeysCharNameWanted; // name of the character for which a new keyset must be created ucstring NewKeysCharNameValidated; std::string GameKeySet = "keys.xml"; @@ -157,9 +159,11 @@ std::string RingEditorKeySet = "keys_r2ed.xml"; string ScenarioFileName; sint LoginCharsel = -1; -static const char *KeySetVarName = "BuiltInKeySets"; +std::string ImportCharacter; +static const char *KeySetVarName = "BuiltInKeySets"; +#define GROUP_LIST_CHARACTER "ui:outgame:charsel_import:import_list" #define GROUP_LIST_MAINLAND "ui:outgame:appear_mainland:mainland_list" #define GROUP_LIST_KEYSET "ui:outgame:appear_keyset:keyset_list" vector Mainlands; @@ -2139,7 +2143,7 @@ public: virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */) { - CInterfaceManager *pIM = CInterfaceManager::getInstance(); + //CInterfaceManager *pIM = CInterfaceManager::getInstance(); CInterfaceGroup *pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND)); if (pList == NULL) @@ -2218,7 +2222,7 @@ public: virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */) { - CInterfaceManager *pIM = CInterfaceManager::getInstance(); + //CInterfaceManager *pIM = CInterfaceManager::getInstance(); CInterfaceGroup *pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND)); pList->clearGroups(); } @@ -2229,32 +2233,56 @@ REGISTER_ACTION_HANDLER (CAHResetMainlandList, "reset_mainland_list"); // *************************************************************************** class CAHMainlandSelect : public IActionHandler { - virtual void execute (CCtrlBase *pCaller, const string &/* Params */) + virtual void execute (CCtrlBase *pCaller, const std::string &Params) { - nlinfo("CAHMainlandSelect called"); - - CInterfaceManager *pIM = CInterfaceManager::getInstance(); + //nlinfo("CAHMainlandSelect called"); + struct CUnpush : public CInterfaceElementVisitor + { + CCtrlBase *Ref; + virtual void visitCtrl(CCtrlBase *ctrl) + { + if (ctrl == Ref) return; + CCtrlBaseButton *but = dynamic_cast(ctrl); + if (but) + { + but->setPushed(false); + } + } + }; + CInterfaceGroup *list = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND)); + if (!list) + return; - CCtrlButton *pCB = NULL; - // Unselect - if (MainlandSelected.asInt() != 0) + // unselect + if (Params.empty()) { - pCB = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND ":"+toString(MainlandSelected)+":but")); - if (pCB != NULL) - pCB->setPushed(false); + CUnpush unpusher; + unpusher.Ref = pCaller; + list->visit(&unpusher); } - pCB = dynamic_cast(pCaller); - if (pCB != NULL) + // now select + uint32 mainland; + if (Params.empty()) { - string name = pCB->getId(); - name = name.substr(0,name.rfind(':')); - uint32 mainland; - fromString(name.substr(name.rfind(':')+1,name.size()), mainland); - MainlandSelected = (TSessionId)mainland; + CCtrlButton *pCB = dynamic_cast(pCaller); + if (!pCB) + return; + + std::string name = pCB->getId(); + name = name.substr(0, name.rfind(':')); + + if (!fromString(name.substr(name.rfind(':')+1, name.size()), mainland)) + return; pCB->setPushed(true); } + else + if (!fromString(Params, mainland)) + return; + + // and store + MainlandSelected = (TSessionId)mainland; } }; REGISTER_ACTION_HANDLER (CAHMainlandSelect, "mainland_select"); @@ -2459,7 +2487,7 @@ public: virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */) { - CInterfaceManager *pIM = CInterfaceManager::getInstance(); + //CInterfaceManager *pIM = CInterfaceManager::getInstance(); CInterfaceGroup *pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_KEYSET)); pList->clearGroups(); } @@ -2470,59 +2498,66 @@ REGISTER_ACTION_HANDLER (CAHResetKeysetList, "reset_keyset_list"); // *************************************************************************** class CAHResetKeysetSelect : public IActionHandler { -public: std::string getIdPostFix(const std::string fullId) { std::string::size_type pos = fullId.find_last_of(":"); if (pos != std::string::npos) - { return fullId.substr(pos + 1); - } + return ""; } - virtual void execute (CCtrlBase *pCaller, const string &/* Params */) + + virtual void execute(CCtrlBase *pCaller, const std::string &Params) { - if (!pCaller) return; // 'unpush' all groups but the caller - // struct CUnpush : public CInterfaceElementVisitor { CCtrlBase *Ref; virtual void visitCtrl(CCtrlBase *ctrl) { if (ctrl == Ref) return; - CCtrlBaseButton *but = dynamic_cast(ctrl); + CCtrlBaseButton *but = dynamic_cast(ctrl); if (but) { but->setPushed(false); } } }; - CInterfaceManager *pIM = CInterfaceManager::getInstance(); - CInterfaceGroup * list = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_KEYSET)); - if (list) - { - CUnpush unpusher; - unpusher.Ref = pCaller; - list->visit(&unpusher); - } - CCtrlBaseButton *but = dynamic_cast(pCaller); + CInterfaceGroup *list = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_KEYSET)); + if (!list) + return; + + // unselect + CUnpush unpusher; + unpusher.Ref = pCaller; + list->visit(&unpusher); + + // now select + CCtrlBaseButton *but = dynamic_cast(pCaller); if (but) - { but->setPushed(true); + + std::string id; + if (Params.empty()) + { + if (!pCaller) return; + if (!pCaller->getParent()) return; + + id = getIdPostFix(pCaller->getParent()->getId()); } - // + else + id = getIdPostFix(Params); + GameKeySet = "keys.xml"; RingEditorKeySet = "keys_r2ed.xml"; - if (!pCaller->getParent()) return; - // compute the 2 filenames from the id - // if id is in the built-in keysets : + + // compute the two filenames from the id + // if id is in the built-in keysets CConfigFile::CVar *keySetVar = ClientCfg.ConfigFile.getVarPtr(KeySetVarName); - if (keySetVar && keySetVar->size() != 0) + if (keySetVar && keySetVar->size() > 0) { for (uint k = 0; k < keySetVar->size(); ++k) { - std::string id = getIdPostFix(pCaller->getParent()->getId()); if (keySetVar->asString(k) == id) { GameKeySet = "keys" + string(id.empty() ? "" : "_") + id + ".xml"; @@ -2531,17 +2566,15 @@ public: } } } - // ... else maybe from a previous character ? - if (CFile::isExists("save/keys_" + getIdPostFix(pCaller->getParent()->getId()) + ".xml") ) - { - GameKeySet = "keys_" + getIdPostFix(pCaller->getParent()->getId()) + ".xml"; - } - if (CFile::isExists("save/keys_r2ed_" + getIdPostFix(pCaller->getParent()->getId()) + ".xml") ) - { - RingEditorKeySet = "keys_r2ed_" + getIdPostFix(pCaller->getParent()->getId()) + ".xml"; - } - // NB : key file will be copied for real when the new 'character summary' is + // else maybe from a previous character? + if (CFile::isExists("save/keys_" + id + ".xml")) + GameKeySet = "keys_" + id + ".xml"; + + if (CFile::isExists("save/keys_r2ed_" + id + ".xml")) + RingEditorKeySet = "keys_r2ed_" + id + ".xml"; + + // NB: key file will be copied for real when the new character summary is } }; REGISTER_ACTION_HANDLER (CAHResetKeysetSelect, "keyset_select"); @@ -3436,3 +3469,239 @@ class CAHOpenRingSessions : public IActionHandler } }; REGISTER_ACTION_HANDLER (CAHOpenRingSessions, "open_ring_sessions"); + +// *************************************************************************** +class CAHInitImportCharacter : public IActionHandler +{ + virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */) + { + CInterfaceGroup *list = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CHARACTER)); + if (!list) + { + nlwarning("element " GROUP_LIST_CHARACTER " not found probably bad outgame.xml"); + return; + } + + // retrieve saved files + std::vector savedCharacters; + CPath::getPathContent("save/", false, false, true, savedCharacters); + + CInterfaceGroup *newLine; + CInterfaceGroup *prevLine; + + for (uint i = 0; i < savedCharacters.size(); ++i) + { + // search saved characters only + if (testWildCard(CFile::getFilename(savedCharacters[i]), "character_*.save")) + { + const std::string id = CFile::getFilenameWithoutExtension(savedCharacters[i]).substr(strlen("character_")); + if (id.empty()) + continue; + + std::vector> params; + params.clear(); + params.push_back(std::pair("id", id)); + // adjust ref + if (list->getNumGroup() > 0) + params.push_back(std::pair("posref", "BL TL")); + + newLine = CWidgetManager::getInstance()->getParser()->createGroupInstance("t_import", GROUP_LIST_CHARACTER, params); + if (newLine) + { + CViewText *text = dynamic_cast(newLine->getView("name")); + if (text) + text->setText(ucstring(savedCharacters[i])); + + // first button is pushed + CCtrlButton *button = dynamic_cast(newLine->getCtrl("but")); + if (button && list->getNumGroup() == 0) + button->setPushed(true); + + // add to the list now + newLine->setParent(list); + newLine->setParentSize(list); + newLine->setParentPos(prevLine); + + list->addGroup(newLine); + + prevLine = newLine; + } + } + } + // none case + if (list->getNumGroup() == 0) + CLuaManager::getInstance().executeLuaScript("outgame:procCharselNotifaction(3)"); + + list->invalidateCoords(); + } +}; +REGISTER_ACTION_HANDLER( CAHInitImportCharacter, "import_char_init" ); + +// *************************************************************************** +class CAHResetImportCharacter : public IActionHandler +{ + virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */) + { + CInterfaceGroup *list = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CHARACTER)); + if (list) + list->clearGroups(); + + if (!ImportCharacter.empty()) + ImportCharacter = ""; + } +}; +REGISTER_ACTION_HANDLER( CAHResetImportCharacter, "import_char_reset" ); + +// *************************************************************************** +class CAHSelectImportCharacter : public IActionHandler +{ + virtual void execute (CCtrlBase *pCaller, const std::string &Params) + { + struct CUnpush : public CInterfaceElementVisitor + { + CCtrlBase *Ref; + virtual void visitCtrl(CCtrlBase *ctrl) + { + if (ctrl == Ref) return; + CCtrlBaseButton *but = dynamic_cast(ctrl); + if (but) + { + but->setPushed(false); + } + } + }; + CInterfaceGroup *list = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CHARACTER)); + if (!list) + return; + + // unselect + if (Params.empty()) + { + CUnpush unpusher; + unpusher.Ref = pCaller; + list->visit(&unpusher); + } + + // now select + std::string name; + if (Params.empty()) + { + CCtrlButton *pCB = dynamic_cast(pCaller); + if (!pCB) + return; + + std::string id = pCB->getId(); + id = id.substr(0, id.rfind(':')); + + if (!fromString(id.substr(id.rfind(':')+1, id.size()), name)) + return; + + pCB->setPushed(true); + } + else + if (!fromString(Params, name)) + return; + + ImportCharacter = ""; + // check filename and store + if (CFile::fileExists(toString("save/character_%s.save", name.c_str()))) + ImportCharacter = name; + } +}; +REGISTER_ACTION_HANDLER( CAHSelectImportCharacter, "import_char_select" ); + +// *************************************************************************** +class CAHImportCharacter : public IActionHandler +{ + virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */) + { + if (ImportCharacter.empty()) + return; + + if (!CFile::fileExists(toString("save/character_%s.save", ImportCharacter.c_str()))) + return; + + bool success = false; + + CIFile fd; + CCharacterSummary CS; + // use temporary file until close() + if (fd.open(toString("save/character_%s.save", ImportCharacter.c_str()))) + { + try + { + CS.serial(fd); + SCharacter3DSetup::setupDBFromCharacterSummary("UI:TEMP:CHAR3D", CS); + + // validate import + CDBManager::getInstance()->getDbProp("UI:TEMP:IMPORT")->setValue32(1); + success = true; + } + catch (const EStream &e) + { + nlwarning(e.what()); + } + fd.close(); + } + else + nlwarning("Failed to open file: save/character_%s.save", ImportCharacter.c_str()); + + // user notification + if (!success) + CLuaManager::getInstance().executeLuaScript("outgame:procCharselNotifaction(2)"); + else + CAHManager::getInstance()->runActionHandler("proc", NULL, "proc_charsel_create_new"); + } +}; +REGISTER_ACTION_HANDLER( CAHImportCharacter, "import_char" ); + +// *************************************************************************** +class CAHExportCharacter : public IActionHandler +{ + virtual void execute (CCtrlBase * /* pCaller */, const std::string &Params) + { + if (Params.empty()) + return; + + sint32 slot = -1; + if (!fromString(getParam(Params, "slot"), slot)) + return; + + if (slot >= CharacterSummaries.size() || slot < 0) + return; + + // retrieve infos + CCharacterSummary &CS = CharacterSummaries[slot]; + if (CS.Name.empty()) + return; + + // extract name + const std::string name = buildPlayerNameForSaveFile(CS.Name.toString()); + + COFile fd; + bool success = false; + // use temporary file until close() + if (fd.open(toString("save/character_%s.save", name.c_str()), false, false, true)) + { + try + { + fd.serial(CS); + fd.flush(); + // validate + success = true; + } + catch (const EStream &e) + { + nlwarning(e.what()); + } + fd.close(); + } + else + nlwarning("Failed to open file: save/character_%s.save", name.c_str()); + + const uint8 val = (success == true) ? 0 : 1; + // user notification + CLuaManager::getInstance().executeLuaScript(toString("outgame:procCharselNotifaction(%i)", val)); + } +}; +REGISTER_ACTION_HANDLER( CAHExportCharacter, "export_char" ); diff --git a/ryzom/client/src/events_listener.cpp b/ryzom/client/src/events_listener.cpp index 879bd5a2a..cfa9d2b3c 100644 --- a/ryzom/client/src/events_listener.cpp +++ b/ryzom/client/src/events_listener.cpp @@ -172,16 +172,12 @@ void CEventsListener::operator()(const CEvent& event) // Get in pixel space, centered uint32 drW, drH; Driver->getWindowSize(drW, drH); - float fX = mouseEvent->X; // from 0 to 1.0 - float fY = (ClientCfg.FreeLookInverted ? -mouseEvent->Y : mouseEvent->Y); - sint scX = (sint32)(fX * (float)drW) - ((sint32)drW >> 1); // in pixels, centered - sint scY = (sint32)(fY * (float)drH) - ((sint32)drH >> 1); + sint scX = (sint32)(mouseEvent->X * (float)drW) - ((sint32)drW >> 1); // in pixels, centered + sint scY = (sint32)(mouseEvent->Y * (float)drH) - ((sint32)drH >> 1); if (!s_MouseFreeLookReady) { - float pfX = _MouseX; - float pfY = (ClientCfg.FreeLookInverted ? -_MouseY : _MouseY); - sint pscX = (sint32)(pfX * (float)drW) - ((sint32)drW >> 1); // in pixels, centered - sint pscY = (sint32)(pfY * (float)drH) - ((sint32)drH >> 1); + sint pscX = (sint32)(_MouseX * (float)drW) - ((sint32)drW >> 1); // in pixels, centered + sint pscY = (sint32)(_MouseY * (float)drH) - ((sint32)drH >> 1); s_MouseFreeLookReady = true; s_MouseFreeLookLastX = pscX; s_MouseFreeLookLastY = pscY; @@ -199,13 +195,12 @@ void CEventsListener::operator()(const CEvent& event) } // Get delta since last center - sint scXd = scX - s_MouseFreeLookLastX; - sint scYd = scY - s_MouseFreeLookLastY; + s_MouseFreeLookFrameX += (scX - s_MouseFreeLookLastX); + s_MouseFreeLookFrameY += (scY - s_MouseFreeLookLastY) * (ClientCfg.FreeLookInverted ? -1 : 1); + s_MouseFreeLookLastX = scX; s_MouseFreeLookLastY = scY; - s_MouseFreeLookFrameX += scXd; - s_MouseFreeLookFrameY += scYd; // updateFreeLookPos is called in updateMouseSmoothing per frame // Center cursor diff --git a/ryzom/client/src/game_context_menu.cpp b/ryzom/client/src/game_context_menu.cpp index c19ea62ac..78e58c4b5 100644 --- a/ryzom/client/src/game_context_menu.cpp +++ b/ryzom/client/src/game_context_menu.cpp @@ -451,18 +451,19 @@ void CGameContextMenu::update() else if (continent == "lepaysmalade.continent") fameIndex = CStaticFames::getInstance().getFactionIndex("zorai"); - + if (fameIndex != CStaticFames::INVALID_FACTION_INDEX) { CCDBNodeLeaf *pLeafFame = NLGUI::CDBManager::getInstance()->getDbProp(toString("SERVER:FAME:PLAYER%d:VALUE", fameIndex), false); if (pLeafFame != NULL) fameValue = pLeafFame->getValue8(); } + if (_TextNews) - _TextNews->setActive(selection && !canAttack() && selection->isNPC() && fameValue >= -30); + _TextNews->setActive(!UserEntity->isFighting() && !UserEntity->isRiding() && selection && !canAttack() && selection->isNPC() && fameValue >= -30); if (_TextNewsAgressive) - _TextNewsAgressive->setActive(selection && !canAttack() && selection->isNPC() && fameValue < -30); + _TextNewsAgressive->setActive(!UserEntity->isFighting() && !UserEntity->isRiding() && selection && !canAttack() && selection->isNPC() && fameValue < -30); if (_TextDuel && _TextUnDuel) diff --git a/ryzom/client/src/interface_v3/action_handler_game.cpp b/ryzom/client/src/interface_v3/action_handler_game.cpp index 58c00421b..3e3ce9b8e 100644 --- a/ryzom/client/src/interface_v3/action_handler_game.cpp +++ b/ryzom/client/src/interface_v3/action_handler_game.cpp @@ -4655,6 +4655,45 @@ public: }; REGISTER_ACTION_HANDLER( CHandlerSortTribeFame, "sort_tribefame"); +// *************************************************************************** +class CHandlerOutgameNaviGetKeys : public IActionHandler +{ + virtual void execute (CCtrlBase *pCaller, const std::string &Params) + { + if (!pCaller->getParent()) + return; + + if (pCaller->getParent()->getId() != "ui:outgame") + return; + + if (Params.empty()) + { + sint32 event = -1; + + if (Driver->AsyncListener.isKeyPushed(KeyESCAPE)) event = 0; + if (Driver->AsyncListener.isKeyPushed(KeyDELETE)) event = 1; + if (Driver->AsyncListener.isKeyPushed(KeyRETURN)) event = 2; + if (Driver->AsyncListener.isKeyPushed(KeyDOWN)) event = 3; + if (Driver->AsyncListener.isKeyPushed(KeyUP)) event = 4; + if (Driver->AsyncListener.isKeyPushed(KeyI)) event = 5; + if (Driver->AsyncListener.isKeyPushed(KeyP)) event = 6; + if (Driver->AsyncListener.isKeyPushed(KeyE)) event = 7; + if (Driver->AsyncListener.isKeyPushed(KeyLEFT)) event = 8; + if (Driver->AsyncListener.isKeyPushed(KeyRIGHT)) event = 9; + + std::string id = "create"; + if (pCaller->getId() == "ui:outgame:charsel") + id = "sel"; + + if (event != -1) +- CLuaManager::getInstance().executeLuaScript(toString("outgame:eventChar%sKeyGet(%i)", id.c_str(), event)); + } + // reset previous input + Driver->AsyncListener.reset(); + } +}; +REGISTER_ACTION_HANDLER( CHandlerOutgameNaviGetKeys, "navigate_outgame" ); + // *************************************************************************** class CHandlerTriggerIconBuffs : public IActionHandler { diff --git a/ryzom/client/src/interface_v3/action_handler_phrase.cpp b/ryzom/client/src/interface_v3/action_handler_phrase.cpp index 0e5ba0c48..b18e348e5 100644 --- a/ryzom/client/src/interface_v3/action_handler_phrase.cpp +++ b/ryzom/client/src/interface_v3/action_handler_phrase.cpp @@ -136,7 +136,7 @@ public: if (pCSDst->isShortCut()) pPM->CompositionPhraseMemoryLineDest= pPM->getSelectedMemoryLineDB(); else - pPM->CompositionPhraseMemoryLineDest= 0; + pPM->CompositionPhraseMemoryLineDest= pPM->getSelectedMemoryAltLineDB(); pPM->CompositionPhraseMemorySlotDest= pCSDst->getIndexInDB(); } @@ -536,7 +536,7 @@ public: CInterfaceManager *pIM= CInterfaceManager::getInstance(); // Launch the modal to select the faber plan - extern void fillFaberPlanSelection(const std::string &brickDB, uint maxSelection, TOOL_TYPE::TCraftingToolType toolType); + extern void fillFaberPlanSelection(const std::string &brickDB, uint maxSelection, TOOL_TYPE::TCraftingToolType toolType); // from sphrase_manager.cpp extern TOOL_TYPE::TCraftingToolType getRightHandCraftToolType(); fillFaberPlanSelection(CDBGroupBuildPhrase::BrickSelectionDB, CDBGroupBuildPhrase::MaxSelection, getRightHandCraftToolType()); @@ -750,8 +750,8 @@ class CHandlerMemorizePhraseOrMacro : public IActionHandler { public: virtual void execute (CCtrlBase *pCaller, const string &Params); - void memorizePhraseOrMacro(uint dstMemoryIndex, bool isMacro, sint32 phraseId, sint32 macroId); - void memorizePhraseSheet(uint dstMemoryIndex, uint32 sheetId); + void memorizePhraseOrMacro(sint32 memoryLine, uint dstMemoryIndex, bool isMacro, sint32 phraseId, sint32 macroId); + void memorizePhraseSheet(sint32 memoryLine, uint dstMemoryIndex, uint32 sheetId); }; REGISTER_ACTION_HANDLER( CHandlerMemorizePhraseOrMacro, "memorize_phrase_or_macro"); @@ -771,7 +771,11 @@ void CHandlerMemorizePhraseOrMacro::execute (CCtrlBase *pCaller, const string &P // The dest must be a memory or a macro memory if (!pCSDst->isSPhraseIdMemory() && !pCSDst->isMacroMemory()) return; // get the memory line and memory index - sint32 dstMemoryLine= pPM->getSelectedMemoryLineDB(); + sint32 dstMemoryLine; + if (pCSDst->isShortCut()) + dstMemoryLine = pPM->getSelectedMemoryLineDB(); + else + dstMemoryLine = pPM->getSelectedMemoryAltLineDB(); uint dstMemoryIndex= pCSDst->getIndexInDB(); bool srcIsMacro; @@ -806,7 +810,7 @@ void CHandlerMemorizePhraseOrMacro::execute (CCtrlBase *pCaller, const string &P pPM->sendLearnToServer(newPhraseId); // memorize the new phrase - memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, newPhraseId, srcMacroId); + memorizePhraseOrMacro(dstMemoryLine, dstMemoryIndex, srcIsMacro, newPhraseId, srcMacroId); } } else @@ -833,7 +837,7 @@ void CHandlerMemorizePhraseOrMacro::execute (CCtrlBase *pCaller, const string &P if(pCSSrc->isSPhrase()) { // learn and memorize this phrase - memorizePhraseSheet(dstMemoryIndex, pCSSrc->getSheetId()); + memorizePhraseSheet(dstMemoryLine, dstMemoryIndex, pCSSrc->getSheetId()); } else { @@ -842,7 +846,7 @@ void CHandlerMemorizePhraseOrMacro::execute (CCtrlBase *pCaller, const string &P pPM->fullDeletePhraseIfLast(dstMemoryLine, dstMemoryIndex); // memorize the phrase or macro - memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId); + memorizePhraseOrMacro(dstMemoryLine, dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId); } } // Else the src is a memory too @@ -868,7 +872,7 @@ void CHandlerMemorizePhraseOrMacro::execute (CCtrlBase *pCaller, const string &P pPM->sendLearnToServer(newPhraseId); // memorize the new phrase - memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, newPhraseId, srcMacroId); + memorizePhraseOrMacro(dstMemoryLine, dstMemoryIndex, srcIsMacro, newPhraseId, srcMacroId); } else { @@ -876,7 +880,7 @@ void CHandlerMemorizePhraseOrMacro::execute (CCtrlBase *pCaller, const string &P pPM->fullDeletePhraseIfLast(dstMemoryLine, dstMemoryIndex); // memorize the macro (still a reference) - memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId); + memorizePhraseOrMacro(dstMemoryLine, dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId); } } // else this is a swap! @@ -887,17 +891,23 @@ void CHandlerMemorizePhraseOrMacro::execute (CCtrlBase *pCaller, const string &P { // get the memory index for src uint srcMemoryIndex= pCSSrc->getIndexInDB(); - + // get the memory line for src + sint32 srcMemoryLine; + if (pCSSrc->isShortCut()) + srcMemoryLine = pPM->getSelectedMemoryLineDB(); + else + srcMemoryLine = pPM->getSelectedMemoryAltLineDB(); + // memorize dst into src - memorizePhraseOrMacro(srcMemoryIndex, dstIsMacro, dstPhraseId, dstMacroId); + memorizePhraseOrMacro(srcMemoryLine, srcMemoryIndex, dstIsMacro, dstPhraseId, dstMacroId); // memorize src into dst - memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId); + memorizePhraseOrMacro(dstMemoryLine, dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId); } // else, it's a move else { // copy - memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId); + memorizePhraseOrMacro(dstMemoryLine, dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId); // forget src (after shorctut change!) CAHManager::getInstance()->runActionHandler("forget_phrase_or_macro", pCSSrc); @@ -909,14 +919,13 @@ void CHandlerMemorizePhraseOrMacro::execute (CCtrlBase *pCaller, const string &P // memorize a spell -void CHandlerMemorizePhraseOrMacro::memorizePhraseOrMacro(uint memoryIndex, bool isMacro, sint32 phraseId, sint32 macroId) +void CHandlerMemorizePhraseOrMacro::memorizePhraseOrMacro(sint32 memoryLine, uint memoryIndex, bool isMacro, sint32 phraseId, sint32 macroId) { CSPhraseManager *pPM= CSPhraseManager::getInstance(); - sint32 memoryLine= pPM->getSelectedMemoryLineDB(); - if(memoryLine<0) - return; - + if (memoryLine<0) + return; + if(isMacro) { pPM->memorizeMacro(memoryLine, memoryIndex, macroId); @@ -931,11 +940,10 @@ void CHandlerMemorizePhraseOrMacro::memorizePhraseOrMacro(uint memoryIndex, bool } // memorize a default spell -void CHandlerMemorizePhraseOrMacro::memorizePhraseSheet(uint memoryIndex, uint32 sheetId) +void CHandlerMemorizePhraseOrMacro::memorizePhraseSheet(sint32 memoryLine, uint memoryIndex, uint32 sheetId) { CSPhraseManager *pPM= CSPhraseManager::getInstance(); - sint32 memoryLine= pPM->getSelectedMemoryLineDB(); if(memoryLine<0) return; @@ -989,7 +997,11 @@ public: return; // Ok, the user try to forget a phrase slot. - sint32 memoryLine= pPM->getSelectedMemoryLineDB(); + sint32 memoryLine; + if (pCSDst->isShortCut()) + memoryLine = pPM->getSelectedMemoryLineDB(); + else + memoryLine = pPM->getSelectedMemoryAltLineDB(); if(memoryLine<0) return; @@ -1026,6 +1038,9 @@ public: if (!pCSDst->isSPhraseIdMemory() && !pCSDst->isMacroMemory()) return; + // is alternative action bar + bool isMain = pCSDst->isShortCut(); + // get the memory index uint memoryIndex = pCSDst->getIndexInDB(); @@ -1034,7 +1049,9 @@ public: // build params string string sParams; - sParams.append("memoryIndex="); + sParams.append("isMain="); + sParams.append(toString(isMain)); + sParams.append("|memoryIndex="); sParams.append(toString(memoryIndex)); sParams.append("|isMacro="); sParams.append(toString(isMacro)); @@ -1066,11 +1083,10 @@ public: // Ok, the user try to forget a phrase slot CSPhraseManager *pPM = CSPhraseManager::getInstance(); - sint32 memoryLine = pPM->getSelectedMemoryLineDB(); - if (memoryLine<0) - return; - + // get params + bool isMain; + fromString(getParam(Params, "isMain"), isMain); uint memoryIndex; fromString(getParam(Params, "memoryIndex"), memoryIndex); bool isMacro; @@ -1078,6 +1094,14 @@ public: sint32 phraseId; fromString(getParam(Params, "phraseId"),phraseId); + sint32 memoryLine; + if (isMain) + memoryLine = pPM->getSelectedMemoryLineDB(); + else + memoryLine = pPM->getSelectedMemoryAltLineDB(); + if (memoryLine<0) + return; + if (isMacro) { pPM->forgetMacro(memoryLine, memoryIndex); @@ -1513,7 +1537,7 @@ public: if (pCSDst->isShortCut()) memoryLine = pPM->getSelectedMemoryLineDB(); else - memoryLine = 0; + memoryLine = pPM->getSelectedMemoryAltLineDB(); if(memoryLine<0) return; diff --git a/ryzom/client/src/interface_v3/bot_chat_page_trade.cpp b/ryzom/client/src/interface_v3/bot_chat_page_trade.cpp index 4a59163b3..d05ba9d7a 100644 --- a/ryzom/client/src/interface_v3/bot_chat_page_trade.cpp +++ b/ryzom/client/src/interface_v3/bot_chat_page_trade.cpp @@ -588,7 +588,8 @@ void CBotChatPageTrade::updateTradeModal() if ((_BuyMean == MoneyGuildXP) || (_BuyMean == GuildMoney) || (_BuyMean == GuildMoneyGuildXP)) { uint64 totalPrice = (uint64) priceWithoutFame * (uint64) quantity; - NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:TRADE_ITEM:PRICE")->setValue64(totalPrice); + NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:TRADE_ITEM:UNIT_PRICE")->setValue64(totalPrice); + NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:TRADE_ITEM:UNIT_PRICE_WITH_FAME")->setValue64(totalPrice); uint64 totalXP = (uint64) getCurrItemXP() * (uint64) quantity; CGuildManager *pGM = CGuildManager::getInstance(); diff --git a/ryzom/client/src/interface_v3/chat_text_manager.cpp b/ryzom/client/src/interface_v3/chat_text_manager.cpp index 3b11d17a5..ec0aee822 100644 --- a/ryzom/client/src/interface_v3/chat_text_manager.cpp +++ b/ryzom/client/src/interface_v3/chat_text_manager.cpp @@ -422,6 +422,42 @@ CViewBase *CChatTextManager::createMsgTextComplex(const ucstring &msg, NLMISC::C return para; } + ucstring::size_type pos = 0; + + // Manage Translations + CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_TRANSLATION_ONLY_AS_TOOLTIP_CB", false); + bool originalFirst = node->getValueBool(); + + string::size_type startTr = msg.find(ucstring("{:")); + string::size_type endOfOriginal = msg.find(ucstring("}@{")); + + // Original/Translated case, example: {:enHello the world!}@{ Bonjour le monde ! + if (startTr != string::npos && endOfOriginal != string::npos) + { + CViewBase *vt = createMsgTextSimple(msg.substr(0, startTr), col, justified, NULL); + para->addChild(vt); + + string texture = "flag-"+toLower(msg.substr(startTr+2, 2)).toString()+".tga"; + ucstring original = msg.substr(startTr+5, endOfOriginal-startTr-5); + ucstring translation = msg.substr(endOfOriginal+3); + CCtrlButton *ctrlButton = new CCtrlButton(CViewBase::TCtorParam()); + ctrlButton->setTexture(texture); + ctrlButton->setTextureOver(texture); + ctrlButton->setTexturePushed(texture); + if (!originalFirst) + { + ctrlButton->setDefaultContextHelp(original); + pos = endOfOriginal+3; + } + else + { + ctrlButton->setDefaultContextHelp(translation); + pos = startTr+5; + textSize = endOfOriginal; + } + ctrlButton->setId("tr"); + para->addChild(ctrlButton); + } // quickly check if text has links or not bool hasUrl; @@ -430,8 +466,7 @@ CViewBase *CChatTextManager::createMsgTextComplex(const ucstring &msg, NLMISC::C hasUrl = (s.find(ucstring("http://")) || s.find(ucstring("https://"))); } - ucstring::size_type pos = 0; - for (ucstring::size_type i = 0; i< textSize;) + for (ucstring::size_type i = pos; i< textSize;) { if (hasUrl && isUrlTag(msg, i, textSize)) { diff --git a/ryzom/client/src/interface_v3/chat_window.cpp b/ryzom/client/src/interface_v3/chat_window.cpp index 1537e7b8b..13f7bc66d 100644 --- a/ryzom/client/src/interface_v3/chat_window.cpp +++ b/ryzom/client/src/interface_v3/chat_window.cpp @@ -215,29 +215,34 @@ void CChatWindow::displayMessage(const ucstring &msg, NLMISC::CRGBA col, CChatGr CChatTextManager &ctm = getChatTextMngr(); gl = dynamic_cast(_Chat->getGroup("cb:text_list")); - if (gl) gl->addChild(ctm.createMsgText(msg, col)); - // if the group is closed, make it blink - if (!_Chat->isOpen()) + CViewBase *child = ctm.createMsgText(msg, col); + if (child) { - if (numBlinks) _Chat->enableBlink(numBlinks); - } - if (_ParentBlink) - { - CGroupContainer *father = dynamic_cast(_Chat->getParent()); - if (father && !father->isOpen()) + if (gl) gl->addChild(child); + + // if the group is closed, make it blink + if (!_Chat->isOpen()) { - father->enableBlink(numBlinks); + if (numBlinks) _Chat->enableBlink(numBlinks); } + if (_ParentBlink) + { + CGroupContainer *father = dynamic_cast(_Chat->getParent()); + if (father && !father->isOpen()) + { + father->enableBlink(numBlinks); + } + } + if (windowVisible != NULL) + { + *windowVisible = isVisible(); + } + /*for(std::vector::iterator it = _Observers.begin(); it != _Observers.end(); ++it) + { + (*it)->displayMessage(this, msg, col, numBlinks); + }*/ } - if (windowVisible != NULL) - { - *windowVisible = isVisible(); - } - /*for(std::vector::iterator it = _Observers.begin(); it != _Observers.end(); ++it) - { - (*it)->displayMessage(this, msg, col, numBlinks); - }*/ } //================================================================================= @@ -563,12 +568,17 @@ void CChatGroupWindow::displayMessage(const ucstring &msg, NLMISC::CRGBA col, CC ucstring newmsg = msg; ucstring prefix; + CViewBase *child = NULL; if (gl != NULL) { - gl->addChild(ctm.createMsgText(newmsg, col)); - if (!gl->getParent()->getActive()) - if (tab != NULL) - tab->setTextColorNormal(newMsgColor); + child = ctm.createMsgText(newmsg, col); + if (child) + { + gl->addChild(child); + if (!gl->getParent()->getActive()) + if (tab != NULL) + tab->setTextColorNormal(newMsgColor); + } } // *** Display the message in the UserChat (special case) @@ -590,7 +600,7 @@ void CChatGroupWindow::displayMessage(const ucstring &msg, NLMISC::CRGBA col, CC case CChatGroup::guild: if (ci.Guild.isListeningWindow(cw)) gl = gl2; break; case CChatGroup::system: if (ci.SystemInfo.isListeningWindow(cw)) gl = gl2; break; case CChatGroup::universe: if (ci.Universe.isListeningWindow(cw)) gl = gl2; break; - case CChatGroup::dyn_chat: + case CChatGroup::dyn_chat: if (ci.DynamicChat[dynamicChatDbIndex].isListeningWindow(cw)) { gl = gl2; @@ -608,7 +618,7 @@ void CChatGroupWindow::displayMessage(const ucstring &msg, NLMISC::CRGBA col, CC pos = newmsg.find(ucstring("}")); prefix += " "; } - + if (pos == ucstring::npos) newmsg = prefix + newmsg; else @@ -635,31 +645,37 @@ void CChatGroupWindow::displayMessage(const ucstring &msg, NLMISC::CRGBA col, CC if (gl != NULL) { - gl->addChild(ctm.createMsgText(newmsg, col)); - if (!gl->getParent()->getActive()) - if (tab != NULL) - tab->setTextColorNormal(newMsgColor); + child = ctm.createMsgText(newmsg, col); + if (child) + { + gl->addChild(child); + if (!gl->getParent()->getActive()) + if (tab != NULL) + tab->setTextColorNormal(newMsgColor); + } } } - - // *** Blink and visibility event - // if the group is closed, make it blink - if (!_Chat->isOpen()) - { - if (numBlinks) _Chat->enableBlink(numBlinks); - } - if (_ParentBlink) + if (child) { - CGroupContainer *father = dynamic_cast(_Chat->getParent()); - if (father && !father->isOpen()) + // *** Blink and visibility event + // if the group is closed, make it blink + if (!_Chat->isOpen()) { - father->enableBlink(numBlinks); + if (numBlinks) _Chat->enableBlink(numBlinks); + } + if (_ParentBlink) + { + CGroupContainer *father = dynamic_cast(_Chat->getParent()); + if (father && !father->isOpen()) + { + father->enableBlink(numBlinks); + } + } + if (windowVisible != NULL) + { + *windowVisible = isVisible(); } - } - if (windowVisible != NULL) - { - *windowVisible = isVisible(); } } @@ -685,8 +701,9 @@ void CChatGroupWindow::displayTellMessage(const ucstring &msg, NLMISC::CRGBA col nlwarning(" can't get text_list."); return; } - - gl->addChild(getChatTextMngr().createMsgText(msg, col)); + CViewBase *child = getChatTextMngr().createMsgText(msg, col); + if (child) + gl->addChild(child); } //================================================================================= diff --git a/ryzom/client/src/interface_v3/dbctrl_sheet.cpp b/ryzom/client/src/interface_v3/dbctrl_sheet.cpp index 56727f6d4..7b188742c 100644 --- a/ryzom/client/src/interface_v3/dbctrl_sheet.cpp +++ b/ryzom/client/src/interface_v3/dbctrl_sheet.cpp @@ -2875,7 +2875,7 @@ bool CDBCtrlSheet::handleEvent (const NLGUI::CEventDescriptor &event) } else { - validClic = isDraggable() && !isDragged() && ((!getItemWeared()&&!getGrayed()) || isShortCut()); + validClic = isDraggable() && !isDragged() && ((!getItemWeared()&&!getGrayed()) || isSPhraseId()); } } if (_Type == SheetType_Macro) diff --git a/ryzom/client/src/interface_v3/group_in_scene_bubble.cpp b/ryzom/client/src/interface_v3/group_in_scene_bubble.cpp index d79861b58..2276eb506 100644 --- a/ryzom/client/src/interface_v3/group_in_scene_bubble.cpp +++ b/ryzom/client/src/interface_v3/group_in_scene_bubble.cpp @@ -843,6 +843,29 @@ void CGroupInSceneBubbleManager::chatOpen (uint32 nUID, const ucstring &ucsText, if (pChar == NULL || nUID==CLFECOMMON::INVALID_CLIENT_DATASET_INDEX) return; if (bubbleTimer == 0) bubbleTimer = CWidgetManager::getInstance()->getSystemOption(CWidgetManager::OptionTimeoutBubbles).getValSInt32(); + + + // Clean bubble from translation system + CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_TRANSLATION_ONLY_AS_TOOLTIP_CB", false); + bool originalFirst = node->getValueBool(); + + ucstring::size_type pos = 0; + ucstring::size_type textSize = ucsText.size(); + string::size_type startTr = ucsText.find(ucstring("{:")); + string::size_type endOfOriginal = ucsText.find(ucstring("}@{")); + if (endOfOriginal != string::npos) + { + if (!originalFirst) + { + pos = endOfOriginal+4; + } + else + { + pos = startTr+5; + textSize = endOfOriginal; + } + } + // Output the message in a bubble bool show = false; @@ -862,7 +885,7 @@ void CGroupInSceneBubbleManager::chatOpen (uint32 nUID, const ucstring &ucsText, return; // Get a bubble - CGroupInSceneBubble *bubble = newBubble (ucsText); + CGroupInSceneBubble *bubble = newBubble (ucsText.substr(pos, textSize-pos)); if (bubble) { // Link the bubble diff --git a/ryzom/client/src/interface_v3/guild_manager.cpp b/ryzom/client/src/interface_v3/guild_manager.cpp index d00661357..5190404ab 100644 --- a/ryzom/client/src/interface_v3/guild_manager.cpp +++ b/ryzom/client/src/interface_v3/guild_manager.cpp @@ -67,6 +67,7 @@ NLMISC_REGISTER_OBJECT(CViewBase, CDBGroupListAscensor, std::string, "list_sheet #define VIEW_TEXT_GUILD_QUIT "ui:interface:guild:content:tab_guild_info:quit_guild" #define CTRL_SHEET_GUILD_BLASON "ui:interface:guild:content:tab_guild_info:blason" #define VIEW_TEXT_GUILD_MEMBER_COUNT "ui:interface:guild:content:tab_guild_info:member_count" +#define VIEW_TEXT_GUILD_MEMBER_COUNT_ONLINE "ui:interface:guild:content:tab_guild_info:member_count_online" #define LIST_GUILD_MEMBERS "ui:interface:guild:content:tab_guild:list_member:guild_members" @@ -817,6 +818,7 @@ class CAHGuildSheetOpen : public IActionHandler if (pParent == NULL) return; pParent->clearGroups(); pParent->setDynamicDisplaySize(false); + uint member_online = 0; for (uint i = 0; i < rGuildMembers.size(); i++) { // create the member line @@ -855,11 +857,13 @@ class CAHGuildSheetOpen : public IActionHandler switch(rGuildMembers[i].Online) { case ccs_online: + member_online++; onlineView->setTexture("w_online.tga"); if (toolTip) toolTip->setDefaultContextHelp(CI18N::get("uittGuildMemberOnline")); break; case ccs_online_abroad: + member_online++; onlineView->setTexture("w_online_abroad.tga"); if (toolTip) toolTip->setDefaultContextHelp(CI18N::get("uittGuildMemberOnlineAbroad")); @@ -895,6 +899,12 @@ class CAHGuildSheetOpen : public IActionHandler pLine->setParent (pParent); pParent->addChild (pLine); } + + // update member online count view + CViewText *pOnlineMember = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(VIEW_TEXT_GUILD_MEMBER_COUNT_ONLINE)); + if (pOnlineMember) + pOnlineMember->setText(toString(member_online)); + } } }; diff --git a/ryzom/client/src/interface_v3/inventory_manager.cpp b/ryzom/client/src/interface_v3/inventory_manager.cpp index f84e38234..5c4799fe4 100644 --- a/ryzom/client/src/interface_v3/inventory_manager.cpp +++ b/ryzom/client/src/interface_v3/inventory_manager.cpp @@ -3777,6 +3777,21 @@ void CInventoryManager::sortBag() if (pIconList != NULL) pIconList->needToSort(); pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(LIST_PA3_TEXT)); if (pList != NULL) pList->needToSort(); + + pIconList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(LIST_PA4_ICONS)); + if (pIconList != NULL) pIconList->needToSort(); + pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(LIST_PA4_TEXT)); + if (pList != NULL) pList->needToSort(); + + pIconList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(LIST_PA5_ICONS)); + if (pIconList != NULL) pIconList->needToSort(); + pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(LIST_PA5_TEXT)); + if (pList != NULL) pList->needToSort(); + + pIconList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(LIST_PA6_ICONS)); + if (pIconList != NULL) pIconList->needToSort(); + pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(LIST_PA6_TEXT)); + if (pList != NULL) pList->needToSort(); } // *************************************************************************** diff --git a/ryzom/client/src/interface_v3/inventory_manager.h b/ryzom/client/src/interface_v3/inventory_manager.h index 8c365a0be..160b7c1aa 100644 --- a/ryzom/client/src/interface_v3/inventory_manager.h +++ b/ryzom/client/src/interface_v3/inventory_manager.h @@ -822,6 +822,15 @@ private: #define LIST_PA3_TEXT "ui:interface:inv_pa3:content:iil:bag_list" #define LIST_PA3_ICONS "ui:interface:inv_pa3:content:iil:bag_icons" +#define LIST_PA4_TEXT "ui:interface:inv_pa4:content:iil:bag_list" +#define LIST_PA4_ICONS "ui:interface:inv_pa4:content:iil:bag_icons" + +#define LIST_PA5_TEXT "ui:interface:inv_pa5:content:iil:bag_list" +#define LIST_PA5_ICONS "ui:interface:inv_pa5:content:iil:bag_icons" + +#define LIST_PA6_TEXT "ui:interface:inv_pa6:content:iil:bag_list" +#define LIST_PA6_ICONS "ui:interface:inv_pa6:content:iil:bag_icons" + // Theorically never used #define LIST_BAG2_TEXT "ui:interface:inv_bag:content:iil:bag_list" #define LIST_BAG2_ICONS "ui:interface:inv_bag:content:iil:bag_icons" diff --git a/ryzom/client/src/interface_v3/people_interraction.cpp b/ryzom/client/src/interface_v3/people_interraction.cpp index 96f27bb6c..9164a78ea 100644 --- a/ryzom/client/src/interface_v3/people_interraction.cpp +++ b/ryzom/client/src/interface_v3/people_interraction.cpp @@ -90,7 +90,7 @@ static const sint PARTY_CHAT_SPAWN_DELTA = 20; // to avoid that all party chat a ////////////////////////////////// /** Display an error msg in the system info window, and also in the last window that triggered the command (so that the user is sure to see it) - */ + */ static void displayVisibleSystemMsg(const ucstring &msg, const string &cat = "CHK"); @@ -289,13 +289,13 @@ void CChatStdInput::registerListeningWindow(CChatWindow *cw) //=========================================================================================================== CPeopleInterraction::CPeopleInterraction() : Region(NULL), - Universe(NULL), - TeamChat(NULL), - GuildChat(NULL), - SystemInfo(NULL), - TellWindow(NULL), - DebugInfo(NULL), - CurrPartyChatID(0) + Universe(NULL), + TeamChat(NULL), + GuildChat(NULL), + SystemInfo(NULL), + TellWindow(NULL), + DebugInfo(NULL), + CurrPartyChatID(0) { for(uint i=0;isetMenu("ui:interface:base_chat_box_menu"); */ + chatDesc.FatherContainer = "ui:interface"; + chatDesc.Title = "uiTellWindow"; + chatDesc.Listener = NULL; + chatDesc.Savable = true; + chatDesc.Localize = true; + chatDesc.Id = "tell"; + chatDesc.ChatTemplate ="chat_no_eb_id"; + chatDesc.AHOnActive = "set"; + chatDesc.AHOnActiveParams = "dblink=UI:SAVE:ISDETACHED:TELL|value=1"; + chatDesc.AHOnDeactive = "set"; + chatDesc.AHOnDeactiveParams = "dblink=UI:SAVE:ISDETACHED:TELL|value=0"; + + TellWindow = getChatWndMgr().createChatWindow(chatDesc); + if (!TellWindow) return; + TellWindow->setMenu("ui:interface:base_chat_box_menu"); */ } //=========================================================================================================== @@ -826,13 +828,13 @@ class CHandlerUserChatActive : public IActionHandler CChatGroup::TGroupType m = PeopleInterraction.TheUserChat.Filter.getTargetGroup(); switch(m) { - default: - case CChatGroup::arround: - case CChatGroup::say: pUserBut->setHardText("uiFilterAround"); break; - case CChatGroup::region: pUserBut->setHardText("uiFilterRegion"); break; - case CChatGroup::universe: pUserBut->setHardText("uiFilterUniverse"); break; - case CChatGroup::team: pUserBut->setHardText("uiFilterTeam"); break; - case CChatGroup::guild: pUserBut->setHardText("uiFilterGuild"); break; + default: + case CChatGroup::arround: + case CChatGroup::say: pUserBut->setHardText("uiFilterAround"); break; + case CChatGroup::region: pUserBut->setHardText("uiFilterRegion"); break; + case CChatGroup::universe: pUserBut->setHardText("uiFilterUniverse"); break; + case CChatGroup::team: pUserBut->setHardText("uiFilterTeam"); break; + case CChatGroup::guild: pUserBut->setHardText("uiFilterGuild"); break; } pUserBut->getParent()->updateCoords(); pUserBut->updateCoords(); @@ -925,29 +927,29 @@ class CHandlerChatGroupFilter : public IActionHandler CChatGroup::TGroupType m = PeopleInterraction.TheUserChat.Filter.getTargetGroup(); switch(m) { - default: - case CChatGroup::arround: - case CChatGroup::say: pUserBut->setHardText("uiFilterAround"); break; - case CChatGroup::region: pUserBut->setHardText("uiFilterRegion"); break; - case CChatGroup::team: pUserBut->setHardText("uiFilterTeam"); break; - case CChatGroup::guild: pUserBut->setHardText("uiFilterGuild"); break; - case CChatGroup::universe: pUserBut->setHardText("uiFilterUniverse"); break; - case CChatGroup::dyn_chat: - uint32 index = PeopleInterraction.TheUserChat.Filter.getTargetDynamicChannelDbIndex(); - uint32 textId = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:DYN_CHAT:CHANNEL"+toString(index)+":NAME")->getValue32(); - ucstring title; - STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId, title); - if (title.empty()) - { - // Dyn channel not available yet, so set to around - PeopleInterraction.TheUserChat.Filter.setTargetGroup(CChatGroup::arround); - pUserBut->setHardText("uiFilterAround"); - } - else - { - pUserBut->setHardText(title.toUtf8()); - } - break; + default: + case CChatGroup::arround: + case CChatGroup::say: pUserBut->setHardText("uiFilterAround"); break; + case CChatGroup::region: pUserBut->setHardText("uiFilterRegion"); break; + case CChatGroup::team: pUserBut->setHardText("uiFilterTeam"); break; + case CChatGroup::guild: pUserBut->setHardText("uiFilterGuild"); break; + case CChatGroup::universe: pUserBut->setHardText("uiFilterUniverse"); break; + case CChatGroup::dyn_chat: + uint32 index = PeopleInterraction.TheUserChat.Filter.getTargetDynamicChannelDbIndex(); + uint32 textId = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:DYN_CHAT:CHANNEL"+toString(index)+":NAME")->getValue32(); + ucstring title; + STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId, title); + if (title.empty()) + { + // Dyn channel not available yet, so set to around + PeopleInterraction.TheUserChat.Filter.setTargetGroup(CChatGroup::arround); + pUserBut->setHardText("uiFilterAround"); + } + else + { + pUserBut->setHardText(title.toUtf8()); + } + break; } pUserBut->setActive(true); @@ -1252,8 +1254,8 @@ void CPeopleInterraction::askRemoveContact(uint peopleIndex, CPeopleList *pl) //================================================================================================================= void CPeopleInterraction::initContactLists( const std::vector &vFriendListName, - const std::vector &vFriendListOnline, - const std::vector &vIgnoreListName ) + const std::vector &vFriendListOnline, + const std::vector &vIgnoreListName ) { // clear the current lists if any @@ -1266,6 +1268,9 @@ void CPeopleInterraction::initContactLists( const std::vector &vFriendLi addContactInList(contactIdPool++, vFriendListName[i], vFriendListOnline[i], 0); for (uint i = 0; i < vIgnoreListName.size(); ++i) addContactInList(contactIdPool++, vIgnoreListName[i], ccs_offline, 1); + FriendList.readContactGroups(); + CPeopleList::TSortOrder order = (CPeopleList::TSortOrder)(NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CONTACT_LIST:SORT_ORDER")->getValue32()); + FriendList.sortEx(order); updateAllFreeTellerHeaders(); } @@ -1278,6 +1283,8 @@ void CPeopleInterraction::addContactInList(uint32 contactId, const ucstring &nam // remove the shard name if possible ucstring name= CEntityCL::removeShardFromName(nameIn); + + // add the contact to this list sint index = pl.getIndexFromName(name); // try to create if not found @@ -1477,7 +1484,7 @@ bool CPeopleInterraction::testValidPartyChatName(const ucstring &title) index = IgnoreList.getIndexFromName(title); if (index != -1) return false; // TODO_GAMEDEV server test for the name (not only local), & modify callers of this function - // The party chat should NOT have the name of a player + // The party chat should NOT have the name of a player // A player name is NOT valid if it is the same that a party chat name return true; } @@ -1547,14 +1554,14 @@ bool CPeopleInterraction::createNewPartyChat(const ucstring &title) { // popup the container /* - newPartyChat->getContainer()->setup(); - newPartyChat->getContainer()->setOpen(true); - newPartyChat->getContainer()->popupCurrentPos(); - newPartyChat->getContainer()->updateCoords(); - newPartyChat->getContainer()->center(); - newPartyChat->getContainer()->setX(newPartyChat->getContainer()->getX() + (sint32) (rand() % PARTY_CHAT_SPAWN_DELTA)); - newPartyChat->getContainer()->setY(newPartyChat->getContainer()->getY() + (sint32) (rand() % PARTY_CHAT_SPAWN_DELTA)); - newPartyChat->getContainer()->enableBlink(2); + newPartyChat->getContainer()->setup(); + newPartyChat->getContainer()->setOpen(true); + newPartyChat->getContainer()->popupCurrentPos(); + newPartyChat->getContainer()->updateCoords(); + newPartyChat->getContainer()->center(); + newPartyChat->getContainer()->setX(newPartyChat->getContainer()->getX() + (sint32) (rand() % PARTY_CHAT_SPAWN_DELTA)); + newPartyChat->getContainer()->setY(newPartyChat->getContainer()->getY() + (sint32) (rand() % PARTY_CHAT_SPAWN_DELTA)); + newPartyChat->getContainer()->enableBlink(2); */ CPartyChatInfo pci; @@ -1742,15 +1749,15 @@ bool CPeopleInterraction::loadUserChatsInfos(NLMISC::IStream &f) f.serialCheck(NELID("TAHC")); if (ver>=1) { -// CChatGroupWindow *pCGW = PeopleInterraction.getChatGroupWindow(); + // CChatGroupWindow *pCGW = PeopleInterraction.getChatGroupWindow(); sint32 index; f.serial(index); /* Yoyo: decide to always start with the default channel (user) activated - because complex (at this time, the buttons are not all active, must wait guild loading, UI:SAVE loading etc...) - Hence this doesn't work for anything but User and Sysinfo (if it is activated....) - NB: must still load the index for file format reason - //if (pCGW) pCGW->setTabIndex(index); - */ + because complex (at this time, the buttons are not all active, must wait guild loading, UI:SAVE loading etc...) + Hence this doesn't work for anything but User and Sysinfo (if it is activated....) + NB: must still load the index for file format reason + //if (pCGW) pCGW->setTabIndex(index); + */ f.serial(present); if (present) { @@ -2012,17 +2019,17 @@ public: if (list == &PeopleInterraction.TeamList) // check for good list { /* - const string msgName = "TEAM:SET_LEADER"; - CBitMemStream out; - if(GenericMsgHeaderMngr.pushNameToStream(msgName, out)) - { - uint8 teamMember = (uint8)(peopleIndex); - out.serial(teamMember); - NetMngr.push(out); - //nlinfo("impulseCallBack : %s %d sent", msgName.c_str(), teamMember); - } - else - nlwarning("command 'set_leader': unknown message named '%s'.", msgName.c_str()); + const string msgName = "TEAM:SET_LEADER"; + CBitMemStream out; + if(GenericMsgHeaderMngr.pushNameToStream(msgName, out)) + { + uint8 teamMember = (uint8)(peopleIndex); + out.serial(teamMember); + NetMngr.push(out); + //nlinfo("impulseCallBack : %s %d sent", msgName.c_str(), teamMember); + } + else + nlwarning("command 'set_leader': unknown message named '%s'.", msgName.c_str()); */ NLMISC::ICommand::execute("a setTeamLeader " + toString(peopleIndex), g_log); } @@ -2177,8 +2184,8 @@ public: void execute (CCtrlBase *pCaller, const std::string &sParams) { /** This msg may have been triggered from valid button or from the edit box itself, so retrieve - * the edit box from the enclosing group - */ + * the edit box from the enclosing group + */ // Get enclosing container to know in which people list we are if (pCaller) { @@ -2221,8 +2228,8 @@ public: CInterfaceManager *pIM = CInterfaceManager::getInstance(); /** This msg may have been triggered from valid button or from the edit box itself, so retrieve - * the edit box from the enclosing group - */ + * the edit box from the enclosing group + */ // Get enclosing container to know in which people list we are if (!LastFatherAddContactId.empty() && pCaller) { @@ -2292,13 +2299,13 @@ public: } switch(listIndex) { - case 0: - destList = &PeopleInterraction.IgnoreList; + case 0: + destList = &PeopleInterraction.IgnoreList; break; - case 1: - destList = &PeopleInterraction.FriendList; + case 1: + destList = &PeopleInterraction.FriendList; break; - default: nlwarning("Bad list index"); return; + default: nlwarning("Bad list index"); return; } PeopleInterraction.askMoveContact(peopleIndex, srcList, destList); @@ -2307,6 +2314,56 @@ public: }; REGISTER_ACTION_HANDLER( CHandlerMoveContact, "move_contact"); +uint lastPeopleIndexChangeGroup; +//================================================================================================================= +class CHandlerChangeContactGroupBegin : public IActionHandler +{ +public: + void execute (CCtrlBase * pCaller, const std::string &sParams) + { + // retrieve the index of the people + CPeopleList *srcList; + if (PeopleInterraction.getPeopleFromCurrentMenu(srcList, lastPeopleIndexChangeGroup)) + { + string groupName= getParam(sParams, "group"); + CInterfaceGroup *gc = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(groupName)); + if (gc) + { + CGroupEditBox *geb = dynamic_cast(gc->getGroup("change_contact_group_eb:eb")); + geb->setInputString(ucstring("")); + } + CAHManager::getInstance()->runActionHandler("enter_modal", pCaller, sParams); + } + } +}; +REGISTER_ACTION_HANDLER( CHandlerChangeContactGroupBegin, "change_contact_group_begin"); + +//================================================================================================================= +// Change the group of a contact in the list +class CHandlerChangeContactGroup : public IActionHandler +{ +public: + void execute (CCtrlBase *pCaller, const std::string &/* sParams */) + { + CInterfaceManager *pIM = CInterfaceManager::getInstance(); + + if (pCaller) + { + // Get the modal edit box + CGroupEditBox *geb = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:change_contact_group:change_contact_group_eb:eb")); + if (geb) + { + + PeopleInterraction.FriendList.changeGroup(lastPeopleIndexChangeGroup, geb->getInputString()); + geb->setInputString(ucstring("")); + CPeopleList::TSortOrder order = (CPeopleList::TSortOrder)(NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CONTACT_LIST:SORT_ORDER")->getValue32()); + PeopleInterraction.FriendList.sortEx(order); + } + } + CAHManager::getInstance()->runActionHandler("leave_modal", pCaller, ""); + } +}; +REGISTER_ACTION_HANDLER( CHandlerChangeContactGroup, "change_contact_group"); //================================================================================================================= class CHandlerSortContacts : public IActionHandler @@ -2372,7 +2429,7 @@ REGISTER_ACTION_HANDLER( CHandlerContactDirectChat, "contact_direct_chat"); //================================================================================================================= /** Menu to create a new party chat - */ + */ class CHandlerNewPartyChat : public IActionHandler { public: @@ -2406,7 +2463,7 @@ REGISTER_ACTION_HANDLER( CHandlerNewPartyChat, "new_party_chat"); //================================================================================================================= /** The name of a party chat has been validated - */ + */ class CHandlerValidatePartyChatName : public IActionHandler { void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */) @@ -2439,12 +2496,12 @@ REGISTER_ACTION_HANDLER(CHandlerValidatePartyChatName, "validate_party_chat_name //================================================================================================================= /** Menu to create a new party chat - */ + */ //================================================================================================================= /** Menu to remove a currenlty created party chat - */ + */ class CHandlerRemovePartyChat : public IActionHandler { void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */) @@ -2457,7 +2514,7 @@ REGISTER_ACTION_HANDLER( CHandlerRemovePartyChat, "remove_party_chat"); //================================================================================================================= /** TEMP : just create an 'invite' command in the 'around me' edit box - */ + */ class CHandlerPartyChatInvite : public IActionHandler { void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */) @@ -2483,12 +2540,12 @@ REGISTER_ACTION_HANDLER( CHandlerPartyChatInvite, "party_chat_invite" ); //================================================================================================================= /** Add all members of the team to the party chat - */ + */ class CHandlerAddAllTeamMembersToPartyChat : public IActionHandler { void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */) { -// CChatWindow *chat = getChatWndMgr().getChatWindowFromCaller(CWidgetManager::getInstance()->getCtrlLaunchingModal()); + // CChatWindow *chat = getChatWndMgr().getChatWindowFromCaller(CWidgetManager::getInstance()->getCtrlLaunchingModal()); // TODO GAMEDEV : add all team members } }; @@ -2496,12 +2553,12 @@ REGISTER_ACTION_HANDLER( CHandlerAddAllTeamMembersToPartyChat, "add_all_team_mem //================================================================================================================= /** Remove all members of the team to the party chat - */ + */ class CHandlerRemoveAllTeamMembersToPartyChat : public IActionHandler { void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */) { -// CChatWindow *chat = getChatWndMgr().getChatWindowFromCaller(CWidgetManager::getInstance()->getCtrlLaunchingModal()); + // CChatWindow *chat = getChatWndMgr().getChatWindowFromCaller(CWidgetManager::getInstance()->getCtrlLaunchingModal()); // TODO GAMEDEV : remove all team members } }; @@ -2509,12 +2566,12 @@ REGISTER_ACTION_HANDLER( CHandlerRemoveAllTeamMembersToPartyChat, "remove_all_te //================================================================================================================= /** Add all members of the guild to the party chat - */ + */ class CHandlerAddAllGuildMembersToPartyChat : public IActionHandler { void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */) { -// CChatWindow *chat = getChatWndMgr().getChatWindowFromCaller(CWidgetManager::getInstance()->getCtrlLaunchingModal()); + // CChatWindow *chat = getChatWndMgr().getChatWindowFromCaller(CWidgetManager::getInstance()->getCtrlLaunchingModal()); // TODO GAMEDEV : add all guild members } }; @@ -2522,12 +2579,12 @@ REGISTER_ACTION_HANDLER( CHandlerAddAllGuildMembersToPartyChat, "add_all_guild_m //================================================================================================================= /** Remove all members of the team to the party chat - */ + */ class CHandlerRemoveAllGuildMembersToPartyChat : public IActionHandler { void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */) { -// CChatWindow *chat = getChatWndMgr().getChatWindowFromCaller(CWidgetManager::getInstance()->getCtrlLaunchingModal()); + // CChatWindow *chat = getChatWndMgr().getChatWindowFromCaller(CWidgetManager::getInstance()->getCtrlLaunchingModal()); // TODO_GAMEDEV : remove all guild members } }; @@ -2539,8 +2596,8 @@ REGISTER_ACTION_HANDLER( CHandlerRemoveAllGuildMembersToPartyChat, "remove_all_g //================================================================================================================= /** Select the target on a filtered chat window - * This create a menu with the standard window (team, around me ...) + the party chat windows - */ + * This create a menu with the standard window (team, around me ...) + the party chat windows + */ class CHandlerSelectChatTarget : public IActionHandler { public: @@ -2603,7 +2660,7 @@ public: { CInterfaceManager *pIM = CInterfaceManager::getInstance(); cw = PeopleInterraction.TheUserChat.Window; -// CChatStdInput &ci = PeopleInterraction.ChatInput; + // CChatStdInput &ci = PeopleInterraction.ChatInput; CGroupMenu *pMenu = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:user_chat_target_menu")); CViewTextMenu *pMenuAround = dynamic_cast(pMenu->getElement("ui:interface:user_chat_target_menu:around")); CViewTextMenu *pMenuRegion = dynamic_cast(pMenu->getElement("ui:interface:user_chat_target_menu:region")); @@ -2659,7 +2716,7 @@ REGISTER_ACTION_HANDLER( CHandlerSelectChatTarget, "select_chat_target"); //================================================================================================================= /** A target has been selected for a filtered chat - */ + */ class CHandlerChatTargetSelected : public IActionHandler { void execute (CCtrlBase * /* pCaller */, const std::string &sParams) @@ -2748,7 +2805,7 @@ REGISTER_ACTION_HANDLER( CHandlerChatTargetSelected, "chat_target_selected"); //================================================================================================================= /** If no more in team, leave team chat mode - */ + */ class CHandlerLeaveTeamChat : public IActionHandler { void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */) @@ -2773,7 +2830,7 @@ REGISTER_ACTION_HANDLER( CHandlerLeaveTeamChat, "leave_team_chat"); /** Create checkbox for a menu. - */ + */ static CInterfaceGroup *createMenuCheckBox(const std::string &onclickL, const std::string ¶msL, bool checked) { pair params [2]; @@ -2795,7 +2852,7 @@ static CInterfaceGroup *createMenuCheckBox(const std::string &onclickL, const st //================================================================================================================= /** Display a menu to select the source on a filtered chat - */ + */ class CHandlerSelectChatSource : public IActionHandler { void execute (CCtrlBase *pCaller, const std::string &/* sParams */) @@ -2977,7 +3034,7 @@ REGISTER_ACTION_HANDLER(CHandlerSelectChatSource, "select_chat_source"); //================================================================================================================= /** A new source has been selected / unselected from a filtered chat - */ + */ class CHandlerChatSourceSelected : public IActionHandler { void execute (CCtrlBase * /* pCaller */, const std::string &sParams) @@ -3001,10 +3058,10 @@ class CHandlerChatSourceSelected : public IActionHandler /*CCtrlBaseButton *button = dynamic_cast(pCaller); - if (button) - { - button->setPushed(!button->getPushed()); - }*/ + if (button) + { + button->setPushed(!button->getPushed()); + }*/ // GUILD if (nlstricmp(sParams, "guild") == 0) { @@ -3012,71 +3069,71 @@ class CHandlerChatSourceSelected : public IActionHandler else ci.Guild.addListeningWindow(cw); } else - // TEAM - if (nlstricmp(sParams, "team") == 0) - { - if (ci.Team.isListeningWindow(cw)) ci.Team.removeListeningWindow(cw); - else ci.Team.addListeningWindow(cw); - } - else - // AROUND ME - if (nlstricmp(sParams, "am") == 0) - { - if (ci.AroundMe.isListeningWindow(cw)) ci.AroundMe.removeListeningWindow(cw); - else ci.AroundMe.addListeningWindow(cw); - } - else - // REGION - if (nlstricmp(sParams, "region") == 0) - { - if (ci.Region.isListeningWindow(cw)) ci.Region.removeListeningWindow(cw); - else ci.Region.addListeningWindow(cw); - } - else - // UNIVERSE - if (nlstricmp(sParams, "universe") == 0) - { - if (ci.Universe.isListeningWindow(cw)) ci.Universe.removeListeningWindow(cw); - else ci.Universe.addListeningWindow(cw); - } - else - // TELL - if (nlstricmp(sParams, "tell") == 0) - { - if (ci.Tell.isListeningWindow(cw)) ci.Tell.removeListeningWindow(cw); - else ci.Tell.addListeningWindow(cw); - } - else - // SYSTEM INFOS - if (nlstricmp(sParams, "si") == 0) - { - if (ci.SystemInfo.isListeningWindow(cw)) ci.SystemInfo.removeListeningWindow(cw); - else ci.SystemInfo.addListeningWindow(cw); - } - else - // PARTY CHAT - if (fromString(sParams, partyChatID)) - { - std::vector &partyChats = PeopleInterraction.PartyChats; - for(uint k = 0; k < partyChats.size(); ++k) + // TEAM + if (nlstricmp(sParams, "team") == 0) { - if (partyChats[k].ID == (uint) partyChatID) + if (ci.Team.isListeningWindow(cw)) ci.Team.removeListeningWindow(cw); + else ci.Team.addListeningWindow(cw); + } + else + // AROUND ME + if (nlstricmp(sParams, "am") == 0) { - if (partyChats[k].Filter != NULL) + if (ci.AroundMe.isListeningWindow(cw)) ci.AroundMe.removeListeningWindow(cw); + else ci.AroundMe.addListeningWindow(cw); + } + else + // REGION + if (nlstricmp(sParams, "region") == 0) { - if (partyChats[k].Filter->isListeningWindow(cw)) partyChats[k].Filter->removeListeningWindow(partyChats[k].Window); - else partyChats[k].Filter->addListeningWindow(cw); + if (ci.Region.isListeningWindow(cw)) ci.Region.removeListeningWindow(cw); + else ci.Region.addListeningWindow(cw); } - } - } - } - else if (nlstricmp(sParams.substr(0, 3), "dyn") == 0) - { - uint8 i = 0; - fromString(sParams.substr(3), i); - if (ci.DynamicChat[i].isListeningWindow(cw)) ci.DynamicChat[i].removeListeningWindow(cw); - else ci.DynamicChat[i].addListeningWindow(cw); - } + else + // UNIVERSE + if (nlstricmp(sParams, "universe") == 0) + { + if (ci.Universe.isListeningWindow(cw)) ci.Universe.removeListeningWindow(cw); + else ci.Universe.addListeningWindow(cw); + } + else + // TELL + if (nlstricmp(sParams, "tell") == 0) + { + if (ci.Tell.isListeningWindow(cw)) ci.Tell.removeListeningWindow(cw); + else ci.Tell.addListeningWindow(cw); + } + else + // SYSTEM INFOS + if (nlstricmp(sParams, "si") == 0) + { + if (ci.SystemInfo.isListeningWindow(cw)) ci.SystemInfo.removeListeningWindow(cw); + else ci.SystemInfo.addListeningWindow(cw); + } + else + // PARTY CHAT + if (fromString(sParams, partyChatID)) + { + std::vector &partyChats = PeopleInterraction.PartyChats; + for(uint k = 0; k < partyChats.size(); ++k) + { + if (partyChats[k].ID == (uint) partyChatID) + { + if (partyChats[k].Filter != NULL) + { + if (partyChats[k].Filter->isListeningWindow(cw)) partyChats[k].Filter->removeListeningWindow(partyChats[k].Window); + else partyChats[k].Filter->addListeningWindow(cw); + } + } + } + } + else if (nlstricmp(sParams.substr(0, 3), "dyn") == 0) + { + uint8 i = 0; + fromString(sParams.substr(3), i); + if (ci.DynamicChat[i].isListeningWindow(cw)) ci.DynamicChat[i].removeListeningWindow(cw); + else ci.DynamicChat[i].addListeningWindow(cw); + } } }; REGISTER_ACTION_HANDLER( CHandlerChatSourceSelected, "chat_source_selected"); @@ -3186,80 +3243,80 @@ NLMISC_COMMAND(ignore, "add or remove a player from the ignore list", "") { - if (args.size() != 1) - { - displayVisibleSystemMsg(CI18N::get("uiPartyChatCmd")); - return true; - } - CPeopleInterraction &pi = PeopleInterraction; - ucstring title = args[0]; +if (args.size() != 1) +{ +displayVisibleSystemMsg(CI18N::get("uiPartyChatCmd")); +return true; +} +CPeopleInterraction &pi = PeopleInterraction; +ucstring title = args[0]; - if (!pi.testValidPartyChatName(title)) - { - displayVisibleSystemMsg(CI18N::get("uiInvalidPartyChatName")); - return true; - } +if (!pi.testValidPartyChatName(title)) +{ +displayVisibleSystemMsg(CI18N::get("uiInvalidPartyChatName")); +return true; +} - PeopleInterraction.createNewPartyChat(title); - return true; +PeopleInterraction.createNewPartyChat(title); +return true; } // Remove the party chat with the given name NLMISC_COMMAND(remove_party_chat, "Remove a party chat", "") { - if (args.size() != 1) - { - displayVisibleSystemMsg(CI18N::get("uiRemovePartyChatCmd")); - return true; - } - ucstring title = ucstring(args[0]); - CChatWindow *chat = getChatWndMgr().getChatWindow(title); - if (!chat) - { - displayVisibleSystemMsg(title + ucstring(" : ") + CI18N::get("uiBadPartyChatName")); - return true; - } - if (!PeopleInterraction.removePartyChat(chat)) - { - displayVisibleSystemMsg(title + ucstring(" : ") + CI18N::get("uiCantRemovePartyChat")); - return true; - } - return true; +if (args.size() != 1) +{ +displayVisibleSystemMsg(CI18N::get("uiRemovePartyChatCmd")); +return true; +} +ucstring title = ucstring(args[0]); +CChatWindow *chat = getChatWndMgr().getChatWindow(title); +if (!chat) +{ +displayVisibleSystemMsg(title + ucstring(" : ") + CI18N::get("uiBadPartyChatName")); +return true; +} +if (!PeopleInterraction.removePartyChat(chat)) +{ +displayVisibleSystemMsg(title + ucstring(" : ") + CI18N::get("uiCantRemovePartyChat")); +return true; +} +return true; } // Join a party chat whose name is known NLMISC_COMMAND(add_to_party_chat, "Join the given party chat", "") { - if (args.size() != 1) - { - displayVisibleSystemMsg(CI18N::get("uiAddPartyChatCmd")); - return true; - } - // TODO GAMEDEV : join the party chat - return true; +if (args.size() != 1) +{ +displayVisibleSystemMsg(CI18N::get("uiAddPartyChatCmd")); +return true; +} +// TODO GAMEDEV : join the party chat +return true; } // Invite someone in a party chat NLMISC_COMMAND(invite, "Invite someone to a party chat", " ") { - if (args.size() != 2) - { - displayVisibleSystemMsg(CI18N::get("uiInviteCmd")); - return true; - } - // TODO GAMEDEV : Send invite message to the server - // Check that the inviter has created the chat ? - // The people being invited should receive a popup to announce that he is being invited - return true; +if (args.size() != 2) +{ +displayVisibleSystemMsg(CI18N::get("uiInviteCmd")); +return true; +} +// TODO GAMEDEV : Send invite message to the server +// Check that the inviter has created the chat ? +// The people being invited should receive a popup to announce that he is being invited +return true; } */ diff --git a/ryzom/client/src/interface_v3/people_list.cpp b/ryzom/client/src/interface_v3/people_list.cpp index 6be310d94..c3f2cf4d7 100644 --- a/ryzom/client/src/interface_v3/people_list.cpp +++ b/ryzom/client/src/interface_v3/people_list.cpp @@ -31,6 +31,7 @@ #include "chat_text_manager.h" #include "people_interraction.h" #include "../user_entity.h" +#include "nel/misc/o_xml.h" using namespace std; using namespace NLMISC; @@ -49,9 +50,9 @@ extern CClientChatManager ChatMngr; //================================================================== CPeopleList::CPeopleList() : _ChatWindow(NULL), - _ContactType(CPeopleListDesc::Unknown), - _CurrPeopleID(0), - _Savable(false) + _ContactType(CPeopleListDesc::Unknown), + _CurrPeopleID(0), + _Savable(false) { // Construct @@ -191,34 +192,41 @@ sint CPeopleList::getIndexFromContainerID(const std::string &id) const //================================================================== bool CPeopleList::sortExByContactId(const CPeople& a, const CPeople& b) { - return (a.ContactId < b.ContactId); + if (a.Group == b.Group) + return (a.ContactId < b.ContactId); + else + return (a.Group < b.Group); } //================================================================== bool CPeopleList::sortExByName(const CPeople& a, const CPeople& b) { - ucstring name_a = toUpper(a.getName()); - ucstring name_b = toUpper(b.getName()); - - return (name_a < name_b); + if (a.Group == b.Group) { + ucstring name_a = toUpper(a.getName()); + ucstring name_b = toUpper(b.getName()); + return (name_a < name_b); + } + else + return (a.Group < b.Group); } //================================================================== bool CPeopleList::sortExByOnline(const CPeople& a, const CPeople& b) { - ucstring name_a = toUpper(a.getName()); - ucstring name_b = toUpper(b.getName()); - - // We want order: online/alpha, offworld/alpha, offline/alpha - if (a.Online == b.Online) - { - return (name_a < name_b); - } - else - { - // Compare online status - switch (a.Online) + if (a.Group == b.Group) { + ucstring name_a = toUpper(a.getName()); + ucstring name_b = toUpper(b.getName()); + + // We want order: online/alpha, offworld/alpha, offline/alpha + if (a.Online == b.Online) + { + return (name_a < name_b); + } + else { + // Compare online status + switch (a.Online) + { case ccs_online: // a is > if a is online return true; @@ -232,11 +240,11 @@ bool CPeopleList::sortExByOnline(const CPeople& a, const CPeople& b) // b is always > if a is offline return false; break; + } } } - - // Should not get here so just return something - return true; + else + return (a.Group < b.Group); } //================================================================== @@ -245,29 +253,54 @@ void CPeopleList::sortEx(TSortOrder order) // remove all people from the father container if (!_BaseContainer) return; uint k; + for(k = 0; k < _Peoples.size(); ++k) { - _BaseContainer->detachContainer(_Peoples[k].Container); + CGroupContainer *parentContainer = _Peoples[k].Container->getProprietaryContainer(); + parentContainer->detachContainer(_Peoples[k].Container); } - + for (k = 0; k < _GroupContainers.size(); ++k) + { + if (_GroupContainers[k].second->getProprietaryContainer() != NULL) + _BaseContainer->detachContainer(_GroupContainers[k].second); + } + switch (order) { - default: - case sort_index: - std::sort(_Peoples.begin(), _Peoples.end(), CPeopleList::sortExByContactId); - break; - case sort_name: - std::sort(_Peoples.begin(), _Peoples.end(), CPeopleList::sortExByName); - break; + default: + case sort_index: + std::sort(_Peoples.begin(), _Peoples.end(), CPeopleList::sortExByContactId); + break; + case sort_name: + std::sort(_Peoples.begin(), _Peoples.end(), CPeopleList::sortExByName); + break; - case sort_online: - std::sort(_Peoples.begin(), _Peoples.end(), CPeopleList::sortExByOnline); - break; + case sort_online: + std::sort(_Peoples.begin(), _Peoples.end(), CPeopleList::sortExByOnline); + break; } + CGroupContainer *group = _BaseContainer; + uint groupIndex = 0; + for(k = 0; k < _Peoples.size(); ++k) { - _BaseContainer->attachContainer(_Peoples[k].Container); + bool newGroup = false; + if (k == 0) + { + newGroup = true; + } + while (groupIndex < _GroupContainers.size() && _GroupContainers[groupIndex].first != _Peoples[k].Group.toString()) + { + newGroup = true; + ++groupIndex; + } + if (newGroup && groupIndex < _GroupContainers.size() && _GroupContainers.size() > 1) + { + group = _GroupContainers[groupIndex].second; + _BaseContainer->attachContainer(group); + } + group->attachContainer(_Peoples[k].Container); } } @@ -299,34 +332,34 @@ bool CPeopleList::isPeopleChatVisible(uint index) const return (_Peoples[index].Chat != NULL); } /* -bool CPeopleList::isPeopleWindowVisible(uint index) const -{ - if (index >= _Peoples.size()) - { - nlwarning("Bad index"); - return false; - } - if (!_Peoples[index].Container) return false; - if (_Peoples[index].Container->isOpen()) - { - CInterfaceGroup *ig = _Peoples[index].Container; - do - { - if (ig->isGroupContainer()) - { - if (!static_cast(ig)->isOpen()) break; - } - if (!ig->getActive()) break; - ig = ig->getParent(); - } - while(ig); - return ig == NULL; // all parent windows must be open & visible - } - else - { - return false; - } -} + bool CPeopleList::isPeopleWindowVisible(uint index) const + { + if (index >= _Peoples.size()) + { + nlwarning("Bad index"); + return false; + } + if (!_Peoples[index].Container) return false; + if (_Peoples[index].Container->isOpen()) + { + CInterfaceGroup *ig = _Peoples[index].Container; + do + { + if (ig->isGroupContainer()) + { + if (!static_cast(ig)->isOpen()) break; + } + if (!ig->getActive()) break; + ig = ig->getParent(); + } + while(ig); + return ig == NULL; // all parent windows must be open & visible + } + else + { + return false; + } + } */ //================================================================== @@ -354,12 +387,12 @@ sint CPeopleList::addPeople(const ucstring &name, uint teamMateIndex /*= 0*/) std::string templateName; switch (_ContactType) { - case CPeopleListDesc::Team: templateName = "mate_id"; break; - case CPeopleListDesc::Contact: templateName = "contact_id_friend"; break; - case CPeopleListDesc::Ignore: templateName = "contact_id_ignore"; break; - default: - nlwarning(" Unknown contact type"); - return -1; + case CPeopleListDesc::Team: templateName = "mate_id"; break; + case CPeopleListDesc::Contact: templateName = "contact_id_friend"; break; + case CPeopleListDesc::Ignore: templateName = "contact_id_ignore"; break; + default: + nlwarning(" Unknown contact type"); + return -1; break; } @@ -379,10 +412,10 @@ sint CPeopleList::addPeople(const ucstring &name, uint teamMateIndex /*= 0*/) gc->setSavable(false); // /*if (_ChatWindow) - { - _ChatWindow->getContainer()->attachContainer(gc); - } - else*/ + { + _ChatWindow->getContainer()->attachContainer(gc); + } + else*/ { _BaseContainer->attachContainer(gc); } @@ -415,8 +448,9 @@ void CPeopleList::removePeople(uint index) } else { - if (_BaseContainer) - _BaseContainer->detachContainer(_Peoples[index].Container); + CGroupContainer *parentContainer = _Peoples[index].Container->getProprietaryContainer(); + if (parentContainer) + parentContainer->detachContainer(_Peoples[index].Container); } CInterfaceManager *im = CInterfaceManager::getInstance(); CInterfaceGroup *pRoot = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface")); @@ -447,6 +481,169 @@ void CPeopleList::setContactId(uint index, uint32 contactId) _Peoples[index].ContactId = contactId; } +//================================================================== +void CPeopleList::changeGroup(uint index, const ucstring &groupName) +{ + if (index >= _Peoples.size()) + { + nlwarning(" bad index."); + return; + } + ucstring group = groupName; + if (group.toString() == "General") + group = ucstring(""); + _Peoples[index].Group = group; + + for (uint k = 0; k < _GroupContainers.size(); ++k) + { + if (_GroupContainers[k].first == group.toString()) + return; + } + + vector > properties; + properties.push_back(make_pair(string("posparent"), string("parent"))); + properties.push_back(make_pair(string("id"), _ContainerID + "_group_" + toString(_GroupContainers.size()))); + if (group.toString() == "") + properties.push_back(make_pair(string("title"), "General")); + else + properties.push_back(make_pair(string("title"), group.toString())); + CGroupContainer *gc = dynamic_cast(CWidgetManager::getInstance()->getParser()->createGroupInstance("people_list_group_header", "ui:interface", properties, false)); + + if (group.toString() == "") + gc->setUCTitle(ucstring("General")); + else + gc->setUCTitle(group.toString()); + gc->setSavable(false); + + CInterfaceGroup *pRoot = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface")); + pRoot->addGroup (gc); + _BaseContainer->attachContainer(gc); + + _GroupContainers.push_back(make_pair(group.toString(), gc)); + + std::sort(_GroupContainers.begin(), _GroupContainers.end()); +} + +//================================================================== +void CPeopleList::readContactGroups() +{ + _GroupContainers.clear(); + + // Create default group even if no groups defined + vector > properties; + properties.push_back(make_pair(string("posparent"), string("parent"))); + properties.push_back(make_pair(string("id"), _ContainerID + "_group_0")); + properties.push_back(make_pair(string("title"), "General")); + CInterfaceGroup *group = CWidgetManager::getInstance()->getParser()->createGroupInstance("people_list_group_header", "ui:interface", properties, false); + CGroupContainer *gc = dynamic_cast(group); + gc->setUCTitle(ucstring("General")); + gc->setSavable(false); + + CInterfaceGroup *pRoot = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface")); + pRoot->addGroup (gc); + _BaseContainer->attachContainer(gc); + + _GroupContainers.push_back(make_pair("", gc)); + + const std::string filename = CInterfaceManager::getInstance()->getSaveFileName("contactgroups", "xml"); + try + { + CIFile fd; + if (fd.open(CPath::lookup(filename))) + { + CIXml stream; + stream.init(fd); + + xmlKeepBlanksDefault(0); + xmlNodePtr root = stream.getRootNode(); + + if (!root) return; + + xmlNodePtr node = root->children; + uint nb = 0; + while (node) + { + CXMLAutoPtr propName; + propName = (char*) xmlGetProp(node, (xmlChar*)"name"); + CXMLAutoPtr propGroup; + propGroup = (char*) xmlGetProp(node, (xmlChar*)"group"); + if (propName && propGroup) + { + sint index = getIndexFromName(propName.str()); + if (index < _Peoples.size()) + { + _Peoples[index].Group = propGroup.str(); + if (_GroupContainers.empty() || _GroupContainers.back().first != propGroup.str()) { + vector > properties; + properties.push_back(make_pair(string("posparent"), string("parent"))); + properties.push_back(make_pair(string("id"), _ContainerID + "_group_" + toString(_GroupContainers.size()))); + if (propGroup.str() == "") + properties.push_back(make_pair(string("title"), "General")); + else + properties.push_back(make_pair(string("title"), propGroup.str())); + CInterfaceGroup *group = CWidgetManager::getInstance()->getParser()->createGroupInstance("people_list_group_header", "ui:interface", properties, false); + CGroupContainer *gc = dynamic_cast(group); + if (propGroup.str() == "") + gc->setUCTitle(ucstring("General")); + else + gc->setUCTitle(propGroup.str()); + gc->setSavable(false); + + CInterfaceGroup *pRoot = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface")); + pRoot->addGroup (gc); + _BaseContainer->attachContainer(gc); + + _GroupContainers.push_back(make_pair(propGroup.str(), gc)); + } + } + } + node = node->next; + nb++; + } + fd.close(); + } + std::sort(_GroupContainers.begin(), _GroupContainers.end()); + } + catch (const Exception &e) + { + nlwarning("Error while parsing xml file %s : %s", filename.c_str(), e.what()); + } +} + +//================================================================== +void CPeopleList::saveContactGroups() +{ + const std::string filename = CInterfaceManager::getInstance()->getSaveFileName("contactgroups", "xml"); + try + { + COFile fd; + if (fd.open(filename, false, false, true)) + { + COXml stream; + stream.init(&fd); + + xmlDocPtr doc = stream.getDocument(); + xmlNodePtr node = xmlNewDocNode(doc, NULL, (const xmlChar*)"contact_groups", NULL); + xmlDocSetRootElement(doc, node); + + for (uint k = 0; k < _Peoples.size(); ++k) + { + xmlNodePtr newNode = xmlNewChild(node, NULL, (const xmlChar*)"contact", NULL); + + xmlSetProp(newNode, (const xmlChar*)"name", (const xmlChar*)_Peoples[k].getName().toString().c_str()); + xmlSetProp(newNode, (const xmlChar*)"group", (const xmlChar*)_Peoples[k].Group.toString().c_str()); + } + stream.flush(); + fd.close(); + } + nlinfo("save %s", filename.c_str()); + } + catch (const Exception &e) + { + nlwarning("Error while writing the file %s : %s", filename.c_str(), e.what()); + } +} + //================================================================== void CPeopleList::displayLocalPlayerTell(const ucstring &receiver, uint index, const ucstring &msg,uint numBlinks /*=0*/) { @@ -480,17 +677,21 @@ void CPeopleList::displayLocalPlayerTell(const ucstring &receiver, uint index, c ucstring s = CI18N::get("youTellPlayer"); strFindReplace(s, "%name", receiver); strFindReplace(finalMsg, CI18N::get("youTell"), s); - gl->addChild(getChatTextMngr().createMsgText(finalMsg, prop.getRGBA())); - CInterfaceManager::getInstance()->log(finalMsg, CChatGroup::groupTypeToString(CChatGroup::tell)); - - // if the group is closed, make it blink - if (!gc->isOpen()) - { - if (numBlinks) gc->enableBlink(numBlinks); - } - if (_BaseContainer && !_BaseContainer->isOpen()) + CViewBase *child = getChatTextMngr().createMsgText(finalMsg, prop.getRGBA()); + if (child) { - _BaseContainer->enableBlink(numBlinks); + gl->addChild(child); + CInterfaceManager::getInstance()->log(finalMsg, CChatGroup::groupTypeToString(CChatGroup::tell)); + + // if the group is closed, make it blink + if (!gc->isOpen()) + { + if (numBlinks) gc->enableBlink(numBlinks); + } + if (_BaseContainer && !_BaseContainer->isOpen()) + { + _BaseContainer->enableBlink(numBlinks); + } } } @@ -539,8 +740,9 @@ void CPeopleList::displayMessage(uint index, const ucstring &msg, NLMISC::CRGBA nlwarning(" can't get text_list."); return; } - - gl->addChild(getChatTextMngr().createMsgText(msg, col)); + CViewBase *child = getChatTextMngr().createMsgText(msg, col); + if (child) + gl->addChild(child); } @@ -612,12 +814,12 @@ void CPeopleList::setPeopleMenu(const std::string &menuName) } void CPeopleList::setPeopleMenuEx(const std::string &offlineUnblockedMenuName, - const std::string &onlineUnblockedMenuName, - const std::string &onlineAbroadUnblockedMenuName, - const std::string &offlineBockedMenuName, - const std::string &onlineBlockedMenuName, - const std::string &onlineAbroadBlockedMenuName - ) + const std::string &onlineUnblockedMenuName, + const std::string &onlineAbroadUnblockedMenuName, + const std::string &offlineBockedMenuName, + const std::string &onlineBlockedMenuName, + const std::string &onlineAbroadBlockedMenuName + ) { _PeopleMenuOfflineUnblocked = offlineUnblockedMenuName; _PeopleMenuOnlineUnblocked = onlineUnblockedMenuName; @@ -777,7 +979,7 @@ void CPeopleList::setOnline(uint index, TCharConnectionState online) CCtrlBase *chatButton = hc->getCtrl("chat_button"); if (chatButton != NULL) chatButton->setActive(online != ccs_offline); - + CCtrlBase *inviteButton = hc->getCtrl("invite_button"); if (inviteButton != NULL) inviteButton->setActive(online != ccs_offline); diff --git a/ryzom/client/src/interface_v3/people_list.h b/ryzom/client/src/interface_v3/people_list.h index 32317b6b8..682b1a6e5 100644 --- a/ryzom/client/src/interface_v3/people_list.h +++ b/ryzom/client/src/interface_v3/people_list.h @@ -110,6 +110,11 @@ public: void setContactId(uint index, uint32 contactId); sint getIndexFromContactId(uint32 contactId); + // For Friend Groups management + void changeGroup(uint index, const ucstring &groupName); + void readContactGroups(); + void saveContactGroups(); + /** Display a message for the given people * If the window is closed, it causes it to blink (and also the parent window) */ @@ -151,19 +156,21 @@ public: private: struct CPeople { - CPeople() : Container(NULL), Chat(NULL), Online(ccs_offline), Blocked(false), ContactId(0) {} + CPeople() : Container(NULL), Chat(NULL), Online(ccs_offline), Blocked(false), ContactId(0), Group("") {} NLMISC::CRefPtr Container; // todo : replace this with a CChatWindow one day, for consistency NLMISC::CRefPtr Chat; uint GlobalID; TCharConnectionState Online; bool Blocked; uint32 ContactId; + ucstring Group; bool operator < (const CPeople &other) const { return getName() < other.getName(); } ucstring getName() const { return Container->getUCTitle(); } }; typedef std::vector TPeopleVect; private: CGroupContainerPtr _BaseContainer; + std::vector > > _GroupContainers; NLMISC::CRefPtr _ChatWindow; TPeopleVect _Peoples; CPeopleListDesc::TContactType _ContactType; diff --git a/ryzom/client/src/interface_v3/sphrase_manager.cpp b/ryzom/client/src/interface_v3/sphrase_manager.cpp index 160010f3f..f9dd511d5 100644 --- a/ryzom/client/src/interface_v3/sphrase_manager.cpp +++ b/ryzom/client/src/interface_v3/sphrase_manager.cpp @@ -411,7 +411,7 @@ void CSPhraseManager::forgetPhrase(uint32 memoryLine, uint32 memorySlot) _Memories[memoryLine].Slot[memorySlot].Id= 0; // must update DB? - if((sint32)memoryLine==_SelectedMemoryDB) + if((sint32)memoryLine==_SelectedMemoryDB || (sint32)memoryLine==_SelectedMemoryDBalt) { // update the db updateMemoryDBSlot(memorySlot); @@ -465,7 +465,7 @@ void CSPhraseManager::memorizePhrase(uint32 memoryLine, uint32 memorySlot, ui _Memories[memoryLine].Slot[memorySlot].Id= slot; // must update DB? - if((sint32)memoryLine==_SelectedMemoryDB) + if((sint32)memoryLine==_SelectedMemoryDB || (sint32)memoryLine==_SelectedMemoryDBalt) { // update the DB updateMemoryDBSlot(memorySlot); @@ -3276,7 +3276,7 @@ void CSPhraseManager::memorizeMacro(uint32 memoryLine, uint32 memorySlot, uint32 _Memories[memoryLine].Slot[memorySlot].Id= macroId; // must update DB? - if((sint32)memoryLine==_SelectedMemoryDB) + if((sint32)memoryLine==_SelectedMemoryDB || (sint32)memoryLine==_SelectedMemoryDBalt) { // update the DB updateMemoryDBSlot(memorySlot); @@ -3302,7 +3302,7 @@ void CSPhraseManager::forgetMacro(uint32 memoryLine, uint32 memorySlot) _Memories[memoryLine].Slot[memorySlot].Id= 0; // must update DB? - if((sint32)memoryLine==_SelectedMemoryDB) + if((sint32)memoryLine==_SelectedMemoryDB || (sint32)memoryLine==_SelectedMemoryDBalt) { // update the db updateMemoryDBSlot(memorySlot); diff --git a/ryzom/client/src/item_group_manager.cpp b/ryzom/client/src/item_group_manager.cpp index fddba873f..82a60f478 100644 --- a/ryzom/client/src/item_group_manager.cpp +++ b/ryzom/client/src/item_group_manager.cpp @@ -733,6 +733,12 @@ std::string CItemGroupManager::toDbPath(INVENTORIES::TInventory inventory) return LIST_PA2_TEXT; break; case INVENTORIES::pet_animal4: return LIST_PA3_TEXT; break; + case INVENTORIES::pet_animal5: + return LIST_PA4_TEXT; break; + case INVENTORIES::pet_animal6: + return LIST_PA5_TEXT; break; + case INVENTORIES::pet_animal7: + return LIST_PA6_TEXT; break; case INVENTORIES::player_room: return LIST_ROOM_TEXT;break; case INVENTORIES::guild: diff --git a/ryzom/client/src/login_patch.cpp b/ryzom/client/src/login_patch.cpp index 926ed61b1..0a6b912dd 100644 --- a/ryzom/client/src/login_patch.cpp +++ b/ryzom/client/src/login_patch.cpp @@ -245,7 +245,7 @@ void CPatchManager::init(const std::vector& patchURIs, const std::s #endif // App name matches Domain on the SQL server - std::string appName = cf->getVarPtr("Application") + std::string appName = cf->getVarPtr("Application") ? cf->getVar("Application").asString(0) : "default"; @@ -1354,7 +1354,7 @@ void CPatchManager::getServerFile (const std::string &name, bool bZipped, const { //nlwarning("EXCEPTION CATCH: getServerFile() failed - try to find an alternative: %i: %s",UsedServer,PatchServers[UsedServer].DisplayedServerPath.c_str()); - nlwarning("EXCEPTION CATCH: getServerFile() failed - try to find an alternative :"); + nlwarning("EXCEPTION CATCH: getServerFile() failed - try to find an alternative : %s", (serverPath+srcName).c_str()); nlwarning("%i", UsedServer); if (UsedServer >= 0 && UsedServer < (int) PatchServers.size()) { @@ -2676,6 +2676,7 @@ void CPatchThread::processFile (CPatchManager::SFileToPatch &rFTP) string OutFilename; bool usePatchFile = true; + bool haveAllreadyTryiedDownloadingOfFile = false; // compute the total size of patch to download uint32 totalPatchSize = 0; @@ -2743,6 +2744,7 @@ void CPatchThread::processFile (CPatchManager::SFileToPatch &rFTP) { // can not load the 7zip file, use normal patching usePatchFile = true; + haveAllreadyTryiedDownloadingOfFile = true; break; } @@ -2754,6 +2756,7 @@ void CPatchThread::processFile (CPatchManager::SFileToPatch &rFTP) { // fallback to standard patch method usePatchFile = true; + haveAllreadyTryiedDownloadingOfFile = true; break; } } @@ -2766,6 +2769,7 @@ void CPatchThread::processFile (CPatchManager::SFileToPatch &rFTP) nlwarning("Failed to unpack lzma file %s", (pPM->ClientPatchPath+lzmaFile).c_str()); // fallback to standard patch method usePatchFile = true; + haveAllreadyTryiedDownloadingOfFile = true; break; } @@ -2874,32 +2878,108 @@ void CPatchThread::processFile (CPatchManager::SFileToPatch &rFTP) sTranslate = CI18N::get("uiApplyingDelta") + " " + CFile::getFilename(PatchName); pPM->setState(true, sTranslate); - xDeltaPatch(PatchName, SourceNameXD, OutFilename); + bool deltaPatchResult = xDeltaPatch(PatchName, SourceNameXD, OutFilename); - if (rFTP.LocalFileExists) - pPM->deleteFile(SourceName); - pPM->deleteFile(PatchName); - - if (j > 0) + if (!deltaPatchResult && !haveAllreadyTryiedDownloadingOfFile) // Patch failed, try to download and apply lzma { - pPM->deleteFile(SourceNameXD, false, false); // File can exists if bad BNP loading - } - tmpSourceName = OutFilename; - PatchSizeProgress += rFTP.PatcheSizes[j]; - currentPatchedSize += rFTP.PatcheSizes[j]; - } + breakable + { + // compute the seven zip filename + string lzmaFile = rFTP.FileName+".lzma"; - if (tmpSourceName != DestinationName) - { - pPM->deleteFile(SourceName, false, false); // File can exists if bad BNP loading - if (!_CommitPatch) - { - // let the patch in the unpack directory - pPM->renameFile(tmpSourceName, pPM->ClientPatchPath + rFTP.FileName + ".tmp"); + // download the 7zip file + try + { + // first, try in the file version subfolfer + try + { + progress.Scale = 1.f; + progress.Bias = 0.f; + if (!rFTP.Patches.empty()) + { + pPM->getServerFile(toString("%05u/", rFTP.Patches.back())+lzmaFile, false, "", &progress); + } + // else -> file comes from a previous download (with .tmp extension, and is up to date) + // the remaining code will just rename it with good name and exit + } + catch (const NLMISC::EWriteError &) + { + // this is a local error, rethrow ... + throw; + } + catch(...) + { + // failed with version subfolder, try in the root patch directory + pPM->getServerFile(lzmaFile, false, "", &progress); + } + } + catch (const NLMISC::EWriteError &) + { + // this is a local error, rethrow ... + throw; + } + catch (...) + { + break; + } + + OutFilename = pPM->ClientPatchPath + NLMISC::CFile::getFilename(rFTP.FileName); + // try to unpack the file + try + { + if (!unpackLZMA(pPM->ClientPatchPath+lzmaFile, OutFilename+".tmp")) + { + break; + } + } + catch (const NLMISC::EWriteError&) + { + throw; + } + catch (...) + { + nlwarning("Failed to unpack lzma file %s", (pPM->ClientPatchPath+lzmaFile).c_str()); + break; + } + + if (rFTP.LocalFileExists) + pPM->deleteFile(SourceName); + + pPM->deleteFile(pPM->ClientPatchPath+lzmaFile); // delete the archive file + pPM->deleteFile(SourceName, false, false); // File can exists if bad BNP loading + if (_CommitPatch) + { + pPM->renameFile(OutFilename+".tmp", DestinationName); + } + } } else { - pPM->renameFile(tmpSourceName, DestinationName); + if (rFTP.LocalFileExists) + pPM->deleteFile(SourceName); + pPM->deleteFile(PatchName); + + if (j > 0) + { + pPM->deleteFile(SourceNameXD, false, false); // File can exists if bad BNP loading + } + tmpSourceName = OutFilename; + PatchSizeProgress += rFTP.PatcheSizes[j]; + currentPatchedSize += rFTP.PatcheSizes[j]; + } + + if (tmpSourceName != DestinationName) + { + pPM->deleteFile(SourceName, false, false); // File can exists if bad BNP loading + if (!_CommitPatch) + { + // let the patch in the unpack directory + pPM->renameFile(tmpSourceName, pPM->ClientPatchPath + rFTP.FileName + ".tmp"); + } + else + { + pPM->renameFile(tmpSourceName, DestinationName); + } } } } @@ -2915,7 +2995,7 @@ void CPatchThread::processFile (CPatchManager::SFileToPatch &rFTP) } // **************************************************************************** -void CPatchThread::xDeltaPatch(const string &patch, const string &src, const string &out) +bool CPatchThread::xDeltaPatch(const string &patch, const string &src, const string &out) { // Internal xdelta @@ -2941,12 +3021,13 @@ void CPatchThread::xDeltaPatch(const string &patch, const string &src, const str break; default: { - std::string str = toString("Error applying %s to %s giving %s", patch.c_str(), src.c_str(), out.c_str()); - throw Exception (str); + nlinfo("Error applying %s to %s giving %s", patch.c_str(), src.c_str(), out.c_str()); + return false; } break; } - } + } else + return true; // Launching xdelta diff --git a/ryzom/client/src/login_patch.h b/ryzom/client/src/login_patch.h index 2b108994d..7c0a68b2d 100644 --- a/ryzom/client/src/login_patch.h +++ b/ryzom/client/src/login_patch.h @@ -269,6 +269,7 @@ public: void setStartRyzomAtEnd(bool startAtEnd){ _StartRyzomAtEnd = startAtEnd; } // Forward message to installation software if needed void fatalError(const std::string& errorId, const std::string& param1, const std::string& param2); + bool bnpUnpack(const std::string &srcBigfile, const std::string &dstPath, std::vector &vFilenames); const std::string & getServerVersion () { return ServerVersion; } private: @@ -320,8 +321,6 @@ private: void getPatchFromDesc(SFileToPatch &ftpOut, const CBNPFile &fIn, bool forceCheckSumTest); - bool bnpUnpack(const std::string &srcBigfile, const std::string &dstPath, std::vector &vFilenames); - // stop the threads (called when knowing the thread ended) void stopCheckThread(); void stopPatchThread(); @@ -547,7 +546,7 @@ private: void run(); void processFile (CPatchManager::SFileToPatch &rFTP); - void xDeltaPatch(const std::string &patch, const std::string &src, const std::string &out); + bool xDeltaPatch(const std::string &patch, const std::string &src, const std::string &out); }; /** diff --git a/ryzom/client/src/net_manager.cpp b/ryzom/client/src/net_manager.cpp index 642935869..c6da153bc 100644 --- a/ryzom/client/src/net_manager.cpp +++ b/ryzom/client/src/net_manager.cpp @@ -147,6 +147,7 @@ extern bool CharNameValidArrived; extern bool CharNameValid; bool IsInRingSession = false; TSessionId HighestMainlandSessionId; // highest in the position stack +ucstring lastUniversMessage; extern const char *CDBBankNames[INVALID_CDB_BANK+1]; @@ -770,7 +771,11 @@ void CInterfaceChatDisplayer::displayChat(TDataSetIndex compressedSenderIndex, c } else if (mode == CChatGroup::universe) { - PeopleInterraction.ChatInput.Universe.displayMessage(finalString, col, 2, &windowVisible); + if (lastUniversMessage != finalString) + { + PeopleInterraction.ChatInput.Universe.displayMessage(finalString, col, 2, &windowVisible); + lastUniversMessage = finalString; + } } else if (mode == CChatGroup::dyn_chat) { diff --git a/ryzom/client/src/string_manager_client.cpp b/ryzom/client/src/string_manager_client.cpp index 06c3523b4..a10be8114 100644 --- a/ryzom/client/src/string_manager_client.cpp +++ b/ryzom/client/src/string_manager_client.cpp @@ -390,7 +390,7 @@ restartLoop4: else { result = it->second; - if (result.size() > 9 && result.substr(0, 9) == ucstring(" 9 && result.substr(0, 9) == ucstring("::iterator itds = _DynStrings.find(result.substr(9, result.size()-10)); if (itds != _DynStrings.end()) @@ -747,6 +747,12 @@ restartLoop: str = CEntityCL::removeTitleFromName(str); } + // if the string contains a special rename of creature, remove it + if (str.size() > 2 && str[0] == '<' && str[1] == '#') + { + str = toUpper(str[2])+str.substr(3); + } + // append this string temp.append(move, src+param.ReplacementPoint); temp += str; @@ -1625,7 +1631,7 @@ const ucchar *CStringManagerClient::getTitleLocalizedName(const ucstring &titleI _TitleWords.push_back(listInfos[0]); return getLocalizedName(_TitleWords.back()); } - + return getLocalizedName(titleId); } diff --git a/ryzom/tools/client/client_patcher/main.cpp b/ryzom/tools/client/client_patcher/main.cpp index e7d57a335..62937dd59 100644 --- a/ryzom/tools/client/client_patcher/main.cpp +++ b/ryzom/tools/client/client_patcher/main.cpp @@ -200,9 +200,38 @@ int main(int argc, char *argv[]) Args.setVersion(getDisplayVersion()); Args.setDescription("Ryzom client"); + Args.addArg("p", "patch", "patch", "Name of the file to use tp xdelta the source file"); + Args.addArg("s", "source", "source", "Name of source file to xdelta with patch file"); + Args.addArg("d", "destination", "destination", "Name of destination operation (patch or unpack)"); + Args.addArg("u", "unpack", "unpack", "Name of bnp file to unpack"); if (!Args.parse(argc, argv)) return 1; + if (Args.haveArg("p") && Args.haveArg("p") && Args.haveArg("p")) + { + string patchName = Args.getArg("p").front(); + string sourceName = Args.getArg("s").front(); + string destinationName = Args.getArg("d").front(); + + std::string errorMsg; + CXDeltaPatch::TApplyResult ar = CXDeltaPatch::apply(patchName, sourceName, destinationName, errorMsg); + nlinfo("%s", errorMsg.c_str()); + return ar; + } + + // initialize patch manager and set the ryzom full path, before it's used + CPatchManager *pPM = CPatchManager::getInstance(); + + if (Args.haveArg("u") && Args.haveArg("d")) + { + string bnpName = Args.getArg("u").front(); + string destinationName = Args.getArg("d").front(); + vector vFilenames; + if (pPM->bnpUnpack(bnpName, destinationName, vFilenames)) + return 0; + return 1; + } + // create logs in temporary directory createDebug(CPath::getTemporaryDirectory().c_str(), true, true); @@ -244,8 +273,6 @@ int main(int argc, char *argv[]) printf("\n"); printf("Checking %s files to patch...\n", convert(CI18N::get("TheSagaOfRyzom")).c_str()); - // initialize patch manager and set the ryzom full path, before it's used - CPatchManager *pPM = CPatchManager::getInstance(); // use PatchUrl vector patchURLs;