From cf357edcb9fff57b14aafbd6374ea78828d90b01 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 3 Jun 2016 14:24:56 +0300 Subject: [PATCH 001/303] Added: Interface auto scaling to view renderer --HG-- branch : experimental-ui-scaling --- code/nel/include/nel/gui/view_renderer.h | 15 ++++- code/nel/src/gui/view_renderer.cpp | 77 +++++++++++++++++++----- 2 files changed, 76 insertions(+), 16 deletions(-) diff --git a/code/nel/include/nel/gui/view_renderer.h b/code/nel/include/nel/gui/view_renderer.h index a54708b04..c737037a1 100644 --- a/code/nel/include/nel/gui/view_renderer.h +++ b/code/nel/include/nel/gui/view_renderer.h @@ -176,6 +176,12 @@ namespace NLGUI */ void getScreenOOSize (float &oow, float &ooh); + /* + * UI scaling + */ + void setInterfaceScale(float scale, sint32 width = 0, sint32 height = 0); + float getInterfaceScale() const { return _InterfaceScale; } + /* * is the Screen minimized? */ @@ -526,6 +532,13 @@ namespace NLGUI float _OneOverScreenW, _OneOverScreenH; bool _IsMinimized; + // UI scaling + float _InterfaceScale; + float _InterfaceUserScale; + sint32 _InterfaceBaseW, _InterfaceBaseH; + sint32 _EffectiveScreenW, _EffectiveScreenH; + + void updateInterfaceScale(); //map linking a uint to a bitmap. Used to display figurs std::vector _IndexesToTextureIds; @@ -585,14 +598,12 @@ namespace NLGUI static CViewRenderer *instance; static NL3D::UDriver *driver; static NL3D::UTextContext *textcontext; - public: static NL3D::UTextContext* getTextContext(){ return textcontext; } /// Set of hw cursor images static std::set< std::string > *hwCursors; static float hwCursorScale; - }; diff --git a/code/nel/src/gui/view_renderer.cpp b/code/nel/src/gui/view_renderer.cpp index 0b4d837f3..b2d793e46 100644 --- a/code/nel/src/gui/view_renderer.cpp +++ b/code/nel/src/gui/view_renderer.cpp @@ -91,16 +91,13 @@ namespace NLGUI if(w!=0 && h!=0) { _IsMinimized= false; - _ScreenW = w; - _ScreenH = h; - if(_ScreenW>0) - _OneOverScreenW = 1.0f / (float)_ScreenW; - else - _OneOverScreenW = 1000; - if(_ScreenH>0) - _OneOverScreenH = 1.0f / (float)_ScreenH; - else - _OneOverScreenH = 1000; + if (w != _ScreenW || h != _ScreenH) + { + _ScreenW = w; + _ScreenH = h; + + updateInterfaceScale(); + } } else { @@ -109,14 +106,48 @@ namespace NLGUI } } + void CViewRenderer::updateInterfaceScale() + { + if(_ScreenW>0) + _OneOverScreenW = 1.0f / (float)_ScreenW; + else + _OneOverScreenW = 1000; + if(_ScreenH>0) + _OneOverScreenH = 1.0f / (float)_ScreenH; + else + _OneOverScreenH = 1000; + + _InterfaceScale = _InterfaceUserScale; + if (_InterfaceBaseW > 0 && _InterfaceBaseH > 0) + { + float wRatio = (float)_ScreenW / _InterfaceBaseW; + float rRatio = (float)_ScreenH / _InterfaceBaseH; + _InterfaceScale *= std::min(wRatio, rRatio); + } + + if (_InterfaceScale != 1.0f) + { + _OneOverScreenW *= _InterfaceScale; + _OneOverScreenH *= _InterfaceScale; + + _EffectiveScreenW = sint(_ScreenW / _InterfaceScale); + _EffectiveScreenH = sint(_ScreenH / _InterfaceScale); + } + else + { + _EffectiveScreenW = _ScreenW; + _EffectiveScreenH = _ScreenH; + } + } + /* * getScreenSize : get the screen window size */ void CViewRenderer::getScreenSize (uint32 &w, uint32 &h) { - w = _ScreenW; - h = _ScreenH; + w = _EffectiveScreenW; + h = _EffectiveScreenH; } /* @@ -128,6 +159,20 @@ namespace NLGUI ooh= _OneOverScreenH; } + void CViewRenderer::setInterfaceScale(float scale, sint32 width/*=0*/, sint32 height/*=0*/) + { + // prevent #div/0 + if (sint(scale*100) > 0) + _InterfaceUserScale = scale; + else + _InterfaceUserScale = 1.0f; + + _InterfaceBaseW = width; + _InterfaceBaseH = height; + + updateInterfaceScale(); + } + void CViewRenderer::setup() { _ClipX = _ClipY = 0; @@ -135,8 +180,10 @@ namespace NLGUI _ClipH = 600; _ScreenW = 800; _ScreenH = 600; - _OneOverScreenW= 1.0f / (float)_ScreenW; - _OneOverScreenH= 1.0f / (float)_ScreenH; + _InterfaceScale = 1.0f; + _InterfaceUserScale = 1.0f; + _InterfaceBaseW = 0; + _InterfaceBaseH = 0; _IsMinimized= false; _WFigurTexture= 0; _HFigurTexture= 0; @@ -152,6 +199,8 @@ namespace NLGUI _EmptyLayer[i]= true; } _BlankGlobalTexture = NULL; + + updateInterfaceScale(); } From b474f39970c7af55527f2638a2cbfe8b734bffee Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 3 Jun 2016 14:26:17 +0300 Subject: [PATCH 002/303] Added: Scaling options to client config --HG-- branch : experimental-ui-scaling --- .../data/gamedev/interfaces_v3/game_config.xml | 16 +++++++++++++++- code/ryzom/client/src/client_cfg.cpp | 6 ++++++ code/ryzom/client/src/client_cfg.h | 3 +++ code/ryzom/client/src/connection.cpp | 11 +++++++++++ code/ryzom/client/src/init.cpp | 1 + .../src/interface_v3/interface_manager.cpp | 10 ++++++++++ .../client/src/interface_v3/interface_manager.h | 3 +++ code/ryzom/client/src/main_loop_utilities.cpp | 6 +++++- 8 files changed, 54 insertions(+), 2 deletions(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml b/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml index 38e63cb24..001d2be1d 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml @@ -878,10 +878,17 @@ posparent="lum" x="0" y="-2" /> + @@ -3086,6 +3093,13 @@ realtime="true" widget="sbfloat" link="Gamma" /> + setInterfaceScale(ClientCfg.InterfaceScale); } @@ -290,6 +293,8 @@ void setOutGameFullScreen() */ } + // Enable auto scaling in login window + CViewRenderer::getInstance()->setInterfaceScale(1.0f, 1024, 768); } @@ -454,6 +459,9 @@ bool connection (const string &cookie, const string &fsaddr) firstConnection = false; + // Restore user UI scaling + CViewRenderer::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale); + // Disable inputs Actions.enable(false); EditActions.enable(false); @@ -586,6 +594,9 @@ bool reconnection() InterfaceState = globalMenu(); } + // Restore user UI scaling + CViewRenderer::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale); + // Disable inputs Actions.enable(false); EditActions.enable(false); diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index 7b1ca728f..8105d9351 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -1316,6 +1316,7 @@ void prelogInit() CInterfaceManager::getInstance(); + CViewRenderer::getInstance()->setInterfaceScale(1.0f, 1024, 768); // Yoyo: initialize NOW the InputHandler for Event filtering. CInputHandlerManager *InputHandlerManager = CInputHandlerManager::getInstance(); diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 3e2a0ba0e..802f98c70 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -475,6 +475,8 @@ CInterfaceManager::CInterfaceManager() interfaceLinkUpdater = new CInterfaceLink::CInterfaceLinkUpdater(); _ScreenW = _ScreenH = 0; _LastInGameScreenW = _LastInGameScreenH = 0; + _InterfaceScaleChanged = false; + _InterfaceScale = 1.0f; _DescTextTarget = NULL; _ConfigLoaded = false; _LogState = false; @@ -1984,6 +1986,14 @@ void CInterfaceManager::drawViews(NL3D::UCamera camera) _CurrentPlayerCharac[i] = node ? node->getValue32() : 0; } + // update value change from ingame config window + // must update it here, right before widget manager checks it + if (_InterfaceScaleChanged) + { + CViewRenderer::getInstance()->setInterfaceScale(_InterfaceScale); + _InterfaceScaleChanged = false; + } + CWidgetManager::getInstance()->drawViews( camera ); // flush obs diff --git a/code/ryzom/client/src/interface_v3/interface_manager.h b/code/ryzom/client/src/interface_v3/interface_manager.h index 6025868e5..c5c641033 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.h +++ b/code/ryzom/client/src/interface_v3/interface_manager.h @@ -543,6 +543,7 @@ public: NLMISC::CCDBNodeLeaf *_DB_UI_DUMMY_FACTION_TYPE; void updateDesktops( uint32 newScreenW, uint32 newScreenH ); + void setInterfaceScale( float scale ) { _InterfaceScaleChanged = true; _InterfaceScale = scale; } private: @@ -581,6 +582,8 @@ private: uint32 _ScreenW, _ScreenH; // Change res detection sint32 _LastInGameScreenW, _LastInGameScreenH; // Resolution used for last InGame interface + float _InterfaceScale; + bool _InterfaceScaleChanged; // Modes CInterfaceConfig::CDesktopImage _Modes[MAX_NUM_MODES]; diff --git a/code/ryzom/client/src/main_loop_utilities.cpp b/code/ryzom/client/src/main_loop_utilities.cpp index 415764bfa..e62c033e4 100644 --- a/code/ryzom/client/src/main_loop_utilities.cpp +++ b/code/ryzom/client/src/main_loop_utilities.cpp @@ -36,6 +36,7 @@ #include "input.h" #include "sound_manager.h" #include "camera.h" +#include "interface_v3/interface_manager.h" using namespace NLMISC; using namespace NL3D; @@ -100,6 +101,9 @@ void updateFromClientCfg() Driver->forceTextureResize(1); } + if (ClientCfg.InterfaceScale != LastClientCfg.InterfaceScale) + CInterfaceManager::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale); + //--------------------------------------------------- if (ClientCfg.WaitVBL != LastClientCfg.WaitVBL) { @@ -395,4 +399,4 @@ void updateFromClientCfg() LastClientCfg = ClientCfg; } -/* end of file */ \ No newline at end of file +/* end of file */ From 8965ce50d5fa03d5b0923930874e033e60fa4131 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 3 Jun 2016 16:02:37 +0300 Subject: [PATCH 003/303] Changed: Font scaling --HG-- branch : experimental-ui-scaling --- code/nel/include/nel/gui/view_text.h | 12 ++- code/nel/src/gui/view_renderer.cpp | 19 ++++ code/nel/src/gui/view_text.cpp | 140 ++++++++++++++------------- 3 files changed, 100 insertions(+), 71 deletions(-) diff --git a/code/nel/include/nel/gui/view_text.h b/code/nel/include/nel/gui/view_text.h index 95507ffe3..c814bcb7b 100644 --- a/code/nel/include/nel/gui/view_text.h +++ b/code/nel/include/nel/gui/view_text.h @@ -232,12 +232,14 @@ namespace NLGUI bool _Embolden; bool _Oblique; // width of the font in pixel. Just a Hint for tabing format (computed with '_') - uint _FontWidth; + float _FontWidth; // height of the font in pixel. // use getFontHeight - uint _FontHeight; - uint _FontLegHeight; + float _FontHeight; + float _FontLegHeight; float _SpaceWidth; + /// last UI scale used to calculate font size + float _Scale; /// the text color NLMISC::CRGBA _Color; /// the shadow mode @@ -333,8 +335,8 @@ namespace NLGUI // Clear the line & remove text contexts void clear(); // Add a new word (and its context) in the line + a number of spaces to append at the end of the line - void addWord(const ucstring &word, uint numSpaces, const CFormatInfo &wordFormat, uint fontWidth); - void addWord(const CWord &word, uint fontWidth); + void addWord(const ucstring &word, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth); + void addWord(const CWord &word, float fontWidth); uint getNumWords() const { return (uint)_Words.size(); } CWord &getWord(uint index) { return _Words[index]; } float getSpaceWidth() const { return _SpaceWidth; } diff --git a/code/nel/src/gui/view_renderer.cpp b/code/nel/src/gui/view_renderer.cpp index b2d793e46..f8a8152b9 100644 --- a/code/nel/src/gui/view_renderer.cpp +++ b/code/nel/src/gui/view_renderer.cpp @@ -1938,6 +1938,25 @@ namespace NLGUI void CViewRenderer::drawText (sint layerId, float x, float y, uint wordIndex, float xmin, float ymin, float xmax, float ymax, UTextContext &textContext) { + xmin = xmin * _OneOverScreenW; + ymin = ymin * _OneOverScreenH; + xmax = xmax * _OneOverScreenW; + ymax = ymax * _OneOverScreenH; + + if (_InterfaceScale != 1.0f && _InterfaceScale != 2.0f) + { + // align to screen pixel + x *= _OneOverScreenW * _ScreenW; + y *= _OneOverScreenH * _ScreenH; + x = floorf(x) * 1.f / (float) _ScreenW; + y = floorf(y) * 1.f / (float) _ScreenH; + } + else + { + x = floorf(x) * _OneOverScreenW; + y = floorf(y) * _OneOverScreenH; + } + if (_WorldSpaceTransformation) { textContext.printClipAtUnProjected(*getStringRenderBuffer(layerId), _CameraFrustum, _WorldSpaceMatrix, x, y, _CurrentZ, wordIndex, xmin, ymin, xmax, ymax); diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index 8c2ca96d3..6a66bdf74 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -79,6 +79,7 @@ namespace NLGUI _MultiMaxLine = 0; _Index = 0xFFFFFFFF; + _Scale = 1.0f; _FontWidth= 0; _FontHeight = 0; _FontLegHeight = 0; @@ -877,12 +878,13 @@ namespace NLGUI // *************************************************************************** sint CViewText::getCurrentMultiLineMaxW() const { + sint maxw = ceilf(_LineMaxW * _Scale); if(_MultiLineMaxWOnly) - return _LineMaxW; + return maxw; else { sint parentWidth = std::min(_Parent->getMaxWReal(), _Parent->getWReal()); - return std::min(parentWidth-(sint)(_XReal-_Parent->getXReal()), (sint)_LineMaxW); + return std::min(parentWidth-(sint)(_XReal-_Parent->getXReal()), maxw); } } @@ -890,6 +892,9 @@ namespace NLGUI // *************************************************************************** void CViewText::checkCoords () { + if (_Scale != CViewRenderer::getInstance()->getInterfaceScale()) + invalidateContent(); + if ((_MultiLine)&&(_Parent != NULL)) { // If never setuped, and if text is not empty @@ -943,6 +948,8 @@ namespace NLGUI CViewRenderer &rVR = *CViewRenderer::getInstance(); + //rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(64,64,64,255)); + // *** Out Of Clip? sint32 ClipX, ClipY, ClipW, ClipH; rVR.getClipWindow (ClipX, ClipY, ClipW, ClipH); @@ -951,12 +958,8 @@ namespace NLGUI return; // *** Screen Minimized? - uint32 w, h; - float oow, ooh; - rVR.getScreenSize (w, h); if (rVR.isMinimized()) return; - rVR.getScreenOOSize (oow, ooh); NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); @@ -989,22 +992,22 @@ namespace NLGUI TextContext->setShaded (_Shadow); TextContext->setShadeOutline (_ShadowOutline); TextContext->setShadeColor (shcol); - TextContext->setFontSize (_FontSize); + TextContext->setFontSize (_FontSize*_Scale); TextContext->setEmbolden (_Embolden); TextContext->setOblique (_Oblique); - float y = (float)(_YReal) * ooh; // y is expressed in scree, coordinates [0..1] + float y = _YReal; //y += _LinesInfos[_LinesInfos.size()-1].StringLine / h; // Y is the base line of the string, so it must be grown up. - y += (float)_FontLegHeight * ooh; + y += _FontLegHeight; - sint y_line = _YReal+_FontLegHeight-2; + sint y_line = _YReal+_FontLegHeight-2.0f*_Scale; if (_MultiMinLine > _Lines.size()) { uint dy = getMultiMinOffsetY(); - y += dy * ooh; + y += dy; y_line += dy; } @@ -1076,8 +1079,7 @@ namespace NLGUI px= max(px, (float)(_XReal + currWord.Format.TabX*_FontWidth)); // draw. We take floorf px to avoid filtering of letters that are not located on a pixel boundary - rVR.drawText (_RenderLayer, floorf(px) * oow, y, currWord.Index, (float)ClipX * oow, (float)ClipY * ooh, - (float)(ClipX+ClipW) * oow, (float)(ClipY+ClipH) * ooh, *TextContext); + rVR.drawText (_RenderLayer, px, y, currWord.Index, ClipX, ClipY, ClipX+ClipW, ClipY+ClipH, *TextContext); // Draw a line if (_Underlined) @@ -1090,7 +1092,7 @@ namespace NLGUI px += currWord.Info.StringWidth; } // go one line up - y += (_FontHeight + _MultiLineSpace) * ooh; + y += (_FontHeight + _MultiLineSpace); y_line += _FontHeight+_MultiLineSpace; } @@ -1116,22 +1118,19 @@ namespace NLGUI TextContext->setShaded (_Shadow); TextContext->setShadeOutline (_ShadowOutline); TextContext->setShadeColor (shcol); - TextContext->setFontSize (_FontSize); + TextContext->setFontSize (_FontSize*_Scale); TextContext->setEmbolden (_Embolden); TextContext->setOblique (_Oblique); - if(_LetterColors!=NULL && !TextContext->isSameLetterColors(_LetterColors, _Index)) { TextContext->setLetterColors(_LetterColors, _Index); } - - float x = (float)(_XReal) * oow; - float y = (float)(_YReal) * ooh; + float y = _YReal; // Y is the base line of the string, so it must be grown up. - y += (float)_FontLegHeight * ooh; + y += _FontLegHeight; // special selection code if(_TextSelection) @@ -1142,12 +1141,11 @@ namespace NLGUI TextContext->setStringColor(_Index, col); // draw - rVR.drawText (_RenderLayer, x, y, _Index, (float)ClipX * oow, (float)ClipY * ooh, - (float)(ClipX+ClipW) * oow, (float)(ClipY+ClipH) * ooh, *TextContext); + rVR.drawText (_RenderLayer, _XReal, y, _Index, ClipX, ClipY, ClipX+ClipW, ClipY+ClipH, *TextContext); // Draw a line if (_Underlined) - rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_FontLegHeight-2, _WReal, 1, 0, false, rVR.getBlankTextureId(), col); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_FontLegHeight-2.0f*_Scale, _WReal, 1, 0, false, rVR.getBlankTextureId(), col); if (_StrikeThrough) rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+(_FontLegHeight/2), _WReal, 1, 0, false, rVR.getBlankTextureId(), col); @@ -1336,7 +1334,7 @@ namespace NLGUI sint32 value; if(CLuaIHM::popSINT32(ls, value)) { - setLineMaxW(value); + setLineMaxW(ceilf(value / _Scale)); } return 0; } @@ -1463,7 +1461,7 @@ namespace NLGUI ucstring ucStrLetter; ucStrLetter= ucLetter; si = TextContext->getStringInfo (ucStrLetter); - rWidthLetter = (si.StringWidth); + rWidthLetter = (si.StringWidth / _Scale); if ((rWidthCurrentLine + rWidthLetter) > nMaxWidth) { flushWordInLine(ucCurrentWord, linePushed, wordFormat); @@ -1538,7 +1536,7 @@ namespace NLGUI static const ucstring spaceStr(" "); // precLineWidth valid only id precedent line is part of same paragraph. float precLineWidth= 0; - float lineWidth = (float)_FirstLineX; // width of the current line + float lineWidth = (float)_FirstLineX * _Scale; // width of the current line uint numWordsInLine = 0; // number of words in the current line bool isParagraphStart = true; // A paragraph is a group of characters between 2 \n bool lineFeed; @@ -1554,7 +1552,7 @@ namespace NLGUI TCharPos spaceEnd; TCharPos wordEnd; uint numSpaces; - float newLineWidth; + float newLineWidth = 0; breakLine = false; // if (_Text[currPos] == (ucchar) '\n') @@ -1629,7 +1627,7 @@ namespace NLGUI // compute size of spaces/Tab + word newLineWidth = lineWidth + numSpaces * _SpaceWidth; newLineWidth = max(newLineWidth, (float)wordFormat.TabX*_FontWidth); - newLineWidth+= si.StringWidth; + newLineWidth+= si.StringWidth / _Scale; } // // Does the word go beyond the end of line ? @@ -1704,8 +1702,8 @@ namespace NLGUI { oneChar = wordValue[currChar]; si = CViewRenderer::getTextContext()->getStringInfo(oneChar); - if ((uint) (px + si.StringWidth) > nMaxWidth) break; - px += si.StringWidth; + if ((uint) (px + si.StringWidth / _Scale) > nMaxWidth) break; + px += si.StringWidth / _Scale; } currChar = std::max((uint) 1, currChar); // must fit at least one character otherwise there's an infinite loop wordValue = _Text.substr(spaceEnd, currChar); @@ -1822,12 +1820,15 @@ namespace NLGUI // *************************************************************************** void CViewText::updateTextContext () { + if (_Scale != CViewRenderer::getInstance()->getInterfaceScale()) + computeFontSize(); + NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); TextContext->setHotSpot (UTextContext::BottomLeft); TextContext->setShaded (_Shadow); TextContext->setShadeOutline (_ShadowOutline); - TextContext->setFontSize (_FontSize); + TextContext->setFontSize (_FontSize*_Scale); TextContext->setEmbolden (_Embolden); TextContext->setOblique (_Oblique); @@ -1836,7 +1837,7 @@ namespace NLGUI if ((_MultiLine)&&(_Parent != NULL)) { - sint nMaxWidth = getCurrentMultiLineMaxW(); + float nMaxWidth = getCurrentMultiLineMaxW(); _LastMultiLineMaxW = nMaxWidth; clearLines(); if (nMaxWidth <= 0) @@ -1873,8 +1874,8 @@ namespace NLGUI { rTotalW = std::max(_Lines[i]->getWidth() + ((i==0)?_FirstLineX:0), rTotalW); } - _W = (sint)rTotalW; - _H = std::max(_FontHeight, uint(_FontHeight * _Lines.size() + std::max(0, sint(_Lines.size()) - 1) * _MultiLineSpace)); + _W = (sint)ceilf(rTotalW); + _H = std::max(_FontHeight, ceilf(_FontHeight * _Lines.size() + std::max(0, sint(_Lines.size()) - 1) * _MultiLineSpace)); // See if we should pretend to have at least X lines if (_MultiMinLine > 1) @@ -1895,7 +1896,7 @@ namespace NLGUI { CCtrlToolTip *pTooltip = _Tooltips[word.Format.IndexTt]; - sint y = (sint) ((_FontHeight + _MultiLineSpace) * (_Lines.size() - i - 1)); + sint y = (sint) ceilf((_FontHeight + _MultiLineSpace) * (_Lines.size() - i - 1)); pTooltip->setX(0); pTooltip->setY(y); @@ -1914,7 +1915,8 @@ namespace NLGUI // Common case: no W clamp _Index = TextContext->textPush (_Text); _Info = TextContext->getStringInfo (_Index); - _W = (sint)(_Info.StringWidth); + _Info.StringWidth /= _Scale; + _W = (sint)ceilf(_Info.StringWidth); // Rare case: clamp W => recompute slowly, cut letters if(_W>_LineMaxW) @@ -1927,7 +1929,7 @@ namespace NLGUI ucCurrentLine.reserve(_Text.size()); // Append ... to the end of line si = TextContext->getStringInfo (ucstring("...")); - float dotWidth= si.StringWidth; + float dotWidth= si.StringWidth / _Scale; float rWidthCurrentLine = 0, rWidthLetter; // for all the text if (_ClampRight) @@ -1938,7 +1940,7 @@ namespace NLGUI ucstring ucStrLetter; ucStrLetter= ucLetter; si = TextContext->getStringInfo (ucStrLetter); - rWidthLetter = (si.StringWidth); + rWidthLetter = (si.StringWidth / _Scale); if ((rWidthCurrentLine + rWidthLetter + dotWidth) > _LineMaxW) { break; @@ -1962,7 +1964,7 @@ namespace NLGUI ucstring ucStrLetter; ucStrLetter= ucLetter; si = TextContext->getStringInfo (ucStrLetter); - rWidthLetter = (si.StringWidth); + rWidthLetter = (si.StringWidth / _Scale); if ((rWidthCurrentLine + rWidthLetter + dotWidth) > _LineMaxW) { break; @@ -1982,13 +1984,14 @@ namespace NLGUI // And so setup this trunc text _Index = TextContext->textPush (ucCurrentLine); _Info = TextContext->getStringInfo (_Index); - _W = (sint)(_Info.StringWidth); + _Info.StringWidth /= _Scale; + _W = (sint)ceilf(_Info.StringWidth); _SingleLineTextClamped= true; } // same height always - _H = _FontHeight; + _H = (sint)ceilf(_FontHeight); } _InvalidTextContext= false; @@ -2025,12 +2028,12 @@ namespace NLGUI if (_ClampRight) { sint32 parentRight = parent->getXReal() + parent->getWReal() - (sint32) _AutoClampOffset; - setLineMaxW(std::max((sint32) 0, parentRight - _XReal)); + setLineMaxW(ceilf(std::max((sint32) 0, parentRight - _XReal) / _Scale)); } else { sint32 parentLeft = parent->getXReal() + (sint32) _AutoClampOffset; - setLineMaxW(std::max((sint32) 0, _XReal + _WReal - parentLeft)); + setLineMaxW(ceilf(std::max((sint32) 0, _XReal + _WReal - parentLeft) / _Scale)); } } } @@ -2154,7 +2157,7 @@ namespace NLGUI TextContext->setHotSpot (UTextContext::BottomLeft); TextContext->setShaded (_Shadow); TextContext->setShadeOutline (_ShadowOutline); - TextContext->setFontSize (_FontSize); + TextContext->setFontSize (_FontSize*_Scale); TextContext->setEmbolden (_Embolden); TextContext->setOblique (_Oblique); // CViewRenderer &rVR = *CViewRenderer::getInstance(); @@ -2224,14 +2227,14 @@ namespace NLGUI ucstring subStr = currWord.Text.substr(0, index - charIndex - currWord.NumSpaces); // compute the size UTextContext::CStringInfo si = TextContext->getStringInfo(subStr); - x = (sint) (px + si.StringWidth + currWord.NumSpaces * currLine.getSpaceWidth()); + x = (sint) ceilf(px + si.StringWidth / _Scale + currWord.NumSpaces * currLine.getSpaceWidth()); height = getFontHeight(); return; } else { // character is in the spaces preceding the word - x = (sint) (px + currLine.getSpaceWidth() * (index - charIndex)); + x = (sint) ceilf(px + currLine.getSpaceWidth() * (index - charIndex)); height = getFontHeight(); return; } @@ -2251,7 +2254,7 @@ namespace NLGUI // compute the size UTextContext::CStringInfo si = TextContext->getStringInfo(subStr); y = 0; - x = (sint) si.StringWidth; + x = (sint) ceilf(si.StringWidth / _Scale); } } @@ -2260,6 +2263,7 @@ namespace NLGUI static uint getCharacterIndex(const ucstring &textValue, float x) { float px = 0.f; + float sw; UTextContext::CStringInfo si; ucstring singleChar(" "); uint i; @@ -2268,12 +2272,13 @@ namespace NLGUI // get character width singleChar[0] = textValue[i]; si = CViewRenderer::getTextContext()->getStringInfo(singleChar); - px += si.StringWidth; + sw = si.StringWidth / CViewRenderer::getInstance()->getInterfaceScale(); + px += sw / CViewRenderer::getInstance()->getInterfaceScale(); // the character is at the i - 1 position if (px > x) { // if the half of the character is after the cursor, then prefer select the next one (like in Word) - if(px-si.StringWidth/2 < x) + if(px-sw/2 < x) i++; break; } @@ -2290,7 +2295,7 @@ namespace NLGUI TextContext->setHotSpot (UTextContext::BottomLeft); TextContext->setShaded (_Shadow); TextContext->setShadeOutline (_ShadowOutline); - TextContext->setFontSize (_FontSize); + TextContext->setFontSize (_FontSize*_Scale); TextContext->setEmbolden (_Embolden); TextContext->setOblique (_Oblique); // find the line where the character is @@ -2490,7 +2495,7 @@ namespace NLGUI } // *************************************************************************** - void CViewText::CLine::addWord(const ucstring &text, uint numSpaces, const CFormatInfo &wordFormat, uint fontWidth) + void CViewText::CLine::addWord(const ucstring &text, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth) { CWord word; word.build(text, numSpaces); @@ -2499,7 +2504,7 @@ namespace NLGUI } // *************************************************************************** - void CViewText::CLine::addWord(const CWord &word, uint fontWidth) + void CViewText::CLine::addWord(const CWord &word, float fontWidth) { _Words.push_back(word); _NumChars += word.NumSpaces + uint(word.Text.length()); @@ -2509,7 +2514,7 @@ namespace NLGUI _StringLine = word.Info.StringLine; } // the width of the line must reach at least the Tab - _WidthWithoutSpaces= max(_WidthWithoutSpaces, word.Format.TabX * float(fontWidth)); + _WidthWithoutSpaces= max(_WidthWithoutSpaces, word.Format.TabX * fontWidth); // append the text space _WidthWithoutSpaces += word.Info.StringWidth; } @@ -2544,6 +2549,7 @@ namespace NLGUI NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); Index = TextContext->textPush(text); Info = TextContext->getStringInfo(Index); + Info.StringWidth /= CViewRenderer::getInstance()->getInterfaceScale(); } // *************************************************************************** @@ -2568,7 +2574,7 @@ namespace NLGUI TextContext->setHotSpot (UTextContext::BottomLeft); TextContext->setShaded (_Shadow); TextContext->setShadeOutline (_ShadowOutline); - TextContext->setFontSize (_FontSize); + TextContext->setFontSize (_FontSize*_Scale); TextContext->setEmbolden (_Embolden); TextContext->setOblique (_Oblique); @@ -2617,7 +2623,7 @@ namespace NLGUI si = TextContext->getStringInfo(wordValue); // compute size of spaces + word - lineWidth += numSpaces * _SpaceWidth + si.StringWidth; + lineWidth += numSpaces * _SpaceWidth + si.StringWidth / _Scale; currPos = wordEnd; } @@ -2629,14 +2635,14 @@ namespace NLGUI linePos = lineEnd+1; } - return (sint32)maxWidth; + return (sint32)ceilf(maxWidth); } // *************************************************************************** sint32 CViewText::getMinUsedW() const { static const ucstring spaceOrLineFeedStr(" \n\t"); - sint32 maxWidth = 0; + float maxWidth = 0.0f; // Not multi line ? Same size than min if (!_MultiLine) @@ -2646,7 +2652,7 @@ namespace NLGUI if (_TextMode == ClipWord) { // No largest font parameter, return the font height - return _FontHeight; + return (sint32)ceilf(_FontHeight); } // If we can't clip the words, return the size of the largest word else if ((_TextMode == DontClipWord) || (_TextMode == Justified)) @@ -2655,7 +2661,7 @@ namespace NLGUI TextContext->setHotSpot (UTextContext::BottomLeft); TextContext->setShaded (_Shadow); TextContext->setShadeOutline (_ShadowOutline); - TextContext->setFontSize (_FontSize); + TextContext->setFontSize (_FontSize*_Scale); TextContext->setEmbolden (_Embolden); TextContext->setOblique (_Oblique); @@ -2683,7 +2689,7 @@ namespace NLGUI si = TextContext->getStringInfo(wordValue); // Larger ? - sint32 stringWidth = (sint32)si.StringWidth; + float stringWidth = (si.StringWidth / _Scale); if (stringWidth>maxWidth) maxWidth = stringWidth; @@ -2692,7 +2698,7 @@ namespace NLGUI } } - return maxWidth; + return ceilf(maxWidth); } // *************************************************************************** @@ -2709,11 +2715,13 @@ namespace NLGUI // *************************************************************************** void CViewText::computeFontSize () { + _Scale = CViewRenderer::getInstance()->getInterfaceScale(); + NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); TextContext->setHotSpot (UTextContext::BottomLeft); TextContext->setShaded (_Shadow); TextContext->setShadeOutline (_ShadowOutline); - TextContext->setFontSize (_FontSize); + TextContext->setFontSize (_FontSize * _Scale); TextContext->setEmbolden (_Embolden); TextContext->setOblique (_Oblique); @@ -2728,16 +2736,16 @@ namespace NLGUI // for now we can't know that directly from UTextContext UTextContext::CStringInfo si = TextContext->getStringInfo(chars); // add a padding of 1 pixel else the top will be truncated - _FontHeight = (uint) si.StringHeight+1; - _FontLegHeight = (uint) si.StringLine; + _FontHeight = (si.StringHeight / _Scale) + 1; + _FontLegHeight = si.StringLine / _Scale; // Space width si = TextContext->getStringInfo(ucstring(" ")); - _SpaceWidth = si.StringWidth; + _SpaceWidth = si.StringWidth / _Scale; // Font Width si = TextContext->getStringInfo(ucstring("_")); - _FontWidth = (uint)si.StringWidth; + _FontWidth = si.StringWidth / _Scale; } From 34fa04644e941fe1fb1f3cbd04dff31749707eb2 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 6 Jun 2016 19:48:08 +0300 Subject: [PATCH 004/303] Fixed: In scene text bubble position --HG-- branch : experimental-ui-scaling --- code/ryzom/client/src/interface_v3/group_in_scene.cpp | 6 ++++-- .../ryzom/client/src/interface_v3/group_in_scene_bubble.cpp | 5 ++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/group_in_scene.cpp b/code/ryzom/client/src/interface_v3/group_in_scene.cpp index fccf2e9e6..b547f7fb0 100644 --- a/code/ryzom/client/src/interface_v3/group_in_scene.cpp +++ b/code/ryzom/client/src/interface_v3/group_in_scene.cpp @@ -86,8 +86,10 @@ void CGroupInScene::computeWindowPos(sint32 &newX, sint32 &newY, CVector &newPro tmp = pVR.getFrustum().projectZ (tmp); // Get the width and height - tmp.x *= (float)CViewRenderer::getInstance()->getDriver()->getWindowWidth(); - tmp.y *= (float)CViewRenderer::getInstance()->getDriver()->getWindowHeight(); + uint32 width, height; + CViewRenderer::getInstance()->getScreenSize(width, height); + tmp.x *= width; + tmp.y *= height; // position without offset, in float newProjCenter.x= tmp.x; diff --git a/code/ryzom/client/src/interface_v3/group_in_scene_bubble.cpp b/code/ryzom/client/src/interface_v3/group_in_scene_bubble.cpp index e964911c3..eb935bc40 100644 --- a/code/ryzom/client/src/interface_v3/group_in_scene_bubble.cpp +++ b/code/ryzom/client/src/interface_v3/group_in_scene_bubble.cpp @@ -668,9 +668,8 @@ CGroupInSceneBubbleManager::CPopupContext *CGroupInSceneBubbleManager::buildCont if (target) { // Find a position - NL3D::UDriver *Driver = CViewRenderer::getInstance()->getDriver(); - const uint width = Driver->getWindowWidth(); - const uint height = Driver->getWindowHeight(); + uint32 width, height; + CViewRenderer::getInstance()->getScreenSize(width, height); h = (target->getXReal() < ((sint)width-target->getXReal()-target->getWReal()))?"l":"r"; v = (target->getYReal() < ((sint)height-target->getYReal()-target->getHReal()))?"b":"t"; target->setActive(true); From 2cb71e654ae945a67cb9a306847e2b28de84220a Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 7 Jun 2016 17:27:00 +0300 Subject: [PATCH 005/303] Fixed: Update text widget parent size when interface scale changes --HG-- branch : experimental-ui-scaling --- code/nel/include/nel/gui/widget_manager.h | 1 + code/nel/src/gui/widget_manager.cpp | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/code/nel/include/nel/gui/widget_manager.h b/code/nel/include/nel/gui/widget_manager.h index cfb51af8e..7566a8ad4 100644 --- a/code/nel/include/nel/gui/widget_manager.h +++ b/code/nel/include/nel/gui/widget_manager.h @@ -614,6 +614,7 @@ namespace NLGUI uint32 _ScreenH; uint32 _ScreenW; + float _InterfaceScale; std::vector< CInterfaceAnim* > activeAnims; diff --git a/code/nel/src/gui/widget_manager.cpp b/code/nel/src/gui/widget_manager.cpp index f866594c9..0288bff12 100644 --- a/code/nel/src/gui/widget_manager.cpp +++ b/code/nel/src/gui/widget_manager.cpp @@ -1850,9 +1850,10 @@ namespace NLGUI class InvalidateTextVisitor : public CInterfaceElementVisitor { public: - InvalidateTextVisitor( bool reset ) + InvalidateTextVisitor( bool reset, bool invalidate ) { this->reset = reset; + this->invalidate = invalidate; } void visitGroup( CInterfaceGroup *group ) @@ -1865,13 +1866,17 @@ namespace NLGUI { if( reset ) vt->resetTextIndex(); - vt->updateTextContext(); + if( invalidate ) + vt->invalidateContent(); + else + vt->updateTextContext(); } } } private: bool reset; + bool invalidate; }; // ------------------------------------------------------------------------------------------------ @@ -1884,6 +1889,8 @@ namespace NLGUI CViewRenderer::getInstance()->checkNewScreenSize (); CViewRenderer::getInstance()->getScreenSize (w, h); + bool scaleChanged = _InterfaceScale != CViewRenderer::getInstance()->getInterfaceScale(); + // Update ui:* (limit the master containers to the height of the screen) for (nMasterGroup = 0; nMasterGroup < _MasterGroups.size(); nMasterGroup++) { @@ -1902,7 +1909,7 @@ namespace NLGUI { SMasterGroup &rMG = _MasterGroups[nMasterGroup]; - InvalidateTextVisitor inv( false ); + InvalidateTextVisitor inv( false, scaleChanged ); rMG.Group->visitGroupAndChildren( &inv ); rMG.Group->invalidateCoords (); @@ -3725,6 +3732,7 @@ namespace NLGUI inGame = false; setScreenWH(0, 0); + _InterfaceScale = 1.0f; _GroupSelection = false; multiSelection = false; From 6bfc777496fe5506575d516c3c55e49322504b3c Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 14 Jul 2016 20:20:55 +0300 Subject: [PATCH 006/303] Fixed: Restore scaled interface from icfg --HG-- branch : experimental-ui-scaling --- code/ryzom/client/src/interface_v3/interface_manager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 802f98c70..c75d880b6 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -1787,8 +1787,12 @@ bool CInterfaceManager::loadConfig (const string &filename) CWidgetManager::getInstance()->setScreenWH(_LastInGameScreenW, _LastInGameScreenH); // NB: we are typically InGame here (even though the _InGame flag is not yet set) // Use the screen size of the config file. Don't update current UI, just _Modes - CWidgetManager::getInstance()->moveAllWindowsToNewScreenSize(ClientCfg.Width, ClientCfg.Height, false); - updateDesktops( ClientCfg.Width, ClientCfg.Height ); + // + // ClientCfg has W/H set to screen size, but interface expects scaled size + sint32 scaledW = ClientCfg.Width / ClientCfg.InterfaceScale; + sint32 scaledH = ClientCfg.Height / ClientCfg.InterfaceScale; + CWidgetManager::getInstance()->moveAllWindowsToNewScreenSize(scaledW, scaledH, false); + updateDesktops(scaledW, scaledH); } // *** apply the current mode From 87aa86e01687da4babd991e3f8c9418a7f9d5881 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 14 Jul 2016 20:20:55 +0300 Subject: [PATCH 007/303] Fixed: Mouse pointer location after exiting freelook --HG-- branch : experimental-ui-scaling --- code/ryzom/client/src/input.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/ryzom/client/src/input.cpp b/code/ryzom/client/src/input.cpp index 403947538..f0a3133b9 100644 --- a/code/ryzom/client/src/input.cpp +++ b/code/ryzom/client/src/input.cpp @@ -179,9 +179,9 @@ void SetMouseCursor (bool updatePos) // Get the last cursor float x = 0.5f, y = 0.5f; - // Window size - uint width = Driver->getWindowWidth(); - uint height = Driver->getWindowHeight(); + // Screen size + uint width, height; + CViewRenderer::getInstance()->getScreenSize(width, height); // Update the interface pointer CInterfaceManager *instance = CInterfaceManager::getInstance(); From 5e1c6cd287f4718efbfae34e34f62a47cbdd99da Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 14 Jul 2016 20:20:55 +0300 Subject: [PATCH 008/303] Added: Bilinear filtering option for texture atlas textures --HG-- branch : experimental-ui-scaling --- code/nel/include/nel/gui/view_renderer.h | 2 ++ code/nel/src/gui/view_renderer.cpp | 5 +++-- code/ryzom/client/src/client_cfg.cpp | 2 ++ code/ryzom/client/src/client_cfg.h | 1 + code/ryzom/client/src/init.cpp | 1 + code/ryzom/client/src/main_loop_utilities.cpp | 3 +++ 6 files changed, 12 insertions(+), 2 deletions(-) diff --git a/code/nel/include/nel/gui/view_renderer.h b/code/nel/include/nel/gui/view_renderer.h index c737037a1..64cbfc888 100644 --- a/code/nel/include/nel/gui/view_renderer.h +++ b/code/nel/include/nel/gui/view_renderer.h @@ -181,6 +181,7 @@ namespace NLGUI */ void setInterfaceScale(float scale, sint32 width = 0, sint32 height = 0); float getInterfaceScale() const { return _InterfaceScale; } + void setBilinearFiltering(bool b) { _Bilinear = b; } /* * is the Screen minimized? @@ -537,6 +538,7 @@ namespace NLGUI float _InterfaceUserScale; sint32 _InterfaceBaseW, _InterfaceBaseH; sint32 _EffectiveScreenW, _EffectiveScreenH; + bool _Bilinear; void updateInterfaceScale(); diff --git a/code/nel/src/gui/view_renderer.cpp b/code/nel/src/gui/view_renderer.cpp index f8a8152b9..fe86dce1f 100644 --- a/code/nel/src/gui/view_renderer.cpp +++ b/code/nel/src/gui/view_renderer.cpp @@ -199,6 +199,7 @@ namespace NLGUI _EmptyLayer[i]= true; } _BlankGlobalTexture = NULL; + _Bilinear = false; updateInterfaceScale(); } @@ -1279,7 +1280,7 @@ namespace NLGUI _Material.setTexture(0, ite->Texture); // Special Case if _WorldSpaceTransformation and _WorldSpaceScale, enable bilinear - if(_WorldSpaceTransformation && _WorldSpaceScale) + if(_Bilinear || (_WorldSpaceTransformation && _WorldSpaceScale)) ite->Texture->setFilterMode(UTexture::Linear, UTexture::LinearMipMapOff); // draw quads and empty list @@ -1296,7 +1297,7 @@ namespace NLGUI } // Special Case if _WorldSpaceTransformation and _WorldSpaceScale, reset - if(_WorldSpaceTransformation && _WorldSpaceScale) + if(_Bilinear || (_WorldSpaceTransformation && _WorldSpaceScale)) ite->Texture->setFilterMode(UTexture::Nearest, UTexture::NearestMipMapOff); } if (!layer.FilteredAlphaBlendedQuads.empty() || diff --git a/code/ryzom/client/src/client_cfg.cpp b/code/ryzom/client/src/client_cfg.cpp index e321fdd6a..237892dbf 100644 --- a/code/ryzom/client/src/client_cfg.cpp +++ b/code/ryzom/client/src/client_cfg.cpp @@ -301,6 +301,7 @@ CClientConfig::CClientConfig() Gamma = 0.f; // Default Monitor Gamma. InterfaceScale = 1.0f; // Resize UI + BilinearUI = false; VREnable = false; VRDisplayDevice = "Auto"; @@ -839,6 +840,7 @@ void CClientConfig::setValues() READ_FLOAT_FV(InterfaceScale); // 50% smaller / 2x bigger clamp(ClientCfg.InterfaceScale, 0.5f, 2.0f); + READ_BOOL_FV(BilinearUI); // 3D Driver varPtr = ClientCfg.ConfigFile.getVarPtr ("Driver3D"); if (varPtr) diff --git a/code/ryzom/client/src/client_cfg.h b/code/ryzom/client/src/client_cfg.h index 157503957..2fc561c4d 100644 --- a/code/ryzom/client/src/client_cfg.h +++ b/code/ryzom/client/src/client_cfg.h @@ -148,6 +148,7 @@ struct CClientConfig // UI scaling float InterfaceScale; + bool BilinearUI; // VR bool VREnable; diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index 8105d9351..d0f38f7b6 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -1317,6 +1317,7 @@ void prelogInit() CInterfaceManager::getInstance(); CViewRenderer::getInstance()->setInterfaceScale(1.0f, 1024, 768); + CViewRenderer::getInstance()->setBilinearFiltering(ClientCfg.BilinearUI); // Yoyo: initialize NOW the InputHandler for Event filtering. CInputHandlerManager *InputHandlerManager = CInputHandlerManager::getInstance(); diff --git a/code/ryzom/client/src/main_loop_utilities.cpp b/code/ryzom/client/src/main_loop_utilities.cpp index e62c033e4..37bfc3247 100644 --- a/code/ryzom/client/src/main_loop_utilities.cpp +++ b/code/ryzom/client/src/main_loop_utilities.cpp @@ -104,6 +104,9 @@ void updateFromClientCfg() if (ClientCfg.InterfaceScale != LastClientCfg.InterfaceScale) CInterfaceManager::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale); + if (ClientCfg.BilinearUI != LastClientCfg.BilinearUI) + CViewRenderer::getInstance()->setBilinearFiltering(ClientCfg.BilinearUI); + //--------------------------------------------------- if (ClientCfg.WaitVBL != LastClientCfg.WaitVBL) { From d8e1d3b25487b4f3e1380fa8a369e85446db6cd3 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 14 Jul 2016 20:20:55 +0300 Subject: [PATCH 009/303] Added: Border duplication option to texture atlas builder. --HG-- branch : experimental-ui-scaling --- code/nel/tools/3d/build_interface/main.cpp | 30 ++++++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/code/nel/tools/3d/build_interface/main.cpp b/code/nel/tools/3d/build_interface/main.cpp index 1b13a0f71..f2d3aa49c 100644 --- a/code/nel/tools/3d/build_interface/main.cpp +++ b/code/nel/tools/3d/build_interface/main.cpp @@ -201,10 +201,13 @@ int main(int nNbArg, char **ppArgs) outString ("ERROR : Wrong number of arguments\n"); outString ("USAGE : build_interface [-s] [path_maps2] [path_maps3] ....\n"); outString (" -s : build a subset of an existing interface definition while preserving the existing texture ids,"); + outString (" -b : border duplication to enable bi-linear filtering"); outString (" to support freeing up VRAM by switching to the subset without rebuilding the entire interface\n"); return -1; } - + + uint borderSize = 0; + // build as a subset of existing interface bool buildSubset = false; string existingUVfilename; @@ -215,6 +218,10 @@ int main(int nNbArg, char **ppArgs) { switch ( ppArgs[i][1] ) { + case 'B': + case 'b': + borderSize = 1; + break; case 'S': case 's': buildSubset = true; @@ -274,6 +281,19 @@ int main(int nNbArg, char **ppArgs) pBtmp->convertToType(CBitmap::RGBA); } + // duplicate bitmap border to enable bilinear filtering + { + NLMISC::CBitmap *tmp = new NLMISC::CBitmap; + tmp->resize(pBtmp->getWidth(), pBtmp->getHeight()); + tmp->blit(pBtmp, 0, 0); + // upscale image to get borders + tmp->resample(tmp->getWidth()+borderSize*2, tmp->getHeight()+borderSize*2); + // copy original + tmp->blit(pBtmp, borderSize, borderSize); + delete pBtmp; + pBtmp = tmp; + } + AllMaps[i] = pBtmp; } catch (const NLMISC::Exception &e) @@ -325,10 +345,10 @@ int main(int nNbArg, char **ppArgs) } putIn (AllMaps[i], &GlobalTexture, x, y); putIn (AllMaps[i], &GlobalMask, x, y, false); - UVMin[i].U = (float)x; - UVMin[i].V = (float)y; - UVMax[i].U = (float)x+AllMaps[i]->getWidth(); - UVMax[i].V = (float)y+AllMaps[i]->getHeight(); + UVMin[i].U = (float)x+borderSize; + UVMin[i].V = (float)y+borderSize; + UVMax[i].U = (float)x+borderSize+AllMaps[i]->getWidth()-borderSize*2; + UVMax[i].V = (float)y+borderSize+AllMaps[i]->getHeight()-borderSize*2; /* // Do not remove this is useful for debugging { From 44208ba1ad7358917c03cf5ee83e16aca52626d7 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 19 Jul 2016 11:12:47 +0300 Subject: [PATCH 010/303] Changed: Use float for bitmap pos for better pixel align when scale is used --HG-- branch : experimental-ui-scaling --- code/nel/include/nel/gui/view_renderer.h | 2 +- code/nel/src/gui/view_renderer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/nel/include/nel/gui/view_renderer.h b/code/nel/include/nel/gui/view_renderer.h index 64cbfc888..99d92a7cd 100644 --- a/code/nel/include/nel/gui/view_renderer.h +++ b/code/nel/include/nel/gui/view_renderer.h @@ -192,7 +192,7 @@ namespace NLGUI * drawBitmap : this is the interface with all the views * */ - void drawRotFlipBitmap (sint layerId, sint32 x, sint32 y, sint32 width, sint32 height, uint8 rot, bool flipv, + void drawRotFlipBitmap (sint layerId, float x, float y, float width, float height, uint8 rot, bool flipv, sint32 nTxId, const NLMISC::CRGBA &col = NLMISC::CRGBA(255,255,255,255)); /* diff --git a/code/nel/src/gui/view_renderer.cpp b/code/nel/src/gui/view_renderer.cpp index fe86dce1f..d0bb214b2 100644 --- a/code/nel/src/gui/view_renderer.cpp +++ b/code/nel/src/gui/view_renderer.cpp @@ -496,7 +496,7 @@ namespace NLGUI /* * drawBitmap */ - void CViewRenderer::drawRotFlipBitmap (sint layerId, sint32 x, sint32 y, sint32 width, sint32 height, + void CViewRenderer::drawRotFlipBitmap (sint layerId, float x, float y, float width, float height, uint8 rot, bool flipv, sint32 nTxId, const CRGBA &col) { if (width <= 0 || height <= 0) return; From 8d09471a6dda49912bbecdc35d3c4a629c0e568b Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 19 Jul 2016 11:12:51 +0300 Subject: [PATCH 011/303] Fixed: Pixel align underline/strikethrough line on text --HG-- branch : experimental-ui-scaling --- code/nel/src/gui/view_text.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index 6a66bdf74..ea0c96ca5 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -1083,10 +1083,10 @@ namespace NLGUI // Draw a line if (_Underlined) - rVR.drawRotFlipBitmap (_RenderLayer, (sint)floorf(px), y_line, line_width, 1, 0, false, rVR.getBlankTextureId(), col); + rVR.drawRotFlipBitmap (_RenderLayer, (sint)floorf(px), y_line, line_width, 1.0f / rVR.getInterfaceScale(), 0, false, rVR.getBlankTextureId(), col); if (_StrikeThrough) - rVR.drawRotFlipBitmap (_RenderLayer, (sint)floorf(px), y_line + (_FontHeight / 2), line_width, 1, 0, false, rVR.getBlankTextureId(), col); + rVR.drawRotFlipBitmap (_RenderLayer, (sint)floorf(px), y_line + (_FontHeight / 2), line_width, 1.0f / rVR.getInterfaceScale(), 0, false, rVR.getBlankTextureId(), col); // skip word px += currWord.Info.StringWidth; From 7b0d1cd0563e757e7bdeb663fa9b6a571d3fb550 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 13 Aug 2016 23:32:54 +0300 Subject: [PATCH 012/303] Fixed: Double font width scaling --HG-- branch : experimental-ui-scaling --- code/nel/src/gui/view_text.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index 0ff74c963..2be91d0d0 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -2293,7 +2293,7 @@ namespace NLGUI singleChar[0] = textValue[i]; si = textContext.getStringInfo(singleChar); sw = si.StringWidth / CViewRenderer::getInstance()->getInterfaceScale(); - px += sw / CViewRenderer::getInstance()->getInterfaceScale(); + px += sw; // the character is at the i - 1 position if (px > x) { From 279f67fc2dc087e4d93b87dc2622bf18d4871309 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 13 Aug 2016 23:34:49 +0300 Subject: [PATCH 013/303] Changed: Use current scale value instead of asking CViewRenderer --HG-- branch : experimental-ui-scaling --- code/nel/include/nel/gui/view_text.h | 4 ++-- code/nel/src/gui/view_text.cpp | 34 ++++++++++++++-------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/code/nel/include/nel/gui/view_text.h b/code/nel/include/nel/gui/view_text.h index 265935067..3c5b8622d 100644 --- a/code/nel/include/nel/gui/view_text.h +++ b/code/nel/include/nel/gui/view_text.h @@ -326,7 +326,7 @@ namespace NLGUI CFormatInfo Format; public: // build from a string, using the current text context - void build(const ucstring &text, NL3D::UTextContext &textContext, uint numSpaces= 0); + void build(const ucstring &text, NL3D::UTextContext &textContext, float scale, uint numSpaces= 0); }; typedef std::vector TWordVect; @@ -339,7 +339,7 @@ namespace NLGUI // Clear the line & remove text contexts void clear(NL3D::UTextContext &textContext); // Add a new word (and its context) in the line + a number of spaces to append at the end of the line - void addWord(const ucstring &word, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth, NL3D::UTextContext &textContext); + void addWord(const ucstring &word, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth, NL3D::UTextContext &textContext, float scale); void addWord(const CWord &word, float fontWidth); uint getNumWords() const { return (uint)_Words.size(); } CWord &getWord(uint index) { return _Words[index]; } diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index 2be91d0d0..f28f9c3ed 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -1082,10 +1082,10 @@ namespace NLGUI // Draw a line if (_Underlined) - rVR.drawRotFlipBitmap (_RenderLayer, (sint)floorf(px), y_line, line_width, 1.0f / rVR.getInterfaceScale(), 0, false, rVR.getBlankTextureId(), col); + rVR.drawRotFlipBitmap (_RenderLayer, (sint)floorf(px), y_line, line_width, 1.0f / _Scale, 0, false, rVR.getBlankTextureId(), col); if (_StrikeThrough) - rVR.drawRotFlipBitmap (_RenderLayer, (sint)floorf(px), y_line + (_FontHeight / 2), line_width, 1.0f / rVR.getInterfaceScale(), 0, false, rVR.getBlankTextureId(), col); + rVR.drawRotFlipBitmap (_RenderLayer, (sint)floorf(px), y_line + (_FontHeight / 2), line_width, 1.0f / _Scale, 0, false, rVR.getBlankTextureId(), col); // skip word px += currWord.Info.StringWidth; @@ -1426,7 +1426,7 @@ namespace NLGUI linePushed= true; } // Append to the last line - _Lines.back()->addWord(ucCurrentWord, 0, wordFormat, _FontWidth, *TextContext); + _Lines.back()->addWord(ucCurrentWord, 0, wordFormat, _FontWidth, *TextContext, _Scale); // reset the word ucCurrentWord = ucstring(""); } @@ -1523,7 +1523,7 @@ namespace NLGUI if(currLine[i].Format!=lineWordFormat) { // add the current lineWord to the line. - _Lines.back()->addWord(lineWord, 0, lineWordFormat, _FontWidth, *TextContext); + _Lines.back()->addWord(lineWord, 0, lineWordFormat, _FontWidth, *TextContext, _Scale); // get new lineWordFormat lineWordFormat= currLine[i].Format; // and clear @@ -1538,7 +1538,7 @@ namespace NLGUI } if(!lineWord.empty()) - _Lines.back()->addWord(lineWord, 0, lineWordFormat, _FontWidth, *TextContext); + _Lines.back()->addWord(lineWord, 0, lineWordFormat, _FontWidth, *TextContext, _Scale); // clear currLine.clear(); @@ -1699,7 +1699,7 @@ namespace NLGUI { uint maxNumSpaces = std::max(1U, (uint) (nMaxWidth / _SpaceWidth)); CWord spaceWord; // a word with only spaces in it - spaceWord.build (ucstring (""), *TextContext, maxNumSpaces); + spaceWord.build (ucstring (""), *TextContext, _Scale, maxNumSpaces); spaceWord.Format= wordFormat; _Lines.push_back(TLineSPtr(new CLine)); _Lines.back()->addWord(spaceWord, _FontWidth); @@ -1728,7 +1728,7 @@ namespace NLGUI currChar = std::max((uint) 1, currChar); // must fit at least one character otherwise there's an infinite loop wordValue = _Text.substr(spaceEnd, currChar); CWord word; - word.build(wordValue, *TextContext, numSpaces); + word.build(wordValue, *TextContext, _Scale, numSpaces); word.Format= wordFormat; _Lines.push_back(TLineSPtr(new CLine)); float roomForSpaces = (float) nMaxWidth - word.Info.StringWidth; @@ -1763,7 +1763,7 @@ namespace NLGUI if (!wordValue.empty() || numSpaces != 0) { CWord word; - word.build(wordValue, *TextContext, numSpaces); + word.build(wordValue, *TextContext, _Scale, numSpaces); word.Format= wordFormat; // update line width _Lines.back()->addWord(word, _FontWidth); @@ -1883,7 +1883,7 @@ namespace NLGUI _Lines.pop_back(); CViewText::CLine *endLine = new CViewText::CLine; CViewText::CWord w; - w.build(string("..."), *TextContext); + w.build(string("..."), *TextContext, _Scale); endLine->addWord(w, _FontWidth); _Lines.push_back(TLineSPtr(endLine)); } @@ -2280,7 +2280,7 @@ namespace NLGUI // *************************************************************************** // Tool fct : From a word and a x coordinate, give the matching character index - static uint getCharacterIndex(const ucstring &textValue, float x, NL3D::UTextContext &textContext) + static uint getCharacterIndex(const ucstring &textValue, float x, NL3D::UTextContext &textContext, float scale) { float px = 0.f; float sw; @@ -2292,7 +2292,7 @@ namespace NLGUI // get character width singleChar[0] = textValue[i]; si = textContext.getStringInfo(singleChar); - sw = si.StringWidth / CViewRenderer::getInstance()->getInterfaceScale(); + sw = si.StringWidth / scale; px += sw; // the character is at the i - 1 position if (px > x) @@ -2390,7 +2390,7 @@ namespace NLGUI else { // the coord is in the word itself - index = charPos + currWord.NumSpaces + getCharacterIndex(currWord.Text, (float) x - (px + spacesWidth), *TextContext); + index = charPos + currWord.NumSpaces + getCharacterIndex(currWord.Text, (float) x - (px + spacesWidth), *TextContext, _Scale); cursorAtPreviousLineEnd = false; return; } @@ -2415,7 +2415,7 @@ namespace NLGUI index = 0; return; } - index = getCharacterIndex(_Text, (float) x, *TextContext); + index = getCharacterIndex(_Text, (float) x, *TextContext, _Scale); return; } } @@ -2516,10 +2516,10 @@ namespace NLGUI } // *************************************************************************** - void CViewText::CLine::addWord(const ucstring &text, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth, NL3D::UTextContext &textContext) + void CViewText::CLine::addWord(const ucstring &text, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth, NL3D::UTextContext &textContext, float scale) { CWord word; - word.build(text, textContext, numSpaces); + word.build(text, textContext, scale, numSpaces); word.Format= wordFormat; addWord(word, fontWidth); } @@ -2563,13 +2563,13 @@ namespace NLGUI } // *************************************************************************** - void CViewText::CWord::build(const ucstring &text, NL3D::UTextContext &textContext, uint numSpaces) + void CViewText::CWord::build(const ucstring &text, NL3D::UTextContext &textContext, float scale, uint numSpaces) { Text = text; NumSpaces = numSpaces; Index = textContext.textPush(text); Info = textContext.getStringInfo(Index); - Info.StringWidth /= CViewRenderer::getInstance()->getInterfaceScale(); + Info.StringWidth /= scale; } // *************************************************************************** From 4a722c7783754c6fead120a6f63cb73d32caf03e Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 14 Aug 2016 02:25:10 +0300 Subject: [PATCH 014/303] Changed: Use UI scale change event to change CViewText font scale --HG-- branch : experimental-ui-scaling --- code/nel/include/nel/gui/interface_element.h | 16 +++++- code/nel/include/nel/gui/view_text.h | 1 + code/nel/include/nel/gui/widget_manager.h | 7 +++ code/nel/src/gui/view_text.cpp | 27 ++++++---- code/nel/src/gui/widget_manager.cpp | 56 ++++++++++++++++---- 5 files changed, 87 insertions(+), 20 deletions(-) diff --git a/code/nel/include/nel/gui/interface_element.h b/code/nel/include/nel/gui/interface_element.h index 65a0fcaff..5177e322a 100644 --- a/code/nel/include/nel/gui/interface_element.h +++ b/code/nel/include/nel/gui/interface_element.h @@ -38,6 +38,16 @@ namespace NLGUI class IActionHandler; class CGroupParagraph; + /** + * Interface for UI scale change event + */ + class IInterfaceScaleWatcher + { + public: + virtual ~IInterfaceScaleWatcher(){} + virtual void onInterfaceScaleChanged()=0; + }; + /** * A visitor to walk a tree of interface elements and apply a teartment on them. * @@ -66,7 +76,7 @@ namespace NLGUI * \author Nevrax France * \date 2002 */ - class CInterfaceElement : public CReflectableRefPtrTarget, public NLMISC::IStreamable + class CInterfaceElement : public IInterfaceScaleWatcher, public CReflectableRefPtrTarget, public NLMISC::IStreamable { public: @@ -402,6 +412,10 @@ namespace NLGUI */ virtual void onInvalidateContent() {} + /* Element UI scale change event callback + */ + virtual void onInterfaceScaleChanged() {} + // called by interfaceManager for master window only void resetInvalidCoords(); diff --git a/code/nel/include/nel/gui/view_text.h b/code/nel/include/nel/gui/view_text.h index 3c5b8622d..95b8d2e4a 100644 --- a/code/nel/include/nel/gui/view_text.h +++ b/code/nel/include/nel/gui/view_text.h @@ -70,6 +70,7 @@ namespace NLGUI virtual void checkCoords(); virtual void updateCoords(); virtual void onAddToGroup(); + virtual void onInterfaceScaleChanged(); /// From CInterfaceElement sint32 getMaxUsedW() const; diff --git a/code/nel/include/nel/gui/widget_manager.h b/code/nel/include/nel/gui/widget_manager.h index 8cca08cc6..827e35224 100644 --- a/code/nel/include/nel/gui/widget_manager.h +++ b/code/nel/include/nel/gui/widget_manager.h @@ -49,6 +49,7 @@ namespace NLGUI class CProcedure; class IEditorSelectionWatcher; class IWidgetAdditionWatcher; + class IInterfaceScaleWatcher; /** GUI Widget Manager @@ -530,6 +531,11 @@ namespace NLGUI bool unGroupSelection(); void setMultiSelection( bool b ){ multiSelection = b; } + float getInterfaceScale() const { return _InterfaceScale; } + void notifyInterfaceScaleWatchers(); + void registerInterfaceScaleWatcher(IInterfaceScaleWatcher *watcher); + void unregisterInterfaceScaleWatcher(IInterfaceScaleWatcher *watcher); + bool createNewGUI( const std::string &project, const std::string &window ); private: @@ -623,6 +629,7 @@ namespace NLGUI std::vector< IOnWidgetsDrawnHandler* > onWidgetsDrawnHandlers; std::vector< IEditorSelectionWatcher* > selectionWatchers; std::vector< IWidgetWatcher* > widgetWatchers; + std::vector< IInterfaceScaleWatcher* > scaleWatchers; std::vector< std::string > editorSelection; bool _GroupSelection; diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index f28f9c3ed..3e649c1c3 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -80,7 +80,7 @@ namespace NLGUI _MultiMaxLine = 0; _Index = 0xFFFFFFFF; - _Scale = 1.0f; + _Scale = CWidgetManager::getInstance()->getInterfaceScale(); _FontWidth= 0; _FontHeight = 0; _FontLegHeight = 0; @@ -113,6 +113,8 @@ namespace NLGUI :CViewBase(param) { setupDefault (); + + CWidgetManager::getInstance()->registerInterfaceScaleWatcher(this); } ///constructor @@ -130,11 +132,15 @@ namespace NLGUI _ShadowOutline = ShadowOutline; setText(Text); computeFontSize (); + + CWidgetManager::getInstance()->registerInterfaceScaleWatcher(this); } // *************************************************************************** CViewText::~CViewText() { + CWidgetManager::getInstance()->unregisterInterfaceScaleWatcher(this); + if (_Index != 0xFFFFFFFF) CViewRenderer::getTextContext(_FontName)->erase (_Index); clearLines(); @@ -893,9 +899,6 @@ namespace NLGUI // *************************************************************************** void CViewText::checkCoords () { - if (_Scale != CViewRenderer::getInstance()->getInterfaceScale()) - invalidateContent(); - if ((_MultiLine)&&(_Parent != NULL)) { // If never setuped, and if text is not empty @@ -1840,9 +1843,6 @@ namespace NLGUI // *************************************************************************** void CViewText::updateTextContext () { - if (_Scale != CViewRenderer::getInstance()->getInterfaceScale()) - computeFontSize(); - NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(_FontName); TextContext->setHotSpot (UTextContext::BottomLeft); @@ -2732,11 +2732,20 @@ namespace NLGUI invalidateCoords(); } + // *************************************************************************** + void CViewText::onInterfaceScaleChanged() + { + _Scale = CWidgetManager::getInstance()->getInterfaceScale(); + + computeFontSize (); + invalidateContent(); + + CViewBase::onInterfaceScaleChanged(); + } + // *************************************************************************** void CViewText::computeFontSize () { - _Scale = CViewRenderer::getInstance()->getInterfaceScale(); - NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(_FontName); TextContext->setHotSpot (UTextContext::BottomLeft); TextContext->setShaded (_Shadow); diff --git a/code/nel/src/gui/widget_manager.cpp b/code/nel/src/gui/widget_manager.cpp index 5d278a29a..a215dbf08 100644 --- a/code/nel/src/gui/widget_manager.cpp +++ b/code/nel/src/gui/widget_manager.cpp @@ -1850,10 +1850,9 @@ namespace NLGUI class InvalidateTextVisitor : public CInterfaceElementVisitor { public: - InvalidateTextVisitor( bool reset, bool invalidate ) + InvalidateTextVisitor( bool reset) { this->reset = reset; - this->invalidate = invalidate; } void visitGroup( CInterfaceGroup *group ) @@ -1866,17 +1865,13 @@ namespace NLGUI { if( reset ) vt->resetTextIndex(); - if( invalidate ) - vt->invalidateContent(); - else - vt->updateTextContext(); + vt->updateTextContext(); } } } private: bool reset; - bool invalidate; }; // ------------------------------------------------------------------------------------------------ @@ -1889,8 +1884,6 @@ namespace NLGUI CViewRenderer::getInstance()->checkNewScreenSize (); CViewRenderer::getInstance()->getScreenSize (w, h); - bool scaleChanged = _InterfaceScale != CViewRenderer::getInstance()->getInterfaceScale(); - // Update ui:* (limit the master containers to the height of the screen) for (nMasterGroup = 0; nMasterGroup < _MasterGroups.size(); nMasterGroup++) { @@ -1900,6 +1893,13 @@ namespace NLGUI } CViewRenderer::getInstance()->setClipWindow(0, 0, w, h); + bool scaleChanged = _InterfaceScale != CViewRenderer::getInstance()->getInterfaceScale(); + if (scaleChanged) + { + _InterfaceScale = CViewRenderer::getInstance()->getInterfaceScale(); + notifyInterfaceScaleWatchers(); + } + // If all conditions are OK, move windows so they fit correctly with new screen size // Do this work only InGame when Config is loaded moveAllWindowsToNewScreenSize(w,h,true); @@ -1909,7 +1909,7 @@ namespace NLGUI { SMasterGroup &rMG = _MasterGroups[nMasterGroup]; - InvalidateTextVisitor inv( false, scaleChanged ); + InvalidateTextVisitor inv( false); rMG.Group->visitGroupAndChildren( &inv ); rMG.Group->invalidateCoords (); @@ -3697,6 +3697,42 @@ namespace NLGUI } + // ------------------------------------------------------------------------------------------------ + void CWidgetManager::notifyInterfaceScaleWatchers() + { + std::vector< IInterfaceScaleWatcher* >::iterator itr = scaleWatchers.begin(); + while( itr != scaleWatchers.end() ) + { + (*itr)->onInterfaceScaleChanged(); + ++itr; + } + } + + // ------------------------------------------------------------------------------------------------ + void CWidgetManager::registerInterfaceScaleWatcher( IInterfaceScaleWatcher *watcher ) + { + std::vector< IInterfaceScaleWatcher* >::const_iterator itr + = std::find( scaleWatchers.begin(), scaleWatchers.end(), watcher ); + + if( itr != scaleWatchers.end() ) + return; + + scaleWatchers.push_back( watcher ); + } + + // ------------------------------------------------------------------------------------------------ + void CWidgetManager::unregisterInterfaceScaleWatcher( IInterfaceScaleWatcher *watcher ) + { + std::vector< IInterfaceScaleWatcher* >::iterator itr + = std::find( scaleWatchers.begin(), scaleWatchers.end(), watcher ); + + if( itr == scaleWatchers.end() ) + return; + + scaleWatchers.erase( itr ); + } + + // ------------------------------------------------------------------------------------------------ CWidgetManager::CWidgetManager() { LinkHack(); From b5717de4fcc9657bc1f78bdb264cf6d2c4faf15a Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 14 Aug 2016 02:25:19 +0300 Subject: [PATCH 015/303] Added: Remove hardcoded text overflow indicator --HG-- branch : experimental-ui-scaling --- code/nel/include/nel/gui/view_text.h | 3 ++ code/nel/src/gui/view_text.cpp | 42 ++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/code/nel/include/nel/gui/view_text.h b/code/nel/include/nel/gui/view_text.h index 95b8d2e4a..e0603895c 100644 --- a/code/nel/include/nel/gui/view_text.h +++ b/code/nel/include/nel/gui/view_text.h @@ -90,6 +90,7 @@ namespace NLGUI void setShadowOutline (bool bShadowOutline); void setShadowColor (const NLMISC::CRGBA &color); void setLineMaxW (sint nMaxW, bool invalidate=true); + void setOverflowText(const ucstring &text) { _OverflowText = text; } void setMultiLine (bool bMultiLine); void setMultiLineSpace (sint nMultiLineSpace); void setMultiLineMaxWOnly (bool state); @@ -114,6 +115,7 @@ namespace NLGUI bool getShadowOutline() { return _ShadowOutline; } NLMISC::CRGBA getShadowColor() { return _ShadowColor; } sint getLineMaxW() const { return _LineMaxW; } + ucstring getOverflowText() const { return _OverflowText; } bool getMultiLine() const { return _MultiLine; } sint getMultiLineSpace() const { return _MultiLineSpace; } bool getMultiLineMaxWOnly() const { return _MultiLineMaxWOnly; } @@ -259,6 +261,7 @@ namespace NLGUI sint32 _LineMaxW; /// For single line, true if the text is clamped (ie displayed with "...") bool _SingleLineTextClamped; + ucstring _OverflowText; /// Multiple lines handling bool _MultiLine; diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index 3e649c1c3..02b2600b4 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -99,6 +99,7 @@ namespace NLGUI _AutoClamp = false; _ClampRight = true; // clamp on the right of the text + _OverflowText = "..."; _LetterColors = NULL; _Setuped= false; @@ -1880,12 +1881,15 @@ namespace NLGUI _Lines.back()->clear(*TextContext); _Lines.pop_back(); } - _Lines.pop_back(); - CViewText::CLine *endLine = new CViewText::CLine; - CViewText::CWord w; - w.build(string("..."), *TextContext, _Scale); - endLine->addWord(w, _FontWidth); - _Lines.push_back(TLineSPtr(endLine)); + if (_OverflowText.size() > 0) + { + _Lines.pop_back(); + CViewText::CLine *endLine = new CViewText::CLine; + CViewText::CWord w; + w.build(_OverflowText, *TextContext, _Scale); + endLine->addWord(w, _FontWidth); + _Lines.push_back(TLineSPtr(endLine)); + } } // Calculate size @@ -1947,10 +1951,20 @@ namespace NLGUI UTextContext::CStringInfo si; ucstring ucCurrentLine; ucCurrentLine.reserve(_Text.size()); + // Append ... to the end of line - si = TextContext->getStringInfo (ucstring("...")); - float dotWidth= si.StringWidth / _Scale; - float rWidthCurrentLine = 0, rWidthLetter; + float dotWidth; + if (_OverflowText.size() > 0) + { + si = TextContext->getStringInfo (ucstring(_OverflowText)); + dotWidth = si.StringWidth / _Scale; + } + else + { + dotWidth = 0.0f; + } + + float rWidthCurrentLine = 0, rWidthLetter; // for all the text if (_ClampRight) { @@ -1974,7 +1988,10 @@ namespace NLGUI } // Add the dots - ucCurrentLine+= "..."; + if (_OverflowText.size() > 0) + { + ucCurrentLine += _OverflowText; + } } else { @@ -1998,7 +2015,10 @@ namespace NLGUI } // Add the dots - ucCurrentLine = "..." + ucCurrentLine; + if (_OverflowText.size() > 0) + { + ucCurrentLine = _OverflowText + ucCurrentLine; + } } // And so setup this trunc text From a6b9da78fc4ec51c6a1009d8846f9454930646b1 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 14 Aug 2016 10:41:27 +0300 Subject: [PATCH 016/303] Changed: Replace icon bitmap text with a font --HG-- branch : experimental-ui-scaling --- .../client/src/interface_v3/dbctrl_sheet.cpp | 274 ++++++++++++------ .../client/src/interface_v3/dbctrl_sheet.h | 26 +- 2 files changed, 197 insertions(+), 103 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp index abd85de83..2b9594db4 100644 --- a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp +++ b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp @@ -542,6 +542,15 @@ CCtrlDraggable(param) _ItemRMClassType= NULL; _ItemRMFaberStatType= NULL; _NotifyAnimEndTime = 0; + + _SheetText = NULL; + _QualityText = NULL; + _QuantityText = NULL; + _SapText = NULL; + + _QualityTextValue = -1; + _QuantityTextValue = -1; + _SapTextValue = -1; } // ---------------------------------------------------------------------------- @@ -562,6 +571,30 @@ CDBCtrlSheet::~CDBCtrlSheet() _GuildSymb = NULL; } + if (_SheetText) + { + delete _SheetText; + _SheetText = NULL; + } + + if (_QualityText) + { + delete _QualityText; + _QualityText = NULL; + } + + if (_QuantityText) + { + delete _QuantityText; + _QuantityText = NULL; + } + + if (_SapText) + { + delete _SapText; + _SapText = NULL; + } + // ensure erase static if(this==_CurrMenuSheet) _CurrMenuSheet = NULL; if(this == dynamic_cast< CDBCtrlSheet* >( CCtrlDraggable::getDraggedSheet() ) ) @@ -1020,6 +1053,19 @@ void CDBCtrlSheet::updateCoords () } } CInterfaceElement::updateCoords(); + + if (getActive()) + { + // updateCoords() is called to apply possible UI scale change to font + if (_SheetText) + _SheetText->updateCoords(); + if (_QualityText) + _QualityText->updateCoords(); + if (_QuantityText) + _QuantityText->updateCoords(); + if (_SapText) + _SapText->updateCoords(); + } } // ---------------------------------------------------------------------------- @@ -1733,82 +1779,107 @@ sint32 CDBCtrlSheet::getSPhraseId() const // *************************************************************************** void CDBCtrlSheet::resetCharBitmaps() { - _CharBitmaps.clear(); + if (_SheetText) + _SheetText->setActive(false); + if (_QualityText) + _QualityText->setActive(false); + if (_QuantityText) + _QuantityText->setActive(false); + if (_SapText) + _SapText->setActive(false); +} + +CViewText* CDBCtrlSheet::createViewText(const std::string &id, sint fontSize) +{ + CViewText *text = new CViewText(CViewBase::TCtorParam()); + text->setActive(false); + text->setId(getId() + ":" + id); + // icon slot does not inherit from CInterfaceGroup and cannot be used as parent + text->setParent(_Parent); + text->setParentPos(_ParentPos); + text->setParentPosRef(_ParentPosRef); + text->setFontSize(fontSize); + text->setShadow(true); + text->setColor(CRGBA::White); + text->setOverflowText(ucstring("")); + text->setModulateGlobalColor(false); + text->setMultiLineSpace(0); + text->setMultiLineMaxWOnly(true); + text->setMultiLine(false); + + return text; } // *************************************************************************** void CDBCtrlSheet::setupCharBitmaps(sint32 maxW, sint32 maxLine, sint32 maxWChar, bool topDown) { // Use the optString for the Macro name - _OptString = toLower(_OptString); CInterfaceManager *pIM = CInterfaceManager::getInstance(); CViewRenderer &rVR = *CViewRenderer::getInstance(); - _CharBitmaps.clear(); - if(maxLine<=0) + { + if (_SheetText) + _SheetText->setActive(false); return; - - uint h = rVR.getTypoTextureH('a'); - sint lineNb = 0; - sint curLineSize = 0; - uint i; - uint xChar= 0; - for (i = 0; i < _OptString.size(); ++i) - { - char c = _OptString[i]; - sint32 w = rVR.getTypoTextureW(c); - if ((curLineSize + w) > maxW || (sint32)xChar>=maxWChar) - { - lineNb ++; - if (lineNb == maxLine) break; - curLineSize = 0; - xChar = 0; - } - sint32 id = rVR.getTypoTextureId(c); - if (id != -1) - { - CCharBitmap bmp; - bmp.X= curLineSize; - bmp.Y= lineNb; - bmp.Id= id; - _CharBitmaps.push_back(bmp); - } - curLineSize += w; - ++xChar; } - if (lineNb == maxLine) lineNb = maxLine-1; + if (!_SheetText) + _SheetText = createViewText("opt", 8); - for (i = 0; i < _CharBitmaps.size(); ++i) - { - _CharBitmaps[i].Y = (lineNb - _CharBitmaps[i].Y)*h; - } - - // if topDown, revert Y + _SheetText->setX(0); if (topDown) { - for (i = 0; i < _CharBitmaps.size(); ++i) - { - _CharBitmaps[i].Y = _IconH - _CharBitmaps[i].Y - h; - } + _SheetText->setY(_IconH); + _SheetText->setPosRef(Hotspot_TL); } + else + _SheetText->setPosRef(Hotspot_BL); + + _SheetText->setActive(true); + + ucstring txt; + txt.fromUtf8(_OptString); + _SheetText->setText(txt); + _SheetText->setLineMaxW(maxW); + _SheetText->setMultiLine(maxLine > 1); + + _SheetText->updateTextContext(); } // *************************************************************************** void CDBCtrlSheet::displayCharBitmaps(sint32 rdrLayer, sint32 x, sint32 y, CRGBA color) { - CInterfaceManager *pIM = CInterfaceManager::getInstance(); CViewRenderer &rVR = *CViewRenderer::getInstance(); - for (uint i = 0; i < _CharBitmaps.size(); ++i) + if (_SheetText) { - rVR.draw11RotFlipBitmap (rdrLayer, x+_CharBitmaps[i].X, y+_CharBitmaps[i].Y, 0, false, - _CharBitmaps[i].Id, color); + sint32 ClipX, ClipY, ClipW, ClipH; + rVR.getClipWindow (ClipX, ClipY, ClipW, ClipH); + + // clip region is bbox from parent + if (isIn(ClipX, ClipY, ClipW, ClipH)) + { + // position text over icon + sint32 sx = x + _SheetText->getX(); + sint32 sy = y + _SheetText->getY(); + if (_SheetText->getPosRef() & Hotspot_Tx) + sy -= _SheetText->getHReal(); + + _SheetText->setRenderLayer(rdrLayer); + _SheetText->setXReal(sx); + _SheetText->setYReal(sy); + + _SheetText->setColor(color); + + // set clip area over icon to hide oversize text + rVR.setClipWindow(sx, sy, _WReal-2, _HReal-2); + _SheetText->draw(); + rVR.setClipWindow (ClipX, ClipY, ClipW, ClipH); + } } } - // *************************************************************************** void CDBCtrlSheet::draw() { @@ -2128,7 +2199,7 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti if (_DispQuality != -1) { // For pact sheets, the quality gives the level of the sheet - drawNumber(x+1, y+1, wSheet, hSheet, numberColor, _DispQuality+1); + drawQuality(x+1, y+1, wSheet, hSheet, numberColor, _DispQuality+1); } break; case CCtrlSheetInfo::SheetType_Skill: @@ -2183,7 +2254,7 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti // Draw Quality. -1 for lookandfeel. Draw it with global color if (_DispQuality != -1) { - drawNumber(x-1,y+1,wSheet, hSheet, numberColor, _DispQuality); + drawQuality(x-1,y+1, wSheet, hSheet, numberColor, _DispQuality); } // Draw Quantity if (_UseQuantity && _DispQuantity>-1) @@ -2200,7 +2271,7 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti { quantity -= getLockValuePtr()->getValue32(); } - drawNumber(x+1+crossW, y+1, wSheet, hSheet, curSheetColor, quantity, false); + drawQuantity(x+1+crossW, y+1, wSheet, hSheet, curSheetColor, quantity); } // Is the item enchanted ? sint32 enchant = _Enchant.getSInt32(); @@ -2209,7 +2280,7 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti // Yes draw the additionnal bitmap and the charge (number of enchanted spell we can launch with the enchanted item) enchant--; rVR.draw11RotFlipBitmap (_RenderLayer+2, x, y, 0, false, rVR.getSystemTextureId(CViewRenderer::ItemEnchantedTexture), curSheetColor); - drawNumber(x+1, y-2+hSheet-rVR.getFigurTextureH(), wSheet, hSheet, numberColor, enchant, false); + drawSap(x+1, y+1, wSheet, hSheet, numberColor, enchant); } // if a raw material for example, must add special icon text. @@ -2472,7 +2543,10 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti // Draw Quality. -1 for lookandfeel. if( _ActualType == CCtrlSheetInfo::SheetType_SBrick ) { - if (_UseQuality && _MustDisplayLevel) drawNumber(px-1,py+1,BrickSheetWidth, BrickSheetHeight, curSheetColor, _DispLevel); + if (_UseQuality && _MustDisplayLevel) + { + drawQuality(px-1, py+1, BrickSheetWidth, BrickSheetHeight, curSheetColor, _DispLevel); + } } else { @@ -2540,51 +2614,63 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti } // ---------------------------------------------------------------------------- -sint32 CDBCtrlSheet::drawNumber(sint32 x, sint32 y, sint32 wSheet, sint32 /* hSheet */, CRGBA color, sint32 value, bool rightAlign) +sint32 CDBCtrlSheet::drawQuality(sint32 x, sint32 y, sint32 wSheet, sint32 /* hSheet */, CRGBA color, sint32 value) { - CInterfaceManager *pIM = CInterfaceManager::getInstance(); - CViewRenderer &rVR = *CViewRenderer::getInstance(); - sint32 wDigit= rVR.getFigurTextureW(); - sint32 hDigit= rVR.getFigurTextureH(); + if (!_QualityText) + _QualityText = createViewText("quality", 7); - sint32 totalWidth = 0; - - if (value > -1) + if (_QualityTextValue != value) { - // compute start pos - sint32 units = value; - sint32 pos; - if(rightAlign) - pos= wSheet-wDigit; - else - { - // compute number of digits to display - pos= 0; - uint numDigits= 0; - do - { - units = units / 10; - numDigits++; - } - while (units != 0); - // so pos is: - pos= numDigits*wDigit - wDigit; - } - // display digits - units = value; - do - { - sint32 unitsID = rVR.getFigurTextureId (units % 10); - // decal layer because must drawn after Items/Brick in DXTC - rVR.drawRotFlipBitmap (_RenderLayer+2, x+pos, y, wDigit, hDigit, 0, false, unitsID, color); - units = units / 10; - pos-= wDigit; - totalWidth += wDigit; - } - while (units != 0); - return totalWidth; + _QualityText->setText(toString(value)); + _QualityText->updateTextContext(); + _QualityTextValue = value; } - return -1; + _QualityText->setActive(true); + _QualityText->setRenderLayer(_RenderLayer + 2); + _QualityText->setXReal(x + wSheet - _QualityText->getW()); + _QualityText->setYReal(y); + _QualityText->setColor(color); + _QualityText->draw(); +} + +// ---------------------------------------------------------------------------- +sint32 CDBCtrlSheet::drawQuantity(sint32 x, sint32 y, sint32 wSheet, sint32 /* hSheet */, CRGBA color, sint32 value) +{ + if (!_QuantityText) + _QuantityText = createViewText(getId() + ":quantity", 7); + + if (_QuantityTextValue != value) + { + _QuantityText->setText(toString(value)); + _QuantityText->updateTextContext(); + _QuantityTextValue = value; + } + _QuantityText->setActive(true); + _QuantityText->setRenderLayer(_RenderLayer + 2); + _QuantityText->setXReal(x); + _QuantityText->setYReal(y); + _QuantityText->setColor(color); + _QuantityText->draw(); +} + +// ---------------------------------------------------------------------------- +sint32 CDBCtrlSheet::drawSap(sint32 x, sint32 y, sint32 wSheet, sint32 hSheet, CRGBA color, sint32 value) +{ + if (!_SapText) + _SapText = createViewText(getId() + ":sap", 8); + + if (_SapTextValue != value) + { + _SapText->setText(toString(value)); + _SapText->updateTextContext(); + _SapTextValue = value; + } + _SapText->setActive(true); + _SapText->setRenderLayer(_RenderLayer + 2); + _SapText->setXReal(x); + _SapText->setYReal(y + hSheet - _SapText->getH()); + _SapText->setColor(color); + _SapText->draw(); } // ---------------------------------------------------------------------------- diff --git a/code/ryzom/client/src/interface_v3/dbctrl_sheet.h b/code/ryzom/client/src/interface_v3/dbctrl_sheet.h index 8c697d660..880199188 100644 --- a/code/ryzom/client/src/interface_v3/dbctrl_sheet.h +++ b/code/ryzom/client/src/interface_v3/dbctrl_sheet.h @@ -27,6 +27,7 @@ #include "nel/gui/ctrl_draggable.h" #include "nel/gui/interface_expr.h" #include "nel/gui/action_handler.h" +#include "nel/gui/view_text.h" #include "sphrase_manager.h" // game share #include "game_share/brick_types.h" @@ -50,6 +51,7 @@ class COutpostBuildingSheet; namespace NLGUI { class CViewRenderer; + class CViewText; } @@ -589,8 +591,10 @@ protected: // setup icon from phrases void setupDisplayAsPhrase(const std::vector &bricks, const ucstring &phraseName); - // draw a number and returns the width of the drawn number - sint32 drawNumber(sint32 x, sint32 y, sint32 wSheet, sint32 hSheet, NLMISC::CRGBA color, sint32 value, bool rightAlign=true); + // + sint32 drawQuality(sint32 x, sint32 y, sint32 wSheet, sint32 hSheet, NLMISC::CRGBA color, sint32 value); + sint32 drawQuantity(sint32 x, sint32 y, sint32 wSheet, sint32 hSheet, NLMISC::CRGBA color, sint32 value); + sint32 drawSap(sint32 x, sint32 y, sint32 wSheet, sint32 hSheet, NLMISC::CRGBA color, sint32 value); protected: @@ -703,13 +707,15 @@ protected: NLMISC::CCDBNodeLeaf *_GrayedLink; - // Macro or sentence String compiled as texture Ids and positions, from the _OptString. - struct CCharBitmap - { - sint32 X,Y; - sint32 Id; - }; - std::vector _CharBitmaps; + // + CViewText *_SheetText; + CViewText *_QualityText; + CViewText *_QuantityText; + CViewText *_SapText; + // cached values for faster comparing + sint32 _QualityTextValue; + sint32 _QuantityTextValue; + sint32 _SapTextValue; // Macro Id sint32 _MacroID; @@ -753,6 +759,8 @@ private: void resetAllTexIDs(); void setupInit(); + CViewText *createViewText(const std::string &id, sint fontSize); + void setupCharBitmaps(sint32 maxW, sint32 maxLine, sint32 maxWChar= 1000, bool topDown= false); void resetCharBitmaps(); void displayCharBitmaps(sint32 rdrLayer, sint32 x, sint32 y, NLMISC::CRGBA color); From edf755188484693f48b7d5ee7363feb7a18261e7 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 11 May 2017 11:47:30 +0300 Subject: [PATCH 017/303] Backed out changeset: 85c435fe41bb --HG-- branch : experimental-ui-scaling --- code/nel/tools/3d/build_interface/main.cpp | 30 ++++------------------ 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/code/nel/tools/3d/build_interface/main.cpp b/code/nel/tools/3d/build_interface/main.cpp index f2d3aa49c..1b13a0f71 100644 --- a/code/nel/tools/3d/build_interface/main.cpp +++ b/code/nel/tools/3d/build_interface/main.cpp @@ -201,13 +201,10 @@ int main(int nNbArg, char **ppArgs) outString ("ERROR : Wrong number of arguments\n"); outString ("USAGE : build_interface [-s] [path_maps2] [path_maps3] ....\n"); outString (" -s : build a subset of an existing interface definition while preserving the existing texture ids,"); - outString (" -b : border duplication to enable bi-linear filtering"); outString (" to support freeing up VRAM by switching to the subset without rebuilding the entire interface\n"); return -1; } - - uint borderSize = 0; - + // build as a subset of existing interface bool buildSubset = false; string existingUVfilename; @@ -218,10 +215,6 @@ int main(int nNbArg, char **ppArgs) { switch ( ppArgs[i][1] ) { - case 'B': - case 'b': - borderSize = 1; - break; case 'S': case 's': buildSubset = true; @@ -281,19 +274,6 @@ int main(int nNbArg, char **ppArgs) pBtmp->convertToType(CBitmap::RGBA); } - // duplicate bitmap border to enable bilinear filtering - { - NLMISC::CBitmap *tmp = new NLMISC::CBitmap; - tmp->resize(pBtmp->getWidth(), pBtmp->getHeight()); - tmp->blit(pBtmp, 0, 0); - // upscale image to get borders - tmp->resample(tmp->getWidth()+borderSize*2, tmp->getHeight()+borderSize*2); - // copy original - tmp->blit(pBtmp, borderSize, borderSize); - delete pBtmp; - pBtmp = tmp; - } - AllMaps[i] = pBtmp; } catch (const NLMISC::Exception &e) @@ -345,10 +325,10 @@ int main(int nNbArg, char **ppArgs) } putIn (AllMaps[i], &GlobalTexture, x, y); putIn (AllMaps[i], &GlobalMask, x, y, false); - UVMin[i].U = (float)x+borderSize; - UVMin[i].V = (float)y+borderSize; - UVMax[i].U = (float)x+borderSize+AllMaps[i]->getWidth()-borderSize*2; - UVMax[i].V = (float)y+borderSize+AllMaps[i]->getHeight()-borderSize*2; + UVMin[i].U = (float)x; + UVMin[i].V = (float)y; + UVMax[i].U = (float)x+AllMaps[i]->getWidth(); + UVMax[i].V = (float)y+AllMaps[i]->getHeight(); /* // Do not remove this is useful for debugging { From 4c605fcfe0618bd19771b67c3ef42fa73dd017cf Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 11 May 2017 11:48:05 +0300 Subject: [PATCH 018/303] Backed out changeset: da24b99ddf3d --HG-- branch : experimental-ui-scaling --- .../client/src/interface_v3/dbctrl_sheet.cpp | 274 ++++++------------ .../client/src/interface_v3/dbctrl_sheet.h | 26 +- 2 files changed, 103 insertions(+), 197 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp index 2b9594db4..abd85de83 100644 --- a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp +++ b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp @@ -542,15 +542,6 @@ CCtrlDraggable(param) _ItemRMClassType= NULL; _ItemRMFaberStatType= NULL; _NotifyAnimEndTime = 0; - - _SheetText = NULL; - _QualityText = NULL; - _QuantityText = NULL; - _SapText = NULL; - - _QualityTextValue = -1; - _QuantityTextValue = -1; - _SapTextValue = -1; } // ---------------------------------------------------------------------------- @@ -571,30 +562,6 @@ CDBCtrlSheet::~CDBCtrlSheet() _GuildSymb = NULL; } - if (_SheetText) - { - delete _SheetText; - _SheetText = NULL; - } - - if (_QualityText) - { - delete _QualityText; - _QualityText = NULL; - } - - if (_QuantityText) - { - delete _QuantityText; - _QuantityText = NULL; - } - - if (_SapText) - { - delete _SapText; - _SapText = NULL; - } - // ensure erase static if(this==_CurrMenuSheet) _CurrMenuSheet = NULL; if(this == dynamic_cast< CDBCtrlSheet* >( CCtrlDraggable::getDraggedSheet() ) ) @@ -1053,19 +1020,6 @@ void CDBCtrlSheet::updateCoords () } } CInterfaceElement::updateCoords(); - - if (getActive()) - { - // updateCoords() is called to apply possible UI scale change to font - if (_SheetText) - _SheetText->updateCoords(); - if (_QualityText) - _QualityText->updateCoords(); - if (_QuantityText) - _QuantityText->updateCoords(); - if (_SapText) - _SapText->updateCoords(); - } } // ---------------------------------------------------------------------------- @@ -1779,107 +1733,82 @@ sint32 CDBCtrlSheet::getSPhraseId() const // *************************************************************************** void CDBCtrlSheet::resetCharBitmaps() { - if (_SheetText) - _SheetText->setActive(false); - if (_QualityText) - _QualityText->setActive(false); - if (_QuantityText) - _QuantityText->setActive(false); - if (_SapText) - _SapText->setActive(false); -} - -CViewText* CDBCtrlSheet::createViewText(const std::string &id, sint fontSize) -{ - CViewText *text = new CViewText(CViewBase::TCtorParam()); - text->setActive(false); - text->setId(getId() + ":" + id); - // icon slot does not inherit from CInterfaceGroup and cannot be used as parent - text->setParent(_Parent); - text->setParentPos(_ParentPos); - text->setParentPosRef(_ParentPosRef); - text->setFontSize(fontSize); - text->setShadow(true); - text->setColor(CRGBA::White); - text->setOverflowText(ucstring("")); - text->setModulateGlobalColor(false); - text->setMultiLineSpace(0); - text->setMultiLineMaxWOnly(true); - text->setMultiLine(false); - - return text; + _CharBitmaps.clear(); } // *************************************************************************** void CDBCtrlSheet::setupCharBitmaps(sint32 maxW, sint32 maxLine, sint32 maxWChar, bool topDown) { // Use the optString for the Macro name + _OptString = toLower(_OptString); CInterfaceManager *pIM = CInterfaceManager::getInstance(); CViewRenderer &rVR = *CViewRenderer::getInstance(); + _CharBitmaps.clear(); + if(maxLine<=0) - { - if (_SheetText) - _SheetText->setActive(false); return; + + uint h = rVR.getTypoTextureH('a'); + sint lineNb = 0; + sint curLineSize = 0; + uint i; + uint xChar= 0; + for (i = 0; i < _OptString.size(); ++i) + { + char c = _OptString[i]; + sint32 w = rVR.getTypoTextureW(c); + if ((curLineSize + w) > maxW || (sint32)xChar>=maxWChar) + { + lineNb ++; + if (lineNb == maxLine) break; + curLineSize = 0; + xChar = 0; + } + sint32 id = rVR.getTypoTextureId(c); + if (id != -1) + { + CCharBitmap bmp; + bmp.X= curLineSize; + bmp.Y= lineNb; + bmp.Id= id; + _CharBitmaps.push_back(bmp); + } + curLineSize += w; + ++xChar; } - if (!_SheetText) - _SheetText = createViewText("opt", 8); + if (lineNb == maxLine) lineNb = maxLine-1; - _SheetText->setX(0); + for (i = 0; i < _CharBitmaps.size(); ++i) + { + _CharBitmaps[i].Y = (lineNb - _CharBitmaps[i].Y)*h; + } + + // if topDown, revert Y if (topDown) { - _SheetText->setY(_IconH); - _SheetText->setPosRef(Hotspot_TL); + for (i = 0; i < _CharBitmaps.size(); ++i) + { + _CharBitmaps[i].Y = _IconH - _CharBitmaps[i].Y - h; + } } - else - _SheetText->setPosRef(Hotspot_BL); - - _SheetText->setActive(true); - - ucstring txt; - txt.fromUtf8(_OptString); - _SheetText->setText(txt); - _SheetText->setLineMaxW(maxW); - _SheetText->setMultiLine(maxLine > 1); - - _SheetText->updateTextContext(); } // *************************************************************************** void CDBCtrlSheet::displayCharBitmaps(sint32 rdrLayer, sint32 x, sint32 y, CRGBA color) { + CInterfaceManager *pIM = CInterfaceManager::getInstance(); CViewRenderer &rVR = *CViewRenderer::getInstance(); - if (_SheetText) + for (uint i = 0; i < _CharBitmaps.size(); ++i) { - sint32 ClipX, ClipY, ClipW, ClipH; - rVR.getClipWindow (ClipX, ClipY, ClipW, ClipH); - - // clip region is bbox from parent - if (isIn(ClipX, ClipY, ClipW, ClipH)) - { - // position text over icon - sint32 sx = x + _SheetText->getX(); - sint32 sy = y + _SheetText->getY(); - if (_SheetText->getPosRef() & Hotspot_Tx) - sy -= _SheetText->getHReal(); - - _SheetText->setRenderLayer(rdrLayer); - _SheetText->setXReal(sx); - _SheetText->setYReal(sy); - - _SheetText->setColor(color); - - // set clip area over icon to hide oversize text - rVR.setClipWindow(sx, sy, _WReal-2, _HReal-2); - _SheetText->draw(); - rVR.setClipWindow (ClipX, ClipY, ClipW, ClipH); - } + rVR.draw11RotFlipBitmap (rdrLayer, x+_CharBitmaps[i].X, y+_CharBitmaps[i].Y, 0, false, + _CharBitmaps[i].Id, color); } } + // *************************************************************************** void CDBCtrlSheet::draw() { @@ -2199,7 +2128,7 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti if (_DispQuality != -1) { // For pact sheets, the quality gives the level of the sheet - drawQuality(x+1, y+1, wSheet, hSheet, numberColor, _DispQuality+1); + drawNumber(x+1, y+1, wSheet, hSheet, numberColor, _DispQuality+1); } break; case CCtrlSheetInfo::SheetType_Skill: @@ -2254,7 +2183,7 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti // Draw Quality. -1 for lookandfeel. Draw it with global color if (_DispQuality != -1) { - drawQuality(x-1,y+1, wSheet, hSheet, numberColor, _DispQuality); + drawNumber(x-1,y+1,wSheet, hSheet, numberColor, _DispQuality); } // Draw Quantity if (_UseQuantity && _DispQuantity>-1) @@ -2271,7 +2200,7 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti { quantity -= getLockValuePtr()->getValue32(); } - drawQuantity(x+1+crossW, y+1, wSheet, hSheet, curSheetColor, quantity); + drawNumber(x+1+crossW, y+1, wSheet, hSheet, curSheetColor, quantity, false); } // Is the item enchanted ? sint32 enchant = _Enchant.getSInt32(); @@ -2280,7 +2209,7 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti // Yes draw the additionnal bitmap and the charge (number of enchanted spell we can launch with the enchanted item) enchant--; rVR.draw11RotFlipBitmap (_RenderLayer+2, x, y, 0, false, rVR.getSystemTextureId(CViewRenderer::ItemEnchantedTexture), curSheetColor); - drawSap(x+1, y+1, wSheet, hSheet, numberColor, enchant); + drawNumber(x+1, y-2+hSheet-rVR.getFigurTextureH(), wSheet, hSheet, numberColor, enchant, false); } // if a raw material for example, must add special icon text. @@ -2543,10 +2472,7 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti // Draw Quality. -1 for lookandfeel. if( _ActualType == CCtrlSheetInfo::SheetType_SBrick ) { - if (_UseQuality && _MustDisplayLevel) - { - drawQuality(px-1, py+1, BrickSheetWidth, BrickSheetHeight, curSheetColor, _DispLevel); - } + if (_UseQuality && _MustDisplayLevel) drawNumber(px-1,py+1,BrickSheetWidth, BrickSheetHeight, curSheetColor, _DispLevel); } else { @@ -2614,63 +2540,51 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti } // ---------------------------------------------------------------------------- -sint32 CDBCtrlSheet::drawQuality(sint32 x, sint32 y, sint32 wSheet, sint32 /* hSheet */, CRGBA color, sint32 value) +sint32 CDBCtrlSheet::drawNumber(sint32 x, sint32 y, sint32 wSheet, sint32 /* hSheet */, CRGBA color, sint32 value, bool rightAlign) { - if (!_QualityText) - _QualityText = createViewText("quality", 7); + CInterfaceManager *pIM = CInterfaceManager::getInstance(); + CViewRenderer &rVR = *CViewRenderer::getInstance(); + sint32 wDigit= rVR.getFigurTextureW(); + sint32 hDigit= rVR.getFigurTextureH(); - if (_QualityTextValue != value) + sint32 totalWidth = 0; + + if (value > -1) { - _QualityText->setText(toString(value)); - _QualityText->updateTextContext(); - _QualityTextValue = value; + // compute start pos + sint32 units = value; + sint32 pos; + if(rightAlign) + pos= wSheet-wDigit; + else + { + // compute number of digits to display + pos= 0; + uint numDigits= 0; + do + { + units = units / 10; + numDigits++; + } + while (units != 0); + // so pos is: + pos= numDigits*wDigit - wDigit; + } + // display digits + units = value; + do + { + sint32 unitsID = rVR.getFigurTextureId (units % 10); + // decal layer because must drawn after Items/Brick in DXTC + rVR.drawRotFlipBitmap (_RenderLayer+2, x+pos, y, wDigit, hDigit, 0, false, unitsID, color); + units = units / 10; + pos-= wDigit; + totalWidth += wDigit; + } + while (units != 0); + return totalWidth; } - _QualityText->setActive(true); - _QualityText->setRenderLayer(_RenderLayer + 2); - _QualityText->setXReal(x + wSheet - _QualityText->getW()); - _QualityText->setYReal(y); - _QualityText->setColor(color); - _QualityText->draw(); -} - -// ---------------------------------------------------------------------------- -sint32 CDBCtrlSheet::drawQuantity(sint32 x, sint32 y, sint32 wSheet, sint32 /* hSheet */, CRGBA color, sint32 value) -{ - if (!_QuantityText) - _QuantityText = createViewText(getId() + ":quantity", 7); - - if (_QuantityTextValue != value) - { - _QuantityText->setText(toString(value)); - _QuantityText->updateTextContext(); - _QuantityTextValue = value; - } - _QuantityText->setActive(true); - _QuantityText->setRenderLayer(_RenderLayer + 2); - _QuantityText->setXReal(x); - _QuantityText->setYReal(y); - _QuantityText->setColor(color); - _QuantityText->draw(); -} - -// ---------------------------------------------------------------------------- -sint32 CDBCtrlSheet::drawSap(sint32 x, sint32 y, sint32 wSheet, sint32 hSheet, CRGBA color, sint32 value) -{ - if (!_SapText) - _SapText = createViewText(getId() + ":sap", 8); - - if (_SapTextValue != value) - { - _SapText->setText(toString(value)); - _SapText->updateTextContext(); - _SapTextValue = value; - } - _SapText->setActive(true); - _SapText->setRenderLayer(_RenderLayer + 2); - _SapText->setXReal(x); - _SapText->setYReal(y + hSheet - _SapText->getH()); - _SapText->setColor(color); - _SapText->draw(); + return -1; } // ---------------------------------------------------------------------------- diff --git a/code/ryzom/client/src/interface_v3/dbctrl_sheet.h b/code/ryzom/client/src/interface_v3/dbctrl_sheet.h index 880199188..8c697d660 100644 --- a/code/ryzom/client/src/interface_v3/dbctrl_sheet.h +++ b/code/ryzom/client/src/interface_v3/dbctrl_sheet.h @@ -27,7 +27,6 @@ #include "nel/gui/ctrl_draggable.h" #include "nel/gui/interface_expr.h" #include "nel/gui/action_handler.h" -#include "nel/gui/view_text.h" #include "sphrase_manager.h" // game share #include "game_share/brick_types.h" @@ -51,7 +50,6 @@ class COutpostBuildingSheet; namespace NLGUI { class CViewRenderer; - class CViewText; } @@ -591,10 +589,8 @@ protected: // setup icon from phrases void setupDisplayAsPhrase(const std::vector &bricks, const ucstring &phraseName); - // - sint32 drawQuality(sint32 x, sint32 y, sint32 wSheet, sint32 hSheet, NLMISC::CRGBA color, sint32 value); - sint32 drawQuantity(sint32 x, sint32 y, sint32 wSheet, sint32 hSheet, NLMISC::CRGBA color, sint32 value); - sint32 drawSap(sint32 x, sint32 y, sint32 wSheet, sint32 hSheet, NLMISC::CRGBA color, sint32 value); + // draw a number and returns the width of the drawn number + sint32 drawNumber(sint32 x, sint32 y, sint32 wSheet, sint32 hSheet, NLMISC::CRGBA color, sint32 value, bool rightAlign=true); protected: @@ -707,15 +703,13 @@ protected: NLMISC::CCDBNodeLeaf *_GrayedLink; - // - CViewText *_SheetText; - CViewText *_QualityText; - CViewText *_QuantityText; - CViewText *_SapText; - // cached values for faster comparing - sint32 _QualityTextValue; - sint32 _QuantityTextValue; - sint32 _SapTextValue; + // Macro or sentence String compiled as texture Ids and positions, from the _OptString. + struct CCharBitmap + { + sint32 X,Y; + sint32 Id; + }; + std::vector _CharBitmaps; // Macro Id sint32 _MacroID; @@ -759,8 +753,6 @@ private: void resetAllTexIDs(); void setupInit(); - CViewText *createViewText(const std::string &id, sint fontSize); - void setupCharBitmaps(sint32 maxW, sint32 maxLine, sint32 maxWChar= 1000, bool topDown= false); void resetCharBitmaps(); void displayCharBitmaps(sint32 rdrLayer, sint32 x, sint32 y, NLMISC::CRGBA color); From ddcdc8b8fb03c704ee7d6416b5ced4a7f1958373 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 16 Dec 2016 00:03:30 +0200 Subject: [PATCH 019/303] Added: Border duplication option to texture atlas builder. --HG-- branch : experimental-ui-scaling --- code/nel/tools/3d/build_interface/main.cpp | 28 ++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/code/nel/tools/3d/build_interface/main.cpp b/code/nel/tools/3d/build_interface/main.cpp index a8f854721..58c97e513 100644 --- a/code/nel/tools/3d/build_interface/main.cpp +++ b/code/nel/tools/3d/build_interface/main.cpp @@ -214,6 +214,7 @@ int main(int argc, char **argv) args.addArg("x", "extract", "", "Extract all interface elements from to ."); args.addAdditionalArg("output_filename", "PNG or TGA file to generate", true); args.addAdditionalArg("input_path", "Path that containts interfaces elements", false); + args.addArg("b", "border", "", "Duplicate icon border to allow bilinear filtering"); if (!args.parse(argc, argv)) return 1; @@ -227,6 +228,13 @@ int main(int argc, char **argv) existingUVfilename = args.getArg("s").front(); } + // + uint borderSize = 0; + if (args.haveArg("b")) + { + borderSize = 1; + } + // extract all interface elements bool extractElements = args.haveArg("x"); @@ -407,6 +415,18 @@ int main(int argc, char **argv) pBtmp->convertToType(CBitmap::RGBA); } + // duplicate icon border + if (borderSize > 0) + { + NLMISC::CBitmap *tmp = new NLMISC::CBitmap; + tmp->resize(pBtmp->getWidth(), pBtmp->getHeight()); + tmp->blit(pBtmp, 0, 0); + tmp->resample(tmp->getWidth() + borderSize * 2, tmp->getHeight() + borderSize * 2); + tmp->blit(pBtmp, borderSize, borderSize); + delete pBtmp; + pBtmp = tmp; + } + AllMaps[i] = pBtmp; } catch (const NLMISC::Exception &e) @@ -461,10 +481,10 @@ int main(int argc, char **argv) putIn (AllMaps[i], &GlobalTexture, x, y); putIn (AllMaps[i], &GlobalMask, x, y, false); - UVMin[i].U = (float)x; - UVMin[i].V = (float)y; - UVMax[i].U = (float)x+AllMaps[i]->getWidth(); - UVMax[i].V = (float)y+AllMaps[i]->getHeight(); + UVMin[i].U = (float)x + borderSize; + UVMin[i].V = (float)y + borderSize; + UVMax[i].U = (float)x + AllMaps[i]->getWidth() - borderSize; + UVMax[i].V = (float)y + AllMaps[i]->getHeight() - borderSize; #if 0 // Do not remove this is useful for debugging From b1f1e081a7f9c616de507500e92125ff570dda4b Mon Sep 17 00:00:00 2001 From: Ulu Kyn Date: Wed, 2 May 2018 16:10:15 +0000 Subject: [PATCH 020/303] Added tag ryzom-patch-3.3.1 for changeset dcd4c4d161ef --HG-- branch : develop --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 8304168ca..6a404b346 100644 --- a/.hgtags +++ b/.hgtags @@ -13,3 +13,4 @@ bfe5628e14a024ba7ea32e4b326ae433a07856b9 ryzomcore/v0.11.3 4300cc14aad098b1f86ea4c55577b7fa4a4cb5d2 ryzom-patch-3.1.0 043aaeb3d8a2a54177581b57bda87a9deaad510e ryzom-patch-3.1.0-april_patch 00dde390a394fce9da06c2f3264140282158d39f 3.3.0 +dcd4c4d161ef775136e18c7e8f5072b75dede27e ryzom-patch-3.3.1 From aa612e379937bbce970511f4dd475d2793b3b1bd Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 30 Apr 2018 15:14:04 +0300 Subject: [PATCH 021/303] Changed: Set max map scale from client cfg --HG-- branch : develop --- code/ryzom/client/client_default.cfg | 4 ++++ code/ryzom/client/data/gamedev/interfaces_v3/map.xml | 7 ++----- code/ryzom/client/src/client_cfg.cpp | 6 ++++++ code/ryzom/client/src/client_cfg.h | 4 ++++ code/ryzom/client/src/interface_v3/group_map.cpp | 2 ++ 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/code/ryzom/client/client_default.cfg b/code/ryzom/client/client_default.cfg index c128ac28a..0f917d2f4 100644 --- a/code/ryzom/client/client_default.cfg +++ b/code/ryzom/client/client_default.cfg @@ -315,6 +315,10 @@ CameraSpeedMin = 2.0; CameraSpeedMax = 100.0; CameraResetSpeed = 10.0; // Speed in radian/s +// Default values for map +MaxMapScale = 2.0f; +R2EDMaxMapScale = 8.0f; + ////////////////// // SOUND CONFIG // ////////////////// diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/map.xml b/code/ryzom/client/data/gamedev/interfaces_v3/map.xml index dcc2515ea..66d948e03 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/map.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/map.xml @@ -316,9 +316,7 @@ selection_axis_color = "0 0 0 127" compass="ui:interface:compass" - scale_max="2" - scale_max_r2="8" - /> + /> @@ -409,8 +407,7 @@ player_pos_tex="player_pos.tga" - scale_max="2" - /> + /> diff --git a/code/ryzom/client/src/client_cfg.cpp b/code/ryzom/client/src/client_cfg.cpp index 4e644ff14..881f99b16 100644 --- a/code/ryzom/client/src/client_cfg.cpp +++ b/code/ryzom/client/src/client_cfg.cpp @@ -603,6 +603,9 @@ CClientConfig::CClientConfig() CameraSpeedMax = 1.0f; CameraResetSpeed = 2.0f; + MaxMapScale = 2.0f; + R2EDMaxMapScale = 8.0f; + // VERBOSES VerboseVP = false; VerboseAnimUser = false; @@ -1466,6 +1469,9 @@ void CClientConfig::setValues() READ_FLOAT_FV(CameraDistance) } + // Default values for CGroupMap + READ_FLOAT_FV(MaxMapScale); + READ_FLOAT_FV(R2EDMaxMapScale); ///////////// // SHADOWS // diff --git a/code/ryzom/client/src/client_cfg.h b/code/ryzom/client/src/client_cfg.h index 4d4d746e0..aa9eba8c2 100644 --- a/code/ryzom/client/src/client_cfg.h +++ b/code/ryzom/client/src/client_cfg.h @@ -591,6 +591,10 @@ struct CClientConfig float CameraSpeedMax; float CameraResetSpeed; + // Default values for CGroupMap + float MaxMapScale; + float R2EDMaxMapScale; + ////////////// // VERBOSES // bool VerboseVP; diff --git a/code/ryzom/client/src/interface_v3/group_map.cpp b/code/ryzom/client/src/interface_v3/group_map.cpp index 929e35f71..6160db539 100644 --- a/code/ryzom/client/src/interface_v3/group_map.cpp +++ b/code/ryzom/client/src/interface_v3/group_map.cpp @@ -711,9 +711,11 @@ bool CGroupMap::parse(xmlNodePtr cur, CInterfaceGroup * parentGroup) } // + _ScaleMax = ClientCfg.MaxMapScale; ptr = (char*) xmlGetProp( cur, (xmlChar*)"scale_max" ); if (ptr) fromString((const char *) ptr, _ScaleMax); // + _ScaleMaxR2 = ClientCfg.R2EDMaxMapScale; ptr = (char*) xmlGetProp( cur, (xmlChar*)"scale_max_r2" ); if (ptr) fromString((const char *) ptr, _ScaleMaxR2); // From b48b1dc0cccdf6f69b188fb0fd02aa90741980f5 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Wed, 2 May 2018 17:05:35 +0300 Subject: [PATCH 022/303] Changed: Set icon background from land speciality sbrick --HG-- branch : develop --- .../client/src/interface_v3/dbctrl_sheet.cpp | 38 +++++++++++++- .../common/src/game_share/sabrina_com.cpp | 49 +++++++++++++++++++ .../ryzom/common/src/game_share/sabrina_com.h | 3 ++ 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp index 88b454279..0533441cf 100644 --- a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp +++ b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp @@ -1548,12 +1548,48 @@ void CDBCtrlSheet::setupDisplayAsPhrase(const std::vector &bri // Get the best SBrick to display. CSheetId rootBrickSheetId= bricks[0]; - { CSheetId bestBrickSheetId= pBM->getSabrinaCom().getPhraseBestDisplayBrick(bricks); setupDisplayAsSBrick (rootBrickSheetId.asInt(), bestBrickSheetId.asInt() ); } + // Override background if type is forace extraction/prospection and ecosystem brick is used + { + BRICK_FAMILIES::TBrickFamily family = pBM->getSabrinaCom().getPhraseForageFamily(bricks); + std::string icon; + switch(family) + { + case BRICK_FAMILIES::BHFEMA: + case BRICK_FAMILIES::BHFPMA: + icon = "bk_matis_brick.tga"; + break; + case BRICK_FAMILIES::BHFEMB: + case BRICK_FAMILIES::BHFPMB: + icon = "bk_fyros_brick.tga"; + break; + case BRICK_FAMILIES::BHFEMC: + case BRICK_FAMILIES::BHFPMC: + icon = "bk_zorai_brick.tga"; + break; + case BRICK_FAMILIES::BHFEMD: + case BRICK_FAMILIES::BHFPMD: + icon = "bk_tryker_brick.tga"; + break; + case BRICK_FAMILIES::BHFEME: + case BRICK_FAMILIES::BHFPME: + icon = "bk_generic_brick.tga"; + break; + default: + icon = ""; + break; + } + if (!icon.empty()) + { + CViewRenderer &rVR = *CViewRenderer::getInstance(); + _DispBackBmpId = rVR.getTextureIdFromName(icon); + } + } + // not so beautiful to display .sphrase name in progression, and in botchat if(_ActualType==SheetType_SPhraseId) { diff --git a/code/ryzom/common/src/game_share/sabrina_com.cpp b/code/ryzom/common/src/game_share/sabrina_com.cpp index 234bf2a87..e7d21cd60 100644 --- a/code/ryzom/common/src/game_share/sabrina_com.cpp +++ b/code/ryzom/common/src/game_share/sabrina_com.cpp @@ -140,6 +140,55 @@ TOOL_TYPE::TCraftingToolType CSabrinaCom::getPhraseFaberPlanToolType(const std: return TOOL_TYPE::Unknown; } +// *************************************************************************** +BRICK_FAMILIES::TBrickFamily CSabrinaCom::getPhraseForageFamily(const std::vector &phraseBricks) const +{ + if(phraseBricks.empty()) + return BRICK_FAMILIES::Unknown; + + BRICK_TYPE::EBrickType bType= _BC->getBrickType(phraseBricks[0]); + if ( (bType == BRICK_TYPE::FORAGE_PROSPECTION) || (bType == BRICK_TYPE::FORAGE_EXTRACTION) ) + { + for ( uint i=1; igetBrickFamily( brickId, indexInFamily ); + // FPMA=prospection, FEMA=extraction + if ((brickFamily == BRICK_FAMILIES::BHFPMA || brickFamily == BRICK_FAMILIES::BHFEMA)) + { + // remapping need to be used because prospection ecosystem families + // have resource speciality inserted right in the middle + // luckily indexInFamily and TBrickFamily is defined in the same order + BRICK_FAMILIES::TBrickFamily bf = (BRICK_FAMILIES::TBrickFamily)(brickFamily + indexInFamily - 1); + // A:matis, B:fyros, C:zorai, D:tryker, E:prime roots + switch (bf) { + case BRICK_FAMILIES::BHFPMA: + case BRICK_FAMILIES::BHFPMB: + return bf; + case BRICK_FAMILIES::BHFPRMFMA: + return BRICK_FAMILIES::BHFPMC; + case BRICK_FAMILIES::BHFPRMFMB: + return BRICK_FAMILIES::BHFPMD; + case BRICK_FAMILIES::BHFPRMFMC: + return BRICK_FAMILIES::BHFPME; + case BRICK_FAMILIES::BHFEMA: + case BRICK_FAMILIES::BHFEMB: + case BRICK_FAMILIES::BHFEMC: + case BRICK_FAMILIES::BHFEMD: + case BRICK_FAMILIES::BHFEME: + return bf; + default: + break; + } + } + } + } + + return BRICK_FAMILIES::Unknown; +} + // *************************************************************************** NLMISC::CSheetId CSabrinaCom::getPhraseBestDisplayBrick(const std::vector &phraseBricks) const { diff --git a/code/ryzom/common/src/game_share/sabrina_com.h b/code/ryzom/common/src/game_share/sabrina_com.h index 4613cdcd0..d799a421e 100644 --- a/code/ryzom/common/src/game_share/sabrina_com.h +++ b/code/ryzom/common/src/game_share/sabrina_com.h @@ -91,6 +91,9 @@ public: /// For Faber. TOOL_TYPE::TCraftingToolType getPhraseFaberPlanToolType(const std::vector &phraseBricks) const; + //// For Display, if ecosystem is in use, then return it + BRICK_FAMILIES::TBrickFamily getPhraseForageFamily(const std::vector &phraseBricks) const; + /// For Display. Return the brick (should be in phrase) used to display the phrase as icon NLMISC::CSheetId getPhraseBestDisplayBrick(const std::vector &phraseBricks) const; From 23d95705fd03c6075689a07e6819369267808936 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Wed, 1 Mar 2017 20:04:54 +0200 Subject: [PATCH 023/303] Added: Map search filter --HG-- branch : develop --- code/nel/src/gui/group_editbox.cpp | 2 +- .../data/gamedev/interfaces_v3/commands.xml | 3 + .../client/data/gamedev/interfaces_v3/map.xml | 84 ++++++++++++++- .../client/src/interface_v3/group_map.cpp | 100 +++++++++++++++++- .../ryzom/client/src/interface_v3/group_map.h | 14 +++ 5 files changed, 196 insertions(+), 7 deletions(-) diff --git a/code/nel/src/gui/group_editbox.cpp b/code/nel/src/gui/group_editbox.cpp index e7ed22583..13979f4aa 100644 --- a/code/nel/src/gui/group_editbox.cpp +++ b/code/nel/src/gui/group_editbox.cpp @@ -1005,7 +1005,6 @@ namespace NLGUI { case KeyESCAPE: _CurrentHistoricIndex= -1; - CWidgetManager::getInstance()->setCaptureKeyboard(NULL); // stop selection _CurrSelection = NULL; _CursorAtPreviousLineEnd = false; @@ -1014,6 +1013,7 @@ namespace NLGUI setInputString(ucstring("")); triggerOnChangeAH(); } + CWidgetManager::getInstance()->setCaptureKeyboard(NULL); break; case KeyTAB: makeTopWindow(); diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml b/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml index 31a1a7099..2a8897555 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml @@ -122,6 +122,9 @@ + + + diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/map.xml b/code/ryzom/client/data/gamedev/interfaces_v3/map.xml index 66d948e03..f2e90bbc0 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/map.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/map.xml @@ -25,6 +25,8 @@ + + @@ -144,6 +146,7 @@ + @@ -155,7 +158,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -191,8 +236,10 @@ + - + @@ -317,8 +364,39 @@ compass="ui:interface:compass" /> - - + + + + + + + + + diff --git a/code/ryzom/client/src/interface_v3/group_map.cpp b/code/ryzom/client/src/interface_v3/group_map.cpp index 6160db539..a05a6f9bb 100644 --- a/code/ryzom/client/src/interface_v3/group_map.cpp +++ b/code/ryzom/client/src/interface_v3/group_map.cpp @@ -426,6 +426,8 @@ CGroupMap::CGroupMap(const TCtorParam ¶m) // _TargetLM = NULL; _HomeLM = NULL; + _LandmarkFilter.clear(); + _MatchedLandmarkCount = 0; // _ScaleMax = 8.f; _ScaleMaxR2 = 8.f; @@ -902,9 +904,19 @@ void CGroupMap::updateCoords() // bool newLandMarkShown = false; uint i; for (i = 0; i < _ContinentLM.size(); ++i) - setupFromZoom(_ContinentLM[i], _ContinentLM[i]->Type, _MeterPerPixel); + { + if (_ContinentLM[i]->SearchMatch) + _ContinentLM[i]->setActive(true); + else + setupFromZoom(_ContinentLM[i], _ContinentLM[i]->Type, _MeterPerPixel); + } for (i = 0; i < _ContinentText.size(); ++i) - setupFromZoom(_ContinentText[i], _ContinentText[i]->Type, _MeterPerPixel); + { + if (_ContinentText[i]->SearchMatch) + _ContinentText[i]->setActive(true); + else + setupFromZoom(_ContinentText[i], _ContinentText[i]->Type, _MeterPerPixel); + } // updateLandMarkList(_ContinentLM); updateLandMarkTextList(_ContinentText); @@ -2316,6 +2328,12 @@ void CGroupMap::createLMWidgets(const std::vector &lms) worldToMap(mapPos, rCLM.Pos); const ucstring ucsTmp(CStringManagerClient::getPlaceLocalizedName(rCLM.TitleTextID)); + const ucstring lcTitle = toLower(ucsTmp); + + bool searchMatch = _LandmarkFilter.size() > 0 && filterLandmark(lcTitle); + if (searchMatch) + _MatchedLandmarkCount++; + // Add button if not a region nor a place if ((rCLM.Type != CContLandMark::Region) && (rCLM.Type != CContLandMark::Place) && (rCLM.Type != CContLandMark::Street)) @@ -2325,6 +2343,7 @@ void CGroupMap::createLMWidgets(const std::vector &lms) else addLandMark(_ContinentLM, mapPos, CI18N::get("uiStable"), _ContinentLMOptions); _ContinentLM.back()->Type = rCLM.Type; + _ContinentLM.back()->SearchMatch = searchMatch; } else // just add a text { @@ -2343,6 +2362,7 @@ void CGroupMap::createLMWidgets(const std::vector &lms) pNewText->setShadowColor(CRGBA(0,0,0,255)); pNewText->setModulateGlobalColor(false); pNewText->Type = rCLM.Type; + pNewText->SearchMatch = searchMatch; _ContinentText.push_back(pNewText); addView(pNewText); } @@ -2372,6 +2392,8 @@ void CGroupMap::createContinentLandMarks() { uint32 k; + _MatchedLandmarkCount = 0; + if (_MapMode != MapMode_Normal) return; if (_CurMap == NULL) return; @@ -2403,8 +2425,24 @@ void CGroupMap::createContinentLandMarks() NLMISC::CVector2f mapPos; worldToMap(mapPos, _CurContinent->UserLandMarks[k].Pos); - addLandMark(_UserLM, mapPos, _CurContinent->UserLandMarks[k].Title, getUserLandMarkOptions(k)); + if (filterLandmark(_CurContinent->UserLandMarks[k].Title)) + { + addLandMark(_UserLM, mapPos, _CurContinent->UserLandMarks[k].Title, getUserLandMarkOptions(k)); + _MatchedLandmarkCount++; + } } + + // update visible landmark count + CInterfaceGroup *gc = getParentContainer(); + if (gc) + { + CViewText *pVT = dynamic_cast(gc->getView("lm_count")); + if (pVT) + { + pVT->setText(toString(_MatchedLandmarkCount)); + } + } + invalidateCoords(); } @@ -2423,6 +2461,20 @@ static void hideTeleportButtonsInPopupMenuIfNotEnoughPriv() if(ie) ie->setActive(showTeleport); } +//============================================================================================================ +void CGroupMap::setLandmarkFilter(const std::string &s) +{ + _LandmarkFilter.clear(); + + if (!s.empty()) { + ucstring ucs; + ucs.fromUtf8(s); + splitUCString(toLower(s), ucstring(" "), _LandmarkFilter); + } + + // recreate landmarks + createContinentLandMarks(); +} //============================================================================================================ void CGroupMap::updateUserLandMarks() @@ -2484,6 +2536,22 @@ void CGroupMap::updateLandMarkButton(CLandMarkButton *lmb, const CLandMarkOption lmb->setColorPushed(options.ColorPushed); } +//============================================================================================================ +bool CGroupMap::filterLandmark(const ucstring &title) const +{ + if (_LandmarkFilter.size() > 0) + { + ucstring lcTitle = toLower(title); + for(uint i = 0; i< _LandmarkFilter.size(); ++i) { + if (lcTitle.find(_LandmarkFilter[i]) == ucstring::npos) { + return false; + } + } + } + + return true; +} + //============================================================================================================ void CGroupMap::addLandMark(TLandMarkButtonVect &destList, const NLMISC::CVector2f &pos, const ucstring &title, const CLandMarkOptions &options) { @@ -3161,6 +3229,32 @@ SMap *CGroupMap::getParentMap(SMap *map) // ACTION HANDLERS // ///////////////////// +//========================================================================================================= +// Set landmark filter +class CAHLandMarkFilter : public IActionHandler +{ + virtual void execute (CCtrlBase * /* pCaller */, const string ¶ms ) + { + string id = getParam(params, "map"); + + CGroupMap* map = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(id)); + if (!map) return; + + string text = getParam(params, "text"); + if (text.empty() && params.find("text=") == std::string::npos) + { + string group = getParam(params, "group"); + CGroupEditBox* eb = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(group)); + if (!eb) return; + + text = eb->getInputString().toUtf8(); + } + + map->setLandmarkFilter(text); + } +}; +REGISTER_ACTION_HANDLER(CAHLandMarkFilter, "land_mark_filter"); + //========================================================================================================= // A land mark button has been pushed class CAHLandMarkSelected : public IActionHandler diff --git a/code/ryzom/client/src/interface_v3/group_map.h b/code/ryzom/client/src/interface_v3/group_map.h index a252bae11..bead3d20f 100644 --- a/code/ryzom/client/src/interface_v3/group_map.h +++ b/code/ryzom/client/src/interface_v3/group_map.h @@ -175,6 +175,9 @@ public: //Remove and re-create UserLandMarks void updateUserLandMarks(); + // set landmarks visibility based text query + void setLandmarkFilter(const std::string &s); + // set the selection axis pos & visibility void setSelectionAxis(bool active, const NLMISC::CVector2f &worldPos = NLMISC::CVector2f::Null); @@ -262,6 +265,7 @@ private: NLMISC::CVector2f Pos; CContLandMark::TContLMType Type; bool HandleEvents; + bool SearchMatch; public: virtual bool handleEvent (const NLGUI::CEventDescriptor& event) { @@ -279,6 +283,7 @@ private: Type = CContLandMark::Unknown; Pos.set(0.f, 0.f); HandleEvents = true; + SearchMatch = false; } }; typedef std::vector TLandMarkButtonVect; @@ -289,12 +294,14 @@ private: public: NLMISC::CVector2f Pos; CContLandMark::TContLMType Type; + bool SearchMatch; CLandMarkText(const TCtorParam ¶m) : CViewText(param) { Type = CContLandMark::Unknown; Pos.set(0.f, 0.f); + SearchMatch = false; } }; typedef std::vector TLandMarkTextVect; @@ -448,6 +455,10 @@ private: typedef std::set TDecos; TDecos _Decos; + // filter keywords + std::vector _LandmarkFilter; + uint32 _MatchedLandmarkCount; + ////////////////////// // Respawn handling // // //////////////// // @@ -501,6 +512,9 @@ private: // update a landmark button void updateLandMarkButton(CLandMarkButton *lmb, const CLandMarkOptions &options); + // Test title against landmark filter + bool filterLandmark(const ucstring &title) const; + // update the scale depending on the window size and the user scale void updateScale(); From 4ba39732954b5c8a7cc941fb0c302e9ca4ecdfc1 Mon Sep 17 00:00:00 2001 From: "nimetu@gmail.com" Date: Fri, 16 Mar 2018 15:00:30 +0200 Subject: [PATCH 024/303] Changed: Remove ui scale option from ingame config --HG-- branch : experimental-ui-scaling --- .../data/gamedev/interfaces_v3/game_config.xml | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml b/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml index c3b904f01..2728e7854 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml @@ -876,17 +876,10 @@ posparent="lum" x="0" y="-2" /> - @@ -3098,13 +3091,6 @@ realtime="true" widget="sbfloat" link="Gamma" /> - Date: Fri, 16 Mar 2018 15:01:22 +0200 Subject: [PATCH 025/303] Added: Allow to set UI scale with /setuiscale command --HG-- branch : experimental-ui-scaling --- .../data/gamedev/interfaces_v3/commands.xml | 2 ++ code/ryzom/client/src/client_cfg.cpp | 3 +- code/ryzom/client/src/client_cfg.h | 3 ++ .../src/interface_v3/action_handler_game.cpp | 28 +++++++++++++++++++ .../src/interface_v3/interface_manager.cpp | 4 +-- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml b/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml index 31a1a7099..6b45ec715 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml @@ -122,6 +122,8 @@ + + diff --git a/code/ryzom/client/src/client_cfg.cpp b/code/ryzom/client/src/client_cfg.cpp index c21797def..14741b7ad 100644 --- a/code/ryzom/client/src/client_cfg.cpp +++ b/code/ryzom/client/src/client_cfg.cpp @@ -839,8 +839,7 @@ void CClientConfig::setValues() READ_FLOAT_FV(Gamma) // UI scaling READ_FLOAT_FV(InterfaceScale); - // 50% smaller / 2x bigger - clamp(ClientCfg.InterfaceScale, 0.5f, 2.0f); + clamp(ClientCfg.InterfaceScale, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE); READ_BOOL_FV(BilinearUI); // 3D Driver varPtr = ClientCfg.ConfigFile.getVarPtr ("Driver3D"); diff --git a/code/ryzom/client/src/client_cfg.h b/code/ryzom/client/src/client_cfg.h index accc5ae1e..9b24f3058 100644 --- a/code/ryzom/client/src/client_cfg.h +++ b/code/ryzom/client/src/client_cfg.h @@ -46,6 +46,9 @@ using NLMISC::CVector; using NLMISC::CRGBA; using std::string; +// limits for UI scale +const float MIN_INTERFACE_SCALE = 0.8; +const float MAX_INTERFACE_SCALE = 2.0; //--------------------------------------------------- // CClientConfig : diff --git a/code/ryzom/client/src/interface_v3/action_handler_game.cpp b/code/ryzom/client/src/interface_v3/action_handler_game.cpp index 196b0a45e..f1b27bb46 100644 --- a/code/ryzom/client/src/interface_v3/action_handler_game.cpp +++ b/code/ryzom/client/src/interface_v3/action_handler_game.cpp @@ -3732,6 +3732,34 @@ class CHandlerGameConfigChangeScreenRatioCustom : public IActionHandler }; REGISTER_ACTION_HANDLER (CHandlerGameConfigChangeScreenRatioCustom, "game_config_change_screen_ratio_custom"); +// *************************************************************************** +class CHandlerSetInterfaceScale : public IActionHandler +{ + virtual void execute (CCtrlBase *pCaller, const string &Params) + { + std::string s; + s = getParam(Params, "scale"); + if (!s.empty()) { + float scale; + if (fromString(s, scale)) + { + if (scale >= MIN_INTERFACE_SCALE && scale <= MAX_INTERFACE_SCALE) + { + ClientCfg.InterfaceScale = scale; + ClientCfg.writeDouble("InterfaceScale", ClientCfg.InterfaceScale); + + ClientCfg.IsInvalidated = true; + return; + } + } + } + + ucstring help("/setuiscale "+toString("%.1f .. %.1f", MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE)); + CInterfaceManager::getInstance()->displaySystemInfo(help); + } +}; +REGISTER_ACTION_HANDLER (CHandlerSetInterfaceScale, "set_ui_scale"); + // *************************************************************************** class CHandlerGameMissionAbandon : public IActionHandler diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 221ae0671..a63d4b5ac 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -2038,8 +2038,7 @@ void CInterfaceManager::drawViews(NL3D::UCamera camera) _CurrentPlayerCharac[i] = node ? node->getValue32() : 0; } - // update value change from ingame config window - // must update it here, right before widget manager checks it + // scale must be updated right before widget manager checks it if (_InterfaceScaleChanged) { CViewRenderer::getInstance()->setInterfaceScale(_InterfaceScale); @@ -2916,7 +2915,6 @@ NLMISC_COMMAND(loadui, "Load an interface file", "") return result; } - // *************************************************************************** void CInterfaceManager::displayWebWindow(const string & name, const string & url) { From d7ee45021533c94ccb671e5655368201689699cb Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 17 Mar 2018 13:59:42 +0200 Subject: [PATCH 026/303] Changed: Use user requested resolution for both char select and ingame --HG-- branch : experimental-ui-scaling --- code/ryzom/client/src/connection.cpp | 36 ++++------------------------ 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/code/ryzom/client/src/connection.cpp b/code/ryzom/client/src/connection.cpp index 20c424688..92fce64f8 100644 --- a/code/ryzom/client/src/connection.cpp +++ b/code/ryzom/client/src/connection.cpp @@ -256,41 +256,13 @@ REGISTER_ACTION_HANDLER (CAHOnReloadTestPage, "on_reload_test_page"); // ------------------------------------------------------------------------------------------------ void setOutGameFullScreen() { - // Setup full screen (special 1024x768 for outgame) if we have to. - // NB: don't setup fullscreen if player wants to play in window if (!ClientCfg.Local && ClientCfg.SelectCharacter == -1) { if (StereoDisplayAttached) StereoDisplay->detachFromDisplay(); StereoDisplayAttached = false; - UDriver::CMode currMode; - Driver->getCurrentScreenMode(currMode); - UDriver::CMode wantedMode; - wantedMode.Windowed = true; - wantedMode.Width = 1024; - wantedMode.Height = 768; - wantedMode.Depth = uint8(ClientCfg.Depth); - wantedMode.Frequency = ClientCfg.Frequency; - - // change mode only if necessary - if ((wantedMode.Windowed != currMode.Windowed) || - (wantedMode.Width != currMode.Width) || - (wantedMode.Height != currMode.Height)) - { - setVideoMode(wantedMode); - } - InitMouseWithCursor(ClientCfg.HardwareCursor && !StereoDisplayAttached); - /* - InitMouseWithCursor (true); - Driver->showCursor(false); - Driver->showCursor(true); - Driver->clearBuffers(CRGBA::Black); - Driver->swapBuffers(); - Driver->showCursor(false); - Driver->showCursor(true); - */ } // Enable auto scaling in login window @@ -312,8 +284,8 @@ bool connection (const string &cookie, const string &fsaddr) game_exit = false; - // Setup full screen (special 1024x768 for outgame) if we have to. - setOutGameFullScreen(); + // set resolution from cfg after login + connectionRestoreVideoMode (); // Preload continents { @@ -347,13 +319,14 @@ bool connection (const string &cookie, const string &fsaddr) // init the string manager cache. STRING_MANAGER::CStringManagerClient::instance()->initCache("", ClientCfg.LanguageCode); // VOIR BORIS #endif - connectionRestoreVideoMode (); return true; } ProgressBar.setFontFactor(1.0f); // Init out game + setOutGameFullScreen(); + ucstring nmsg("Initializing outgame..."); ProgressBar.newMessage (ClientCfg.buildLoadingString(nmsg) ); pIM->initOutGame(); @@ -492,7 +465,6 @@ bool reconnection() game_exit = false; - // Setup full screen (special 1024x768 for outgame) if we have to. setOutGameFullScreen(); // Preload continents From 8ef8b2d62d626b10b2fdfff2cd7bd36a02bd701c Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 27 Sep 2018 21:42:31 +0300 Subject: [PATCH 027/303] Fixed: checkCoords needs XReal to be same as in updateCoords --HG-- branch : develop --- code/nel/src/gui/interface_group.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/code/nel/src/gui/interface_group.cpp b/code/nel/src/gui/interface_group.cpp index 5640da530..789030a4a 100644 --- a/code/nel/src/gui/interface_group.cpp +++ b/code/nel/src/gui/interface_group.cpp @@ -1407,6 +1407,9 @@ namespace NLGUI // ------------------------------------------------------------------------------------------------ void CInterfaceGroup::checkCoords() { + // Make XReal same as in updateCoords() as some elements (CViewText) depends on it + _XReal += _MarginLeft; + //update all children elements vector::const_iterator ite; for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++) @@ -1415,7 +1418,9 @@ namespace NLGUI if(pIE->getActive()) pIE->checkCoords(); } - executeLuaScriptOnDraw(); + + _XReal -= _MarginLeft; + executeLuaScriptOnDraw(); } // ------------------------------------------------------------------------------------------------ From 1dc3d51ce238b884270abb0527252e50ebeb49fe Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 11 Oct 2018 15:24:03 +0300 Subject: [PATCH 028/303] Added: save_ui action handler to save keys and icfg files --HG-- branch : develop --- .../client/src/interface_v3/group_map.cpp | 14 +--- .../src/interface_v3/interface_manager.cpp | 70 +++++++++++++++---- .../src/interface_v3/interface_manager.h | 4 ++ 3 files changed, 61 insertions(+), 27 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/group_map.cpp b/code/ryzom/client/src/interface_v3/group_map.cpp index 37a0a8a57..e6cfcf824 100644 --- a/code/ryzom/client/src/interface_v3/group_map.cpp +++ b/code/ryzom/client/src/interface_v3/group_map.cpp @@ -2665,18 +2665,8 @@ CCtrlButton *CGroupMap::addUserLandMark(const NLMISC::CVector2f &pos, const ucst addLandMark(_UserLM, pos, title, getUserLandMarkOptions((uint32)_CurContinent->UserLandMarks.size() - 1)); // Save the config file each time a user landmark is created - CInterfaceManager *pIM = CInterfaceManager::getInstance(); - uint8 currMode = pIM->getMode(); - std::string filename = "save/interface_" + PlayerSelectedFileName + ".icfg"; - if (!CFile::fileExists(filename) && CFile::fileExists("save/shared_interface.icfg")) - { - filename = "save/shared_interface.icfg"; - } - pIM->saveConfig (filename); - if (currMode != pIM->getMode()) - { - pIM->setMode(currMode); - } + CInterfaceManager::getInstance()->saveConfig(); + return _UserLM.back(); } diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 6ec32a34d..debe0b9ab 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -1270,32 +1270,19 @@ void CInterfaceManager::loadInterfaceConfig() // ------------------------------------------------------------------------------------------------ void CInterfaceManager::uninitInGame0 () { - // Autosave of the keys if (_KeysLoaded) { - if (!ClientCfg.R2EDEnabled) - { - string filename = "save/keys_" + PlayerSelectedFileName + ".xml"; - if (!CFile::fileExists(filename) && CFile::fileExists("save/shared_keys.xml")) - filename = "save/shared_keys.xml"; + saveKeys(); - saveKeys(filename); - } _KeysLoaded = false; } // Autosave of the interface in interface.cfg if (_ConfigLoaded) { - if (!ClientCfg.R2EDEnabled) - { - string filename = "save/interface_" + PlayerSelectedFileName + ".icfg"; - if (!CFile::fileExists(filename) && CFile::fileExists("save/shared_interface.icfg")) - filename = "save/shared_interface.icfg"; + saveConfig(); - saveConfig(filename); - } _ConfigLoaded = false; } } @@ -1884,6 +1871,29 @@ public: } }; +// ------------------------------------------------------------------------------------------------ +// +bool CInterfaceManager::saveConfig (bool verbose) +{ + bool ret = true; + + if (!ClientCfg.R2EDEnabled) + { + uint8 currMode = getMode(); + + string filename = "save/interface_" + PlayerSelectedFileName + ".icfg"; + if (!CFile::fileExists(filename) && CFile::fileExists("save/shared_interface.icfg")) + filename = "save/shared_interface.icfg"; + + if (verbose) CInterfaceManager::getInstance()->displaySystemInfo("Saving " + filename); + ret = saveConfig(filename); + + if (currMode != getMode()) + setMode(currMode); + } + + return ret; +} // ------------------------------------------------------------------------------------------------ bool CInterfaceManager::saveConfig (const string &filename) @@ -2722,7 +2732,25 @@ void writeMacros (xmlNodePtr node) } // *************************************************************************** +bool CInterfaceManager::saveKeys(bool verbose) +{ + bool ret = true; + if (!ClientCfg.R2EDEnabled) + { + string filename = "save/keys_" + PlayerSelectedFileName + ".xml"; + if (!CFile::fileExists(filename) && CFile::fileExists("save/shared_keys.xml")) + filename = "save/shared_keys.xml"; + + if (verbose) CInterfaceManager::getInstance()->displaySystemInfo("Saving " + filename); + + ret = saveKeys(filename); + } + + return ret; +} + +// *************************************************************************** bool CInterfaceManager::saveKeys(const std::string &filename) { bool ret = false; @@ -2924,6 +2952,18 @@ void CInterfaceManager::displayWebWindow(const string & name, const string & url CAHManager::getInstance()->runActionHandler("browse", NULL, "name="+name+":content:html|url="+url); } + +// *************************************************************************** +class CAHSaveUI : public IActionHandler +{ + virtual void execute (CCtrlBase *pCaller, const string &Params) + { + CInterfaceManager::getInstance()->saveKeys(true); + CInterfaceManager::getInstance()->saveConfig(true); + } +}; +REGISTER_ACTION_HANDLER (CAHSaveUI, "save_ui"); + /* // *************************************************************************** class CHandlerDispWebOnQuit : public IActionHandler diff --git a/code/ryzom/client/src/interface_v3/interface_manager.h b/code/ryzom/client/src/interface_v3/interface_manager.h index 93089a826..e83192a3d 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.h +++ b/code/ryzom/client/src/interface_v3/interface_manager.h @@ -205,10 +205,14 @@ public: // Load/Save position, size, etc.. of windows bool loadConfig (const std::string &filename); + // Save config to default location, if verbose is true, display message in game sysinfo + bool saveConfig (bool verbose = false); bool saveConfig (const std::string &filename); // delete the user config (give the player ident fileName) bool deletePlayerConfig (const std::string &playerFileIdent); + // Save keys to default location, if verbose is true, display message in game sysinfo + bool saveKeys (bool verbose = false); // Save the keys config file bool saveKeys (const std::string &filename); // delete the user Keysconfig (give the player ident fileName) From 2e7d025109d19035151a8549c0d4edeb595c416b Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 17 Mar 2018 13:59:42 +0200 Subject: [PATCH 029/303] Changed: Use user requested resolution for both char select and ingame --HG-- branch : develop --- code/ryzom/client/src/connection.cpp | 36 ++++------------------------ 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/code/ryzom/client/src/connection.cpp b/code/ryzom/client/src/connection.cpp index 3d8fbc75c..7fd707354 100644 --- a/code/ryzom/client/src/connection.cpp +++ b/code/ryzom/client/src/connection.cpp @@ -253,41 +253,13 @@ REGISTER_ACTION_HANDLER (CAHOnReloadTestPage, "on_reload_test_page"); // ------------------------------------------------------------------------------------------------ void setOutGameFullScreen() { - // Setup full screen (special 1024x768 for outgame) if we have to. - // NB: don't setup fullscreen if player wants to play in window if (!ClientCfg.Local && ClientCfg.SelectCharacter == -1) { if (StereoDisplayAttached) StereoDisplay->detachFromDisplay(); StereoDisplayAttached = false; - UDriver::CMode currMode; - Driver->getCurrentScreenMode(currMode); - UDriver::CMode wantedMode; - wantedMode.Windowed = true; - wantedMode.Width = 1024; - wantedMode.Height = 768; - wantedMode.Depth = uint8(ClientCfg.Depth); - wantedMode.Frequency = ClientCfg.Frequency; - - // change mode only if necessary - if ((wantedMode.Windowed != currMode.Windowed) || - (wantedMode.Width != currMode.Width) || - (wantedMode.Height != currMode.Height)) - { - setVideoMode(wantedMode); - } - InitMouseWithCursor(ClientCfg.HardwareCursor && !StereoDisplayAttached); - /* - InitMouseWithCursor (true); - Driver->showCursor(false); - Driver->showCursor(true); - Driver->clearBuffers(CRGBA::Black); - Driver->swapBuffers(); - Driver->showCursor(false); - Driver->showCursor(true); - */ } } @@ -307,8 +279,8 @@ bool connection (const string &cookie, const string &fsaddr) game_exit = false; - // Setup full screen (special 1024x768 for outgame) if we have to. - setOutGameFullScreen(); + // set resolution from cfg after login + connectionRestoreVideoMode (); // Preload continents { @@ -342,13 +314,14 @@ bool connection (const string &cookie, const string &fsaddr) // init the string manager cache. STRING_MANAGER::CStringManagerClient::instance()->initCache("", ClientCfg.LanguageCode); // VOIR BORIS #endif - connectionRestoreVideoMode (); return true; } ProgressBar.setFontFactor(1.0f); // Init out game + setOutGameFullScreen(); + ucstring nmsg("Initializing outgame..."); ProgressBar.newMessage (ClientCfg.buildLoadingString(nmsg) ); pIM->initOutGame(); @@ -484,7 +457,6 @@ bool reconnection() game_exit = false; - // Setup full screen (special 1024x768 for outgame) if we have to. setOutGameFullScreen(); // Preload continents From 6389fe3048d931e99977cbbc5698ebeabb90f48f Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 7 May 2018 16:53:54 +0300 Subject: [PATCH 030/303] Fixed: Bad value in client_default.cfg --HG-- branch : develop --- code/ryzom/client/client_default.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/ryzom/client/client_default.cfg b/code/ryzom/client/client_default.cfg index 0f917d2f4..6de6c1e8e 100644 --- a/code/ryzom/client/client_default.cfg +++ b/code/ryzom/client/client_default.cfg @@ -316,8 +316,8 @@ CameraSpeedMax = 100.0; CameraResetSpeed = 10.0; // Speed in radian/s // Default values for map -MaxMapScale = 2.0f; -R2EDMaxMapScale = 8.0f; +MaxMapScale = 2.0; +R2EDMaxMapScale = 8.0; ////////////////// // SOUND CONFIG // From 98ae75fe571a8924ce8b133dc524755c35a6af2f Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 7 May 2018 21:37:40 +0300 Subject: [PATCH 031/303] Added: curl ca bundle option to client cfg --HG-- branch : develop --- code/nel/include/nel/gui/group_html.h | 2 ++ code/nel/src/gui/group_html.cpp | 18 ++++++++++++++---- code/ryzom/client/client_default.cfg | 5 +++++ code/ryzom/client/src/client_cfg.cpp | 3 +++ code/ryzom/client/src/client_cfg.h | 1 + .../src/interface_v3/interface_manager.cpp | 10 ++++++++++ 6 files changed, 35 insertions(+), 4 deletions(-) diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index 8d3478579..56144b61e 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -66,6 +66,8 @@ namespace NLGUI std::vector< std::string > trustedDomains; /// Maximum concurrent MultiCurl connections per CGroupHTML instance sint32 curlMaxConnections; + /// cacert.pem location + std::string curlCABundle; SWebOptions(): curlMaxConnections(2) { diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 7b2621b18..de1064bd7 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -395,13 +395,18 @@ namespace NLGUI return false; } -#if defined(NL_OS_WINDOWS) // https:// if (toLower(download.url.substr(0, 8)) == "https://") { +#if defined(NL_OS_WINDOWS) curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, &CCurlCertificates::sslCtxFunction); - } +#else + if (!options.curlCABundle.empty()) + { + curl_easy_setopt(curl, CURLOPT_CAINFO, options.curlCABundle.c_str()); + } #endif + } download.data = new CCurlWWWData(curl, download.url); download.fp = fp; @@ -5354,13 +5359,18 @@ namespace NLGUI return; } -#if defined(NL_OS_WINDOWS) // https:// if (toLower(url.substr(0, 8)) == "https://") { +#if defined(NL_OS_WINDOWS) curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, &CCurlCertificates::sslCtxFunction); - } +#else + if (!options.curlCABundle.empty()) + { + curl_easy_setopt(curl, CURLOPT_CAINFO, options.curlCABundle.c_str()); + } #endif + } // do not follow redirects, we have own handler curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 0); diff --git a/code/ryzom/client/client_default.cfg b/code/ryzom/client/client_default.cfg index 6de6c1e8e..4ffddc935 100644 --- a/code/ryzom/client/client_default.cfg +++ b/code/ryzom/client/client_default.cfg @@ -52,6 +52,11 @@ ForgetPwdURL = "http://shard.ryzomcore.org/ams/?page=forgot_password"; LoginSupportURL = "https://plus.google.com/u/0/communities/103798956862568269036"; InstallWebPage = ""; +// Full path and filename where cURL can find certificate bundle file +// cacert.pem file can be downloaded from https://curl.haxx.se/docs/caextract.html +// and added to client data path or system specific bundle can be used +// Ubuntu has "/etc/ssl/certs/ca-certificates.crt" +//CurlCABundle = "cacert.pem"; //////////////// // INTERFACES // diff --git a/code/ryzom/client/src/client_cfg.cpp b/code/ryzom/client/src/client_cfg.cpp index 881f99b16..112875cc9 100644 --- a/code/ryzom/client/src/client_cfg.cpp +++ b/code/ryzom/client/src/client_cfg.cpp @@ -430,6 +430,7 @@ CClientConfig::CClientConfig() WebIgTrustedDomains.push_back(WebIgMainDomain); CurlMaxConnections = 2; + CurlCABundle.clear(); RingReleaseNotePath = "http://" + WebIgMainDomain + "/releasenotes_ring/index.php"; ReleaseNotePath = "http://" + WebIgMainDomain + "/releasenotes/index.php"; @@ -1087,6 +1088,8 @@ void CClientConfig::setValues() if (ClientCfg.CurlMaxConnections < 0) ClientCfg.CurlMaxConnections = 2; + READ_STRING_FV(CurlCABundle); + /////////////// // ANIMATION // // AnimatedAngleThreshold diff --git a/code/ryzom/client/src/client_cfg.h b/code/ryzom/client/src/client_cfg.h index aa9eba8c2..f562dfde0 100644 --- a/code/ryzom/client/src/client_cfg.h +++ b/code/ryzom/client/src/client_cfg.h @@ -308,6 +308,7 @@ struct CClientConfig std::vector WebIgTrustedDomains; sint32 CurlMaxConnections; + string CurlCABundle; /////////////// // ANIMATION // diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 14abf00a1..53eddd7b9 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -471,6 +471,16 @@ CInterfaceManager::CInterfaceManager() CGroupHTML::options.appName = getUserAgentName(); CGroupHTML::options.appVersion = getUserAgentVersion(); CGroupHTML::options.curlMaxConnections = ClientCfg.CurlMaxConnections; + if (!ClientCfg.CurlCABundle.empty()) + { + string filename = CPath::lookup(ClientCfg.CurlCABundle, false); + if (!filename.empty()) + { + filename = CPath::getFullPath(filename, false); + CGroupHTML::options.curlCABundle = filename; + nlinfo("curl ca bundle '%s'", filename.c_str()); + } + } NLGUI::CDBManager::getInstance()->resizeBanks( NB_CDB_BANKS ); interfaceLinkUpdater = new CInterfaceLink::CInterfaceLinkUpdater(); From e625f2b3c7e1dd6c36ff40c025422d58c4f19d81 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 10 May 2018 12:46:11 +0300 Subject: [PATCH 032/303] Fixed: Mouse wheel should scroll target object instead scroll bar (fixes issue #327) --HG-- branch : develop --- code/nel/src/gui/ctrl_scroll.cpp | 2 +- code/nel/src/gui/interface_group.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/nel/src/gui/ctrl_scroll.cpp b/code/nel/src/gui/ctrl_scroll.cpp index 9c9585fcc..50e7c6aa1 100644 --- a/code/nel/src/gui/ctrl_scroll.cpp +++ b/code/nel/src/gui/ctrl_scroll.cpp @@ -885,7 +885,7 @@ namespace NLGUI } if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousewheel && _Vertical) { - moveTrackY (eventDesc.getWheel() * 12); + moveTargetY (-(eventDesc.getWheel() * 12)); return true; } } diff --git a/code/nel/src/gui/interface_group.cpp b/code/nel/src/gui/interface_group.cpp index dce9fc266..d349411e1 100644 --- a/code/nel/src/gui/interface_group.cpp +++ b/code/nel/src/gui/interface_group.cpp @@ -1305,7 +1305,7 @@ namespace NLGUI CInterfaceGroup *currParent = _Parent; while (currParent) { - if (currParent->moveSBTrackY (this, eventDesc.getWheel()*12)) + if (currParent->moveSBTargetY (this, -(eventDesc.getWheel()*12))) return true; currParent = currParent->getParent(); } From 5b4759df72bf2347cb3cc6699ff11ef0b0e6899e Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 10 May 2018 15:30:01 +0300 Subject: [PATCH 033/303] Changed: Show map search results in a list --HG-- branch : develop --- .../client/data/gamedev/interfaces_v3/map.xml | 42 +++- .../client/src/interface_v3/group_map.cpp | 187 +++++++++++++++--- .../ryzom/client/src/interface_v3/group_map.h | 17 +- 3 files changed, 211 insertions(+), 35 deletions(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/map.xml b/code/ryzom/client/data/gamedev/interfaces_v3/map.xml index f2e90bbc0..0f1ab111c 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/map.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/map.xml @@ -204,6 +204,31 @@ + + + + + + h="-4" + child_resize_w="true"> + + + + + + + + + + + diff --git a/code/ryzom/client/src/interface_v3/group_map.cpp b/code/ryzom/client/src/interface_v3/group_map.cpp index a05a6f9bb..a841beb44 100644 --- a/code/ryzom/client/src/interface_v3/group_map.cpp +++ b/code/ryzom/client/src/interface_v3/group_map.cpp @@ -427,7 +427,7 @@ CGroupMap::CGroupMap(const TCtorParam ¶m) _TargetLM = NULL; _HomeLM = NULL; _LandmarkFilter.clear(); - _MatchedLandmarkCount = 0; + _MatchedLandmarks.clear(); // _ScaleMax = 8.f; _ScaleMaxR2 = 8.f; @@ -2249,6 +2249,31 @@ void CGroupMap::centerOnPlayer() computeOffsets(); invalidateCoords(); } +//============================================================================================================ +void CGroupMap::centerOnWorldPos(const CVector2f &worldPos) +{ + CVector2f mapPos; + worldToMap(mapPos, worldPos); + + sint32 sx, sy; + mapToScreen(sx, sy, mapPos); + + sint32 x, y, w, h; + computeMapRectInsideGroup(x, y, w, h); + + sint32 dx, dy; + if (sx < getXReal()) + dx = -(getXReal() - sx + w/2); + else + dx = sx - getXReal() - w/2; + + if (sy < getYReal()) + dy = -(getYReal() - sy + h/2); + else + dy = sy - getYReal() - h/2; + + pan(dx, dy); +} //============================================================================================================ void CGroupMap::setScale(float newUserScale, const NLMISC::CVector2f &/* center */) @@ -2271,7 +2296,6 @@ void CGroupMap::setScale(float newScale) setScale(newScale, mapCoords); } - //============================================================================================================ void CGroupMap::updateLandMarkList(TLandMarkButtonVect &lmVect) { @@ -2303,6 +2327,63 @@ void CGroupMap::updateLandMarkTextList(TLandMarkTextVect &lmVect) } } +//============================================================================================================ +void CGroupMap::updateMatchedLandmarks() +{ + CInterfaceGroup *gc = getParentContainer(); + if (!gc) return; + + // visible landmark count + CViewText *pVT = dynamic_cast(gc->getView("lm_count")); + if (pVT) + { + // show total landmark count if search filter has not been set + uint c = _MatchedLandmarks.size(); + if (c == 0 && _LandmarkFilter.size() == 0) + c = _UserLM.size(); + + pVT->setText(toString(c)); + } + + // list of matched landmarks + CGroupList *pL = dynamic_cast(gc->getGroup("lm_result")); + if (!pL) return; + + pL->clearGroups(); + + if (_LandmarkFilter.size() == 0) return; + + // create result list + for(uint k = 0; k < _MatchedLandmarks.size(); ++k) + { + std::vector > params; + params.clear(); + params.push_back(std::pair("id", toString("lm%d", k))); + params.push_back(std::pair("tooltip", _MatchedLandmarks[k].Title.toUtf8())); + params.push_back(std::pair("index", toString(k))); + + CInterfaceGroup *g = CWidgetManager::getInstance()->getParser()->createGroupInstance("lm_search_result", pL->getId(), params); + if (g) + { + pL->addChild(g); + + CViewText* t = dynamic_cast(g->getView("title")); + if (t) + { + t->setSingleLineTextFormatTaged(_MatchedLandmarks[k].Title); + } + + CViewBitmap* b = dynamic_cast(g->getView("icon")); + if (b) + { + b->setTexture(_MatchedLandmarks[k].Options.LandMarkTexNormal); + b->setColor(_MatchedLandmarks[k].Options.ColorNormal); + } + } + } + pL->invalidateCoords(); +} + //============================================================================================================ void CGroupMap::removeLandMarks(TLandMarkButtonVect &lm) { @@ -2320,6 +2401,9 @@ void CGroupMap::removeLandMarks(TLandMarkButtonVect &lm) //============================================================================================================ void CGroupMap::createLMWidgets(const std::vector &lms) { + // disable any match in "world" mode + bool notWorldMode = _CurMap->Name != "world"; + for (uint32 k = 0; k < lms.size(); ++k) { const CContLandMark &rCLM =lms[k]; @@ -2330,9 +2414,9 @@ void CGroupMap::createLMWidgets(const std::vector &lms) const ucstring ucsTmp(CStringManagerClient::getPlaceLocalizedName(rCLM.TitleTextID)); const ucstring lcTitle = toLower(ucsTmp); - bool searchMatch = _LandmarkFilter.size() > 0 && filterLandmark(lcTitle); + bool searchMatch = notWorldMode && _LandmarkFilter.size() > 0 && filterLandmark(lcTitle); if (searchMatch) - _MatchedLandmarkCount++; + _MatchedLandmarks.push_back(SMatchedLandmark(rCLM.Pos, ucsTmp, _ContinentLMOptions)); // Add button if not a region nor a place if ((rCLM.Type != CContLandMark::Region) && (rCLM.Type != CContLandMark::Place) && @@ -2391,8 +2475,7 @@ void CGroupMap::createLMWidgets(const std::vector &lms) void CGroupMap::createContinentLandMarks() { uint32 k; - - _MatchedLandmarkCount = 0; + _MatchedLandmarks.clear(); if (_MapMode != MapMode_Normal) return; if (_CurMap == NULL) return; @@ -2411,38 +2494,35 @@ void CGroupMap::createContinentLandMarks() if (_CurMap->Name == "world") { createLMWidgets(ContinentMngr.WorldMap); - invalidateCoords(); - return; } - - if (_CurContinent == NULL) return; - - // Continent Landmarks - createLMWidgets(_CurContinent->ContLandMarks); - // User Landmarks - for(k = 0; k < _CurContinent->UserLandMarks.size(); ++k) + else if (_CurContinent) { - NLMISC::CVector2f mapPos; - worldToMap(mapPos, _CurContinent->UserLandMarks[k].Pos); - - if (filterLandmark(_CurContinent->UserLandMarks[k].Title)) + // Continent Landmarks + createLMWidgets(_CurContinent->ContLandMarks); + // User Landmarks + for(k = 0; k < _CurContinent->UserLandMarks.size(); ++k) { - addLandMark(_UserLM, mapPos, _CurContinent->UserLandMarks[k].Title, getUserLandMarkOptions(k)); - _MatchedLandmarkCount++; - } - } - - // update visible landmark count - CInterfaceGroup *gc = getParentContainer(); - if (gc) - { - CViewText *pVT = dynamic_cast(gc->getView("lm_count")); - if (pVT) - { - pVT->setText(toString(_MatchedLandmarkCount)); + NLMISC::CVector2f mapPos; + worldToMap(mapPos, _CurContinent->UserLandMarks[k].Pos); + + CLandMarkOptions options = getUserLandMarkOptions(k); + addLandMark(_UserLM, mapPos, _CurContinent->UserLandMarks[k].Title, options); + + if (_LandmarkFilter.size() > 0) + { + if (filterLandmark(_CurContinent->UserLandMarks[k].Title)) + { + _MatchedLandmarks.push_back(SMatchedLandmark(_CurContinent->UserLandMarks[k].Pos, _CurContinent->UserLandMarks[k].Title, options)); + } + else + { + _UserLM.back()->setActive(false); + } + } } } + updateMatchedLandmarks(); invalidateCoords(); } @@ -3035,6 +3115,30 @@ void CGroupMap::targetLandmark(CCtrlButton *lm) } } +//========================================================================================================= +void CGroupMap::targetLandmarkResult(uint32 index) +{ + if (index > _MatchedLandmarks.size()) return; + + CCompassTarget ct; + ct.Pos = _MatchedLandmarks[index].Pos; + ct.Name = _MatchedLandmarks[index].Title; + // type sets compass arrow color + ct.setType(CCompassTarget::UserLandMark); + + centerOnWorldPos(ct.Pos); + + CInterfaceManager *im = CInterfaceManager::getInstance(); + CGroupCompas *gc = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(_CompassId)); + if (gc) + { + gc->setActive(true); + gc->setTarget(ct); + gc->blink(); + CWidgetManager::getInstance()->setTopWindow(gc); + } +} + //========================================================================================================= void CGroupMap::getLandmarkPosition(const CCtrlButton *lm, NLMISC::CVector2f &worldPos) { @@ -3255,6 +3359,25 @@ class CAHLandMarkFilter : public IActionHandler }; REGISTER_ACTION_HANDLER(CAHLandMarkFilter, "land_mark_filter"); +//========================================================================================================= +// Landmark selected from result list +class CAHLandMarkResultSelected : public IActionHandler +{ + virtual void execute (CCtrlBase * /* pCaller */, const string ¶ms) + { + string id = getParam(params, "map"); + CGroupMap* map = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(id)); + if (!map) return; + + sint index; + string nr = getParam(params, "index"); + if (!fromString(nr, index)) return; + + map->targetLandmarkResult(index); + } +}; +REGISTER_ACTION_HANDLER(CAHLandMarkResultSelected, "land_mark_result_selected"); + //========================================================================================================= // A land mark button has been pushed class CAHLandMarkSelected : public IActionHandler diff --git a/code/ryzom/client/src/interface_v3/group_map.h b/code/ryzom/client/src/interface_v3/group_map.h index bead3d20f..52980c0d8 100644 --- a/code/ryzom/client/src/interface_v3/group_map.h +++ b/code/ryzom/client/src/interface_v3/group_map.h @@ -139,6 +139,9 @@ public: // center the map on the player void centerOnPlayer(); + // center current map on world coords (if not out of map bounds) + void centerOnWorldPos(const NLMISC::CVector2f &worldPos); + void setPlayerPos(const NLMISC::CVector2f &p) { _PlayerPos = p; } NLMISC::CVector2f getPlayerPos() const { return _PlayerPos; } // test if player is currently panning the map @@ -169,6 +172,7 @@ public: CLandMarkOptions getUserLandMarkOptions(uint32 lmindex) const; // target the given landmark void targetLandmark(CCtrlButton *lm); + void targetLandmarkResult(uint32 index); // get the world position of a landmark or return vector Null if not found void getLandmarkPosition(const CCtrlButton *lm, NLMISC::CVector2f &worldPos); @@ -457,7 +461,17 @@ private: // filter keywords std::vector _LandmarkFilter; - uint32 _MatchedLandmarkCount; + struct SMatchedLandmark + { + SMatchedLandmark(const NLMISC::CVector2f pos, const ucstring &title, CLandMarkOptions opts) + : Pos(pos), Title(title), Options(opts) + {} + NLMISC::CVector2f Pos; + ucstring Title; + + CLandMarkOptions Options; + }; + std::vector _MatchedLandmarks; ////////////////////// // Respawn handling // @@ -497,6 +511,7 @@ private: */ void updateLandMarkList(TLandMarkButtonVect &lm); void updateLandMarkTextList(TLandMarkTextVect &lm); + void updateMatchedLandmarks(); // void removeLandMarks(TLandMarkButtonVect &lm); /** create landmarks from the continent (and remove previous ones) From b5a0fbe2663a39fe42412f213d689332ed27693e Mon Sep 17 00:00:00 2001 From: Riasan Date: Wed, 9 May 2018 21:33:02 +0200 Subject: [PATCH 034/303] Changed: rework "creat guild" UI Window --HG-- branch : develop --- .../gamedev/interfaces_v3/bot_chat_v4.xml | 126 ++++++++++-------- 1 file changed, 69 insertions(+), 57 deletions(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/bot_chat_v4.xml b/code/ryzom/client/data/gamedev/interfaces_v3/bot_chat_v4.xml index 2d3271082..b8d9e358e 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/bot_chat_v4.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/bot_chat_v4.xml @@ -436,6 +436,9 @@ + + - - - + w="380" + onenter="" + title="uiGuildDescWarning" + tooltip="uiGuildDescWarning" /> + + + + - + posref="BL BL" + x="150" + y="15" /> + Date: Fri, 11 May 2018 14:42:49 +0300 Subject: [PATCH 035/303] Added: Duplicating macro or macro commands --HG-- branch : develop --- .../data/gamedev/interfaces_v3/macros.xml | 4 ++ .../src/interface_v3/macrocmd_manager.cpp | 42 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/macros.xml b/code/ryzom/client/data/gamedev/interfaces_v3/macros.xml index 8c2eb9f82..d3c886282 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/macros.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/macros.xml @@ -234,6 +234,8 @@ + + @@ -324,6 +326,8 @@ + + diff --git a/code/ryzom/client/src/interface_v3/macrocmd_manager.cpp b/code/ryzom/client/src/interface_v3/macrocmd_manager.cpp index fdb4f45c8..cff97fc68 100644 --- a/code/ryzom/client/src/interface_v3/macrocmd_manager.cpp +++ b/code/ryzom/client/src/interface_v3/macrocmd_manager.cpp @@ -777,6 +777,25 @@ public: }; REGISTER_ACTION_HANDLER( CHandlerNewMacroCmdEdit, "new_macro_cmd_edit"); +// *************************************************************************** +// Called from context menu when we right click on a command of the new_macro container +class CHandlerNewMacroCmdCopy: public IActionHandler +{ +public: + virtual void execute(CCtrlBase *pCaller, const string &/* Params */) + { + CMacroCmdManager *pMCM = CMacroCmdManager::getInstance(); + sint nCmdNb = getCmdNbFromId(pCaller->getId()); + pMCM->CurrentEditMacro.addCommand(pMCM->CurrentEditMacro.Commands[nCmdNb].Name, + pMCM->CurrentEditMacro.Commands[nCmdNb].Params, + nCmdNb); + CInterfaceManager *pIM = CInterfaceManager::getInstance(); + CMacroCmdManager::getInstance()->EditCmd->deactivate(); + CAHManager::getInstance()->runActionHandler("new_macro_open",NULL); + } +}; +REGISTER_ACTION_HANDLER( CHandlerNewMacroCmdCopy, "new_macro_cmd_copy"); + // *************************************************************************** // Called from context menu when we right click on a command of the new_macro container class CHandlerNewMacroCmdDelete: public IActionHandler @@ -1087,6 +1106,29 @@ public: }; REGISTER_ACTION_HANDLER( CHandlerMacrosEdit, "macros_edit"); +// *************************************************************************** +// Called from context menu on a macro +class CHandlerMacrosCopy : public IActionHandler +{ +public: + virtual void execute(CCtrlBase *pCaller, const string &/* Params */) + { + sint nMacNb = getMacroFromId(pCaller->getId()); + CInterfaceManager *pIM = CInterfaceManager::getInstance(); + CMacroCmdManager *pMCM = CMacroCmdManager::getInstance(); + + // duplicate selected macro + CMacroCmd m = pMCM->getMacros()[nMacNb]; + m.ID = -1; + m.Combo.Key = KeyCount; + m.Combo.KeyButtons = noKeyButton; + pMCM->addMacro(m, nMacNb+1); + + CAHManager::getInstance()->runActionHandler("macros_open",NULL); + } +}; +REGISTER_ACTION_HANDLER( CHandlerMacrosCopy, "macros_copy"); + // *************************************************************************** // Called from context menu on a macro class CHandlerMacrosDel : public IActionHandler From 4cca062177aa906a8682373d3905875780177ec7 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 11 May 2018 14:51:54 +0300 Subject: [PATCH 036/303] Changed: Move leave team menu option --HG-- branch : develop --- .../client/data/gamedev/interfaces_v3/game_context_menu.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/game_context_menu.xml b/code/ryzom/client/data/gamedev/interfaces_v3/game_context_menu.xml index 14ef15b80..25fd8b202 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/game_context_menu.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/game_context_menu.xml @@ -97,7 +97,6 @@ - @@ -107,6 +106,9 @@ + + + From a62c8eefd46f2ff1892a5d9f20edec59ba2f8e9c Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 13 May 2018 17:00:45 +0300 Subject: [PATCH 037/303] Fixed: Filtered user landmarks became visible when landmark was edited/removed. --HG-- branch : develop --- code/ryzom/client/src/interface_v3/group_map.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/ryzom/client/src/interface_v3/group_map.cpp b/code/ryzom/client/src/interface_v3/group_map.cpp index a841beb44..37a0a8a57 100644 --- a/code/ryzom/client/src/interface_v3/group_map.cpp +++ b/code/ryzom/client/src/interface_v3/group_map.cpp @@ -2574,6 +2574,10 @@ void CGroupMap::updateUserLandMarks() worldToMap(mapPos, _CurContinent->UserLandMarks[k].Pos); addLandMark(_UserLM, mapPos, _CurContinent->UserLandMarks[k].Title, getUserLandMarkOptions(k)); + + // hide landmark if not matching filter + if (!filterLandmark(_CurContinent->UserLandMarks[k].Title)) + _UserLM.back()->setActive(false); } invalidateCoords(); From ebbb270bc1b3ca6624d82496e4d6125e6b71bd49 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 13 May 2018 17:00:45 +0300 Subject: [PATCH 038/303] Fixed: Use target_stepy to calculate dy for scrolling --HG-- branch : develop --- code/nel/src/gui/ctrl_scroll.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/nel/src/gui/ctrl_scroll.cpp b/code/nel/src/gui/ctrl_scroll.cpp index 50e7c6aa1..acdaa15f5 100644 --- a/code/nel/src/gui/ctrl_scroll.cpp +++ b/code/nel/src/gui/ctrl_scroll.cpp @@ -1226,6 +1226,12 @@ namespace NLGUI if(hReal <= maxHReal) return; + if (_TargetStepY > 1) + { + sint sign = (0 < dy) - (dy < 0); + dy = sign * max(1, (dy / _TargetStepY)) * _TargetStepY; + } + // compute the new ofsY. sint32 ofsY= _Target->getOfsY(); ofsY+= dy; From 30caac063eae3f9b3cdfad6f480005f65ef0b872 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Wed, 23 May 2018 22:18:19 +0300 Subject: [PATCH 039/303] Fixed: Wrong text width when used inside html list element --HG-- branch : develop --- code/nel/src/gui/view_text.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index 2faae3a0a..c14a7f9a1 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -886,8 +886,8 @@ namespace NLGUI return _LineMaxW; else { - sint parentWidth = std::min(_Parent->getMaxWReal(), _Parent->getWReal()); - return std::min(parentWidth-(sint)(_XReal-_Parent->getXReal()), (sint)_LineMaxW); + sint parentWidth = std::min(_Parent->getMaxWReal(), _Parent->getWReal() - _Parent->getMarginLeft()); + return std::min(parentWidth-(sint)(_XReal-(_Parent->getXReal()-_Parent->getMarginLeft())), (sint)_LineMaxW); } } From c228349098c97cddf2d46a9e14e95c150894230f Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 28 May 2018 14:36:58 +0300 Subject: [PATCH 040/303] Added: Personal projects directory --HG-- branch : develop --- .hgignore | 3 +++ code/CMakeLists.txt | 4 ++++ code/personal/README.md | 9 +++++++++ 3 files changed, 16 insertions(+) create mode 100644 code/personal/README.md diff --git a/.hgignore b/.hgignore index 41a0e58cf..990487a2a 100644 --- a/.hgignore +++ b/.hgignore @@ -242,6 +242,9 @@ external_stlport nel_tools* ryzom_tools* +#personal projects +personal/ + #Dumps *.dmp diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 0e72cc5f9..425f296f5 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -475,6 +475,10 @@ IF(WITH_STUDIO) ADD_SUBDIRECTORY(studio) ENDIF() +IF(WITH_PERSONAL) + ADD_SUBDIRECTORY(personal) +ENDIF() + # To build the documention, you will have to enable it # and then do the equivalent of "make DoxygenDoc". IF(BUILD_DOCUMENTATION) diff --git a/code/personal/README.md b/code/personal/README.md new file mode 100644 index 000000000..cb2ebdf41 --- /dev/null +++ b/code/personal/README.md @@ -0,0 +1,9 @@ + +cmake option to include CMakeLists.txt from this directory is `-DWITH_PERSONAL=ON` + +Example: + +``` +ADD_SUBDIRECTORY(example) +``` + From e2617bfe9bd64345b56d2947a21663f31b576381 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 28 May 2018 14:46:16 +0300 Subject: [PATCH 041/303] Fixed: Decoding dds with improper width/height --HG-- branch : develop --- code/nel/src/misc/bitmap.cpp | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/code/nel/src/misc/bitmap.cpp b/code/nel/src/misc/bitmap.cpp index 47bdf3886..7a3a38e70 100644 --- a/code/nel/src/misc/bitmap.cpp +++ b/code/nel/src/misc/bitmap.cpp @@ -1356,10 +1356,14 @@ bool CBitmap::decompressDXT1(bool alpha) { for(k=0; k<4; k++) { - dataTmp[m][pixelsCount + j*wtmp*4 + 4*k]= c[bits&3].R; - dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+1]= c[bits&3].G; - dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+2]= c[bits&3].B; - dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+3]= c[bits&3].A; + uint32 index = pixelsCount + (j*wtmp+k)*4; + // incase input image does not have proper width/height + if (index+3 > mipMapSz) break; + + dataTmp[m][index+0]= c[bits&3].R; + dataTmp[m][index+1]= c[bits&3].G; + dataTmp[m][index+2]= c[bits&3].B; + dataTmp[m][index+3]= c[bits&3].A; bits>>=2; } } @@ -1466,10 +1470,14 @@ bool CBitmap::decompressDXT3() { for(k=0; k<4; k++) { - dataTmp[m][pixelsCount + j*wtmp*4 + 4*k]= c[bits&3].R; - dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+1]= c[bits&3].G; - dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+2]= c[bits&3].B; - dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+3]= alpha[4*j+k]; + uint32 index = pixelsCount + (j*wtmp+k)*4; + // incase input image does not have proper width/height + if (index+3 > mipMapSz) break; + + dataTmp[m][index+0]= c[bits&3].R; + dataTmp[m][index+1]= c[bits&3].G; + dataTmp[m][index+2]= c[bits&3].B; + dataTmp[m][index+3]= alpha[4*j+k]; bits>>=2; } } @@ -1602,10 +1610,14 @@ bool CBitmap::decompressDXT5() { for(k=0; k<4; k++) { - dataTmp[m][pixelsCount + (j*wtmp+k)*4 +0]= c[bits&3].R; - dataTmp[m][pixelsCount + (j*wtmp+k)*4 +1]= c[bits&3].G; - dataTmp[m][pixelsCount + (j*wtmp+k)*4 +2]= c[bits&3].B; - dataTmp[m][pixelsCount + (j*wtmp+k)*4 +3]= (uint8) alpha[codeAlpha[4*j+k]]; + uint32 index = pixelsCount + (j*wtmp+k)*4; + // incase input image does not have proper width/height + if (index+3 > mipMapSz) break; + + dataTmp[m][index+0]= c[bits&3].R; + dataTmp[m][index+1]= c[bits&3].G; + dataTmp[m][index+2]= c[bits&3].B; + dataTmp[m][index+3]= (uint8) alpha[codeAlpha[4*j+k]]; bits>>=2; } } From 97d0d45384fde8f8fc4187f2b06db0dafcf61387 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 29 May 2018 22:34:29 +0300 Subject: [PATCH 042/303] Fixed: lua:showDiv accessing already deleted objects --HG-- branch : develop --- code/nel/src/gui/group_html.cpp | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index de1064bd7..ef193b54e 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -4027,13 +4027,6 @@ namespace NLGUI void CGroupHTML::endParagraph() { - // Remove previous paragraph if empty - if (_Paragraph && (_Paragraph->getNumChildren() == 0)) - { - _Paragraph->getParent ()->delGroup(_Paragraph); - _Paragraph = NULL; - } - _Paragraph = NULL; paragraphChange (); @@ -4043,13 +4036,6 @@ namespace NLGUI void CGroupHTML::newParagraph(uint beginSpace) { - // Remove previous paragraph if empty - if (_Paragraph && (_Paragraph->getNumChildren() == 0)) - { - _Paragraph->getParent ()->delGroup(_Paragraph); - _Paragraph = NULL; - } - // Add a new paragraph CGroupParagraph *newParagraph = new CGroupParagraph(CViewBase::TCtorParam()); newParagraph->setResizeFromChildH(true); @@ -4889,13 +4875,6 @@ namespace NLGUI if (!group) return; - // Remove previous paragraph if empty - if (_Paragraph && (_Paragraph->getNumChildren() == 0)) - { - _Paragraph->getParent ()->delGroup(_Paragraph); - _Paragraph = NULL; - } - registerAnchor(group); if (!_DivName.empty()) From 6573d96fd7c44393a864e4898303e97946739eba Mon Sep 17 00:00:00 2001 From: ulukyn Date: Thu, 31 May 2018 21:03:05 +0200 Subject: [PATCH 043/303] Fixed: enable _TrustedDomain when html is rendered by lua code --HG-- branch : develop --- code/nel/src/gui/group_html.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index ef193b54e..c3494028c 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -5830,6 +5830,8 @@ namespace NLGUI CLuaIHM::checkArgType(ls, funcName, 1, LUA_TSTRING); std::string html = ls.toString(1); + // Always trust domain if rendered from lua + _TrustedDomain = true; renderHtmlString(html); return 0; From 6499b1b0535280f17e91da87126c025099bde819 Mon Sep 17 00:00:00 2001 From: ulukyn Date: Wed, 6 Jun 2018 14:15:42 +0200 Subject: [PATCH 044/303] Added: getDbProp64 to get 64b values from db with lua --HG-- branch : develop --- .../client/src/interface_v3/lua_ihm_ryzom.cpp | 17 +++++++++++++++++ .../client/src/interface_v3/lua_ihm_ryzom.h | 1 + 2 files changed, 18 insertions(+) diff --git a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp index 241e8f269..36780f9e5 100644 --- a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp +++ b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp @@ -491,6 +491,7 @@ void CLuaIHMRyzom::RegisterRyzomFunctions(NLGUI::CLuaState &ls) luabind::module(L) [ LUABIND_FUNC(getDbProp), + LUABIND_FUNC(getDbProp64), LUABIND_FUNC(setDbProp), LUABIND_FUNC(addDbProp), LUABIND_FUNC(delDbProp), @@ -2570,6 +2571,22 @@ sint32 CLuaIHMRyzom::getDbProp(const std::string &dbProp) } } +sint64 CLuaIHMRyzom::getDbProp64(const std::string &dbProp) +{ + //H_AUTO(Lua_CLuaIHM_getDbProp) + CInterfaceManager *pIM = CInterfaceManager::getInstance(); + CCDBNodeLeaf *node = NLGUI::CDBManager::getInstance()->getDbProp(dbProp, false); + + if (node) + return node->getValue64(); + else + { + debugInfo(toString("getDbProp(): '%s' dbProp Not found", dbProp.c_str())); + return 0; + } +} + + void CLuaIHMRyzom::setDbProp(const std::string &dbProp, sint32 value) { //H_AUTO(Lua_CLuaIHM_setDbProp) diff --git a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.h b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.h index 0c29bbd3c..fa8e57c9c 100644 --- a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.h +++ b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.h @@ -120,6 +120,7 @@ private: ///////////////////////////// Standard Lua stuff ends here ////////////////////////////////////////////// static sint32 getDbProp(const std::string &dbProp); // return 0 if not found. + static sint64 getDbProp64(const std::string &dbProp); // return 0 if not found. static void setDbProp(const std::string &dbProp, sint32 value); // Nb: the db prop is not created if not present. static void addDbProp(const std::string &dbProp, sint32 value); // Nb: the db prop is created if not present. static void delDbProp(const std::string &dbProp); From f80e36ebd689bf17893a0f930cb5481e554d8272 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 7 Jun 2018 12:59:58 +0300 Subject: [PATCH 045/303] Changed: Workaround for huge target reticle when max polygon is set to low --HG-- branch : develop --- code/ryzom/client/src/entity_cl.cpp | 2 ++ code/ryzom/client/src/init_main_loop.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/code/ryzom/client/src/entity_cl.cpp b/code/ryzom/client/src/entity_cl.cpp index 98d4c619c..30514fb95 100644 --- a/code/ryzom/client/src/entity_cl.cpp +++ b/code/ryzom/client/src/entity_cl.cpp @@ -3055,6 +3055,7 @@ void CEntityCL::updateVisiblePostPos(const NLMISC::TTime &/* currentTimeInMs */, if (!instance.empty()) { _SelectionFX.cast (instance); + _SelectionFX.setLoadBalancingGroup("SelectionFx"); if (_SelectionFX.empty()) { // shape found, but not a particle system @@ -3083,6 +3084,7 @@ void CEntityCL::updateVisiblePostPos(const NLMISC::TTime &/* currentTimeInMs */, if (!instance.empty()) { _MouseOverFX.cast (instance); + _MouseOverFX.setLoadBalancingGroup("SelectionFx"); if (_MouseOverFX.empty()) { // shape found, but not a particle system diff --git a/code/ryzom/client/src/init_main_loop.cpp b/code/ryzom/client/src/init_main_loop.cpp index cce91b5ba..910c454d0 100644 --- a/code/ryzom/client/src/init_main_loop.cpp +++ b/code/ryzom/client/src/init_main_loop.cpp @@ -593,6 +593,8 @@ void initMainLoop() Scene->setGroupLoadMaxPolygon("Skin", ClientCfg.SkinNbMaxPoly); Scene->setGroupLoadMaxPolygon("Fx", ClientCfg.FxNbMaxPoly); Scene->setMaxSkeletonsInNotCLodForm(ClientCfg.NbMaxSkeletonNotCLod); + // separate group for mouse/target selection reticle + Scene->setGroupLoadMaxPolygon("SelectionFx", 10000); // enable Scene Lighting Scene->enableLightingSystem(true); Scene->setAmbientGlobal(CRGBA::Black); From f0757edb36fe1c03bc68cf3ba1e39bdd09dc3090 Mon Sep 17 00:00:00 2001 From: ulukyn Date: Thu, 7 Jun 2018 17:01:51 +0200 Subject: [PATCH 046/303] Added: New PvpClan "Marauder" based on fame "black_kami" --HG-- branch : develop --- code/ryzom/common/src/game_share/pvp_clan.cpp | 5 ++++- code/ryzom/common/src/game_share/pvp_clan.h | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/code/ryzom/common/src/game_share/pvp_clan.cpp b/code/ryzom/common/src/game_share/pvp_clan.cpp index d6b4f6a0a..f030b73f5 100644 --- a/code/ryzom/common/src/game_share/pvp_clan.cpp +++ b/code/ryzom/common/src/game_share/pvp_clan.cpp @@ -37,6 +37,7 @@ namespace PVP_CLAN NL_STRING_CONVERSION_TABLE_ENTRY(Matis) NL_STRING_CONVERSION_TABLE_ENTRY(Tryker) NL_STRING_CONVERSION_TABLE_ENTRY(Zorai) + NL_STRING_CONVERSION_TABLE_ENTRY(Marauder) NL_END_STRING_CONVERSION_TABLE(TPVPClan, PVPClanConversion, Unknown) TPVPClan fromString(const std::string & str) @@ -69,6 +70,7 @@ namespace PVP_CLAN factionIndexes[Matis] = CStaticFames::getInstance().getFactionIndex("matis"); factionIndexes[Tryker] = CStaticFames::getInstance().getFactionIndex("tryker"); factionIndexes[Zorai] = CStaticFames::getInstance().getFactionIndex("zorai"); + factionIndexes[Marauder] = CStaticFames::getInstance().getFactionIndex("black_kami"); for (uint i = BeginClans; i <= EndClans; i++) nlassert( factionIndexes[i] != CStaticFames::INVALID_FACTION_INDEX ); @@ -84,7 +86,7 @@ namespace PVP_CLAN { // These names are in order of the enum TPVPClan // The first two clans, "None" and "Neutral", don't count. Subtract 2 from the lookup. - std::string FactionNames[] = { "kami","karavan","fyros","matis","tryker","zorai" }; + std::string FactionNames[] = { "kami","karavan","fyros","matis","tryker","zorai","marauder" }; for (int looper = BeginClans; looper <= EndClans; looper += 1) { @@ -111,6 +113,7 @@ namespace PVP_CLAN factionSheetIds[Matis] = "matis.faction"; factionSheetIds[Tryker] = "tryker.faction"; factionSheetIds[Zorai] = "zorai.faction"; + factionSheetIds[Marauder] = "marauder.faction"; for (uint i = BeginClans; i <= EndClans; i++) nlassert( factionSheetIds[i] != NLMISC::CSheetId::Unknown ); diff --git a/code/ryzom/common/src/game_share/pvp_clan.h b/code/ryzom/common/src/game_share/pvp_clan.h index 717c5c138..14352828b 100644 --- a/code/ryzom/common/src/game_share/pvp_clan.h +++ b/code/ryzom/common/src/game_share/pvp_clan.h @@ -44,7 +44,9 @@ namespace PVP_CLAN Zorai, EndCivs = Zorai, // end of civs - EndClans = Zorai, // end of clans + + Marauder, + EndClans = Marauder, // end of clans Unknown, NbClans = Unknown, From 24b99e677c9a1069b1c42d5269fb0541be1b481e Mon Sep 17 00:00:00 2001 From: ulukyn Date: Thu, 7 Jun 2018 17:49:15 +0200 Subject: [PATCH 047/303] Changed: Added WinchGate headers to generate_client_db --HG-- branch : develop --- .../src/game_share/generate_client_db.xslt | 61 ++++++++++++++++++- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/code/ryzom/common/src/game_share/generate_client_db.xslt b/code/ryzom/common/src/game_share/generate_client_db.xslt index 0680a3e39..699630569 100644 --- a/code/ryzom/common/src/game_share/generate_client_db.xslt +++ b/code/ryzom/common/src/game_share/generate_client_db.xslt @@ -58,9 +58,37 @@ +// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/> +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + ///////////////////////////////////////////////////////////////// -// WARNING : this is a generated file, don't change it ! +// +// +// +// +// +// WARNING : this is a generated file, don't change it ! +// +// +// +// +// +// ///////////////////////////////////////////////////////////////// + #include "stdpch.h" #include "database_.h" @@ -125,8 +153,35 @@ void CBankAccessor_::init() #ifndef INCLUDED__H #define INCLUDED__H +// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/> +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + ///////////////////////////////////////////////////////////////// -// WARNING : this is a generated file, don't change it ! +// +// +// +// +// +// WARNING : this is a generated file, don't change it ! +// +// +// +// +// +// ///////////////////////////////////////////////////////////////// #include "nel/misc/string_common.h" @@ -693,4 +748,4 @@ void ::init(ICDBStructNode *parent< - \ No newline at end of file + From 1a128ac26987316adf71be909a2de095e345e944 Mon Sep 17 00:00:00 2001 From: ulukyn Date: Tue, 12 Jun 2018 13:39:33 +0200 Subject: [PATCH 048/303] Added: Diplay:inline-block option to style of div in group_html --HG-- branch : develop --- code/nel/src/gui/group_html.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index c3494028c..e0ed401ce 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -1570,6 +1570,8 @@ namespace NLGUI { if ((*it).first == "template") templateName = (*it).second; + else if ((*it).first == "display" && (*it).second == "inline-block") + _BlockLevelElement.back() = false; else tmplParams.push_back(TTmplParam((*it).first, (*it).second)); } From 0863830734194f226bf1fb5a34a6d4217e961eaf Mon Sep 17 00:00:00 2001 From: ulukyn Date: Tue, 12 Jun 2018 14:43:20 +0200 Subject: [PATCH 049/303] Added: Downloadable textures in texture property of CViewBitmap --HG-- branch : develop --- code/nel/include/nel/gui/group_html.h | 16 ++++++++++------ code/nel/src/gui/view_bitmap.cpp | 15 ++++++++++++++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index 56144b61e..35ba3e40e 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -106,6 +106,10 @@ namespace NLGUI sint32 MaxHeight; }; + // ImageDownload system + enum TDataType {ImgType= 0, BnpType}; + enum TImageType {NormalImage=0, OverImage}; + // Constructor CGroupHTML(const TCtorParam ¶m); ~CGroupHTML(); @@ -151,6 +155,10 @@ namespace NLGUI // End of the paragraph void endParagraph(); + + // add image download (used by view_bitmap.cpp to load web images) + void addImageDownload(const std::string &url, CViewBase *img, const CStyleParams &style = CStyleParams(), const TImageType type = NormalImage); + std::string localImageName(const std::string &url); // Timeout void setTimeout(float tm) {_TimeoutValue= std::max(0.f, tm);} @@ -722,6 +730,8 @@ namespace NLGUI return 0; return _Indent.back(); } + + // Current node is a title bool _Title; @@ -811,10 +821,6 @@ namespace NLGUI private: // decode all HTML entities static ucstring decodeHTMLEntities(const ucstring &str); - - // ImageDownload system - enum TDataType {ImgType= 0, BnpType}; - enum TImageType {NormalImage=0, OverImage}; struct CDataImageDownload { @@ -857,8 +863,6 @@ namespace NLGUI void initImageDownload(); void checkImageDownload(); - void addImageDownload(const std::string &url, CViewBase *img, const CStyleParams &style = CStyleParams(), const TImageType type = NormalImage); - std::string localImageName(const std::string &url); std::string getAbsoluteUrl(const std::string &url); bool isTrustedDomain(const std::string &domain); diff --git a/code/nel/src/gui/view_bitmap.cpp b/code/nel/src/gui/view_bitmap.cpp index b479cb889..79b8c32a4 100644 --- a/code/nel/src/gui/view_bitmap.cpp +++ b/code/nel/src/gui/view_bitmap.cpp @@ -21,6 +21,7 @@ #include "nel/gui/widget_manager.h" #include "nel/gui/interface_group.h" #include "nel/gui/group_container_base.h" +#include "nel/gui/group_html.h" using namespace std; using namespace NLMISC; @@ -452,7 +453,19 @@ namespace NLGUI // ---------------------------------------------------------------------------- void CViewBitmap::setTexture(const std::string & TxName) { - _TextureId.setTexture (TxName.c_str (), _TxtOffsetX, _TxtOffsetY, _TxtWidth, _TxtHeight, false); + if (TxName.find("://") != string::npos || TxName.find("//") == 0) + { + CGroupHTML *groupHtml = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:webig:content:html")); + if (groupHtml) { + string localname = groupHtml->localImageName(TxName); + if (!CFile::fileExists(localname)) + localname = "web_del.tga"; + _TextureId.setTexture (localname.c_str(), _TxtOffsetX, _TxtOffsetY, _TxtWidth, _TxtHeight, false); + groupHtml->addImageDownload(TxName, dynamic_cast(this)); + } + } + else + _TextureId.setTexture (TxName.c_str (), _TxtOffsetX, _TxtOffsetY, _TxtWidth, _TxtHeight, false); } // ---------------------------------------------------------------------------- From 1c142ef968800e27d1577f730f681c0f1bbe42ad Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 22 Jun 2018 19:44:12 +0300 Subject: [PATCH 050/303] Fixed: Font size calculations for scaled text. --HG-- branch : experimental-ui-scaling --- code/nel/include/nel/gui/view_text.h | 12 +- code/nel/src/gui/group_editbox.cpp | 12 +- code/nel/src/gui/view_text.cpp | 265 ++++++++++-------- .../src/interface_v3/action_handler_edit.cpp | 18 +- 4 files changed, 166 insertions(+), 141 deletions(-) diff --git a/code/nel/include/nel/gui/view_text.h b/code/nel/include/nel/gui/view_text.h index e5c5d7e10..ad5a30f2a 100644 --- a/code/nel/include/nel/gui/view_text.h +++ b/code/nel/include/nel/gui/view_text.h @@ -129,6 +129,8 @@ namespace NLGUI uint getFontHeight() const; // get current font leg height, in pixels uint getFontLegHeight() const; + // get current line height, in pixels + float getLineHeight() const; // Set the display mode (supported with multiline only for now) void setTextMode(TTextMode mode); TTextMode getTextMode() const { return _TextMode; } @@ -149,11 +151,11 @@ namespace NLGUI * When looking at standard edit box, we see that if a line is split accross to line with no * This also returns the height of the line */ - void getCharacterPositionFromIndex(sint index, bool lineEnd, sint &x, sint &y, sint &height) const; + void getCharacterPositionFromIndex(sint index, bool lineEnd, float &x, float &y, float &height) const; /** From a coordinate relative to the BR BR corner of the text, return the index of a character. * If no character is found at the given position, the closest character is returned (first or last character, for the line or the whole text) */ - void getCharacterIndexFromPosition(sint x, sint y, uint &index, bool &lineEnd) const; + void getCharacterIndexFromPosition(float x, float y, uint &index, bool &lineEnd) const; /** From a character index, get the index of the line it belongs to, or -1 if the index is invalid * \param cursorDisplayedAtEndOfPreviousLine true if the cursor is displayed at the end of the previous line that match its index */ @@ -330,7 +332,7 @@ namespace NLGUI CFormatInfo Format; public: // build from a string, using the current text context - void build(const ucstring &text, NL3D::UTextContext &textContext, float scale, uint numSpaces= 0); + void build(const ucstring &text, NL3D::UTextContext &textContext, uint numSpaces= 0); }; typedef std::vector TWordVect; @@ -343,7 +345,7 @@ namespace NLGUI // Clear the line & remove text contexts void clear(NL3D::UTextContext &textContext); // Add a new word (and its context) in the line + a number of spaces to append at the end of the line - void addWord(const ucstring &word, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth, NL3D::UTextContext &textContext, float scale); + void addWord(const ucstring &word, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth, NL3D::UTextContext &textContext); void addWord(const CWord &word, float fontWidth); uint getNumWords() const { return (uint)_Words.size(); } CWord &getWord(uint index) { return _Words[index]; } @@ -404,7 +406,7 @@ namespace NLGUI uint _TextSelectionEnd; // First line X coordinate - sint _FirstLineX; + float _FirstLineX; /// Dynamic tooltips std::vector _Tooltips; diff --git a/code/nel/src/gui/group_editbox.cpp b/code/nel/src/gui/group_editbox.cpp index 13979f4aa..1a800b23a 100644 --- a/code/nel/src/gui/group_editbox.cpp +++ b/code/nel/src/gui/group_editbox.cpp @@ -702,9 +702,9 @@ namespace NLGUI sint32 maxPos= max(_CursorPos, _SelectCursorPos) + (sint32)_Prompt.length(); // get its position on screen - sint cxMinPos, cyMinPos; - sint cxMaxPos, cyMaxPos; - sint height; + float cxMinPos, cyMinPos; + float cxMaxPos, cyMaxPos; + float height; _ViewText->getCharacterPositionFromIndex(minPos, false, cxMinPos, cyMinPos, height); _ViewText->getCharacterPositionFromIndex(maxPos, false, cxMaxPos, cyMaxPos, height); @@ -755,8 +755,8 @@ namespace NLGUI if (_BlinkState) // is the cursor shown ? { // get its position on screen - sint cx, cy; - sint height; + float cx, cy; + float height; _ViewText->getCharacterPositionFromIndex(_CursorPos + (sint)_Prompt.length(), _CursorAtPreviousLineEnd, cx, cy, height); // display the cursor // get the texture for the cursor @@ -1482,7 +1482,7 @@ namespace NLGUI if (_ViewText->getWReal() > _WReal) { // Check if cursor visible - sint xCursVT, xCurs, yTmp, hTmp; + float xCursVT, xCurs, yTmp, hTmp; // Get the cursor pos from the BL of the viewtext _ViewText->getCharacterPositionFromIndex(_CursorPos+(sint)_Prompt.size(), false, xCursVT, yTmp, hTmp); // Get the cursor pos from the BL of the edit box diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index 881b4fa5d..f9403014e 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -957,8 +957,31 @@ namespace NLGUI CViewRenderer &rVR = *CViewRenderer::getInstance(); +#if 0 //rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(64,64,64,255)); + // debug text with mouse hover + if(CWidgetManager::getInstance()->getPointer()) + { + // but must check first if mouse is over + sint32 x = CWidgetManager::getInstance()->getPointer()->getX(); + sint32 y = CWidgetManager::getInstance()->getPointer()->getY(); + bool mouseIn; + // use parent clip or self clip? + if(_OverExtendViewTextUseParentRect) + mouseIn= _Parent && _Parent->isIn(x,y); + else + mouseIn= isIn(x,y); + // if the mouse cursor is in the clip area + if(mouseIn) { + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, 1, 0, false, rVR.getBlankTextureId(), CRGBA(200,200,200,255)); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_HReal, _WReal, 1, 0, false, rVR.getBlankTextureId(), CRGBA(200,200,200,255)); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(200,200,200,255)); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(200,200,200,255)); + } + } +#endif + // *** Out Of Clip? sint32 ClipX, ClipY, ClipW, ClipH; rVR.getClipWindow (ClipX, ClipY, ClipW, ClipH); @@ -1003,19 +1026,12 @@ namespace NLGUI TextContext->setEmbolden (_Embolden); TextContext->setOblique (_Oblique); - float y = _YReal; - //y += _LinesInfos[_LinesInfos.size()-1].StringLine / h; - // Y is the base line of the string, so it must be grown up. - y += _FontLegHeight; - - sint y_line = _YReal+_FontLegHeight-2.0f*_Scale; + float y = _YReal * _Scale + _FontLegHeight; if (_MultiMinLine > _Lines.size()) { - uint dy = getMultiMinOffsetY(); - y += dy; - y_line += dy; + y += getMultiMinOffsetY() * _Scale; } // special selection code @@ -1056,7 +1072,7 @@ namespace NLGUI { CLine &currLine = *_Lines[i]; // current x position - float px = (float) (_XReal + ((i==0) ? (sint)_FirstLineX : 0)); + float px = (float) (_XReal * _Scale + ((i==0) ? (sint)_FirstLineX : 0)); // draw each words of the line for(uint k = 0; k < currLine.getNumWords(); ++k) { @@ -1083,24 +1099,25 @@ namespace NLGUI px += firstSpace; // skip tabulation before current word if(currWord.Format.TabX) - px= max(px, (float)(_XReal + currWord.Format.TabX*_FontWidth)); + px= max(px, (float)(_XReal * _Scale + currWord.Format.TabX*_FontWidth)); // draw. We take floorf px to avoid filtering of letters that are not located on a pixel boundary - rVR.drawText (_RenderLayer, px, y, currWord.Index, ClipX, ClipY, ClipX+ClipW, ClipY+ClipH, *TextContext); + float fx = px / _Scale; + float fy = y / _Scale; + rVR.drawText (_RenderLayer, fx, fy, currWord.Index, ClipX, ClipY, ClipX+ClipW, ClipY+ClipH, *TextContext); // Draw a line if (_Underlined) - rVR.drawRotFlipBitmap (_RenderLayer, (sint)floorf(px), y_line, line_width, 1.0f / _Scale, 0, false, rVR.getBlankTextureId(), col); + rVR.drawRotFlipBitmap (_RenderLayer, fx, fy - _FontLegHeight*0.3f / _Scale, line_width / _Scale, 1.0f / _Scale, 0, false, rVR.getBlankTextureId(), col); if (_StrikeThrough) - rVR.drawRotFlipBitmap (_RenderLayer, (sint)floorf(px), y_line + (_FontHeight / 2), line_width, 1.0f / _Scale, 0, false, rVR.getBlankTextureId(), col); + rVR.drawRotFlipBitmap (_RenderLayer, fx, fy + _FontHeight*0.2f / _Scale, line_width / _Scale, 1.0f / _Scale, 0, false, rVR.getBlankTextureId(), col); // skip word px += currWord.Info.StringWidth; } // go one line up - y += (_FontHeight + _MultiLineSpace); - y_line += _FontHeight+_MultiLineSpace; + y += (_FontHeight + _MultiLineSpace * _Scale); } // reset selection @@ -1134,10 +1151,8 @@ namespace NLGUI TextContext->setLetterColors(_LetterColors, _Index); } - float y = _YReal; - // Y is the base line of the string, so it must be grown up. - y += _FontLegHeight; + float y = _YReal * _Scale + _FontLegHeight; // special selection code if(_TextSelection) @@ -1148,14 +1163,14 @@ namespace NLGUI TextContext->setStringColor(_Index, col); // draw - rVR.drawText (_RenderLayer, _XReal, y, _Index, ClipX, ClipY, ClipX+ClipW, ClipY+ClipH, *TextContext); + rVR.drawText (_RenderLayer, _XReal, y / _Scale, _Index, ClipX, ClipY, ClipX+ClipW, ClipY+ClipH, *TextContext); // Draw a line if (_Underlined) - rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_FontLegHeight-2.0f*_Scale, _WReal, 1, 0, false, rVR.getBlankTextureId(), col); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal - _FontLegHeight*0.3f/_Scale, _WReal, 1, 0, false, rVR.getBlankTextureId(), col); if (_StrikeThrough) - rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+(_FontLegHeight/2), _WReal, 1, 0, false, rVR.getBlankTextureId(), col); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal + _FontHeight*0.2f / _Scale, _WReal, 1, 0, false, rVR.getBlankTextureId(), col); // reset selection if(_TextSelection) @@ -1204,7 +1219,6 @@ namespace NLGUI } } } - } // *************************************************************************** @@ -1344,6 +1358,7 @@ namespace NLGUI // *************************************************************************** void CViewText::setLineMaxW (sint nMaxW, bool invalidate) { + nMaxW *= _Scale; if(_LineMaxW!=nMaxW) { _LineMaxW = nMaxW; @@ -1395,19 +1410,25 @@ namespace NLGUI // *************************************************************************** uint CViewText::getFontWidth() const { - return _FontWidth; + return _FontWidth / _Scale; } // *************************************************************************** uint CViewText::getFontHeight() const { - return _FontHeight; + return _FontHeight / _Scale; } // *************************************************************************** uint CViewText::getFontLegHeight() const { - return _FontLegHeight; + return _FontLegHeight / _Scale; + } + + // *************************************************************************** + float CViewText::getLineHeight() const + { + return _FontHeight / _Scale + _MultiLineSpace; } // *************************************************************************** @@ -1418,7 +1439,7 @@ namespace NLGUI { // first line is always present even if _Lines is empty uint nbLines = _MultiMinLine - std::max((sint)1, (sint)_Lines.size()); - dy = nbLines * _FontHeight + (nbLines - 1) * _MultiLineSpace; + dy = (nbLines * _FontHeight + (nbLines - 1) * _MultiLineSpace * _Scale) / _Scale; } return dy; } @@ -1434,7 +1455,7 @@ namespace NLGUI linePushed= true; } // Append to the last line - _Lines.back()->addWord(ucCurrentWord, 0, wordFormat, _FontWidth, *TextContext, _Scale); + _Lines.back()->addWord(ucCurrentWord, 0, wordFormat, _FontWidth, *TextContext); // reset the word ucCurrentWord.clear(); } @@ -1450,11 +1471,12 @@ namespace NLGUI ucstring ucCurrentWord; CFormatInfo wordFormat; // line state - float rWidthCurrentLine = 0, rWidthLetter; + float rWidthCurrentLine = 0; bool linePushed= false; // for all the text uint textSize= (uint)_Text.size(); uint formatTagIndex= 0; + nMaxWidth *= _Scale; for (i = 0; i < textSize; ++i) { if(isFormatTagChange(i, formatTagIndex)) @@ -1487,21 +1509,20 @@ namespace NLGUI ucstring ucStrLetter; ucStrLetter= ucLetter; si = TextContext->getStringInfo (ucStrLetter); - rWidthLetter = (si.StringWidth / _Scale); - if ((rWidthCurrentLine + rWidthLetter) > nMaxWidth) + if ((rWidthCurrentLine + si.StringWidth) > nMaxWidth) { flushWordInLine(ucCurrentWord, linePushed, wordFormat); // reset line state, and begin with the cut letter linePushed= false; - rWidthCurrentLine = rWidthLetter; + rWidthCurrentLine = si.StringWidth; ucCurrentWord = ucLetter; } else { // Grow the current word ucCurrentWord += ucLetter; - rWidthCurrentLine += rWidthLetter; + rWidthCurrentLine += si.StringWidth; } } } @@ -1531,7 +1552,7 @@ namespace NLGUI if(currLine[i].Format!=lineWordFormat) { // add the current lineWord to the line. - _Lines.back()->addWord(lineWord, 0, lineWordFormat, _FontWidth, *TextContext, _Scale); + _Lines.back()->addWord(lineWord, 0, lineWordFormat, _FontWidth, *TextContext); // get new lineWordFormat lineWordFormat= currLine[i].Format; // and clear @@ -1546,7 +1567,7 @@ namespace NLGUI } if(!lineWord.empty()) - _Lines.back()->addWord(lineWord, 0, lineWordFormat, _FontWidth, *TextContext, _Scale); + _Lines.back()->addWord(lineWord, 0, lineWordFormat, _FontWidth, *TextContext); // clear currLine.clear(); @@ -1564,7 +1585,7 @@ namespace NLGUI static const ucstring spaceStr(" "); // precLineWidth valid only id precedent line is part of same paragraph. float precLineWidth= 0; - float lineWidth = (float)_FirstLineX * _Scale; // width of the current line + float lineWidth = (float)_FirstLineX; // width of the current line uint numWordsInLine = 0; // number of words in the current line bool isParagraphStart = true; // A paragraph is a group of characters between 2 \n bool lineFeed; @@ -1575,6 +1596,7 @@ namespace NLGUI CFormatInfo wordFormat; uint formatTagIndex= 0; // + nMaxWidth *= _Scale; while (currPos != _Text.length()) { TCharPos spaceEnd; @@ -1655,7 +1677,7 @@ namespace NLGUI // compute size of spaces/Tab + word newLineWidth = lineWidth + numSpaces * _SpaceWidth; newLineWidth = max(newLineWidth, (float)wordFormat.TabX*_FontWidth); - newLineWidth+= si.StringWidth / _Scale; + newLineWidth+= si.StringWidth; } // // Does the word go beyond the end of line ? @@ -1707,7 +1729,7 @@ namespace NLGUI { uint maxNumSpaces = std::max(1U, (uint) (nMaxWidth / _SpaceWidth)); CWord spaceWord; // a word with only spaces in it - spaceWord.build (ucstring (""), *TextContext, _Scale, maxNumSpaces); + spaceWord.build (ucstring (""), *TextContext, maxNumSpaces); spaceWord.Format= wordFormat; _Lines.push_back(TLineSPtr(new CLine)); _Lines.back()->addWord(spaceWord, _FontWidth); @@ -1730,13 +1752,13 @@ namespace NLGUI { oneChar = wordValue[currChar]; si = TextContext->getStringInfo(oneChar); - if ((uint) (px + si.StringWidth / _Scale) > nMaxWidth) break; - px += si.StringWidth / _Scale; + if ((uint) (px + si.StringWidth) > nMaxWidth) break; + px += si.StringWidth; } currChar = std::max((uint) 1, currChar); // must fit at least one character otherwise there's an infinite loop wordValue = _Text.substr(spaceEnd, currChar); CWord word; - word.build(wordValue, *TextContext, _Scale, numSpaces); + word.build(wordValue, *TextContext, numSpaces); word.Format= wordFormat; _Lines.push_back(TLineSPtr(new CLine)); float roomForSpaces = (float) nMaxWidth - word.Info.StringWidth; @@ -1771,7 +1793,7 @@ namespace NLGUI if (!wordValue.empty() || numSpaces != 0) { CWord word; - word.build(wordValue, *TextContext, _Scale, numSpaces); + word.build(wordValue, *TextContext, numSpaces); word.Format= wordFormat; // update line width _Lines.back()->addWord(word, _FontWidth); @@ -1890,24 +1912,25 @@ namespace NLGUI _Lines.pop_back(); CViewText::CLine *endLine = new CViewText::CLine; CViewText::CWord w; - w.build(_OverflowText, *TextContext, _Scale); + w.build(_OverflowText, *TextContext); endLine->addWord(w, _FontWidth); _Lines.push_back(TLineSPtr(endLine)); } } // Calculate size + float rMultiLineSpace = _MultiLineSpace * _Scale; float rTotalW = 0; for (uint i = 0; i < _Lines.size(); ++i) { rTotalW = std::max(_Lines[i]->getWidth() + ((i==0)?_FirstLineX:0), rTotalW); } - _W = (sint)ceilf(rTotalW); - _H = std::max(_FontHeight, ceilf(_FontHeight * _Lines.size() + std::max(0, sint(_Lines.size()) - 1) * _MultiLineSpace)); + _W = (sint)ceilf(rTotalW / _Scale); + _H = std::max(_FontHeight / _Scale, ceilf((_FontHeight * _Lines.size() + std::max(0, sint(_Lines.size()) - 1) * rMultiLineSpace) / _Scale)); // See if we should pretend to have at least X lines if (_MultiMinLine > 1) - _H = std::max(_H, sint(_FontHeight * _MultiMinLine + (_MultiMinLine - 1) * _MultiLineSpace)); + _H = std::max(_H, sint((_FontHeight * _MultiMinLine + (_MultiMinLine - 1) * rMultiLineSpace)/_Scale)); // Compute tooltips size if (!_Tooltips.empty()) @@ -1916,7 +1939,6 @@ namespace NLGUI for (uint j=0 ; j<_Lines[i]->getNumWords() ; ++j) { CWord word = _Lines[i]->getWord(j); - // float w = _Lines[i]->getWidth(); if (word.Format.IndexTt != -1) { @@ -1924,7 +1946,7 @@ namespace NLGUI { CCtrlToolTip *pTooltip = _Tooltips[word.Format.IndexTt]; - sint y = (sint) ceilf((_FontHeight + _MultiLineSpace) * (_Lines.size() - i - 1)); + sint y = (sint) ceilf(((_FontHeight + rMultiLineSpace) * (_Lines.size() - i - 1))/_Scale); pTooltip->setX(0); pTooltip->setY(y); @@ -1943,11 +1965,10 @@ namespace NLGUI // Common case: no W clamp _Index = TextContext->textPush (_Text); _Info = TextContext->getStringInfo (_Index); - _Info.StringWidth /= _Scale; - _W = (sint)ceilf(_Info.StringWidth); + _W = (sint)ceilf(_Info.StringWidth / _Scale); // Rare case: clamp W => recompute slowly, cut letters - if(_W>_LineMaxW) + if(_Info.StringWidth > _LineMaxW) { TextContext->erase (_Index); @@ -1957,18 +1978,14 @@ namespace NLGUI ucCurrentLine.reserve(_Text.size()); // Append ... to the end of line - float dotWidth; + float dotWidth = 0.f; if (_OverflowText.size() > 0) { si = TextContext->getStringInfo (ucstring(_OverflowText)); - dotWidth = si.StringWidth / _Scale; - } - else - { - dotWidth = 0.0f; + dotWidth = si.StringWidth; } - float rWidthCurrentLine = 0, rWidthLetter; + float rWidthCurrentLine = 0; // for all the text if (_ClampRight) { @@ -1978,8 +1995,7 @@ namespace NLGUI ucstring ucStrLetter; ucStrLetter= ucLetter; si = TextContext->getStringInfo (ucStrLetter); - rWidthLetter = (si.StringWidth / _Scale); - if ((rWidthCurrentLine + rWidthLetter + dotWidth) > _LineMaxW) + if ((rWidthCurrentLine + si.StringWidth + dotWidth) > _LineMaxW) { break; } @@ -1987,7 +2003,7 @@ namespace NLGUI { // Grow the current line ucCurrentLine += ucLetter; - rWidthCurrentLine += rWidthLetter; + rWidthCurrentLine += si.StringWidth; } } @@ -2005,8 +2021,7 @@ namespace NLGUI ucstring ucStrLetter; ucStrLetter= ucLetter; si = TextContext->getStringInfo (ucStrLetter); - rWidthLetter = (si.StringWidth / _Scale); - if ((rWidthCurrentLine + rWidthLetter + dotWidth) > _LineMaxW) + if ((rWidthCurrentLine + si.StringWidth + dotWidth) > _LineMaxW) { break; } @@ -2014,7 +2029,7 @@ namespace NLGUI { // Grow the current line ucCurrentLine = ucLetter + ucCurrentLine; - rWidthCurrentLine += rWidthLetter; + rWidthCurrentLine += si.StringWidth; } } @@ -2028,14 +2043,13 @@ namespace NLGUI // And so setup this trunc text _Index = TextContext->textPush (ucCurrentLine); _Info = TextContext->getStringInfo (_Index); - _Info.StringWidth /= _Scale; - _W = (sint)ceilf(_Info.StringWidth); + _W = (sint)ceilf(_Info.StringWidth / _Scale); _SingleLineTextClamped= true; } // same height always - _H = (sint)ceilf(_FontHeight); + _H = (sint)ceilf(_FontHeight / _Scale); } _InvalidTextContext= false; @@ -2072,12 +2086,12 @@ namespace NLGUI if (_ClampRight) { sint32 parentRight = parent->getXReal() + parent->getWReal() - (sint32) _AutoClampOffset; - setLineMaxW(ceilf(std::max((sint32) 0, parentRight - _XReal) / _Scale)); + setLineMaxW(std::max((sint32) 0, parentRight - _XReal)); } else { sint32 parentLeft = parent->getXReal() + (sint32) _AutoClampOffset; - setLineMaxW(ceilf(std::max((sint32) 0, _XReal + _WReal - parentLeft) / _Scale)); + setLineMaxW(std::max((sint32) 0, _XReal + _WReal - parentLeft)); } } } @@ -2194,7 +2208,7 @@ namespace NLGUI } // *************************************************************************** - void CViewText::getCharacterPositionFromIndex(sint index, bool cursorAtPreviousLineEnd, sint &x, sint &y, sint &height) const + void CViewText::getCharacterPositionFromIndex(sint index, bool cursorAtPreviousLineEnd, float &x, float &y, float &height) const { NLMISC::clamp(index, 0, (sint) _Text.length()); NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(_FontName); @@ -2204,18 +2218,19 @@ namespace NLGUI TextContext->setFontSize (_FontSize*_Scale); TextContext->setEmbolden (_Embolden); TextContext->setOblique (_Oblique); - // CViewRenderer &rVR = *CViewRenderer::getInstance(); - height = getFontHeight(); + height = getLineHeight(); // if (_MultiLine) { - uint dy = getMultiMinOffsetY(); + float fx, fy; + float dy = getMultiMinOffsetY() * _Scale; + float nMaxWidth = getCurrentMultiLineMaxW() * _Scale; uint charIndex = 0; // special case for end of text if (index == (sint) _Text.length()) { - y = dy; + fy = dy; if (_Lines.empty()) { x = 0; @@ -2223,10 +2238,12 @@ namespace NLGUI else { CLine &lastLine = *_Lines.back(); - x = (sint) (lastLine.getWidth() + lastLine.getEndSpaces() * lastLine.getSpaceWidth()); - sint nMaxWidth = getCurrentMultiLineMaxW(); - x = std::min(x, nMaxWidth); + fx = lastLine.getWidth() + lastLine.getEndSpaces() * lastLine.getSpaceWidth(); + fx = std::min(fx, nMaxWidth); } + + x = fx / _Scale; + y = fy / _Scale; return; } for(sint i = 0; i < (sint) _Lines.size(); ++i) @@ -2235,10 +2252,12 @@ namespace NLGUI { // should display the character at the end of previous line CLine &currLine = *_Lines[i - 1]; - y = (sint) ((_FontHeight + _MultiLineSpace) * (_Lines.size() - i) + dy); - x = (sint) (currLine.getWidth() + currLine.getEndSpaces() * currLine.getSpaceWidth()); - sint nMaxWidth = getCurrentMultiLineMaxW(); - x = std::min(x, nMaxWidth); + fy = (_FontHeight + _MultiLineSpace * _Scale) * (_Lines.size() - i) + dy; + fx = currLine.getWidth() + currLine.getEndSpaces() * currLine.getSpaceWidth(); + fx = std::min(fx, nMaxWidth); + + x = fx / _Scale; + y = fy / _Scale; return; } CLine &currLine = *_Lines[i]; @@ -2246,14 +2265,16 @@ namespace NLGUI if ((sint) newCharIndex > index) { // ok, this line contains the character, now, see which word contains it. - y = (sint) ((_FontHeight + _MultiLineSpace) * (_Lines.size() - 1 - i) + dy); + fy = (_FontHeight + _MultiLineSpace * _Scale) * (_Lines.size() - 1 - i) + dy; // see if the index is in the spaces at the end of line if (index - charIndex >= currLine.getNumChars()) { uint numSpaces = index - charIndex - currLine.getNumChars(); - x = (sint) (currLine.getWidth() + numSpaces * _SpaceWidth); - sint nMaxWidth = getCurrentMultiLineMaxW(); - x = std::min(x, nMaxWidth); + fx = currLine.getWidth() + numSpaces * _SpaceWidth; + fx = std::min(fx, nMaxWidth); + + x = fx / _Scale; + y = fy / _Scale; return; } // now, search containing word in current line @@ -2271,15 +2292,19 @@ namespace NLGUI ucstring subStr = currWord.Text.substr(0, index - charIndex - currWord.NumSpaces); // compute the size UTextContext::CStringInfo si = TextContext->getStringInfo(subStr); - x = (sint) ceilf(px + si.StringWidth / _Scale + currWord.NumSpaces * currLine.getSpaceWidth()); - height = getFontHeight(); + fx = px + si.StringWidth + currWord.NumSpaces * currLine.getSpaceWidth(); + + x = fx / _Scale; + y = fy / _Scale; return; } else { // character is in the spaces preceding the word - x = (sint) ceilf(px + currLine.getSpaceWidth() * (index - charIndex)); - height = getFontHeight(); + fx = px + currLine.getSpaceWidth() * (index - charIndex); + + x = fx / _Scale; + y = fy / _Scale; return; } } @@ -2303,11 +2328,11 @@ namespace NLGUI } // *************************************************************************** - // Tool fct : From a word and a x coordinate, give the matching character index - static uint getCharacterIndex(const ucstring &textValue, float x, NL3D::UTextContext &textContext, float scale) + // Tool fct : From a word and a x coordinate (font scale), give the matching character index + static uint getCharacterIndex(const ucstring &textValue, float x, NL3D::UTextContext &textContext) { float px = 0.f; - float sw; + UTextContext::CStringInfo si; ucstring singleChar(" "); uint i; @@ -2316,13 +2341,12 @@ namespace NLGUI // get character width singleChar[0] = textValue[i]; si = textContext.getStringInfo(singleChar); - sw = si.StringWidth / scale; - px += sw; + px += si.StringWidth; // the character is at the i - 1 position if (px > x) { // if the half of the character is after the cursor, then prefer select the next one (like in Word) - if(px-sw/2 < x) + if(px-si.StringWidth/2.f < x) i++; break; } @@ -2331,10 +2355,13 @@ namespace NLGUI } // *************************************************************************** - void CViewText::getCharacterIndexFromPosition(sint x, sint y, uint &index, bool &cursorAtPreviousLineEnd) const + void CViewText::getCharacterIndexFromPosition(float x, float y, uint &index, bool &cursorAtPreviousLineEnd) const { NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(_FontName); + x *= _Scale; + y = roundf(y * _Scale); + // setup the text context TextContext->setHotSpot (UTextContext::BottomLeft); TextContext->setShaded (_Shadow); @@ -2347,7 +2374,7 @@ namespace NLGUI uint charPos = 0; if (_MultiLine) { - y -= getMultiMinOffsetY(); + y -= getMultiMinOffsetY() * _Scale; // seek the line float py = 0.f; if (py > y) @@ -2359,7 +2386,7 @@ namespace NLGUI sint line; for (line = (uint)_Lines.size() - 1; line >= 0; --line) { - float newPy = py + _FontHeight + _MultiLineSpace; + float newPy = py + _FontHeight + _MultiLineSpace * _Scale; if (newPy > y) { break; @@ -2392,6 +2419,7 @@ namespace NLGUI return; } + cursorAtPreviousLineEnd = false; float px = (float)_FirstLineX; for(uint k = 0; k < currLine.getNumWords(); ++k) { @@ -2408,14 +2436,12 @@ namespace NLGUI : 0; clamp(numSpaces, 0, (sint)currWord.NumSpaces); index = numSpaces + charPos; - cursorAtPreviousLineEnd = false; return; } else { // the coord is in the word itself - index = charPos + currWord.NumSpaces + getCharacterIndex(currWord.Text, (float) x - (px + spacesWidth), *TextContext, _Scale); - cursorAtPreviousLineEnd = false; + index = charPos + currWord.NumSpaces + getCharacterIndex(currWord.Text, x - (px + spacesWidth), *TextContext); return; } } @@ -2423,7 +2449,6 @@ namespace NLGUI charPos += (uint)currWord.Text.length() + currWord.NumSpaces; } index = charPos; - cursorAtPreviousLineEnd = false; return; } else @@ -2439,7 +2464,7 @@ namespace NLGUI index = 0; return; } - index = getCharacterIndex(_Text, (float) x, *TextContext, _Scale); + index = getCharacterIndex(_Text, x, *TextContext); return; } } @@ -2507,21 +2532,21 @@ namespace NLGUI // *************************************************************************** uint CViewText::getFirstLineX() const { - return _FirstLineX; + return _FirstLineX / _Scale; } // *************************************************************************** uint CViewText::getLastLineW () const { if (!_Lines.empty()) - return (uint)_Lines.back()->getWidth(); + return (uint)_Lines.back()->getWidth() / _Scale; return 0; } // *************************************************************************** void CViewText::setFirstLineX(sint firstLineX) { - _FirstLineX = firstLineX; + _FirstLineX = firstLineX * _Scale; } ///////////////////////////////////// @@ -2540,10 +2565,10 @@ namespace NLGUI } // *************************************************************************** - void CViewText::CLine::addWord(const ucstring &text, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth, NL3D::UTextContext &textContext, float scale) + void CViewText::CLine::addWord(const ucstring &text, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth, NL3D::UTextContext &textContext) { CWord word; - word.build(text, textContext, scale, numSpaces); + word.build(text, textContext, numSpaces); word.Format= wordFormat; addWord(word, fontWidth); } @@ -2587,13 +2612,12 @@ namespace NLGUI } // *************************************************************************** - void CViewText::CWord::build(const ucstring &text, NL3D::UTextContext &textContext, float scale, uint numSpaces) + void CViewText::CWord::build(const ucstring &text, NL3D::UTextContext &textContext, uint numSpaces) { Text = text; NumSpaces = numSpaces; Index = textContext.textPush(text); Info = textContext.getStringInfo(Index); - Info.StringWidth /= scale; } // *************************************************************************** @@ -2667,7 +2691,7 @@ namespace NLGUI si = TextContext->getStringInfo(wordValue); // compute size of spaces + word - lineWidth += numSpaces * _SpaceWidth + si.StringWidth / _Scale; + lineWidth += numSpaces * _SpaceWidth + si.StringWidth; currPos = wordEnd; } @@ -2679,7 +2703,7 @@ namespace NLGUI linePos = lineEnd+1; } - return (sint32)ceilf(maxWidth); + return (sint32)ceilf(maxWidth / _Scale); } // *************************************************************************** @@ -2696,7 +2720,7 @@ namespace NLGUI if (_TextMode == ClipWord) { // No largest font parameter, return the font height - return (sint32)ceilf(_FontHeight); + return (sint32)ceilf(_FontHeight / _Scale); } // If we can't clip the words, return the size of the largest word else if ((_TextMode == DontClipWord) || (_TextMode == Justified)) @@ -2733,16 +2757,15 @@ namespace NLGUI si = TextContext->getStringInfo(wordValue); // Larger ? - float stringWidth = (si.StringWidth / _Scale); - if (stringWidth>maxWidth) - maxWidth = stringWidth; + if (maxWidth < si.StringWidth) + maxWidth = si.StringWidth; // Next word currPos = wordEnd; } } - return ceilf(maxWidth); + return ceilf(maxWidth / _Scale); } // *************************************************************************** @@ -2796,16 +2819,16 @@ namespace NLGUI si = TextContext->getStringInfo(chars); } // add a padding of 1 pixel else the top will be truncated - _FontHeight = (si.StringHeight / _Scale) + 1; - _FontLegHeight = si.StringLine / _Scale; + _FontHeight = si.StringHeight + 1; + _FontLegHeight = si.StringLine; // Space width si = TextContext->getStringInfo(ucstring(" ")); - _SpaceWidth = si.StringWidth / _Scale; + _SpaceWidth = si.StringWidth; // Font Width si = TextContext->getStringInfo(ucstring("_")); - _FontWidth = si.StringWidth / _Scale; + _FontWidth = si.StringWidth; } diff --git a/code/ryzom/client/src/interface_v3/action_handler_edit.cpp b/code/ryzom/client/src/interface_v3/action_handler_edit.cpp index 2b3bb7c5e..9c44fa492 100644 --- a/code/ryzom/client/src/interface_v3/action_handler_edit.cpp +++ b/code/ryzom/client/src/interface_v3/action_handler_edit.cpp @@ -383,10 +383,10 @@ class CAHEditPreviousLine : public CAHEdit // .. so do nothing return; } - sint cx, cy; - sint height; + float cx, cy; + float height; _GroupEdit->getViewText()->getCharacterPositionFromIndex(cursorPosInText, _GroupEdit->isCursorAtPreviousLineEnd(), cx, cy, height); - cy += height + _GroupEdit->getViewText()->getMultiLineSpace(); + cy += _GroupEdit->getViewText()->getLineHeight(); uint newCharIndex; bool newLineEnd; _GroupEdit->getViewText()->getCharacterIndexFromPosition(cx, cy, newCharIndex, newLineEnd); @@ -401,8 +401,8 @@ class CAHEditPreviousLine : public CAHEdit } _GroupEdit->setCursorAtPreviousLineEnd(false); // takes character whose X is closer to the current X - sint cx0, cx1; - sint cy0, cy1; + float cx0, cx1; + float cy0, cy1; _GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex, _GroupEdit->isCursorAtPreviousLineEnd(), cx0, cy0, height); _GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex + 1, _GroupEdit->isCursorAtPreviousLineEnd(), cx1, cy1, height); if (abs(cx0 - cx) < abs(cx1 - cx) || cy0 != cy1) @@ -446,8 +446,8 @@ class CAHEditNextLine : public CAHEdit } else if (_GroupEdit->getViewText()->getMultiLine()) { - sint cx, cy; - sint height; + float cx, cy; + float height; _GroupEdit->getViewText()->getCharacterPositionFromIndex(_GroupEdit->getCursorPos() + (sint)_GroupEdit->getPrompt().length(), _GroupEdit->isCursorAtPreviousLineEnd(), cx, cy, height); if (cy != 0) { @@ -466,8 +466,8 @@ class CAHEditNextLine : public CAHEdit } _GroupEdit->setCursorAtPreviousLineEnd(false); // takes character whose X is closer to the current X - sint cx0, cx1; - sint cy0, cy1; + float cx0, cx1; + float cy0, cy1; _GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex, _GroupEdit->isCursorAtPreviousLineEnd(), cx0, cy0, height); _GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex + 1, _GroupEdit->isCursorAtPreviousLineEnd(), cx1, cy1, height); if (abs(cx0 - cx) < abs(cx1 - cx) || cy0 != cy1) From 7eb63bfb3f16771e5e37b2a992f7defbb087ae8a Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 25 Jun 2018 11:16:59 +0300 Subject: [PATCH 051/303] Fixed: Font underline position --HG-- branch : experimental-ui-scaling --- code/nel/src/gui/view_text.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index f9403014e..1a175e224 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -1108,7 +1108,7 @@ namespace NLGUI // Draw a line if (_Underlined) - rVR.drawRotFlipBitmap (_RenderLayer, fx, fy - _FontLegHeight*0.3f / _Scale, line_width / _Scale, 1.0f / _Scale, 0, false, rVR.getBlankTextureId(), col); + rVR.drawRotFlipBitmap (_RenderLayer, fx, fy - _FontLegHeight*0.6f / _Scale, line_width / _Scale, 1.0f / _Scale, 0, false, rVR.getBlankTextureId(), col); if (_StrikeThrough) rVR.drawRotFlipBitmap (_RenderLayer, fx, fy + _FontHeight*0.2f / _Scale, line_width / _Scale, 1.0f / _Scale, 0, false, rVR.getBlankTextureId(), col); From 13e2da698a1c3ec840944da5161a90dd3a2bb224 Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Tue, 3 Jul 2018 16:09:15 +0800 Subject: [PATCH 052/303] Fix build under Visual Studio 2008 --HG-- branch : develop --- code/CMakeModules/GetRevision.cmake | 2 ++ code/nel/include/nel/gui/http_hsts.h | 4 ++-- code/nel/src/gui/CMakeLists.txt | 4 ++-- code/nel/src/gui/http_hsts.cpp | 16 ++++++++++------ 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/code/CMakeModules/GetRevision.cmake b/code/CMakeModules/GetRevision.cmake index b29a8763e..dba90c765 100644 --- a/code/CMakeModules/GetRevision.cmake +++ b/code/CMakeModules/GetRevision.cmake @@ -83,4 +83,6 @@ ENDIF() IF(DEFINED REVISION) MESSAGE(STATUS "Found revision ${REVISION}") +ELSE() + SET(REVISION 0) ENDIF() diff --git a/code/nel/include/nel/gui/http_hsts.h b/code/nel/include/nel/gui/http_hsts.h index 2693461cd..28f1b5f5b 100644 --- a/code/nel/include/nel/gui/http_hsts.h +++ b/code/nel/include/nel/gui/http_hsts.h @@ -42,7 +42,7 @@ namespace NLGUI class CStrictTransportSecurity { public: - typedef std::map THSTSObject; + typedef std::map THSTSObjectMap; static CStrictTransportSecurity* getInstance(); static void release(); @@ -66,7 +66,7 @@ namespace NLGUI ~CStrictTransportSecurity(); std::string _Filename; - THSTSObject _Domains; + THSTSObjectMap _Domains; }; } diff --git a/code/nel/src/gui/CMakeLists.txt b/code/nel/src/gui/CMakeLists.txt index 5233b8ceb..cdd090f0b 100644 --- a/code/nel/src/gui/CMakeLists.txt +++ b/code/nel/src/gui/CMakeLists.txt @@ -6,9 +6,9 @@ SOURCE_GROUP("src" FILES ${SRC}) NL_TARGET_LIB(nelgui ${SRC} ${HEADERS}) -INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR} ${LUA_INCLUDE_DIR} ${LUABIND_INCLUDE_DIR} ${CURL_INCLUDE_DIRS}) +INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR} ${LUA_INCLUDE_DIR} ${LUABIND_INCLUDE_DIR} ${CURL_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR}) -TARGET_LINK_LIBRARIES(nelgui nelmisc nel3d ${LUA_LIBRARIES} ${LUABIND_LIBRARIES} ${CURL_LIBRARIES}) +TARGET_LINK_LIBRARIES(nelgui nelmisc nel3d ${LUA_LIBRARIES} ${LUABIND_LIBRARIES} ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES}) NL_DEFAULT_PROPS(nelgui "NeL, Library: NeL GUI") NL_ADD_RUNTIME_FLAGS(nelgui) diff --git a/code/nel/src/gui/http_hsts.cpp b/code/nel/src/gui/http_hsts.cpp index c69062538..c57bb738c 100644 --- a/code/nel/src/gui/http_hsts.cpp +++ b/code/nel/src/gui/http_hsts.cpp @@ -87,9 +87,12 @@ namespace NLGUI { if (domain.empty() || _Domains.empty()) return false; - if (_Domains.count(domain) > 0) + THSTSObjectMap::const_iterator itHsts; + + itHsts = _Domains.find(domain); + if (itHsts != _Domains.end()) { - hsts = _Domains.at(domain); + hsts = itHsts->second; return true; } @@ -99,11 +102,12 @@ namespace NLGUI { { std::string tmp; tmp = domain.substr(firstOf+1); - if (_Domains.count(tmp)) + itHsts = _Domains.find(tmp); + if (itHsts != _Domains.end()) { - if (_Domains.at(tmp).IncludeSubDomains) + if (itHsts->second.IncludeSubDomains) { - hsts = _Domains.at(tmp); + hsts = itHsts->second; return true; } @@ -182,7 +186,7 @@ namespace NLGUI { { uint32 nbItems = _Domains.size(); f.serial(nbItems); - for (THSTSObject::iterator it = _Domains.begin(); it != _Domains.end(); ++it) + for (THSTSObjectMap::iterator it = _Domains.begin(); it != _Domains.end(); ++it) { std::string domain(it->first); f.serial(domain); From 1f897f6106373cb306bb01d240ee3385f6407034 Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Tue, 3 Jul 2018 16:10:04 +0800 Subject: [PATCH 053/303] Fix configuration for Snowballs --HG-- branch : develop --- code/snowballs2/bin/snowballs_client_default.cfg | 3 +++ code/snowballs2/client/src/configuration.cpp | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/code/snowballs2/bin/snowballs_client_default.cfg b/code/snowballs2/bin/snowballs_client_default.cfg index 49ec9e4d5..f8af00386 100755 --- a/code/snowballs2/bin/snowballs_client_default.cfg +++ b/code/snowballs2/bin/snowballs_client_default.cfg @@ -57,6 +57,9 @@ ScreenFull = 1; // Start position of the player (the z is always 0) StartPoint = { 1840.0, -970.0, 0.0 }; +// Anti-Aliasing +EnableFXAA = 0; + ////////////////////////////////////////////////////////////////////////////// // HMD Variables ///////////////////////////////////////////////////////////// diff --git a/code/snowballs2/client/src/configuration.cpp b/code/snowballs2/client/src/configuration.cpp index 303db63ce..bc37448b2 100644 --- a/code/snowballs2/client/src/configuration.cpp +++ b/code/snowballs2/client/src/configuration.cpp @@ -37,7 +37,15 @@ namespace SBCLIENT { void CConfiguration::setAndCallback(const std::string &varName, void (*cb)(CConfigFile::CVar &var)) { ConfigFile->setCallback(varName, cb); - cb(*ConfigFile->getVarPtr(varName)); + CConfigFile::CVar *varPtr = ConfigFile->getVarPtr(varName); + if (!varPtr) + { + nlwarning("Missing config variable '%s'", varName.c_str()); + } + else + { + cb(*varPtr); + } } void CConfiguration::dropCallback(const std::string &varName) From 4444e93bf7b0380ba915780cd68c48a97d2d4f9b Mon Sep 17 00:00:00 2001 From: kervala Date: Tue, 10 Jul 2018 17:02:42 +0200 Subject: [PATCH 054/303] Changed: Use CPP11 everywhere if supported --HG-- branch : develop --- code/CMakeModules/PCHSupport.cmake | 4 ++-- code/CMakeModules/nel.cmake | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/code/CMakeModules/PCHSupport.cmake b/code/CMakeModules/PCHSupport.cmake index c396bd6cf..24b4d5a85 100644 --- a/code/CMakeModules/PCHSupport.cmake +++ b/code/CMakeModules/PCHSupport.cmake @@ -209,8 +209,8 @@ MACRO(PCH_SET_COMPILE_FLAGS _target) ENDIF() ENDIF() - IF(USE_CPP0X AND gcc_compiler_version GREATER "6.2.0") - LIST(APPEND _FLAGS "-std=gnu++11") + IF(CMAKE_CXX11_EXTENSION_COMPILE_OPTION) + LIST(APPEND _FLAGS ${CMAKE_CXX11_EXTENSION_COMPILE_OPTION}) ENDIF() # Format definitions diff --git a/code/CMakeModules/nel.cmake b/code/CMakeModules/nel.cmake index 95b28bb8a..6b5b36745 100644 --- a/code/CMakeModules/nel.cmake +++ b/code/CMakeModules/nel.cmake @@ -874,7 +874,9 @@ MACRO(NL_SETUP_BUILD) ENDIF() # use c++0x standard to use std::unique_ptr and std::shared_ptr - SET(PLATFORM_CXXFLAGS "${PLATFORM_CXXFLAGS} -std=c++0x") + IF(CMAKE_CXX11_EXTENSION_COMPILE_OPTION) + SET(PLATFORM_CXXFLAGS "${PLATFORM_CXXFLAGS} ${CMAKE_CXX11_EXTENSION_COMPILE_OPTION}") + ENDIF() ADD_PLATFORM_FLAGS("-D_REENTRANT") From f3753a08a8b3780f8d404ade353cce3b999e5d13 Mon Sep 17 00:00:00 2001 From: kervala Date: Tue, 10 Jul 2018 20:42:37 +0200 Subject: [PATCH 055/303] Changed: Allow to use static C++ runtimes --HG-- branch : develop --- code/CMakeModules/nel.cmake | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/code/CMakeModules/nel.cmake b/code/CMakeModules/nel.cmake index 6b5b36745..99d958771 100644 --- a/code/CMakeModules/nel.cmake +++ b/code/CMakeModules/nel.cmake @@ -238,6 +238,7 @@ MACRO(NL_SETUP_DEFAULT_OPTIONS) OPTION(WITH_EXTERNAL "With provided external." OFF) ENDIF() OPTION(WITH_STATIC_EXTERNAL "With static external libraries" OFF) + OPTION(WITH_STATIC_RUNTIMES "Use only static C++ runtimes" OFF) IF(UNIX AND NOT APPLE) OPTION(WITH_UNIX_STRUCTURE "Use UNIX structure (bin, include, lib)" ON ) ELSE() @@ -636,8 +637,14 @@ MACRO(NL_SETUP_BUILD) SET(NL_RELEASE_LINKFLAGS "/RELEASE ${NL_RELEASE_LINKFLAGS}") ENDIF() - SET(NL_DEBUG_CFLAGS "/Zi /MDd /RTC1 /D_DEBUG ${DEBUG_CFLAGS} ${NL_DEBUG_CFLAGS}") - SET(NL_RELEASE_CFLAGS "/MD /DNDEBUG ${RELEASE_CFLAGS} ${NL_RELEASE_CFLAGS}") + IF(WITH_STATIC_RUNTIMES) + SET(RUNTIME_FLAG "/MT") + ELSE() + SET(RUNTIME_FLAG "/MD") + ENDIF() + + SET(NL_DEBUG_CFLAGS "/Zi ${RUNTIME_FLAG}d /RTC1 /D_DEBUG ${DEBUG_CFLAGS} ${NL_DEBUG_CFLAGS}") + SET(NL_RELEASE_CFLAGS "${RUNTIME_FLAG} /DNDEBUG ${RELEASE_CFLAGS} ${NL_RELEASE_CFLAGS}") SET(NL_DEBUG_LINKFLAGS "/DEBUG /OPT:NOREF /OPT:NOICF /NODEFAULTLIB:msvcrt ${MSVC_INCREMENTAL_YES_FLAG} ${NL_DEBUG_LINKFLAGS}") SET(NL_RELEASE_LINKFLAGS "/OPT:REF /OPT:ICF /INCREMENTAL:NO ${NL_RELEASE_LINKFLAGS}") @@ -967,6 +974,10 @@ MACRO(NL_SETUP_BUILD) IF(NOT APPLE) ADD_PLATFORM_LINKFLAGS("-Wl,--no-undefined -Wl,--as-needed") + + IF(WITH_STATIC_RUNTIMES) + ADD_PLATFORM_LINKFLAGS("-static-libstdc++") + ENDIF() ENDIF() IF(NOT APPLE) From 7b23be0c46a07d1005325effdc80dcf605ad465b Mon Sep 17 00:00:00 2001 From: kervala Date: Wed, 18 Jul 2018 10:40:36 +0200 Subject: [PATCH 056/303] Fixed: Compilation under Linux with Qt 5.10 --HG-- branch : develop --- code/CMakeLists.txt | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 425f296f5..159c63ef2 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -312,12 +312,19 @@ IF(WITH_QT5) ADD_QT_PLUGIN(xcbglintegrations qxcb-glx-integration) ADD_QT_LIBRARY(XcbQpa) + ADD_QT_LIBRARY(GlxSupport) + ADD_QT_LIBRARY(ServiceSupport) + ADD_QT_LIBRARY(EdidSupport) + ADD_QT_LIBRARY(FontDatabaseSupport) + ADD_QT_LIBRARY(ThemeSupport) + ADD_QT_LIBRARY(EventDispatcherSupport) ADD_QT_LIBRARY(PlatformSupport) - SET(QT_LIBRARIES ${QT_LIBRARIES} -lX11-xcb -lXi -lSM -lICE -lxcb -lGL -lxcb-glx) + + SET(QT_LIBRARIES ${QT_LIBRARIES} -lX11-xcb -lSM -lICE -lxcb -lGL -lxcb-glx) IF(EXISTS "${QT_LIBRARY_DIR}/libxcb-static.a") SET(QT_LIBRARIES ${QT_LIBRARIES} "${QT_LIBRARY_DIR}/libxcb-static.a") ENDIF() - SET(QT_LIBRARIES ${QT_LIBRARIES} -lfontconfig) + SET(QT_LIBRARIES ${QT_LIBRARIES} -lfontconfig -lX11 -lXrender) ADD_QT_LIBRARY(DBus) ENDIF() @@ -329,6 +336,9 @@ IF(WITH_QT5) # harfbuzz is needed since Qt 5.3 IF(UNIX) SET(HB_LIB "${QT_LIBRARY_DIR}/libqtharfbuzzng.a") + IF(NOT EXISTS ${HB_LIB}) + SET(HB_LIB "${QT_LIBRARY_DIR}/libqtharfbuzz.a") + ENDIF() ELSEIF(WIN32) SET(HB_LIB "${QT_LIBRARY_DIR}/qtharfbuzzng.lib") ENDIF() @@ -373,6 +383,9 @@ IF(WITH_QT5) # pcre is needed since Qt 5.5 IF(UNIX) SET(PCRE_LIB "${QT_LIBRARY_DIR}/libqtpcre.a") + IF(NOT EXISTS ${PCRE_LIB}) + SET(PCRE_LIB "${QT_LIBRARY_DIR}/libqtpcre2.a") + ENDIF() ELSEIF(WIN32) SET(PCRE_LIB "${QT_LIBRARY_DIR}/qtpcre.lib") ENDIF() @@ -391,7 +404,7 @@ IF(WITH_QT5) ${CARBON_FRAMEWORK} ${SECURITY_FRAMEWORK}) ELSEIF(UNIX) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} -ldl -lrt) + SET(QT_LIBRARIES ${QT_LIBRARIES} ${ZLIB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} -ldl -lrt) ENDIF() ELSE() SET(QT_LIBRARIES Qt5::Widgets Qt5::Network Qt5::Xml Qt5::Gui Qt5::OpenGL Qt5::Core) From 728c602bc384c30de15a4fcd78db33e95aa46c28 Mon Sep 17 00:00:00 2001 From: kervala Date: Wed, 18 Jul 2018 10:41:11 +0200 Subject: [PATCH 057/303] Fixed: Compilation under Ubuntu 16.04 --HG-- branch : develop --- code/CMakeModules/nel.cmake | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/CMakeModules/nel.cmake b/code/CMakeModules/nel.cmake index 99d958771..3919419be 100644 --- a/code/CMakeModules/nel.cmake +++ b/code/CMakeModules/nel.cmake @@ -672,7 +672,7 @@ MACRO(NL_SETUP_BUILD) IF(APPLE) SET(OBJC_FLAGS -fobjc-abi-version=2 -fobjc-legacy-dispatch -fobjc-weak) - + IF(NOT XCODE) IF(CMAKE_OSX_ARCHITECTURES) SET(TARGETS_COUNT 0) @@ -959,8 +959,6 @@ MACRO(NL_SETUP_BUILD) ADD_PLATFORM_FLAGS("-fPIC") ENDIF() - SET(PLATFORM_CXXFLAGS "${PLATFORM_CXXFLAGS} -ftemplate-depth-48") - # hardening ADD_PLATFORM_FLAGS("-fstack-protector --param=ssp-buffer-size=4") From 41d2b26d1a904c5589a5753c3f6d791a4e78c12c Mon Sep 17 00:00:00 2001 From: kervala Date: Wed, 18 Jul 2018 22:17:04 +0200 Subject: [PATCH 058/303] Changed: Link dynamically to existing system libs only --HG-- branch : develop --- code/CMakeLists.txt | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 159c63ef2..df71410fb 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -227,6 +227,28 @@ MACRO(ADD_QT_PLUGIN _TYPE _NAME) ENDIF() ENDMACRO() +MACRO(ADD_QT_SYSTEM_LIBRARY _NAME) + # Save default suffixes + SET(_OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + + # Define specific suffixes + SET(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX}) + + # Find the library with specified suffixes + FIND_LIBRARY(${_NAME}_LIBRARY NAMES ${_NAME}) + + # Restore default suffixes + SET(CMAKE_FIND_LIBRARY_SUFFIXES ${_OLD_SUFFIXES}) + + IF(${_NAME}_LIBRARY) + MESSAGE(STATUS "Found ${${_NAME}_LIBRARY} ${_NAME}") + + LIST(APPEND QT_LIBRARIES ${${_NAME}_LIBRARY}) + ELSE() + MESSAGE(STATUS "Didn't find ${_NAME}") + ENDIF() +ENDMACRO() + IF(WITH_QT5) CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11 FATAL_ERROR) @@ -320,12 +342,24 @@ IF(WITH_QT5) ADD_QT_LIBRARY(EventDispatcherSupport) ADD_QT_LIBRARY(PlatformSupport) - SET(QT_LIBRARIES ${QT_LIBRARIES} -lX11-xcb -lSM -lICE -lxcb -lGL -lxcb-glx) + ADD_QT_LIBRARY(DBus) + IF(EXISTS "${QT_LIBRARY_DIR}/libxcb-static.a") SET(QT_LIBRARIES ${QT_LIBRARIES} "${QT_LIBRARY_DIR}/libxcb-static.a") ENDIF() - SET(QT_LIBRARIES ${QT_LIBRARIES} -lfontconfig -lX11 -lXrender) - ADD_QT_LIBRARY(DBus) + + # always link these in dynamic, API never changes + ADD_QT_SYSTEM_LIBRARY(X11) + ADD_QT_SYSTEM_LIBRARY(Xmu) + ADD_QT_SYSTEM_LIBRARY(X11-xcb) + ADD_QT_SYSTEM_LIBRARY(Xi) + ADD_QT_SYSTEM_LIBRARY(SM) + ADD_QT_SYSTEM_LIBRARY(ICE) + ADD_QT_SYSTEM_LIBRARY(xcb) + ADD_QT_SYSTEM_LIBRARY(GL) + ADD_QT_SYSTEM_LIBRARY(xcb-glx) + ADD_QT_SYSTEM_LIBRARY(fontconfig) + ADD_QT_SYSTEM_LIBRARY(Xrender) ENDIF() ADD_QT_PLUGIN(imageformats qgif) From adb3362b449de84b1d5b897d23775c44faf6bd3a Mon Sep 17 00:00:00 2001 From: kervala Date: Sun, 22 Jul 2018 18:37:44 +0200 Subject: [PATCH 059/303] Changed: Always compile ryzom_gameshare if WITH_RYZOM is defined --HG-- branch : develop --- code/ryzom/common/CMakeLists.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/code/ryzom/common/CMakeLists.txt b/code/ryzom/common/CMakeLists.txt index 00eec3097..82e5030a7 100644 --- a/code/ryzom/common/CMakeLists.txt +++ b/code/ryzom/common/CMakeLists.txt @@ -1,7 +1,4 @@ -# only compile game_share for Ryzom client, server and tools -IF(WITH_RYZOM_CLIENT OR WITH_RYZOM_SERVER OR WITH_RYZOM_TOOLS) - ADD_SUBDIRECTORY(src) -ENDIF() +ADD_SUBDIRECTORY(src) #ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_BINARY_DIR}/share/data_common.bnp" # COMMAND bnp_make -p ${CMAKE_CURRENT_SOURCE_DIR}/data_common ${CMAKE_BINARY_DIR}/share > /dev/null) From a2707f93f1e81d01d7135201c259fc4bb8e47dbb Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 26 Jul 2018 20:24:17 +0300 Subject: [PATCH 060/303] Fixed: Wrong resolution saved to config when window receives wm_destroy signal --HG-- branch : develop --- code/ryzom/client/src/main_loop.cpp | 4 ++++ code/ryzom/client/src/release.cpp | 4 +--- code/ryzom/client/src/release.h | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/code/ryzom/client/src/main_loop.cpp b/code/ryzom/client/src/main_loop.cpp index fe96d4da3..4657f1dff 100644 --- a/code/ryzom/client/src/main_loop.cpp +++ b/code/ryzom/client/src/main_loop.cpp @@ -80,6 +80,7 @@ #include "world_database_manager.h" #include "continent_manager.h" #include "ig_callback.h" +#include "release.h" //#include "fog_map.h" #include "movie_shooter.h" #include "sound_manager.h" @@ -2555,6 +2556,9 @@ bool mainLoop() if ( ! FarTP.isReselectingChar() ) // skip some parts if the user wants to quit in the middle of a char reselect { + // Saving ingame resolution when in windowed mode + saveIngameResolution(); + // Release the structure for the ping. Ping.release (); diff --git a/code/ryzom/client/src/release.cpp b/code/ryzom/client/src/release.cpp index ff569b22a..d5c16bf47 100644 --- a/code/ryzom/client/src/release.cpp +++ b/code/ryzom/client/src/release.cpp @@ -136,7 +136,7 @@ extern void selectTipsOfTheDay (uint tips); // *************************************************************************** // Saving ingame resolution when in windowed mode -static void saveIngameResolution() +void saveIngameResolution() { if (ClientCfg.Windowed) { @@ -382,8 +382,6 @@ void releaseMainLoop(bool closeConnection) { ProgressBar.release(); - saveIngameResolution(); - // Release R2 editor if applicable R2::getEditor().autoConfigRelease(IsInRingSession); diff --git a/code/ryzom/client/src/release.h b/code/ryzom/client/src/release.h index 02eae2fa7..56ceca73d 100644 --- a/code/ryzom/client/src/release.h +++ b/code/ryzom/client/src/release.h @@ -22,7 +22,8 @@ #include "nel/misc/types_nl.h" - +// Saving ingame resolution when in windowed mode +void saveIngameResolution(); // called from farTP at reselection void releaseMainLoopReselect(); // Release InGame Data From 5cb3f8426dfb34ac67bf2b5ae66e902dc65257a5 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 28 Jul 2018 11:24:03 +0200 Subject: [PATCH 061/303] Changed: Install Ryzom GameShare headers and libraries --HG-- branch : develop --- .../common/src/game_share/CMakeLists.txt | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/code/ryzom/common/src/game_share/CMakeLists.txt b/code/ryzom/common/src/game_share/CMakeLists.txt index 547b1a470..1a0b0da3f 100644 --- a/code/ryzom/common/src/game_share/CMakeLists.txt +++ b/code/ryzom/common/src/game_share/CMakeLists.txt @@ -1,5 +1,12 @@ -FILE(GLOB SRC *.cpp time_weather_season/*.cpp) -FILE(GLOB PRIV_H *.h time_weather_season/*.h) +FIND_PACKAGE(ZLIB REQUIRED) + +FILE(GLOB SRC *.cpp) +FILE(GLOB SRC_TIME time_weather_season/*.cpp) + +FILE(GLOB PRIV_H *.h) +FILE(GLOB PRIV_TIME_H time_weather_season/*.h) + +SET(HEADER ${PRIV_H}) FILE(GLOB R2 dms.h dms.cpp @@ -17,20 +24,21 @@ FILE(GLOB R2 ring_*.h ring_*.cpp) LIST(REMOVE_ITEM SRC R2) -LIST(REMOVE_ITEM PRIV_H R2) +LIST(REMOVE_ITEM HEADER R2) -SOURCE_GROUP("" FILES ${SRC} ${PRIV_H}) +SOURCE_GROUP("" FILES ${SRC} ${HEADER}) +SOURCE_GROUP("time_weather_season" FILES ${SRC_TIME} ${PRIV_TIME_H}) SOURCE_GROUP("R2" FILES ${R2}) # Filter out the source files not actually compiled. LIST(REMOVE_ITEM SRC ${CMAKE_CURRENT_SOURCE_DIR}/enum_template.cpp) -LIST(REMOVE_ITEM PRIV_H ${CMAKE_CURRENT_SOURCE_DIR}/enum_template.h) +LIST(REMOVE_ITEM HEADER ${CMAKE_CURRENT_SOURCE_DIR}/enum_template.h) -NL_TARGET_LIB(ryzom_gameshare ${PRIV_H} ${SRC} ${R2}) +NL_TARGET_LIB(ryzom_gameshare ${HEADER} ${PRIV_TIME_H} ${SRC} ${SRC_TIME} ${R2}) -INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR} ${NEL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) -TARGET_LINK_LIBRARIES(ryzom_gameshare nelmisc nelnet nelligo nelgeorges) +TARGET_LINK_LIBRARIES(ryzom_gameshare ${NELMISC_LIBRARIES} ${NELNET_LIBRARIES} ${NELLIGO_LIBRARIES} ${NELGEORGES_LIBRARIES}) NL_DEFAULT_PROPS(ryzom_gameshare "Ryzom, Library: Game Share") NL_ADD_RUNTIME_FLAGS(ryzom_gameshare) NL_ADD_LIB_SUFFIX(ryzom_gameshare) @@ -44,3 +52,9 @@ ENDIF() IF((WITH_INSTALL_LIBRARIES AND WITH_STATIC) OR NOT WITH_STATIC) INSTALL(TARGETS ryzom_gameshare LIBRARY DESTINATION ${RYZOM_LIB_PREFIX} ARCHIVE DESTINATION ${RYZOM_LIB_PREFIX} COMPONENT libraries) ENDIF() + +IF(WITH_INSTALL_LIBRARIES) + INSTALL(FILES ${PRIV_H} DESTINATION include/ryzom/game_share COMPONENT headers) + INSTALL(FILES ${PRIV_TIME_H} DESTINATION include/ryzom/game_share/time_weather_season COMPONENT headers) +ENDIF() + From 307eb77e63b44a4900a1647941bcefc851e8ad95 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 28 Jul 2018 11:31:32 +0200 Subject: [PATCH 062/303] Changed: Generate version_nl.h in include/nel/misc --HG-- branch : develop --- code/CMakeLists.txt | 6 +++--- code/CMakeModules/nel.cmake | 7 +++++++ code/nel/include/nel/misc/CMakeLists.txt | 6 +++++- code/nel/include/nel/misc/version_nl.cmake | 14 ++++++++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 code/nel/include/nel/misc/version_nl.cmake diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index df71410fb..25887a0e6 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -86,12 +86,12 @@ NL_SETUP_NELNS_DEFAULT_OPTIONS() NL_SETUP_RYZOM_DEFAULT_OPTIONS() NL_SETUP_SNOWBALLS_DEFAULT_OPTIONS() -NL_SETUP_PREFIX_PATHS() -RYZOM_SETUP_PREFIX_PATHS() - NL_SETUP_BUILD() NL_SETUP_BUILD_FLAGS() +NL_SETUP_PREFIX_PATHS() +RYZOM_SETUP_PREFIX_PATHS() + #----------------------------------------------------------------------------- #Platform specifics diff --git a/code/CMakeModules/nel.cmake b/code/CMakeModules/nel.cmake index 3919419be..258e777aa 100644 --- a/code/CMakeModules/nel.cmake +++ b/code/CMakeModules/nel.cmake @@ -374,6 +374,13 @@ MACRO(ADD_PLATFORM_LINKFLAGS _FLAGS) SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} ${_FLAGS}") ENDMACRO() +MACRO(CONVERT_VERSION_NUMBER _VERSION_NUMBER _BASE) + SET(${_VERSION_NUMBER} 0) + FOREACH(_ARG ${ARGN}) + MATH(EXPR ${_VERSION_NUMBER} "${${_VERSION_NUMBER}} * ${_BASE} + ${_ARG}") + ENDFOREACH() +ENDMACRO() + MACRO(NL_SETUP_BUILD) #----------------------------------------------------------------------------- diff --git a/code/nel/include/nel/misc/CMakeLists.txt b/code/nel/include/nel/misc/CMakeLists.txt index 4b77b813f..85d8914f5 100644 --- a/code/nel/include/nel/misc/CMakeLists.txt +++ b/code/nel/include/nel/misc/CMakeLists.txt @@ -1,3 +1,7 @@ +CONVERT_VERSION_NUMBER(NL_VERSION_NUM 100 ${NL_VERSION_MAJOR} ${NL_VERSION_MINOR} ${NL_VERSION_PATCH}) + +CONFIGURE_FILE(version_nl.cmake ${CMAKE_BINARY_DIR}/version_nl.h) + FILE(GLOB HEADERS *.h) -INSTALL(FILES ${HEADERS} DESTINATION include/nel/misc COMPONENT headers) +INSTALL(FILES ${HEADERS} ${CMAKE_BINARY_DIR}/version_nl.h DESTINATION include/nel/misc COMPONENT headers) diff --git a/code/nel/include/nel/misc/version_nl.cmake b/code/nel/include/nel/misc/version_nl.cmake new file mode 100644 index 000000000..2e650486e --- /dev/null +++ b/code/nel/include/nel/misc/version_nl.cmake @@ -0,0 +1,14 @@ +#ifndef NL_VERSION_H +#define NL_VERSION_H + +#define NL_VERSION "${NL_VERSION}" +#define NL_VERSION_MAJOR ${NL_VERSION_MAJOR} +#define NL_VERSION_MINOR ${NL_VERSION_MINOR} +#define NL_VERSION_PATCH ${NL_VERSION_PATCH} +#define NL_VERSION_NUM ${NL_VERSION_NUM} + +#define NL_REVISION ${REVISION} + +#define NL_BUILD_DATE "${BUILD_DATE}" + +#endif From d9e509d3ccd0882197cb957b9c78d123d2895104 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 28 Jul 2018 11:38:48 +0200 Subject: [PATCH 063/303] Changed: NeL/Ryzom Core Version 1.0.0 (why to keep a 0.x version for almost 20 years ?) --HG-- branch : develop --- code/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 25887a0e6..c97f269fc 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -53,8 +53,8 @@ ENDIF() CMAKE_MINIMUM_REQUIRED(VERSION 2.6) PROJECT(RyzomCore CXX C) -SET(NL_VERSION_MAJOR 0) -SET(NL_VERSION_MINOR 12) +SET(NL_VERSION_MAJOR 1) +SET(NL_VERSION_MINOR 0) SET(NL_VERSION_PATCH 0) SET(YEAR "2004-${CURRENT_YEAR}") SET(AUTHOR "Winch Gate and The Ryzom Core Community") From 0bd577310dfa707e0902ee0175abb8f9ba35ac62 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 28 Jul 2018 11:44:33 +0200 Subject: [PATCH 064/303] Added: New CMake modules to find NeL and Ryzom GameShare --HG-- branch : develop --- code/CMakeLists.txt | 255 +----- code/CMakeModules/FindHelpers.cmake | 943 +++++++++++++++++++++ code/CMakeModules/FindNeL.cmake | 398 +++++++++ code/CMakeModules/FindRyzomGameShare.cmake | 10 + 4 files changed, 1353 insertions(+), 253 deletions(-) create mode 100644 code/CMakeModules/FindHelpers.cmake create mode 100644 code/CMakeModules/FindNeL.cmake create mode 100644 code/CMakeModules/FindRyzomGameShare.cmake diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index c97f269fc..87367c98e 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -191,261 +191,10 @@ IF(APPLE) ENDIF() ENDIF() -MACRO(ADD_QT_LIBRARY _NAME) - IF(WIN32) - SET(_PREFIX "Qt5") - SET(_EXT "lib") - ELSE() - SET(_PREFIX "libQt5") - SET(_EXT "a") - ENDIF() - SET(_LIB "${QT_LIBRARY_DIR}/${_PREFIX}${_NAME}.${_EXT}") - IF(EXISTS ${_LIB}) - SET(QT_LIBRARIES ${QT_LIBRARIES} optimized ${_LIB}) - ENDIF() - SET(_LIB "${QT_LIBRARY_DIR}/${_PREFIX}${_NAME}d.${_EXT}") - IF(EXISTS ${_LIB}) - SET(QT_LIBRARIES ${QT_LIBRARIES} debug ${_LIB}) - ENDIF() -ENDMACRO() - -MACRO(ADD_QT_PLUGIN _TYPE _NAME) - IF(WIN32) - SET(_PREFIX "") - SET(_EXT "lib") - ELSE() - SET(_PREFIX "lib") - SET(_EXT "a") - ENDIF() - SET(_LIB "${QT_PLUGINS_DIR}/${_TYPE}/${_PREFIX}${_NAME}.${_EXT}") - IF(EXISTS ${_LIB}) - SET(QT_LIBRARIES ${QT_LIBRARIES} optimized ${_LIB}) - ENDIF() - SET(_LIB "${QT_PLUGINS_DIR}/${_TYPE}/${_PREFIX}${_NAME}d.${_EXT}") - IF(EXISTS ${_LIB}) - SET(QT_LIBRARIES ${QT_LIBRARIES} debug ${_LIB}) - ENDIF() -ENDMACRO() - -MACRO(ADD_QT_SYSTEM_LIBRARY _NAME) - # Save default suffixes - SET(_OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - - # Define specific suffixes - SET(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX}) - - # Find the library with specified suffixes - FIND_LIBRARY(${_NAME}_LIBRARY NAMES ${_NAME}) - - # Restore default suffixes - SET(CMAKE_FIND_LIBRARY_SUFFIXES ${_OLD_SUFFIXES}) - - IF(${_NAME}_LIBRARY) - MESSAGE(STATUS "Found ${${_NAME}_LIBRARY} ${_NAME}") - - LIST(APPEND QT_LIBRARIES ${${_NAME}_LIBRARY}) - ELSE() - MESSAGE(STATUS "Didn't find ${_NAME}") - ENDIF() -ENDMACRO() +INCLUDE(FindHelpers) IF(WITH_QT5) - CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11 FATAL_ERROR) - - SET(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QTDIR} $ENV{QTDIR}) - - FIND_PACKAGE(Qt5Core QUIET) - - IF(Qt5Core_FOUND) - # Check if we are using Qt static or shared libraries - GET_TARGET_PROPERTY(_FILE Qt5::Core IMPORTED_LOCATION_RELEASE) - - SET(QT_VERSION "${Qt5Core_VERSION_STRING}") - SET(_VERSION "${QT_VERSION}") - - IF(_FILE MATCHES "\\.(lib|a)$") - SET(QT_STATIC ON) - SET(_VERSION "${_VERSION} static version") - ELSE() - SET(QT_STATIC OFF) - SET(_VERSION "${_VERSION} shared version") - ENDIF() - - MESSAGE(STATUS "Found Qt ${_VERSION}") - - # These variables are not defined with Qt5 CMake modules - SET(QT_BINARY_DIR "${_qt5Core_install_prefix}/bin") - SET(QT_LIBRARY_DIR "${_qt5Core_install_prefix}/lib") - SET(QT_PLUGINS_DIR "${_qt5Core_install_prefix}/plugins") - SET(QT_TRANSLATIONS_DIR "${_qt5Core_install_prefix}/translations") - - # Fix wrong include directories with Qt 5 under Mac OS X - INCLUDE_DIRECTORIES("${_qt5Core_install_prefix}/include") - - FIND_PACKAGE(Qt5Gui) - FIND_PACKAGE(Qt5Widgets) - FIND_PACKAGE(Qt5OpenGL) - FIND_PACKAGE(Qt5Xml) - FIND_PACKAGE(Qt5LinguistTools) - FIND_PACKAGE(Qt5Network) - - IF(QT_STATIC) - ADD_DEFINITIONS(-DQT_STATICPLUGIN) - - SET(QT_LIBRARIES Qt5::Widgets) - - # Gui - SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::Gui Qt5::OpenGL) - - ADD_QT_LIBRARY(PrintSupport) - - IF(WIN32) - SET(QT_LIBRARIES ${QT_LIBRARIES} - ${WINSDK_LIBRARY_DIR}/Imm32.lib - ${WINSDK_LIBRARY_DIR}/OpenGL32.lib - ${WINSDK_LIBRARY_DIR}/WinMM.Lib) - ADD_QT_PLUGIN(platforms qwindows) - ADD_QT_LIBRARY(PlatformSupport) - ELSEIF(APPLE) - # Cups needs .dylib - SET(OLD_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - SET(CMAKE_FIND_LIBRARY_SUFFIXES .dylib) - FIND_LIBRARY(CUPS_LIBRARY cups) - SET(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_CMAKE_FIND_LIBRARY_SUFFIXES}) - - FIND_LIBRARY(IOKIT_FRAMEWORK IOKit) - FIND_LIBRARY(COCOA_FRAMEWORK Cocoa) - FIND_LIBRARY(SYSTEMCONFIGURATION_FRAMEWORK SystemConfiguration) - FIND_LIBRARY(OPENGL_FRAMEWORK NAMES OpenGL) - - SET(QT_LIBRARIES ${QT_LIBRARIES} - ${CUPS_LIBRARY} - ${COCOA_FRAMEWORK} - ${SYSTEMCONFIGURATION_FRAMEWORK} - ${IOKIT_FRAMEWORK} - ${OPENGL_FRAMEWORK}) - - ADD_QT_PLUGIN(printsupport cocoaprintersupport) - ADD_QT_PLUGIN(platforms qcocoa) - ADD_QT_LIBRARY(PlatformSupport) - ELSE() - # order is very important there - ADD_QT_PLUGIN(platforms qxcb) - ADD_QT_PLUGIN(xcbglintegrations qxcb-glx-integration) - - ADD_QT_LIBRARY(XcbQpa) - ADD_QT_LIBRARY(GlxSupport) - ADD_QT_LIBRARY(ServiceSupport) - ADD_QT_LIBRARY(EdidSupport) - ADD_QT_LIBRARY(FontDatabaseSupport) - ADD_QT_LIBRARY(ThemeSupport) - ADD_QT_LIBRARY(EventDispatcherSupport) - ADD_QT_LIBRARY(PlatformSupport) - - ADD_QT_LIBRARY(DBus) - - IF(EXISTS "${QT_LIBRARY_DIR}/libxcb-static.a") - SET(QT_LIBRARIES ${QT_LIBRARIES} "${QT_LIBRARY_DIR}/libxcb-static.a") - ENDIF() - - # always link these in dynamic, API never changes - ADD_QT_SYSTEM_LIBRARY(X11) - ADD_QT_SYSTEM_LIBRARY(Xmu) - ADD_QT_SYSTEM_LIBRARY(X11-xcb) - ADD_QT_SYSTEM_LIBRARY(Xi) - ADD_QT_SYSTEM_LIBRARY(SM) - ADD_QT_SYSTEM_LIBRARY(ICE) - ADD_QT_SYSTEM_LIBRARY(xcb) - ADD_QT_SYSTEM_LIBRARY(GL) - ADD_QT_SYSTEM_LIBRARY(xcb-glx) - ADD_QT_SYSTEM_LIBRARY(fontconfig) - ADD_QT_SYSTEM_LIBRARY(Xrender) - ENDIF() - - ADD_QT_PLUGIN(imageformats qgif) - ADD_QT_PLUGIN(imageformats qicns) - ADD_QT_PLUGIN(imageformats qico) - ADD_QT_PLUGIN(imageformats qjpeg) - - # harfbuzz is needed since Qt 5.3 - IF(UNIX) - SET(HB_LIB "${QT_LIBRARY_DIR}/libqtharfbuzzng.a") - IF(NOT EXISTS ${HB_LIB}) - SET(HB_LIB "${QT_LIBRARY_DIR}/libqtharfbuzz.a") - ENDIF() - ELSEIF(WIN32) - SET(HB_LIB "${QT_LIBRARY_DIR}/qtharfbuzzng.lib") - ENDIF() - IF(EXISTS ${HB_LIB}) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${HB_LIB}) - ENDIF() - - # freetype is needed since Qt 5.5 - FIND_PACKAGE(Freetype) - - IF(FREETYPE_FOUND) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${FREETYPE_LIBRARIES}) - ELSE() - IF(UNIX) - SET(FREETYPE_LIB "${QT_LIBRARY_DIR}/libqtfreetype.a") - ELSEIF(WIN32) - SET(FREETYPE_LIB "${QT_LIBRARY_DIR}/qtfreetype.lib") - ENDIF() - IF(EXISTS ${FREETYPE_LIB}) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${FREETYPE_LIB}) - ENDIF() - ENDIF() - - ADD_QT_PLUGIN(accessible qtaccessiblewidgets) - - SET(QT_LIBRARIES ${QT_LIBRARIES} ${PNG_LIBRARIES} ${JPEG_LIBRARY}) - - # Network - SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::Network Qt5::Xml) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES}) - - IF(WIN32) - SET(QT_LIBRARIES ${QT_LIBRARIES} - ${WINSDK_LIBRARY_DIR}/Crypt32.lib - ${WINSDK_LIBRARY_DIR}/WS2_32.Lib - ${WINSDK_LIBRARY_DIR}/IPHlpApi.Lib) - ENDIF() - - # Core - SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::Core) - - # pcre is needed since Qt 5.5 - IF(UNIX) - SET(PCRE_LIB "${QT_LIBRARY_DIR}/libqtpcre.a") - IF(NOT EXISTS ${PCRE_LIB}) - SET(PCRE_LIB "${QT_LIBRARY_DIR}/libqtpcre2.a") - ENDIF() - ELSEIF(WIN32) - SET(PCRE_LIB "${QT_LIBRARY_DIR}/qtpcre.lib") - ENDIF() - IF(EXISTS ${PCRE_LIB}) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${PCRE_LIB}) - ENDIF() - - IF(APPLE) - FIND_LIBRARY(PCRE_LIBRARY pcre16 pcre) - - FIND_LIBRARY(SECURITY_FRAMEWORK Security) - - SET(QT_LIBRARIES ${QT_LIBRARIES} - ${PCRE_LIBRARY} - ${FOUNDATION_FRAMEWORK} - ${CARBON_FRAMEWORK} - ${SECURITY_FRAMEWORK}) - ELSEIF(UNIX) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${ZLIB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} -ldl -lrt) - ENDIF() - ELSE() - SET(QT_LIBRARIES Qt5::Widgets Qt5::Network Qt5::Xml Qt5::Gui Qt5::OpenGL Qt5::Core) - ENDIF() - ELSE() - MESSAGE(WARNING "Unable to find Qt 5") - ENDIF() + FIND_QT5() ENDIF() IF(WITH_QT) diff --git a/code/CMakeModules/FindHelpers.cmake b/code/CMakeModules/FindHelpers.cmake new file mode 100644 index 000000000..d9aa3e75c --- /dev/null +++ b/code/CMakeModules/FindHelpers.cmake @@ -0,0 +1,943 @@ +MACRO(CONVERT_NUMBER_VERSION _VERSION_NUMBER _BASE _OUT) + SET(${_OUT}) + SET(_NUMBER ${_VERSION_NUMBER}) + WHILE(_NUMBER GREATER 0) + MATH(EXPR _TEMP "${_NUMBER} % ${_BASE}") + LIST(APPEND ${_OUT} ${_TEMP}) + MATH(EXPR _NUMBER "${_NUMBER} / ${_BASE}") + ENDWHILE() +ENDMACRO(CONVERT_NUMBER_VERSION) + +FUNCTION(JOIN VALUES GLUE OUTPUT) + STRING(REGEX REPLACE "([^\\]|^);" "\\1${GLUE}" _TMP_STR "${VALUES}") + STRING(REGEX REPLACE "[\\](.)" "\\1" _TMP_STR "${_TMP_STR}") #fixes escaping + SET(${OUTPUT} "${_TMP_STR}" PARENT_SCOPE) +ENDFUNCTION() + +MACRO(PARSE_VERSION_OTHER FILENAME) + IF(EXISTS ${FILENAME}) + SET(_FILTER_ARRAY ${ARGN}) + JOIN("${_FILTER_ARRAY}" "|" _FILTER_REGEX) + FILE(STRINGS ${FILENAME} _FILE REGEX "(${_FILTER_REGEX})[: \t=\(\)\"]+([0-9.]+)") + + IF(_FILE) + FOREACH(_LINE ${_FILE}) + FOREACH(_VAR ${_FILTER_ARRAY}) + IF("${${_VAR}}" STREQUAL "") + STRING(REGEX REPLACE "^.*${_VAR}[: \t=\(\)\"]+([0-9.]+).*$" "\\1" ${_VAR} "${_LINE}") + IF(${_VAR} STREQUAL "${_LINE}") + SET(${_VAR}) + ENDIF() + IF(NOT ${_VAR} AND NOT STREQUAL "0") + SET(${_VAR} 0) + ENDIF() + ENDIF() + ENDFOREACH() + ENDFOREACH() + ENDIF() + ENDIF() +ENDMACRO() + +MACRO(FIND_PACKAGE_HELPER NAME INCLUDE) + # Looks for a directory containing NAME. + # + # NAME is the name of the library, lowercase and uppercase can be mixed + # It should be EXACTLY (same case) the same part as XXXX in FindXXXX.cmake + # + # INCLUDE is the file to check for includes + # + # Following parameters are optional variables and must be prefixed by: + # + # RELEASE is the list of libraries to check in release mode + # DEBUG is the list of libraries to check in debug mode + # SUFFIXES is the PATH_SUFFIXES to check for include file + # QUIET don't display anything + # VERBOSE display more details if not found + # REQUIRED throw an error if not found + # DIR is the base directory where to look for + # + # The first match will be used in the specified order and next matches will be ignored + # + # The following values are defined + # NAME_INCLUDE_DIR - where to find NAME + # NAME_LIBRARIES - link against these to use NAME + # NAME_FOUND - True if NAME is available. + + SET(_PARAMS ${ARGN}) + + SET(_RELEASE_LIBRARIES) + SET(_DEBUG_LIBRARIES) + SET(_SUFFIXES) + SET(_BASE_DIRECTORIES) + + SET(_IS_RELEASE OFF) + SET(_IS_DEBUG OFF) + SET(_IS_SUFFIXES OFF) + SET(_IS_VERBOSE OFF) + SET(_IS_DIR OFF) + + IF(_PARAMS) + FOREACH(_PARAM ${_PARAMS}) + IF(_PARAM STREQUAL "RELEASE") + SET(_IS_RELEASE ON) + SET(_IS_DEBUG OFF) + SET(_IS_SUFFIXES OFF) + SET(_IS_DIR OFF) + ELSEIF(_PARAM STREQUAL "DEBUG") + SET(_IS_RELEASE OFF) + SET(_IS_DEBUG ON) + SET(_IS_SUFFIXES OFF) + SET(_IS_DIR OFF) + ELSEIF(_PARAM STREQUAL "SUFFIXES") + SET(_IS_RELEASE OFF) + SET(_IS_DEBUG OFF) + SET(_IS_DIR OFF) + SET(_IS_SUFFIXES ON) + ELSEIF(_PARAM STREQUAL "QUIET") + SET(_IS_RELEASE OFF) + SET(_IS_DEBUG OFF) + SET(_IS_SUFFIXES OFF) + SET(_IS_DIR OFF) + SET(${NAME}_FIND_QUIETLY ON) + ELSEIF(_PARAM STREQUAL "VERBOSE") + SET(_IS_RELEASE OFF) + SET(_IS_DEBUG OFF) + SET(_IS_SUFFIXES OFF) + SET(_IS_DIR OFF) + SET(_IS_VERBOSE ON) + ELSEIF(_PARAM STREQUAL "REQUIRED") + SET(_IS_RELEASE OFF) + SET(_IS_DEBUG OFF) + SET(_IS_SUFFIXES OFF) + SET(_IS_DIR OFF) + SET(${NAME}_FIND_REQUIRED ON) + ELSEIF(_PARAM STREQUAL "DIR") + SET(_IS_RELEASE OFF) + SET(_IS_DEBUG OFF) + SET(_IS_SUFFIXES OFF) + SET(_IS_DIR ON) + ELSE() + IF(_IS_RELEASE) + LIST(APPEND _RELEASE_LIBRARIES ${_PARAM}) + ELSEIF(_IS_DEBUG) + LIST(APPEND _DEBUG_LIBRARIES ${_PARAM}) + ELSEIF(_IS_SUFFIXES) + LIST(APPEND _SUFFIXES ${_PARAM}) + ELSEIF(_IS_DIR) + LIST(APPEND _BASE_DIRECTORIES ${_PARAM}) + ELSE() + MESSAGE(STATUS "parameter ${_PARAM} with no prefix") + ENDIF() + ENDIF() + ENDFOREACH() + ENDIF() + + # Fixes names if invalid characters are found + IF("${NAME}" MATCHES "^[a-zA-Z0-9]+$") + SET(_NAME_FIXED ${NAME}) + ELSE() + # if invalid characters are detected, replace them by valid ones + STRING(REPLACE "+" "p" _NAME_FIXED ${NAME}) + ENDIF() + + # Create uppercase and lowercase versions of NAME + STRING(TOUPPER ${NAME} _UPNAME) + STRING(TOLOWER ${NAME} _LOWNAME) + + STRING(TOUPPER ${_NAME_FIXED} _UPNAME_FIXED) + STRING(TOLOWER ${_NAME_FIXED} _LOWNAME_FIXED) + + SET(_SUFFIXES ${_SUFFIXES} ${_LOWNAME} ${_LOWNAME_FIXED} ${NAME}) + +# Don't use pkg-config +# IF(NOT WIN32 AND NOT IOS) +# FIND_PACKAGE(PkgConfig QUIET) +# SET(_MODULES ${_LOWNAME} ${_RELEASE_LIBRARIES}) +# LIST(REMOVE_DUPLICATES _MODULES) +# IF(PKG_CONFIG_EXECUTABLE) +# PKG_SEARCH_MODULE(PKG_${_NAME_FIXED} QUIET ${_MODULES}) +# ENDIF() +# ENDIF() + + SET(_INCLUDE_PATHS) + SET(_LIBRARY_PATHS) + + # Check for root directories passed to CMake with -DXXX_DIR=... + IF(DEFINED ${_UPNAME_FIXED}_DIR) + SET(_TMP ${${_UPNAME_FIXED}_DIR}) + GET_FILENAME_COMPONENT(_TMP ${_TMP} ABSOLUTE) + LIST(APPEND _INCLUDE_PATHS ${_TMP}/include ${_TMP}) + LIST(APPEND _LIBRARY_PATHS ${_TMP}/lib${LIB_SUFFIX}) + + IF(_IS_VERBOSE) + MESSAGE(STATUS "Using ${_UPNAME_FIXED}_DIR as root directory ${_TMP}") + ENDIF() + ENDIF() + + IF(DEFINED ${_UPNAME}_DIR) + SET(_TMP ${${_UPNAME}_DIR}) + LIST(APPEND _INCLUDE_PATHS ${_TMP}/include ${_TMP}) + LIST(APPEND _LIBRARY_PATHS ${_TMP}/lib${LIB_SUFFIX}) + + IF(_IS_VERBOSE) + MESSAGE(STATUS "Using ${_UPNAME_FIXED}_DIR as root directory ${_TMP}") + ENDIF() + ENDIF() + + IF(_BASE_DIRECTORIES) + FOREACH(_DIR ${_BASE_DIRECTORIES}) + IF(_DIR) + LIST(APPEND _INCLUDE_PATHS ${_DIR}/include ${_DIR}) + LIST(APPEND _LIBRARY_PATHS ${_DIR}/lib${LIB_SUFFIX}) + + IF(_IS_VERBOSE) + MESSAGE(STATUS "Using ${_DIR} as root directory") + ENDIF() + ENDIF() + ENDFOREACH() + ENDIF() + + IF(UNIX) + # Append UNIX standard include paths + SET(_UNIX_INCLUDE_PATHS) + + # Append multiarch include paths + IF(CMAKE_LIBRARY_ARCHITECTURE) + LIST(APPEND _UNIX_INCLUDE_PATHS + /usr/local/include/${CMAKE_LIBRARY_ARCHITECTURE} + /usr/include/${CMAKE_LIBRARY_ARCHITECTURE}) + ENDIF() + + LIST(APPEND _UNIX_INCLUDE_PATHS + /usr/local/include + /usr/include + /sw/include + /opt/local/include + /opt/csw/include + /opt/include) + ENDIF() + + IF(_IS_VERBOSE) + MESSAGE(STATUS "Searching header ${INCLUDE} in: ${_INCLUDE_PATHS} with suffixes ${_SUFFIXES}") + ENDIF() + + # Search for include directory + FIND_PATH(${_UPNAME_FIXED}_INCLUDE_DIR + NAMES ${INCLUDE} + HINTS + ${PKG_${_NAME_FIXED}_INCLUDE_DIRS} + ${_INCLUDE_PATHS} + $ENV{${_UPNAME}_DIR}/include + $ENV{${_UPNAME_FIXED}_DIR}/include + $ENV{${_UPNAME}_DIR} + $ENV{${_UPNAME_FIXED}_DIR} + PATHS + ${_UNIX_INCLUDE_PATHS} + PATH_SUFFIXES + ${_SUFFIXES} + DOC "Include path for ${NAME}" + ) + + IF(_IS_VERBOSE) + IF(${_UPNAME_FIXED}_INCLUDE_DIR) + MESSAGE(STATUS "${INCLUDE} found in ${${_UPNAME_FIXED}_INCLUDE_DIR}") + ELSE() + MESSAGE(STATUS "${INCLUDE} not found") + ENDIF() + ENDIF() + + # Append environment variables XXX_DIR + LIST(APPEND _LIBRARY_PATHS + $ENV{${_UPNAME}_DIR}/lib${LIB_SUFFIX} + $ENV{${_UPNAME_FIXED}_DIR}/lib${LIB_SUFFIX}) + + IF(UNIX) + SET(_UNIX_LIBRARY_PATHS) + + # Append multiarch libraries paths + IF(CMAKE_LIBRARY_ARCHITECTURE) + LIST(APPEND _UNIX_LIBRARY_PATHS + /usr/local/lib/${CMAKE_LIBRARY_ARCHITECTURE} + /lib/${CMAKE_LIBRARY_ARCHITECTURE} + /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}) + ENDIF() + + # Append UNIX standard libraries paths + LIST(APPEND _UNIX_LIBRARY_PATHS + /usr/local/lib + /usr/lib + /lib + /usr/local/X11R6/lib + /usr/X11R6/lib + /sw/lib + /opt/local/lib + /opt/csw/lib + /opt/lib + /usr/freeware/lib${LIB_SUFFIX}) + ENDIF() + + LIST(APPEND _RELEASE_LIBRARIES ${_LOWNAME} ${_LOWNAME_FIXED} ${NAME} ${_NAME_FIXED}) + LIST(APPEND _DEBUG_LIBRARIES ${_LOWNAME}d ${_LOWNAME_FIXED}d ${NAME}d ${_NAME_FIXED}d) + + # Under Windows, some libs may need the lib prefix + IF(WIN32) + SET(_LIBS ${_RELEASE_LIBRARIES}) + FOREACH(_LIB ${_LIBS}) + LIST(APPEND _RELEASE_LIBRARIES lib${_LIB}) + ENDFOREACH() + + SET(_LIBS ${_DEBUG_LIBRARIES}) + FOREACH(_LIB ${_LIBS}) + LIST(APPEND _DEBUG_LIBRARIES lib${_LIB}) + ENDFOREACH() + ENDIF() + + LIST(REMOVE_DUPLICATES _RELEASE_LIBRARIES) + LIST(REMOVE_DUPLICATES _DEBUG_LIBRARIES) + + # Search for release library + FIND_LIBRARY(${_UPNAME_FIXED}_LIBRARY_RELEASE + NAMES + ${_RELEASE_LIBRARIES} + HINTS ${PKG_${_NAME_FIXED}_LIBRARY_DIRS} + PATHS + ${_LIBRARY_PATHS} + ${_UNIX_LIBRARY_PATHS} + NO_CMAKE_SYSTEM_PATH + ) + + IF(_IS_VERBOSE) + IF(${_UPNAME_FIXED}_LIBRARY_RELEASE) + MESSAGE(STATUS "${NAME} release library found: ${${_UPNAME_FIXED}_LIBRARY_RELEASE}") + ELSE() + MESSAGE(STATUS "${NAME} release library not found in ${_LIBRARY_PATHS};${_UNIX_LIBRARY_PATHS}") + ENDIF() + ENDIF() + + # Search for debug library + FIND_LIBRARY(${_UPNAME_FIXED}_LIBRARY_DEBUG + NAMES + ${_DEBUG_LIBRARIES} + HINTS ${PKG_${_NAME_FIXED}_LIBRARY_DIRS} + PATHS + ${_LIBRARY_PATHS} + ${_UNIX_LIBRARY_PATHS} + NO_CMAKE_SYSTEM_PATH + ) + + IF(_IS_VERBOSE) + IF(${_UPNAME_FIXED}_LIBRARY_DEBUG) + MESSAGE(STATUS "${NAME} debug library found: ${${_UPNAME_FIXED}_LIBRARY_DEBUG}") + ELSE() + MESSAGE(STATUS "${NAME} debug library not found") + ENDIF() + ENDIF() + + SET(${_UPNAME_FIXED}_FOUND OFF) + + IF(${_UPNAME_FIXED}_INCLUDE_DIR) + # Set also _INCLUDE_DIRS + SET(${_UPNAME_FIXED}_INCLUDE_DIRS ${${_UPNAME_FIXED}_INCLUDE_DIR}) + ENDIF() + + # Library has been found if at least only one library and include are found + IF(${_UPNAME_FIXED}_LIBRARY_RELEASE AND ${_UPNAME_FIXED}_LIBRARY_DEBUG) + # Release and debug libraries found + SET(${_UPNAME_FIXED}_FOUND ON) + SET(${_UPNAME_FIXED}_LIBRARIES optimized ${${_UPNAME_FIXED}_LIBRARY_RELEASE} debug ${${_UPNAME_FIXED}_LIBRARY_DEBUG}) + SET(${_UPNAME_FIXED}_LIBRARY ${${_UPNAME_FIXED}_LIBRARY_RELEASE}) + ELSEIF(${_UPNAME_FIXED}_LIBRARY_RELEASE) + # Release library found + SET(${_UPNAME_FIXED}_FOUND ON) + SET(${_UPNAME_FIXED}_LIBRARIES ${${_UPNAME_FIXED}_LIBRARY_RELEASE}) + SET(${_UPNAME_FIXED}_LIBRARY ${${_UPNAME_FIXED}_LIBRARY_RELEASE}) + ELSEIF(${_UPNAME_FIXED}_LIBRARY_DEBUG) + # Debug library found + SET(${_UPNAME_FIXED}_FOUND ON) + SET(${_UPNAME_FIXED}_LIBRARIES ${${_UPNAME_FIXED}_LIBRARY_DEBUG}) + SET(${_UPNAME_FIXED}_LIBRARY ${${_UPNAME_FIXED}_LIBRARY_DEBUG}) + ENDIF() + + IF(${_UPNAME_FIXED}_FOUND) + IF(NOT ${NAME}_FIND_QUIETLY) + MESSAGE(STATUS "Found ${NAME}: ${${_UPNAME_FIXED}_LIBRARIES}") + ENDIF() + ELSE() + IF(${NAME}_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Error: Unable to find ${NAME}!") + ENDIF() + IF(NOT ${NAME}_FIND_QUIETLY) + MESSAGE(STATUS "Warning: Unable to find ${NAME}!") + ENDIF() + ENDIF() + + MARK_AS_ADVANCED(${_UPNAME_FIXED}_LIBRARY_RELEASE ${_UPNAME_FIXED}_LIBRARY_DEBUG) +ENDMACRO() + +MACRO(MESSAGE_VERSION_PACKAGE_HELPER NAME VERSION) + MESSAGE(STATUS "Found ${NAME} ${VERSION}: ${ARGN}") +ENDMACRO() + +MACRO(FIND_LIBRARY_HELPER NAME) + # Looks for libraries. + # + # NAME is the name of the library, lowercase and uppercase can be mixed + # + # Following parameters are optional variables and must be prefixed by: + # + # RELEASE is the list of libraries to check in release mode + # DEBUG is the list of libraries to check in debug mode + # VERBOSE display more details if not found + # REQUIRED throw an error if not found + # DIR is the base directory where to look for + # + # The first match will be used in the specified order and next matches will be ignored + # + # The following values are defined + # NAME_LIBRARIES - link against these to use NAME + + SET(_PARAMS ${ARGN}) + + SET(_RELEASE_LIBRARIES) + SET(_DEBUG_LIBRARIES) + SET(_BASE_DIRECTORIES) + + SET(_IS_RELEASE OFF) + SET(_IS_DEBUG OFF) + SET(_IS_VERBOSE OFF) + SET(_IS_DIR OFF) + + IF(_PARAMS) + FOREACH(_PARAM ${_PARAMS}) + IF(_PARAM STREQUAL "RELEASE") + SET(_IS_RELEASE ON) + SET(_IS_DEBUG OFF) + SET(_IS_DIR OFF) + ELSEIF(_PARAM STREQUAL "DEBUG") + SET(_IS_RELEASE OFF) + SET(_IS_DEBUG ON) + SET(_IS_DIR OFF) + ELSEIF(_PARAM STREQUAL "VERBOSE") + SET(_IS_RELEASE OFF) + SET(_IS_DEBUG OFF) + SET(_IS_DIR OFF) + SET(_IS_VERBOSE ON) + ELSEIF(_PARAM STREQUAL "REQUIRED") + SET(_IS_RELEASE OFF) + SET(_IS_DEBUG OFF) + SET(_IS_DIR OFF) + SET(${NAME}_FIND_REQUIRED ON) + ELSEIF(_PARAM STREQUAL "DIR") + SET(_IS_RELEASE OFF) + SET(_IS_DEBUG OFF) + SET(_IS_DIR ON) + ELSE() + IF(_IS_RELEASE) + LIST(APPEND _RELEASE_LIBRARIES ${_PARAM}) + ELSEIF(_IS_DEBUG) + LIST(APPEND _DEBUG_LIBRARIES ${_PARAM}) + ELSEIF(_IS_DIR) + LIST(APPEND _BASE_DIRECTORIES ${_PARAM}) + ELSE() + MESSAGE(STATUS "parameter ${_PARAM} with no prefix") + ENDIF() + ENDIF() + ENDFOREACH() + ENDIF() + + # Fixes names if invalid characters are found + IF("${NAME}" MATCHES "^[a-zA-Z0-9]+$") + SET(_NAME_FIXED ${NAME}) + ELSE() + # if invalid characters are detected, replace them by valid ones + STRING(REPLACE "+" "p" _NAME_FIXED ${NAME}) + ENDIF() + + # Create uppercase and lowercase versions of NAME + STRING(TOUPPER ${NAME} _UPNAME) + STRING(TOLOWER ${NAME} _LOWNAME) + + STRING(TOUPPER ${_NAME_FIXED} _UPNAME_FIXED) + STRING(TOLOWER ${_NAME_FIXED} _LOWNAME_FIXED) + + SET(_LIBRARY_PATHS) + + # Check for root directories passed to CMake with -DXXX_DIR=... + IF(DEFINED ${_UPNAME_FIXED}_DIR) + SET(_TMP ${${_UPNAME_FIXED}_DIR}) + GET_FILENAME_COMPONENT(_TMP ${_TMP} ABSOLUTE) + LIST(APPEND _LIBRARY_PATHS ${_TMP}/lib${LIB_SUFFIX}) + + IF(_IS_VERBOSE) + MESSAGE(STATUS "Using ${_UPNAME_FIXED}_DIR as root directory ${_TMP}") + ENDIF() + ENDIF() + + IF(DEFINED ${_UPNAME}_DIR) + SET(_TMP ${${_UPNAME}_DIR}) + LIST(APPEND _LIBRARY_PATHS ${_TMP}/lib${LIB_SUFFIX}) + + IF(_IS_VERBOSE) + MESSAGE(STATUS "Using ${_UPNAME_FIXED}_DIR as root directory ${_TMP}") + ENDIF() + ENDIF() + + IF(_BASE_DIRECTORIES) + FOREACH(_DIR ${_BASE_DIRECTORIES}) + IF(_DIR) + LIST(APPEND _LIBRARY_PATHS ${_DIR}/lib${LIB_SUFFIX}) + + IF(_IS_VERBOSE) + MESSAGE(STATUS "Using ${_DIR} as root directory") + ENDIF() + ENDIF() + ENDFOREACH() + ENDIF() + + # Append environment variables XXX_DIR + LIST(APPEND _LIBRARY_PATHS + $ENV{${_UPNAME}_DIR}/lib${LIB_SUFFIX} + $ENV{${_UPNAME_FIXED}_DIR}/lib${LIB_SUFFIX}) + + IF(UNIX) + SET(_UNIX_LIBRARY_PATHS) + + # Append multiarch libraries paths + IF(CMAKE_LIBRARY_ARCHITECTURE) + LIST(APPEND _UNIX_LIBRARY_PATHS + /usr/local/lib/${CMAKE_LIBRARY_ARCHITECTURE} + /lib/${CMAKE_LIBRARY_ARCHITECTURE} + /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}) + ENDIF() + + # Append UNIX standard libraries paths + LIST(APPEND _UNIX_LIBRARY_PATHS + /usr/local/lib + /usr/lib + /lib + /usr/local/X11R6/lib + /usr/X11R6/lib + /sw/lib + /opt/local/lib + /opt/csw/lib + /opt/lib + /usr/freeware/lib${LIB_SUFFIX}) + ENDIF() + + LIST(APPEND _RELEASE_LIBRARIES ${_LOWNAME} ${_LOWNAME_FIXED} ${NAME} ${_NAME_FIXED}) + LIST(APPEND _DEBUG_LIBRARIES ${_LOWNAME}d ${_LOWNAME_FIXED}d ${NAME}d ${_NAME_FIXED}d) + + # Under Windows, some libs may need the lib prefix + IF(WIN32) + SET(_LIBS ${_RELEASE_LIBRARIES}) + FOREACH(_LIB ${_LIBS}) + LIST(APPEND _RELEASE_LIBRARIES lib${_LIB}) + ENDFOREACH() + + SET(_LIBS ${_DEBUG_LIBRARIES}) + FOREACH(_LIB ${_LIBS}) + LIST(APPEND _DEBUG_LIBRARIES lib${_LIB}) + ENDFOREACH() + ENDIF() + + LIST(REMOVE_DUPLICATES _RELEASE_LIBRARIES) + LIST(REMOVE_DUPLICATES _DEBUG_LIBRARIES) + + # Search for release library + FIND_LIBRARY(${_UPNAME_FIXED}_LIBRARY_RELEASE + NAMES + ${_RELEASE_LIBRARIES} + HINTS ${PKG_${_NAME_FIXED}_LIBRARY_DIRS} + PATHS + ${_LIBRARY_PATHS} + ${_UNIX_LIBRARY_PATHS} + NO_CMAKE_SYSTEM_PATH + ) + + IF(_IS_VERBOSE) + IF(${_UPNAME_FIXED}_LIBRARY_RELEASE) + MESSAGE(STATUS "${NAME} release library found: ${${_UPNAME_FIXED}_LIBRARY_RELEASE}") + ELSE() + MESSAGE(STATUS "${NAME} release library not found in ${_LIBRARY_PATHS};${_UNIX_LIBRARY_PATHS}") + ENDIF() + ENDIF() + + # Search for debug library + FIND_LIBRARY(${_UPNAME_FIXED}_LIBRARY_DEBUG + NAMES + ${_DEBUG_LIBRARIES} + HINTS ${PKG_${_NAME_FIXED}_LIBRARY_DIRS} + PATHS + ${_LIBRARY_PATHS} + ${_UNIX_LIBRARY_PATHS} + NO_CMAKE_SYSTEM_PATH + ) + + IF(_IS_VERBOSE) + IF(${_UPNAME_FIXED}_LIBRARY_DEBUG) + MESSAGE(STATUS "${NAME} debug library found: ${${_UPNAME_FIXED}_LIBRARY_DEBUG}") + ELSE() + MESSAGE(STATUS "${NAME} debug library not found") + ENDIF() + ENDIF() + + # Library has been found if at least only one library and include are found + IF(${_UPNAME_FIXED}_LIBRARY_RELEASE AND ${_UPNAME_FIXED}_LIBRARY_DEBUG) + # Release and debug libraries found + SET(${_UPNAME_FIXED}_LIBRARIES optimized ${${_UPNAME_FIXED}_LIBRARY_RELEASE} debug ${${_UPNAME_FIXED}_LIBRARY_DEBUG}) + SET(${_UPNAME_FIXED}_LIBRARY ${${_UPNAME_FIXED}_LIBRARY_RELEASE}) + ELSEIF(${_UPNAME_FIXED}_LIBRARY_RELEASE) + # Release library found + SET(${_UPNAME_FIXED}_LIBRARIES ${${_UPNAME_FIXED}_LIBRARY_RELEASE}) + SET(${_UPNAME_FIXED}_LIBRARY ${${_UPNAME_FIXED}_LIBRARY_RELEASE}) + ELSEIF(${_UPNAME_FIXED}_LIBRARY_DEBUG) + # Debug library found + SET(${_UPNAME_FIXED}_LIBRARIES ${${_UPNAME_FIXED}_LIBRARY_DEBUG}) + SET(${_UPNAME_FIXED}_LIBRARY ${${_UPNAME_FIXED}_LIBRARY_DEBUG}) + ENDIF() + + MARK_AS_ADVANCED(${_UPNAME_FIXED}_LIBRARY_RELEASE ${_UPNAME_FIXED}_LIBRARY_DEBUG) +ENDMACRO() + +MACRO(FIND_LIBCURL) + IF(NOT CURL_FOUND) + FIND_PACKAGE(CURL REQUIRED) + + IF(WIN32 OR CURL_LIBRARY MATCHES "\\.a" OR WITH_STATIC_CURL) + SET(CURL_STATIC ON) + ELSE() + SET(CURL_STATIC OFF) + ENDIF() + + IF(CURL_STATIC) + SET(CURL_DEFINITIONS -DCURL_STATICLIB) + + IF(UNIX) + # CURL can depend on libidn + FIND_LIBRARY(IDN_LIBRARY idn) + IF(IDN_LIBRARY) + LIST(APPEND CURL_LIBRARIES ${IDN_LIBRARY}) + ENDIF() + + # CURL Macports version can depend on libidn, libintl and libiconv too + IF(APPLE) + FIND_LIBRARY(INTL_LIBRARY intl) + IF(INTL_LIBRARY) + LIST(APPEND CURL_LIBRARIES ${INTL_LIBRARY}) + ENDIF() + ELSE() + # Only used by libcurl under Linux + FIND_PACKAGE(OpenSSL REQUIRED) + + #IF(WIN32) + # SET(OPENSSL_LIBRARIES ${OPENSSL_LIBRARIES} Crypt32.lib) + #ENDIF() + + # Only Linux version of libcurl depends on OpenSSL + LIST(APPEND CURL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR}) + LIST(APPEND CURL_LIBRARIES ${OPENSSL_LIBRARIES}) + ENDIF() + ENDIF() + ENDIF() + ENDIF() +ENDMACRO() + +MACRO(FIND_LIBXML2) + IF(NOT LIBXML2_FOUND) + FIND_PACKAGE(LibXml2 REQUIRED) + + IF(WIN32 OR WITH_STATIC_LIBXML2) + LIST(APPEND LIBXML2_DEFINITIONS -DLIBXML_STATIC) + ENDIF() + + IF(WITH_LIBXML2_ICONV) + FIND_PACKAGE(Iconv REQUIRED) +# LIST(APPEND CURL_INCLUDE_DIRS ${ICONV_INCLUDE_DIR}) + LIST(APPEND LIBXML2_LIBRARIES ${ICONV_LIBRARIES}) + ENDIF() + + IF(WITH_STATIC) + # libxml2 could need winsock2 library + IF(WIN32) + FIND_LIBRARY(WINSOCK2_LIB ws2_32) + + IF(WINSOCK2_LIB) + LIST(APPEND LIBXML2_LIBRARIES ${WINSOCK2_LIB}) + ENDIF() + + FIND_LIBRARY(CRYPT32_LIB Crypt32) + + IF(CRYPT32_LIB) + LIST(APPEND LIBXML2_LIBRARIES ${CRYPT32_LIB}) + ENDIF() + ELSE() + # under Linux and OS X, recent libxml2 versions are linked against liblzma + FIND_PACKAGE(LibLZMA) + + IF(LIBLZMA_LIBRARIES) + LIST(APPEND LIBXML2_LIBRARIES ${LIBLZMA_LIBRARIES}) + ENDIF() + ENDIF() + ENDIF() + ENDIF() +ENDMACRO() + +MACRO(ADD_QT_LIBRARY _NAME) + IF(WIN32) + SET(_PREFIX "Qt5") + SET(_EXT "lib") + ELSE() + SET(_PREFIX "libQt5") + SET(_EXT "a") + ENDIF() + SET(_LIB "${QT_LIBRARY_DIR}/${_PREFIX}${_NAME}.${_EXT}") + IF(EXISTS ${_LIB}) + SET(QT_LIBRARIES ${QT_LIBRARIES} optimized ${_LIB}) + ENDIF() + SET(_LIB "${QT_LIBRARY_DIR}/${_PREFIX}${_NAME}d.${_EXT}") + IF(EXISTS ${_LIB}) + SET(QT_LIBRARIES ${QT_LIBRARIES} debug ${_LIB}) + ENDIF() +ENDMACRO() + +MACRO(ADD_QT_PLUGIN _TYPE _NAME) + IF(WIN32) + SET(_PREFIX "") + SET(_EXT "lib") + ELSE() + SET(_PREFIX "lib") + SET(_EXT "a") + ENDIF() + SET(_LIB "${QT_PLUGINS_DIR}/${_TYPE}/${_PREFIX}${_NAME}.${_EXT}") + IF(EXISTS ${_LIB}) + SET(QT_LIBRARIES ${QT_LIBRARIES} optimized ${_LIB}) + ENDIF() + SET(_LIB "${QT_PLUGINS_DIR}/${_TYPE}/${_PREFIX}${_NAME}d.${_EXT}") + IF(EXISTS ${_LIB}) + SET(QT_LIBRARIES ${QT_LIBRARIES} debug ${_LIB}) + ENDIF() +ENDMACRO() + +MACRO(ADD_QT_SYSTEM_LIBRARY _NAME) + # Save default suffixes + SET(_OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + + # Define specific suffixes + SET(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX}) + + # Find the library with specified suffixes + FIND_LIBRARY(${_NAME}_LIBRARY NAMES ${_NAME}) + + # Restore default suffixes + SET(CMAKE_FIND_LIBRARY_SUFFIXES ${_OLD_SUFFIXES}) + + IF(${_NAME}_LIBRARY) + MESSAGE(STATUS "Found ${${_NAME}_LIBRARY} ${_NAME}") + + LIST(APPEND QT_LIBRARIES ${${_NAME}_LIBRARY}) + ELSE() + MESSAGE(STATUS "Didn't find ${_NAME}") + ENDIF() +ENDMACRO() + +MACRO(FIND_QT5) + CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11 FATAL_ERROR) + + SET(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QTDIR} $ENV{QTDIR}) + + FIND_PACKAGE(Qt5Core QUIET) + + IF(Qt5Core_FOUND) + # Check if we are using Qt static or shared libraries + GET_TARGET_PROPERTY(_FILE Qt5::Core IMPORTED_LOCATION_RELEASE) + + SET(QT_VERSION "${Qt5Core_VERSION_STRING}") + SET(_VERSION "${QT_VERSION}") + + IF(_FILE MATCHES "\\.(lib|a)$") + SET(QT_STATIC ON) + SET(_VERSION "${_VERSION} static version") + ELSE() + SET(QT_STATIC OFF) + SET(_VERSION "${_VERSION} shared version") + ENDIF() + + MESSAGE(STATUS "Found Qt ${_VERSION}") + + # These variables are not defined with Qt5 CMake modules + SET(QT_BINARY_DIR "${_qt5Core_install_prefix}/bin") + SET(QT_LIBRARY_DIR "${_qt5Core_install_prefix}/lib") + SET(QT_PLUGINS_DIR "${_qt5Core_install_prefix}/plugins") + SET(QT_TRANSLATIONS_DIR "${_qt5Core_install_prefix}/translations") + + # Fix wrong include directories with Qt 5 under Mac OS X + INCLUDE_DIRECTORIES("${_qt5Core_install_prefix}/include") + + FIND_PACKAGE(Qt5Gui) + FIND_PACKAGE(Qt5Widgets) + FIND_PACKAGE(Qt5OpenGL) + FIND_PACKAGE(Qt5Xml) + FIND_PACKAGE(Qt5LinguistTools) + FIND_PACKAGE(Qt5Network) + + IF(QT_STATIC) + FIND_PACKAGE(PNG REQUIRED) + FIND_PACKAGE(Jpeg REQUIRED) + + ADD_DEFINITIONS(-DQT_STATICPLUGIN) + + SET(QT_LIBRARIES Qt5::Widgets) + + # Gui + SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::Gui Qt5::OpenGL) + + ADD_QT_LIBRARY(PrintSupport) + + IF(WIN32) + SET(QT_LIBRARIES ${QT_LIBRARIES} + ${WINSDK_LIBRARY_DIR}/Imm32.lib + ${WINSDK_LIBRARY_DIR}/OpenGL32.lib + ${WINSDK_LIBRARY_DIR}/WinMM.Lib) + ADD_QT_PLUGIN(platforms qwindows) + ADD_QT_LIBRARY(PlatformSupport) + ELSEIF(APPLE) + # Cups needs .dylib + SET(OLD_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + SET(CMAKE_FIND_LIBRARY_SUFFIXES .dylib) + FIND_LIBRARY(CUPS_LIBRARY cups) + SET(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_CMAKE_FIND_LIBRARY_SUFFIXES}) + + FIND_LIBRARY(IOKIT_FRAMEWORK IOKit) + FIND_LIBRARY(COCOA_FRAMEWORK Cocoa) + FIND_LIBRARY(SYSTEMCONFIGURATION_FRAMEWORK SystemConfiguration) + FIND_LIBRARY(OPENGL_FRAMEWORK NAMES OpenGL) + + SET(QT_LIBRARIES ${QT_LIBRARIES} + ${CUPS_LIBRARY} + ${COCOA_FRAMEWORK} + ${SYSTEMCONFIGURATION_FRAMEWORK} + ${IOKIT_FRAMEWORK} + ${OPENGL_FRAMEWORK}) + + ADD_QT_PLUGIN(printsupport cocoaprintersupport) + ADD_QT_PLUGIN(platforms qcocoa) + ADD_QT_LIBRARY(PlatformSupport) + ELSE() + # order is very important there + ADD_QT_PLUGIN(platforms qxcb) + ADD_QT_PLUGIN(xcbglintegrations qxcb-glx-integration) + + ADD_QT_LIBRARY(XcbQpa) + ADD_QT_LIBRARY(GlxSupport) + ADD_QT_LIBRARY(ServiceSupport) + ADD_QT_LIBRARY(EdidSupport) + ADD_QT_LIBRARY(FontDatabaseSupport) + ADD_QT_LIBRARY(ThemeSupport) + ADD_QT_LIBRARY(EventDispatcherSupport) + ADD_QT_LIBRARY(PlatformSupport) + + ADD_QT_LIBRARY(DBus) + + IF(EXISTS "${QT_LIBRARY_DIR}/libxcb-static.a") + SET(QT_LIBRARIES ${QT_LIBRARIES} "${QT_LIBRARY_DIR}/libxcb-static.a") + ENDIF() + + # always link these in dynamic, API never changes + ADD_QT_SYSTEM_LIBRARY(X11) + ADD_QT_SYSTEM_LIBRARY(Xmu) + ADD_QT_SYSTEM_LIBRARY(X11-xcb) + ADD_QT_SYSTEM_LIBRARY(Xi) + ADD_QT_SYSTEM_LIBRARY(SM) + ADD_QT_SYSTEM_LIBRARY(ICE) + ADD_QT_SYSTEM_LIBRARY(xcb) + ADD_QT_SYSTEM_LIBRARY(GL) + ADD_QT_SYSTEM_LIBRARY(xcb-glx) + ADD_QT_SYSTEM_LIBRARY(fontconfig) + ADD_QT_SYSTEM_LIBRARY(Xrender) + ENDIF() + + ADD_QT_PLUGIN(imageformats qgif) + ADD_QT_PLUGIN(imageformats qicns) + ADD_QT_PLUGIN(imageformats qico) + ADD_QT_PLUGIN(imageformats qjpeg) + + # harfbuzz is needed since Qt 5.3 + IF(UNIX) + SET(HB_LIB "${QT_LIBRARY_DIR}/libqtharfbuzzng.a") + IF(NOT EXISTS ${HB_LIB}) + SET(HB_LIB "${QT_LIBRARY_DIR}/libqtharfbuzz.a") + ENDIF() + ELSEIF(WIN32) + SET(HB_LIB "${QT_LIBRARY_DIR}/qtharfbuzzng.lib") + ENDIF() + IF(EXISTS ${HB_LIB}) + SET(QT_LIBRARIES ${QT_LIBRARIES} ${HB_LIB}) + ENDIF() + + # freetype is needed since Qt 5.5 + FIND_PACKAGE(Freetype) + + IF(FREETYPE_FOUND) + SET(QT_LIBRARIES ${QT_LIBRARIES} ${FREETYPE_LIBRARIES}) + ELSE() + IF(UNIX) + SET(FREETYPE_LIB "${QT_LIBRARY_DIR}/libqtfreetype.a") + ELSEIF(WIN32) + SET(FREETYPE_LIB "${QT_LIBRARY_DIR}/qtfreetype.lib") + ENDIF() + IF(EXISTS ${FREETYPE_LIB}) + SET(QT_LIBRARIES ${QT_LIBRARIES} ${FREETYPE_LIB}) + ENDIF() + ENDIF() + + ADD_QT_PLUGIN(accessible qtaccessiblewidgets) + + SET(QT_LIBRARIES ${QT_LIBRARIES} ${PNG_LIBRARIES} ${JPEG_LIBRARY}) + + # Network + SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::Network Qt5::Xml) + SET(QT_LIBRARIES ${QT_LIBRARIES} ${ZLIB_LIBRARIES}) + + IF(WIN32) + SET(QT_LIBRARIES ${QT_LIBRARIES} + ${WINSDK_LIBRARY_DIR}/Crypt32.lib + ${WINSDK_LIBRARY_DIR}/WS2_32.Lib + ${WINSDK_LIBRARY_DIR}/IPHlpApi.Lib) + ENDIF() + + # Core + SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::Core) + + # pcre is needed since Qt 5.5 + IF(UNIX) + SET(PCRE_LIB "${QT_LIBRARY_DIR}/libqtpcre.a") + IF(NOT EXISTS ${PCRE_LIB}) + SET(PCRE_LIB "${QT_LIBRARY_DIR}/libqtpcre2.a") + ENDIF() + ELSEIF(WIN32) + SET(PCRE_LIB "${QT_LIBRARY_DIR}/qtpcre.lib") + ENDIF() + IF(EXISTS ${PCRE_LIB}) + SET(QT_LIBRARIES ${QT_LIBRARIES} ${PCRE_LIB}) + ENDIF() + + IF(APPLE) + FIND_LIBRARY(PCRE_LIBRARY pcre16 pcre) + + FIND_LIBRARY(SECURITY_FRAMEWORK Security) + + SET(QT_LIBRARIES ${QT_LIBRARIES} + ${PCRE_LIBRARY} + ${FOUNDATION_FRAMEWORK} + ${CARBON_FRAMEWORK} + ${SECURITY_FRAMEWORK}) + ELSEIF(UNIX) + SET(QT_LIBRARIES ${QT_LIBRARIES} ${ZLIB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} -ldl -lrt) + ENDIF() + ELSE() + SET(QT_LIBRARIES Qt5::Widgets Qt5::Network Qt5::Xml Qt5::Gui Qt5::OpenGL Qt5::Core) + ENDIF() + ELSE() + MESSAGE(WARNING "Unable to find Qt 5") + ENDIF() +ENDMACRO() diff --git a/code/CMakeModules/FindNeL.cmake b/code/CMakeModules/FindNeL.cmake new file mode 100644 index 000000000..e75163cce --- /dev/null +++ b/code/CMakeModules/FindNeL.cmake @@ -0,0 +1,398 @@ +# NEL_DIR can be specified as root directory + +# Returned variables +# NELDRIVER_XXX_BINARY_DEBUG +# NELDRIVER_XXX_BINARY_RELEASE +# NELDRIVER_XXX_LIBRARY_DEBUG +# NELDRIVER_XXX_LIBRARY_RELEASE +# NELDRIVER_XXX_FOUND +# NEL_DEFINITIONS +# NEL_INCLUDE_DIR +# NEL_INCLUDE_DIRS +# NEL_LIBRARIES +# NELXXX_FOUND +# NELXXX_LIBRARIES + + +INCLUDE(FindHelpers) + +# Init all variables we'll set +SET(NEL_LIBRARIES) +SET(NEL_INCLUDE_DIR) +SET(NEL_INCLUDE_DIRS) +SET(NEL_VERSION) +SET(NEL_STATIC) +SET(NEL_STATIC_DRIVERS) +SET(NEL_VERSION_MAJOR) +SET(NEL_VERSION_MINOR) +SET(NEL_VERSION_PATCH) +SET(NEL_REVISION) +SET(NEL_VERSION) + +SET(NEL_MODULES_FOUND) +SET(NEL_MODULES_AVAILABLE 3d georges gui ligo logic net pacs sound) # cegui pipeline + +SET(NEL_DRIVERS_FOUND) +SET(NEL_DRIVERS_AVAILABLE opengl opengles direct3d dsound fmod openal xaudio2) + +SET(NELMISC_FIND_REQUIRED ${NeL_FIND_REQUIRED}) + +# Force search of NELMISC +FIND_PACKAGE_HELPER(nelmisc nel/misc/types_nl.h RELEASE nelmisc_r nelmisc DEBUG nelmisc_d DIR ${NEL_DIR} VERBOSE QUIET) + +IF(NELMISC_FOUND) + # define NEL_DIR if not specified + IF(NOT NEL_DIR) + GET_FILENAME_COMPONENT(NEL_DIR ${NELMISC_INCLUDE_DIR}/.. ABSOLUTE) + ENDIF() + + # Aliases for include directory + SET(NEL_INCLUDE_DIR ${NELMISC_INCLUDE_DIR}) + SET(NEL_INCLUDE_DIRS ${NEL_INCLUDE_DIR}) + + MESSAGE(STATUS "Found NeL headers in ${NEL_INCLUDE_DIR}") + + GET_FILENAME_COMPONENT(NEL_LIBRARY_DIR ${NELMISC_LIBRARY} DIRECTORY) + + MESSAGE(STATUS "Found NeL library in ${NEL_LIBRARY_DIR}") + + # TODO: implement static version checks for Windows + + # static libraries + IF(UNIX) + GET_FILENAME_COMPONENT(_LIBEXT ${NELMISC_LIBRARY} EXT) + + IF(_LIBEXT STREQUAL ".a") + SET(NEL_STATIC ON) + MESSAGE(STATUS "NeL is using static libraries") + ENDIF() + ENDIF() + + IF(WIN32) + SET(NELDRIVER_DIRS_TO_CHECK + ${NEL_DIR}/bin${LIB_SUFFIX} + ${NEL_DIR} + ) + ELSE() + SET(NELDRIVER_DIRS_TO_CHECK + /usr/local/lib/${CMAKE_LIBRARY_ARCHITECTURE}/nel + /usr/local/lib/${CMAKE_LIBRARY_ARCHITECTURE} + /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/nel + /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} + /usr/lib/nel + /usr/lib + ) + ENDIF() + + # check for static drivers + FOREACH(_DRIVER ${NEL_DRIVERS_AVAILABLE}) + IF(WIN32) + SET(_DRIVER_RELASE_FILE "nel_drv_${_DRIVER}_win_r") + SET(_DRIVER_DEBUG_FILE "nel_drv_${_DRIVER}_win_d") + SET(_DRIVER_SHARED_EXT dll) + SET(_DRIVER_STATIC_EXT lib) + ELSE() + SET(_DRIVER_RELEASE_FILE "nel_drv_${_DRIVER}") + SET(_DRIVER_DEBUG_FILE) + SET(_DRIVER_SHARED_EXT so) + SET(_DRIVER_STATIC_EXT a) + ENDIF() + + STRING(TOUPPER ${_DRIVER} _UPDRIVER) + + FOREACH(_DIR ${NELDRIVER_DIRS_TO_CHECK}) + SET(_FOUND OFF) + + IF(_DRIVER_RELASE_FILE) + SET(_FILE "${_DIR}/${_DRIVER_RELASE_FILE}.${_DRIVER_SHARED_EXT}") + IF(EXISTS ${_FILE}) + SET(NELDRIVER_${_UPDRIVER}_BINARY_RELEASE ${_FILE}) + + MESSAGE(STATUS "Found NeL release shared driver ${_DRIVER}: ${_FILE}") + + SET(NEL_STATIC_DRIVERS OFF) + + IF(NOT NEL_DRIVER_DIR) + SET(NEL_DRIVER_DIR ${_DIR}) + ENDIF() + ENDIF() + + SET(_FILE "${_DIR}/${_DRIVER_RELASE_FILE}.${_DRIVER_STATIC_EXT}") + IF(EXISTS ${_FILE}) + SET(NELDRIVER_${_UPDRIVER}_LIBRARY_RELEASE ${_FILE}) + + MESSAGE(STATUS "Found NeL release static driver ${_DRIVER}: ${_FILE}") + + SET(NEL_STATIC_DRIVERS ON) + + IF(NOT NEL_DRIVER_DIR) + SET(NEL_DRIVER_DIR ${_DIR}) + ENDIF() + ENDIF() + ENDIF() + + IF(_DRIVER_DEBUG_FILE) + SET(_FILE "${_DIR}/${_DRIVER_RELASE_FILE}.${_DRIVER_SHARED_EXT}") + IF(EXISTS ${_FILE}) + SET(NELDRIVER_${_UPDRIVER}_BINARY_DEBUG ${_FILE}) + + MESSAGE(STATUS "Found NeL debug shared driver ${_DRIVER}: ${_FILE}") + + SET(NEL_STATIC_DRIVERS OFF) + + IF(NOT NEL_DRIVER_DIR) + SET(NEL_DRIVER_DIR ${_DIR}) + ENDIF() + ENDIF() + + SET(_FILE "${_DIR}/${_DRIVER_RELASE_FILE}.${_DRIVER_STATIC_EXT}") + IF(EXISTS ${_FILE}) + SET(NELDRIVER_${_UPDRIVER}_LIBRARY_DEBUG ${_FILE}) + + MESSAGE(STATUS "Found NeL debug static driver ${_DRIVER}: ${_FILE}") + + SET(NEL_STATIC_DRIVERS ON) + + IF(NOT NEL_DRIVER_DIR) + SET(NEL_DRIVER_DIR ${_DIR}) + ENDIF() + ENDIF() + + IF(_FOUND) + SET(NELDRIVER_${_UPDRIVER}_FOUND ON) + LIST(APPEND NEL_DRIVERS_FOUND ${_DRIVER}) + ENDIF() + ENDIF() + ENDFOREACH() + ENDFOREACH() + + MESSAGE(STATUS "Found NeL driver in ${NEL_DRIVER_DIR}") + + PARSE_VERSION_OTHER(${NEL_INCLUDE_DIR}/nel/misc/version_nl.h NL_VERSION_MAJOR NL_VERSION_MINOR NL_VERSION_PATCH NL_REVISION) + + SET(NEL_VERSION_MAJOR ${NL_VERSION_MAJOR}) + SET(NEL_VERSION_MINOR ${NL_VERSION_MINOR}) + SET(NEL_VERSION_PATCH ${NL_VERSION_PATCH}) + SET(NEL_REVISION ${NL_REVISION}) + + IF(NOT NEL_VERSION) + IF(NEL_VERSION_MAJOR OR NEL_VERSION_MINOR} OR NEL_VERSION_PATCH) + SET(NEL_VERSION "${NEL_VERSION_MAJOR}.${NEL_VERSION_MINOR}.${NEL_VERSION_PATCH}") + ELSE() + SET(NEL_VERSION "0.5.0") + ENDIF() + + IF(NEL_REVISION) + SET(NEL_VERSION "${NEL_VERSION}.${NEL_REVISION}") + ENDIF() + ENDIF() + + FIND_PACKAGE(PNG REQUIRED) + IF(PNG_FOUND) + LIST(APPEND NELMISC_LIBRARIES ${PNG_LIBRARIES}) + ENDIF() + + FIND_PACKAGE(Jpeg REQUIRED) + IF(JPEG_FOUND) + LIST(APPEND NELMISC_LIBRARIES ${JPEG_LIBRARY}) + ENDIF() + + FIND_PACKAGE(GIF) + + IF(GIF_FOUND) + LIST(APPEND NELMISC_LIBRARIES ${GIF_LIBRARY}) + ENDIF() + + FIND_LIBXML2() + + IF(LIBXML2_FOUND) + LIST(APPEND NELMISC_LIBRARIES ${LIBXML2_LIBRARIES}) + ENDIF() + + LIST(REMOVE_ITEM NeL_FIND_COMPONENTS misc) + + LIST(APPEND NEL_MODULES_FOUND misc) + LIST(APPEND NEL_LIBRARIES ${NELMISC_LIBRARIES}) +ENDIF() + +IF(NOT NeL_FIND_COMPONENTS) + SET(NeL_FIND_COMPONENTS ${NEL_MODULES_AVAILABLE}) + + # We can skip not installed modules + SET(NeL_FIND_REQUIRED OFF) +ENDIF() + +FOREACH(COMPONENT ${NeL_FIND_COMPONENTS}) + SET(_NAME NeL${COMPONENT}) + STRING(TOUPPER ${_NAME} _UPNAME) + + # module is required + SET(${_NAME}_FIND_REQUIRED ${NeL_FIND_REQUIRED}) + + IF(COMPONENT STREQUAL "3d") + SET(HEADER_FILE shape.h) +# ELSEIF(COMPONENT STREQUAL "cegui") +# SET(HEADER_FILE shape.h) + ELSEIF(COMPONENT STREQUAL "georges") + SET(HEADER_FILE form.h) + ELSEIF(COMPONENT STREQUAL "gui") + SET(HEADER_FILE reflect.h) + ELSEIF(COMPONENT STREQUAL "ligo") + SET(HEADER_FILE primitive.h) + ELSEIF(COMPONENT STREQUAL "logic") + SET(HEADER_FILE logic_state.h) + ELSEIF(COMPONENT STREQUAL "net") + SET(HEADER_FILE sock.h) + ELSEIF(COMPONENT STREQUAL "pacs") + SET(HEADER_FILE primitive_block.h) +# ELSEIF(COMPONENT STREQUAL "pipeline") +# SET(HEADER_FILE shape.h) + ELSEIF(COMPONENT STREQUAL "sound") + SET(HEADER_FILE shape.h) + ELSE() + SET(HEADER_FILE) + ENDIF() + + # display if a component has a wrong name + IF(NOT HEADER_FILE) + MESSAGE(STATUS "NeL module ${COMPONENT} not supported, ignoring it...") + CONTINUE() + ENDIF() + + FIND_PACKAGE_HELPER(${_NAME} nel/${COMPONENT}/${HEADER_FILE} + RELEASE nel${COMPONENT}_r nel${COMPONENT} + DEBUG nel${COMPONENT}_d + QUIET) + + IF(${_UPNAME}_FOUND) + LIST(APPEND NEL_MODULES_FOUND ${COMPONENT}) + + IF(COMPONENT STREQUAL "3d") + IF(NEL_STATIC) + # 3rd party dependencies + FIND_PACKAGE(Freetype REQUIRED) + IF(FREETYPE_FOUND) + LIST(APPEND ${_UPNAME}_LIBRARIES ${FREETYPE_LIBRARIES}) + ENDIF() + + # Append static 3D drivers + IF(NEL_STATIC_DRIVERS) + # Direct3D driver (only under Windows) + IF(WIN32) + IF(NELDRIVER_DIRECT3D_LIBRARY_DEBUG) + LIST(APPEND ${_UPNAME}_LIBRARIES debug ${NELDRIVER_DIRECT3D_LIBRARY_DEBUG}) + ENDIF() + + IF(NELDRIVER_DIRECT3D_LIBRARY_RELEASE) + LIST(APPEND ${_UPNAME}_LIBRARIES optimized ${NELDRIVER_DIRECT3D_LIBRARY_RELEASE}) + ENDIF() + ENDIF() + + # OpenGL driver + IF(NELDRIVER_OPENGL_LIBRARY_DEBUG) + LIST(APPEND ${_UPNAME}_LIBRARIES debug ${NELDRIVER_OPENGL_LIBRARY_DEBUG}) + ENDIF() + + IF(NELDRIVER_OPENGL_LIBRARY_RELEASE) + LIST(APPEND ${_UPNAME}_LIBRARIES optimized ${NELDRIVER_OPENGL_LIBRARY_RELEASE}) + ENDIF() + ENDIF() + ENDIF() + ELSEIF(COMPONENT STREQUAL "gui") + FIND_PACKAGE(Luabind REQUIRED) + + LIST(APPEND ${_UPNAME}_LIBRARIES ${LUABIND_LIBRARIES}) + + FIND_LIBCURL() + + IF(CURL_FOUND) + LIST(APPEND ${_UPNAME}_LIBRARIES ${CURL_LIBRARIES}) + LIST(APPEND ${_UPNAME}_DEFINITIONS ${CURL_DEFINITIONS}) + ENDIF() + + # TODO: remove complately OpenSSL requirement on Windows + + # Only used by libcurl under Linux + FIND_PACKAGE(OpenSSL REQUIRED) + + IF(WIN32) + LIST(APPEND OPENSSL_LIBRARIES Crypt32.lib) + ENDIF() + + # Only Linux version of libcurl depends on OpenSSL + LIST(APPEND CURL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR}) + LIST(APPEND CURL_LIBRARIES ${OPENSSL_LIBRARIES}) + + LIST(APPEND ${_UPNAME}_LIBRARIES ${LUABIND_LIBRARIES} ${CURL_LIBRARIES}) + LIST(APPEND NEL_DEFINITIONS ${${_UPNAME}_DEFINITIONS}) + ELSEIF(COMPONENT STREQUAL "sound") + FIND_PACKAGE(Ogg REQUIRED) + + IF(OGG_FOUND) + LIST(APPEND ${_UPNAME}_LIBRARIES ${OGG_LIBRARY}) + ENDIF() + + FIND_PACKAGE(Vorbis REQUIRED) + + IF(VORBIS_FOUND) + LIST(APPEND ${_UPNAME}_LIBRARIES ${VORBIS_LIBRARY} ${VORBISFILE_LIBRARY}) + ENDIF() + + IF(NEL_STATIC) + # Link to snd_lowlevel + FIND_LIBRARY_HELPER(nelsnd_lowlevel RELEASE nelsnd_lowlevel_r DEBUG nelsnd_lowlevel_d DIR ${NEL_DIR} REQUIRED) + + IF(NELSND_LOWLEVEL_LIBRARIES) + MESSAGE(STATUS "Found NeL sound lowlevel ${NELSND_LOWLEVEL_LIBRARIES}") + + LIST(APPEND NELSOUND_LIBRARIES ${NELSND_LOWLEVEL_LIBRARIES}) + + IF(NEL_STATIC_DRIVERS) + # DirectSound, XAudio2 and FMod drivers (only under Windows) + IF(WIN32) + # DirectSound + IF(NELDRIVER_DIRECTSOUND_LIBRARY_DEBUG) + LIST(APPEND NELSOUND_LIBRARIES debug ${NELDRIVER_DIRECTSOUND_LIBRARY_DEBUG}) + ENDIF() + + IF(NELDRIVER_DIRECTSOUND_LIBRARY_RELEASE) + LIST(APPEND NELSOUND_LIBRARIES optimized ${NELDRIVER_DIRECTSOUND_LIBRARY_RELEASE}) + ENDIF() + + # FMod + IF(NELDRIVER_FMOD_LIBRARY_DEBUG) + LIST(APPEND NELSOUND_LIBRARIES debug ${NELDRIVER_FMOD_LIBRARY_DEBUG}) + ENDIF() + + IF(NELDRIVER_FMOD_LIBRARY_RELEASE) + LIST(APPEND NELSOUND_LIBRARIES optimized ${NELDRIVER_FMOD_LIBRARY_RELEASE}) + ENDIF() + + # XAudio2 + IF(NELDRIVER_XAUDIO2_LIBRARY_DEBUG) + LIST(APPEND NELSOUND_LIBRARIES debug ${NELDRIVER_XAUDIO2_LIBRARY_DEBUG}) + ENDIF() + + IF(NELDRIVER_XAUDIO2_LIBRARY_RELEASE) + LIST(APPEND NELSOUND_LIBRARIES optimized ${NELDRIVER_XAUDIO2_LIBRARY_RELEASE}) + ENDIF() + ENDIF() + + # OpenAL driver + IF(NELDRIVER_OPENAL_LIBRARY_DEBUG) + LIST(APPEND NELSOUND_LIBRARIES debug ${NELDRIVER_OPENAL_LIBRARY_DEBUG}) + ENDIF() + + IF(NELDRIVER_OPENAL_LIBRARY_RELEASE) + LIST(APPEND NELSOUND_LIBRARIES optimized ${NELDRIVER_OPENAL_LIBRARY_RELEASE}) + ENDIF() + ENDIF() + ENDIF() + ENDIF() + ENDIF() + + LIST(APPEND NEL_LIBRARIES ${${_UPNAME}_LIBRARIES}) + ENDIF() +ENDFOREACH() + +MESSAGE_VERSION_PACKAGE_HELPER(NeL ${NEL_VERSION} ${NEL_MODULES_FOUND}) diff --git a/code/CMakeModules/FindRyzomGameShare.cmake b/code/CMakeModules/FindRyzomGameShare.cmake new file mode 100644 index 000000000..56eb94569 --- /dev/null +++ b/code/CMakeModules/FindRyzomGameShare.cmake @@ -0,0 +1,10 @@ +INCLUDE(FindHelpers) + +FIND_PACKAGE_HELPER(RyzomGameShare game_share/continent.h RELEASE ryzom_gameshare_r ryzom_gameshare DEBUG ryzom_gameshare_d DIR ${NEL_DIR} ${RYZOM_DIR} SUFFIXES ryzom) + +IF(RYZOMGAMESHARE_FOUND) + SET(RYZOM_GAMESHARE_LIBRARIES ${RYZOMGAMESHARE_LIBRARIES}) + SET(RYZOM_GAMESHARE_FOUND ${RYZOMGAMESHARE_FOUND}) + SET(RYZOM_GAMESHARE_INCLUDE_DIR ${RYZOMGAMESHARE_INCLUDE_DIR}) + SET(RYZOM_GAMESHARE_INCLUDE_DIRS ${RYZOMGAMESHARE_INCLUDE_DIRS}) +ENDIF() From 4df0fd37f3dd93be1d8bc18d7edc595d503ebf03 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 28 Jul 2018 11:45:49 +0200 Subject: [PATCH 065/303] Changed: Define and use LIB_SUFFIX --HG-- branch : develop --- code/CMakeLists.txt | 13 +++++++++++++ code/CMakeModules/nel.cmake | 24 +++++++++++++++++------- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 87367c98e..022c34659 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -249,6 +249,19 @@ IF(WITH_NEL) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/nel/include) ADD_SUBDIRECTORY(nel) + + # Aliases for targets + SET(NELMISC_LIBRARIES nelmisc) + SET(NELNET_LIBRARIES nelnet) + SET(NELLIGO_LIBRARIES nelligo) + SET(NELGEORGES_LIBRARIES nelgeorges) + SET(NEL3D_LIBRARIES nel3d) + SET(NELGUI_LIBRARIES nelgui) + SET(NELSOUND_LIBRARIES nelsound) +ELSE() +# FIND_PACKAGE(NeL COMPONENTS 3d misc pacs sound nimp REQUIRED) + FIND_PACKAGE(NeL REQUIRED) + INCLUDE_DIRECTORIES(${NEL_INCLUDE_DIRS}) ENDIF() IF(WITH_RYZOM) diff --git a/code/CMakeModules/nel.cmake b/code/CMakeModules/nel.cmake index 258e777aa..453b1fe1a 100644 --- a/code/CMakeModules/nel.cmake +++ b/code/CMakeModules/nel.cmake @@ -1041,6 +1041,12 @@ MACRO(NL_MAKE_ABSOLUTE_PREFIX NAME_RELATIVE NAME_ABSOLUTE) ENDMACRO(NL_MAKE_ABSOLUTE_PREFIX) MACRO(NL_SETUP_PREFIX_PATHS) + IF(TARGET_X64 AND WIN32) + SET(LIB_SUFFIX "64") + ELSE() + SET(LIB_SUFFIX "") + ENDIF() + ## Allow override of install_prefix/etc path. IF(NOT NL_ETC_PREFIX) IF(WITH_UNIX_STRUCTURE) @@ -1064,7 +1070,7 @@ MACRO(NL_SETUP_PREFIX_PATHS) ## Allow override of install_prefix/sbin path. IF(NOT NL_SBIN_PREFIX) IF(WITH_UNIX_STRUCTURE) - SET(NL_SBIN_PREFIX "sbin" CACHE PATH "Installation path for admin tools and services.") + SET(NL_SBIN_PREFIX "sbin${LIB_SUFFIX}" CACHE PATH "Installation path for admin tools and services.") ELSE() SET(NL_SBIN_PREFIX "." CACHE PATH "Installation path for admin tools and services.") ENDIF() @@ -1074,7 +1080,7 @@ MACRO(NL_SETUP_PREFIX_PATHS) ## Allow override of install_prefix/bin path. IF(NOT NL_BIN_PREFIX) IF(WITH_UNIX_STRUCTURE) - SET(NL_BIN_PREFIX "bin" CACHE PATH "Installation path for tools and applications.") + SET(NL_BIN_PREFIX "bin${LIB_SUFFIX}" CACHE PATH "Installation path for tools and applications.") ELSE() SET(NL_BIN_PREFIX "." CACHE PATH "Installation path for tools and applications.") ENDIF() @@ -1086,7 +1092,7 @@ MACRO(NL_SETUP_PREFIX_PATHS) IF(LIBRARY_ARCHITECTURE) SET(NL_LIB_PREFIX "lib/${LIBRARY_ARCHITECTURE}" CACHE PATH "Installation path for libraries.") ELSE() - SET(NL_LIB_PREFIX "lib" CACHE PATH "Installation path for libraries.") + SET(NL_LIB_PREFIX "lib${LIB_SUFFIX}" CACHE PATH "Installation path for libraries.") ENDIF() ENDIF() NL_MAKE_ABSOLUTE_PREFIX(NL_LIB_PREFIX NL_LIB_ABSOLUTE_PREFIX) @@ -1097,7 +1103,11 @@ MACRO(NL_SETUP_PREFIX_PATHS) IF(LIBRARY_ARCHITECTURE) SET(NL_DRIVER_PREFIX "lib/${LIBRARY_ARCHITECTURE}/nel" CACHE PATH "Installation path for drivers.") ELSE() - SET(NL_DRIVER_PREFIX "lib/nel" CACHE PATH "Installation path for drivers.") + IF(WIN32) + SET(NL_DRIVER_PREFIX "bin${LIB_SUFFIX}" CACHE PATH "Installation path for drivers.") + ELSE() + SET(NL_DRIVER_PREFIX "lib${LIB_SUFFIX}/nel" CACHE PATH "Installation path for drivers.") + ENDIF() ENDIF() ELSE() SET(NL_DRIVER_PREFIX "." CACHE PATH "Installation path for drivers.") @@ -1130,7 +1140,7 @@ MACRO(RYZOM_SETUP_PREFIX_PATHS) ## Allow override of install_prefix/sbin path. IF(NOT RYZOM_SBIN_PREFIX) IF(WITH_UNIX_STRUCTURE) - SET(RYZOM_SBIN_PREFIX "sbin" CACHE PATH "Installation path for admin tools and services.") + SET(RYZOM_SBIN_PREFIX "sbin${LIB_SUFFIX}" CACHE PATH "Installation path for admin tools and services.") ELSE() SET(RYZOM_SBIN_PREFIX "." CACHE PATH "Installation path for admin tools and services.") ENDIF() @@ -1140,7 +1150,7 @@ MACRO(RYZOM_SETUP_PREFIX_PATHS) ## Allow override of install_prefix/bin path. IF(NOT RYZOM_BIN_PREFIX) IF(WITH_UNIX_STRUCTURE) - SET(RYZOM_BIN_PREFIX "bin" CACHE PATH "Installation path for tools.") + SET(RYZOM_BIN_PREFIX "bin${LIB_SUFFIX}" CACHE PATH "Installation path for tools.") ELSE() SET(RYZOM_BIN_PREFIX "." CACHE PATH "Installation path for tools and applications.") ENDIF() @@ -1152,7 +1162,7 @@ MACRO(RYZOM_SETUP_PREFIX_PATHS) IF(LIBRARY_ARCHITECTURE) SET(RYZOM_LIB_PREFIX "lib/${LIBRARY_ARCHITECTURE}" CACHE PATH "Installation path for libraries.") ELSE() - SET(RYZOM_LIB_PREFIX "lib" CACHE PATH "Installation path for libraries.") + SET(RYZOM_LIB_PREFIX "lib${LIB_SUFFIX}" CACHE PATH "Installation path for libraries.") ENDIF() ENDIF() NL_MAKE_ABSOLUTE_PREFIX(RYZOM_LIB_PREFIX RYZOM_LIB_ABSOLUTE_PREFIX) From 7a85eef10bfec9dfe0040c3ab9e1e55736024929 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 28 Jul 2018 11:46:34 +0200 Subject: [PATCH 066/303] Changed: Minor changes --HG-- branch : develop --- code/CMakeModules/nel.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/CMakeModules/nel.cmake b/code/CMakeModules/nel.cmake index 453b1fe1a..abe41ca1f 100644 --- a/code/CMakeModules/nel.cmake +++ b/code/CMakeModules/nel.cmake @@ -382,7 +382,6 @@ MACRO(CONVERT_VERSION_NUMBER _VERSION_NUMBER _BASE) ENDMACRO() MACRO(NL_SETUP_BUILD) - #----------------------------------------------------------------------------- # Setup the buildmode variables. # @@ -1238,4 +1237,4 @@ MACRO(SETUP_EXTERNAL) FIND_PACKAGE(MSVC REQUIRED) FIND_PACKAGE(WindowsSDK REQUIRED) ENDIF() -ENDMACRO(SETUP_EXTERNAL) +ENDMACRO() From d4fbb641207bf24d7d4d41d827e442bf83c46be1 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 28 Jul 2018 11:52:16 +0200 Subject: [PATCH 067/303] Added: Steam CMake module --HG-- branch : develop --- code/CMakeModules/FindSteam.cmake | 74 +++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 code/CMakeModules/FindSteam.cmake diff --git a/code/CMakeModules/FindSteam.cmake b/code/CMakeModules/FindSteam.cmake new file mode 100644 index 000000000..5657312eb --- /dev/null +++ b/code/CMakeModules/FindSteam.cmake @@ -0,0 +1,74 @@ +# - Locate Steam API +# This module defines +# STEAM_LIBRARY, the library to link against +# STEAM_FOUND, if false, do not try to link to STEAM +# STEA%_INCLUDE_DIR, where to find headers. + +IF(STEAM_LIBRARY AND STEAM_INCLUDE_DIR) + # in cache already + SET(Steam_FIND_QUIETLY TRUE) +ENDIF() + + +FIND_PATH(STEAM_INCLUDE_DIR + steam_api.h + PATH_SUFFIXES steam + PATHS + $ENV{STEAM_DIR}/public +) + +IF(WIN32) + IF(TARGET_X64) + SET(STEAM_LIBNAME steam_api64) + SET(STEAM_RUNTIMENAME steam_api64.dll) + SET(STEAM_PATHNAME redistributable_bin/win64) + ELSE() + SET(STEAM_LIBNAME steam_api) + SET(STEAM_RUNTIMENAME steam_api.dll) + SET(STEAM_PATHNAME redistributable_bin) + ENDIF() +ELSEIF(APPLE) + # universal binary + SET(STEAM_LIBNAME steam_api) + SET(STEAM_RUNTIMENAME libsteam_api.dylib) + SET(STEAM_PATHNAME redistributable_bin/osx32) +ELSE() + SET(STEAM_LIBNAME steam_api) + SET(STEAM_RUNTIMENAME libsteam_api.so) + IF(TARGET_X64) + SET(STEAM_PATHNAME redistributable_bin/linux64) + ELSE() + SET(STEAM_PATHNAME redistributable_bin/linux32) + ENDIF() +ENDIF() + +FIND_LIBRARY(STEAM_LIBRARY + NAMES ${STEAM_LIBNAME} + HINTS + $ENV{STEAM_DIR}/${STEAM_PATHNAME} +) + +FIND_FILE(STEAM_RUNTIME + NAMES ${STEAM_RUNTIMENAME} + HINTS + $ENV{STEAM_DIR}/${STEAM_PATHNAME} + PATHS + ${EXTERNAL_BINARY_PATH} + ${CMAKE_LIBRARY_PATH} + /usr/local/lib + /usr/lib +) + +# Don't need to check STEAM_LIBRARY because we're dynamically loading Steam DLL +IF(STEAM_INCLUDE_DIR) + SET(STEAM_FOUND ON) + SET(STEAM_LIBRARIES ${STEAM_LIBRARY}) + SET(STEAM_INCLUDE_DIRS ${STEAM_INCLUDE_DIR}) + IF(NOT Steam_FIND_QUIETLY) + MESSAGE(STATUS "Found Steam: ${STEAM_INCLUDE_DIR} and ${STEAM_RUNTIME}") + ENDIF() +ELSE() + IF(NOT Steam_FIND_QUIETLY) + MESSAGE(STATUS "Warning: Unable to find Steam!") + ENDIF() +ENDIF() From 1000e29a963a7f182deaf0f30f3b3b2c299571b7 Mon Sep 17 00:00:00 2001 From: kervala Date: Tue, 31 Jul 2018 18:36:36 +0200 Subject: [PATCH 068/303] Fixed: Compilation with VC++ 2013 --HG-- branch : develop --- code/nel/tools/pacs/build_rbank/build_surf.cpp | 2 +- code/ryzom/server/src/ags_test/command_event_manager.h | 2 +- code/ryzom/server/src/ags_test/move_manager.h | 2 +- .../server/src/entity_view_service/entity_view_service.h | 2 +- code/ryzom/tools/pd_parser/parser.cpp | 4 ++-- code/ryzom/tools/pd_parser/parser_rules.h | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code/nel/tools/pacs/build_rbank/build_surf.cpp b/code/nel/tools/pacs/build_rbank/build_surf.cpp index 7e873f15f..465f5f94f 100644 --- a/code/nel/tools/pacs/build_rbank/build_surf.cpp +++ b/code/nel/tools/pacs/build_rbank/build_surf.cpp @@ -671,7 +671,7 @@ bool NLPACS::CComputableSurface::checkConsistency() CComputableSurfaceBorder& border = (*BorderKeeper)[BorderIds[i]]; for (j=0; j+1(border.Vertices[j], border.Vertices[j+1])); + edges.push_back(std::make_pair(border.Vertices[j], border.Vertices[j+1])); } for (i=0; i+1 res = _Map.insert(std::make_pair(var, value)); + std::pair res = _Map.insert(std::make_pair(var, value)); if (!res.second) (*(res.first)).second = value; return (*(res.first)).second; diff --git a/code/ryzom/server/src/ags_test/move_manager.h b/code/ryzom/server/src/ags_test/move_manager.h index 9987b0169..ab78cecd4 100644 --- a/code/ryzom/server/src/ags_test/move_manager.h +++ b/code/ryzom/server/src/ags_test/move_manager.h @@ -95,7 +95,7 @@ public: { if (PrimZoneMap.find(primZone.getName()) == PrimZoneMap.end()) { - PrimZoneMap.insert(std::make_pair(primZone.getName(), primZone)); + PrimZoneMap.insert(std::make_pair(primZone.getName(), primZone)); nlinfo("Using PrimZone '%s'", primZone.getName().c_str()); } else diff --git a/code/ryzom/server/src/entity_view_service/entity_view_service.h b/code/ryzom/server/src/entity_view_service/entity_view_service.h index 2b7e47ca1..5656d86eb 100644 --- a/code/ryzom/server/src/entity_view_service/entity_view_service.h +++ b/code/ryzom/server/src/entity_view_service/entity_view_service.h @@ -179,7 +179,7 @@ public: { nlinfo("Create entity %s", id.toString().c_str()); - std::pair res = _Entities.insert(std::make_pair(id, CEntity())); + std::pair res = _Entities.insert(std::make_pair(id, CEntity())); TEntityMap::iterator ite = res.first; nlassert(ite != _Entities.end() && res.second); diff --git a/code/ryzom/tools/pd_parser/parser.cpp b/code/ryzom/tools/pd_parser/parser.cpp index e1c564c33..d4ae04508 100644 --- a/code/ryzom/tools/pd_parser/parser.cpp +++ b/code/ryzom/tools/pd_parser/parser.cpp @@ -4512,11 +4512,11 @@ void CDeclarationNode::generateSetContent(CCallContext *context) if (useReference) { FetchId.add(Type+"*\t"+objectVariable+" = static_cast<"+Type+"*>("+pdslibFunc("create")+"(tableIndex));"); - FetchId.add(cppName()+".insert(std::make_pair<"+keyType->getName()+","+Type+"*>("+keyVariable+", "+objectVariable+"));"); + FetchId.add(cppName()+".insert(std::make_pair("+keyVariable+", "+objectVariable+"));"); } else { - FetchId.add(cppName()+".insert(std::make_pair<"+keyType->getName()+","+Type+">("+keyVariable+", "+Type+"()));"); + FetchId.add(cppName()+".insert(std::make_pair("+keyVariable+", "+Type+"()));"); FetchId.add(Type+"*\t"+objectVariable+" = &("+cppName()+"["+keyVariable+"]);"); } FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, "+objectVariable+");"); diff --git a/code/ryzom/tools/pd_parser/parser_rules.h b/code/ryzom/tools/pd_parser/parser_rules.h index 9fbc28899..01d7310e6 100644 --- a/code/ryzom/tools/pd_parser/parser_rules.h +++ b/code/ryzom/tools/pd_parser/parser_rules.h @@ -161,7 +161,7 @@ CParseNode *parse##nodename(CTokenizer &tokenizer) \ PARSE_FAIL \ CTokenizer::CToken t2 = tokenizer.currentToken(); \ tokenizer.next(); \ - main->savein.push_back(std::make_pair(tokenizer.get(t1), tokenizer.get(t2))); \ + main->savein.push_back(std::make_pair(tokenizer.get(t1), tokenizer.get(t2))); \ } /* From f04fd9809c42339bcd83b64c49477df4d20f9ce1 Mon Sep 17 00:00:00 2001 From: kervala Date: Sun, 5 Aug 2018 14:31:53 +0200 Subject: [PATCH 069/303] Fixed: Allow to use custom CA Certificates under all platforms if libcurl compiled with OpenSSL for WebIG and login --HG-- branch : develop --- code/nel/include/nel/gui/curl_certificates.h | 15 +- code/nel/src/gui/curl_certificates.cpp | 219 ++++++++++++++++--- code/nel/src/gui/group_html.cpp | 19 +- code/ryzom/client/src/http_client_curl.cpp | 126 +---------- 4 files changed, 224 insertions(+), 155 deletions(-) diff --git a/code/nel/include/nel/gui/curl_certificates.h b/code/nel/include/nel/gui/curl_certificates.h index 021b13360..dd4e923a0 100644 --- a/code/nel/include/nel/gui/curl_certificates.h +++ b/code/nel/include/nel/gui/curl_certificates.h @@ -17,19 +17,24 @@ #ifndef CL_CURL_CERTIFICATES_HTML_H #define CL_CURL_CERTIFICATES_HTML_H -#include - #include "nel/misc/types_nl.h" +#include + namespace NLGUI { -#if defined(NL_OS_WINDOWS) - class CCurlCertificates { + class CCurlCertificates + { public: + // check if compiled with OpenSSL backend + static void init(CURL *curl); + + // allow to use custom PEM certificates + static void addCertificateFile(const std::string &cert); + // cURL SSL certificate loading static CURLcode sslCtxFunction(CURL *curl, void *sslctx, void *parm); }; -#endif // NL_OS_WINDOWS } // namespace #endif diff --git a/code/nel/src/gui/curl_certificates.cpp b/code/nel/src/gui/curl_certificates.cpp index 6cf34c8b8..a279d35f6 100644 --- a/code/nel/src/gui/curl_certificates.cpp +++ b/code/nel/src/gui/curl_certificates.cpp @@ -21,11 +21,7 @@ #include #include - -#if defined(NL_OS_WINDOWS) -#pragma comment(lib, "crypt32.lib") -#pragma comment(lib, "cryptui.lib") -#endif +#include using namespace std; using namespace NLMISC; @@ -36,36 +32,68 @@ using namespace NLMISC; namespace NLGUI { -#if defined(NL_OS_WINDOWS) - static std::vector x509CertList; - // // x509CertList lifetime manager // - class SX509Certificates { + class SX509Certificates + { public: - SX509Certificates() + std::vector CertList; + std::vector FilesList; + + bool isUsingOpenSSLBackend; + bool isInitialized; + + SX509Certificates():isUsingOpenSSLBackend(false), isInitialized(false) { - curl_version_info_data *data; - data = curl_version_info(CURLVERSION_NOW); - if (!(data && data->features & CURL_VERSION_SSPI)) - { - addCertificatesFrom("CA"); - addCertificatesFrom("AuthRoot"); - addCertificatesFrom("ROOT"); - } } ~SX509Certificates() { - for (uint i = 0; i < x509CertList.size(); ++i) + for (uint i = 0; i < CertList.size(); ++i) { - X509_free(x509CertList[i]); + X509_free(CertList[i]); } - x509CertList.clear(); + CertList.clear(); } + void init(CURL *curl) + { + if (isInitialized) return; + + // get information on CURL + curl_version_info_data *data = curl_version_info(CURLVERSION_NOW); + + // get more information on CURL session + curl_tlssessioninfo *sessionInfo; + CURLcode res = curl_easy_getinfo(curl, CURLINFO_TLS_SSL_PTR, &sessionInfo); + + // only use OpenSSL callback if not using Windows SSPI and using OpenSSL backend + if (!res && sessionInfo && sessionInfo->backend == CURLSSLBACKEND_OPENSSL && !(data && data->features & CURL_VERSION_SSPI)) + { +#ifdef NL_OS_WINDOWS + // load native Windows CA Certs + addCertificatesFrom("CA"); + addCertificatesFrom("AuthRoot"); + addCertificatesFrom("ROOT"); + + // we manually loaded native CA Certs, don't need to use custom certificates + isUsingOpenSSLBackend = false; +#else + isUsingOpenSSLBackend = true; +#endif + } + else + { + // if CURL is using SSPI under Windows or SecureChannel under OS X, we'll use native system CA Certs + isUsingOpenSSLBackend = false; + } + + isInitialized = true; + } + +#ifdef NL_OS_WINDOWS void addCertificatesFrom(LPCSTR root) { HCERTSTORE hStore; @@ -80,7 +108,7 @@ namespace NLGUI x509 = d2i_X509(NULL, (const unsigned char **)&pContext->pbCertEncoded, pContext->cbCertEncoded); if (x509) { - x509CertList.push_back(x509); + CertList.push_back(x509); } } CertFreeCertificateContext(pContext); @@ -88,26 +116,157 @@ namespace NLGUI } // this is called before debug context is set and log ends up in log.log - //nlinfo("Loaded %d certificates from '%s' certificate store", List.size(), root); + nlinfo("Loaded %d certificates from '%s' certificate store", (int)CertList.size(), root); + } +#endif + + void addCertificatesFromFile(const std::string &cert) + { + if (!isInitialized) + { + nlwarning("You MUST call NLGUI::CCurlCertificates::init before adding new certificates"); + return; + } + + if (!isUsingOpenSSLBackend) return; + + // this file was already loaded + if (std::find(FilesList.begin(), FilesList.end(), cert) != FilesList.end()) return; + + FilesList.push_back(cert); + + // look for certificate in search paths + string path = CPath::lookup(cert); + nlinfo("Cert path '%s'", path.c_str()); + + if (path.empty()) + { + nlwarning("Unable to find %s", cert.c_str()); + return; + } + + CIFile file; + + // open certificate + if (!file.open(path)) + { + nlwarning("Unable to open %s", path.c_str()); + return; + } + + // load certificate content into memory + std::vector buffer(file.getFileSize()); + file.serialBuffer(&buffer[0], file.getFileSize()); + + // get a BIO + BIO *bio = BIO_new_mem_buf(&buffer[0], file.getFileSize()); + + if (bio) + { + // use it to read the PEM formatted certificate from memory into an X509 + // structure that SSL can use + STACK_OF(X509_INFO) *info = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); + + if (info) + { + // iterate over all entries from the PEM file, add them to the x509_store one by one + for (sint i = 0; i < sk_X509_INFO_num(info); ++i) + { + X509_INFO *itmp = sk_X509_INFO_value(info, i); + + if (itmp && itmp->x509) + { + CertList.push_back(X509_dup(itmp->x509)); + } + } + + // cleanup + sk_X509_INFO_pop_free(info, X509_INFO_free); + } + else + { + nlwarning("Unable to read PEM info"); + } + + // decrease reference counts + BIO_free(bio); + } + else + { + nlwarning("Unable to allocate BIO buffer for certificates"); + } } }; /// this will be initialized on startup and cleared on exit static SX509Certificates x509CertListManager; + // *************************************************************************** + // static + void CCurlCertificates::init(CURL *curl) + { + x509CertListManager.init(curl); + } + + // *************************************************************************** + // static + void CCurlCertificates::addCertificateFile(const std::string &cert) + { + x509CertListManager.addCertificatesFromFile(cert); + } + // *************************************************************************** // static CURLcode CCurlCertificates::sslCtxFunction(CURL *curl, void *sslctx, void *parm) { - if (x509CertList.size() > 0) + CURLcode res = CURLE_OK; + + if (x509CertListManager.CertList.size() > 0) { SSL_CTX *ctx = (SSL_CTX*)sslctx; X509_STORE *x509store = SSL_CTX_get_cert_store(ctx); if (x509store) { - for (uint i = 0; i < x509CertList.size(); ++i) + char errorBuffer[1024]; + + for (uint i = 0, ilen = x509CertListManager.CertList.size(); i < ilen; ++i) { - X509_STORE_add_cert(x509store, x509CertList[i]); + X509_NAME *subject = X509_get_subject_name(x509CertListManager.CertList[i]); + + std::string name; + unsigned char *tmp = NULL; + + // construct a multiline string with name + for (int j = 0, jlen = X509_NAME_entry_count(subject); j < jlen; ++j) + { + X509_NAME_ENTRY *e = X509_NAME_get_entry(subject, j); + ASN1_STRING *d = X509_NAME_ENTRY_get_data(e); + + if (ASN1_STRING_to_UTF8(&tmp, d) > 0) + { + name += NLMISC::toString("%s\n", tmp); + + OPENSSL_free(tmp); + } + } + + // add our certificate to this store + if (X509_STORE_add_cert(x509store, x509CertListManager.CertList[i]) == 0) + { + uint errCode = ERR_get_error(); + + // ignore already in hash table errors + if (ERR_GET_LIB(errCode) != ERR_LIB_X509 || ERR_GET_REASON(errCode) != X509_R_CERT_ALREADY_IN_HASH_TABLE) + { + ERR_error_string_n(errCode, errorBuffer, 1024); + nlwarning("Error adding certificate %s: %s", name.c_str(), errorBuffer); + res = CURLE_SSL_CACERT; + } + } + else + { + nldebug("Added certificate %s", name.c_str()); + } } } else @@ -115,9 +274,13 @@ namespace NLGUI nlwarning("SSL_CTX_get_cert_store returned NULL"); } } - return CURLE_OK; + else + { + res = CURLE_SSL_CACERT; + } + + return res; } -#endif // NL_OS_WINDOWS }// namespace diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index e0ed401ce..fe08b6931 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -398,14 +398,21 @@ namespace NLGUI // https:// if (toLower(download.url.substr(0, 8)) == "https://") { -#if defined(NL_OS_WINDOWS) - curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, &CCurlCertificates::sslCtxFunction); -#else - if (!options.curlCABundle.empty()) + // check if compiled with OpenSSL backend + CCurlCertificates::init(curl); + + // specify custom CA certs + CCurlCertificates::addCertificateFile(options.curlCABundle); + + // would allow to provide the CA in memory instead of using CURLOPT_CAINFO, but needs to include and link OpenSSL + if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, &CCurlCertificates::sslCtxFunction) != CURLE_OK) { - curl_easy_setopt(curl, CURLOPT_CAINFO, options.curlCABundle.c_str()); + nlwarning("Unable to support CURLOPT_SSL_CTX_FUNCTION, curl not compiled with OpenSSL ?"); } -#endif + + // set both CURLOPT_CAINFO and CURLOPT_CAPATH to NULL to be sure we won't use default values (these files can be missing and generate errors) + curl_easy_setopt(curl, CURLOPT_CAINFO, NULL); + curl_easy_setopt(curl, CURLOPT_CAPATH, NULL); } download.data = new CCurlWWWData(curl, download.url); diff --git a/code/ryzom/client/src/http_client_curl.cpp b/code/ryzom/client/src/http_client_curl.cpp index 2fd5bad81..418fc61bd 100644 --- a/code/ryzom/client/src/http_client_curl.cpp +++ b/code/ryzom/client/src/http_client_curl.cpp @@ -19,8 +19,7 @@ #include -#include -#include +#include "nel/gui/curl_certificates.h" using namespace NLMISC; using namespace NLNET; @@ -64,119 +63,7 @@ bool CCurlHttpClient::authenticate(const std::string &user, const std::string &p return true; } -const char *CAFilename = "ssl_ca_cert.pem"; // this is the certificate "Thawte Server CA" - -// *************************************************************************** -static CURLcode sslctx_function(CURL * /* curl */, void *sslctx, void * /* parm */) -{ - // look for certificate in search paths - string path = CPath::lookup(CAFilename); - nlinfo("Cert path '%s'", path.c_str()); - - if (path.empty()) - { - nlwarning("Unable to find %s", CAFilename); - return CURLE_SSL_CACERT; - } - - CIFile file; - - // open certificate - if (!file.open(path)) - { - nlwarning("Unable to open %s", path.c_str()); - return CURLE_SSL_CACERT; - } - - CURLcode res = CURLE_OK; - - // load certificate content into memory - std::vector buffer(file.getFileSize()); - file.serialBuffer(&buffer[0], file.getFileSize()); - - // get a BIO - BIO *bio = BIO_new_mem_buf(&buffer[0], file.getFileSize()); - - char errorBuffer[1024]; - - if (bio) - { - // get a pointer to the X509 certificate store (which may be empty!) - X509_STORE *store = SSL_CTX_get_cert_store((SSL_CTX *)sslctx); - - // use it to read the PEM formatted certificate from memory into an X509 - // structure that SSL can use - STACK_OF(X509_INFO) *info = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); - - if (info) - { - // iterate over all entries from the PEM file, add them to the x509_store one by one - for (sint i = 0; i < sk_X509_INFO_num(info); ++i) - { - X509_INFO *itmp = sk_X509_INFO_value(info, i); - - if (itmp && itmp->x509) - { - X509_NAME *subject = X509_get_subject_name(itmp->x509); - - std::string name; - unsigned char *tmp = NULL; - - // construct a multiline string with name - for (int i = 0, ilen = X509_NAME_entry_count(subject); i < ilen; ++i) - { - X509_NAME_ENTRY *e = X509_NAME_get_entry(subject, i); - ASN1_STRING *d = X509_NAME_ENTRY_get_data(e); - - if (ASN1_STRING_to_UTF8(&tmp, d) > 0) - { - name += NLMISC::toString("%s\n", tmp); - - OPENSSL_free(tmp); - } - } - - // add our certificate to this store - if (X509_STORE_add_cert(store, itmp->x509) == 0) - { - uint errCode = ERR_get_error(); - - // ignore already in hash table errors - if (ERR_GET_LIB(errCode) != ERR_LIB_X509 || ERR_GET_REASON(errCode) != X509_R_CERT_ALREADY_IN_HASH_TABLE) - { - ERR_error_string_n(errCode, errorBuffer, 1024); - nlwarning("Error adding certificate %s: %s", name.c_str(), errorBuffer); - res = CURLE_SSL_CACERT; - } - } - else - { - nlinfo("Added certificate %s", name.c_str()); - } - } - } - - // cleanup - sk_X509_INFO_pop_free(info, X509_INFO_free); - } - else - { - nlwarning("Unable to read PEM info"); - res = CURLE_SSL_CACERT; - } - - // decrease reference counts - BIO_free(bio); - } - else - { - nlwarning("Unable to allocate BIO buffer for certificates"); - res = CURLE_SSL_CACERT; - } - - // all set to go - return res; -} +static const std::string CAFilename = "ssl_ca_cert.pem"; // this is the certificate "Thawte Server CA" // *************************************************************************** bool CCurlHttpClient::verifyServer(bool verify) @@ -184,8 +71,15 @@ bool CCurlHttpClient::verifyServer(bool verify) curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYHOST, verify ? 2 : 0); curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYPEER, verify ? 1 : 0); curl_easy_setopt(_Curl, CURLOPT_SSLCERTTYPE, "PEM"); + + // check if compiled with OpenSSL backend + NLGUI::CCurlCertificates::init(_Curl); + + // specify custom CA certs + NLGUI::CCurlCertificates::addCertificateFile(CAFilename); + // would allow to provide the CA in memory instead of using CURLOPT_CAINFO, but needs to include and link OpenSSL - if (curl_easy_setopt(_Curl, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function) != CURLE_OK) + if (curl_easy_setopt(_Curl, CURLOPT_SSL_CTX_FUNCTION, &NLGUI::CCurlCertificates::sslCtxFunction) != CURLE_OK) { nlwarning("Unable to support CURLOPT_SSL_CTX_FUNCTION, curl not compiled with OpenSSL ?"); } From 1dc5ad039e34797500388572ad37c826b8116d45 Mon Sep 17 00:00:00 2001 From: kervala Date: Sun, 5 Aug 2018 14:59:06 +0200 Subject: [PATCH 070/303] Fixed: Link NELGUI to Crypt32.lib and Cryptui.lib under Windows --HG-- branch : develop --- code/nel/src/gui/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/nel/src/gui/CMakeLists.txt b/code/nel/src/gui/CMakeLists.txt index cdd090f0b..a5f157c01 100644 --- a/code/nel/src/gui/CMakeLists.txt +++ b/code/nel/src/gui/CMakeLists.txt @@ -9,6 +9,11 @@ NL_TARGET_LIB(nelgui ${SRC} ${HEADERS}) INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR} ${LUA_INCLUDE_DIR} ${LUABIND_INCLUDE_DIR} ${CURL_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR}) TARGET_LINK_LIBRARIES(nelgui nelmisc nel3d ${LUA_LIBRARIES} ${LUABIND_LIBRARIES} ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES}) + +IF(WIN32) + TARGET_LINK_LIBRARIES(nelgui Crypt32 Cryptui) +ENDIF() + NL_DEFAULT_PROPS(nelgui "NeL, Library: NeL GUI") NL_ADD_RUNTIME_FLAGS(nelgui) From ce31c4c17fd3c8ff7a16399be890c8294419b45e Mon Sep 17 00:00:00 2001 From: kervala Date: Sun, 5 Aug 2018 14:59:28 +0200 Subject: [PATCH 071/303] Changed: Minor changes --HG-- branch : develop --- code/nel/src/gui/curl_certificates.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/nel/src/gui/curl_certificates.cpp b/code/nel/src/gui/curl_certificates.cpp index a279d35f6..e44161882 100644 --- a/code/nel/src/gui/curl_certificates.cpp +++ b/code/nel/src/gui/curl_certificates.cpp @@ -86,7 +86,7 @@ namespace NLGUI } else { - // if CURL is using SSPI under Windows or SecureChannel under OS X, we'll use native system CA Certs + // if CURL is using SSPI or SChannel under Windows or DarwinSSL under OS X, we'll use native system CA Certs isUsingOpenSSLBackend = false; } @@ -122,14 +122,14 @@ namespace NLGUI void addCertificatesFromFile(const std::string &cert) { + if (!isUsingOpenSSLBackend) return; + if (!isInitialized) { nlwarning("You MUST call NLGUI::CCurlCertificates::init before adding new certificates"); return; } - if (!isUsingOpenSSLBackend) return; - // this file was already loaded if (std::find(FilesList.begin(), FilesList.end(), cert) != FilesList.end()) return; From 5385e04bbaaa718d8d0e926141a481b78c3142a5 Mon Sep 17 00:00:00 2001 From: kervala Date: Tue, 7 Aug 2018 12:09:33 +0200 Subject: [PATCH 072/303] Fixed: Link Qt to OpenSSL --HG-- branch : develop --- code/CMakeModules/FindHelpers.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/CMakeModules/FindHelpers.cmake b/code/CMakeModules/FindHelpers.cmake index d9aa3e75c..a4af37229 100644 --- a/code/CMakeModules/FindHelpers.cmake +++ b/code/CMakeModules/FindHelpers.cmake @@ -896,7 +896,7 @@ MACRO(FIND_QT5) # Network SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::Network Qt5::Xml) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${ZLIB_LIBRARIES}) + SET(QT_LIBRARIES ${QT_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES}) IF(WIN32) SET(QT_LIBRARIES ${QT_LIBRARIES} From a0c3a3adc50b55a02f0f9efa45d9a12b939ad967 Mon Sep 17 00:00:00 2001 From: kervala Date: Tue, 7 Aug 2018 13:29:36 +0200 Subject: [PATCH 073/303] Fixed: Link nelgui to Security framework (fix compilation with curl using DarwinSSL backend) --HG-- branch : develop --- code/CMakeLists.txt | 15 ++++++++++----- code/nel/src/gui/CMakeLists.txt | 4 ---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 022c34659..e10bb54db 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -167,6 +167,7 @@ ENDIF() IF(APPLE) FIND_LIBRARY(CARBON_FRAMEWORK Carbon) FIND_LIBRARY(FOUNDATION_FRAMEWORK Foundation) + FIND_LIBRARY(SECURITY_FRAMEWORK Security) IF(APPLE_CERTIFICATE) # Find codesign_allocate @@ -226,22 +227,26 @@ IF(WITH_NEL) IF(CURL_STATIC) SET(CURL_DEFINITIONS -DCURL_STATICLIB) - SET(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR}) - SET(CURL_LIBRARIES ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES}) + LIST(APPEND CURL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR}) + LIST(APPEND CURL_LIBRARIES ${OPENSSL_LIBRARIES}) - IF(UNIX) + IF(WIN32) + LIST(APPEND CURL_LIBRARIES Crypt32 Cryptui) + ELSE() # CURL depends on libidn FIND_LIBRARY(IDN_LIBRARY idn) IF(IDN_LIBRARY) - SET(CURL_LIBRARIES ${CURL_LIBRARIES} ${IDN_LIBRARY}) + LIST(APPEND CURL_LIBRARIES ${IDN_LIBRARY}) ENDIF() # CURL Macports version depends on libidn, libintl and libiconv too IF(APPLE) FIND_LIBRARY(INTL_LIBRARY intl) IF(INTL_LIBRARY) - SET(CURL_LIBRARIES ${CURL_LIBRARIES} ${INTL_LIBRARY}) + LIST(APPEND CURL_LIBRARIES ${INTL_LIBRARY}) ENDIF() + + LIST(APPEND CURL_LIBRARIES ${SECURITY_FRAMEWORK}) ENDIF() ENDIF() ENDIF() diff --git a/code/nel/src/gui/CMakeLists.txt b/code/nel/src/gui/CMakeLists.txt index a5f157c01..cb7bbe23a 100644 --- a/code/nel/src/gui/CMakeLists.txt +++ b/code/nel/src/gui/CMakeLists.txt @@ -10,10 +10,6 @@ INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR} ${LUA_INCLUDE_DIR} ${LUABIND_INCLUDE_ TARGET_LINK_LIBRARIES(nelgui nelmisc nel3d ${LUA_LIBRARIES} ${LUABIND_LIBRARIES} ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES}) -IF(WIN32) - TARGET_LINK_LIBRARIES(nelgui Crypt32 Cryptui) -ENDIF() - NL_DEFAULT_PROPS(nelgui "NeL, Library: NeL GUI") NL_ADD_RUNTIME_FLAGS(nelgui) From dd517424c79c91a977689096500d27d25ef5619d Mon Sep 17 00:00:00 2001 From: kervala Date: Tue, 7 Aug 2018 13:38:00 +0200 Subject: [PATCH 074/303] Fixed: CURL also depends on libidn2 and libpsl under OS X --HG-- branch : develop --- code/CMakeLists.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index e10bb54db..9ba0ebe65 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -239,13 +239,23 @@ IF(WITH_NEL) LIST(APPEND CURL_LIBRARIES ${IDN_LIBRARY}) ENDIF() - # CURL Macports version depends on libidn, libintl and libiconv too + # CURL Macports version can depend on libidn, libidn2, libintl, libpsl and libiconv too IF(APPLE) FIND_LIBRARY(INTL_LIBRARY intl) IF(INTL_LIBRARY) LIST(APPEND CURL_LIBRARIES ${INTL_LIBRARY}) ENDIF() + FIND_LIBRARY(IDN2_LIBRARY idn2) + IF(IDN2_LIBRARY) + LIST(APPEND CURL_LIBRARIES ${IDN2_LIBRARY}) + ENDIF() + + FIND_LIBRARY(PSL_LIBRARY psl) + IF(PSL_LIBRARY) + LIST(APPEND CURL_LIBRARIES ${PSL_LIBRARY}) + ENDIF() + LIST(APPEND CURL_LIBRARIES ${SECURITY_FRAMEWORK}) ENDIF() ENDIF() From df032e220e52b958b928c9c520320e627e51ceb7 Mon Sep 17 00:00:00 2001 From: kervala Date: Tue, 7 Aug 2018 16:02:34 +0200 Subject: [PATCH 075/303] Fixed: CURL also depends on libunistring under OS X --HG-- branch : develop --- code/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 9ba0ebe65..681f7a959 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -256,6 +256,11 @@ IF(WITH_NEL) LIST(APPEND CURL_LIBRARIES ${PSL_LIBRARY}) ENDIF() + FIND_LIBRARY(UNISTRING_LIBRARY unistring) + IF(UNISTRING_LIBRARY) + LIST(APPEND CURL_LIBRARIES ${UNISTRING_LIBRARY}) + ENDIF() + LIST(APPEND CURL_LIBRARIES ${SECURITY_FRAMEWORK}) ENDIF() ENDIF() From d9e6d34fcc9112244b8602140ab8639443626ae7 Mon Sep 17 00:00:00 2001 From: kervala Date: Tue, 7 Aug 2018 18:40:48 +0200 Subject: [PATCH 076/303] Changed: Make sslCtxFunction private and don't include curl.h in header --HG-- branch : develop --- code/nel/include/nel/gui/curl_certificates.h | 7 +-- code/nel/src/gui/curl_certificates.cpp | 55 ++++++++++++++------ code/nel/src/gui/group_html.cpp | 27 ++++------ code/ryzom/client/src/http_client_curl.cpp | 11 +--- 4 files changed, 54 insertions(+), 46 deletions(-) diff --git a/code/nel/include/nel/gui/curl_certificates.h b/code/nel/include/nel/gui/curl_certificates.h index dd4e923a0..ee6938842 100644 --- a/code/nel/include/nel/gui/curl_certificates.h +++ b/code/nel/include/nel/gui/curl_certificates.h @@ -19,7 +19,8 @@ #include "nel/misc/types_nl.h" -#include +// forward declaration to avoid curl.h inclusion everywhere +typedef void CURL; namespace NLGUI { @@ -32,8 +33,8 @@ namespace NLGUI // allow to use custom PEM certificates static void addCertificateFile(const std::string &cert); - // cURL SSL certificate loading - static CURLcode sslCtxFunction(CURL *curl, void *sslctx, void *parm); + // set all CURL options to use custom SSL context function + static void useCertificates(CURL *curl); }; } // namespace diff --git a/code/nel/src/gui/curl_certificates.cpp b/code/nel/src/gui/curl_certificates.cpp index e44161882..552ed2a9f 100644 --- a/code/nel/src/gui/curl_certificates.cpp +++ b/code/nel/src/gui/curl_certificates.cpp @@ -23,6 +23,8 @@ #include #include +#include + using namespace std; using namespace NLMISC; @@ -201,23 +203,8 @@ namespace NLGUI /// this will be initialized on startup and cleared on exit static SX509Certificates x509CertListManager; - // *************************************************************************** - // static - void CCurlCertificates::init(CURL *curl) - { - x509CertListManager.init(curl); - } - - // *************************************************************************** - // static - void CCurlCertificates::addCertificateFile(const std::string &cert) - { - x509CertListManager.addCertificatesFromFile(cert); - } - - // *************************************************************************** - // static - CURLcode CCurlCertificates::sslCtxFunction(CURL *curl, void *sslctx, void *parm) + // cURL SSL certificate loading + static CURLcode sslCtxFunction(CURL *curl, void *sslctx, void *parm) { CURLcode res = CURLE_OK; @@ -282,5 +269,39 @@ namespace NLGUI return res; } + // *************************************************************************** + // static + void CCurlCertificates::init(CURL *curl) + { + x509CertListManager.init(curl); + } + + // *************************************************************************** + // static + void CCurlCertificates::addCertificateFile(const std::string &cert) + { + x509CertListManager.addCertificatesFromFile(cert); + } + + // *************************************************************************** + // static + void CCurlCertificates::useCertificates(CURL *curl) + { + // CURL must be valid, using OpenSSL backend and certificates must be loaded, else return + if (!curl || !isUsingOpenSSLBackend || x509CertListManager.CertList.empty()) return; + + curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM"); + + // would allow to provide the CA in memory instead of using CURLOPT_CAINFO, but needs to include and link OpenSSL + if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, &sslCtxFunction) != CURLE_OK) + { + nlwarning("Unable to support CURLOPT_SSL_CTX_FUNCTION, curl not compiled with OpenSSL ?"); + } + + // set both CURLOPT_CAINFO and CURLOPT_CAPATH to NULL to be sure we won't use default values (these files can be missing and generate errors) + curl_easy_setopt(curl, CURLOPT_CAINFO, NULL); + curl_easy_setopt(curl, CURLOPT_CAPATH, NULL); + } + }// namespace diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index fe08b6931..6f0e612c9 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -404,15 +404,8 @@ namespace NLGUI // specify custom CA certs CCurlCertificates::addCertificateFile(options.curlCABundle); - // would allow to provide the CA in memory instead of using CURLOPT_CAINFO, but needs to include and link OpenSSL - if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, &CCurlCertificates::sslCtxFunction) != CURLE_OK) - { - nlwarning("Unable to support CURLOPT_SSL_CTX_FUNCTION, curl not compiled with OpenSSL ?"); - } - - // set both CURLOPT_CAINFO and CURLOPT_CAPATH to NULL to be sure we won't use default values (these files can be missing and generate errors) - curl_easy_setopt(curl, CURLOPT_CAINFO, NULL); - curl_easy_setopt(curl, CURLOPT_CAPATH, NULL); + // if supported, use custom SSL context function to load certificates + CCurlCertificates::useCertificates(curl); } download.data = new CCurlWWWData(curl, download.url); @@ -5350,14 +5343,14 @@ namespace NLGUI // https:// if (toLower(url.substr(0, 8)) == "https://") { -#if defined(NL_OS_WINDOWS) - curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, &CCurlCertificates::sslCtxFunction); -#else - if (!options.curlCABundle.empty()) - { - curl_easy_setopt(curl, CURLOPT_CAINFO, options.curlCABundle.c_str()); - } -#endif + // check if compiled with OpenSSL backend + CCurlCertificates::init(curl); + + // specify custom CA certs + CCurlCertificates::addCertificateFile(options.curlCABundle); + + // if supported, use custom SSL context function to load certificates + CCurlCertificates::useCertificates(curl); } // do not follow redirects, we have own handler diff --git a/code/ryzom/client/src/http_client_curl.cpp b/code/ryzom/client/src/http_client_curl.cpp index 418fc61bd..2887543c3 100644 --- a/code/ryzom/client/src/http_client_curl.cpp +++ b/code/ryzom/client/src/http_client_curl.cpp @@ -70,7 +70,6 @@ bool CCurlHttpClient::verifyServer(bool verify) { curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYHOST, verify ? 2 : 0); curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYPEER, verify ? 1 : 0); - curl_easy_setopt(_Curl, CURLOPT_SSLCERTTYPE, "PEM"); // check if compiled with OpenSSL backend NLGUI::CCurlCertificates::init(_Curl); @@ -78,15 +77,9 @@ bool CCurlHttpClient::verifyServer(bool verify) // specify custom CA certs NLGUI::CCurlCertificates::addCertificateFile(CAFilename); - // would allow to provide the CA in memory instead of using CURLOPT_CAINFO, but needs to include and link OpenSSL - if (curl_easy_setopt(_Curl, CURLOPT_SSL_CTX_FUNCTION, &NLGUI::CCurlCertificates::sslCtxFunction) != CURLE_OK) - { - nlwarning("Unable to support CURLOPT_SSL_CTX_FUNCTION, curl not compiled with OpenSSL ?"); - } + // if supported, use custom SSL context function to load certificates + NLGUI::CCurlCertificates::useCertificates(_Curl); - // set both CURLOPT_CAINFO and CURLOPT_CAPATH to NULL to be sure we won't use default values (these files can be missing and generate errors) - curl_easy_setopt(_Curl, CURLOPT_CAINFO, NULL); - curl_easy_setopt(_Curl, CURLOPT_CAPATH, NULL); return true; } From 6966bc1a12a57f2586221642007706c12412ecc3 Mon Sep 17 00:00:00 2001 From: kervala Date: Tue, 7 Aug 2018 18:41:04 +0200 Subject: [PATCH 077/303] Fixed: Compilation with older CURL --HG-- branch : develop --- code/nel/src/gui/curl_certificates.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/code/nel/src/gui/curl_certificates.cpp b/code/nel/src/gui/curl_certificates.cpp index 552ed2a9f..14a1c3f0a 100644 --- a/code/nel/src/gui/curl_certificates.cpp +++ b/code/nel/src/gui/curl_certificates.cpp @@ -69,7 +69,16 @@ namespace NLGUI // get more information on CURL session curl_tlssessioninfo *sessionInfo; - CURLcode res = curl_easy_getinfo(curl, CURLINFO_TLS_SSL_PTR, &sessionInfo); + + CURLINFO info; + +#if CURL_AT_LEAST_VERSION(7, 48, 0) + info = CURLINFO_TLS_SSL_PTR; +#else + info = CURLINFO_TLS_SESSION; +#endif + + CURLcode res = curl_easy_getinfo(curl, info, &sessionInfo); // only use OpenSSL callback if not using Windows SSPI and using OpenSSL backend if (!res && sessionInfo && sessionInfo->backend == CURLSSLBACKEND_OPENSSL && !(data && data->features & CURL_VERSION_SSPI)) From b4f69007f60fbae3f2bf3f5d0b1a2c36cd854cb4 Mon Sep 17 00:00:00 2001 From: kervala Date: Tue, 7 Aug 2018 20:29:39 +0200 Subject: [PATCH 078/303] Fixed: Compilation --HG-- branch : develop --- code/nel/src/gui/curl_certificates.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/src/gui/curl_certificates.cpp b/code/nel/src/gui/curl_certificates.cpp index 14a1c3f0a..f06d92608 100644 --- a/code/nel/src/gui/curl_certificates.cpp +++ b/code/nel/src/gui/curl_certificates.cpp @@ -297,7 +297,7 @@ namespace NLGUI void CCurlCertificates::useCertificates(CURL *curl) { // CURL must be valid, using OpenSSL backend and certificates must be loaded, else return - if (!curl || !isUsingOpenSSLBackend || x509CertListManager.CertList.empty()) return; + if (!curl || !x509CertListManager.isUsingOpenSSLBackend || x509CertListManager.CertList.empty()) return; curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM"); From 53bae35fc41eda6ba5eea533c5405960738fd76d Mon Sep 17 00:00:00 2001 From: kervala Date: Wed, 8 Aug 2018 09:39:40 +0200 Subject: [PATCH 079/303] Fixed: Use GlobalMemoryStatusEx instead of GlobalMemoryStatus (returns 64 bits numbers) --HG-- branch : develop --- code/nel/src/misc/system_info.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/code/nel/src/misc/system_info.cpp b/code/nel/src/misc/system_info.cpp index 2afa8da09..75d9707b3 100644 --- a/code/nel/src/misc/system_info.cpp +++ b/code/nel/src/misc/system_info.cpp @@ -1470,9 +1470,9 @@ uint64 CSystemInfo::availableHDSpace (const string &filename) uint64 CSystemInfo::availablePhysicalMemory () { #ifdef NL_OS_WINDOWS - MEMORYSTATUS ms; - GlobalMemoryStatus (&ms); - return uint64(ms.dwAvailPhys); + MEMORYSTATUSEX ms; + GlobalMemoryStatusEx(&ms); + return ms.ullAvailPhys; #elif defined NL_OS_MAC return uint64(getsysctlnum64("hw.usermem")); #elif defined NL_OS_UNIX @@ -1485,9 +1485,9 @@ uint64 CSystemInfo::availablePhysicalMemory () uint64 CSystemInfo::totalPhysicalMemory () { #ifdef NL_OS_WINDOWS - MEMORYSTATUS ms; - GlobalMemoryStatus (&ms); - return uint64(ms.dwTotalPhys); + MEMORYSTATUSEX ms; + GlobalMemoryStatusEx(&ms); + return ms.ullTotalPhys; #elif defined NL_OS_MAC return uint64(getsysctlnum64("hw.physmem")); #elif defined NL_OS_UNIX @@ -1867,9 +1867,9 @@ bool CSystemInfo::getVideoInfo (std::string &deviceName, uint64 &driverVersion) uint64 CSystemInfo::virtualMemory () { #ifdef NL_OS_WINDOWS - MEMORYSTATUS ms; - GlobalMemoryStatus (&ms); - return uint64(ms.dwTotalVirtual - ms.dwAvailVirtual); + MEMORYSTATUSEX ms; + GlobalMemoryStatusEx(&ms); + return ms.ullTotalVirtual - ms.ullAvailVirtual; #else return 0; #endif From 675f85c2888825bceb76c6f271f830ff8beea9bf Mon Sep 17 00:00:00 2001 From: kervala Date: Wed, 8 Aug 2018 20:37:51 +0200 Subject: [PATCH 080/303] Fixed: Warnings, throw(type) deprecated in C++11 and removed in C++17 --HG-- branch : develop --- code/nel/include/nel/3d/driver.h | 2 +- code/nel/include/nel/3d/dru.h | 6 ++-- code/nel/include/nel/3d/landscape.h | 4 +-- code/nel/include/nel/3d/nelu.h | 4 +-- code/nel/include/nel/gui/lua_ihm.h | 2 +- code/nel/include/nel/gui/lua_object.h | 36 +++++++++---------- code/nel/include/nel/misc/class_registry.h | 4 +-- code/nel/include/nel/misc/file.h | 16 ++++----- code/nel/include/nel/misc/mem_stream.h | 2 +- code/nel/include/nel/misc/string_mapper.h | 4 +-- code/nel/include/nel/net/message.h | 2 +- code/nel/include/nel/net/module.h | 4 +-- code/nel/include/nel/net/module_gateway.h | 4 +-- .../src/3d/driver/direct3d/driver_direct3d.h | 2 +- code/nel/src/3d/driver/opengl/driver_opengl.h | 2 +- code/nel/src/gui/lua_object.cpp | 24 ++++++------- code/nel/src/misc/file.cpp | 2 +- code/nel/src/misc/mem_stream.cpp | 2 +- code/ryzom/client/src/camera_recorder.cpp | 2 +- .../client/src/gateway_fec_transport.cpp | 6 ++-- code/ryzom/client/src/login_patch.cpp | 2 +- code/ryzom/client/src/r2/editor.cpp | 2 +- code/ryzom/client/src/r2/editor.h | 2 +- .../server/src/ai_service/ai_script_comp.h | 2 +- .../server/src/ai_service/script_compiler.h | 2 +- .../entity_manager/entity_base.h | 12 +++---- .../shop_type/item_for_sale.h | 4 +-- .../shop_type/items_for_sale.h | 2 +- 28 files changed, 79 insertions(+), 79 deletions(-) diff --git a/code/nel/include/nel/3d/driver.h b/code/nel/include/nel/3d/driver.h index 52bda8576..85140b3da 100644 --- a/code/nel/include/nel/3d/driver.h +++ b/code/nel/include/nel/3d/driver.h @@ -224,7 +224,7 @@ public: // @{ // first param is the associated window. // Must be a HWND for Windows (WIN32). - virtual bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show = true, bool resizeable = true) throw(EBadDisplay) = 0; + virtual bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show = true, bool resizeable = true) = 0; // Must be called after a setDisplay that initialize the mode virtual bool setMode(const GfxMode &mode) = 0; virtual bool getModes(std::vector &modes) = 0; diff --git a/code/nel/include/nel/3d/dru.h b/code/nel/include/nel/3d/dru.h index fda543ecd..c23d41382 100644 --- a/code/nel/include/nel/3d/dru.h +++ b/code/nel/include/nel/3d/dru.h @@ -134,14 +134,14 @@ class CDRU public: /// Portable Function which create a GL Driver (using gl dll...). - static IDriver *createGlDriver() throw(EDru); + static IDriver *createGlDriver(); /// Portable Function which create a GL ES Driver (using gl dll...). - static IDriver *createGlEsDriver() throw(EDru); + static IDriver *createGlEsDriver(); #ifdef NL_OS_WINDOWS /// Windows Function which create a Direct3d Driver. - static IDriver *createD3DDriver() throw(EDru); + static IDriver *createD3DDriver(); #endif // NL_OS_WINDOWS /// \name 2D render. diff --git a/code/nel/include/nel/3d/landscape.h b/code/nel/include/nel/3d/landscape.h index aa432f88b..a7383963d 100644 --- a/code/nel/include/nel/3d/landscape.h +++ b/code/nel/include/nel/3d/landscape.h @@ -168,9 +168,9 @@ public: void clear(); /// Verify the binding of patchs of all zones. throw EBadBind if error. - void checkBinds() throw(EBadBind); + void checkBinds(); /// Verify the binding of patchs of one zone. throw EBadBind if error. nop if zone not loaded. - void checkBinds(uint16 zoneId) throw(EBadBind); + void checkBinds(uint16 zoneId); /** * Build tileBank. Call this after loading the near and far tile banks. diff --git a/code/nel/include/nel/3d/nelu.h b/code/nel/include/nel/3d/nelu.h index fb30a5012..b64e83672 100644 --- a/code/nel/include/nel/3d/nelu.h +++ b/code/nel/include/nel/3d/nelu.h @@ -64,7 +64,7 @@ public: * * You can access the driver with CNELU::Driver. */ - static bool initDriver(uint w, uint h, uint bpp=32, bool windowed=true, nlWindow systemWindow=EmptyWindow, bool offscreen=false, bool direct3d=false) throw(EDru); + static bool initDriver(uint w, uint h, uint bpp=32, bool windowed=true, nlWindow systemWindow=EmptyWindow, bool offscreen=false, bool direct3d=false); /** Init all that we need for a Scene. * - register scene basics models, @@ -108,7 +108,7 @@ public: * - initScene(); * - initEventServer(); */ - static bool init(uint w, uint h, CViewport viewport=CViewport(), uint bpp=32, bool windowed=true, nlWindow systemWindow=EmptyWindow, bool offscreen = false, bool direct3d = false) throw(EDru); + static bool init(uint w, uint h, CViewport viewport=CViewport(), uint bpp=32, bool windowed=true, nlWindow systemWindow=EmptyWindow, bool offscreen = false, bool direct3d = false); /** Delete all: * - releaseEventServer(); diff --git a/code/nel/include/nel/gui/lua_ihm.h b/code/nel/include/nel/gui/lua_ihm.h index 974ece6f7..e45e1125f 100644 --- a/code/nel/include/nel/gui/lua_ihm.h +++ b/code/nel/include/nel/gui/lua_ihm.h @@ -118,7 +118,7 @@ namespace NLGUI /** read/write between values on a lua stack & a property exported from a 'CReflectable' derived object * (throws on error) */ - static void luaValueToReflectedProperty(CLuaState &ls, int stackIndex, CReflectable &target, const CReflectedProperty &property) throw(ELuaIHMException); + static void luaValueToReflectedProperty(CLuaState &ls, int stackIndex, CReflectable &target, const CReflectedProperty &property); // push a reflected property on the stack // NB : no check is done that 'property' is part of the class info of 'reflectedObject' diff --git a/code/nel/include/nel/gui/lua_object.h b/code/nel/include/nel/gui/lua_object.h index 1d3b0d64c..88c011347 100644 --- a/code/nel/include/nel/gui/lua_object.h +++ b/code/nel/include/nel/gui/lua_object.h @@ -110,7 +110,7 @@ namespace NLGUI /** create a sub table for this object, with a string as a key * This object must be a table or an exception if thrown */ - CLuaObject newTable(const char *tableName) throw(ELuaNotATable); + CLuaObject newTable(const char *tableName); /** Set a value in a table. @@ -118,29 +118,29 @@ namespace NLGUI * NB : value should came from the same lua environment * \TODO other type of keys */ - void setValue(const char *key, const CLuaObject &value) throw(ELuaNotATable); - void setValue(const std::string &key, const CLuaObject &value) throw(ELuaNotATable) { setValue(key.c_str(), value); } - void setValue(const char *key, const std::string &value) throw(ELuaNotATable); - void setValue(const char *key, const char *value) throw(ELuaNotATable); - void setValue(const char *key, bool value) throw(ELuaNotATable); - void setValue(const char *key, TLuaWrappedFunction value) throw(ELuaNotATable); - void setValue(const char *key, double value) throw(ELuaNotATable); - void setValue(const char *key, uint32 value) throw(ELuaNotATable); - void setValue(const char *key, sint32 value) throw(ELuaNotATable); - void setValue(const char *key, sint64 value) throw(ELuaNotATable); - void setValue(const std::string &key, const std::string &value) throw(ELuaNotATable) { setValue(key.c_str(), value); } - void setNil(const char *key) throw(ELuaNotATable); - void setNil(const std::string &key) throw(ELuaNotATable) { setNil(key.c_str()); } + void setValue(const char *key, const CLuaObject &value); + void setValue(const std::string &key, const CLuaObject &value) { setValue(key.c_str(), value); } + void setValue(const char *key, const std::string &value); + void setValue(const char *key, const char *value); + void setValue(const char *key, bool value); + void setValue(const char *key, TLuaWrappedFunction value); + void setValue(const char *key, double value); + void setValue(const char *key, uint32 value); + void setValue(const char *key, sint32 value); + void setValue(const char *key, sint64 value); + void setValue(const std::string &key, const std::string &value) { setValue(key.c_str(), value); } + void setNil(const char *key); + void setNil(const std::string &key) { setNil(key.c_str()); } /** Erase a value in a table by its key. * If this object is not a table then an exception is thrown. * \TODO other type of keys */ - void eraseValue(const char *key) throw(ELuaNotATable); - void eraseValue(const std::string &key) throw(ELuaNotATable) { eraseValue(key.c_str()); } + void eraseValue(const char *key); + void eraseValue(const std::string &key) { eraseValue(key.c_str()); } // test is this object is enumerable bool isEnumerable() const; // Enumeration of a table. If the object is not a table, an exception is thrown. - CLuaEnumeration enumerate() throw(ELuaNotATable); + CLuaEnumeration enumerate(); // retrieve metatable of an object (or nil if object has no metatable) CLuaObject getMetaTable() const; // set metatable for this object @@ -155,7 +155,7 @@ namespace NLGUI CLuaObject operator[](const std::string &key) const { return operator[](key.c_str()); } /** Checked access to a sub element of a table. An exception is thrown is the element is not a table. */ - CLuaObject at(const char *key) const throw (ELuaNotATable); + CLuaObject at(const char *key) const; CLuaObject at(const std::string &key) const { return at(key.c_str()); } // Test is that table has the given key. The object must be a table or an exception is thrown diff --git a/code/nel/include/nel/misc/class_registry.h b/code/nel/include/nel/misc/class_registry.h index 5c1fe8cd6..98139f5dc 100644 --- a/code/nel/include/nel/misc/class_registry.h +++ b/code/nel/include/nel/misc/class_registry.h @@ -86,10 +86,10 @@ public: static void release(); /// Register your class for future Instanciation. - static void registerClass(const std::string &className, IClassable* (*creator)(), const std::string &typeidCheck) throw(ERegistry); + static void registerClass(const std::string &className, IClassable* (*creator)(), const std::string &typeidCheck); /// Create an object from his class name. - static IClassable *create(const std::string &className) throw(ERegistry); + static IClassable *create(const std::string &className); /// check if the object has been correctly registered. Must be used for debug only, and Must compile with RTTI. static bool checkObject(IClassable* obj); diff --git a/code/nel/include/nel/misc/file.h b/code/nel/include/nel/misc/file.h index 17154e6be..78dba95c6 100644 --- a/code/nel/include/nel/misc/file.h +++ b/code/nel/include/nel/misc/file.h @@ -108,9 +108,9 @@ public: // Advanced Usage. /// flush the file. void flush(); /// Seek the file - bool seek (sint32 offset, IStream::TSeekOrigin origin) const throw(EStream); + bool seek (sint32 offset, IStream::TSeekOrigin origin) const; /// Get the location of the file pointer - sint32 getPos () const throw(EStream); + sint32 getPos () const; // Imp the Name of the stream as the name of the file. virtual std::string getStreamName() const; @@ -125,7 +125,7 @@ public: // Advanced Usage. // return true if there's nothing more to read (same as ifstream) bool eof (); - virtual void serialBuffer(uint8 *buf, uint len)throw(EReadError); + virtual void serialBuffer(uint8 *buf, uint len); /// \name Statistics @@ -148,7 +148,7 @@ public: // Advanced Usage. static void clearDump (); protected: - virtual void serialBit(bool &bit) throw(EReadError); + virtual void serialBit(bool &bit); virtual uint getDbgStreamSize() const; @@ -223,20 +223,20 @@ public: // Advanced Usage. /// flush the file. void flush(); /// Seek the file - bool seek (sint32 offset, IStream::TSeekOrigin origin) const throw(EStream); + bool seek (sint32 offset, IStream::TSeekOrigin origin) const; /// Get the location of the file pointer - sint32 getPos () const throw(EStream); + sint32 getPos () const; // Imp the Name of the stream as the name of the file. virtual std::string getStreamName() const; // very useful to serialize string in text mode (without the size) - virtual void serialBuffer(uint8 *buf, uint len) throw(EWriteError); + virtual void serialBuffer(uint8 *buf, uint len); protected: /// Internal close. void internalClose(bool success); - virtual void serialBit(bool &bit) throw(EWriteError); + virtual void serialBit(bool &bit); private: FILE *_F; diff --git a/code/nel/include/nel/misc/mem_stream.h b/code/nel/include/nel/misc/mem_stream.h index f614cc040..a9e8aacfc 100644 --- a/code/nel/include/nel/misc/mem_stream.h +++ b/code/nel/include/nel/misc/mem_stream.h @@ -197,7 +197,7 @@ public: * \return true if seek sucessfull. * \see ESeekNotSupported SeekOrigin getPos */ - virtual bool seek (sint32 offset, TSeekOrigin origin) const throw(EStream); + virtual bool seek (sint32 offset, TSeekOrigin origin) const; /** * Get the location of the stream pointer. diff --git a/code/nel/include/nel/misc/string_mapper.h b/code/nel/include/nel/misc/string_mapper.h index a20489f1c..aeaccf959 100644 --- a/code/nel/include/nel/misc/string_mapper.h +++ b/code/nel/include/nel/misc/string_mapper.h @@ -177,10 +177,10 @@ public: uint32 getCount() { return _IdCounter; } // helper serialize a string id as a string - void serial(NLMISC::IStream &f, TSStringId &strId) throw(EStream); + void serial(NLMISC::IStream &f, TSStringId &strId); // helper serialize a string id vector - void serial(NLMISC::IStream &f, std::vector &strIdVect) throw(EStream); + void serial(NLMISC::IStream &f, std::vector &strIdVect); }; diff --git a/code/nel/include/nel/net/message.h b/code/nel/include/nel/net/message.h index e96cb50d3..f1c571d44 100644 --- a/code/nel/include/nel/net/message.h +++ b/code/nel/include/nel/net/message.h @@ -146,7 +146,7 @@ public: return _LengthR; } - virtual sint32 getPos () const throw(NLMISC::EStream) + virtual sint32 getPos() const { // return (_BufPos - _Buffer.getPtr()) - _SubMessagePosR; return _Buffer.Pos - _SubMessagePosR; diff --git a/code/nel/include/nel/net/module.h b/code/nel/include/nel/net/module.h index 4493dd966..0b5b158d2 100644 --- a/code/nel/include/nel/net/module.h +++ b/code/nel/include/nel/net/module.h @@ -779,10 +779,10 @@ namespace NLNET // Init base module, init module name bool initModule(const TParsedCommandLine &initInfo); - void plugModule(IModuleSocket *moduleSocket) throw (EModuleAlreadyPluggedHere); + void plugModule(IModuleSocket *moduleSocket); void unplugModule(IModuleSocket *moduleSocket) throw (EModuleNotPluggedHere); void getPluggedSocketList(std::vector &resultList); - void invokeModuleOperation(IModuleProxy *destModule, const NLNET::CMessage &opMsg, NLNET::CMessage &resultMsg) throw (EInvokeFailed); + void invokeModuleOperation(IModuleProxy *destModule, const NLNET::CMessage &opMsg, NLNET::CMessage &resultMsg); void _onModuleUp(IModuleProxy *removedProxy); void _onModuleDown(IModuleProxy *removedProxy); diff --git a/code/nel/include/nel/net/module_gateway.h b/code/nel/include/nel/net/module_gateway.h index a097f8de0..75d386162 100644 --- a/code/nel/include/nel/net/module_gateway.h +++ b/code/nel/include/nel/net/module_gateway.h @@ -346,9 +346,9 @@ namespace NLNET virtual const std::string &getClassName() const =0; /// The gateway send a command message to the transport - virtual void onCommand(const CMessage &command) throw (EInvalidCommand) = 0; + virtual void onCommand(const CMessage &command) = 0; /// The gateway send a textual command to the transport - virtual bool onCommand(const TParsedCommandLine &command) throw (EInvalidCommand) = 0; + virtual bool onCommand(const TParsedCommandLine &command) = 0; /// The gateway update the transport regularly virtual void update() =0; diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d.h b/code/nel/src/3d/driver/direct3d/driver_direct3d.h index a4d9dbaeb..6621ab6cb 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.h +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.h @@ -849,7 +849,7 @@ public: // Mode initialisation, requests virtual bool init (uintptr_t windowIcon = 0, emptyProc exitFunc = 0); - virtual bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable) throw(EBadDisplay); + virtual bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable virtual bool release(); virtual bool setMode(const GfxMode& mode); virtual bool getModes(std::vector &modes); diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.h b/code/nel/src/3d/driver/opengl/driver_opengl.h index 68e6b0edf..a03077544 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.h +++ b/code/nel/src/3d/driver/opengl/driver_opengl.h @@ -325,7 +325,7 @@ public: virtual void disableHardwareVertexArrayAGP(); virtual void disableHardwareTextureShader(); - virtual bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable) throw(EBadDisplay); + virtual bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable); virtual bool setMode(const GfxMode& mode); virtual bool getModes(std::vector &modes); virtual bool getCurrentScreenMode(GfxMode &mode); diff --git a/code/nel/src/gui/lua_object.cpp b/code/nel/src/gui/lua_object.cpp index c957c3f2c..5417ba0c5 100644 --- a/code/nel/src/gui/lua_object.cpp +++ b/code/nel/src/gui/lua_object.cpp @@ -271,7 +271,7 @@ namespace NLGUI } // ************************************************* - CLuaObject CLuaObject::at(const char *key) const throw(ELuaNotATable) + CLuaObject CLuaObject::at(const char *key) const { if (!isEnumerable()) throw ELuaNotATable(NLMISC::toString("Can't get key '%s' in object '%s' because type is '%s', it is not a table.", key, getId().c_str(), getTypename()).c_str()); return operator[](key); @@ -286,7 +286,7 @@ namespace NLGUI } // ************************************************* - CLuaObject CLuaObject::newTable(const char *tableName) throw(ELuaNotATable) + CLuaObject CLuaObject::newTable(const char *tableName) { nlassert(tableName); nlassert(isValid()); @@ -301,7 +301,7 @@ namespace NLGUI } // ************************************************* - void CLuaObject::setValue(const char *key, const CLuaObject &value) throw(ELuaNotATable) + void CLuaObject::setValue(const char *key, const CLuaObject &value) { nlassert(key); nlassert(isValid()); @@ -331,7 +331,7 @@ namespace NLGUI } // ************************************************* - void CLuaObject::setValue(const char *key, const char *value) throw(ELuaNotATable) + void CLuaObject::setValue(const char *key, const char *value) { nlassert(value); nlassert(key); @@ -346,13 +346,13 @@ namespace NLGUI } // ************************************************* - void CLuaObject::setValue(const char *key, const std::string &value) throw(ELuaNotATable) + void CLuaObject::setValue(const char *key, const std::string &value) { setValue(key, value.c_str()); } // ************************************************* - void CLuaObject::setValue(const char *key, bool value) throw(ELuaNotATable) + void CLuaObject::setValue(const char *key, bool value) { nlassert(key); nlassert(isValid()); @@ -366,7 +366,7 @@ namespace NLGUI } // ************************************************* - void CLuaObject::setValue(const char *key, TLuaWrappedFunction value) throw(ELuaNotATable) + void CLuaObject::setValue(const char *key, TLuaWrappedFunction value) { nlassert(key); nlassert(isValid()); @@ -380,7 +380,7 @@ namespace NLGUI } // ************************************************* - void CLuaObject::setValue(const char *key, double value) throw(ELuaNotATable) + void CLuaObject::setValue(const char *key, double value) { nlassert(key); nlassert(isValid()); @@ -394,7 +394,7 @@ namespace NLGUI } // ************************************************* - void CLuaObject::setValue(const char *key, uint32 value) throw(ELuaNotATable) + void CLuaObject::setValue(const char *key, uint32 value) { nlassert(key); nlassert(isValid()); @@ -408,7 +408,7 @@ namespace NLGUI } // ************************************************* - void CLuaObject::setValue(const char *key, sint32 value) throw(ELuaNotATable) + void CLuaObject::setValue(const char *key, sint32 value) { nlassert(key); nlassert(isValid()); @@ -422,7 +422,7 @@ namespace NLGUI } // ************************************************* - void CLuaObject::setValue(const char *key, sint64 value) throw(ELuaNotATable) + void CLuaObject::setValue(const char *key, sint64 value) { nlassert(key); nlassert(isValid()); @@ -436,7 +436,7 @@ namespace NLGUI } // ************************************************* - void CLuaObject::eraseValue(const char *key) throw(ELuaNotATable) + void CLuaObject::eraseValue(const char *key) { nlassert(isValid()); nlassert(key); diff --git a/code/nel/src/misc/file.cpp b/code/nel/src/misc/file.cpp index 727c02f83..722043fd8 100644 --- a/code/nel/src/misc/file.cpp +++ b/code/nel/src/misc/file.cpp @@ -453,7 +453,7 @@ void CIFile::serialBit(bool &bit) throw(EReadError) } // ====================================================================================================== -bool CIFile::seek (sint32 offset, IStream::TSeekOrigin origin) const throw(EStream) +bool CIFile::seek (sint32 offset, IStream::TSeekOrigin origin) const { if ((_CacheFileOnOpen) && (_Cache == NULL)) return false; diff --git a/code/nel/src/misc/mem_stream.cpp b/code/nel/src/misc/mem_stream.cpp index 49e19f523..dd81334d1 100644 --- a/code/nel/src/misc/mem_stream.cpp +++ b/code/nel/src/misc/mem_stream.cpp @@ -107,7 +107,7 @@ void CMemStream::serialBit(bool &bit) * (to prevent from an "inside serial" to increment it). * Then a seek(end) would get back to the pointer. */ -bool CMemStream::seek (sint32 offset, TSeekOrigin origin) const throw(EStream) +bool CMemStream::seek (sint32 offset, TSeekOrigin origin) const { switch (origin) { diff --git a/code/ryzom/client/src/camera_recorder.cpp b/code/ryzom/client/src/camera_recorder.cpp index 12cd4ff01..8f427c321 100644 --- a/code/ryzom/client/src/camera_recorder.cpp +++ b/code/ryzom/client/src/camera_recorder.cpp @@ -56,7 +56,7 @@ public: CVector Heading; //CVMatrix Matrix; public: - void serial(NLMISC::IStream &f) throw(EStream) + void serial(NLMISC::IStream &f) { f.serial(Date); f.serial(Pos); diff --git a/code/ryzom/client/src/gateway_fec_transport.cpp b/code/ryzom/client/src/gateway_fec_transport.cpp index 26104216e..fa15c465b 100644 --- a/code/ryzom/client/src/gateway_fec_transport.cpp +++ b/code/ryzom/client/src/gateway_fec_transport.cpp @@ -216,13 +216,13 @@ public: } } - void onCommand(const CMessage &/* command */) throw (IGatewayTransport::EInvalidCommand) + void onCommand(const CMessage &/* command */) { // nothing done for now throw EInvalidCommand(); } /// The gateway send a textual command to the transport - bool onCommand(const TParsedCommandLine &command) throw (IGatewayTransport::EInvalidCommand) + bool onCommand(const TParsedCommandLine &command) { if (command.SubParams.size() < 1) throw EInvalidCommand(); @@ -256,7 +256,7 @@ public: } /// Open the connection by intercepting client gateway message - void open() throw (ETransportError) + void open() { if (_Open) { diff --git a/code/ryzom/client/src/login_patch.cpp b/code/ryzom/client/src/login_patch.cpp index 5cf77aae7..6a3500ae0 100644 --- a/code/ryzom/client/src/login_patch.cpp +++ b/code/ryzom/client/src/login_patch.cpp @@ -101,7 +101,7 @@ struct EPatchDownloadException : public Exception { EPatchDownloadException() : Exception( "Download Error" ) {} EPatchDownloadException( const std::string& str ) : Exception( str ) {} - virtual ~EPatchDownloadException() throw() {} + virtual ~EPatchDownloadException() {} }; diff --git a/code/ryzom/client/src/r2/editor.cpp b/code/ryzom/client/src/r2/editor.cpp index dc81eeb38..68214151c 100644 --- a/code/ryzom/client/src/r2/editor.cpp +++ b/code/ryzom/client/src/r2/editor.cpp @@ -4370,7 +4370,7 @@ void CEditor::setCurrentTool(CTool *tool) } // ********************************************************************************************************* -CLuaObject CEditor::getClasses() throw(ELuaError) +CLuaObject CEditor::getClasses() { //H_AUTO(R2_getClasses_throw) CHECK_EDITOR diff --git a/code/ryzom/client/src/r2/editor.h b/code/ryzom/client/src/r2/editor.h index 48a9c6a50..cd19f6c71 100644 --- a/code/ryzom/client/src/r2/editor.h +++ b/code/ryzom/client/src/r2/editor.h @@ -421,7 +421,7 @@ public: // get table for registry in lua environment CLuaObject &getRegistry() { return _Registry; } // get lua classes (the r2.Classes table) - CLuaObject getClasses() throw(ELuaError); + CLuaObject getClasses(); // get R2 environment (the 'r2' table into lua global environment) CLuaObject &getEnv(); // get the config table (that is the 'r2.Config' table) diff --git a/code/ryzom/server/src/ai_service/ai_script_comp.h b/code/ryzom/server/src/ai_service/ai_script_comp.h index 834bbacd7..0b02cc722 100644 --- a/code/ryzom/server/src/ai_service/ai_script_comp.h +++ b/code/ryzom/server/src/ai_service/ai_script_comp.h @@ -54,7 +54,7 @@ public: virtual CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) = 0; virtual std::string getName () const =0; - static CFightScriptCompReader *getScriptReader (const std::string &str) throw (ReadFightActionException); + static CFightScriptCompReader *getScriptReader (const std::string &str); static CFightScriptComp *createScriptComp (const std::string &str) throw (ReadFightActionException); protected: diff --git a/code/ryzom/server/src/ai_service/script_compiler.h b/code/ryzom/server/src/ai_service/script_compiler.h index 80d83a860..a03de1f8d 100644 --- a/code/ryzom/server/src/ai_service/script_compiler.h +++ b/code/ryzom/server/src/ai_service/script_compiler.h @@ -298,7 +298,7 @@ public: static CToken* getToken (std::string const& tokenName); static NLMISC::CSmartPtr getRule (std::string const& ruleName); - static bool getNextToken (std::string const& text, size_t& index, std::string& tokenName, std::string& textValue) throw (EScriptError); + static bool getNextToken (std::string const& text, size_t& index, std::string& tokenName, std::string& textValue); static std::string const& getOpcodeName (AIVM::CScriptVM::EOpcode const& op); static AIVM::CScriptVM::EOpcode getOpcodeAndValue (std::string const& str, std::string& value); static CScriptNativeFuncParams* getNativeFunc (std::string const& funcName, std::string const& inparams, std::string const& outparams); diff --git a/code/ryzom/server/src/entities_game_service/entity_manager/entity_base.h b/code/ryzom/server/src/entities_game_service/entity_manager/entity_base.h index 05342be92..89d3271ae 100644 --- a/code/ryzom/server/src/entities_game_service/entity_manager/entity_base.h +++ b/code/ryzom/server/src/entities_game_service/entity_manager/entity_base.h @@ -521,36 +521,36 @@ public: * \param var is the name of the variable * \return ref on the stat value */ - sint32& lookupStat( const std::string& stat ) throw (EInvalidStat); + sint32& lookupStat( const std::string& stat); /** * get a reference on a characterristics value * \param c is enum of characteristic, st is enum of subtype of characterisitics (like max, current..) * \return ref on the stat value */ - sint32& lookupStat( CHARACTERISTICS::TCharacteristics c, SCharacteristicsAndScores::TCharacteristicsAndScoreSubType st ) throw (CEntityBase::EInvalidStat); + sint32& lookupStat( CHARACTERISTICS::TCharacteristics c, SCharacteristicsAndScores::TCharacteristicsAndScoreSubType st); /** * get a reference on a scores value * \param score is enum of score, st is enum of subtype of score (like max, current..) * \return ref on the stat value */ - sint32& lookupStat( SCORES::TScores score, SCharacteristicsAndScores::TCharacteristicsAndScoreSubType st ) throw (CEntityBase::EInvalidStat); + sint32& lookupStat( SCORES::TScores score, SCharacteristicsAndScores::TCharacteristicsAndScoreSubType st); /** * get a reference on a skill value * \param skill is enum of Skills, st is enum of subtype of skill (like base, current..) * \return ref on the stat value */ - sint32& lookupStat( SKILLS::ESkills skill, SSkill::ESkillSubType st ) throw (CEntityBase::EInvalidStat); + sint32& lookupStat( SKILLS::ESkills skill, SSkill::ESkillSubType st); /** * get a reference on a SpecialModifiers value * \param sm is enum of SpecialModifiers * \return ref on the stat value */ - sint32& lookupStat( CSpecialModifiers::ESpecialModifiers sm ) throw (CEntityBase::EInvalidStat); - const sint32& lookupStat( CSpecialModifiers::ESpecialModifiers sm ) const throw (CEntityBase::EInvalidStat); + sint32& lookupStat( CSpecialModifiers::ESpecialModifiers sm); + const sint32& lookupStat( CSpecialModifiers::ESpecialModifiers sm) const; /// accessors on hp (read only) inline sint32 currentHp() const { return _PhysScores._PhysicalScores[SCORES::hit_points].Current;} diff --git a/code/ryzom/server/src/entities_game_service/shop_type/item_for_sale.h b/code/ryzom/server/src/entities_game_service/shop_type/item_for_sale.h index 834c27dd1..3fffe22e7 100644 --- a/code/ryzom/server/src/entities_game_service/shop_type/item_for_sale.h +++ b/code/ryzom/server/src/entities_game_service/shop_type/item_for_sale.h @@ -83,7 +83,7 @@ public: virtual void setContinent( CONTINENT::TContinent continent ) = 0; // // serial -// virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream ) = 0; +// virtual void serial(NLMISC::IStream &f) = 0; // set item for sale virtual void itemForSale( uint32 price, uint32 retirePrice, CGameItemPtr item, uint32 quantity, const NLMISC::CEntityId& id, CONTINENT::TContinent continent, uint32 identifier ) = 0; @@ -190,7 +190,7 @@ public: void itemForSale( uint32 price, uint32 retirePrice, CGameItemPtr item, uint32 quantity, const NLMISC::CEntityId& id, CONTINENT::TContinent continent, uint32 identifier ); // serial -// void serial(NLMISC::IStream &f) throw(NLMISC::EStream ); +// void serial(NLMISC::IStream &f); // cast operator // const IItemTrade * operator = ( CItemForSale * i ) const { return (IItemTrade *) i; } diff --git a/code/ryzom/server/src/entities_game_service/shop_type/items_for_sale.h b/code/ryzom/server/src/entities_game_service/shop_type/items_for_sale.h index d8e02b4f6..6de4e8380 100644 --- a/code/ryzom/server/src/entities_game_service/shop_type/items_for_sale.h +++ b/code/ryzom/server/src/entities_game_service/shop_type/items_for_sale.h @@ -55,7 +55,7 @@ public: const std::vector< TItemTradePtr >& getContent() const { return _ItemsForSale; } // serial - void serial(NLMISC::IStream &f) throw(NLMISC::EStream ); + void serial(NLMISC::IStream &f); // check coherency between CDynamicItems and CItemsForSale of character, assume CItemsForSale is a reference void checkSellStore( NLMISC::CEntityId charId ); From c4888b2d5b82a9426b17e9d07d5986e4fe044a0c Mon Sep 17 00:00:00 2001 From: kervala Date: Wed, 8 Aug 2018 20:54:09 +0200 Subject: [PATCH 081/303] Fixed: Warnings, throw(type) deprecated in C++11 and removed in C++17 --HG-- branch : develop --- code/nel/include/nel/misc/smart_ptr.h | 6 +++--- .../nel/src/3d/driver/direct3d/driver_direct3d.cpp | 2 +- .../src/3d/driver/opengl/driver_opengl_window.cpp | 2 +- code/nel/src/3d/dru.cpp | 6 +++--- code/nel/src/3d/landscape.cpp | 4 ++-- code/nel/src/3d/nelu.cpp | 4 ++-- code/nel/src/gui/lua_ihm.cpp | 2 +- code/nel/src/gui/lua_object.cpp | 4 ++-- code/nel/src/misc/file.cpp | 14 +++++++------- code/nel/src/misc/string_mapper.cpp | 4 ++-- code/nel/src/net/module.cpp | 6 +++--- code/nel/src/net/module_gateway_transport.cpp | 10 +++++----- code/nel/src/net/module_l5_transport.cpp | 6 +++--- .../tools/3d/object_viewer/particle_workspace.h | 2 +- .../ryzom/server/src/ai_service/ai_script_comp.cpp | 2 +- .../server/src/ai_service/script_compiler.cpp | 2 +- .../entity_manager/entity_base.cpp | 12 ++++++------ .../shop_type/item_for_sale.cpp | 2 +- .../shop_type/item_for_sale.h | 2 +- .../shop_type/items_for_sale.cpp | 2 +- .../src/frontend_service/gateway_fes_transport.cpp | 6 +++--- .../server/src/input_output_service/chat_manager.h | 2 +- .../server/build_spell_sheet/build_spell_sheet.cpp | 6 +++--- .../object_viewer/particle_system/particle_node.h | 2 +- 24 files changed, 55 insertions(+), 55 deletions(-) diff --git a/code/nel/include/nel/misc/smart_ptr.h b/code/nel/include/nel/misc/smart_ptr.h index 2273cebeb..b0fc1c301 100644 --- a/code/nel/include/nel/misc/smart_ptr.h +++ b/code/nel/include/nel/misc/smart_ptr.h @@ -226,7 +226,7 @@ public: std::string toString() { if(Ptr) return toString(*Ptr); else return ""; } // serial using serialPtr - void serialPtr(NLMISC::IStream &f) throw(NLMISC::EStream ) + void serialPtr(NLMISC::IStream &f) { T* obj= NULL; if(f.isReading()) @@ -242,7 +242,7 @@ public: } } // serial using serialPloyPtr - void serialPolyPtr(NLMISC::IStream &f) throw(NLMISC::EStream ) + void serialPolyPtr(NLMISC::IStream &f) { T* obj= NULL; if(f.isReading()) @@ -337,7 +337,7 @@ public: void kill(); // serial using serialPloyPtr - void serialPolyPtr(NLMISC::IStream &f) throw(NLMISC::EStream ) + void serialPolyPtr(NLMISC::IStream &f) { T* obj= NULL; if(f.isReading()) diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp index be7a74722..7a4618683 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp @@ -1328,7 +1328,7 @@ const D3DFORMAT FinalPixelFormat[ITexture::UploadFormatCount][CDriverD3D::FinalP // *************************************************************************** -bool CDriverD3D::setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable) throw(EBadDisplay) +bool CDriverD3D::setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable) { H_AUTO_D3D(CDriver3D_setDisplay); diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp index a7eb6e62a..3d1803a2a 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp @@ -611,7 +611,7 @@ void CDriverGL::setWindowIcon(const std::vector &bitmaps) } // -------------------------------------------------- -bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool resizeable) throw(EBadDisplay) +bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool resizeable) { H_AUTO_OGL(CDriverGL_setDisplay) diff --git a/code/nel/src/3d/dru.cpp b/code/nel/src/3d/dru.cpp index 15ccbfe01..54248c001 100644 --- a/code/nel/src/3d/dru.cpp +++ b/code/nel/src/3d/dru.cpp @@ -77,7 +77,7 @@ extern IDriver* createGlEsDriverInstance (); #endif // *************************************************************************** -IDriver *CDRU::createGlDriver() throw (EDru) +IDriver *CDRU::createGlDriver() { #ifdef NL_STATIC @@ -131,7 +131,7 @@ IDriver *CDRU::createGlDriver() throw (EDru) } // *************************************************************************** -IDriver *CDRU::createGlEsDriver() throw (EDru) +IDriver *CDRU::createGlEsDriver() { #ifdef NL_STATIC @@ -188,7 +188,7 @@ IDriver *CDRU::createGlEsDriver() throw (EDru) #ifdef NL_OS_WINDOWS -IDriver *CDRU::createD3DDriver() throw (EDru) +IDriver *CDRU::createD3DDriver() { #ifdef NL_STATIC diff --git a/code/nel/src/3d/landscape.cpp b/code/nel/src/3d/landscape.cpp index 4b597fc2d..75e71920a 100644 --- a/code/nel/src/3d/landscape.cpp +++ b/code/nel/src/3d/landscape.cpp @@ -2423,7 +2423,7 @@ void CLandscape::checkZoneBinds(CZone &curZone, EBadBind &bindError) // *************************************************************************** -void CLandscape::checkBinds() throw(EBadBind) +void CLandscape::checkBinds() { EBadBind bindError; @@ -2439,7 +2439,7 @@ void CLandscape::checkBinds() throw(EBadBind) // *************************************************************************** -void CLandscape::checkBinds(uint16 zoneId) throw(EBadBind) +void CLandscape::checkBinds(uint16 zoneId) { EBadBind bindError; diff --git a/code/nel/src/3d/nelu.cpp b/code/nel/src/3d/nelu.cpp index 8cb6e0968..7807a5ef7 100644 --- a/code/nel/src/3d/nelu.cpp +++ b/code/nel/src/3d/nelu.cpp @@ -51,7 +51,7 @@ CEventServer CNELU::EventServer; CEventListenerAsync CNELU::AsyncListener; -bool CNELU::initDriver (uint w, uint h, uint bpp, bool windowed, nlWindow systemWindow, bool offscreen, bool direct3d) throw(EDru) +bool CNELU::initDriver (uint w, uint h, uint bpp, bool windowed, nlWindow systemWindow, bool offscreen, bool direct3d) { // Init debug system // NLMISC::InitDebug(); @@ -183,7 +183,7 @@ void CNELU::releaseDriver() } } -bool CNELU::init (uint w, uint h, CViewport viewport, uint bpp, bool windowed, nlWindow systemWindow, bool offscreen, bool direct3d) throw(EDru) +bool CNELU::init (uint w, uint h, CViewport viewport, uint bpp, bool windowed, nlWindow systemWindow, bool offscreen, bool direct3d) { NL3D::registerSerial3d(); if (initDriver(w,h,bpp,windowed,systemWindow,offscreen,direct3d)) diff --git a/code/nel/src/gui/lua_ihm.cpp b/code/nel/src/gui/lua_ihm.cpp index 0b4a1d0dc..4a51d221f 100644 --- a/code/nel/src/gui/lua_ihm.cpp +++ b/code/nel/src/gui/lua_ihm.cpp @@ -1434,7 +1434,7 @@ namespace NLGUI } // *************************************************************************** - void CLuaIHM::luaValueToReflectedProperty(CLuaState &ls, int stackIndex, CReflectable &target, const CReflectedProperty &property) throw(ELuaIHMException) + void CLuaIHM::luaValueToReflectedProperty(CLuaState &ls, int stackIndex, CReflectable &target, const CReflectedProperty &property) { //H_AUTO(Lua_property_throw) if(ls.isNil(stackIndex)) diff --git a/code/nel/src/gui/lua_object.cpp b/code/nel/src/gui/lua_object.cpp index 5417ba0c5..805e38ceb 100644 --- a/code/nel/src/gui/lua_object.cpp +++ b/code/nel/src/gui/lua_object.cpp @@ -222,7 +222,7 @@ namespace NLGUI } // ************************************************* - CLuaEnumeration CLuaObject::enumerate() throw(ELuaNotATable) + CLuaEnumeration CLuaObject::enumerate() { if (!isEnumerable()) { @@ -317,7 +317,7 @@ namespace NLGUI } // ************************************************* - void CLuaObject::setNil(const char *key) throw(ELuaNotATable) + void CLuaObject::setNil(const char *key) { nlassert(key); nlassert(isValid()); diff --git a/code/nel/src/misc/file.cpp b/code/nel/src/misc/file.cpp index 722043fd8..414a10e5a 100644 --- a/code/nel/src/misc/file.cpp +++ b/code/nel/src/misc/file.cpp @@ -401,7 +401,7 @@ bool CIFile::eof () } // ====================================================================================================== -void CIFile::serialBuffer(uint8 *buf, uint len) throw(EReadError) +void CIFile::serialBuffer(uint8 *buf, uint len) { if (len == 0) return; @@ -444,7 +444,7 @@ void CIFile::serialBuffer(uint8 *buf, uint len) throw(EReadError) } // ====================================================================================================== -void CIFile::serialBit(bool &bit) throw(EReadError) +void CIFile::serialBit(bool &bit) { // Simple for now. uint8 v=bit; @@ -485,7 +485,7 @@ bool CIFile::seek (sint32 offset, IStream::TSeekOrigin origin) const } // ====================================================================================================== -sint32 CIFile::getPos () const throw(EStream) +sint32 CIFile::getPos () const { return _ReadPos; } @@ -652,7 +652,7 @@ void COFile::flush() // ====================================================================================================== -void COFile::serialBuffer(uint8 *buf, uint len) throw(EWriteError) +void COFile::serialBuffer(uint8 *buf, uint len) { if(!_F) throw EFileNotOpened(_FileName); @@ -667,14 +667,14 @@ void COFile::serialBuffer(uint8 *buf, uint len) throw(EWriteError) } } // ====================================================================================================== -void COFile::serialBit(bool &bit) throw(EWriteError) +void COFile::serialBit(bool &bit) { // Simple for now. uint8 v=bit; serialBuffer(&v, 1); } // ====================================================================================================== -bool COFile::seek (sint32 offset, IStream::TSeekOrigin origin) const throw(EStream) +bool COFile::seek (sint32 offset, IStream::TSeekOrigin origin) const { if (_F) { @@ -701,7 +701,7 @@ bool COFile::seek (sint32 offset, IStream::TSeekOrigin origin) const throw(EStr return false; } // ====================================================================================================== -sint32 COFile::getPos () const throw(EStream) +sint32 COFile::getPos () const { if (_F) { diff --git a/code/nel/src/misc/string_mapper.cpp b/code/nel/src/misc/string_mapper.cpp index 6e59f7bab..39931efd2 100644 --- a/code/nel/src/misc/string_mapper.cpp +++ b/code/nel/src/misc/string_mapper.cpp @@ -211,7 +211,7 @@ void CStaticStringMapper::clear() } // **************************************************************************** -void CStaticStringMapper::serial(IStream &f, TSStringId &strId) throw(EStream) +void CStaticStringMapper::serial(IStream &f, TSStringId &strId) { std::string tmp; if (f.isReading()) @@ -227,7 +227,7 @@ void CStaticStringMapper::serial(IStream &f, TSStringId &strId) throw(EStream) } // **************************************************************************** -void CStaticStringMapper::serial(IStream &f, std::vector &strIdVect) throw(EStream) +void CStaticStringMapper::serial(IStream &f, std::vector &strIdVect) { std::vector vsTmp; std::string sTmp; diff --git a/code/nel/src/net/module.cpp b/code/nel/src/net/module.cpp index 1b5e03bec..b5707fea3 100644 --- a/code/nel/src/net/module.cpp +++ b/code/nel/src/net/module.cpp @@ -397,7 +397,7 @@ namespace NLNET } - void CModuleBase::plugModule(IModuleSocket *moduleSocket) throw (EModuleAlreadyPluggedHere) + void CModuleBase::plugModule(IModuleSocket *moduleSocket) { CModuleSocket *sock = dynamic_cast(moduleSocket); nlassert(sock != NULL); @@ -415,7 +415,7 @@ namespace NLNET _ModuleSockets.insert(moduleSocket); } - void CModuleBase::unplugModule(IModuleSocket *moduleSocket) throw (EModuleNotPluggedHere) + void CModuleBase::unplugModule(IModuleSocket *moduleSocket) { CModuleSocket *sock = dynamic_cast(moduleSocket); nlassert(sock != NULL); @@ -443,7 +443,7 @@ namespace NLNET * The call is blocking until receptions of the operation * result message (or a module down) */ - void CModuleBase::invokeModuleOperation(IModuleProxy *destModule, const NLNET::CMessage &opMsg, NLNET::CMessage &resultMsg) throw (EInvokeFailed) + void CModuleBase::invokeModuleOperation(IModuleProxy *destModule, const NLNET::CMessage &opMsg, NLNET::CMessage &resultMsg) { H_AUTO(CModuleBase_invokeModuleOperation); diff --git a/code/nel/src/net/module_gateway_transport.cpp b/code/nel/src/net/module_gateway_transport.cpp index d9029285f..08ff51eeb 100644 --- a/code/nel/src/net/module_gateway_transport.cpp +++ b/code/nel/src/net/module_gateway_transport.cpp @@ -184,13 +184,13 @@ namespace NLNET } } - void onCommand(const CMessage &/* command */) throw (EInvalidCommand) + void onCommand(const CMessage &/* command */) { // nothing done for now throw EInvalidCommand(); } /// The gateway send a textual command to the transport - bool onCommand(const TParsedCommandLine &command) throw (EInvalidCommand) + bool onCommand(const TParsedCommandLine &command) { if (command.SubParams.size() < 1) throw EInvalidCommand(); @@ -218,7 +218,7 @@ namespace NLNET } /// Open the server by starting listing for incoming connection on the specified port - void openServer(uint16 port) throw (ETransportError) + void openServer(uint16 port) { if (_CallbackServer.get() != NULL) throw ETransportError("openServer : The server is already open"); @@ -607,13 +607,13 @@ namespace NLNET } } - void onCommand(const CMessage &/* command */) throw (EInvalidCommand) + void onCommand(const CMessage &/* command */) { // nothing done for now throw EInvalidCommand(); } /// The gateway send a textual command to the transport - bool onCommand(const TParsedCommandLine &command) throw (EInvalidCommand) + bool onCommand(const TParsedCommandLine &command) { if (command.SubParams.size() < 1) throw EInvalidCommand(); diff --git a/code/nel/src/net/module_l5_transport.cpp b/code/nel/src/net/module_l5_transport.cpp index 5eddabc9f..e902263c7 100644 --- a/code/nel/src/net/module_l5_transport.cpp +++ b/code/nel/src/net/module_l5_transport.cpp @@ -218,13 +218,13 @@ namespace NLNET } } - void onCommand(const CMessage &/* command */) throw (EInvalidCommand) + void onCommand(const CMessage &/* command */) { // nothing done for now throw EInvalidCommand(); } /// The gateway send a textual command to the transport - bool onCommand(const TParsedCommandLine &command) throw (EInvalidCommand) + bool onCommand(const TParsedCommandLine &command) { if (command.SubParams.size() < 1) throw EInvalidCommand(); @@ -255,7 +255,7 @@ namespace NLNET /// Open the server by establishing route with all known services - void open(const std::string &subNetName) throw (ETransportError) + void open(const std::string &subNetName) { H_AUTO(L5_open); diff --git a/code/nel/tools/3d/object_viewer/particle_workspace.h b/code/nel/tools/3d/object_viewer/particle_workspace.h index 694aab986..3508746d5 100644 --- a/code/nel/tools/3d/object_viewer/particle_workspace.h +++ b/code/nel/tools/3d/object_viewer/particle_workspace.h @@ -186,7 +186,7 @@ public: * * \return pointer to new node, or NULL if already inserted */ - CNode *addNode(const std::string &filenameWithFullPath) throw( NLMISC::Exception); + CNode *addNode(const std::string &filenameWithFullPath); // remove a node by its index void removeNode(uint index); // remove a node by its pointer diff --git a/code/ryzom/server/src/ai_service/ai_script_comp.cpp b/code/ryzom/server/src/ai_service/ai_script_comp.cpp index 87cbb939d..d076e6832 100644 --- a/code/ryzom/server/src/ai_service/ai_script_comp.cpp +++ b/code/ryzom/server/src/ai_service/ai_script_comp.cpp @@ -1066,7 +1066,7 @@ void CFightScript::add(CFightScriptCompReader *reader) } -CFightScriptCompReader *CFightScriptCompReader::getScriptReader (const string &str) throw (ReadFightActionException) +CFightScriptCompReader *CFightScriptCompReader::getScriptReader (const string &str) { CFightScript::TFightScriptMap::iterator it=CFightScript::_ScriptCompList.find(str); if (it==CFightScript::_ScriptCompList.end()) diff --git a/code/ryzom/server/src/ai_service/script_compiler.cpp b/code/ryzom/server/src/ai_service/script_compiler.cpp index 7ba10f149..bafdefd92 100644 --- a/code/ryzom/server/src/ai_service/script_compiler.cpp +++ b/code/ryzom/server/src/ai_service/script_compiler.cpp @@ -1279,7 +1279,7 @@ static void displayErrorLinesForIndex(const string &text, size_t &index) } -bool CCompiler::getNextToken(const string &text, size_t &index, string &tokenName, string &textValue) throw (EScriptError) +bool CCompiler::getNextToken(const string &text, size_t &index, string &tokenName, string &textValue) { char c=text.at(index); while (c==' '||c=='\n'||c=='\r'||c=='\t') // to avoid blanks, returns and Tabs. diff --git a/code/ryzom/server/src/entities_game_service/entity_manager/entity_base.cpp b/code/ryzom/server/src/entities_game_service/entity_manager/entity_base.cpp index 374b00295..069933e2b 100644 --- a/code/ryzom/server/src/entities_game_service/entity_manager/entity_base.cpp +++ b/code/ryzom/server/src/entities_game_service/entity_manager/entity_base.cpp @@ -394,7 +394,7 @@ void CEntityBase::setTarget( const NLMISC::CEntityId& targetId, bool sendMessage // lookupStat : // //--------------------------------------------------- -sint32& CEntityBase::lookupStat( const string& var ) throw (CEntityBase::EInvalidStat) +sint32& CEntityBase::lookupStat( const string& var) { // TODO Alain: optimize this... uint i; @@ -562,7 +562,7 @@ sint32& CEntityBase::lookupStat( const string& var ) throw (CEntityBase::EInvali // lookupStat for Characteristics: // //--------------------------------------------------- -sint32& CEntityBase::lookupStat( CHARACTERISTICS::TCharacteristics c, SCharacteristicsAndScores::TCharacteristicsAndScoreSubType st ) throw (CEntityBase::EInvalidStat) +sint32& CEntityBase::lookupStat( CHARACTERISTICS::TCharacteristics c, SCharacteristicsAndScores::TCharacteristicsAndScoreSubType st) { if( c < CHARACTERISTICS::NUM_CHARACTERISTICS ) { @@ -601,7 +601,7 @@ sint32& CEntityBase::lookupStat( CHARACTERISTICS::TCharacteristics c, SCharacter // lookupStat for Scores: // //--------------------------------------------------- -sint32& CEntityBase::lookupStat( SCORES::TScores score, SCharacteristicsAndScores::TCharacteristicsAndScoreSubType st ) throw (CEntityBase::EInvalidStat) +sint32& CEntityBase::lookupStat( SCORES::TScores score, SCharacteristicsAndScores::TCharacteristicsAndScoreSubType st) { if( score < SCORES::NUM_SCORES ) { @@ -640,7 +640,7 @@ sint32& CEntityBase::lookupStat( SCORES::TScores score, SCharacteristicsAndScore // lookupStat for Skills: // //--------------------------------------------------- -sint32& CEntityBase::lookupStat( SKILLS::ESkills skill, SSkill::ESkillSubType st ) throw (CEntityBase::EInvalidStat) +sint32& CEntityBase::lookupStat( SKILLS::ESkills skill, SSkill::ESkillSubType st) { /* enum ESkillSubType { @@ -675,7 +675,7 @@ sint32& CEntityBase::lookupStat( SKILLS::ESkills skill, SSkill::ESkillSubType st // lookupStat for SpecialModifiers: // //--------------------------------------------------- -sint32& CEntityBase::lookupStat( CSpecialModifiers::ESpecialModifiers sm ) throw (CEntityBase::EInvalidStat) +sint32& CEntityBase::lookupStat( CSpecialModifiers::ESpecialModifiers sm) { switch( sm ) { @@ -738,7 +738,7 @@ sint32& CEntityBase::lookupStat( CSpecialModifiers::ESpecialModifiers sm ) throw throw CEntityBase::EInvalidStat() ; } // lookupStat // -const sint32& CEntityBase::lookupStat( CSpecialModifiers::ESpecialModifiers sm ) const throw (CEntityBase::EInvalidStat) +const sint32& CEntityBase::lookupStat( CSpecialModifiers::ESpecialModifiers sm) const { return const_cast(this)->lookupStat(sm); } diff --git a/code/ryzom/server/src/entities_game_service/shop_type/item_for_sale.cpp b/code/ryzom/server/src/entities_game_service/shop_type/item_for_sale.cpp index 2844db92c..c2464c0ee 100644 --- a/code/ryzom/server/src/entities_game_service/shop_type/item_for_sale.cpp +++ b/code/ryzom/server/src/entities_game_service/shop_type/item_for_sale.cpp @@ -93,7 +93,7 @@ void CItemForSale::setAvailable( bool a ) } //----------------------------------------------------------------------------- -//void CItemForSale::serial(NLMISC::IStream &f) throw(NLMISC::EStream ) +//void CItemForSale::serial(NLMISC::IStream &f) //{ // f.serial( _PriceInfo ); // f.serial( _RetirePrice ); diff --git a/code/ryzom/server/src/entities_game_service/shop_type/item_for_sale.h b/code/ryzom/server/src/entities_game_service/shop_type/item_for_sale.h index 3fffe22e7..7387a9a10 100644 --- a/code/ryzom/server/src/entities_game_service/shop_type/item_for_sale.h +++ b/code/ryzom/server/src/entities_game_service/shop_type/item_for_sale.h @@ -312,7 +312,7 @@ public: void setContinent( CONTINENT::TContinent ) {} // serial - void serial(NLMISC::IStream &f) throw(NLMISC::EStream ) {} + void serial(NLMISC::IStream &f) {} // set item for sale void itemForSale( uint32 price, uint32 retirePrice, CGameItemPtr item, uint32 quantity, const NLMISC::CEntityId& id, CONTINENT::TContinent continent, uint32 identifier ) {} diff --git a/code/ryzom/server/src/entities_game_service/shop_type/items_for_sale.cpp b/code/ryzom/server/src/entities_game_service/shop_type/items_for_sale.cpp index c247b93ac..61538b674 100644 --- a/code/ryzom/server/src/entities_game_service/shop_type/items_for_sale.cpp +++ b/code/ryzom/server/src/entities_game_service/shop_type/items_for_sale.cpp @@ -96,7 +96,7 @@ NLMISC::CSmartPtr< IItemTrade > CItemsForSale::removeItem( uint32 identifier, ui } //----------------------------------------------------------------------------- -void CItemsForSale::serial(NLMISC::IStream &f) throw(NLMISC::EStream ) +void CItemsForSale::serial(NLMISC::IStream &f) { // YOYO: we should not be here. OLD serial was very buggy. // AlainS ensure me this code is no more called (no write, use PDS instead, and old version diff --git a/code/ryzom/server/src/frontend_service/gateway_fes_transport.cpp b/code/ryzom/server/src/frontend_service/gateway_fes_transport.cpp index a24fd8d51..40cb4dde2 100644 --- a/code/ryzom/server/src/frontend_service/gateway_fes_transport.cpp +++ b/code/ryzom/server/src/frontend_service/gateway_fes_transport.cpp @@ -179,13 +179,13 @@ public: } } - void onCommand(const CMessage &command) throw (EInvalidCommand) + void onCommand(const CMessage &command) { // nothing done for now throw EInvalidCommand(); } /// The gateway send a textual command to the transport - bool onCommand(const TParsedCommandLine &command) throw (EInvalidCommand) + bool onCommand(const TParsedCommandLine &command) { if (command.SubParams.size() < 1) throw EInvalidCommand(); @@ -212,7 +212,7 @@ public: } /// Open the server by intercepting client gateway message - void openServer() throw (ETransportError) + void openServer() { if (OpenTransport() != NULL) throw ETransportError("openServer : a transport is already open !"); diff --git a/code/ryzom/server/src/input_output_service/chat_manager.h b/code/ryzom/server/src/input_output_service/chat_manager.h index 544dbfa2c..658a72d81 100644 --- a/code/ryzom/server/src/input_output_service/chat_manager.h +++ b/code/ryzom/server/src/input_output_service/chat_manager.h @@ -145,7 +145,7 @@ public : * \param gId is the group's id * \return the group */ - CChatGroup& getGroup( const TGroupId& gId );// throw (EChatGroup); + CChatGroup& getGroup( const TGroupId& gId ); /** * Transmit a chat message diff --git a/code/ryzom/tools/server/build_spell_sheet/build_spell_sheet.cpp b/code/ryzom/tools/server/build_spell_sheet/build_spell_sheet.cpp index 5e892410b..6a8383485 100644 --- a/code/ryzom/tools/server/build_spell_sheet/build_spell_sheet.cpp +++ b/code/ryzom/tools/server/build_spell_sheet/build_spell_sheet.cpp @@ -65,7 +65,7 @@ public: return true; } public: - void serial(IStream &f) throw(EStream) + void serial(IStream &f) { for(uint k = 0; k < NumUserParams; ++k) { @@ -87,7 +87,7 @@ public: { return PSName.empty() && UserParams.empty(); } - void serial(IStream &f) throw(EStream) + void serial(IStream &f) { if (!PSName.empty()) writeAtom(f, "PSName", PSName); UserParams.serial(f); @@ -111,7 +111,7 @@ public: } return true; } - void serial(IStream &f) throw(EStream) + void serial(IStream &f) { for(uint k = 0; k < NumFX; ++k) { diff --git a/code/studio/src/plugins/object_viewer/particle_system/particle_node.h b/code/studio/src/plugins/object_viewer/particle_system/particle_node.h index 033802a44..7b164580d 100644 --- a/code/studio/src/plugins/object_viewer/particle_system/particle_node.h +++ b/code/studio/src/plugins/object_viewer/particle_system/particle_node.h @@ -283,7 +283,7 @@ public: /// The node is in the 'unloaded' state, so caller must load it afterward. /// NB : no lookup is done, full path must be provided. /// @return pointer to new node, or NULL if already inserted - CWorkspaceNode *addNode(const std::string &filenameWithFullPath) throw( NLMISC::Exception); + CWorkspaceNode *addNode(const std::string &filenameWithFullPath); /// Remove a node by it's index void removeNode(uint index); From 8a1588c1471b3161248bee5f0b6d3555bb02ecb9 Mon Sep 17 00:00:00 2001 From: kervala Date: Wed, 8 Aug 2018 20:55:14 +0200 Subject: [PATCH 082/303] Fixed: Also use SSL context callback when manually using Windows CA certs --HG-- branch : develop --- code/nel/src/gui/curl_certificates.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/code/nel/src/gui/curl_certificates.cpp b/code/nel/src/gui/curl_certificates.cpp index f06d92608..5cec3c511 100644 --- a/code/nel/src/gui/curl_certificates.cpp +++ b/code/nel/src/gui/curl_certificates.cpp @@ -88,12 +88,9 @@ namespace NLGUI addCertificatesFrom("CA"); addCertificatesFrom("AuthRoot"); addCertificatesFrom("ROOT"); - - // we manually loaded native CA Certs, don't need to use custom certificates - isUsingOpenSSLBackend = false; -#else - isUsingOpenSSLBackend = true; #endif + + isUsingOpenSSLBackend = true; } else { From 443cc7df65aa5fcc070624fa8b1bbe523b6b9aa2 Mon Sep 17 00:00:00 2001 From: kervala Date: Wed, 8 Aug 2018 20:55:40 +0200 Subject: [PATCH 083/303] Fixed: Don't throw an exception when a certifcate can't be found --HG-- branch : develop --- code/nel/src/gui/curl_certificates.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/src/gui/curl_certificates.cpp b/code/nel/src/gui/curl_certificates.cpp index 5cec3c511..7d26e7e5a 100644 --- a/code/nel/src/gui/curl_certificates.cpp +++ b/code/nel/src/gui/curl_certificates.cpp @@ -144,7 +144,7 @@ namespace NLGUI FilesList.push_back(cert); // look for certificate in search paths - string path = CPath::lookup(cert); + string path = CPath::lookup(cert, false); nlinfo("Cert path '%s'", path.c_str()); if (path.empty()) From facc5f6d288724fce12c9ab03810032249e2f037 Mon Sep 17 00:00:00 2001 From: kervala Date: Thu, 9 Aug 2018 14:27:42 +0200 Subject: [PATCH 084/303] Fixed: Warnings, throw(type) deprecated in C++11 and removed in C++17 --HG-- branch : develop --- code/nel/include/nel/misc/mem_stream.h | 2 +- code/nel/include/nel/net/module.h | 2 +- .../src/3d/driver/direct3d/driver_direct3d.h | 2 +- code/nel/src/misc/class_registry.cpp | 4 +-- .../3d/object_viewer/particle_workspace.cpp | 2 +- .../server/src/ai_service/ai_script_comp.cpp | 32 +++++++++---------- .../server/src/ai_service/ai_script_comp.h | 6 ++-- .../src/input_output_service/chat_manager.h | 2 +- 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/code/nel/include/nel/misc/mem_stream.h b/code/nel/include/nel/misc/mem_stream.h index a9e8aacfc..4222e1672 100644 --- a/code/nel/include/nel/misc/mem_stream.h +++ b/code/nel/include/nel/misc/mem_stream.h @@ -210,7 +210,7 @@ public: * \return the new offset regarding from the origin. * \see ESeekNotSupported SeekOrigin seek */ - virtual sint32 getPos () const throw(EStream) + virtual sint32 getPos () const { return sint32(_Buffer.Pos); } diff --git a/code/nel/include/nel/net/module.h b/code/nel/include/nel/net/module.h index 0b5b158d2..05cd48fed 100644 --- a/code/nel/include/nel/net/module.h +++ b/code/nel/include/nel/net/module.h @@ -780,7 +780,7 @@ namespace NLNET bool initModule(const TParsedCommandLine &initInfo); void plugModule(IModuleSocket *moduleSocket); - void unplugModule(IModuleSocket *moduleSocket) throw (EModuleNotPluggedHere); + void unplugModule(IModuleSocket *moduleSocket); void getPluggedSocketList(std::vector &resultList); void invokeModuleOperation(IModuleProxy *destModule, const NLNET::CMessage &opMsg, NLNET::CMessage &resultMsg); void _onModuleUp(IModuleProxy *removedProxy); diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d.h b/code/nel/src/3d/driver/direct3d/driver_direct3d.h index 6621ab6cb..51c21bbc9 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.h +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.h @@ -849,7 +849,7 @@ public: // Mode initialisation, requests virtual bool init (uintptr_t windowIcon = 0, emptyProc exitFunc = 0); - virtual bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable + virtual bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable); virtual bool release(); virtual bool setMode(const GfxMode& mode); virtual bool getModes(std::vector &modes); diff --git a/code/nel/src/misc/class_registry.cpp b/code/nel/src/misc/class_registry.cpp index 91c603c90..c703e45d0 100644 --- a/code/nel/src/misc/class_registry.cpp +++ b/code/nel/src/misc/class_registry.cpp @@ -49,7 +49,7 @@ void CClassRegistry::release() } // ====================================================================================================== -IClassable *CClassRegistry::create(const string &className) throw(ERegistry) +IClassable *CClassRegistry::create(const string &className) { init(); @@ -72,7 +72,7 @@ IClassable *CClassRegistry::create(const string &className) throw(ERegistry) } // ====================================================================================================== -void CClassRegistry::registerClass(const string &className, IClassable* (*creator)(), const string &typeidCheck) throw(ERegistry) +void CClassRegistry::registerClass(const string &className, IClassable* (*creator)(), const string &typeidCheck) { init(); diff --git a/code/nel/tools/3d/object_viewer/particle_workspace.cpp b/code/nel/tools/3d/object_viewer/particle_workspace.cpp index 43be30812..1a289d2b0 100644 --- a/code/nel/tools/3d/object_viewer/particle_workspace.cpp +++ b/code/nel/tools/3d/object_viewer/particle_workspace.cpp @@ -357,7 +357,7 @@ void CParticleWorkspace::setName(const std::string &name) //*********************************************************************************************** -CParticleWorkspace::CNode *CParticleWorkspace::addNode(const std::string &filenameWithFullPath) throw( NLMISC::EStream) +CParticleWorkspace::CNode *CParticleWorkspace::addNode(const std::string &filenameWithFullPath) { nlassert(_OV); // Check that file is not already inserted diff --git a/code/ryzom/server/src/ai_service/ai_script_comp.cpp b/code/ryzom/server/src/ai_service/ai_script_comp.cpp index d076e6832..69c4c9bab 100644 --- a/code/ryzom/server/src/ai_service/ai_script_comp.cpp +++ b/code/ryzom/server/src/ai_service/ai_script_comp.cpp @@ -83,7 +83,7 @@ std::string CFightSelectFilter::toString() const -CFightScriptComp *CFightSelectFilterReader::create (const std::string &inStr) throw (ReadFightActionException) +CFightScriptComp *CFightSelectFilterReader::create (const std::string &inStr) { std::vector params; explodeSubStrings(inStr, params, -1); @@ -151,7 +151,7 @@ public: CFightOnceReader() {} virtual ~CFightOnceReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) + CFightScriptComp *create (const std::string &inStr) { vector params; explodeSubStrings(inStr, params, -1); @@ -229,7 +229,7 @@ public: CFightTimedFilterReader() {} virtual ~CFightTimedFilterReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) + CFightScriptComp *create (const std::string &inStr) { vector params; explodeSubStrings(inStr, params, -1); @@ -302,7 +302,7 @@ public: CFightHPLessFilterReader() {} virtual ~CFightHPLessFilterReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) + CFightScriptComp *create (const std::string &inStr) { vector params; explodeSubStrings(inStr, params, -1); @@ -372,7 +372,7 @@ public: CFightHPMoreFilterReader() {} virtual ~CFightHPMoreFilterReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) + CFightScriptComp *create (const std::string &inStr) { vector params; explodeSubStrings(inStr, params, -1); @@ -443,7 +443,7 @@ public: CFightRandomFilterReader() {} virtual ~CFightRandomFilterReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) + CFightScriptComp *create (const std::string &inStr) { vector params; explodeSubStrings(inStr, params, -1); @@ -523,7 +523,7 @@ public: CFightSendActionReader() {} virtual ~CFightSendActionReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) + CFightScriptComp *create (const std::string &inStr) { vector strings; explodeSubStrings(inStr, strings, -1); @@ -588,7 +588,7 @@ public: CFightSendSelfActionReader() {} virtual ~CFightSendSelfActionReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) + CFightScriptComp *create (const std::string &inStr) { vector strings; explodeSubStrings(inStr, strings, -1); @@ -647,7 +647,7 @@ public: CFightAggroBlockReader() {} virtual ~CFightAggroBlockReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) + CFightScriptComp *create (const std::string &inStr) { vector strings; explodeSubStrings(inStr, strings, -1); @@ -705,7 +705,7 @@ public: CFightAggroChangeReader() {} virtual ~CFightAggroChangeReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) + CFightScriptComp *create (const std::string &inStr) { return new CFightAggroChange(); } @@ -751,7 +751,7 @@ public: CFightDamageCoefReader() {} virtual ~CFightDamageCoefReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) + CFightScriptComp *create (const std::string &inStr) { vector strings; explodeSubStrings(inStr, strings, -1); @@ -818,7 +818,7 @@ public: CFightGroupDamageCoefReader() {} virtual ~CFightGroupDamageCoefReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) + CFightScriptComp *create (const std::string &inStr) { vector strings; explodeSubStrings(inStr, strings, -1); @@ -871,7 +871,7 @@ public: CFightDamageSpeedCoefReader() {} virtual ~CFightDamageSpeedCoefReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) + CFightScriptComp *create (const std::string &inStr) { vector strings; explodeSubStrings(inStr, strings, -1); @@ -933,7 +933,7 @@ public: CFightSetRandomTargetReader() {} virtual ~CFightSetRandomTargetReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) + CFightScriptComp *create (const std::string &inStr) { vector strings; explodeSubStrings(inStr, strings, -1); @@ -1003,7 +1003,7 @@ public: CFightMultReader() {} virtual ~CFightMultReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) + CFightScriptComp *create (const std::string &inStr) { vector params; explodeSubStrings(inStr, params, -1); @@ -1075,7 +1075,7 @@ CFightScriptCompReader *CFightScriptCompReader::getScriptReader (const string &s return &(*(it->second)); } -CFightScriptComp *CFightScriptCompReader::createScriptComp (const string &str) throw (ReadFightActionException) +CFightScriptComp *CFightScriptCompReader::createScriptComp (const string &str) { string scriptCompName; { diff --git a/code/ryzom/server/src/ai_service/ai_script_comp.h b/code/ryzom/server/src/ai_service/ai_script_comp.h index 0b02cc722..a35253d66 100644 --- a/code/ryzom/server/src/ai_service/ai_script_comp.h +++ b/code/ryzom/server/src/ai_service/ai_script_comp.h @@ -51,12 +51,12 @@ public: {} virtual ~CFightScriptCompReader() {} - virtual CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException) = 0; + virtual CFightScriptComp *create (const std::string &inStr) = 0; virtual std::string getName () const =0; static CFightScriptCompReader *getScriptReader (const std::string &str); - static CFightScriptComp *createScriptComp (const std::string &str) throw (ReadFightActionException); + static CFightScriptComp *createScriptComp (const std::string &str) protected: private: }; @@ -116,7 +116,7 @@ public: CFightSelectFilterReader() {} virtual ~CFightSelectFilterReader() {} - CFightScriptComp *create (const std::string &inStr) throw (ReadFightActionException); + CFightScriptComp *create (const std::string &inStr) std::string getName () const { return std::string("SELECT"); diff --git a/code/ryzom/server/src/input_output_service/chat_manager.h b/code/ryzom/server/src/input_output_service/chat_manager.h index 658a72d81..a64b68d52 100644 --- a/code/ryzom/server/src/input_output_service/chat_manager.h +++ b/code/ryzom/server/src/input_output_service/chat_manager.h @@ -101,7 +101,7 @@ public : * Get the client infos * \param id is the client character id */ - CChatClient& getClient( const TDataSetRow& id ); //throw (EChatClient); + CChatClient& getClient( const TDataSetRow& id ); /** * Return a reference on the static database From f39c6ed3c64a205475ada0dff0da819808396c9d Mon Sep 17 00:00:00 2001 From: kervala Date: Thu, 9 Aug 2018 14:30:13 +0200 Subject: [PATCH 085/303] Fixed: Warnings --HG-- branch : develop --- code/nel/src/gui/group_html.cpp | 4 +-- code/ryzom/client/src/item_group_manager.cpp | 26 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 6f0e612c9..9c022934a 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -459,7 +459,7 @@ namespace NLGUI #endif // Display cached image while downloading new - if (type != TImageType::OverImage && CFile::fileExists(dest)) + if (type != OverImage && CFile::fileExists(dest)) { setImage(img, dest, type); setImageSize(img, style); @@ -4711,7 +4711,7 @@ namespace NLGUI if (overBitmap != normalBitmap) { over = localImageName(overBitmap); - addImageDownload(overBitmap, ctrlButton, style, TImageType::OverImage); + addImageDownload(overBitmap, ctrlButton, style, OverImage); } } diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index e72f2d730..d4a7a4ba0 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -83,8 +83,8 @@ void CItemGroup::addItem(sint32 createTime, sint32 serial, SLOT_EQUIPMENT::TSlot nldebug("Not adding duplicate item, createTime: %d, serial: %d", createTime, serial); //In this case, we are adding the duplicate item for a 2 hands item //If it's saved as a left hand item, save it as a right hand item instead (so we have only 1 correct item) - if(Items[i].slot == SLOT_EQUIPMENT::TSlotEquipment::HANDL && slot == SLOT_EQUIPMENT::TSlotEquipment::HANDR) - Items[i].slot = SLOT_EQUIPMENT::TSlotEquipment::HANDR; + if(Items[i].slot == SLOT_EQUIPMENT::HANDL && slot == SLOT_EQUIPMENT::HANDR) + Items[i].slot = SLOT_EQUIPMENT::HANDR; return; } } @@ -389,7 +389,7 @@ CItemGroup CItemGroupManager::migrateGroup(CItemGroup group) //Get all matching items from all inventory CItemGroup out; out.name = group.name; - for (int i=0; i < INVENTORIES::TInventory::NUM_ALL_INVENTORY; i++) + for (int i=0; i < INVENTORIES::NUM_ALL_INVENTORY; i++) { INVENTORIES::TInventory inventory = (INVENTORIES::TInventory)i; std::vector items = matchingItems(&group, inventory); @@ -501,7 +501,7 @@ bool CItemGroupManager::moveGroup(std::string name, INVENTORIES::TInventory dst) std::string moveParams = "to=lists|nblist=1|listsheet0=" + toDbPath(dst); // Grab all matching item from all available inventory and put it in dst - for (int i=0; i< INVENTORIES::TInventory::NUM_ALL_INVENTORY; i ++) + for (int i=0; i< INVENTORIES::NUM_ALL_INVENTORY; i ++) { INVENTORIES::TInventory inventory = (INVENTORIES::TInventory)i; if (inventory != dst && pIM->isInventoryAvailable(inventory)) @@ -531,7 +531,7 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) return false; } - if(pullBefore) moveGroup(name, INVENTORIES::TInventory::bag); + if(pullBefore) moveGroup(name, INVENTORIES::bag); //Start by unequipping all slot that user wants to unequip for(int i=0; i < group->removeBeforeEquip.size(); i++) { @@ -555,7 +555,7 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) {ITEM_TYPE::RING, false}, }; std::vector duals; - std::vector items = matchingItems(group, INVENTORIES::TInventory::bag); + std::vector items = matchingItems(group, INVENTORIES::bag); for(int i=0; i < items.size(); i++) { CInventoryItem item = items[i]; @@ -713,19 +713,19 @@ std::string CItemGroupManager::toDbPath(INVENTORIES::TInventory inventory) { switch(inventory) { - case INVENTORIES::TInventory::bag: + case INVENTORIES::bag: return LIST_BAG_TEXT; break; - case INVENTORIES::TInventory::pet_animal1: + case INVENTORIES::pet_animal1: return LIST_PA0_TEXT; break; - case INVENTORIES::TInventory::pet_animal2: + case INVENTORIES::pet_animal2: return LIST_PA1_TEXT; break; - case INVENTORIES::TInventory::pet_animal3: + case INVENTORIES::pet_animal3: return LIST_PA2_TEXT; break; - case INVENTORIES::TInventory::pet_animal4: + case INVENTORIES::pet_animal4: return LIST_PA3_TEXT; break; - case INVENTORIES::TInventory::player_room: + case INVENTORIES::player_room: return LIST_ROOM_TEXT;break; - case INVENTORIES::TInventory::guild: + case INVENTORIES::guild: return ClientCfg.ItemGroupAllowGuild ? LIST_GUILD_TEXT : ""; break; default: return ""; From 78670dfdda3f33c4151890747e6ef8624e7181b8 Mon Sep 17 00:00:00 2001 From: kervala Date: Thu, 9 Aug 2018 14:31:17 +0200 Subject: [PATCH 086/303] Fixed: Compilation with VC++ 2010 --HG-- branch : develop --- code/nel/include/nel/misc/types_nl.h | 3 +++ .../src/interface_v3/chat_text_manager.cpp | 16 +++++++++++++++- code/ryzom/client/src/item_group_manager.cpp | 10 ++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/code/nel/include/nel/misc/types_nl.h b/code/nel/include/nel/misc/types_nl.h index 71702bce5..2851759de 100644 --- a/code/nel/include/nel/misc/types_nl.h +++ b/code/nel/include/nel/misc/types_nl.h @@ -79,6 +79,9 @@ # elif _MSC_VER >= 1600 # define NL_COMP_VC10 # define NL_COMP_VC_VERSION 100 +# ifdef _HAS_CPP0X +# undef _HAS_CPP0X // VC++ 2010 doesn't implement C++11 stuff we need +# endif # elif _MSC_VER >= 1500 # define NL_COMP_VC9 # define NL_COMP_VC_VERSION 90 diff --git a/code/ryzom/client/src/interface_v3/chat_text_manager.cpp b/code/ryzom/client/src/interface_v3/chat_text_manager.cpp index e21872018..a9a682bf1 100644 --- a/code/ryzom/client/src/interface_v3/chat_text_manager.cpp +++ b/code/ryzom/client/src/interface_v3/chat_text_manager.cpp @@ -187,7 +187,21 @@ static inline bool isUrlTag(const ucstring &s, ucstring::size_type index, ucstri if (isUrl && i > 0 && !markdown) { // '}' is in the list because of color tags, ie "@{FFFF}http://..." - const vector chars {' ', '"', '\'', '(', '[', '}'}; +#ifdef NL_ISO_CPP0X_AVAILABLE + const vector chars{ ' ', '"', '\'', '(', '[', '}' }; +#else + static std::vector chars; + + if (chars.empty()) + { + chars.push_back(' '); + chars.push_back('"'); + chars.push_back('\''); + chars.push_back('('); + chars.push_back('['); + chars.push_back('}'); + } +#endif isUrl = std::find(chars.begin(), chars.end(), s[i - 1]) != chars.end(); } return isUrl; diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index d4a7a4ba0..fddba873f 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -547,6 +547,7 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) uint32 maxEquipTime = 0; +#ifdef NL_ISO_CPP0X_AVAILABLE std::map possiblyDual = { {ITEM_TYPE::ANKLET, false}, @@ -554,6 +555,15 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) {ITEM_TYPE::EARING, false}, {ITEM_TYPE::RING, false}, }; +#else + std::map possiblyDual; + + possiblyDual[ITEM_TYPE::ANKLET] = false; + possiblyDual[ITEM_TYPE::BRACELET] = false; + possiblyDual[ITEM_TYPE::EARING] = false; + possiblyDual[ITEM_TYPE::RING] = false; +#endif + std::vector duals; std::vector items = matchingItems(group, INVENTORIES::bag); for(int i=0; i < items.size(); i++) From cc6ed038b91b1e2b811f972ea74aca5bfc4237f8 Mon Sep 17 00:00:00 2001 From: kervala Date: Thu, 9 Aug 2018 14:32:00 +0200 Subject: [PATCH 087/303] Fixed: Don't use memory aligned functions while debugging with VC++ --HG-- branch : develop --- code/nel/include/nel/misc/types_nl.h | 14 +++++++++++--- code/nel/src/misc/common.cpp | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/code/nel/include/nel/misc/types_nl.h b/code/nel/include/nel/misc/types_nl.h index 2851759de..6431701fe 100644 --- a/code/nel/include/nel/misc/types_nl.h +++ b/code/nel/include/nel/misc/types_nl.h @@ -412,8 +412,16 @@ typedef unsigned int uint; // at least 32bits (depend of processor) #define NL_DEFAULT_MEMORY_ALIGNMENT 16 #define NL_ALIGN_SSE2 NL_ALIGN(NL_DEFAULT_MEMORY_ALIGNMENT) -#ifndef NL_CPU_X86_64 +#ifdef NL_CPU_X86_64 // on x86_64, new and delete are already aligned on 16 bytes +#elif (defined(NL_COMP_VC) && defined(NL_DEBUG)) +// don't use aligned memory if debugging with VC++ in 32 bits +#else +// use aligned memory in all other cases +#define NL_USE_ALIGNED_MEMORY_OPERATORS +#endif + +#ifdef NL_USE_ALIGNED_MEMORY_OPERATORS #ifdef NL_NO_EXCEPTION_SPECS extern void *operator new(size_t size); @@ -425,9 +433,9 @@ extern void *operator new(size_t size) throw(std::bad_alloc); extern void *operator new[](size_t size) throw(std::bad_alloc); extern void operator delete(void *p) throw(); extern void operator delete[](void *p) throw(); -#endif +#endif /* NL_NO_EXCEPTION_SPECS */ -#endif +#endif /* NL_USE_ALIGNED_MEMORY_OPERATORS */ #else /* NL_HAS_SSE2 */ diff --git a/code/nel/src/misc/common.cpp b/code/nel/src/misc/common.cpp index db605f4f1..599f3cfb2 100644 --- a/code/nel/src/misc/common.cpp +++ b/code/nel/src/misc/common.cpp @@ -80,7 +80,7 @@ extern "C" long _ftol2( double dblSource ) { return _ftol( dblSource ); } #endif // !NL_COMP_MINGW -#if defined(NL_HAS_SSE2) && !defined(NL_CPU_X86_64) +#ifdef NL_USE_ALIGNED_MEMORY_OPERATORS #ifdef NL_NO_EXCEPTION_SPECS void *operator new(size_t size) From dcaf417aeea1d778444671eedb635f6d927ed69f Mon Sep 17 00:00:00 2001 From: kervala Date: Thu, 9 Aug 2018 14:34:28 +0200 Subject: [PATCH 088/303] Changed: Minor changes --HG-- branch : develop --- code/nel/src/3d/water_height_map.cpp | 2 +- code/ryzom/server/src/ai_service/event_reaction.h | 2 +- code/ryzom/server/src/ai_service/event_reaction_include.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/nel/src/3d/water_height_map.cpp b/code/nel/src/3d/water_height_map.cpp index 5f67ffce3..6fe88a8bc 100644 --- a/code/nel/src/3d/water_height_map.cpp +++ b/code/nel/src/3d/water_height_map.cpp @@ -677,7 +677,7 @@ void CWaterHeightMap::setWaves(float intensity, float period, uint radius, bool void CWaterHeightMap::serial(NLMISC::IStream &f) { f.xmlPushBegin("WaterHeightMap"); - f.xmlSetAttrib ("NAME") ; + f.xmlSetAttrib ("NAME"); f.serial (_Name); f.xmlPushEnd(); (void)f.serialVersion(0); diff --git a/code/ryzom/server/src/ai_service/event_reaction.h b/code/ryzom/server/src/ai_service/event_reaction.h index 1f92d3047..57dcf22d0 100644 --- a/code/ryzom/server/src/ai_service/event_reaction.h +++ b/code/ryzom/server/src/ai_service/event_reaction.h @@ -90,7 +90,7 @@ public: // the following routine shouldn't be needed it should be superceded by a better alternative // in the event manager template - bool testCompatibility(CStateInstance *const stateInstance, const TState *const state) const; + bool testCompatibility(const CStateInstance *stateInstance, const TState *state) const protected: // protected data --------------------------------------------------- diff --git a/code/ryzom/server/src/ai_service/event_reaction_include.h b/code/ryzom/server/src/ai_service/event_reaction_include.h index 3c44b03dc..04fd2c16f 100644 --- a/code/ryzom/server/src/ai_service/event_reaction_include.h +++ b/code/ryzom/server/src/ai_service/event_reaction_include.h @@ -28,7 +28,7 @@ #include "continent.h"*/ template -bool CAIEventReaction::testCompatibility(CStateInstance *const stateInstance, const TState *const state) const +bool CAIEventReaction::testCompatibility(const CStateInstance *stateInstance, const TState *state) const { if (!stateInstance) return false; From 184d3698c99c41d8c51477a50436134c6951a9fa Mon Sep 17 00:00:00 2001 From: kervala Date: Thu, 9 Aug 2018 19:38:33 +0200 Subject: [PATCH 089/303] Fixed: Warnings, throw(type) deprecated in C++11 and removed in C++17 --HG-- branch : develop --- code/nel/include/nel/net/module.h | 15 ++++----------- code/nel/include/nel/net/module_socket.h | 22 ++++++---------------- code/nel/src/net/module.cpp | 1 - code/nel/src/net/module_gateway.cpp | 3 +-- code/nel/src/net/module_local_gateway.cpp | 4 +--- 5 files changed, 12 insertions(+), 33 deletions(-) diff --git a/code/nel/include/nel/net/module.h b/code/nel/include/nel/net/module.h index 05cd48fed..803fe458c 100644 --- a/code/nel/include/nel/net/module.h +++ b/code/nel/include/nel/net/module.h @@ -213,18 +213,14 @@ namespace NLNET * Note that a module can be plugged in several socket at the same * time, but not twice in the same socket. */ - virtual void plugModule(IModuleSocket *moduleSocket) - throw (EModuleAlreadyPluggedHere) - =0; + virtual void plugModule(IModuleSocket *moduleSocket) =0; /** Unplug this module from the specified socket. * Note that a module can be plugged in several socket at the same * time, but not twice in the same socket. * Throw an exception if the socket is not currently plug into * the specified socket. */ - virtual void unplugModule(IModuleSocket *moduleSocket) - throw (EModuleNotPluggedHere) - =0; + virtual void unplugModule(IModuleSocket *moduleSocket) =0; /** Fill resultList vector with the list of socket into * witch this module is currently plugged. * This method don't clear the result vector before filling it. @@ -448,9 +444,7 @@ namespace NLNET * This method do the job of finding a valid socket to effectively send * the message. */ - virtual void sendModuleMessage(IModule *senderModule, const NLNET::CMessage &message) - throw (EModuleNotReachable) - =0; + virtual void sendModuleMessage(IModule *senderModule, const NLNET::CMessage &message) =0; /** Return the first item of the security item list * If no security data are available, the method @@ -879,8 +873,7 @@ namespace NLNET /** Send a message to the module. */ - virtual void sendModuleMessage(IModule *senderModule, const NLNET::CMessage &message) - throw (EModuleNotReachable); + virtual void sendModuleMessage(IModule *senderModule, const NLNET::CMessage &message); virtual const TSecurityData *getFirstSecurityData() const { diff --git a/code/nel/include/nel/net/module_socket.h b/code/nel/include/nel/net/module_socket.h index f4bad56d4..a60836656 100644 --- a/code/nel/include/nel/net/module_socket.h +++ b/code/nel/include/nel/net/module_socket.h @@ -42,15 +42,11 @@ namespace NLNET * If the destination module is not accessible through this socket, * an exception is thrown. */ - virtual void sendModuleMessage(IModule *senderModule, TModuleId destModuleProxyId, const NLNET::CMessage &message ) - throw (EModuleNotPluggedHere) - =0; + virtual void sendModuleMessage(IModule *senderModule, TModuleId destModuleProxyId, const NLNET::CMessage &message) =0; /** A plugged module send a message to all the module reachable * with this socket. */ - virtual void broadcastModuleMessage(IModule *senderModule, const NLNET::CMessage &message) - throw (EModuleNotPluggedHere) - =0; + virtual void broadcastModuleMessage(IModule *senderModule, const NLNET::CMessage &message) =0; /** Fill the resultList with the list of module that are * reachable with this socket. @@ -95,21 +91,15 @@ namespace NLNET virtual void _onModulePlugged(const TModulePtr &pluggedModule); virtual void _onModuleUnplugged(const TModulePtr &pluggedModule); - virtual void _sendModuleMessage(IModule *senderModule, TModuleId destModuleProxyId, const NLNET::CMessage &message ) - throw (EModuleNotPluggedHere, NLNET::EModuleNotReachable) - =0; + virtual void _sendModuleMessage(IModule *senderModule, TModuleId destModuleProxyId, const NLNET::CMessage &message) =0; - virtual void _broadcastModuleMessage(IModule *senderModule, const NLNET::CMessage &message) - throw (EModuleNotPluggedHere) - =0; + virtual void _broadcastModuleMessage(IModule *senderModule, const NLNET::CMessage &message) =0; - virtual void sendModuleMessage(IModule *senderModule, TModuleId destModuleProxyId, const NLNET::CMessage &message ) - throw (EModuleNotPluggedHere); + virtual void sendModuleMessage(IModule *senderModule, TModuleId destModuleProxyId, const NLNET::CMessage &message); /** A plugged module send a message to all the module reachable * with this socket. */ - virtual void broadcastModuleMessage(IModule *senderModule, const NLNET::CMessage &message) - throw (EModuleNotPluggedHere); + virtual void broadcastModuleMessage(IModule *senderModule, const NLNET::CMessage &message); }; diff --git a/code/nel/src/net/module.cpp b/code/nel/src/net/module.cpp index b5707fea3..23f618973 100644 --- a/code/nel/src/net/module.cpp +++ b/code/nel/src/net/module.cpp @@ -867,7 +867,6 @@ namespace NLNET } void CModuleProxy::sendModuleMessage(IModule *senderModule, const NLNET::CMessage &message) - throw (EModuleNotReachable) { H_AUTO(CModuleProxy_sendModuleMessage); diff --git a/code/nel/src/net/module_gateway.cpp b/code/nel/src/net/module_gateway.cpp index 81ba76859..0acb4375d 100644 --- a/code/nel/src/net/module_gateway.cpp +++ b/code/nel/src/net/module_gateway.cpp @@ -1560,8 +1560,7 @@ namespace NLNET return getModuleName(); } - void _sendModuleMessage(IModule *senderModule, TModuleId destModuleProxyId, const NLNET::CMessage &message ) - throw (EModuleNotReachable, EModuleNotPluggedHere) + void _sendModuleMessage(IModule *senderModule, TModuleId destModuleProxyId, const NLNET::CMessage &message) { // the socket implementation already checked that the module is plugged here // just check that the destination module effectively from here diff --git a/code/nel/src/net/module_local_gateway.cpp b/code/nel/src/net/module_local_gateway.cpp index 3446c0663..292a6cafe 100644 --- a/code/nel/src/net/module_local_gateway.cpp +++ b/code/nel/src/net/module_local_gateway.cpp @@ -364,8 +364,7 @@ namespace NLNET return getModuleName(); } - void _sendModuleMessage(IModule *senderModule, TModuleId destModuleProxyId, const NLNET::CMessage &message ) - throw (EModuleNotReachable, EModuleNotPluggedHere) + void _sendModuleMessage(IModule *senderModule, TModuleId destModuleProxyId, const NLNET::CMessage &message) { TModuleProxies::TAToBMap::const_iterator first(_ModuleProxies.getAToBMap().begin()), last(_ModuleProxies.getAToBMap().end()); for (; first != last && first->first->getModuleProxyId() != destModuleProxyId; ++first) {} @@ -373,7 +372,6 @@ namespace NLNET throw EModuleNotReachable(); } virtual void _broadcastModuleMessage(IModule * /* senderModule */, const NLNET::CMessage &/* message */) - throw (EModuleNotPluggedHere) { nlstop; } From c13b758be9215c1d1a936134af0d2bd8a25bfd02 Mon Sep 17 00:00:00 2001 From: kervala Date: Thu, 9 Aug 2018 19:47:44 +0200 Subject: [PATCH 090/303] Fixed: Warnings, throw(type) deprecated in C++11 and removed in C++17 --HG-- branch : develop --- code/nel/include/nel/net/module.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/nel/include/nel/net/module.h b/code/nel/include/nel/net/module.h index 803fe458c..790a49199 100644 --- a/code/nel/include/nel/net/module.h +++ b/code/nel/include/nel/net/module.h @@ -261,9 +261,7 @@ namespace NLNET * The call is blocking until receptions of the operation * result message (or detection of the dest module module is down) */ - virtual void invokeModuleOperation(IModuleProxy *destModule, const NLNET::CMessage &opMsg, NLNET::CMessage &resultMsg) - throw (EInvokeFailed) - =0; + virtual void invokeModuleOperation(IModuleProxy *destModule, const NLNET::CMessage &opMsg, NLNET::CMessage &resultMsg) =0; //@} From 91fa4d3f5fba8884d5494c41ce096516e9793fcc Mon Sep 17 00:00:00 2001 From: kervala Date: Thu, 9 Aug 2018 19:54:08 +0200 Subject: [PATCH 091/303] Fixed: Warnings, throw(type) deprecated in C++11 and removed in C++17 --HG-- branch : develop --- code/nel/src/net/module_socket.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/nel/src/net/module_socket.cpp b/code/nel/src/net/module_socket.cpp index 068567761..6ea16e8d6 100644 --- a/code/nel/src/net/module_socket.cpp +++ b/code/nel/src/net/module_socket.cpp @@ -85,8 +85,7 @@ namespace NLNET _PluggedModules.removeWithB(pluggedModule); } - void CModuleSocket::sendModuleMessage(IModule *senderModule, TModuleId destModuleProxyId, const NLNET::CMessage &message ) - throw (EModuleNotPluggedHere) + void CModuleSocket::sendModuleMessage(IModule *senderModule, TModuleId destModuleProxyId, const NLNET::CMessage &message) { TPluggedModules::TBToAMap::const_iterator it(_PluggedModules.getBToAMap().find(senderModule)); if (it == _PluggedModules.getBToAMap().end()) @@ -100,7 +99,6 @@ namespace NLNET } void CModuleSocket::broadcastModuleMessage(IModule *senderModule, const NLNET::CMessage &message) - throw (EModuleNotPluggedHere) { TPluggedModules::TBToAMap::const_iterator it(_PluggedModules.getBToAMap().find(senderModule)); if (it == _PluggedModules.getBToAMap().end()) From d32877ddc98f3349612c029b0918184b82f05b55 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 10 Aug 2018 16:00:43 +0300 Subject: [PATCH 092/303] Changed: Keep track of style states in a single struct --HG-- branch : develop --- code/nel/include/nel/gui/group_html.h | 86 ++---- code/nel/src/gui/group_html.cpp | 366 +++++++++++--------------- 2 files changed, 175 insertions(+), 277 deletions(-) diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index 35ba3e40e..0ccd227b7 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -505,78 +505,32 @@ namespace NLGUI // IL mode bool _LI; - // Current text color - std::vector _TextColor; - inline const NLMISC::CRGBA &getTextColor() const + // Current active style + CStyleParams _Style; + // Default style + CStyleParams _StyleDefault; + // Nested style stack + std::vector _StyleParams; + inline void pushStyle() { - if (_TextColor.empty()) - return TextColor; - return _TextColor.back(); + _StyleParams.push_back(_Style); + } + inline void popStyle() + { + if (_StyleParams.empty()) + _Style = _StyleDefault; + else + { + _Style = _StyleParams.back(); + _StyleParams.pop_back(); + } } - // Current global color flag - std::vector _GlobalColor; - inline bool getGlobalColor() const - { - if (_GlobalColor.empty()) - return false; - return _GlobalColor.back(); - } - - // Current font name - std::vector _FontFamily; - inline const char* getFontFamily() const - { - if (_FontFamily.empty()) - return ""; - return _FontFamily.back().c_str(); - } - - // Current font size - std::vector _FontSize; - inline uint getFontSize() const - { - if (_FontSize.empty()) - return TextFontSize; - return _FontSize.back(); - } inline uint getFontSizeSmaller() const { - if (getFontSize() < 5) + if (_Style.FontSize < 5) return 3; - return getFontSize()-2; - } - - std::vector _FontWeight; - inline uint getFontWeight() const - { - if (_FontWeight.empty()) - return 400; - return _FontWeight.back(); - } - - std::vector _FontOblique; - inline bool getFontOblique() const - { - if (_FontOblique.empty()) - return false; - return _FontOblique.back(); - } - - std::vector _FontUnderlined; - inline bool getFontUnderlined() const - { - if (_FontUnderlined.empty()) - return false; - return _FontUnderlined.back(); - } - - std::vector _FontStrikeThrough; - inline bool getFontStrikeThrough() const - { - if (_FontStrikeThrough.empty()) - return false; - return _FontStrikeThrough.back(); + return _Style.FontSize-2; } // Current link diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 9c022934a..46a32fb13 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -1485,23 +1485,14 @@ namespace NLGUI { registerAnchorName(MY_HTML_A); - CStyleParams style; - style.FontFamily = getFontFamily(); - style.FontSize = getFontSize(); - style.TextColor = LinkColor; - style.Underlined = true; - style.StrikeThrough = getFontStrikeThrough(); - style.GlobalColor = LinkColorGlobalColor; + pushStyle(); + _Style.TextColor = LinkColor; + _Style.Underlined = true; + _Style.GlobalColor = LinkColorGlobalColor; if (present[HTML_A_STYLE] && value[HTML_A_STYLE]) - getStyleParams(value[HTML_A_STYLE], style); + getStyleParams(value[HTML_A_STYLE], _Style); - _FontFamily.push_back(style.FontFamily); - _FontSize.push_back(style.FontSize); - _TextColor.push_back(style.TextColor); - _FontUnderlined.push_back(style.Underlined); - _FontStrikeThrough.push_back(style.StrikeThrough); - _GlobalColor.push_back(style.GlobalColor); _A.push_back(true); _Link.push_back (""); _LinkTitle.push_back(""); @@ -1625,30 +1616,19 @@ namespace NLGUI break; case HTML_FONT: { - bool found = false; + pushStyle(); if (present[HTML_FONT_COLOR] && value[HTML_FONT_COLOR]) { CRGBA color; if (scanHTMLColor(value[HTML_FONT_COLOR], color)) - { - _TextColor.push_back(color); - found = true; - } - } - if (!found) - { - _TextColor.push_back(_TextColor.empty() ? CRGBA::White : _TextColor.back()); + _Style.TextColor = color; } if (present[HTML_FONT_SIZE] && value[HTML_FONT_SIZE]) { uint fontsize; fromString(value[HTML_FONT_SIZE], fontsize); - _FontSize.push_back(fontsize); - } - else - { - _FontSize.push_back(_FontSize.empty() ? TextFontSize : _FontSize.back()); + _Style.FontSize = fontsize; } } break; @@ -1720,46 +1700,64 @@ namespace NLGUI } break; case HTML_H1: - registerAnchorName(MY_HTML_H1); - newParagraph(PBeginSpace); - _FontSize.push_back(H1FontSize); - _TextColor.push_back(H1Color); - _GlobalColor.push_back(H1ColorGlobalColor); + { + registerAnchorName(MY_HTML_H1); + newParagraph(PBeginSpace); + pushStyle(); + _Style.FontSize = H1FontSize; + _Style.TextColor = H1Color; + _Style.GlobalColor = H1ColorGlobalColor; + } break; case HTML_H2: - registerAnchorName(MY_HTML_H2); - newParagraph(PBeginSpace); - _FontSize.push_back(H2FontSize); - _TextColor.push_back(H2Color); - _GlobalColor.push_back(H2ColorGlobalColor); + { + registerAnchorName(MY_HTML_H2); + newParagraph(PBeginSpace); + pushStyle(); + _Style.FontSize = H2FontSize; + _Style.TextColor = H2Color; + _Style.GlobalColor = H2ColorGlobalColor; + } break; case HTML_H3: - registerAnchorName(MY_HTML_H3); - newParagraph(PBeginSpace); - _FontSize.push_back(H3FontSize); - _TextColor.push_back(H3Color); - _GlobalColor.push_back(H3ColorGlobalColor); + { + registerAnchorName(MY_HTML_H3); + newParagraph(PBeginSpace); + pushStyle(); + _Style.FontSize = H3FontSize; + _Style.TextColor = H3Color; + _Style.GlobalColor = H3ColorGlobalColor; + } break; case HTML_H4: - registerAnchorName(MY_HTML_H4); - newParagraph(PBeginSpace); - _FontSize.push_back(H4FontSize); - _TextColor.push_back(H4Color); - _GlobalColor.push_back(H4ColorGlobalColor); + { + registerAnchorName(MY_HTML_H4); + newParagraph(PBeginSpace); + pushStyle(); + _Style.FontSize = H4FontSize; + _Style.TextColor = H4Color; + _Style.GlobalColor = H4ColorGlobalColor; + } break; case HTML_H5: - registerAnchorName(MY_HTML_H5); - newParagraph(PBeginSpace); - _FontSize.push_back(H5FontSize); - _TextColor.push_back(H5Color); - _GlobalColor.push_back(H5ColorGlobalColor); + { + registerAnchorName(MY_HTML_H5); + newParagraph(PBeginSpace); + pushStyle(); + _Style.FontSize = H5FontSize; + _Style.TextColor = H5Color; + _Style.GlobalColor = H5ColorGlobalColor; + } break; case HTML_H6: - registerAnchorName(MY_HTML_H6); - newParagraph(PBeginSpace); - _FontSize.push_back(H6FontSize); - _TextColor.push_back(H6Color); - _GlobalColor.push_back(H6ColorGlobalColor); + { + registerAnchorName(MY_HTML_H6); + newParagraph(PBeginSpace); + pushStyle(); + _Style.FontSize = H6FontSize; + _Style.TextColor = H6Color; + _Style.GlobalColor = H6ColorGlobalColor; + } break; case HTML_IMG: { @@ -1857,15 +1855,15 @@ namespace NLGUI if (present[MY_HTML_INPUT_TYPE] && value[MY_HTML_INPUT_TYPE]) { // by default not inherited, font family defaults to system font - CStyleParams style; - style.TextColor = TextColor; - style.FontSize = TextFontSize; - style.FontWeight = FONT_WEIGHT_NORMAL; - style.FontOblique = false; + pushStyle(); + _Style.TextColor = TextColor; + _Style.FontSize = TextFontSize; + _Style.FontWeight = FONT_WEIGHT_NORMAL; + _Style.FontOblique = false; // Global color flag if (present[MY_HTML_INPUT_GLOBAL_COLOR]) - style.GlobalColor = true; + _Style.GlobalColor = true; // Tooltip const char *tooltip = NULL; @@ -1873,13 +1871,7 @@ namespace NLGUI tooltip = value[MY_HTML_INPUT_ALT]; if (present[MY_HTML_INPUT_STYLE] && value[MY_HTML_INPUT_STYLE]) - getStyleParams(value[MY_HTML_INPUT_STYLE], style); - - _TextColor.push_back(style.TextColor); - _FontFamily.push_back(style.FontFamily); - _FontSize.push_back(style.FontSize); - _FontWeight.push_back(style.FontWeight); - _FontOblique.push_back(style.FontOblique); + getStyleParams(value[MY_HTML_INPUT_STYLE], _Style); string type = toLower(value[MY_HTML_INPUT_TYPE]); if (type == "image") @@ -1899,7 +1891,7 @@ namespace NLGUI // Add the ctrl button addButton (CCtrlButton::PushButton, name, normal, pushed.empty()?normal:pushed, over, - "html_submit_form", param.c_str(), tooltip, style); + "html_submit_form", param.c_str(), tooltip, _Style); } if (type == "button" || type == "submit") { @@ -1954,7 +1946,7 @@ namespace NLGUI if (!ctrlButton) ctrlButton = dynamic_cast(buttonGroup->getCtrl("b")); if (ctrlButton) { - ctrlButton->setModulateGlobalColorAll (style.GlobalColor); + ctrlButton->setModulateGlobalColorAll (_Style.GlobalColor); // Translate the tooltip if (tooltip) @@ -2037,7 +2029,7 @@ namespace NLGUI checked = (present[MY_HTML_INPUT_CHECKED] && value[MY_HTML_INPUT_CHECKED]); // Add the ctrl button - CCtrlButton *checkbox = addButton (btnType, name, normal, pushed, over, "", "", tooltip, style); + CCtrlButton *checkbox = addButton (btnType, name, normal, pushed, over, "", "", tooltip, _Style); if (checkbox) { if (btnType == CCtrlButton::RadioButton) @@ -2091,11 +2083,7 @@ namespace NLGUI } } - popIfNotEmpty(_FontFamily); - popIfNotEmpty(_FontSize); - popIfNotEmpty(_TextColor); - popIfNotEmpty(_FontWeight); - popIfNotEmpty(_FontOblique); + popStyle(); } } break; @@ -2210,25 +2198,12 @@ namespace NLGUI break; case HTML_PRE: { - CStyleParams style; - style.TextColor = getTextColor(); - style.FontFamily = "monospace"; - style.FontSize = getFontSize(); - style.FontWeight = getFontWeight(); - style.FontOblique = getFontOblique(); - style.Underlined = getFontUnderlined(); - style.StrikeThrough = getFontStrikeThrough(); + pushStyle(); + _Style.FontFamily = "monospace"; if (present[HTML_PRE_STYLE] && value[HTML_PRE_STYLE]) - getStyleParams(value[HTML_PRE_STYLE], style); + getStyleParams(value[HTML_PRE_STYLE], _Style); - _TextColor.push_back(style.TextColor); - _FontFamily.push_back(style.FontFamily); - _FontSize.push_back(style.FontSize); - _FontWeight.push_back(style.FontWeight); - _FontOblique.push_back(style.FontOblique); - _FontUnderlined.push_back(style.Underlined); - _FontStrikeThrough.push_back(style.StrikeThrough); _PRE.push_back(true); } @@ -2274,7 +2249,8 @@ namespace NLGUI if (element_number == HTML_TH) { - _FontWeight.push_back(FONT_WEIGHT_BOLD); + pushStyle(); + _Style.FontWeight = FONT_WEIGHT_BOLD; // center if not specified otherwise. TD/TH present/value arrays have same indices if (!(present[MY_HTML_TD_ALIGN] && value[MY_HTML_TD_ALIGN])) _CellParams.back().Align = CGroupCell::Center; @@ -2365,20 +2341,14 @@ namespace NLGUI if (!(_Forms.empty())) { // not inherited by default, font family defaults to system font - CStyleParams style; - style.TextColor = TextColor; - style.FontWeight = FONT_WEIGHT_NORMAL; - style.FontOblique = false; - style.FontSize = TextFontSize; + pushStyle(); + _Style.TextColor = TextColor; + _Style.FontWeight = FONT_WEIGHT_NORMAL; + _Style.FontOblique = false; + _Style.FontSize = TextFontSize; if (present[MY_HTML_TEXTAREA_STYLE] && value[MY_HTML_TEXTAREA_STYLE]) - getStyleParams(value[MY_HTML_TEXTAREA_STYLE], style); - - _TextColor.push_back(style.TextColor); - _FontFamily.push_back(style.FontFamily); - _FontSize.push_back(style.FontSize); - _FontWeight.push_back(style.FontWeight); - _FontOblique.push_back(style.FontOblique); + getStyleParams(value[MY_HTML_TEXTAREA_STYLE], _Style); // read general property string templateName; @@ -2460,43 +2430,41 @@ namespace NLGUI break; case HTML_SPAN: { - CStyleParams style; - style.TextColor = getTextColor(); - style.FontFamily = getFontFamily(); - style.FontSize = getFontSize(); - style.FontWeight = getFontWeight(); - style.FontOblique = getFontOblique(); - style.Underlined = getFontUnderlined(); - style.StrikeThrough = getFontStrikeThrough(); - style.GlobalColor = getGlobalColor(); + pushStyle(); if (present[MY_HTML_SPAN_STYLE] && value[MY_HTML_SPAN_STYLE]) - getStyleParams(value[MY_HTML_SPAN_STYLE], style); - - _TextColor.push_back(style.TextColor); - _FontFamily.push_back(style.FontFamily); - _FontSize.push_back(style.FontSize); - _FontWeight.push_back(style.FontWeight); - _FontOblique.push_back(style.FontOblique); - _FontUnderlined.push_back(style.Underlined); - _FontStrikeThrough.push_back(style.StrikeThrough); - _GlobalColor.push_back(style.GlobalColor); + getStyleParams(value[MY_HTML_SPAN_STYLE], _Style); } break; case HTML_DEL: - _FontStrikeThrough.push_back(true); + { + pushStyle(); + _Style.StrikeThrough = true; + } break; case HTML_U: - _FontUnderlined.push_back(true); + { + pushStyle(); + _Style.Underlined = true; + } break; case HTML_EM: - _FontOblique.push_back(true); + { + pushStyle(); + _Style.FontOblique = true; + } break; case HTML_STRONG: - _FontWeight.push_back(FONT_WEIGHT_BOLD); + { + pushStyle(); + _Style.FontWeight = FONT_WEIGHT_BOLD; + } break; case HTML_SMALL: - _FontSize.push_back(getFontSizeSmaller()); + { + pushStyle(); + _Style.FontSize = getFontSizeSmaller(); + } break; case HTML_STYLE: case HTML_SCRIPT: @@ -2521,7 +2489,8 @@ namespace NLGUI if (!_DL.back().DT) { _DL.back().DT = true; - _FontWeight.push_back(FONT_WEIGHT_BOLD); + pushStyle(); + _Style.FontWeight = FONT_WEIGHT_BOLD; } if (!_LI) @@ -2542,7 +2511,7 @@ namespace NLGUI if (_DL.back().DT) { _DL.back().DT = false; - popIfNotEmpty (_FontWeight); + popStyle(); } if (!_DL.back().DD) @@ -2633,16 +2602,10 @@ namespace NLGUI _ReadingHeadTag = false; break; case HTML_FONT: - popIfNotEmpty (_TextColor); - popIfNotEmpty (_FontSize); + popStyle(); break; case HTML_A: - popIfNotEmpty (_FontFamily); - popIfNotEmpty (_FontSize); - popIfNotEmpty (_TextColor); - popIfNotEmpty (_FontUnderlined); - popIfNotEmpty (_FontStrikeThrough); - popIfNotEmpty (_GlobalColor); + popStyle(); popIfNotEmpty (_A); popIfNotEmpty (_Link); popIfNotEmpty (_LinkTitle); @@ -2654,22 +2617,14 @@ namespace NLGUI case HTML_H4: case HTML_H5: case HTML_H6: - popIfNotEmpty (_FontSize); - popIfNotEmpty (_TextColor); - popIfNotEmpty (_GlobalColor); + popStyle(); endParagraph(); break; case HTML_P: endParagraph(); break; case HTML_PRE: - popIfNotEmpty (_FontFamily); - popIfNotEmpty (_FontSize); - popIfNotEmpty (_FontWeight); - popIfNotEmpty (_FontOblique); - popIfNotEmpty (_TextColor); - popIfNotEmpty (_FontUnderlined); - popIfNotEmpty (_FontStrikeThrough); + popStyle(); popIfNotEmpty (_PRE); break; case HTML_DIV: @@ -2692,7 +2647,7 @@ namespace NLGUI // Add a cell break; case HTML_TH: - popIfNotEmpty (_FontWeight); + popStyle(); // no break; case HTML_TD: popIfNotEmpty (_CellParams); @@ -2717,11 +2672,7 @@ namespace NLGUI _Forms.back().Entries.push_back (entry); } - popIfNotEmpty (_FontFamily); - popIfNotEmpty (_FontSize); - popIfNotEmpty (_FontWeight); - popIfNotEmpty (_FontOblique); - popIfNotEmpty (_TextColor); + popStyle(); } popIfNotEmpty (_PRE); @@ -2843,7 +2794,7 @@ namespace NLGUI // unclosed DT if (_DL.back().DT) { - popIfNotEmpty (_FontWeight); + popStyle(); } // unclosed DD @@ -2859,7 +2810,7 @@ namespace NLGUI if (!_DL.empty()) { _DL.back().DT = false; - popIfNotEmpty (_FontWeight); + popStyle(); } break; case HTML_DD: @@ -2874,29 +2825,22 @@ namespace NLGUI } break; case HTML_SPAN: - popIfNotEmpty (_FontFamily); - popIfNotEmpty (_FontSize); - popIfNotEmpty (_FontWeight); - popIfNotEmpty (_FontOblique); - popIfNotEmpty (_TextColor); - popIfNotEmpty (_FontUnderlined); - popIfNotEmpty (_FontStrikeThrough); - popIfNotEmpty (_GlobalColor); + popStyle(); break; case HTML_DEL: - popIfNotEmpty (_FontStrikeThrough); + popStyle(); break; case HTML_U: - popIfNotEmpty (_FontUnderlined); + popStyle(); break; case HTML_EM: - popIfNotEmpty (_FontOblique); + popStyle(); break; case HTML_STRONG: - popIfNotEmpty (_FontWeight); + popStyle(); break; case HTML_SMALL: - popIfNotEmpty (_FontSize); + popStyle(); break; case HTML_STYLE: case HTML_SCRIPT: @@ -4325,7 +4269,7 @@ namespace NLGUI // Text added ? bool added = false; - bool embolden = getFontWeight() >= FONT_WEIGHT_BOLD; + bool embolden = _Style.FontWeight >= FONT_WEIGHT_BOLD; // Number of child in this paragraph if (_CurrentViewLink) @@ -4333,15 +4277,15 @@ namespace NLGUI bool skipLine = !_CurrentViewLink->getText().empty() && *(_CurrentViewLink->getText().rbegin()) == (ucchar) '\n'; // Compatible with current parameters ? if (!skipLine && - (getTextColor() == _CurrentViewLink->getColor()) && - (getFontFamily() == _CurrentViewLink->getFontName()) && - (getFontSize() == (uint)_CurrentViewLink->getFontSize()) && - (getFontUnderlined() == _CurrentViewLink->getUnderlined()) && - (getFontStrikeThrough() == _CurrentViewLink->getStrikeThrough()) && + (_Style.TextColor == _CurrentViewLink->getColor()) && + (_Style.FontFamily == _CurrentViewLink->getFontName()) && + (_Style.FontSize == (uint)_CurrentViewLink->getFontSize()) && + (_Style.Underlined == _CurrentViewLink->getUnderlined()) && + (_Style.StrikeThrough == _CurrentViewLink->getStrikeThrough()) && (embolden == _CurrentViewLink->getEmbolden()) && - (getFontOblique() == _CurrentViewLink->getOblique()) && + (_Style.FontOblique == _CurrentViewLink->getOblique()) && (getLink() == _CurrentViewLink->Link) && - (getGlobalColor() == _CurrentViewLink->getModulateGlobalColor())) + (_Style.GlobalColor == _CurrentViewLink->getModulateGlobalColor())) { // Concat the text _CurrentViewLink->setText(_CurrentViewLink->getText()+tmpStr); @@ -4401,16 +4345,16 @@ namespace NLGUI } } newLink->setText(tmpStr); - newLink->setColor(getTextColor()); - newLink->setFontName(getFontFamily()); - newLink->setFontSize(getFontSize()); + newLink->setColor(_Style.TextColor); + newLink->setFontName(_Style.FontFamily); + newLink->setFontSize(_Style.FontSize); newLink->setEmbolden(embolden); - newLink->setOblique(getFontOblique()); - newLink->setUnderlined(getFontUnderlined()); - newLink->setStrikeThrough(getFontStrikeThrough()); - newLink->setMultiLineSpace((uint)((float)getFontSize()*LineSpaceFontFactor)); + newLink->setOblique(_Style.FontOblique); + newLink->setUnderlined(_Style.Underlined); + newLink->setStrikeThrough(_Style.StrikeThrough); + newLink->setMultiLineSpace((uint)((float)(_Style.FontSize)*LineSpaceFontFactor)); newLink->setMultiLine(true); - newLink->setModulateGlobalColor(getGlobalColor()); + newLink->setModulateGlobalColor(_Style.GlobalColor); // newLink->setLineAtBottom (true); registerAnchor(newLink); @@ -4517,15 +4461,15 @@ namespace NLGUI { // Not added ? std::vector > templateParams; - templateParams.push_back (std::pair ("w", toString (cols*getFontSize()))); + templateParams.push_back (std::pair ("w", toString (cols*_Style.FontSize))); templateParams.push_back (std::pair ("id", name)); templateParams.push_back (std::pair ("prompt", "")); templateParams.push_back (std::pair ("multiline", multiLine?"true":"false")); - templateParams.push_back (std::pair ("fontsize", toString (getFontSize()))); - templateParams.push_back (std::pair ("color", getTextColor().toString())); - if (getFontWeight() >= FONT_WEIGHT_BOLD) + templateParams.push_back (std::pair ("fontsize", toString (_Style.FontSize))); + templateParams.push_back (std::pair ("color", _Style.TextColor.toString())); + if (_Style.FontWeight >= FONT_WEIGHT_BOLD) templateParams.push_back (std::pair ("fontweight", "bold")); - if (getFontOblique()) + if (_Style.FontOblique) templateParams.push_back (std::pair ("fontstyle", "oblique")); if (multiLine) templateParams.push_back (std::pair ("multi_min_line", toString(rows))); @@ -4767,13 +4711,6 @@ namespace NLGUI { _Paragraph = NULL; _PRE.clear(); - _TextColor.clear(); - _GlobalColor.clear(); - _FontSize.clear(); - _FontWeight.clear(); - _FontOblique.clear(); - _FontUnderlined.clear(); - _FontStrikeThrough.clear(); _Indent.clear(); _LI = false; _UL.clear(); @@ -4797,6 +4734,11 @@ namespace NLGUI _IgnoreHeadTag = false; _IgnoreBaseUrlTag = false; + // reset style + _StyleDefault = CStyleParams(); + _Style = _StyleDefault; + _StyleParams.clear(); + // TR paragraphChange (); @@ -6118,6 +6060,8 @@ namespace NLGUI // style.StrikeThrough; // text-decoration: line-through; text-decoration-line: line-through; void CGroupHTML::getStyleParams(const std::string &styleString, CStyleParams &style, bool inherit) { + const CStyleParams current = _Style; + float tmpf; TStyle styles = parseStyle(styleString); TStyle::iterator it; @@ -6126,7 +6070,7 @@ namespace NLGUI if (it->first == "font-size") { if (it->second == "inherit") - style.FontSize = getFontSize(); + style.FontSize = current.FontSize; else { float tmp; @@ -6140,7 +6084,7 @@ namespace NLGUI if (it->first == "font-style") { if (it->second == "inherit") - style.FontOblique = getFontOblique(); + style.FontOblique = current.FontOblique; else if (it->second == "italic" || it->second == "oblique") style.FontOblique = true; @@ -6149,7 +6093,7 @@ namespace NLGUI if (it->first == "font-family") { if (it->second == "inherit") - style.FontFamily = getFontFamily(); + style.FontFamily = current.FontFamily; else if (it->second == "monospace") style.FontFamily = "monospace"; @@ -6162,7 +6106,7 @@ namespace NLGUI // https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight uint weight = 400; if (it->second == "inherit") - weight = getFontWeight(); + weight = current.FontWeight; else if (it->second == "normal") weight = 400; @@ -6173,7 +6117,7 @@ namespace NLGUI if (it->second == "lighter") { const uint lighter[] = {100, 100, 100, 100, 100, 400, 400, 700, 700}; - uint index = getFontWeight() / 100 - 1; + uint index = current.FontWeight / 100 - 1; clamp(index, 1u, 9u); weight = lighter[index-1]; } @@ -6181,7 +6125,7 @@ namespace NLGUI if (it->second == "bolder") { const uint bolder[] = {400, 400, 400, 700, 700, 900, 900, 900, 900}; - uint index = getFontWeight() / 100 + 1; + uint index = current.FontWeight / 100 + 1; clamp(index, 1u, 9u); weight = bolder[index-1]; } @@ -6197,7 +6141,7 @@ namespace NLGUI else if (it->first == "color") if (it->second == "inherit") - style.TextColor = getTextColor(); + style.TextColor = current.TextColor; else scanHTMLColor(it->second.c_str(), style.TextColor); else @@ -6224,7 +6168,7 @@ namespace NLGUI { bool b; if (it->second == "inherit") - style.GlobalColor = getGlobalColor(); + style.GlobalColor = current.GlobalColor; else if (fromString(it->second, b)) style.GlobalColor = b; @@ -6232,8 +6176,8 @@ namespace NLGUI } if (inherit) { - style.Underlined = getFontUnderlined() || style.Underlined; - style.StrikeThrough = getFontStrikeThrough() || style.StrikeThrough; + style.Underlined = current.Underlined || style.Underlined; + style.StrikeThrough = current.StrikeThrough || style.StrikeThrough; } } From 1525b03a83321bd207c8171757208d25d1c3ff95 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 11 Aug 2018 09:59:01 +0300 Subject: [PATCH 093/303] Changed: Extend style attribute to other tags --HG-- branch : develop --- code/nel/include/nel/gui/libwww.h | 1 + code/nel/src/gui/group_html.cpp | 145 +++++++++++++++++++++++------- code/nel/src/gui/libwww.cpp | 1 + 3 files changed, 113 insertions(+), 34 deletions(-) diff --git a/code/nel/include/nel/gui/libwww.h b/code/nel/include/nel/gui/libwww.h index 0825779f2..892e07eb2 100644 --- a/code/nel/include/nel/gui/libwww.h +++ b/code/nel/include/nel/gui/libwww.h @@ -102,6 +102,7 @@ namespace NLGUI HTML_ATTR(TR,L_MARGIN), HTML_ATTR(TR,NOWRAP), HTML_ATTR(TR,VALIGN), + HTML_ATTR(TR,STYLE), }; enum diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 46a32fb13..970178947 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -1530,6 +1530,7 @@ namespace NLGUI { _BlockLevelElement.push_back(true); registerAnchorName(MY_HTML_DIV); + pushStyle(); if (present[MY_HTML_DIV_NAME] && value[MY_HTML_DIV_NAME]) _DivName = value[MY_HTML_DIV_NAME]; @@ -1538,6 +1539,13 @@ namespace NLGUI if (present[MY_HTML_DIV_CLASS] && value[MY_HTML_DIV_CLASS]) instClass = value[MY_HTML_DIV_CLASS]; + string style; + if (present[MY_HTML_DIV_STYLE] && value[MY_HTML_DIV_STYLE]) + style = value[MY_HTML_DIV_STYLE]; + + if (!style.empty()) + getStyleParams(style, _Style); + // use generic template system if (_TrustedDomain && !instClass.empty() && instClass == "ryzom-ui-grouptemplate") { @@ -1545,10 +1553,6 @@ namespace NLGUI if (present[MY_HTML_DIV_ID] && value[MY_HTML_DIV_ID]) id = value[MY_HTML_DIV_ID]; - string style; - if (present[MY_HTML_DIV_STYLE] && value[MY_HTML_DIV_STYLE]) - style = value[MY_HTML_DIV_STYLE]; - typedef pair TTmplParam; vector tmplParams; @@ -1679,6 +1683,10 @@ namespace NLGUI image = image.substr(4, image.size()-5); setBackground (image, scale, repeat); } + + // set default text style from + getStyleParams(style, _StyleDefault); + _Style = _StyleDefault; } } break; @@ -1707,6 +1715,8 @@ namespace NLGUI _Style.FontSize = H1FontSize; _Style.TextColor = H1Color; _Style.GlobalColor = H1ColorGlobalColor; + if (present[MY_HTML_H1_STYLE] && value[MY_HTML_H1_STYLE]) + getStyleParams(value[MY_HTML_H1_STYLE], _Style); } break; case HTML_H2: @@ -1717,6 +1727,8 @@ namespace NLGUI _Style.FontSize = H2FontSize; _Style.TextColor = H2Color; _Style.GlobalColor = H2ColorGlobalColor; + if (present[MY_HTML_H2_STYLE] && value[MY_HTML_H2_STYLE]) + getStyleParams(value[MY_HTML_H2_STYLE], _Style); } break; case HTML_H3: @@ -1727,6 +1739,8 @@ namespace NLGUI _Style.FontSize = H3FontSize; _Style.TextColor = H3Color; _Style.GlobalColor = H3ColorGlobalColor; + if (present[MY_HTML_H3_STYLE] && value[MY_HTML_H3_STYLE]) + getStyleParams(value[MY_HTML_H3_STYLE], _Style); } break; case HTML_H4: @@ -1737,6 +1751,8 @@ namespace NLGUI _Style.FontSize = H4FontSize; _Style.TextColor = H4Color; _Style.GlobalColor = H4ColorGlobalColor; + if (present[MY_HTML_H4_STYLE] && value[MY_HTML_H4_STYLE]) + getStyleParams(value[MY_HTML_H4_STYLE], _Style); } break; case HTML_H5: @@ -1747,6 +1763,8 @@ namespace NLGUI _Style.FontSize = H5FontSize; _Style.TextColor = H5Color; _Style.GlobalColor = H5ColorGlobalColor; + if (present[MY_HTML_H5_STYLE] && value[MY_HTML_H5_STYLE]) + getStyleParams(value[MY_HTML_H5_STYLE], _Style); } break; case HTML_H6: @@ -1757,6 +1775,8 @@ namespace NLGUI _Style.FontSize = H6FontSize; _Style.TextColor = H6Color; _Style.GlobalColor = H6ColorGlobalColor; + if (present[MY_HTML_H6_STYLE] && value[MY_HTML_H6_STYLE]) + getStyleParams(value[MY_HTML_H6_STYLE], _Style); } break; case HTML_IMG: @@ -2177,6 +2197,10 @@ namespace NLGUI if (present[HTML_LI_VALUE] && value[HTML_LI_VALUE]) fromString(value[HTML_LI_VALUE], _UL.back().Value); + pushStyle(); + if (present[HTML_LI_STYLE] && value[HTML_LI_STYLE]) + getStyleParams(value[HTML_LI_STYLE], _Style); + ucstring str; str.fromUtf8(_UL.back().getListMarkerText()); addString (str); @@ -2194,7 +2218,12 @@ namespace NLGUI } break; case HTML_P: - newParagraph(PBeginSpace); + { + newParagraph(PBeginSpace); + pushStyle(); + if (present[HTML_BLOCK_STYLE] && value[HTML_BLOCK_STYLE]) + getStyleParams(value[HTML_BLOCK_STYLE], _Style); + } break; case HTML_PRE: { @@ -2210,6 +2239,7 @@ namespace NLGUI break; case HTML_TABLE: { + pushStyle(); registerAnchorName(MY_HTML_TABLE); // Get cells parameters @@ -2228,6 +2258,8 @@ namespace NLGUI fromString(value[MY_HTML_TABLE_CELLSPACING], table->CellSpacing); if (present[MY_HTML_TABLE_CELLPADDING] && value[MY_HTML_TABLE_CELLPADDING]) fromString(value[MY_HTML_TABLE_CELLPADDING], table->CellPadding); + if (present[MY_HTML_TABLE_STYLE] && value[MY_HTML_TABLE_STYLE]) + getStyleParams(value[MY_HTML_TABLE_STYLE], _Style); table->setMarginLeft(getIndent()); addHtmlGroup (table, 0); @@ -2247,15 +2279,18 @@ namespace NLGUI // Get cells parameters getCellsParameters (MY_HTML_TD, true); + pushStyle(); if (element_number == HTML_TH) { - pushStyle(); _Style.FontWeight = FONT_WEIGHT_BOLD; // center if not specified otherwise. TD/TH present/value arrays have same indices if (!(present[MY_HTML_TD_ALIGN] && value[MY_HTML_TD_ALIGN])) _CellParams.back().Align = CGroupCell::Center; } + if (present[MY_HTML_TD_STYLE] && value[MY_HTML_TD_STYLE]) + getStyleParams(value[MY_HTML_TD_STYLE], _Style); + CGroupTable *table = getTable(); if (table) { @@ -2335,21 +2370,21 @@ namespace NLGUI } break; case HTML_TEXTAREA: + pushStyle(); _PRE.push_back(true); + // not inherited by default, font family defaults to system font + _Style.TextColor = TextColor; + _Style.FontWeight = FONT_WEIGHT_NORMAL; + _Style.FontOblique = false; + _Style.FontSize = TextFontSize; + + if (present[MY_HTML_TEXTAREA_STYLE] && value[MY_HTML_TEXTAREA_STYLE]) + getStyleParams(value[MY_HTML_TEXTAREA_STYLE], _Style); + // Got one form ? if (!(_Forms.empty())) { - // not inherited by default, font family defaults to system font - pushStyle(); - _Style.TextColor = TextColor; - _Style.FontWeight = FONT_WEIGHT_NORMAL; - _Style.FontOblique = false; - _Style.FontSize = TextFontSize; - - if (present[MY_HTML_TEXTAREA_STYLE] && value[MY_HTML_TEXTAREA_STYLE]) - getStyleParams(value[MY_HTML_TEXTAREA_STYLE], _Style); - // read general property string templateName; @@ -2398,6 +2433,10 @@ namespace NLGUI // Set TR flag if (!_TR.empty()) _TR.back() = true; + + pushStyle(); + if (present[MY_HTML_TR_STYLE] && value[MY_HTML_TR_STYLE]) + getStyleParams(value[MY_HTML_TR_STYLE], _Style); } break; case HTML_UL: @@ -2411,6 +2450,10 @@ namespace NLGUI _LI = _UL.size() > 1 || _DL.size() > 1; _Indent.push_back(getIndent() + ULIndent); endParagraph(); + + pushStyle(); + if (present[HTML_UL_STYLE] && value[HTML_UL_STYLE]) + getStyleParams(value[HTML_UL_STYLE], _Style); break; case HTML_OBJECT: _ObjectType.clear(); @@ -2471,27 +2514,36 @@ namespace NLGUI _IgnoreText = true; break; case HTML_DL: - _DL.push_back(HTMLDListElement()); - _LI = _DL.size() > 1 || !_UL.empty(); - endParagraph(); + { + _DL.push_back(HTMLDListElement()); + _LI = _DL.size() > 1 || !_UL.empty(); + endParagraph(); + pushStyle(); + if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE]) + getStyleParams(value[HTML_GEN_STYLE], _Style); + } break; case HTML_DT: if (!_DL.empty()) { - // close DT if still open + // close if still open if (_DL.back().DD) { _DL.back().DD = false; popIfNotEmpty(_Indent); + popStyle(); } - // see if this is the first
, closing tag not required - if (!_DL.back().DT) - { - _DL.back().DT = true; - pushStyle(); - _Style.FontWeight = FONT_WEIGHT_BOLD; - } + // close if still open + if (_DL.back().DT) + popStyle(); + + _DL.back().DT = true; + + pushStyle(); + _Style.FontWeight = FONT_WEIGHT_BOLD; + if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE]) + getStyleParams(value[HTML_GEN_STYLE], _Style); if (!_LI) { @@ -2514,12 +2566,20 @@ namespace NLGUI popStyle(); } - if (!_DL.back().DD) + if (_DL.back().DD) { - _DL.back().DD = true; - _Indent.push_back(getIndent() + ULIndent); + _DL.back().DD = false; + popStyle(); + popIfNotEmpty(_Indent); } + _DL.back().DD = true; + _Indent.push_back(getIndent() + ULIndent); + + pushStyle(); + if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE]) + getStyleParams(value[HTML_GEN_STYLE], _Style); + if (!_LI) { _LI = true; @@ -2533,6 +2593,7 @@ namespace NLGUI break; case HTML_OL: { + pushStyle(); sint32 start = 1; std::string type("1"); @@ -2540,6 +2601,8 @@ namespace NLGUI fromString(value[HTML_OL_START], start); if (present[HTML_OL_TYPE] && value[HTML_OL_TYPE]) type = value[HTML_OL_TYPE]; + if (present[HTML_OL_STYLE] && value[HTML_OL_STYLE]) + getStyleParams(value[HTML_OL_STYLE], _Style); _UL.push_back(HTMLOListElement(start, type)); // if LI is already present @@ -2621,6 +2684,7 @@ namespace NLGUI endParagraph(); break; case HTML_P: + popStyle(); endParagraph(); break; case HTML_PRE: @@ -2628,6 +2692,7 @@ namespace NLGUI popIfNotEmpty (_PRE); break; case HTML_DIV: + popStyle(); if (isBlockLevelElement()) { endParagraph(); @@ -2638,6 +2703,7 @@ namespace NLGUI break; case HTML_TABLE: + popStyle(); popIfNotEmpty (_CellParams); popIfNotEmpty (_TR); popIfNotEmpty (_Cells); @@ -2647,14 +2713,15 @@ namespace NLGUI // Add a cell break; case HTML_TH: - popStyle(); // no break; case HTML_TD: + popStyle(); popIfNotEmpty (_CellParams); if (!_Cells.empty()) _Cells.back() = NULL; break; case HTML_TR: + popStyle(); popIfNotEmpty (_CellParams); break; case HTML_TEXTAREA: @@ -2671,10 +2738,9 @@ namespace NLGUI entry.TextArea = textArea; _Forms.back().Entries.push_back (entry); } - - popStyle(); } + popStyle(); popIfNotEmpty (_PRE); } break; @@ -2782,10 +2848,16 @@ namespace NLGUI if (!_UL.empty()) { endParagraph(); + popStyle(); popIfNotEmpty(_UL); popIfNotEmpty(_Indent); } break; + case HTML_LI: + { + popStyle(); + } + break; case HTML_DL: if (!_DL.empty()) { @@ -2801,16 +2873,19 @@ namespace NLGUI if (_DL.back().DD) { popIfNotEmpty(_Indent); + popStyle(); } popIfNotEmpty (_DL); + popStyle(); } break; case HTML_DT: if (!_DL.empty()) { + if (_DL.back().DT) + popStyle(); _DL.back().DT = false; - popStyle(); } break; case HTML_DD: @@ -2821,6 +2896,7 @@ namespace NLGUI { _DL.back().DD = false; popIfNotEmpty(_Indent); + popStyle(); } } break; @@ -4477,6 +4553,7 @@ namespace NLGUI templateParams.push_back (std::pair ("enter_recover_focus", "false")); if (maxlength > 0) templateParams.push_back (std::pair ("max_num_chars", toString(maxlength))); + CInterfaceGroup *textArea = CWidgetManager::getInstance()->getParser()->createGroupInstance (templateName.c_str(), getParagraph()->getId(), templateParams.empty()?NULL:&(templateParams[0]), (uint)templateParams.size()); diff --git a/code/nel/src/gui/libwww.cpp b/code/nel/src/gui/libwww.cpp index c8b41a38f..fef3d788e 100644 --- a/code/nel/src/gui/libwww.cpp +++ b/code/nel/src/gui/libwww.cpp @@ -101,6 +101,7 @@ namespace NLGUI HTML_ATTR(TR,L_MARGIN), HTML_ATTR(TR,NOWRAP), HTML_ATTR(TR,VALIGN), + HTML_ATTR(TR,STYLE), { 0 } }; From 33f6b64bb999969eb15390ea6d9d1ffd44b89201 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 10 Aug 2018 14:09:34 +0300 Subject: [PATCH 094/303] Changed: Add text-shadow and text-stroke style properties --HG-- branch : develop --- code/nel/include/nel/3d/text_context.h | 110 +++++++------- code/nel/include/nel/3d/text_context_user.h | 2 +- code/nel/include/nel/3d/u_text_context.h | 2 +- code/nel/include/nel/gui/group_html.h | 28 +++- code/nel/include/nel/gui/view_text.h | 4 + code/nel/src/3d/text_context.cpp | 3 +- code/nel/src/3d/text_context_user.cpp | 4 +- code/nel/src/gui/group_html.cpp | 159 +++++++++++++++++++- code/nel/src/gui/view_text.cpp | 24 +++ 9 files changed, 276 insertions(+), 60 deletions(-) diff --git a/code/nel/include/nel/3d/text_context.h b/code/nel/include/nel/3d/text_context.h index 156ea9f79..a95916da4 100644 --- a/code/nel/include/nel/3d/text_context.h +++ b/code/nel/include/nel/3d/text_context.h @@ -88,7 +88,7 @@ public: void setShadeOutline (bool b) { _ShadeOutline = b; } - void setShadeExtent (float shext) { _ShadeExtent = shext; } + void setShadeExtent (float x, float y) { _ShadeExtentX = x; _ShadeExtentY = y; } /// The alpha of the shade is multiplied at each draw with the alpha of the color. Default: (0,0,0,255) void setShadeColor (NLMISC::CRGBA color) { _ShadeColor = color; } @@ -157,19 +157,20 @@ public: rCS.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); if (_ShadeOutline) { - float rext = _ShadeExtent * 0.7071f; - rCS.render2D(*_Driver, x+rext, z-rext, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x-rext, z-rext, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x-rext, z+rext, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x+rext, z+rext, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x+_ShadeExtent, z, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x-_ShadeExtent, z, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x, z-_ShadeExtent, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x, z-_ShadeExtent, _HotSpot, _ScaleX, _ScaleZ); + float rextX = _ShadeExtentX * 0.7071f; + float rextY = _ShadeExtentY * 0.7071f; + rCS.render2D(*_Driver, x+rextX, z-rextY, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x-rextX, z-rextY, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x-rextX, z+rextY, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x+rextX, z+rextY, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x+_ShadeExtentX, z, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x-_ShadeExtentX, z, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x, z-_ShadeExtentY, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x, z-_ShadeExtentY, _HotSpot, _ScaleX, _ScaleZ); } else { - rCS.render2D(*_Driver, x+_ShadeExtent, z-_ShadeExtent, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x+_ShadeExtentX, z-_ShadeExtentY, _HotSpot, _ScaleX, _ScaleZ); } rCS.Color= bkup; } @@ -190,19 +191,20 @@ public: rCS.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); if (_ShadeOutline) { - float rext = _ShadeExtent * 0.7071f; - rCS.render2DClip(*_Driver, rdrBuffer, x+rext, z-rext, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x-rext, z-rext, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x-rext, z+rext, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x+rext, z+rext, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x+_ShadeExtent, z, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x-_ShadeExtent, z, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x, z+_ShadeExtent, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x, z-_ShadeExtent, xmin, ymin, xmax, ymax); + float rextX = _ShadeExtentX * 0.7071f; + float rextY = _ShadeExtentY * 0.7071f; + rCS.render2DClip(*_Driver, rdrBuffer, x+rextX, z-rextY, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x-rextX, z-rextY, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x-rextX, z+rextY, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x+rextX, z+rextY, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x+_ShadeExtentX, z, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x-_ShadeExtentX, z, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x, z+_ShadeExtentY, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x, z-_ShadeExtentY, xmin, ymin, xmax, ymax); } else { - rCS.render2DClip(*_Driver, rdrBuffer, x+_ShadeExtent, z-_ShadeExtent, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x+_ShadeExtentX, z-_ShadeExtentY, xmin, ymin, xmax, ymax); } rCS.Color= bkup; } @@ -223,19 +225,20 @@ public: rCS.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); if (_ShadeOutline) { - float rext = _ShadeExtent * 0.7071f; - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+rext, y-rext, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-rext, y-rext, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-rext, y+rext, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+rext, y+rext, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+_ShadeExtent, y, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-_ShadeExtent, y, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x, y+_ShadeExtent, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x, y-_ShadeExtent, depth, xmin, ymin, xmax, ymax); + float rextX = _ShadeExtentX * 0.7071f; + float rextY = _ShadeExtentY * 0.7071f; + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+rextX, y-rextY, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-rextX, y-rextY, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-rextX, y+rextY, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+rextX, y+rextY, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+_ShadeExtentX, y, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-_ShadeExtentX, y, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x, y+_ShadeExtentY, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x, y-_ShadeExtentY, depth, xmin, ymin, xmax, ymax); } else { - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+_ShadeExtent, y-_ShadeExtent, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+_ShadeExtentX, y-_ShadeExtentY, depth, xmin, ymin, xmax, ymax); } rCS.Color= bkup; } @@ -258,19 +261,20 @@ public: _TempString.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); if (_ShadeOutline) { - float rext = _ShadeExtent * 0.7071f; - _TempString.render2D(*_Driver,x+rext,z-rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x-rext,z-rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x-rext,z+rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x+rext,z+rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x+_ShadeExtent,z,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x-_ShadeExtent,z,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x,z+_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); + float rextX = _ShadeExtentX * 0.7071f; + float rextY = _ShadeExtentY * 0.7071f; + _TempString.render2D(*_Driver,x+rextX,z-rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x-rextX,z-rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x-rextX,z+rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x+rextX,z+rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x+_ShadeExtentX,z,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x-_ShadeExtentX,z,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x,z+_ShadeExtentY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x,z-_ShadeExtentY,_HotSpot,_ScaleX,_ScaleZ); } else { - _TempString.render2D(*_Driver,x+_ShadeExtent,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver, x+_ShadeExtentX, z-_ShadeExtentY, _HotSpot, _ScaleX, _ScaleZ); } _TempString.Color = bkup; } @@ -297,19 +301,20 @@ public: _TempString.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); if (_ShadeOutline) { - float rext = _ShadeExtent * 0.7071f; - _TempString.render2D(*_Driver,x+rext,z-rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x-rext,z-rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x-rext,z+rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x+rext,z+rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x+_ShadeExtent,z,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x-_ShadeExtent,z,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x,z+_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); + float rextX = _ShadeExtentX * 0.7071f; + float rextY = _ShadeExtentY * 0.7071f; + _TempString.render2D(*_Driver,x+rextX,z-rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x-rextX,z-rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x-rextX,z+rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x+rextX,z+rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x+_ShadeExtentX,z,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x-_ShadeExtentX,z,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x,z+_ShadeExtentY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x,z-_ShadeExtentY,_HotSpot,_ScaleX,_ScaleZ); } else { - _TempString.render2D(*_Driver,x+_ShadeExtent,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver, x+_ShadeExtentX, z-_ShadeExtentY, _HotSpot, _ScaleX, _ScaleZ); } _TempString.Color = bkup; } @@ -412,7 +417,8 @@ private: bool _ShadeOutline; /// shade's extent (shadow size) - float _ShadeExtent; + float _ShadeExtentX; + float _ShadeExtentY; /// Shade color (default is black) NLMISC::CRGBA _ShadeColor; diff --git a/code/nel/include/nel/3d/text_context_user.h b/code/nel/include/nel/3d/text_context_user.h index b05238dbf..15e93c3f2 100644 --- a/code/nel/include/nel/3d/text_context_user.h +++ b/code/nel/include/nel/3d/text_context_user.h @@ -80,7 +80,7 @@ public: bool getShaded() const; void setShadeOutline(bool b); bool getShadeOutline() const; - void setShadeExtent(float shext) ; + void setShadeExtent(float x, float y); void setShadeColor (NLMISC::CRGBA sc); NLMISC::CRGBA getShadeColor () const; void setKeep800x600Ratio(bool keep); diff --git a/code/nel/include/nel/3d/u_text_context.h b/code/nel/include/nel/3d/u_text_context.h index 0aa9ea2f9..4c1dfea47 100644 --- a/code/nel/include/nel/3d/u_text_context.h +++ b/code/nel/include/nel/3d/u_text_context.h @@ -205,7 +205,7 @@ public: * set the shadow's size * \param the shade extent */ - virtual void setShadeExtent (float shext) = 0; + virtual void setShadeExtent (float x, float y) = 0; /** * set the shadow's color * The alpha of the shade is multiplied at each draw with the alpha of the color. Default: (0,0,0,255) diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index 0ccd227b7..811cd3503 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -75,11 +75,26 @@ namespace NLGUI }; static SWebOptions options; - + + // text-shadow + struct STextShadow + { + public: + STextShadow(bool enabled = false, bool outline = false, sint32 x=1, sint32 y=1, NLMISC::CRGBA color=NLMISC::CRGBA::Black) + : Enabled(enabled), Outline(outline), X(x), Y(y), Color(color) + { } + + bool Enabled; + bool Outline; + sint32 X; + sint32 Y; + NLMISC::CRGBA Color; + }; + class CStyleParams { public: - CStyleParams () : FontFamily(""), TextColor(255,255,255,255) + CStyleParams () : FontFamily(""), TextColor(255,255,255,255), TextShadow() { FontSize=10; FontWeight=400; @@ -97,6 +112,7 @@ namespace NLGUI bool FontOblique; std::string FontFamily; NLMISC::CRGBA TextColor; + STextShadow TextShadow; bool GlobalColor; bool Underlined; bool StrikeThrough; @@ -595,6 +611,14 @@ namespace NLGUI return _TR.back(); } + std::vector _TextShadow; + inline STextShadow getTextShadow() const + { + if (_TextShadow.empty()) + return STextShadow(); + return _TextShadow.back(); + } + // Forms class CForm { diff --git a/code/nel/include/nel/gui/view_text.h b/code/nel/include/nel/gui/view_text.h index 8b8e1a7cf..cf53b5207 100644 --- a/code/nel/include/nel/gui/view_text.h +++ b/code/nel/include/nel/gui/view_text.h @@ -88,6 +88,7 @@ namespace NLGUI void setShadow (bool bShadow); void setShadowOutline (bool bShadowOutline); void setShadowColor (const NLMISC::CRGBA &color); + void setShadowOffset (sint x, sint y); void setLineMaxW (sint nMaxW, bool invalidate=true); void setMultiLine (bool bMultiLine); void setMultiLineSpace (sint nMultiLineSpace); @@ -112,6 +113,7 @@ namespace NLGUI bool getShadow() { return _Shadow; } bool getShadowOutline() { return _ShadowOutline; } NLMISC::CRGBA getShadowColor() { return _ShadowColor; } + void getShadowOffset(sint &x, sint &y) { x = _ShadowX; y = _ShadowY; } sint getLineMaxW() const { return _LineMaxW; } bool getMultiLine() const { return _MultiLine; } sint getMultiLineSpace() const { return _MultiLineSpace; } @@ -247,6 +249,8 @@ namespace NLGUI /// the shadow mode bool _Shadow; bool _ShadowOutline; + sint32 _ShadowX; + sint32 _ShadowY; /// the case mode TCaseMode _CaseMode; /// the text shadow color diff --git a/code/nel/src/3d/text_context.cpp b/code/nel/src/3d/text_context.cpp index 8cee144ca..5fcc43daa 100644 --- a/code/nel/src/3d/text_context.cpp +++ b/code/nel/src/3d/text_context.cpp @@ -47,7 +47,8 @@ CTextContext::CTextContext() _Shaded = false; _ShadeOutline = false; - _ShadeExtent = 0.001f; + _ShadeExtentX = 0.001f; + _ShadeExtentY = 0.001f; _ShadeColor = NLMISC::CRGBA(0,0,0); _Keep800x600Ratio= true; diff --git a/code/nel/src/3d/text_context_user.cpp b/code/nel/src/3d/text_context_user.cpp index 1834a93ce..ae2cc2417 100644 --- a/code/nel/src/3d/text_context_user.cpp +++ b/code/nel/src/3d/text_context_user.cpp @@ -187,11 +187,11 @@ bool CTextContextUser::getShadeOutline() const return _TextContext.getShadeOutline(); } -void CTextContextUser::setShadeExtent(float shext) +void CTextContextUser::setShadeExtent(float x, float y) { H_AUTO2; - _TextContext.setShadeExtent(shext); + _TextContext.setShadeExtent(x, y); } void CTextContextUser::setShadeColor (NLMISC::CRGBA sc) { diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 970178947..e8a2ac889 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -1057,6 +1057,29 @@ namespace NLGUI _CellParams.push_back (cellParams); \ } + static bool scanCssLength(const std::string& str, uint32 &px) + { + if (fromString(str, px)) + return true; + + if (str == "thin") + { + px = 1; + return true; + } + if (str == "medium") + { + px = 3; + return true; + } + if (str == "thick") + { + px = 5; + return true; + } + + return false; + } static bool isHexa(char c) { @@ -2378,6 +2401,7 @@ namespace NLGUI _Style.FontWeight = FONT_WEIGHT_NORMAL; _Style.FontOblique = false; _Style.FontSize = TextFontSize; + _Style.TextShadow = STextShadow(true); if (present[MY_HTML_TEXTAREA_STYLE] && value[MY_HTML_TEXTAREA_STYLE]) getStyleParams(value[MY_HTML_TEXTAREA_STYLE], _Style); @@ -4351,8 +4375,17 @@ namespace NLGUI if (_CurrentViewLink) { bool skipLine = !_CurrentViewLink->getText().empty() && *(_CurrentViewLink->getText().rbegin()) == (ucchar) '\n'; + bool sameShadow = _Style.TextShadow.Enabled && _CurrentViewLink->getShadow(); + if (sameShadow && _Style.TextShadow.Enabled) + { + sint sx, sy; + _CurrentViewLink->getShadowOffset(sx, sy); + sameShadow = (_Style.TextShadow.Color == _CurrentViewLink->getShadowColor()); + sameShadow = sameShadow && (_Style.TextShadow.Outline == _CurrentViewLink->getShadowOutline()); + sameShadow = sameShadow && (_Style.TextShadow.X == sx) && (_Style.TextShadow.Y == sy); + } // Compatible with current parameters ? - if (!skipLine && + if (!skipLine && sameShadow && (_Style.TextColor == _CurrentViewLink->getColor()) && (_Style.FontFamily == _CurrentViewLink->getFontName()) && (_Style.FontSize == (uint)_CurrentViewLink->getFontSize()) && @@ -4431,6 +4464,13 @@ namespace NLGUI newLink->setMultiLineSpace((uint)((float)(_Style.FontSize)*LineSpaceFontFactor)); newLink->setMultiLine(true); newLink->setModulateGlobalColor(_Style.GlobalColor); + if (_Style.TextShadow.Enabled) + { + newLink->setShadow(true); + newLink->setShadowColor(_Style.TextShadow.Color); + newLink->setShadowOutline(_Style.TextShadow.Outline); + newLink->setShadowOffset(_Style.TextShadow.X, _Style.TextShadow.Y); + } // newLink->setLineAtBottom (true); registerAnchor(newLink); @@ -4553,6 +4593,14 @@ namespace NLGUI templateParams.push_back (std::pair ("enter_recover_focus", "false")); if (maxlength > 0) templateParams.push_back (std::pair ("max_num_chars", toString(maxlength))); + templateParams.push_back (std::pair ("shadow", toString(_Style.TextShadow.Enabled))); + if (_Style.TextShadow.Enabled) + { + templateParams.push_back (std::pair ("shadow_x", toString(_Style.TextShadow.X))); + templateParams.push_back (std::pair ("shadow_y", toString(_Style.TextShadow.Y))); + templateParams.push_back (std::pair ("shadow_color", _Style.TextShadow.Color.toString())); + templateParams.push_back (std::pair ("shadow_outline", toString(_Style.TextShadow.Outline))); + } CInterfaceGroup *textArea = CWidgetManager::getInstance()->getParser()->createGroupInstance (templateName.c_str(), getParagraph()->getId(), templateParams.empty()?NULL:&(templateParams[0]), (uint)templateParams.size()); @@ -6229,6 +6277,115 @@ namespace NLGUI style.StrikeThrough = (prop.find("line-through") != std::string::npos); } else + if (it->first == "text-stroke" || it->first == "-webkit-text-stroke") + { + // text-stroke: length || color + bool success = false; + uint px = 0; + CRGBA color; + std::vector parts; + NLMISC::splitString(it->second, " ", parts); + if (parts.size() == 1) + { + success = scanCssLength(parts[0], px); + if (!success) + success = scanHTMLColor(parts[0].c_str(), color); + } + else if (parts.size() == 2) + { + success = scanCssLength(parts[0], px); + if (success) + success = scanHTMLColor(parts[1].c_str(), color); + else + { + success = scanHTMLColor(parts[0].c_str(), color); + success = success && scanCssLength(parts[1], px); + } + } + + // do not disable shadow if one is already set + if (success) + { + style.TextShadow.Enabled = (px > 0); + style.TextShadow.Color = color; + style.TextShadow.X = px; + style.TextShadow.Y = px; + style.TextShadow.Outline = true; + } + } + else + if (it->first == "text-shadow") + { + if (it->second == "none") + style.TextShadow = STextShadow(false); + else + if (it->second == "inherit") + style.TextShadow = current.TextShadow; + else + { + // text-shadow: offset-x offset-y | blur | #color + // text-shadow: #color | offset-x offset-y + bool success = true; + std::string prop(it->second); + size_t pos; + pos = prop.find_first_of(",\n\r"); + if (pos != std::string::npos) + prop = prop.substr(0, pos); + + std::vector parts; + NLMISC::splitString(prop, " ", parts); + switch(parts.size()) + { + case 1: + { + success = scanHTMLColor(it->second.c_str(), style.TextShadow.Color); + break; + } + // no case 2: + case 3: + { + if (!fromString(parts[0], style.TextShadow.X)) + { + success = scanHTMLColor(parts[0].c_str(), style.TextShadow.Color); + success = success && fromString(parts[1], style.TextShadow.X); + success = success && fromString(parts[2], style.TextShadow.Y); + } + else + { + success = fromString(parts[1], style.TextShadow.Y); + success = success && scanHTMLColor(parts[2].c_str(), style.TextShadow.Color); + } + break; + } + case 4: + { + if (!fromString(parts[0], style.TextShadow.X)) + { + success = scanHTMLColor(parts[0].c_str(), style.TextShadow.Color); + success = success && fromString(parts[1], style.TextShadow.X); + success = success && fromString(parts[2], style.TextShadow.Y); + // ignore blur [3] + } + else + { + success = fromString(parts[0], style.TextShadow.X); + success = success && fromString(parts[1], style.TextShadow.Y); + // ignore blur [2] + success = success && scanHTMLColor(parts[3].c_str(), style.TextShadow.Color); + } + break; + } + default: + { + // unsupported rule + break; + } + } + + style.TextShadow.Enabled = success; + } + } + else if (it->first == "width") getPercentage(style.Width, tmpf, it->second.c_str()); else diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index c14a7f9a1..bd10afbb9 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -72,6 +72,8 @@ namespace NLGUI _Shadow = false; _ShadowOutline = false; _ShadowColor = CRGBA(0,0,0,255); + _ShadowX = 1; + _ShadowY = 1; _MultiLine = false; _TextMode = DontClipWord; @@ -955,6 +957,19 @@ namespace NLGUI ((_YReal) > (ClipY+ClipH)) || ((_YReal+_HReal) < ClipY)) return; + // hack: allow shadow to overflow outside parent box. + // In CGroupHTML context, clip is set for row + if (std::abs(_ShadowX) > 0) + { + ClipX -= 3; + ClipW += 3; + } + if (std::abs(_ShadowY) > 0) + { + ClipY -= 3; + ClipH += 3; + } + // *** Screen Minimized? uint32 w, h; float oow, ooh; @@ -992,6 +1007,7 @@ namespace NLGUI TextContext->setShaded (_Shadow); TextContext->setShadeOutline (_ShadowOutline); TextContext->setShadeColor (shcol); + TextContext->setShadeExtent (_ShadowX*oow, _ShadowY*ooh); TextContext->setFontSize (_FontSize); TextContext->setEmbolden (_Embolden); TextContext->setOblique (_Oblique); @@ -1119,6 +1135,7 @@ namespace NLGUI TextContext->setShaded (_Shadow); TextContext->setShadeOutline (_ShadowOutline); TextContext->setShadeColor (shcol); + TextContext->setShadeExtent (_ShadowX*oow, _ShadowY*ooh); TextContext->setFontSize (_FontSize); TextContext->setEmbolden (_Embolden); TextContext->setOblique (_Oblique); @@ -1339,6 +1356,13 @@ namespace NLGUI _ShadowColor = color; } + // *************************************************************************** + void CViewText::setShadowOffset(sint32 x, sint32 y) + { + _ShadowX = x; + _ShadowY = y; + } + // *************************************************************************** void CViewText::setLineMaxW (sint nMaxW, bool invalidate) { From 15355e3815f3d3380da1a6d744481b8766ada8a3 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 11 Aug 2018 15:33:01 +0300 Subject: [PATCH 095/303] Changed: shadow attributes for CViewText and editbox templates --HG-- branch : develop --- code/nel/src/gui/view_text.cpp | 28 +++++++++++++++ .../gamedev/interfaces_v3/login_widgets.xml | 35 ++++++++++++++++--- .../data/gamedev/interfaces_v3/widgets.xml | 22 ++++++++++-- 3 files changed, 78 insertions(+), 7 deletions(-) diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index bd10afbb9..34f8fd3e1 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -438,6 +438,22 @@ namespace NLGUI return true; } else + if( name == "shadow_x" ) + { + sint sx; + if( fromString( value, sx ) ) + _ShadowX = sx; + return true; + } + else + if( name == "shadow_y" ) + { + sint sy; + if( fromString( value, sy ) ) + _ShadowY = sy; + return true; + } + else if( name == "multi_line" ) { bool b; @@ -618,6 +634,8 @@ namespace NLGUI xmlSetProp( node, BAD_CAST "shadow", BAD_CAST toString( _Shadow ).c_str() ); xmlSetProp( node, BAD_CAST "shadow_outline", BAD_CAST toString( _ShadowOutline ).c_str() ); xmlSetProp( node, BAD_CAST "shadow_color", BAD_CAST toString( _ShadowColor ).c_str() ); + xmlSetProp( node, BAD_CAST "shadow_x", BAD_CAST toString( _ShadowX ).c_str() ); + xmlSetProp( node, BAD_CAST "shadow_y", BAD_CAST toString( _ShadowY ).c_str() ); xmlSetProp( node, BAD_CAST "multi_line", BAD_CAST toString( _MultiLine ).c_str() ); std::string just; @@ -729,6 +747,16 @@ namespace NLGUI if (prop) _ShadowColor = convertColor(prop); + prop= (char*) xmlGetProp( cur, (xmlChar*)"shadow_x" ); + _ShadowX = 1; + if (prop) + fromString( (const char *)prop, _ShadowX); + + prop= (char*) xmlGetProp( cur, (xmlChar*)"shadow_y" ); + _ShadowY = 1; + if (prop) + fromString( (const char *)prop, _ShadowY); + prop = (char*) xmlGetProp( cur, (xmlChar*)"multi_line" ); _MultiLine = false; if (prop) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/login_widgets.xml b/code/ryzom/client/data/gamedev/interfaces_v3/login_widgets.xml index 660cb4f9d..6d7ac1fa7 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/login_widgets.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/login_widgets.xml @@ -75,6 +75,11 @@ keep="true" max_historic="0" fontsize="10" + shadow="true" + shadow_x="1" + shadow_y="1" + shadow_color="0 0 0 255" + shadow_outline="false" backup_father_container_pos="false" want_return="false" color="255 255 255 255" @@ -93,7 +98,7 @@ - + @@ -114,6 +119,11 @@ fontsize="10" fontweight="" fontstyle="" + shadow="true" + shadow_x="1" + shadow_y="1" + shadow_color="0 0 0 255" + shadow_outline="false" backup_father_container_pos="false" want_return="false" color="255 255 255 255" @@ -124,7 +134,7 @@ - + @@ -153,6 +163,11 @@ keep="true" max_historic="40" fontsize="10" + shadow="true" + shadow_x="1" + shadow_y="1" + shadow_color="0 0 0 255" + shadow_outline="false" backup_father_container_pos="false" want_return="false" color="255 255 255 255" @@ -162,7 +177,7 @@ - + @@ -397,6 +412,11 @@ keep="true" max_historic="40" fontsize="10" + shadow="true" + shadow_x="1" + shadow_y="1" + shadow_color="0 0 0 255" + shadow_outline="false" backup_father_container_pos="false" want_return="false" color="255 255 255 255" @@ -407,7 +427,7 @@ - + @@ -435,6 +455,11 @@ keep="true" max_historic="40" fontsize="10" + shadow="true" + shadow_x="1" + shadow_y="1" + shadow_color="0 0 0 255" + shadow_outline="false" backup_father_container_pos="false" want_return="false" color="255 255 255 255" @@ -444,7 +469,7 @@ - + diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml b/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml index e5ece5680..62c202815 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml @@ -2653,6 +2653,11 @@ keep="true" max_historic="40" fontsize="10" + shadow="true" + shadow_x="1" + shadow_y="1" + shadow_color="0 0 0 255" + shadow_outline="false" backup_father_container_pos="false" want_return="false" clear_on_escape="false" @@ -2722,7 +2727,11 @@ multi_line_space="0" fontsize="#fontsize" color="#color" - shadow="true" + shadow="#shadow" + shadow_x="#shadow_x" + shadow_y="#shadow_y" + shadow_color="#shadow_color" + shadow_outline="#shadow_outline" hardtext="" global_color="false" /> @@ -2826,6 +2835,11 @@ keep="true" max_historic="40" fontsize="10" + shadow="true" + shadow_x="1" + shadow_y="1" + shadow_color="0 0 0 255" + shadow_outline="false" backup_father_container_pos="false" want_return="false" color="255 255 255 255" @@ -2886,7 +2900,11 @@ multi_min_line="#multi_min_line" fontsize="#fontsize" color="#color" - shadow="true" + shadow="#shadow" + shadow_x="#shadow_x" + shadow_y="#shadow_y" + shadow_color="#shadow_color" + shadow_outline="#shadow_outline" hardtext="" global_color="false" render_layer="#render_layer" /> From c7ded068d9c93c13fa440f2dabe90d64f8307afc Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 11 Aug 2018 15:34:42 +0200 Subject: [PATCH 096/303] Fixed: Compilation (reverted back some changes) --HG-- branch : develop --- code/ryzom/server/src/ai_service/event_reaction.h | 2 +- code/ryzom/server/src/ai_service/event_reaction_include.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/ryzom/server/src/ai_service/event_reaction.h b/code/ryzom/server/src/ai_service/event_reaction.h index 57dcf22d0..31689f613 100644 --- a/code/ryzom/server/src/ai_service/event_reaction.h +++ b/code/ryzom/server/src/ai_service/event_reaction.h @@ -90,7 +90,7 @@ public: // the following routine shouldn't be needed it should be superceded by a better alternative // in the event manager template - bool testCompatibility(const CStateInstance *stateInstance, const TState *state) const + bool testCompatibility(CStateInstance *const stateInstance, const TState *const state) const; protected: // protected data --------------------------------------------------- diff --git a/code/ryzom/server/src/ai_service/event_reaction_include.h b/code/ryzom/server/src/ai_service/event_reaction_include.h index 04fd2c16f..3c44b03dc 100644 --- a/code/ryzom/server/src/ai_service/event_reaction_include.h +++ b/code/ryzom/server/src/ai_service/event_reaction_include.h @@ -28,7 +28,7 @@ #include "continent.h"*/ template -bool CAIEventReaction::testCompatibility(const CStateInstance *stateInstance, const TState *state) const +bool CAIEventReaction::testCompatibility(CStateInstance *const stateInstance, const TState *const state) const { if (!stateInstance) return false; From ad99c2afb79180f94d8d1833ba2755b3fde4c968 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 11 Aug 2018 15:35:13 +0200 Subject: [PATCH 097/303] Fixed: Warning (missing return) --HG-- branch : develop --- code/ryzom/server/src/ai_service/fx_entity.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ryzom/server/src/ai_service/fx_entity.h b/code/ryzom/server/src/ai_service/fx_entity.h index 74ea07f91..028ee3ad9 100644 --- a/code/ryzom/server/src/ai_service/fx_entity.h +++ b/code/ryzom/server/src/ai_service/fx_entity.h @@ -32,7 +32,7 @@ public: NLMISC::CEntityId const& id() const; bool spawn(); void despawn(); - bool update() { } + bool update() { return false; } void set(std::string const& prop, std::string const& value, bool reportChange=false) { } std::string get(std::string const& prop); std::string getIndexString() const { return _EntityId.toString(); } From ad98b1414a5cbf344775f59fc85eb93014180f7f Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 11 Aug 2018 15:35:40 +0200 Subject: [PATCH 098/303] Changed: Minor changes --HG-- branch : develop --- code/ryzom/server/src/ai_service/ai_bot.cpp | 1 - code/ryzom/server/src/ai_service/ai_grp_npc.h | 2 +- code/ryzom/server/src/ai_service/ai_script_comp.h | 8 ++------ 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/code/ryzom/server/src/ai_service/ai_bot.cpp b/code/ryzom/server/src/ai_service/ai_bot.cpp index 2fb47023a..6698de755 100644 --- a/code/ryzom/server/src/ai_service/ai_bot.cpp +++ b/code/ryzom/server/src/ai_service/ai_bot.cpp @@ -88,7 +88,6 @@ void CSpawnBot::setVisualPropertiesName() return; // the npc name is displayed as a fauna } - CVisualPropertiesInterface::setName(dataSetRow(), name); } diff --git a/code/ryzom/server/src/ai_service/ai_grp_npc.h b/code/ryzom/server/src/ai_service/ai_grp_npc.h index bac75d1a9..1f838584d 100644 --- a/code/ryzom/server/src/ai_service/ai_grp_npc.h +++ b/code/ryzom/server/src/ai_service/ai_grp_npc.h @@ -190,7 +190,7 @@ public: uint32 getAggroDist() { return _AggroDist; } uint32& despawnTime() { return _DespawnTime; } - uint32& respawnTime() { return _RespawnTime; } + uint32& respawnTime() { return _RespawnTime; } AITYPES::CPropertySetWithExtraList& faction() { return _faction; } AITYPES::CPropertySetWithExtraList& ennemyFaction() { return _ennemyFaction; } diff --git a/code/ryzom/server/src/ai_service/ai_script_comp.h b/code/ryzom/server/src/ai_service/ai_script_comp.h index a35253d66..d4782ac18 100644 --- a/code/ryzom/server/src/ai_service/ai_script_comp.h +++ b/code/ryzom/server/src/ai_service/ai_script_comp.h @@ -56,9 +56,7 @@ public: static CFightScriptCompReader *getScriptReader (const std::string &str); - static CFightScriptComp *createScriptComp (const std::string &str) -protected: -private: + static CFightScriptComp *createScriptComp(const std::string &str); }; @@ -74,8 +72,6 @@ public: typedef CHashMap > TFightScriptMap; static TFightScriptMap _ScriptCompList; -protected: -private: }; @@ -116,7 +112,7 @@ public: CFightSelectFilterReader() {} virtual ~CFightSelectFilterReader() {} - CFightScriptComp *create (const std::string &inStr) + CFightScriptComp *create(const std::string &inStr); std::string getName () const { return std::string("SELECT"); From b86bf43090444ef92e789b1bd93f7064b288a634 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 11 Aug 2018 21:47:50 +0200 Subject: [PATCH 099/303] Fixed: Simplify certificates management --HG-- branch : develop --- code/nel/include/nel/gui/curl_certificates.h | 3 - code/nel/include/nel/gui/group_html.h | 2 - code/nel/src/gui/curl_certificates.cpp | 121 +++++++++++------- code/nel/src/gui/group_html.cpp | 12 -- code/ryzom/client/src/http_client_curl.cpp | 3 - .../src/interface_v3/interface_manager.cpp | 12 +- 6 files changed, 78 insertions(+), 75 deletions(-) diff --git a/code/nel/include/nel/gui/curl_certificates.h b/code/nel/include/nel/gui/curl_certificates.h index ee6938842..9d5ad4855 100644 --- a/code/nel/include/nel/gui/curl_certificates.h +++ b/code/nel/include/nel/gui/curl_certificates.h @@ -27,9 +27,6 @@ namespace NLGUI class CCurlCertificates { public: - // check if compiled with OpenSSL backend - static void init(CURL *curl); - // allow to use custom PEM certificates static void addCertificateFile(const std::string &cert); diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index 811cd3503..c96b67456 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -66,8 +66,6 @@ namespace NLGUI std::vector< std::string > trustedDomains; /// Maximum concurrent MultiCurl connections per CGroupHTML instance sint32 curlMaxConnections; - /// cacert.pem location - std::string curlCABundle; SWebOptions(): curlMaxConnections(2) { diff --git a/code/nel/src/gui/curl_certificates.cpp b/code/nel/src/gui/curl_certificates.cpp index 7d26e7e5a..fa3cd10f0 100644 --- a/code/nel/src/gui/curl_certificates.cpp +++ b/code/nel/src/gui/curl_certificates.cpp @@ -40,29 +40,43 @@ namespace NLGUI class SX509Certificates { public: - std::vector CertList; - std::vector FilesList; + struct CertEntry + { + X509 *cert; + std::string name; + std::string file; + + bool operator == (const std::string &str) + { + return file == str; + } + }; + + std::vector CertList; bool isUsingOpenSSLBackend; bool isInitialized; SX509Certificates():isUsingOpenSSLBackend(false), isInitialized(false) { + init(); } ~SX509Certificates() { for (uint i = 0; i < CertList.size(); ++i) { - X509_free(CertList[i]); + X509_free(CertList[i].cert); } CertList.clear(); } - void init(CURL *curl) + void init() { - if (isInitialized) return; + // init CURL + CURL *curl = curl_easy_init(); + if (!curl) return; // get information on CURL curl_version_info_data *data = curl_version_info(CURLVERSION_NOW); @@ -98,9 +112,39 @@ namespace NLGUI isUsingOpenSSLBackend = false; } + // clean up CURL + curl_easy_cleanup(curl); + isInitialized = true; } + static std::string getCertName(X509 *cert) + { + // NULL certificate + if (!cert) return ""; + + X509_NAME *subject = X509_get_subject_name(cert); + + std::string name; + unsigned char *tmp = NULL; + + // construct a multiline string with name + for (int j = 0, jlen = X509_NAME_entry_count(subject); j < jlen; ++j) + { + X509_NAME_ENTRY *e = X509_NAME_get_entry(subject, j); + ASN1_STRING *d = X509_NAME_ENTRY_get_data(e); + + if (ASN1_STRING_to_UTF8(&tmp, d) > 0) + { + name += NLMISC::toString("%s\n", tmp); + + OPENSSL_free(tmp); + } + } + + return name; + } + #ifdef NL_OS_WINDOWS void addCertificatesFrom(LPCSTR root) { @@ -114,38 +158,36 @@ namespace NLGUI { x509 = NULL; x509 = d2i_X509(NULL, (const unsigned char **)&pContext->pbCertEncoded, pContext->cbCertEncoded); + if (x509) { - CertList.push_back(x509); + CertEntry entry; + entry.cert = x509; + entry.file = root; + entry.name = getCertName(x509); + + CertList.push_back(entry); } } + CertFreeCertificateContext(pContext); CertCloseStore(hStore, 0); } // this is called before debug context is set and log ends up in log.log - nlinfo("Loaded %d certificates from '%s' certificate store", (int)CertList.size(), root); + //nlinfo("Loaded %d certificates from '%s' certificate store", (int)CertList.size(), root); } #endif void addCertificatesFromFile(const std::string &cert) { - if (!isUsingOpenSSLBackend) return; - - if (!isInitialized) - { - nlwarning("You MUST call NLGUI::CCurlCertificates::init before adding new certificates"); - return; - } + if (!isInitialized || !isUsingOpenSSLBackend) return; // this file was already loaded - if (std::find(FilesList.begin(), FilesList.end(), cert) != FilesList.end()) return; - - FilesList.push_back(cert); + if (std::find(CertList.begin(), CertList.end(), cert) != CertList.end()) return; // look for certificate in search paths string path = CPath::lookup(cert, false); - nlinfo("Cert path '%s'", path.c_str()); if (path.empty()) { @@ -153,6 +195,8 @@ namespace NLGUI return; } + nlinfo("CURL CA bundle '%s'", path.c_str()); + CIFile file; // open certificate @@ -184,7 +228,12 @@ namespace NLGUI if (itmp && itmp->x509) { - CertList.push_back(X509_dup(itmp->x509)); + CertEntry entry; + entry.cert = X509_dup(itmp->x509); + entry.file = cert; + entry.name = getCertName(entry.cert); + + CertList.push_back(entry); } } @@ -224,27 +273,10 @@ namespace NLGUI for (uint i = 0, ilen = x509CertListManager.CertList.size(); i < ilen; ++i) { - X509_NAME *subject = X509_get_subject_name(x509CertListManager.CertList[i]); - - std::string name; - unsigned char *tmp = NULL; - - // construct a multiline string with name - for (int j = 0, jlen = X509_NAME_entry_count(subject); j < jlen; ++j) - { - X509_NAME_ENTRY *e = X509_NAME_get_entry(subject, j); - ASN1_STRING *d = X509_NAME_ENTRY_get_data(e); - - if (ASN1_STRING_to_UTF8(&tmp, d) > 0) - { - name += NLMISC::toString("%s\n", tmp); - - OPENSSL_free(tmp); - } - } + SX509Certificates::CertEntry entry = x509CertListManager.CertList[i]; // add our certificate to this store - if (X509_STORE_add_cert(x509store, x509CertListManager.CertList[i]) == 0) + if (X509_STORE_add_cert(x509store, entry.cert) == 0) { uint errCode = ERR_get_error(); @@ -252,13 +284,13 @@ namespace NLGUI if (ERR_GET_LIB(errCode) != ERR_LIB_X509 || ERR_GET_REASON(errCode) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { ERR_error_string_n(errCode, errorBuffer, 1024); - nlwarning("Error adding certificate %s: %s", name.c_str(), errorBuffer); + nlwarning("Error adding certificate %s: %s", entry.name.c_str(), errorBuffer); res = CURLE_SSL_CACERT; } } else { - nldebug("Added certificate %s", name.c_str()); + nldebug("Added certificate %s", entry.name.c_str()); } } } @@ -275,13 +307,6 @@ namespace NLGUI return res; } - // *************************************************************************** - // static - void CCurlCertificates::init(CURL *curl) - { - x509CertListManager.init(curl); - } - // *************************************************************************** // static void CCurlCertificates::addCertificateFile(const std::string &cert) @@ -294,7 +319,7 @@ namespace NLGUI void CCurlCertificates::useCertificates(CURL *curl) { // CURL must be valid, using OpenSSL backend and certificates must be loaded, else return - if (!curl || !x509CertListManager.isUsingOpenSSLBackend || x509CertListManager.CertList.empty()) return; + if (!curl || !x509CertListManager.isInitialized || !x509CertListManager.isUsingOpenSSLBackend || x509CertListManager.CertList.empty()) return; curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM"); diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index e8a2ac889..9a987d450 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -398,12 +398,6 @@ namespace NLGUI // https:// if (toLower(download.url.substr(0, 8)) == "https://") { - // check if compiled with OpenSSL backend - CCurlCertificates::init(curl); - - // specify custom CA certs - CCurlCertificates::addCertificateFile(options.curlCABundle); - // if supported, use custom SSL context function to load certificates CCurlCertificates::useCertificates(curl); } @@ -5410,12 +5404,6 @@ namespace NLGUI // https:// if (toLower(url.substr(0, 8)) == "https://") { - // check if compiled with OpenSSL backend - CCurlCertificates::init(curl); - - // specify custom CA certs - CCurlCertificates::addCertificateFile(options.curlCABundle); - // if supported, use custom SSL context function to load certificates CCurlCertificates::useCertificates(curl); } diff --git a/code/ryzom/client/src/http_client_curl.cpp b/code/ryzom/client/src/http_client_curl.cpp index 2887543c3..16436516b 100644 --- a/code/ryzom/client/src/http_client_curl.cpp +++ b/code/ryzom/client/src/http_client_curl.cpp @@ -71,9 +71,6 @@ bool CCurlHttpClient::verifyServer(bool verify) curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYHOST, verify ? 2 : 0); curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYPEER, verify ? 1 : 0); - // check if compiled with OpenSSL backend - NLGUI::CCurlCertificates::init(_Curl); - // specify custom CA certs NLGUI::CCurlCertificates::addCertificateFile(CAFilename); diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 53eddd7b9..6ec32a34d 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -113,6 +113,8 @@ #include "nel/gui/lua_helper.h" using namespace NLGUI; #include "nel/gui/lua_ihm.h" +#include "nel/gui/curl_certificates.h" + #include "lua_ihm_ryzom.h" #include "add_on_manager.h" @@ -471,15 +473,11 @@ CInterfaceManager::CInterfaceManager() CGroupHTML::options.appName = getUserAgentName(); CGroupHTML::options.appVersion = getUserAgentVersion(); CGroupHTML::options.curlMaxConnections = ClientCfg.CurlMaxConnections; + if (!ClientCfg.CurlCABundle.empty()) { - string filename = CPath::lookup(ClientCfg.CurlCABundle, false); - if (!filename.empty()) - { - filename = CPath::getFullPath(filename, false); - CGroupHTML::options.curlCABundle = filename; - nlinfo("curl ca bundle '%s'", filename.c_str()); - } + // specify custom CA certs, lookup will be made in this function + NLGUI::CCurlCertificates::addCertificateFile(ClientCfg.CurlCABundle); } NLGUI::CDBManager::getInstance()->resizeBanks( NB_CDB_BANKS ); From adc89b3a82410bce94ed9525faf170b7aa076f27 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 18 Aug 2018 09:16:14 +0300 Subject: [PATCH 100/303] Fixed: style inheritance for underline, strikethrough --HG-- branch : develop --- code/nel/src/gui/group_html.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 9a987d450..45398102b 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -6175,6 +6175,12 @@ namespace NLGUI { const CStyleParams current = _Style; + if (inherit) + { + style.Underlined = current.Underlined; + style.StrikeThrough = current.StrikeThrough; + } + float tmpf; TStyle styles = parseStyle(styleString); TStyle::iterator it; @@ -6396,11 +6402,6 @@ namespace NLGUI style.GlobalColor = b; } } - if (inherit) - { - style.Underlined = current.Underlined || style.Underlined; - style.StrikeThrough = current.StrikeThrough || style.StrikeThrough; - } } // *************************************************************************** From 40dc2188f268f71d9488c1efb42ce90079b195b6 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 18 Aug 2018 10:53:04 +0200 Subject: [PATCH 101/303] Fixed: Check CURL backend on old CURL versions (tested with 7.22) --HG-- branch : develop --- code/nel/src/gui/curl_certificates.cpp | 51 +++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/code/nel/src/gui/curl_certificates.cpp b/code/nel/src/gui/curl_certificates.cpp index fa3cd10f0..11053545a 100644 --- a/code/nel/src/gui/curl_certificates.cpp +++ b/code/nel/src/gui/curl_certificates.cpp @@ -25,6 +25,14 @@ #include +// for compatibility with older versions +#ifndef CURL_AT_LEAST_VERSION +#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z) +#define CURL_AT_LEAST_VERSION(x,y,z) \ + (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) +#endif + + using namespace std; using namespace NLMISC; @@ -81,6 +89,9 @@ namespace NLGUI // get information on CURL curl_version_info_data *data = curl_version_info(CURLVERSION_NOW); + bool useOpenSSLBackend = false; + +#if CURL_AT_LEAST_VERSION(7, 34, 0) // get more information on CURL session curl_tlssessioninfo *sessionInfo; @@ -94,8 +105,30 @@ namespace NLGUI CURLcode res = curl_easy_getinfo(curl, info, &sessionInfo); + // CURL using OpenSSL backend + if ((res == CURLE_OK) && sessionInfo && sessionInfo->backend == CURLSSLBACKEND_OPENSSL) useOpenSSLBackend = true; +#elif CURL_AT_LEAST_VERSION(7, 12, 3) + // get a list of OpenSSL engines + struct curl_slist *engines; + + CURLcode res = curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines); + + // CURL using OpenSSL backend + // With OpenSSL compiled without any engine, engines will too return NULL + // Fortunately, if OpenSSL isn't compiled with engines means we compiled it ourself and CURL is a recent version + if ((res == CURLE_OK) && engine) + { + // free engines + curl_slist_free_all(engines); + + useOpenSSLBackend = true; + } +#else + // TODO: implement an equivalent, but CURL 7.12 was released in 2004 +#endif + // only use OpenSSL callback if not using Windows SSPI and using OpenSSL backend - if (!res && sessionInfo && sessionInfo->backend == CURLSSLBACKEND_OPENSSL && !(data && data->features & CURL_VERSION_SSPI)) + if (useOpenSSLBackend && !(data && data->features & CURL_VERSION_SSPI)) { #ifdef NL_OS_WINDOWS // load native Windows CA Certs @@ -181,7 +214,21 @@ namespace NLGUI void addCertificatesFromFile(const std::string &cert) { - if (!isInitialized || !isUsingOpenSSLBackend) return; + if (!isInitialized) + { + nlwarning("CURL not initialized! Check if there are another errors"); + return; + } + + if (!isUsingOpenSSLBackend) + { + nlinfo("CURL not using OpenSSL backend! Unable to use custom certificates"); + return; + } + else + { + nlinfo("CURL using OpenSSL backend!"); + } // this file was already loaded if (std::find(CertList.begin(), CertList.end(), cert) != CertList.end()) return; From 58efd082c112c552660e33c43775acef872c6058 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 18 Aug 2018 10:57:33 +0200 Subject: [PATCH 102/303] Changed: Don't include curl.h in headers to avoid dependencies on CURL for more files that required --HG-- branch : develop --- code/nel/include/nel/gui/group_html.h | 10 +- code/nel/include/nel/gui/libwww.h | 5 +- code/nel/src/gui/group_html.cpp | 91 ++++++++++--------- code/nel/src/gui/libwww.cpp | 2 + .../src/interface_v3/group_html_webig.cpp | 2 + 5 files changed, 57 insertions(+), 53 deletions(-) diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index c96b67456..9c48149bf 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -17,8 +17,6 @@ #ifndef CL_GROUP_HTML_H #define CL_GROUP_HTML_H -#include - #include "nel/misc/types_nl.h" #include "nel/gui/interface_group.h" #include "nel/gui/group_scrolltext.h" @@ -27,6 +25,9 @@ #include "nel/gui/group_table.h" #include "nel/gui/libwww_types.h" +// forward declaration +typedef void CURLM; + typedef std::map TStyle; namespace NLGUI @@ -856,11 +857,6 @@ namespace NLGUI // HtmlType download finished void htmlDownloadFinished(const std::string &content, const std::string &type, long code); - - // cURL transfer callbacks - static size_t curlHeaderCallback(char *buffer, size_t size, size_t nmemb, void *pCCurlWWWData); - static size_t curlDataCallback(char *buffer, size_t size, size_t nmemb, void *pCCurlWWWData); - static size_t curlProgressCallback(void *pCCurlWWWData, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); }; // adapter group that store y offset for inputs inside an html form diff --git a/code/nel/include/nel/gui/libwww.h b/code/nel/include/nel/gui/libwww.h index 892e07eb2..64258608e 100644 --- a/code/nel/include/nel/gui/libwww.h +++ b/code/nel/include/nel/gui/libwww.h @@ -20,11 +20,12 @@ #ifndef CL_LIB_WWW_H #define CL_LIB_WWW_H -#include - #include "nel/misc/rgba.h" #include "nel/gui/libwww_types.h" +// forward declaration to avoid curl.h inclusion everywhere +typedef void CURL; + namespace NLGUI { class CCtrlBaseButton; diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 45398102b..fdf32f44c 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -49,6 +49,8 @@ #include "nel/gui/http_hsts.h" #include "nel/gui/curl_certificates.h" +#include + using namespace std; using namespace NLMISC; @@ -205,6 +207,47 @@ namespace NLGUI std::map HeadersRecv; }; + // cURL transfer callbacks + // *************************************************************************** + static size_t curlHeaderCallback(char *buffer, size_t size, size_t nmemb, void *pCCurlWWWData) + { + CCurlWWWData * me = static_cast(pCCurlWWWData); + if (me) + { + std::string header; + header.append(buffer, size * nmemb); + me->setRecvHeader(header.substr(0, header.find_first_of("\n\r"))); + } + + return size * nmemb; + } + + // *************************************************************************** + static size_t curlDataCallback(char *buffer, size_t size, size_t nmemb, void *pCCurlWWWData) + { + CCurlWWWData * me = static_cast(pCCurlWWWData); + if (me) + me->Content.append(buffer, size * nmemb); + + return size * nmemb; + } + + // *************************************************************************** + static size_t curlProgressCallback(void *pCCurlWWWData, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) + { + CCurlWWWData * me = static_cast(pCCurlWWWData); + if (me) + { + if (dltotal > 0 || dlnow > 0 || ultotal > 0 || ulnow > 0) + { + nlwarning("> dltotal %d, dlnow %d, ultotal %d, ulnow %d, url '%s'", dltotal, dlnow, ultotal, ulnow, me->Url.c_str()); + } + } + + // return 1 to cancel download + return 0; + } + // Check if domain is on TrustedDomain bool CGroupHTML::isTrustedDomain(const string &domain) { @@ -423,7 +466,7 @@ namespace NLGUI download.data->sendHeaders(headers); // catch headers - curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curlHeaderCallback); + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, NLGUI::curlHeaderCallback); curl_easy_setopt(curl, CURLOPT_WRITEHEADER, download.data); std::string userAgent = options.appName + "/" + options.appVersion; @@ -5476,17 +5519,17 @@ namespace NLGUI _CurlWWW->sendHeaders(headers); // catch headers for redirect - curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curlHeaderCallback); + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, NLGUI::curlHeaderCallback); curl_easy_setopt(curl, CURLOPT_WRITEHEADER, _CurlWWW); // catch body - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlDataCallback); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NLGUI::curlDataCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, _CurlWWW); #if LOG_DL // progress callback curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); - curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, curlProgressCallback); + curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, NLGUI::curlProgressCallback); curl_easy_setopt(curl, CURLOPT_XFERINFODATA, _CurlWWW); #else // progress off @@ -6472,46 +6515,6 @@ namespace NLGUI } } - // *************************************************************************** - size_t CGroupHTML::curlHeaderCallback(char *buffer, size_t size, size_t nmemb, void *pCCurlWWWData) - { - CCurlWWWData * me = static_cast(pCCurlWWWData); - if (me) - { - std::string header; - header.append(buffer, size * nmemb); - me->setRecvHeader(header.substr(0, header.find_first_of("\n\r"))); - } - - return size * nmemb; - } - - // *************************************************************************** - size_t CGroupHTML::curlDataCallback(char *buffer, size_t size, size_t nmemb, void *pCCurlWWWData) - { - CCurlWWWData * me = static_cast(pCCurlWWWData); - if (me) - me->Content.append(buffer, size * nmemb); - - return size * nmemb; - } - - // *************************************************************************** - size_t CGroupHTML::curlProgressCallback(void *pCCurlWWWData, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) - { - CCurlWWWData * me = static_cast(pCCurlWWWData); - if (me) - { - if (dltotal > 0 || dlnow > 0 || ultotal > 0 || ulnow > 0) - { - nlwarning("> dltotal %d, dlnow %d, ultotal %d, ulnow %d, url '%s'", dltotal, dlnow, ultotal, ulnow, me->Url.c_str()); - } - } - - // return 1 to cancel download - return 0; - } - // *************************************************************************** std::string CGroupHTML::HTMLOListElement::getListMarkerText() const { diff --git a/code/nel/src/gui/libwww.cpp b/code/nel/src/gui/libwww.cpp index fef3d788e..2e9b4451a 100644 --- a/code/nel/src/gui/libwww.cpp +++ b/code/nel/src/gui/libwww.cpp @@ -19,6 +19,8 @@ #include "nel/gui/libwww.h" #include "nel/gui/group_html.h" +#include + using namespace NLMISC; #ifdef DEBUG_NEW diff --git a/code/ryzom/client/src/interface_v3/group_html_webig.cpp b/code/ryzom/client/src/interface_v3/group_html_webig.cpp index 58d27c851..fe2fa5229 100644 --- a/code/ryzom/client/src/interface_v3/group_html_webig.cpp +++ b/code/ryzom/client/src/interface_v3/group_html_webig.cpp @@ -28,6 +28,8 @@ #include "../net_manager.h" #include "../connection.h" +#include + using namespace std; using namespace NLMISC; From 1380a94f5d9db9ac70e265010736662bc2f9282f Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 18 Aug 2018 11:12:26 +0200 Subject: [PATCH 103/303] Changed: Use LIST(APPEND instead of SET --HG-- branch : develop --- code/CMakeModules/FindHelpers.cmake | 36 +++++++++++++-------------- code/CMakeModules/FindSteam.cmake | 2 +- code/ryzom/client/src/login_patch.cpp | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/code/CMakeModules/FindHelpers.cmake b/code/CMakeModules/FindHelpers.cmake index a4af37229..874555820 100644 --- a/code/CMakeModules/FindHelpers.cmake +++ b/code/CMakeModules/FindHelpers.cmake @@ -692,11 +692,11 @@ MACRO(ADD_QT_LIBRARY _NAME) ENDIF() SET(_LIB "${QT_LIBRARY_DIR}/${_PREFIX}${_NAME}.${_EXT}") IF(EXISTS ${_LIB}) - SET(QT_LIBRARIES ${QT_LIBRARIES} optimized ${_LIB}) + LIST(APPEND QT_LIBRARIES optimized ${_LIB}) ENDIF() SET(_LIB "${QT_LIBRARY_DIR}/${_PREFIX}${_NAME}d.${_EXT}") IF(EXISTS ${_LIB}) - SET(QT_LIBRARIES ${QT_LIBRARIES} debug ${_LIB}) + LIST(APPEND QT_LIBRARIES debug ${_LIB}) ENDIF() ENDMACRO() @@ -710,11 +710,11 @@ MACRO(ADD_QT_PLUGIN _TYPE _NAME) ENDIF() SET(_LIB "${QT_PLUGINS_DIR}/${_TYPE}/${_PREFIX}${_NAME}.${_EXT}") IF(EXISTS ${_LIB}) - SET(QT_LIBRARIES ${QT_LIBRARIES} optimized ${_LIB}) + LIST(APPEND QT_LIBRARIES optimized ${_LIB}) ENDIF() SET(_LIB "${QT_PLUGINS_DIR}/${_TYPE}/${_PREFIX}${_NAME}d.${_EXT}") IF(EXISTS ${_LIB}) - SET(QT_LIBRARIES ${QT_LIBRARIES} debug ${_LIB}) + LIST(APPEND QT_LIBRARIES debug ${_LIB}) ENDIF() ENDMACRO() @@ -789,12 +789,12 @@ MACRO(FIND_QT5) SET(QT_LIBRARIES Qt5::Widgets) # Gui - SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::Gui Qt5::OpenGL) + LIST(APPEND QT_LIBRARIES Qt5::Gui Qt5::OpenGL) ADD_QT_LIBRARY(PrintSupport) IF(WIN32) - SET(QT_LIBRARIES ${QT_LIBRARIES} + LIST(APPEND QT_LIBRARIES ${WINSDK_LIBRARY_DIR}/Imm32.lib ${WINSDK_LIBRARY_DIR}/OpenGL32.lib ${WINSDK_LIBRARY_DIR}/WinMM.Lib) @@ -812,7 +812,7 @@ MACRO(FIND_QT5) FIND_LIBRARY(SYSTEMCONFIGURATION_FRAMEWORK SystemConfiguration) FIND_LIBRARY(OPENGL_FRAMEWORK NAMES OpenGL) - SET(QT_LIBRARIES ${QT_LIBRARIES} + LIST(APPEND QT_LIBRARIES ${CUPS_LIBRARY} ${COCOA_FRAMEWORK} ${SYSTEMCONFIGURATION_FRAMEWORK} @@ -839,7 +839,7 @@ MACRO(FIND_QT5) ADD_QT_LIBRARY(DBus) IF(EXISTS "${QT_LIBRARY_DIR}/libxcb-static.a") - SET(QT_LIBRARIES ${QT_LIBRARIES} "${QT_LIBRARY_DIR}/libxcb-static.a") + LIST(APPEND QT_LIBRARIES "${QT_LIBRARY_DIR}/libxcb-static.a") ENDIF() # always link these in dynamic, API never changes @@ -871,14 +871,14 @@ MACRO(FIND_QT5) SET(HB_LIB "${QT_LIBRARY_DIR}/qtharfbuzzng.lib") ENDIF() IF(EXISTS ${HB_LIB}) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${HB_LIB}) + LIST(APPEND QT_LIBRARIES ${HB_LIB}) ENDIF() # freetype is needed since Qt 5.5 FIND_PACKAGE(Freetype) IF(FREETYPE_FOUND) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${FREETYPE_LIBRARIES}) + LIST(APPEND QT_LIBRARIES ${FREETYPE_LIBRARIES}) ELSE() IF(UNIX) SET(FREETYPE_LIB "${QT_LIBRARY_DIR}/libqtfreetype.a") @@ -886,27 +886,27 @@ MACRO(FIND_QT5) SET(FREETYPE_LIB "${QT_LIBRARY_DIR}/qtfreetype.lib") ENDIF() IF(EXISTS ${FREETYPE_LIB}) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${FREETYPE_LIB}) + LIST(APPEND QT_LIBRARIES ${FREETYPE_LIB}) ENDIF() ENDIF() ADD_QT_PLUGIN(accessible qtaccessiblewidgets) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${PNG_LIBRARIES} ${JPEG_LIBRARY}) + LIST(APPEND QT_LIBRARIES ${PNG_LIBRARIES} ${JPEG_LIBRARY}) # Network - SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::Network Qt5::Xml) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES}) + LIST(APPEND QT_LIBRARIES Qt5::Network Qt5::Xml) + LIST(APPEND QT_LIBRARIES ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES}) IF(WIN32) - SET(QT_LIBRARIES ${QT_LIBRARIES} + LIST(APPEND QT_LIBRARIES ${WINSDK_LIBRARY_DIR}/Crypt32.lib ${WINSDK_LIBRARY_DIR}/WS2_32.Lib ${WINSDK_LIBRARY_DIR}/IPHlpApi.Lib) ENDIF() # Core - SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::Core) + LIST(APPEND QT_LIBRARIES Qt5::Core) # pcre is needed since Qt 5.5 IF(UNIX) @@ -918,7 +918,7 @@ MACRO(FIND_QT5) SET(PCRE_LIB "${QT_LIBRARY_DIR}/qtpcre.lib") ENDIF() IF(EXISTS ${PCRE_LIB}) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${PCRE_LIB}) + LIST(APPEND QT_LIBRARIES ${PCRE_LIB}) ENDIF() IF(APPLE) @@ -926,7 +926,7 @@ MACRO(FIND_QT5) FIND_LIBRARY(SECURITY_FRAMEWORK Security) - SET(QT_LIBRARIES ${QT_LIBRARIES} + LIST(APPEND QT_LIBRARIES ${PCRE_LIBRARY} ${FOUNDATION_FRAMEWORK} ${CARBON_FRAMEWORK} diff --git a/code/CMakeModules/FindSteam.cmake b/code/CMakeModules/FindSteam.cmake index 5657312eb..8d9b12372 100644 --- a/code/CMakeModules/FindSteam.cmake +++ b/code/CMakeModules/FindSteam.cmake @@ -2,7 +2,7 @@ # This module defines # STEAM_LIBRARY, the library to link against # STEAM_FOUND, if false, do not try to link to STEAM -# STEA%_INCLUDE_DIR, where to find headers. +# STEAM_INCLUDE_DIR, where to find headers. IF(STEAM_LIBRARY AND STEAM_INCLUDE_DIR) # in cache already diff --git a/code/ryzom/client/src/login_patch.cpp b/code/ryzom/client/src/login_patch.cpp index 6a3500ae0..f4e7e237f 100644 --- a/code/ryzom/client/src/login_patch.cpp +++ b/code/ryzom/client/src/login_patch.cpp @@ -101,7 +101,7 @@ struct EPatchDownloadException : public Exception { EPatchDownloadException() : Exception( "Download Error" ) {} EPatchDownloadException( const std::string& str ) : Exception( str ) {} - virtual ~EPatchDownloadException() {} + virtual ~EPatchDownloadException() throw(){} }; From 6da051e1a82832b791c843a6b8187de6539500b4 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 18 Aug 2018 11:12:47 +0200 Subject: [PATCH 104/303] Changed: New macro FIX_PACKAGE_OPTIONS --HG-- branch : develop --- code/CMakeModules/FindHelpers.cmake | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/code/CMakeModules/FindHelpers.cmake b/code/CMakeModules/FindHelpers.cmake index 874555820..ab8df32a6 100644 --- a/code/CMakeModules/FindHelpers.cmake +++ b/code/CMakeModules/FindHelpers.cmake @@ -38,6 +38,21 @@ MACRO(PARSE_VERSION_OTHER FILENAME) ENDIF() ENDMACRO() +# macro to define FIND_PACKAGE options with a different package name +MACRO(FIX_PACKAGE_OPTIONS OLDNAME NEWNAME) + # append other options if needed + SET(_OPTIONS COMPONENTS REQUIRED QUIETLY) + + # process each options + FOREACH(_OPTION ${_OPTIONS}) + SET(OLD_OPTION ${OLDNAME}_FIND_${_OPTION}) + IF(DEFINED ) + SET(NEW_OPTION ${NEWNAME}_FIND_${_OPTION}) + SET(${NEW_OPTION} ${OLD_OPTION}) + ENDIF() + ENDFOREACH() +ENDMACRO() + MACRO(FIND_PACKAGE_HELPER NAME INCLUDE) # Looks for a directory containing NAME. # From 964e32cd93b5e44d90e6154617999b14303a1a6d Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 18 Aug 2018 11:13:10 +0200 Subject: [PATCH 105/303] Changed: Use Threads CMake module and CMAKE_DL_LIBS --HG-- branch : develop --- code/CMakeModules/FindHelpers.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/CMakeModules/FindHelpers.cmake b/code/CMakeModules/FindHelpers.cmake index ab8df32a6..bc38354f4 100644 --- a/code/CMakeModules/FindHelpers.cmake +++ b/code/CMakeModules/FindHelpers.cmake @@ -947,7 +947,8 @@ MACRO(FIND_QT5) ${CARBON_FRAMEWORK} ${SECURITY_FRAMEWORK}) ELSEIF(UNIX) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${ZLIB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} -ldl -lrt) + FIND_PACKAGE(Threads) + LIST(APPEND QT_LIBRARIES ${ZLIB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS} -lrt) ENDIF() ELSE() SET(QT_LIBRARIES Qt5::Widgets Qt5::Network Qt5::Xml Qt5::Gui Qt5::OpenGL Qt5::Core) From 06a4244df36c1d6ac8af63f86f3d4db60436287a Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 18 Aug 2018 11:14:14 +0200 Subject: [PATCH 106/303] Changed: Include NeL in RyzomGameShare CMake module --HG-- branch : develop --- code/CMakeModules/FindRyzomGameShare.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/CMakeModules/FindRyzomGameShare.cmake b/code/CMakeModules/FindRyzomGameShare.cmake index 56eb94569..f76e4dd93 100644 --- a/code/CMakeModules/FindRyzomGameShare.cmake +++ b/code/CMakeModules/FindRyzomGameShare.cmake @@ -3,6 +3,10 @@ INCLUDE(FindHelpers) FIND_PACKAGE_HELPER(RyzomGameShare game_share/continent.h RELEASE ryzom_gameshare_r ryzom_gameshare DEBUG ryzom_gameshare_d DIR ${NEL_DIR} ${RYZOM_DIR} SUFFIXES ryzom) IF(RYZOMGAMESHARE_FOUND) + FIND_PACKAGE(NeL REQUIRED) + LIST(APPEND RYZOMGAMESHARE_INCLUDE_DIRS ${NEL_INCLUDE_DIRS}) + LIST(APPEND RYZOMGAMESHARE_LIBRARIES ${NELMISC_LIBRARIES} ${NELLIGO_LIBRARIES} ${NELNET_LIBRARIES} ${NELGEORGES_LIBRARIES}) + SET(RYZOM_GAMESHARE_LIBRARIES ${RYZOMGAMESHARE_LIBRARIES}) SET(RYZOM_GAMESHARE_FOUND ${RYZOMGAMESHARE_FOUND}) SET(RYZOM_GAMESHARE_INCLUDE_DIR ${RYZOMGAMESHARE_INCLUDE_DIR}) From 6097ada1fa52c347561c4cf7bce52972741aff0e Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 18 Aug 2018 11:20:37 +0200 Subject: [PATCH 107/303] Changed: Removed other throws --HG-- branch : develop --- code/nel/include/nel/net/module_gateway.h | 7 ++----- code/nel/src/net/module_gateway.cpp | 3 --- code/nel/src/net/module_local_gateway.cpp | 4 ---- .../object_viewer/particle_system/particle_node.cpp | 2 +- 4 files changed, 3 insertions(+), 13 deletions(-) diff --git a/code/nel/include/nel/net/module_gateway.h b/code/nel/include/nel/net/module_gateway.h index 75d386162..40da736a3 100644 --- a/code/nel/include/nel/net/module_gateway.h +++ b/code/nel/include/nel/net/module_gateway.h @@ -171,8 +171,7 @@ namespace NLNET virtual void setTransportPeerInvisible(const std::string &transportInstanceName, bool peerInvisible) =0; /// Activate/stop firewalling mode on a transport - virtual void setTransportFirewallMode(const std::string &transportInstanceName, bool firewalled) - throw (EGatewayFirewallBreak) =0; + virtual void setTransportFirewallMode(const std::string &transportInstanceName, bool firewalled) =0; /// Send a command to a transport virtual void transportCommand(const TParsedCommandLine &commandLine) =0; @@ -233,9 +232,7 @@ namespace NLNET /** Disclose module information to a connected gateway. * This can also be this gateway itself. */ - virtual void discloseModule(IModuleProxy *moduleProxy) - throw (EGatewayNotConnected) - =0; + virtual void discloseModule(IModuleProxy *moduleProxy) =0; /** Retrieve the proxy for a locally plugged module. * Each local module plugged in a gateway has an associated diff --git a/code/nel/src/net/module_gateway.cpp b/code/nel/src/net/module_gateway.cpp index 0acb4375d..d4d07ea61 100644 --- a/code/nel/src/net/module_gateway.cpp +++ b/code/nel/src/net/module_gateway.cpp @@ -448,7 +448,6 @@ namespace NLNET /// Activate/stop firewalling mode on a transport virtual void setTransportFirewallMode(const std::string &transportInstanceName, bool firewalled) - throw (EGatewayFirewallBreak) { TTransportList::iterator it(_Transports.find(transportInstanceName)); if (it == _Transports.end()) @@ -1246,7 +1245,6 @@ namespace NLNET } virtual void discloseModule(IModuleProxy *moduleProxy) - throw (EGatewayNotConnected) { nlassert(moduleProxy->getModuleGateway() == this); @@ -1584,7 +1582,6 @@ namespace NLNET } virtual void _broadcastModuleMessage(IModule *senderModule, const NLNET::CMessage &message) - throw (EModuleNotPluggedHere) { H_AUTO(CModuleGetaway__broadcastModuleMessage); // send the message to all proxies (except the sender module) diff --git a/code/nel/src/net/module_local_gateway.cpp b/code/nel/src/net/module_local_gateway.cpp index 292a6cafe..0782c2d2c 100644 --- a/code/nel/src/net/module_local_gateway.cpp +++ b/code/nel/src/net/module_local_gateway.cpp @@ -102,7 +102,6 @@ namespace NLNET /// Activate/stop firewalling mode on a transport virtual void setTransportFirewallMode(const std::string &/* transportInstanceName */, bool /* firewalled */) - throw (EGatewayFirewallBreak) { // unsupported nlstop; @@ -174,12 +173,10 @@ namespace NLNET // return; // } // virtual void openGatewayServer(uint16 listeningPort) -// throw (EGatewayAlreadyOpen, EGatewayPortInUse) // { // nlstop; // } // virtual void closeGatewayServer() -// throw (EGatewayNotOpen) // { // nlstop; // } @@ -233,7 +230,6 @@ namespace NLNET { } virtual void discloseModule(IModuleProxy *moduleProxy) - throw (EGatewayNotConnected) { // check that the module is plugged here nlassert(_ModuleProxies.getB(moduleProxy) != NULL); diff --git a/code/studio/src/plugins/object_viewer/particle_system/particle_node.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_node.cpp index 7bffe2fa3..d8a7573ec 100644 --- a/code/studio/src/plugins/object_viewer/particle_system/particle_node.cpp +++ b/code/studio/src/plugins/object_viewer/particle_system/particle_node.cpp @@ -340,7 +340,7 @@ std::string CParticleWorkspace::getFilename() const return CFile::getFilename(_Filename); } -CWorkspaceNode *CParticleWorkspace::addNode(const std::string &filenameWithFullPath) throw( NLMISC::Exception) +CWorkspaceNode *CParticleWorkspace::addNode(const std::string &filenameWithFullPath) { // Check that file is not already inserted std::string fileName = NLMISC::CFile::getFilename(filenameWithFullPath); From 729ba2ebbda876f58079632a87c53c4e5d6eaf64 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 18 Aug 2018 11:51:55 +0200 Subject: [PATCH 108/303] Fixed: Typo --HG-- branch : develop --- code/nel/src/gui/curl_certificates.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/src/gui/curl_certificates.cpp b/code/nel/src/gui/curl_certificates.cpp index 11053545a..6d1bc86ee 100644 --- a/code/nel/src/gui/curl_certificates.cpp +++ b/code/nel/src/gui/curl_certificates.cpp @@ -116,7 +116,7 @@ namespace NLGUI // CURL using OpenSSL backend // With OpenSSL compiled without any engine, engines will too return NULL // Fortunately, if OpenSSL isn't compiled with engines means we compiled it ourself and CURL is a recent version - if ((res == CURLE_OK) && engine) + if ((res == CURLE_OK) && engines) { // free engines curl_slist_free_all(engines); From dd03e1f0b1130fbc570d0e71563b8c5408ac927b Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 18 Aug 2018 14:15:32 +0300 Subject: [PATCH 109/303] Fixed: Remove onenter callback from html textarea --HG-- branch : develop --- code/nel/src/gui/group_html.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index fdf32f44c..b606a093d 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -4627,6 +4627,7 @@ namespace NLGUI if (multiLine) templateParams.push_back (std::pair ("multi_min_line", toString(rows))); templateParams.push_back (std::pair ("want_return", multiLine?"true":"false")); + templateParams.push_back (std::pair ("onenter", "")); templateParams.push_back (std::pair ("enter_recover_focus", "false")); if (maxlength > 0) templateParams.push_back (std::pair ("max_num_chars", toString(maxlength))); From fc32dc92b9b6085f1602531caa0c9760c84d80a9 Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Mon, 20 Aug 2018 20:06:36 +0800 Subject: [PATCH 110/303] Test two-way github sync --- .gitignore | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 6d75a91f5..1d7b8efd4 100644 --- a/.gitignore +++ b/.gitignore @@ -216,6 +216,7 @@ code/ryzom/server/src/ryzom_admin_service/ryzom_admin_service code/ryzom/server/src/ryzom_naming_service/ryzom_naming_service code/ryzom/server/src/ryzom_welcome_service/ryzom_welcome_service code/ryzom/server/src/tick_service/tick_service + # WebTT temp dir code/ryzom/tools/server/www/webtt/app/tmp @@ -236,13 +237,13 @@ code/ryzom/tools/server/ryzom_ams/old -#tools and external dir's +# Tools and external directories external external_stlport nel_tools* ryzom_tools* -#Dumps +# Dumps *.dmp code/nel/tools/build_gamedata/processes/ai_wmap/ai_build_wmap.cfg From 0f44a7da27fc5dd261db83d5d85abda8596ebbd7 Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Fri, 24 Aug 2018 09:30:56 +0800 Subject: [PATCH 111/303] Fix pointer accessed after delete --- code/ryzom/client/src/r2/dmc/client_edition_module.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/ryzom/client/src/r2/dmc/client_edition_module.cpp b/code/ryzom/client/src/r2/dmc/client_edition_module.cpp index a3da447dc..66dd94c9f 100644 --- a/code/ryzom/client/src/r2/dmc/client_edition_module.cpp +++ b/code/ryzom/client/src/r2/dmc/client_edition_module.cpp @@ -1312,8 +1312,8 @@ void CClientEditionModule::onUserComponentDownloaded(NLNET::IModuleProxy *sender if (decompressionState != Z_OK) { - delete component; - nlwarning("Error: the downloaded user component is corrupted '%s' ", component->Filename.c_str()); + nlwarning("Error: the downloaded user component is corrupted '%s'", component->Filename.c_str()); + delete component; return; } component->UncompressedData[component->UncompressedDataLength] = '\0'; From 37c567c88c57b3bd8442507a7f24469d94e0684a Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Sat, 25 Aug 2018 15:31:58 +0800 Subject: [PATCH 112/303] File ai_instance.cpp uses inline processStateEvent from state_instance.h which uses inline testCompatibility from event_reaction_include.h https://gist.github.com/sjvs/8795aae6671734ff991033b510e62de5 --- code/ryzom/server/src/ai_service/ai_instance.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/ryzom/server/src/ai_service/ai_instance.cpp b/code/ryzom/server/src/ai_service/ai_instance.cpp index ef7c4aea9..a4da91956 100644 --- a/code/ryzom/server/src/ai_service/ai_instance.cpp +++ b/code/ryzom/server/src/ai_service/ai_instance.cpp @@ -1566,3 +1566,5 @@ NLMISC_COMMAND(simulateMsgDespawnEasterEgg, "", " Date: Sat, 25 Aug 2018 16:18:24 +0800 Subject: [PATCH 113/303] Change travis options --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ec12c9989..20f9ef43e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ os: matrix: fast_finish: true env: - - CMAKE_CONFIGURE_OPTIONS="-DWITH_NEL_TESTS=OFF -DWITH_NEL_SAMPLES=OFF -DWITH_LUA51=ON -DWITH_RYZOM_SERVER=OFF -DWITH_RYZOM_TOOLS=OFF -DWITH_NEL_TOOLS=OFF" + - CMAKE_CONFIGURE_OPTIONS="-DWITH_NEL_TESTS=OFF -DWITH_NEL_SAMPLES=ON -DWITH_LUA51=ON -DWITH_RYZOM_SERVER=ON -DWITH_RYZOM_TOOLS=OFF -DWITH_NEL_TOOLS=OFF" - CMAKE_CONFIGURE_OPTIONS="-DCPPTEST_LIBRARY_DEBUG:STRING=/usr/lib/libcpptest.so" CMAKE_BUILD_OPTIONS="--target nel_unit_test -- -j 2" RUN="build/bin/nel_unit_test" From df129ed657844b38465b0a3c3a0c4ab77937a272 Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Sat, 25 Aug 2018 17:36:22 +0800 Subject: [PATCH 114/303] Put previous config back since it exceeds time limit --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 20f9ef43e..33b3d0f8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ os: matrix: fast_finish: true env: - - CMAKE_CONFIGURE_OPTIONS="-DWITH_NEL_TESTS=OFF -DWITH_NEL_SAMPLES=ON -DWITH_LUA51=ON -DWITH_RYZOM_SERVER=ON -DWITH_RYZOM_TOOLS=OFF -DWITH_NEL_TOOLS=OFF" + - CMAKE_CONFIGURE_OPTIONS="-DWITH_NEL_TESTS=OFF -DWITH_NEL_SAMPLES=ON -DWITH_LUA51=ON -DWITH_RYZOM_SERVER=OFF -DWITH_RYZOM_TOOLS=OFF -DWITH_NEL_TOOLS=OFF" - CMAKE_CONFIGURE_OPTIONS="-DCPPTEST_LIBRARY_DEBUG:STRING=/usr/lib/libcpptest.so" CMAKE_BUILD_OPTIONS="--target nel_unit_test -- -j 2" RUN="build/bin/nel_unit_test" From ea95d8e0919f933001c17edbd204c5551d406e0b Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 26 Aug 2018 22:58:48 +0300 Subject: [PATCH 115/303] Fixed: HTML list element invalidates content on each frame --HG-- branch : develop --- code/nel/include/nel/gui/interface_element.h | 3 +++ code/nel/include/nel/gui/interface_group.h | 1 + code/nel/src/gui/group_paragraph.cpp | 4 ++-- code/nel/src/gui/group_table.cpp | 10 ++++++++-- code/nel/src/gui/interface_element.cpp | 10 ++++++++-- code/nel/src/gui/interface_group.cpp | 15 ++++++++++++--- code/nel/src/gui/view_text.cpp | 3 +-- 7 files changed, 35 insertions(+), 11 deletions(-) diff --git a/code/nel/include/nel/gui/interface_element.h b/code/nel/include/nel/gui/interface_element.h index cd82417d6..1a360bbc6 100644 --- a/code/nel/include/nel/gui/interface_element.h +++ b/code/nel/include/nel/gui/interface_element.h @@ -182,6 +182,9 @@ namespace NLGUI void setMarginLeft(sint32 m) { _MarginLeft = m; } sint32 getMarginLeft() const { return _MarginLeft; } + // Return inner width for child elements + virtual sint32 getInnerWidth() const; + /** * Get the max width used by the window. * diff --git a/code/nel/include/nel/gui/interface_group.h b/code/nel/include/nel/gui/interface_group.h index b9efd3357..01f2b9701 100644 --- a/code/nel/include/nel/gui/interface_group.h +++ b/code/nel/include/nel/gui/interface_group.h @@ -164,6 +164,7 @@ namespace NLGUI sint32 getMaxH () const { return _MaxH; } sint32 getMaxWReal () const { return _Active ? _MaxWReal : 0; } sint32 getMaxHReal () const { return _Active ? _MaxHReal : 0; } + sint32 getInnerWidth () const; sint32 getOfsX () const { return _OffsetX; } sint32 getOfsY () const { return _OffsetY; } bool getResizeFromChildW() const { return _ResizeFromChildW; } diff --git a/code/nel/src/gui/group_paragraph.cpp b/code/nel/src/gui/group_paragraph.cpp index b2635b52e..d7d50af2e 100644 --- a/code/nel/src/gui/group_paragraph.cpp +++ b/code/nel/src/gui/group_paragraph.cpp @@ -1410,7 +1410,7 @@ namespace NLGUI // Get the child width maxWidth += _Elements[k].Element->getMaxUsedW(); } - return maxWidth; + return maxWidth + _MarginLeft; } // ---------------------------------------------------------------------------- @@ -1425,7 +1425,7 @@ namespace NLGUI if (width > minWidth) minWidth = width; } - return minWidth; + return minWidth + _MarginLeft; } diff --git a/code/nel/src/gui/group_table.cpp b/code/nel/src/gui/group_table.cpp index ef3eca57a..4408bc9c3 100644 --- a/code/nel/src/gui/group_table.cpp +++ b/code/nel/src/gui/group_table.cpp @@ -703,7 +703,7 @@ namespace NLGUI { if (ContinuousUpdate) { - sint parentWidth = std::min(_Parent->getMaxWReal(), _Parent->getWReal()); + sint parentWidth = _Parent->getInnerWidth(); if (_LastParentW != (sint) parentWidth) { _LastParentW = parentWidth; @@ -1163,7 +1163,7 @@ namespace NLGUI { if (_Parent != NULL) { - sint parentWidth = std::min(_Parent->getMaxWReal(), _Parent->getWReal()); + sint parentWidth = _Parent->getInnerWidth(); if (_LastParentW != (sint) parentWidth) { if (ContinuousUpdate) @@ -1311,6 +1311,9 @@ namespace NLGUI // ---------------------------------------------------------------------------- void CGroupTable::draw () { + // move X for clip and borders + _XReal += _MarginLeft; + // search a parent container CInterfaceGroup *gr = getParent(); while (gr) @@ -1391,6 +1394,9 @@ namespace NLGUI } CInterfaceGroup::draw (); + + // restore + _XReal -= _MarginLeft; } std::string CGroupTable::getProperties( const std::string &name ) const diff --git a/code/nel/src/gui/interface_element.cpp b/code/nel/src/gui/interface_element.cpp index 2e13d80e6..d3ed2d01c 100644 --- a/code/nel/src/gui/interface_element.cpp +++ b/code/nel/src/gui/interface_element.cpp @@ -506,10 +506,16 @@ namespace NLGUI } } + // ------------------------------------------------------------------------------------------------ + sint32 CInterfaceElement::getInnerWidth() const + { + return _WReal - _MarginLeft; + } + // ------------------------------------------------------------------------------------------------ void CInterfaceElement::updateCoords() { - _XReal = _X + _MarginLeft; + _XReal = _X; _YReal = _Y; _WReal = getW(); _HReal = getH(); @@ -526,7 +532,7 @@ namespace NLGUI if (el == NULL) return; - _XReal += el->_XReal - el->_MarginLeft; + _XReal += el->_XReal; _YReal += el->_YReal; THotSpot hsParent = _ParentPosRef; diff --git a/code/nel/src/gui/interface_group.cpp b/code/nel/src/gui/interface_group.cpp index d349411e1..5640da530 100644 --- a/code/nel/src/gui/interface_group.cpp +++ b/code/nel/src/gui/interface_group.cpp @@ -1397,6 +1397,13 @@ namespace NLGUI restoreClip (oldSciX, oldSciY, oldSciW, oldSciH); } + // ------------------------------------------------------------------------------------------------ + sint32 CInterfaceGroup::getInnerWidth() const + { + sint width = CInterfaceElement::getInnerWidth(); + return std::min(width, _MaxWReal - _MarginLeft); + } + // ------------------------------------------------------------------------------------------------ void CInterfaceGroup::checkCoords() { @@ -1468,7 +1475,7 @@ namespace NLGUI pIE->updateCoords(); } - _XReal -= _OffsetX - _MarginLeft; + _XReal -= (_OffsetX + _MarginLeft); _YReal -= _OffsetY; } @@ -1958,9 +1965,11 @@ namespace NLGUI newSciH = newSciH - ((newSciY+newSciH)-(oldSciY+oldSciH)); } - newSciXDest = newSciX - _MarginLeft; + // Don't apply margins because HTML list marker is drawn outside group paragraph inner content. + // Should not be an issue because horizontal scolling not used. + newSciXDest = newSciX/* + _MarginLeft*/; newSciYDest = newSciY; - newSciWDest = newSciW + _MarginLeft; + newSciWDest = newSciW/* - _MarginLeft*/; newSciHDest = newSciH; } diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index 34f8fd3e1..805143f32 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -916,8 +916,7 @@ namespace NLGUI return _LineMaxW; else { - sint parentWidth = std::min(_Parent->getMaxWReal(), _Parent->getWReal() - _Parent->getMarginLeft()); - return std::min(parentWidth-(sint)(_XReal-(_Parent->getXReal()-_Parent->getMarginLeft())), (sint)_LineMaxW); + return std::min(_Parent->getInnerWidth(), (sint)_LineMaxW); } } From f5c8335fa985a8ef2b609d8bac6fb882bbd7ecee Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 26 Aug 2018 22:58:48 +0300 Subject: [PATCH 116/303] Fixed: Wrong table width if colspan is used --HG-- branch : develop --- code/nel/src/gui/group_table.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/code/nel/src/gui/group_table.cpp b/code/nel/src/gui/group_table.cpp index 4408bc9c3..b10114a18 100644 --- a/code/nel/src/gui/group_table.cpp +++ b/code/nel/src/gui/group_table.cpp @@ -813,10 +813,6 @@ namespace NLGUI for(sint span = 0; span < cell->ColSpan -1; ++span) { ++column; - _Columns[column].Width = std::max(_Columns[column].Width, _Columns[column-1].Width); - _Columns[column].WidthMax = std::max(_Columns[column].WidthMax, _Columns[column-1].WidthMax); - _Columns[column].TableRatio = std::max(_Columns[column].TableRatio, _Columns[column-1].TableRatio); - _Columns[column].WidthWanted = std::max(_Columns[column].WidthWanted, _Columns[column-1].WidthWanted); _Columns[column].RowSpan = _Columns[column-1].RowSpan; } } From 4f7c082a4a6dd4746782833833727ed9910d660a Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 27 Sep 2018 08:30:33 +0300 Subject: [PATCH 117/303] Fixed: Wrong text width --HG-- branch : develop --- code/nel/src/gui/view_text.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index 805143f32..cfc2c3b92 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -916,7 +916,8 @@ namespace NLGUI return _LineMaxW; else { - return std::min(_Parent->getInnerWidth(), (sint)_LineMaxW); + sint offset = (sint)_XReal - (sint)_Parent->getXReal(); + return std::min(_Parent->getInnerWidth() - offset, (sint)_LineMaxW); } } From c2ffa714d2efdfe686a92b755e1851df0a8e86f5 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 27 Sep 2018 12:36:09 +0300 Subject: [PATCH 118/303] Fixed: Wrong width for container list element --HG-- branch : develop --- code/nel/src/gui/group_container.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/nel/src/gui/group_container.cpp b/code/nel/src/gui/group_container.cpp index 1922db221..26a23fd9f 100644 --- a/code/nel/src/gui/group_container.cpp +++ b/code/nel/src/gui/group_container.cpp @@ -2473,7 +2473,7 @@ namespace NLGUI if (_LayerSetup == 0) { - _List->forceSizeW(_W - pLayer->W_M_Open); + _List->forceSizeW(_W - (pLayer->W_M_Open + pLayer->W_R) ); } else { @@ -2748,6 +2748,9 @@ namespace NLGUI if (_Content != NULL) h += _Content->getHReal(); + if (_List != NULL) + h += _List->getHReal(); + h -= _ContentYOffset; } else From ace1684f5c66a6318ad9bec17b661bb0fdb5e3f5 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 11 Oct 2018 21:51:00 +0300 Subject: [PATCH 119/303] Fixed: Ingame UI restored wrongly if window resized in char select mode --HG-- branch : develop --- code/ryzom/client/src/connection.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/code/ryzom/client/src/connection.cpp b/code/ryzom/client/src/connection.cpp index 7fd707354..ec9f3dee8 100644 --- a/code/ryzom/client/src/connection.cpp +++ b/code/ryzom/client/src/connection.cpp @@ -1241,6 +1241,16 @@ TInterfaceState globalMenu() // Restore video mode if (ClientCfg.SelectCharacter == -1) { + if (ClientCfg.Windowed) + { + // if used changed window resolution in char select + // if we don't update ClientCfg, then UI from icfg is restored wrong + uint32 width, height; + Driver->getWindowSize(width, height); + ClientCfg.Width = width; + ClientCfg.Height = height; + } + connectionRestoreVideoMode (); } From 94861ac7090e2602fa3e708bb67f8a6ae99b9326 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 11 Oct 2018 21:54:02 +0300 Subject: [PATCH 120/303] Changed: Make sure char select window resolution is at least 1024x768 --HG-- branch : develop --- code/ryzom/client/src/connection.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/ryzom/client/src/connection.cpp b/code/ryzom/client/src/connection.cpp index ec9f3dee8..ef1a491ab 100644 --- a/code/ryzom/client/src/connection.cpp +++ b/code/ryzom/client/src/connection.cpp @@ -201,9 +201,9 @@ void connectionRestoreVideoMode () mode.Height = height; } - // don't allow sizes smaller than 800x600 - if (ClientCfg.Width < 800) ClientCfg.Width = 800; - if (ClientCfg.Height < 600) ClientCfg.Height = 600; + // don't allow sizes smaller than 1024x768 + if (ClientCfg.Width < 1024) ClientCfg.Width = 1024; + if (ClientCfg.Height < 768) ClientCfg.Height = 768; if (StereoDisplay) StereoDisplayAttached = StereoDisplay->attachToDisplay(); From f4ef386ec9a86d6227a5ed3d3fab89ffb566aca7 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 11 Oct 2018 23:30:37 +0300 Subject: [PATCH 121/303] Changed: Limit fullscreen resolutions to 1024x768 or higher --HG-- branch : develop --- code/ryzom/client/src/misc.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/code/ryzom/client/src/misc.cpp b/code/ryzom/client/src/misc.cpp index 0f87b8037..97aaea128 100644 --- a/code/ryzom/client/src/misc.cpp +++ b/code/ryzom/client/src/misc.cpp @@ -1404,13 +1404,12 @@ bool getRyzomModes(std::vector &videoModes, std::vectorgetModes(videoModes); - // Remove modes under 800x600 and get the unique strings + // Remove modes under 1024x768 (outgame ui limitation) and get the unique strings sint i, j; for (i = 0; i < (sint)videoModes.size(); ++i) { - if ((videoModes[i].Width < 800) || (videoModes[i].Height < 600)) + if ((videoModes[i].Width < 1024) || (videoModes[i].Height < 768)) { - // discard modes under 800x600 videoModes.erase(videoModes.begin()+i); --i; } From 9aa52bc26753fbc073377c77c3b6f4bb512cfaaf Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 20 Oct 2018 19:07:32 +0300 Subject: [PATCH 122/303] Fixed: Scale button height as needed based on text height --HG-- branch : develop --- code/nel/src/gui/ctrl_text_button.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/src/gui/ctrl_text_button.cpp b/code/nel/src/gui/ctrl_text_button.cpp index 81dfcc953..6e1fab26e 100644 --- a/code/nel/src/gui/ctrl_text_button.cpp +++ b/code/nel/src/gui/ctrl_text_button.cpp @@ -899,7 +899,7 @@ namespace NLGUI } if (!(_SizeRef & 2)) { - _H= _BmpH; + _H= max(_BmpH, _ViewText->getH()); } CViewBase::updateCoords(); From 12ec528b5a92582efefbf30e8d8cff1d437261a9 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 20 Oct 2018 19:07:32 +0300 Subject: [PATCH 123/303] Fixed: Mouse events on partially hidden elemnts --HG-- branch : develop --- code/nel/include/nel/gui/interface_group.h | 10 ++++++- code/nel/src/gui/interface_group.cpp | 32 ++++++++++++++++++---- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/code/nel/include/nel/gui/interface_group.h b/code/nel/include/nel/gui/interface_group.h index 01f2b9701..5f864e9e9 100644 --- a/code/nel/include/nel/gui/interface_group.h +++ b/code/nel/include/nel/gui/interface_group.h @@ -101,6 +101,9 @@ namespace NLGUI // test is a group is a direct child of this interface group bool isChildGroup(const CInterfaceGroup *group) const; + // test is x,y is inside last draw clip aread + bool isInViewport(sint32 x, sint32 y) const; + virtual bool isWindowUnder (sint32 x, sint32 y); // Virtual for menu that is not square CInterfaceGroup *getGroupUnder (sint32 x, sint32 y); virtual bool getViewsUnder (sint32 x, sint32 y, sint32 clipX, sint32 clipY, sint32 clipW, sint32 clipH, std::vector &vVB); // Return true if x,y under the group @@ -341,8 +344,13 @@ namespace NLGUI void alignElements(); protected: + /// Last clip area cached from draw call + sint32 _LastClipX; + sint32 _LastClipY; + sint32 _LastClipW; + sint32 _LastClipH; - void makeNewClip (sint32 &oldClipX, sint32 &oldClipY, sint32 &oldClipW, sint32 &oldClipH); + void makeNewClip (sint32 &oldClipX, sint32 &oldClipY, sint32 &oldClipW, sint32 &oldClipH, bool drawing = false); void restoreClip (sint32 oldSciX, sint32 oldSciY, sint32 oldSciW, sint32 oldSciH); // Compute clip contribution for current window, and a previous clipping rectangle. This doesn't change the clip window in the driver. diff --git a/code/nel/src/gui/interface_group.cpp b/code/nel/src/gui/interface_group.cpp index 789030a4a..3da60c9f2 100644 --- a/code/nel/src/gui/interface_group.cpp +++ b/code/nel/src/gui/interface_group.cpp @@ -77,6 +77,11 @@ namespace NLGUI _LUAEnvTableCreated= false; _DepthForZSort= 0.f; + _LastClipX = 0; + _LastClipY = 0; + _LastClipW = 0; + _LastClipH = 0; + #ifdef AJM_DEBUG_TRACK_INTERFACE_GROUPS CInterfaceManager::getInstance()->DebugTrackGroupsCreated( this ); #endif @@ -1254,7 +1259,8 @@ namespace NLGUI { const NLGUI::CEventDescriptorMouse &eventDesc = (const NLGUI::CEventDescriptorMouse &)event; - if (!isIn(eventDesc.getX(), eventDesc.getY())) + // group might be partially hidden (scolling) so test against last visible area + if (!isInViewport(eventDesc.getX(), eventDesc.getY())) return false; bool taken = false; @@ -1299,7 +1305,6 @@ namespace NLGUI } if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousewheel) { - // handle the Mouse Wheel only if interesting if (_H>_MaxH) { CInterfaceGroup *currParent = _Parent; @@ -1329,7 +1334,7 @@ namespace NLGUI void CInterfaceGroup::draw () { sint32 oldSciX, oldSciY, oldSciW, oldSciH; - makeNewClip (oldSciX, oldSciY, oldSciW, oldSciH); + makeNewClip (oldSciX, oldSciY, oldSciW, oldSciH, true); // Display sons only if not total clipped CViewRenderer &rVR = *CViewRenderer::getInstance(); @@ -1718,6 +1723,16 @@ namespace NLGUI (y <= (_YReal + _HReal))); } + // ------------------------------------------------------------------------------------------------ + bool CInterfaceGroup::isInViewport(sint32 x, sint32 y) const + { + return ( + (x > _LastClipX) && + (x < (_LastClipX + _LastClipW))&& + (y > _LastClipY) && + (y < (_LastClipY + _LastClipH))); + } + // ------------------------------------------------------------------------------------------------ CInterfaceGroup* CInterfaceGroup::getGroupUnder (sint32 x, sint32 y) { @@ -1976,11 +1991,10 @@ namespace NLGUI newSciYDest = newSciY; newSciWDest = newSciW/* - _MarginLeft*/; newSciHDest = newSciH; - } // ------------------------------------------------------------------------------------------------ - void CInterfaceGroup::makeNewClip (sint32 &oldSciX, sint32 &oldSciY, sint32 &oldSciW, sint32 &oldSciH) + void CInterfaceGroup::makeNewClip (sint32 &oldSciX, sint32 &oldSciY, sint32 &oldSciW, sint32 &oldSciH, bool drawing) { CViewRenderer &rVR = *CViewRenderer::getInstance(); rVR.getClipWindow (oldSciX, oldSciY, oldSciW, oldSciH); @@ -1988,6 +2002,14 @@ namespace NLGUI sint32 newSciX, newSciY, newSciW, newSciH; computeCurrentClipContribution(oldSciX, oldSciY, oldSciW, oldSciH, newSciX, newSciY, newSciW, newSciH); rVR.setClipWindow (newSciX, newSciY, newSciW, newSciH); + + if (drawing) + { + _LastClipX = newSciX; + _LastClipY = newSciY; + _LastClipW = newSciW; + _LastClipH = newSciH; + } } // ------------------------------------------------------------------------------------------------ From c74a56f3b961fe787c9a03d7bdb0821525319c33 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 20 Oct 2018 19:07:32 +0300 Subject: [PATCH 124/303] Fixed: Streaming source did not report finished state correctly --HG-- branch : develop --- code/nel/include/nel/sound/stream_file_source.h | 3 ++- code/nel/src/sound/stream_file_source.cpp | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/code/nel/include/nel/sound/stream_file_source.h b/code/nel/include/nel/sound/stream_file_source.h index 79151f171..b7c48f96a 100644 --- a/code/nel/include/nel/sound/stream_file_source.h +++ b/code/nel/include/nel/sound/stream_file_source.h @@ -98,8 +98,9 @@ private: NLMISC::IThread *m_Thread; IAudioDecoder *m_AudioDecoder; - + bool m_Paused; + bool m_DecodingEnded; }; /* class CStreamFileSource */ diff --git a/code/nel/src/sound/stream_file_source.cpp b/code/nel/src/sound/stream_file_source.cpp index 185b7514f..9a03ba2d8 100644 --- a/code/nel/src/sound/stream_file_source.cpp +++ b/code/nel/src/sound/stream_file_source.cpp @@ -45,7 +45,7 @@ using namespace std; namespace NLSOUND { CStreamFileSource::CStreamFileSource(CStreamFileSound *streamFileSound, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster, CGroupController *groupController) -: CStreamSource(streamFileSound, spawn, cb, cbUserParam, cluster, groupController), m_AudioDecoder(NULL), m_Paused(false) +: CStreamSource(streamFileSound, spawn, cb, cbUserParam, cluster, groupController), m_AudioDecoder(NULL), m_Paused(false), m_DecodingEnded(false) { m_Thread = NLMISC::IThread::create(this); } @@ -244,7 +244,7 @@ void CStreamFileSource::resume() bool CStreamFileSource::isEnded() { - return (!m_Thread->isRunning() && !_Playing && !m_WaitingForPlay && !m_Paused); + return m_DecodingEnded || (!m_Thread->isRunning() && !_Playing && !m_WaitingForPlay && !m_Paused); } float CStreamFileSource::getLength() @@ -319,6 +319,7 @@ void CStreamFileSource::run() this->getRecommendedBufferSize(samples, bytes); uint32 recSleep = 40; uint32 doSleep = 10; + m_DecodingEnded = false; while (_Playing || m_WaitingForPlay) { if (!m_AudioDecoder->isMusicEnded()) @@ -369,6 +370,9 @@ void CStreamFileSource::run() { delete m_AudioDecoder; m_AudioDecoder = NULL; + // _Playing cannot be used to detect play state because its required in cleanup + // Using m_AudioDecoder in isEnded() may result race condition (decoder is only created after thread is started) + m_DecodingEnded = true; } // drop buffers m_FreeBuffers = 3; From c93d8ffd50b36c0d3f9d2ed15f76460ace9c53ce Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 20 Oct 2018 19:07:47 +0300 Subject: [PATCH 125/303] Changed: Improve music player UI, add repeat, shuffle options --HG-- branch : develop --- .../client/src/interface_v3/music_player.cpp | 156 ++++++++++++++---- .../client/src/interface_v3/music_player.h | 16 +- 2 files changed, 141 insertions(+), 31 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/music_player.cpp b/code/ryzom/client/src/interface_v3/music_player.cpp index b9cadad5c..358189d42 100644 --- a/code/ryzom/client/src/interface_v3/music_player.cpp +++ b/code/ryzom/client/src/interface_v3/music_player.cpp @@ -39,6 +39,9 @@ extern UDriver *Driver; #define TEMPLATE_PLAYLIST_SONG "playlist_song" #define TEMPLATE_PLAYLIST_SONG_TITLE "title" #define TEMPLATE_PLAYLIST_SONG_DURATION "duration" +// ui state +#define MP3_SAVE_SHUFFLE "UI:SAVE:MP3_SHUFFLE" +#define MP3_SAVE_REPEAT "UI:SAVE:MP3_REPEAT" static const std::string MediaPlayerDirectory("music/"); @@ -48,8 +51,20 @@ CMusicPlayer MusicPlayer; CMusicPlayer::CMusicPlayer () { - _CurrentSong = 0; + _CurrentSongIndex = 0; _State = Stopped; + _PlayStart = 0; + _PauseTime = 0; +} + +bool CMusicPlayer::isRepeatEnabled() const +{ + return (NLGUI::CDBManager::getInstance()->getDbProp(MP3_SAVE_REPEAT)->getValue32() == 1); +} + +bool CMusicPlayer::isShuffleEnabled() const +{ + return (NLGUI::CDBManager::getInstance()->getDbProp(MP3_SAVE_SHUFFLE)->getValue32() == 1); } @@ -59,16 +74,61 @@ void CMusicPlayer::playSongs (const std::vector &songs) _Songs = songs; // reset song index if out of bounds - if (_CurrentSong > _Songs.size()) - _CurrentSong = 0; + if (_CurrentSongIndex > _Songs.size()) + _CurrentSongIndex = 0; + if (isShuffleEnabled()) + shuffleAndRebuildPlaylist(); + else + rebuildPlaylist(); + + // If pause, stop, else play will resume + if (_State == Paused) + _State = Stopped; +} + +// *************************************************************************** +void CMusicPlayer::updatePlaylist(sint prevIndex) +{ + CInterfaceElement *pIE; + std::string rowId; + + if (prevIndex >= 0 && prevIndex < _Songs.size()) + { + rowId = toString("%s:s%d:bg", MP3_PLAYER_PLAYLIST_LIST, prevIndex); + pIE = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(rowId)); + if (pIE) pIE->setActive(false); + } + + rowId = toString("%s:s%d:bg", MP3_PLAYER_PLAYLIST_LIST, _CurrentSongIndex); + pIE = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(rowId)); + if (pIE) pIE->setActive(true); +} + +// *************************************************************************** +void CMusicPlayer::shuffleAndRebuildPlaylist() +{ + std::random_shuffle(_Songs.begin(), _Songs.end()); + rebuildPlaylist(); +} + +// *************************************************************************** +void CMusicPlayer::rebuildPlaylist() +{ CGroupList *pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(MP3_PLAYER_PLAYLIST_LIST)); if (pList) { pList->clearGroups(); pList->setDynamicDisplaySize(true); + bool found = _CurrentSong.Filename.empty(); for (uint i=0; i < _Songs.size(); ++i) { + if (!found && _CurrentSong.Filename == _Songs[i].Filename) + { + found = true; + _CurrentSongIndex = i; + } + uint min = (sint32)(_Songs[i].Length / 60) % 60; uint sec = (sint32)(_Songs[i].Length) % 60; uint hour = _Songs[i].Length / 3600; @@ -103,9 +163,7 @@ void CMusicPlayer::playSongs (const std::vector &songs) pList->invalidateCoords(); } - // If pause, stop, else play will resume - if (_State == Paused) - _State = Stopped; + updatePlaylist(); } @@ -116,31 +174,40 @@ void CMusicPlayer::play (sint index) if(!SoundMngr) return; + sint prevSongIndex = _CurrentSongIndex; + if (index >= 0 && index < (sint)_Songs.size()) { if (_State == Paused) + { stop(); + } - _CurrentSong = index; + _CurrentSongIndex = index; + _PauseTime = 0; } if (!_Songs.empty()) { - nlassert (_CurrentSong<_Songs.size()); + nlassert (_CurrentSongIndex<_Songs.size()); /* If the player is paused, resume, else, play the current song */ if (_State == Paused) + { SoundMngr->resumeMusic(); + } else - SoundMngr->playMusic(_Songs[_CurrentSong].Filename, 0, true, false, false); + { + SoundMngr->playMusic(_Songs[_CurrentSongIndex].Filename, 0, true, false, false); + _PauseTime = 0; + } _State = Playing; + _PlayStart = CTime::getLocalTime() - _PauseTime; - /* Show the song title */ - CInterfaceManager *pIM = CInterfaceManager::getInstance(); - CViewText *pVT = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:mp3_player:screen:text")); - if (pVT) - pVT->setText (ucstring::makeFromUtf8(_Songs[_CurrentSong].Title)); + _CurrentSong = _Songs[_CurrentSongIndex]; + + updatePlaylist(prevSongIndex); } } @@ -155,6 +222,9 @@ void CMusicPlayer::pause () { SoundMngr->pauseMusic(); _State = Paused; + + if (_PlayStart > 0) + _PauseTime = CTime::getLocalTime() - _PlayStart; } } @@ -167,6 +237,8 @@ void CMusicPlayer::stop () // stop the music only if we are really playing (else risk to stop a background music!) SoundMngr->stopMusic(0); _State = Stopped; + _PlayStart = 0; + _PauseTime = 0; } // *************************************************************************** @@ -176,12 +248,13 @@ void CMusicPlayer::previous () if (!_Songs.empty()) { // Point the previous song - if (_CurrentSong == 0) - _CurrentSong = (uint)_Songs.size()-1; + sint index; + if (_CurrentSongIndex == 0) + index = (uint)_Songs.size()-1; else - _CurrentSong--; + index = _CurrentSongIndex-1; - play (); + play(index); } } @@ -191,9 +264,11 @@ void CMusicPlayer::next () { if (!_Songs.empty()) { - _CurrentSong++; - _CurrentSong%=_Songs.size(); - play (); + sint index = _CurrentSongIndex+1; + if (index == _Songs.size()) + index = 0; + + play(index); } } @@ -205,17 +280,30 @@ void CMusicPlayer::update () return; if (_State == Playing) { + CViewText *pVT = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:mp3_player:screen:text")); + if (pVT) + { + TTime dur = (CTime::getLocalTime() - _PlayStart) / 1000; + std::string title; + title = toString("%02d:%02d %s", dur / 60, dur % 60, _CurrentSong.Title.c_str()); + pVT->setText(ucstring::makeFromUtf8(title)); + } + if (SoundMngr->isMusicEnded ()) { - // Point the next song - _CurrentSong++; - _CurrentSong%=_Songs.size(); - - // End of the playlist ? - if (_CurrentSong != 0) + // select next song from playlist + sint index = _CurrentSongIndex + 1; + if (isRepeatEnabled() || index < _Songs.size()) { - // No, play the next song - play (); + if (index == _Songs.size()) + { + index = 0; + + if (isShuffleEnabled()) + shuffleAndRebuildPlaylist(); + } + + play(index); } else { @@ -361,11 +449,19 @@ public: CMusicPlayer::CSongs song; song.Filename = filenames[i]; SoundMngr->getMixer()->getSongTitle(filenames[i], song.Title, song.Length); - songs.push_back (song); + if (song.Length > 0) + songs.push_back (song); } MusicPlayer.playSongs(songs); } + else if (Params == "update_playlist") + { + if (MusicPlayer.isShuffleEnabled()) + MusicPlayer.shuffleAndRebuildPlaylist(); + + MusicPlayer.rebuildPlaylist(); + } else if (Params == "previous") MusicPlayer.previous(); else if (Params == "play") diff --git a/code/ryzom/client/src/interface_v3/music_player.h b/code/ryzom/client/src/interface_v3/music_player.h index 33de33c74..7170934d4 100644 --- a/code/ryzom/client/src/interface_v3/music_player.h +++ b/code/ryzom/client/src/interface_v3/music_player.h @@ -55,14 +55,28 @@ public: void update (); + bool isRepeatEnabled() const; + bool isShuffleEnabled() const; + + // Build playlist UI from songs + void rebuildPlaylist(); + // Randomize playlist and rebuild the ui + void shuffleAndRebuildPlaylist(); + // Update playlist active row + void updatePlaylist(sint prevIndex = -1); + private: // The playlist - uint _CurrentSong; // If (!_Songs.empty()) must always be <_Songs.size() + CSongs _CurrentSong; + uint _CurrentSongIndex; // If (!_Songs.empty()) must always be <_Songs.size() std::vector _Songs; // State enum TState { Stopped, Playing, Paused } _State; + + TTime _PlayStart; + TTime _PauseTime; }; extern CMusicPlayer MusicPlayer; From e994c1298347cb24002f4ea9c39f497ab622feed Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 23 Oct 2018 11:19:07 +0300 Subject: [PATCH 126/303] Added: FFmpeg based audio decoder --HG-- branch : develop --- code/CMakeModules/FindFFmpeg.cmake | 173 +++++++ code/nel/CMakeLists.txt | 1 + .../include/nel/sound/audio_decoder_ffmpeg.h | 108 +++++ code/nel/src/sound/CMakeLists.txt | 7 + code/nel/src/sound/audio_decoder.cpp | 42 +- code/nel/src/sound/audio_decoder_ffmpeg.cpp | 430 ++++++++++++++++++ .../client/src/interface_v3/music_player.cpp | 25 +- 7 files changed, 761 insertions(+), 25 deletions(-) create mode 100644 code/CMakeModules/FindFFmpeg.cmake create mode 100644 code/nel/include/nel/sound/audio_decoder_ffmpeg.h create mode 100644 code/nel/src/sound/audio_decoder_ffmpeg.cpp diff --git a/code/CMakeModules/FindFFmpeg.cmake b/code/CMakeModules/FindFFmpeg.cmake new file mode 100644 index 000000000..96cbb6ed0 --- /dev/null +++ b/code/CMakeModules/FindFFmpeg.cmake @@ -0,0 +1,173 @@ +# vim: ts=2 sw=2 +# - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC) +# +# Once done this will define +# FFMPEG_FOUND - System has the all required components. +# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers. +# FFMPEG_LIBRARIES - Link these to use the required ffmpeg components. +# FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components. +# +# For each of the components it will additionaly set. +# - AVCODEC +# - AVDEVICE +# - AVFORMAT +# - AVUTIL +# - POSTPROC +# - SWSCALE +# - SWRESAMPLE +# the following variables will be defined +# _FOUND - System has +# _INCLUDE_DIRS - Include directory necessary for using the headers +# _LIBRARIES - Link these to use +# _DEFINITIONS - Compiler switches required for using +# _VERSION - The components version +# +# Copyright (c) 2006, Matthias Kretz, +# Copyright (c) 2008, Alexander Neundorf, +# Copyright (c) 2011, Michael Jansen, +# +# Redistribution and use is allowed according to the terms of the BSD license. + +include(FindPackageHandleStandardArgs) + +if(NOT FFmpeg_FIND_COMPONENTS) + set(FFmpeg_FIND_COMPONENTS AVFORMAT AVCODEC AVUTIL) +endif() + +# +### Macro: set_component_found +# +# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present. +# +macro(set_component_found _component) + if(${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS) + # message(STATUS " - ${_component} found.") + set(${_component}_FOUND TRUE) + else() + # message(STATUS " - ${_component} not found.") + endif() +endmacro() + +# +### Macro: find_component +# +# Checks for the given component by invoking pkgconfig and then looking up the libraries and +# include directories. +# +macro(find_component _component _pkgconfig _library _header) + if(NOT WIN32) + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + find_package(PkgConfig) + if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_${_component} ${_pkgconfig}) + endif() + endif() + + find_path(${_component}_INCLUDE_DIRS ${_header} + HINTS + ${FFMPEGSDK_INC} + ${PC_LIB${_component}_INCLUDEDIR} + ${PC_LIB${_component}_INCLUDE_DIRS} + PATH_SUFFIXES + ffmpeg + ) + + find_library(${_component}_LIBRARIES NAMES ${_library} + HINTS + ${FFMPEGSDK_LIB} + ${PC_LIB${_component}_LIBDIR} + ${PC_LIB${_component}_LIBRARY_DIRS} + ) + + STRING(REGEX REPLACE "/.*" "/version.h" _ver_header ${_header}) + if(EXISTS "${${_component}_INCLUDE_DIRS}/${_ver_header}") + file(STRINGS "${${_component}_INCLUDE_DIRS}/${_ver_header}" version_str REGEX "^#define[\t ]+LIB${_component}_VERSION_M.*") + + foreach(_str "${version_str}") + if(NOT version_maj) + string(REGEX REPLACE "^.*LIB${_component}_VERSION_MAJOR[\t ]+([0-9]*).*$" "\\1" version_maj "${_str}") + endif() + if(NOT version_min) + string(REGEX REPLACE "^.*LIB${_component}_VERSION_MINOR[\t ]+([0-9]*).*$" "\\1" version_min "${_str}") + endif() + if(NOT version_mic) + string(REGEX REPLACE "^.*LIB${_component}_VERSION_MICRO[\t ]+([0-9]*).*$" "\\1" version_mic "${_str}") + endif() + endforeach() + unset(version_str) + + set(${_component}_VERSION "${version_maj}.${version_min}.${version_mic}" CACHE STRING "The ${_component} version number.") + unset(version_maj) + unset(version_min) + unset(version_mic) + endif(EXISTS "${${_component}_INCLUDE_DIRS}/${_ver_header}") + set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number.") + set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS.") + + set_component_found(${_component}) + + mark_as_advanced( + ${_component}_INCLUDE_DIRS + ${_component}_LIBRARIES + ${_component}_DEFINITIONS + ${_component}_VERSION) +endmacro() + + +set(FFMPEGSDK $ENV{FFMPEG_HOME}) +if(FFMPEGSDK) + set(FFMPEGSDK_INC "${FFMPEGSDK}/include") + set(FFMPEGSDK_LIB "${FFMPEGSDK}/lib") +endif() + +# Check for all possible components. +find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h) +find_component(AVFORMAT libavformat avformat libavformat/avformat.h) +find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h) +find_component(AVUTIL libavutil avutil libavutil/avutil.h) +find_component(SWSCALE libswscale swscale libswscale/swscale.h) +find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h) +find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h) + +# Check if the required components were found and add their stuff to the FFMPEG_* vars. +foreach(_component ${FFmpeg_FIND_COMPONENTS}) + if(${_component}_FOUND) + # message(STATUS "Required component ${_component} present.") + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${${_component}_LIBRARIES}) + set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS}) + list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS}) + else() + # message(STATUS "Required component ${_component} missing.") + endif() +endforeach() + +# Build the include path and library list with duplicates removed. +if(FFMPEG_INCLUDE_DIRS) + list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS) +endif() + +if(FFMPEG_LIBRARIES) + list(REMOVE_DUPLICATES FFMPEG_LIBRARIES) +endif() + +# cache the vars. +set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE) +set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE) +set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} CACHE STRING "The FFmpeg cflags." FORCE) + +mark_as_advanced(FFMPEG_INCLUDE_DIRS FFMPEG_LIBRARIES FFMPEG_DEFINITIONS) + +# Now set the noncached _FOUND vars for the components. +foreach(_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWRESAMPLE SWSCALE) + set_component_found(${_component}) +endforeach () + +# Compile the list of required vars +set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS) +foreach(_component ${FFmpeg_FIND_COMPONENTS}) + list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS) +endforeach() + +# Give a nice error message if some of the required vars are missing. +find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS}) diff --git a/code/nel/CMakeLists.txt b/code/nel/CMakeLists.txt index 84b820d33..3470fcebb 100644 --- a/code/nel/CMakeLists.txt +++ b/code/nel/CMakeLists.txt @@ -20,6 +20,7 @@ ENDIF() IF(WITH_SOUND) FIND_PACKAGE(Ogg) FIND_PACKAGE(Vorbis) + FIND_PACKAGE(FFmpeg COMPONENTS AVCODEC AVFORMAT AVUTIL SWRESAMPLE) IF(WITH_DRIVER_OPENAL) FIND_PACKAGE(OpenAL) diff --git a/code/nel/include/nel/sound/audio_decoder_ffmpeg.h b/code/nel/include/nel/sound/audio_decoder_ffmpeg.h new file mode 100644 index 000000000..c12f52f58 --- /dev/null +++ b/code/nel/include/nel/sound/audio_decoder_ffmpeg.h @@ -0,0 +1,108 @@ +// NeL - MMORPG Framework +// Copyright (C) 2018 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef NLSOUND_AUDIO_DECODER_FFMPEG_H +#define NLSOUND_AUDIO_DECODER_FFMPEG_H +#include + +#include + +struct AVCodecContext; +struct AVFormatContext; +struct AVIOContext; +struct AVPacket; +struct SwrContext; + +namespace NLSOUND { + +/** + * \brief CAudioDecoderFfmpeg + * \date 2018-10-21 08:08GMT + * \author Meelis Mägi (Nimetu) + * CAudioDecoderFfmpeg + * Create trough IAudioDecoder + */ +class CAudioDecoderFfmpeg : public IAudioDecoder +{ +protected: + NLMISC::IStream *_Stream; + + bool _IsSupported; + bool _Loop; + bool _IsMusicEnded; + sint32 _StreamOffset; + sint32 _StreamSize; + + AVIOContext *_AvioContext; + AVFormatContext *_FormatContext; + AVCodecContext *_AudioContext; + SwrContext *_SwrContext; + + // selected stream + sint32 _AudioStreamIndex; + + // output buffer for decoded frame + SwrContext *_ConvertContext; + +private: + // called from constructor if ffmpeg fails to initialize + // or from destructor to cleanup ffmpeg pointers + void release(); + +public: + CAudioDecoderFfmpeg(NLMISC::IStream *stream, bool loop); + virtual ~CAudioDecoderFfmpeg(); + + inline NLMISC::IStream *getStream() { return _Stream; } + inline sint32 getStreamSize() { return _StreamSize; } + inline sint32 getStreamOffset() { return _StreamOffset; } + + // Return true if ffmpeg is able to decode the stream + bool isFormatSupported() const; + + /// Get information on a music file (only artist and title at the moment). + static bool getInfo(NLMISC::IStream *stream, std::string &artist, std::string &title, float &length); + + /// Get how many bytes the music buffer requires for output minimum. + virtual uint32 getRequiredBytes(); + + /// Get an amount of bytes between minimum and maximum (can be lower than minimum if at end). + virtual uint32 getNextBytes(uint8 *buffer, uint32 minimum, uint32 maximum); + + /// Get the amount of channels (2 is stereo) in output. + virtual uint8 getChannels(); + + /// Get the samples per second (often 44100) in output. + virtual uint getSamplesPerSec(); + + /// Get the bits per sample (often 16) in output. + virtual uint8 getBitsPerSample(); + + /// Get if the music has ended playing (never true if loop). + virtual bool isMusicEnded(); + + /// Get the total time in seconds. + virtual float getLength(); + + /// Set looping + virtual void setLooping(bool loop); +}; /* class CAudioDecoderFfmpeg */ + +} /* namespace NLSOUND */ + +#endif // NLSOUND_AUDIO_DECODER_FFMPEG_H + +/* end of file */ diff --git a/code/nel/src/sound/CMakeLists.txt b/code/nel/src/sound/CMakeLists.txt index e4831c643..bc1816a17 100644 --- a/code/nel/src/sound/CMakeLists.txt +++ b/code/nel/src/sound/CMakeLists.txt @@ -58,6 +58,7 @@ FILE(GLOB STREAM FILE(GLOB STREAM_FILE audio_decoder.cpp ../../include/nel/sound/audio_decoder.h audio_decoder_vorbis.cpp ../../include/nel/sound/audio_decoder_vorbis.h + audio_decoder_ffmpeg.cpp ../../include/nel/sound/audio_decoder_ffmpeg.h stream_file_sound.cpp ../../include/nel/sound/stream_file_sound.h stream_file_source.cpp ../../include/nel/sound/stream_file_source.h ) @@ -95,6 +96,12 @@ IF(WITH_STATIC) TARGET_LINK_LIBRARIES(nelsound ${OGG_LIBRARY}) ENDIF() +IF(FFMPEG_FOUND) + ADD_DEFINITIONS(-DFFMPEG_ENABLED) + INCLUDE_DIRECTORIES(${FFMPEG_INCLUDE_DIRS}) + TARGET_LINK_LIBRARIES(nelsound ${FFMPEG_LIBRARIES}) +ENDIF() + INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) diff --git a/code/nel/src/sound/audio_decoder.cpp b/code/nel/src/sound/audio_decoder.cpp index 6e9e42b61..f0eb80efd 100644 --- a/code/nel/src/sound/audio_decoder.cpp +++ b/code/nel/src/sound/audio_decoder.cpp @@ -37,6 +37,10 @@ // Project includes #include +#ifdef FFMPEG_ENABLED +#include +#endif + using namespace std; using namespace NLMISC; @@ -82,6 +86,17 @@ IAudioDecoder *IAudioDecoder::createAudioDecoder(const std::string &type, NLMISC nlwarning("Stream is NULL"); return NULL; } +#ifdef FFMPEG_ENABLED + try { + CAudioDecoderFfmpeg *decoder = new CAudioDecoderFfmpeg(stream, loop); + return static_cast(decoder); + } + catch(const Exception &e) + { + nlwarning("Exception %s during ffmpeg setup", e.what()); + return NULL; + } +#else std::string type_lower = toLower(type); if (type_lower == "ogg") { @@ -92,23 +107,32 @@ IAudioDecoder *IAudioDecoder::createAudioDecoder(const std::string &type, NLMISC nlwarning("Music file type unknown: '%s'", type_lower.c_str()); return NULL; } +#endif } bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, std::string &title, float &length) { std::string lookup = CPath::lookup(filepath, false); if (lookup.empty()) - { + { nlwarning("Music file %s does not exist!", filepath.c_str()); - return false; + return false; } + +#ifdef FFMPEG_ENABLED + CIFile ifile; + ifile.setCacheFileOnOpen(false); + ifile.allowBNPCacheFileOnOpen(false); + if (ifile.open(lookup)) + return CAudioDecoderFfmpeg::getInfo(&ifile, artist, title, length); +#else std::string type = CFile::getExtension(filepath); std::string type_lower = NLMISC::toLower(type); if (type_lower == "ogg") { - CIFile ifile; - ifile.setCacheFileOnOpen(false); + CIFile ifile; + ifile.setCacheFileOnOpen(false); ifile.allowBNPCacheFileOnOpen(false); if (ifile.open(lookup)) return CAudioDecoderVorbis::getInfo(&ifile, artist, title, length); @@ -119,6 +143,7 @@ bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, st { nlwarning("Music file type unknown: '%s'", type_lower.c_str()); } +#endif artist.clear(); title.clear(); return false; @@ -132,6 +157,11 @@ void IAudioDecoder::getMusicExtensions(std::vector &extensions) { extensions.push_back("ogg"); } +#ifdef FFMPEG_ENABLED + extensions.push_back("mp3"); + extensions.push_back("flac"); + extensions.push_back("aac"); +#endif // extensions.push_back("wav"); // TODO: Easy. } @@ -139,7 +169,11 @@ void IAudioDecoder::getMusicExtensions(std::vector &extensions) /// Return if a music extension is supported by the nel sound library. bool IAudioDecoder::isMusicExtensionSupported(const std::string &extension) { +#ifdef FFMPEG_ENABLED + return (extension == "ogg" || extension == "mp3" || extension == "flac" || extension == "aac"); +#else return (extension == "ogg"); +#endif } } /* namespace NLSOUND */ diff --git a/code/nel/src/sound/audio_decoder_ffmpeg.cpp b/code/nel/src/sound/audio_decoder_ffmpeg.cpp new file mode 100644 index 000000000..50acb17cc --- /dev/null +++ b/code/nel/src/sound/audio_decoder_ffmpeg.cpp @@ -0,0 +1,430 @@ +// NeL - MMORPG Framework +// Copyright (C) 2018 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "stdsound.h" + +#include + +#define __STDC_CONSTANT_MACROS +extern "C" +{ +#include +#include +#include +#include +}; + +using namespace std; +using namespace NLMISC; + +namespace { + +const std::string av_err2string(sint err) +{ + char buf[AV_ERROR_MAX_STRING_SIZE]; + av_strerror(err, buf, AV_ERROR_MAX_STRING_SIZE); + return (std::string)buf; +} + +void nel_logger(void *ptr, int level, const char *fmt, va_list vargs) +{ + static char msg[1024]; + + const char *module = NULL; + + // AV_LOG_DEBUG, AV_LOG_TRACE + if (level >= AV_LOG_DEBUG) return; + + if (ptr) + { + AVClass *avc = *(AVClass**) ptr; + module = avc->item_name(ptr); + } + + vsnprintf(msg, sizeof(msg), fmt, vargs); + msg[sizeof(msg)-1] = '\0'; + + switch(level) + { + case AV_LOG_PANIC: + // ffmpeg is about to crash so lets throw + nlerror("FFMPEG(P): (%s) %s", module, msg); + break; + case AV_LOG_FATAL: + // ffmpeg had unrecoverable error, corrupted stream or such + nlerrornoex("FFMPEG(F): (%s) %s", module, msg); + break; + case AV_LOG_ERROR: + nlwarning("FFMPEG(E): (%s) %s", module, msg); + break; + case AV_LOG_WARNING: + nlwarning("FFMPEG(W): (%s) %s", module, msg); + break; + case AV_LOG_INFO: + nlinfo("FFMPEG(I): (%s) %s", module, msg); + break; + case AV_LOG_VERBOSE: + nldebug("FFMPEG(V): (%s) %s", module, msg); + break; + case AV_LOG_DEBUG: + nldebug("FFMPEG(D): (%s) %s", module, msg); + break; + default: + nlinfo("FFMPEG: invalid log level:%d (%s) %s", level, module, msg); + break; + } +} + +class CFfmpegInstance +{ +public: + CFfmpegInstance() + { + av_log_set_level(AV_LOG_DEBUG); + av_log_set_callback(nel_logger); + + av_register_all(); + + //avformat_network_init(); + } + + virtual ~CFfmpegInstance() + { + //avformat_network_deinit(); + } +}; + +CFfmpegInstance ffmpeg; + +// Send bytes to ffmpeg +int avio_read_packet(void *opaque, uint8 *buf, int buf_size) +{ + NLSOUND::CAudioDecoderFfmpeg *decoder = static_cast(opaque); + NLMISC::IStream *stream = decoder->getStream(); + nlassert(stream->isReading()); + + uint32 available = decoder->getStreamSize() - stream->getPos(); + if (available == 0) return 0; + + buf_size = FFMIN(buf_size, available); + stream->serialBuffer((uint8 *)buf, buf_size); + return buf_size; +} + +sint64 avio_seek(void *opaque, sint64 offset, int whence) +{ + NLSOUND::CAudioDecoderFfmpeg *decoder = static_cast(opaque); + NLMISC::IStream *stream = decoder->getStream(); + nlassert(stream->isReading()); + + NLMISC::IStream::TSeekOrigin origin; + switch(whence) + { + case SEEK_SET: + origin = NLMISC::IStream::begin; + break; + case SEEK_CUR: + origin = NLMISC::IStream::current; + break; + case SEEK_END: + origin = NLMISC::IStream::end; + break; + case AVSEEK_SIZE: + return decoder->getStreamSize(); + default: + return -1; + } + + stream->seek((sint32) offset, origin); + return stream->getPos(); +} + +}//ns + +namespace NLSOUND { + +// swresample will convert audio to this format +#define FFMPEG_SAMPLE_RATE 44100 +#define FFMPEG_CHANNELS 2 +#define FFMPEG_CHANNEL_LAYOUT AV_CH_LAYOUT_STEREO +#define FFMPEG_BITS_PER_SAMPLE 16 +#define FFMPEG_SAMPLE_FORMAT AV_SAMPLE_FMT_S16 + +CAudioDecoderFfmpeg::CAudioDecoderFfmpeg(NLMISC::IStream *stream, bool loop) +: IAudioDecoder(), + _Stream(stream), _Loop(loop), _IsMusicEnded(false), _StreamSize(0), _IsSupported(false), + _AvioContext(NULL), _FormatContext(NULL), + _AudioContext(NULL), _AudioStreamIndex(0), + _SwrContext(NULL) +{ + _StreamOffset = stream->getPos(); + stream->seek(0, NLMISC::IStream::end); + _StreamSize = stream->getPos(); + stream->seek(_StreamOffset, NLMISC::IStream::begin); + + try { + _FormatContext = avformat_alloc_context(); + if (!_FormatContext) + throw Exception("Can't create AVFormatContext"); + + // avio_ctx_buffer can be reallocated by ffmpeg and assigned to avio_ctx->buffer + uint8 *avio_ctx_buffer = NULL; + size_t avio_ctx_buffer_size = 4096; + avio_ctx_buffer = static_cast(av_malloc(avio_ctx_buffer_size)); + if (!avio_ctx_buffer) + throw Exception("Can't allocate avio context buffer"); + + _AvioContext = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size, 0, this, &avio_read_packet, NULL, &avio_seek); + if (!_AvioContext) + throw Exception("Can't allocate avio context"); + + _FormatContext->pb = _AvioContext; + sint ret = avformat_open_input(&_FormatContext, NULL, NULL, NULL); + if (ret < 0) + throw Exception("avformat_open_input: %d", ret); + + // find stream and then audio codec to see if ffmpeg supports this + _IsSupported = false; + if (avformat_find_stream_info(_FormatContext, NULL) >= 0) + { + _AudioStreamIndex = av_find_best_stream(_FormatContext, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); + if (_AudioStreamIndex >= 0) + { + _AudioContext = _FormatContext->streams[_AudioStreamIndex]->codec; + av_opt_set_int(_AudioContext, "refcounted_frames", 1, 0); + + AVCodec *codec = avcodec_find_decoder(_AudioContext->codec_id); + if (codec != NULL && avcodec_open2(_AudioContext, codec, NULL) >= 0) + { + _IsSupported = true; + } + } + } + } + catch(...) + { + release(); + + throw; + } + + if (!_IsSupported) + { + nlwarning("FFMPEG: Decoder created, unknown stream format / codec"); + } +} + +CAudioDecoderFfmpeg::~CAudioDecoderFfmpeg() +{ + release(); +} + +void CAudioDecoderFfmpeg::release() +{ + if (_SwrContext) + swr_free(&_SwrContext); + + if (_AudioContext) + avcodec_close(_AudioContext); + + if (_FormatContext) + avformat_close_input(&_FormatContext); + + if (_AvioContext && _AvioContext->buffer) + av_freep(&_AvioContext->buffer); + + if (_AvioContext) + av_freep(&_AvioContext); +} + +bool CAudioDecoderFfmpeg::isFormatSupported() const +{ + return _IsSupported; +} + +/// Get information on a music file. +bool CAudioDecoderFfmpeg::getInfo(NLMISC::IStream *stream, std::string &artist, std::string &title, float &length) +{ + CAudioDecoderFfmpeg ffmpeg(stream, false); + if (!ffmpeg.isFormatSupported()) + { + title.clear(); + artist.clear(); + length = 0.f; + + return false; + } + + AVDictionaryEntry *tag = NULL; + while((tag = av_dict_get(ffmpeg._FormatContext->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) + { + if (!strcmp(tag->key, "artist")) + { + artist = tag->value; + } + else if (!strcmp(tag->key, "title")) + { + title = tag->value; + } + } + + if (ffmpeg._FormatContext->duration != AV_NOPTS_VALUE) + { + length = ffmpeg._FormatContext->duration * av_q2d(AV_TIME_BASE_Q); + } + else if (ffmpeg._FormatContext->streams[ffmpeg._AudioStreamIndex]->duration != AV_NOPTS_VALUE) + { + length = ffmpeg._FormatContext->streams[ffmpeg._AudioStreamIndex]->duration * av_q2d(ffmpeg._FormatContext->streams[ffmpeg._AudioStreamIndex]->time_base); + } + else + { + length = 0.f; + } + + return true; +} + +uint32 CAudioDecoderFfmpeg::getRequiredBytes() +{ + return 0; // no minimum requirement of bytes to buffer out +} + +uint32 CAudioDecoderFfmpeg::getNextBytes(uint8 *buffer, uint32 minimum, uint32 maximum) +{ + if (_IsMusicEnded) return 0; + nlassert(minimum <= maximum); // can't have this.. + + // TODO: CStreamFileSource::play() will stall when there is no frames on warmup + // supported can be set false if there is an issue creating converter + if (!_IsSupported) + { + _IsMusicEnded = true; + return 1; + } + + uint32 bytes_read = 0; + + AVFrame frame = {0}; + AVPacket packet = {0}; + + if (!_SwrContext) + { + sint64 in_channel_layout = av_get_default_channel_layout(_AudioContext->channels); + _SwrContext = swr_alloc_set_opts(NULL, + // output + FFMPEG_CHANNEL_LAYOUT, FFMPEG_SAMPLE_FORMAT, FFMPEG_SAMPLE_RATE, + // input + in_channel_layout, _AudioContext->sample_fmt, _AudioContext->sample_rate, + 0, NULL); + swr_init(_SwrContext); + } + + sint ret; + while(bytes_read < minimum) + { + // read packet from stream + if ((ret = av_read_frame(_FormatContext, &packet)) < 0) + { + _IsMusicEnded = true; + // TODO: looping + break; + } + + if (packet.stream_index == _AudioStreamIndex) + { + // packet can contain multiple frames + AVPacket first = packet; + int got_frame = 0; + do { + got_frame = 0; + ret = avcodec_decode_audio4(_AudioContext, &frame, &got_frame, &packet); + if (ret < 0) + { + nlwarning("FFMPEG: error decoding audio frame: %s", av_err2string(ret).c_str()); + break; + } + packet.size -= ret; + packet.data += ret; + + if (got_frame) + { + uint32 out_bps = av_get_bytes_per_sample(FFMPEG_SAMPLE_FORMAT) * FFMPEG_CHANNELS; + uint32 max_samples = (maximum - bytes_read) / out_bps; + + uint32 out_samples = av_rescale_rnd(swr_get_delay(_SwrContext, _AudioContext->sample_rate) + frame.nb_samples, + FFMPEG_SAMPLE_RATE, _AudioContext->sample_rate, AV_ROUND_UP); + + if (max_samples > out_samples) + max_samples = out_samples; + + uint32 converted = swr_convert(_SwrContext, &buffer, max_samples, (const uint8 **)frame.extended_data, frame.nb_samples); + uint32 size = out_bps * converted; + + bytes_read += size; + buffer += size; + + av_frame_unref(&frame); + } + } while (got_frame && packet.size > 0); + + av_packet_unref(&first); + } + else + { + ret = 0; + av_packet_unref(&packet); + } + } + + return bytes_read; +} + +uint8 CAudioDecoderFfmpeg::getChannels() +{ + return FFMPEG_CHANNELS; +} + +uint CAudioDecoderFfmpeg::getSamplesPerSec() +{ + return FFMPEG_SAMPLE_RATE; +} + +uint8 CAudioDecoderFfmpeg::getBitsPerSample() +{ + return FFMPEG_BITS_PER_SAMPLE; +} + +bool CAudioDecoderFfmpeg::isMusicEnded() +{ + return _IsMusicEnded; +} + +float CAudioDecoderFfmpeg::getLength() +{ + printf(">> CAudioDecoderFfmpeg::getLength\n"); + // TODO: return (float)ov_time_total(&_OggVorbisFile, -1); + return 0.f; +} + +void CAudioDecoderFfmpeg::setLooping(bool loop) +{ + _Loop = loop; +} + +} /* namespace NLSOUND */ + +/* end of file */ diff --git a/code/ryzom/client/src/interface_v3/music_player.cpp b/code/ryzom/client/src/interface_v3/music_player.cpp index 358189d42..55aa9e342 100644 --- a/code/ryzom/client/src/interface_v3/music_player.cpp +++ b/code/ryzom/client/src/interface_v3/music_player.cpp @@ -372,22 +372,10 @@ public: // no format supported if (extensions.empty()) return; - bool oggSupported = false; - bool mp3Supported = false; - std::string message; for(uint i = 0; i < extensions.size(); ++i) { - if (extensions[i] == "ogg") - { - oggSupported = true; - message += " ogg"; - } - else if (extensions[i] == "mp3") - { - mp3Supported = true; - message += " mp3"; - } + message += " " + extensions[i]; } message += " m3u m3u8"; nlinfo("Media player supports: '%s'", message.substr(1).c_str()); @@ -404,15 +392,9 @@ public: for (i = 0; i < filesToProcess.size(); ++i) { std::string ext = toLower(CFile::getExtension(filesToProcess[i])); - if (ext == "ogg") + if (std::find(extensions.begin(), extensions.end(), ext) != extensions.end()) { - if (oggSupported) - filenames.push_back(filesToProcess[i]); - } - else if (ext == "mp3" || ext == "mp2" || ext == "mp1") - { - if (mp3Supported) - filenames.push_back(filesToProcess[i]); + filenames.push_back(filesToProcess[i]); } else if (ext == "m3u" || ext == "m3u8") { @@ -448,6 +430,7 @@ public: CMusicPlayer::CSongs song; song.Filename = filenames[i]; + // TODO: cache the result for next refresh SoundMngr->getMixer()->getSongTitle(filenames[i], song.Title, song.Length); if (song.Length > 0) songs.push_back (song); From 9b9bd0eb8cd548cfa745a2b6ab1de59f8fb1604b Mon Sep 17 00:00:00 2001 From: Nimetu Date: Wed, 24 Oct 2018 08:38:47 +0300 Subject: [PATCH 127/303] Fixed: Compiling withoud ffmpeg --HG-- branch : develop --- code/nel/src/sound/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/nel/src/sound/CMakeLists.txt b/code/nel/src/sound/CMakeLists.txt index bc1816a17..f0417754c 100644 --- a/code/nel/src/sound/CMakeLists.txt +++ b/code/nel/src/sound/CMakeLists.txt @@ -1,6 +1,10 @@ FILE(GLOB SRC *.cpp *.h) FILE(GLOB HEADERS ../../include/nel/sound/*.h) +IF(NOT FFMPEG_FOUND) + LIST(REMOVE_ITEM SRC ${CMAKE_CURRENT_SOURCE_DIR}/audio_decoder_ffmpeg.cpp) + LIST(REMOVE_ITEM HEADERS ${CMAKE_CURRENT_SOURCE_DIR}../../include/nel/sound/audio_decoder_ffmpeg.h) +ENDIF() FILE(GLOB ANIMATION sound_anim_manager.cpp ../../include/nel/sound/sound_anim_manager.h From cea7a4c0cbd423aff0761efab0ad4b34f38ab1ea Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 1 Nov 2018 08:33:35 +0200 Subject: [PATCH 128/303] Backed out changeset: 68e5d9033466 --HG-- branch : develop --- code/nel/include/nel/gui/interface_group.h | 10 +------ code/nel/src/gui/interface_group.cpp | 32 ++++------------------ 2 files changed, 6 insertions(+), 36 deletions(-) diff --git a/code/nel/include/nel/gui/interface_group.h b/code/nel/include/nel/gui/interface_group.h index 5f864e9e9..01f2b9701 100644 --- a/code/nel/include/nel/gui/interface_group.h +++ b/code/nel/include/nel/gui/interface_group.h @@ -101,9 +101,6 @@ namespace NLGUI // test is a group is a direct child of this interface group bool isChildGroup(const CInterfaceGroup *group) const; - // test is x,y is inside last draw clip aread - bool isInViewport(sint32 x, sint32 y) const; - virtual bool isWindowUnder (sint32 x, sint32 y); // Virtual for menu that is not square CInterfaceGroup *getGroupUnder (sint32 x, sint32 y); virtual bool getViewsUnder (sint32 x, sint32 y, sint32 clipX, sint32 clipY, sint32 clipW, sint32 clipH, std::vector &vVB); // Return true if x,y under the group @@ -344,13 +341,8 @@ namespace NLGUI void alignElements(); protected: - /// Last clip area cached from draw call - sint32 _LastClipX; - sint32 _LastClipY; - sint32 _LastClipW; - sint32 _LastClipH; - void makeNewClip (sint32 &oldClipX, sint32 &oldClipY, sint32 &oldClipW, sint32 &oldClipH, bool drawing = false); + void makeNewClip (sint32 &oldClipX, sint32 &oldClipY, sint32 &oldClipW, sint32 &oldClipH); void restoreClip (sint32 oldSciX, sint32 oldSciY, sint32 oldSciW, sint32 oldSciH); // Compute clip contribution for current window, and a previous clipping rectangle. This doesn't change the clip window in the driver. diff --git a/code/nel/src/gui/interface_group.cpp b/code/nel/src/gui/interface_group.cpp index 3da60c9f2..789030a4a 100644 --- a/code/nel/src/gui/interface_group.cpp +++ b/code/nel/src/gui/interface_group.cpp @@ -77,11 +77,6 @@ namespace NLGUI _LUAEnvTableCreated= false; _DepthForZSort= 0.f; - _LastClipX = 0; - _LastClipY = 0; - _LastClipW = 0; - _LastClipH = 0; - #ifdef AJM_DEBUG_TRACK_INTERFACE_GROUPS CInterfaceManager::getInstance()->DebugTrackGroupsCreated( this ); #endif @@ -1259,8 +1254,7 @@ namespace NLGUI { const NLGUI::CEventDescriptorMouse &eventDesc = (const NLGUI::CEventDescriptorMouse &)event; - // group might be partially hidden (scolling) so test against last visible area - if (!isInViewport(eventDesc.getX(), eventDesc.getY())) + if (!isIn(eventDesc.getX(), eventDesc.getY())) return false; bool taken = false; @@ -1305,6 +1299,7 @@ namespace NLGUI } if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousewheel) { + // handle the Mouse Wheel only if interesting if (_H>_MaxH) { CInterfaceGroup *currParent = _Parent; @@ -1334,7 +1329,7 @@ namespace NLGUI void CInterfaceGroup::draw () { sint32 oldSciX, oldSciY, oldSciW, oldSciH; - makeNewClip (oldSciX, oldSciY, oldSciW, oldSciH, true); + makeNewClip (oldSciX, oldSciY, oldSciW, oldSciH); // Display sons only if not total clipped CViewRenderer &rVR = *CViewRenderer::getInstance(); @@ -1723,16 +1718,6 @@ namespace NLGUI (y <= (_YReal + _HReal))); } - // ------------------------------------------------------------------------------------------------ - bool CInterfaceGroup::isInViewport(sint32 x, sint32 y) const - { - return ( - (x > _LastClipX) && - (x < (_LastClipX + _LastClipW))&& - (y > _LastClipY) && - (y < (_LastClipY + _LastClipH))); - } - // ------------------------------------------------------------------------------------------------ CInterfaceGroup* CInterfaceGroup::getGroupUnder (sint32 x, sint32 y) { @@ -1991,10 +1976,11 @@ namespace NLGUI newSciYDest = newSciY; newSciWDest = newSciW/* - _MarginLeft*/; newSciHDest = newSciH; + } // ------------------------------------------------------------------------------------------------ - void CInterfaceGroup::makeNewClip (sint32 &oldSciX, sint32 &oldSciY, sint32 &oldSciW, sint32 &oldSciH, bool drawing) + void CInterfaceGroup::makeNewClip (sint32 &oldSciX, sint32 &oldSciY, sint32 &oldSciW, sint32 &oldSciH) { CViewRenderer &rVR = *CViewRenderer::getInstance(); rVR.getClipWindow (oldSciX, oldSciY, oldSciW, oldSciH); @@ -2002,14 +1988,6 @@ namespace NLGUI sint32 newSciX, newSciY, newSciW, newSciH; computeCurrentClipContribution(oldSciX, oldSciY, oldSciW, oldSciH, newSciX, newSciY, newSciW, newSciH); rVR.setClipWindow (newSciX, newSciY, newSciW, newSciH); - - if (drawing) - { - _LastClipX = newSciX; - _LastClipY = newSciY; - _LastClipW = newSciW; - _LastClipH = newSciH; - } } // ------------------------------------------------------------------------------------------------ From 19e1b47ddbf2cfefed9907e06c9454ea2187711d Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 4 Nov 2018 15:59:42 +0200 Subject: [PATCH 129/303] Fixed: Compiling under windows --HG-- branch : develop --- code/nel/src/sound/CMakeLists.txt | 2 +- code/nel/src/sound/audio_decoder_ffmpeg.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/code/nel/src/sound/CMakeLists.txt b/code/nel/src/sound/CMakeLists.txt index f0417754c..7b9eebc9f 100644 --- a/code/nel/src/sound/CMakeLists.txt +++ b/code/nel/src/sound/CMakeLists.txt @@ -3,7 +3,7 @@ FILE(GLOB HEADERS ../../include/nel/sound/*.h) IF(NOT FFMPEG_FOUND) LIST(REMOVE_ITEM SRC ${CMAKE_CURRENT_SOURCE_DIR}/audio_decoder_ffmpeg.cpp) - LIST(REMOVE_ITEM HEADERS ${CMAKE_CURRENT_SOURCE_DIR}../../include/nel/sound/audio_decoder_ffmpeg.h) + LIST(REMOVE_ITEM HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../../include/nel/sound/audio_decoder_ffmpeg.h) ENDIF() FILE(GLOB ANIMATION diff --git a/code/nel/src/sound/audio_decoder_ffmpeg.cpp b/code/nel/src/sound/audio_decoder_ffmpeg.cpp index 50acb17cc..dea8368d2 100644 --- a/code/nel/src/sound/audio_decoder_ffmpeg.cpp +++ b/code/nel/src/sound/audio_decoder_ffmpeg.cpp @@ -26,10 +26,15 @@ extern "C" #include #include #include -}; +} using namespace std; using namespace NLMISC; +using namespace NLSOUND; + +// Visual Studio does not support AV_TIME_BASE_Q macro in C++ +#undef AV_TIME_BASE_Q +static const AVRational AV_TIME_BASE_Q = {1, AV_TIME_BASE}; namespace { From edf1d12f65197ef665fb8c1d145789475e89da6f Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 4 Nov 2018 18:14:52 +0200 Subject: [PATCH 130/303] Fixed: Opening local file with @ char in filename. --HG-- branch : develop --- code/nel/src/misc/file.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/src/misc/file.cpp b/code/nel/src/misc/file.cpp index 414a10e5a..54ffdfbc6 100644 --- a/code/nel/src/misc/file.cpp +++ b/code/nel/src/misc/file.cpp @@ -185,7 +185,7 @@ bool CIFile::open(const std::string &path, bool text) // Bigfile or xml pack access requested ? string::size_type pos; - if ((pos = path.find('@')) != string::npos) + if (!CFile::fileExists(path) && (pos = path.find('@')) != string::npos) { // check for a double @ to identify XML pack file if (pos+1 < path.size() && path[pos+1] == '@') From 6c8e42361a8fa5513a41ad6d39a352498a782213 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 4 Nov 2018 18:15:27 +0200 Subject: [PATCH 131/303] Fixed: Playing music files with @ in the filename. --HG-- branch : develop --- code/ryzom/client/src/interface_v3/music_player.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/music_player.cpp b/code/ryzom/client/src/interface_v3/music_player.cpp index 55aa9e342..c49757681 100644 --- a/code/ryzom/client/src/interface_v3/music_player.cpp +++ b/code/ryzom/client/src/interface_v3/music_player.cpp @@ -415,14 +415,6 @@ public: std::vector songs; for (i=0; i Date: Sun, 4 Nov 2018 17:22:33 +0200 Subject: [PATCH 132/303] Fixed: Displaying song playtime --HG-- branch : develop --- code/ryzom/client/src/interface_v3/music_player.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/music_player.cpp b/code/ryzom/client/src/interface_v3/music_player.cpp index c49757681..0670c2935 100644 --- a/code/ryzom/client/src/interface_v3/music_player.cpp +++ b/code/ryzom/client/src/interface_v3/music_player.cpp @@ -284,8 +284,13 @@ void CMusicPlayer::update () if (pVT) { TTime dur = (CTime::getLocalTime() - _PlayStart) / 1000; - std::string title; - title = toString("%02d:%02d %s", dur / 60, dur % 60, _CurrentSong.Title.c_str()); + uint min = (dur / 60) % 60; + uint sec = dur % 60; + uint hour = dur / 3600; + + std::string title(toString("%02d:%02d", min, sec)); + if (hour > 0) title = toString("%02d:", hour) + title; + title += " " + _CurrentSong.Title; pVT->setText(ucstring::makeFromUtf8(title)); } From 5b4b7893f8dcb13465f5f91dd6c3685cc9986c46 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 5 Nov 2018 13:11:43 +0200 Subject: [PATCH 133/303] Fixed: openURL crash under linux --HG-- branch : develop --- code/nel/src/misc/common.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/nel/src/misc/common.cpp b/code/nel/src/misc/common.cpp index 599f3cfb2..48e6e9845 100644 --- a/code/nel/src/misc/common.cpp +++ b/code/nel/src/misc/common.cpp @@ -1720,12 +1720,12 @@ static bool openDocWithExtension (const std::string &document, const std::string const char *previousEnv = getenv("LD_LIBRARY_PATH"); // clear LD_LIBRARY_PATH to avoid problems with Steam Runtime - setenv("LD_LIBRARY_PATH", "", 1); + if (previousEnv) setenv("LD_LIBRARY_PATH", "", 1); bool res = launchProgram(command, document); // restore previous LD_LIBRARY_PATH - setenv("LD_LIBRARY_PATH", previousEnv, 1); + if (previousEnv) setenv("LD_LIBRARY_PATH", previousEnv, 1); return res; #endif // NL_OS_WINDOWS From ab6467f64c36cc1cbfb7d2f614b66f88455756de Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 11 Nov 2018 23:50:16 +0200 Subject: [PATCH 134/303] Fixed: Html P element not using style attribute --HG-- branch : develop --- code/nel/include/nel/gui/libwww.h | 1 + code/nel/src/gui/group_html.cpp | 4 ++-- code/nel/src/gui/libwww.cpp | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/code/nel/include/nel/gui/libwww.h b/code/nel/include/nel/gui/libwww.h index 64258608e..9c6579f1f 100644 --- a/code/nel/include/nel/gui/libwww.h +++ b/code/nel/include/nel/gui/libwww.h @@ -208,6 +208,7 @@ namespace NLGUI HTML_ATTR(P,QUICK_HELP_EVENTS), HTML_ATTR(P,QUICK_HELP_LINK), HTML_ATTR(P,NAME), + HTML_ATTR(P,STYLE), }; enum diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index b606a093d..efea31898 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -2281,8 +2281,8 @@ namespace NLGUI { newParagraph(PBeginSpace); pushStyle(); - if (present[HTML_BLOCK_STYLE] && value[HTML_BLOCK_STYLE]) - getStyleParams(value[HTML_BLOCK_STYLE], _Style); + if (present[MY_HTML_P_STYLE] && value[MY_HTML_P_STYLE]) + getStyleParams(value[MY_HTML_P_STYLE], _Style); } break; case HTML_PRE: diff --git a/code/nel/src/gui/libwww.cpp b/code/nel/src/gui/libwww.cpp index 2e9b4451a..f00a92749 100644 --- a/code/nel/src/gui/libwww.cpp +++ b/code/nel/src/gui/libwww.cpp @@ -213,6 +213,7 @@ namespace NLGUI HTML_ATTR(P,QUICK_HELP_EVENTS), HTML_ATTR(P,QUICK_HELP_LINK), HTML_ATTR(P,NAME), + HTML_ATTR(P,STYLE), { 0 } }; From e5b7064a4dc53bfc2194ca5aaaf784489abe1afe Mon Sep 17 00:00:00 2001 From: Nimetu Date: Wed, 24 Oct 2018 14:22:35 +0300 Subject: [PATCH 135/303] Changed: New font texture implementation --HG-- branch : develop --- code/nel/include/nel/3d/computed_string.h | 5 + code/nel/include/nel/3d/font_generator.h | 2 + code/nel/include/nel/3d/font_manager.h | 17 +- code/nel/include/nel/3d/text_context.h | 13 + code/nel/include/nel/3d/texture_font.h | 133 ++++- code/nel/src/3d/font_generator.cpp | 5 + code/nel/src/3d/font_manager.cpp | 55 +- code/nel/src/3d/text_context.cpp | 28 +- code/nel/src/3d/texture_font.cpp | 692 +++++++++++++--------- code/ryzom/client/src/main_loop.cpp | 16 + 10 files changed, 637 insertions(+), 329 deletions(-) diff --git a/code/nel/include/nel/3d/computed_string.h b/code/nel/include/nel/3d/computed_string.h index 517200383..25d12a3ac 100644 --- a/code/nel/include/nel/3d/computed_string.h +++ b/code/nel/include/nel/3d/computed_string.h @@ -178,6 +178,10 @@ public: CVertexBuffer Vertices; CMaterial *Material; CRGBA Color; + ucstring Text; + + uint32 CacheVersion; + /// The width of the string, in pixels (eg: 30) float StringWidth; /// The height of the string, in pixels (eg: 10) @@ -223,6 +227,7 @@ public: */ CComputedString (bool bSetupVB=true) { + CacheVersion = 0; StringWidth = 0; StringHeight = 0; if (bSetupVB) diff --git a/code/nel/include/nel/3d/font_generator.h b/code/nel/include/nel/3d/font_generator.h index 5a07733a0..e71551c43 100644 --- a/code/nel/include/nel/3d/font_generator.h +++ b/code/nel/include/nel/3d/font_generator.h @@ -74,6 +74,8 @@ public: uint32 getUID() { return _UID; } + std::string getFontFileName() const; + private: static uint32 _FontGeneratorCounterUID; diff --git a/code/nel/include/nel/3d/font_manager.h b/code/nel/include/nel/3d/font_manager.h index 26ea02ce0..663e9d23a 100644 --- a/code/nel/include/nel/3d/font_manager.h +++ b/code/nel/include/nel/3d/font_manager.h @@ -59,6 +59,9 @@ class CFontManager CSmartPtr _MatFont; CSmartPtr _TexFont; + // Keep track number of textures created to properly report cache version + uint32 _TexCacheNr; + public: /** @@ -71,6 +74,7 @@ public: _NbChar = 0; _MatFont = NULL; _TexFont = NULL; + _TexCacheNr = 0; } @@ -94,7 +98,6 @@ public: */ CMaterial* getFontMaterial(); - /** * Compute primitive blocks and materials of each character of * the string. @@ -152,7 +155,8 @@ public: void dumpCache (const char *filename) { - _TexFont->dumpTextureFont (filename); + if (_TexFont) + _TexFont->dumpTextureFont (filename); } /** @@ -160,6 +164,15 @@ public: */ void invalidate(); + // get font atlas rebuild count + uint32 getCacheVersion() const + { + if (_TexFont) + return (_TexFont->getCacheVersion() << 16) + _TexCacheNr; + + return 0; + } + }; diff --git a/code/nel/include/nel/3d/text_context.h b/code/nel/include/nel/3d/text_context.h index a95916da4..1f75e1184 100644 --- a/code/nel/include/nel/3d/text_context.h +++ b/code/nel/include/nel/3d/text_context.h @@ -150,6 +150,10 @@ public: { nlassert (index < _CacheStrings.size()); CComputedString &rCS = _CacheStrings[index]; + if (rCS.CacheVersion != _FontManager->getCacheVersion()) + { + computeString(rCS.Text, rCS); + } if (_Shaded) { CRGBA bkup = rCS.Color; @@ -184,6 +188,10 @@ public: { nlassert (index < _CacheStrings.size()); CComputedString &rCS = _CacheStrings[index]; + if (rCS.CacheVersion != _FontManager->getCacheVersion()) + { + computeString(rCS.Text, rCS); + } if(_Shaded) { CRGBA bkup = rCS.Color; @@ -218,6 +226,11 @@ public: { nlassert (index < _CacheStrings.size()); CComputedString &rCS = _CacheStrings[index]; + if (rCS.CacheVersion != _FontManager->getCacheVersion()) + { + computeString(rCS.Text, rCS); + } + if (_Shaded) { CRGBA bkup = rCS.Color; diff --git a/code/nel/include/nel/3d/texture_font.h b/code/nel/include/nel/3d/texture_font.h index e743bb137..865615b63 100644 --- a/code/nel/include/nel/3d/texture_font.h +++ b/code/nel/include/nel/3d/texture_font.h @@ -18,6 +18,7 @@ #define NL_TEXTURE_FONT_H #include "nel/misc/types_nl.h" +#include "nel/misc/rect.h" #include "nel/3d/texture.h" namespace NL3D @@ -25,9 +26,6 @@ namespace NL3D class CFontGenerator; -#define TEXTUREFONT_NBCATEGORY 5 // Config 1 -//#define TEXTUREFONT_NBCATEGORY 4 - // **************************************************************************** /** * CTextureFont @@ -37,32 +35,59 @@ class CTextureFont : public ITexture public: - struct SLetterInfo + // Holds info for glyphs rendered on atlas + struct SGlyphInfo { - // To generate the letter - ucchar Char; - CFontGenerator *FontGenerator; + // font atlas info + uint32 CacheVersion; + + // atlas region with padding + uint32 X, Y, W, H; + + // rendered glyph size without padding + uint32 CharWidth; + uint32 CharHeight; + + // UV coords for rendered glyph without padding + float U0, V0, U1, V1; + + uint32 GlyphIndex; sint Size; bool Embolden; bool Oblique; + CFontGenerator *FontGenerator; + SGlyphInfo() + : CacheVersion(0), + U0(0.f), V0(0.f), U1(0.f), V1(0.f), + X(0), Y(0), W(0), H(0), CharWidth(0), CharHeight(0), + GlyphIndex(0), Size(0), Embolden(false), Oblique(false), FontGenerator(NULL) + { + } + }; - // The less recently used infos - SLetterInfo *Next, *Prev; + // Holds info for glyphs displayed on screen + struct SLetterInfo + { + ucchar Char; + sint Size; + bool Embolden; + bool Oblique; + CFontGenerator *FontGenerator; - uint Cat; // 8x8, 16x16, 24x24, 32x32 - - ////////////////////////////////////////////////////////////////////// - - float U ,V; - uint32 CharWidth; - uint32 CharHeight; - uint32 GlyphIndex; // number of the character in the this font + uint32 GlyphIndex; + uint32 CharWidth; // Displayed glyph height + uint32 CharHeight; // Displayed glyph height sint32 Top; // Distance between origin and top of the texture sint32 Left; // Distance between origin and left of the texture sint32 AdvX; // Advance to the next caracter - SLetterInfo():Char(0), FontGenerator(NULL), Size(0), Embolden(false), Oblique(false), Next(NULL), Prev(NULL), Cat(0), CharWidth(0), CharHeight(0), GlyphIndex(0), Top(0), Left(0), AdvX(0) + SGlyphInfo* glyph; + + SLetterInfo() + : Char(0), Size(0), Embolden(false), Oblique(false), FontGenerator(NULL), + GlyphIndex(0), CharWidth(0), CharHeight(0), Top(0), Left(0), AdvX(0), + glyph(NULL) { } }; @@ -70,14 +95,13 @@ public: struct SLetterKey { ucchar Char; - CFontGenerator *FontGenerator; sint Size; bool Embolden; bool Oblique; + CFontGenerator *FontGenerator; + // Does not use FontGenerator in return value uint32 getVal(); - //bool operator < (const SLetterKey&k) const; - //bool operator == (const SLetterKey&k) const; SLetterKey():Char(0), FontGenerator(NULL), Size(0), Embolden(false), Oblique(false) { @@ -96,19 +120,76 @@ public: void doGenerate (bool async = false); // This function manage the cache if the letter wanted does not exist - SLetterInfo* getLetterInfo (SLetterKey& k); + // \param render Set to true if letter is currently visible on screen + SLetterInfo* getLetterInfo (SLetterKey& k, bool render); void dumpTextureFont (const char *filename); + // Version is increased with each rebuild of font atlas + uint32 getCacheVersion() const { return _CacheVersion; } + private: + uint32 _CacheVersion; + + // current texture size + uint32 _TextureSizeX; + uint32 _TextureSizeY; + + // maximum texture size allowed + uint32 _TextureMaxW; + uint32 _TextureMaxH; + + // padding around glyphs + uint8 _PaddingL, _PaddingT; + uint8 _PaddingR, _PaddingB; // To find a letter in the texture - std::map Accel; - std::vector Letters[TEXTUREFONT_NBCATEGORY]; - SLetterInfo *Front[TEXTUREFONT_NBCATEGORY], *Back[TEXTUREFONT_NBCATEGORY]; + // Keep track of available space in main texture + std::vector _AtlasNodes; - void rebuildLetter (sint cat, sint x, sint y); + std::vector _Letters; + + // lookup letter from letter cache or create new + SLetterInfo* findLetter(SLetterKey& k, bool insert); + + // lower/upper bound of glyphs to render, sizes outside are scaled bitmaps + uint _MinGlyphSize; + uint _MaxGlyphSize; + // start using size stem from this font size + uint _GlyphSizeStepMin; + // every n'th font size is rendered, intermediates are using bitmap scaling + uint _GlyphSizeStep; + + // rendered glyph cache + std::list _GlyphCache; + SGlyphInfo* findLetterGlyph(SLetterInfo *letter, bool insert); + + // render letter glyph into glyph cache + SGlyphInfo* renderLetterGlyph(SLetterInfo *letter, uint32 bitmapFontSize); + + // copy glyph bitmap into texture and invalidate that region + void copyGlyphBitmap(uint8* bitmap, uint32 bitmapW, uint32 bitmapH, uint32 atlasX, uint32 atlasY); + + // Find best fit for WxH rect in atlas + uint fitRegion(uint index, uint width, uint height); + + // Return top/left from font texture or false if there is no more room + bool reserveAtlas(const uint32 width, const uint32 height, uint32 &x, uint32 &y); + + // repack glyphs, resize texture, and invalidate unused glyphs. + void repackAtlas(); + void repackAtlas(uint32 width, uint32 height); + + // resize texture, + bool resizeAtlas(); + + // remove all glyphs from atlas, clear glyph cache, letter info is kept + void clearAtlas(); + + // if return true: newW, newH contains next size font atlas should be resized + // if return false: _TextureMaxW and _TextureMaxH is reached + bool getNextTextureSize(uint32 &newW, uint32 &newH) const; /// Todo: serialize a font texture. public: diff --git a/code/nel/src/3d/font_generator.cpp b/code/nel/src/3d/font_generator.cpp index f50b61c5b..b0e917b6f 100644 --- a/code/nel/src/3d/font_generator.cpp +++ b/code/nel/src/3d/font_generator.cpp @@ -81,6 +81,11 @@ const char *CFontGenerator::getFT2Error(FT_Error fte) return ukn; } +std::string CFontGenerator::getFontFileName() const +{ + return _FontFileName; +} + CFontGenerator *newCFontGenerator(const std::string &fontFileName) { return new CFontGenerator(fontFileName); diff --git a/code/nel/src/3d/font_manager.cpp b/code/nel/src/3d/font_manager.cpp index 3b77a2100..d00ebb8f5 100644 --- a/code/nel/src/3d/font_manager.cpp +++ b/code/nel/src/3d/font_manager.cpp @@ -46,6 +46,7 @@ CMaterial* CFontManager::getFontMaterial() if (_TexFont == NULL) { _TexFont = new CTextureFont; + _TexCacheNr++; } if (_MatFont == NULL) @@ -142,11 +143,17 @@ void CFontManager::computeString (const ucstring &s, sint32 nMaxZ = -1000000, nMinZ = 1000000; output.StringHeight = 0; + // save string info for later rebuild as needed + output.Text = s; + output.CacheVersion = getCacheVersion(); + uint j = 0; { CVertexBufferReadWrite vba; output.Vertices.lock (vba); + hlfPixScrW = 0.f; + hlfPixScrH = 0.f; // For all chars for (uint i = 0; i < s.size(); i++) @@ -157,38 +164,43 @@ void CFontManager::computeString (const ucstring &s, k.Size = fontSize; k.Embolden = embolden; k.Oblique = oblique; - CTextureFont::SLetterInfo *pLI = pTexFont->getLetterInfo (k); + // render letter + CTextureFont::SLetterInfo *pLI = pTexFont->getLetterInfo (k, true); if(pLI != NULL) { - if ((pLI->CharWidth > 0) && (pLI->CharHeight > 0)) + if (pLI->glyph) { + // If letter is heavily upscaled, then there is noticeable clipping on edges + // fixing UV will make it bit better + if ((pLI->Size >> 1) > pLI->glyph->Size) + { + hlfPixTexW = 0.5f * TexRatioW; + hlfPixTexH = 0.5f * TexRatioH; + } + // Creating vertices dx = pLI->Left; - dz = -((sint32)pLI->CharHeight-(sint32)(pLI->Top)); - u1 = pLI->U - hlfPixTexW; - v1 = pLI->V - hlfPixTexH; - u2 = pLI->U + ((float)pLI->CharWidth) * TexRatioW + hlfPixTexW; - v2 = pLI->V + ((float)pLI->CharHeight) * TexRatioH + hlfPixTexH; + dz = -((sint32)pLI->CharHeight - (sint32)(pLI->Top)); x1 = (penx + dx) - hlfPixScrW; z1 = (penz + dz) - hlfPixScrH; - x2 = (penx + dx + (sint32)pLI->CharWidth) + hlfPixScrW; + x2 = (penx + dx + (sint32)pLI->CharWidth) + hlfPixScrW; z2 = (penz + dz + (sint32)pLI->CharHeight) + hlfPixScrH; vba.setVertexCoord (j, x1, 0, z1); - vba.setTexCoord (j, 0, u1, v2); + vba.setTexCoord (j, 0, pLI->glyph->U0-hlfPixTexW, pLI->glyph->V1+hlfPixTexH); ++j; vba.setVertexCoord (j, x2, 0, z1); - vba.setTexCoord (j, 0, u2, v2); + vba.setTexCoord (j, 0, pLI->glyph->U1+hlfPixTexW, pLI->glyph->V1+hlfPixTexH); ++j; vba.setVertexCoord (j, x2, 0, z2); - vba.setTexCoord (j, 0, u2, v1); + vba.setTexCoord (j, 0, pLI->glyph->U1+hlfPixTexW, pLI->glyph->V0-hlfPixTexH); ++j; vba.setVertexCoord (j, x1, 0, z2); - vba.setTexCoord (j, 0, u1, v1); + vba.setTexCoord (j, 0, pLI->glyph->U0-hlfPixTexW, pLI->glyph->V0-hlfPixTexH); ++j; // String Bound @@ -245,6 +257,19 @@ void CFontManager::computeStringInfo ( const ucstring &s, { output.Color = color; + // save string info for later rebuild as needed + output.Text = s; + output.CacheVersion = 0; + + if (s.empty()) + { + output.StringWidth = 0.f; + output.StringHeight = 0; + output.StringLine = 0; + + return; + } + // resize fontSize if window not of 800x600. if (keep800x600Ratio) { @@ -273,7 +298,7 @@ void CFontManager::computeStringInfo ( const ucstring &s, k.Size = fontSize; k.Embolden = embolden; k.Oblique = oblique; - pLI = pTexFont->getLetterInfo (k); + pLI = pTexFont->getLetterInfo (k, false); if(pLI != NULL) { if ((pLI->CharWidth > 0) && (pLI->CharHeight > 0)) @@ -318,7 +343,11 @@ void CFontManager::invalidate() { if (_TexFont) _TexFont = NULL; + _TexFont = new CTextureFont; + _TexCacheNr++; + + getFontMaterial()->setTexture(0, _TexFont); } diff --git a/code/nel/src/3d/text_context.cpp b/code/nel/src/3d/text_context.cpp index 5fcc43daa..235ea9fcb 100644 --- a/code/nel/src/3d/text_context.cpp +++ b/code/nel/src/3d/text_context.cpp @@ -74,25 +74,9 @@ uint32 CTextContext::textPush (const char *format, ...) char *str; NLMISC_CONVERT_VARGS (str, format, NLMISC::MaxCStringSize); - if (_CacheNbFreePlaces == 0) - { - CComputedString csTmp; - - _CacheStrings.push_back (csTmp); - if (_CacheFreePlaces.empty()) - _CacheFreePlaces.resize (1); - _CacheFreePlaces[0] = (uint32)_CacheStrings.size()-1; - _CacheNbFreePlaces = 1; - } - - // compute the string. - uint32 index = _CacheFreePlaces[_CacheNbFreePlaces-1]; - CComputedString &strToFill = _CacheStrings[index]; - _FontManager->computeString (str, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, strToFill, _Keep800x600Ratio); - - _CacheNbFreePlaces--; - - return index; + ucstring uc; + uc.fromUtf8((const char *)str); + return textPush(uc); } // ------------------------------------------------------------------------------------------------ @@ -115,8 +99,10 @@ uint32 CTextContext::textPush (const ucstring &str) uint32 index = _CacheFreePlaces[_CacheNbFreePlaces-1]; nlassert (index < _CacheStrings.size()); CComputedString &strToFill = _CacheStrings[index]; - _FontManager->computeString (str, _FontGen, _Color - , _FontSize, _Embolden, _Oblique, _Driver, strToFill, _Keep800x600Ratio); + + _FontManager->computeString (str, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, strToFill, _Keep800x600Ratio); + // just compute letters, glyphs are rendered on demand before first draw + //_FontManager->computeStringInfo(str, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, strToFill, _Keep800x600Ratio); _CacheNbFreePlaces--; diff --git a/code/nel/src/3d/texture_font.cpp b/code/nel/src/3d/texture_font.cpp index cf46d025d..eac8cb545 100644 --- a/code/nel/src/3d/texture_font.cpp +++ b/code/nel/src/3d/texture_font.cpp @@ -23,7 +23,7 @@ #include "nel/misc/common.h" #include "nel/misc/rect.h" #include "nel/misc/file.h" - +#include "nel/misc/path.h" using namespace std; using namespace NLMISC; @@ -35,37 +35,14 @@ using namespace NLMISC; namespace NL3D { -// Config 1 -const int TextureSizeX = 1024; -const int TextureSizeY = 1024; // If change this value -> change NbLine too -const int Categories[TEXTUREFONT_NBCATEGORY] = { 8, 16, 24, 32, 64 }; -const int NbLine[TEXTUREFONT_NBCATEGORY] = { 8, 24, 16, 4, 1 }; // Based on textsize - -/* -const int TextureSizeX = 256; -const int TextureSizeY = 256; -const int Categories[TEXTUREFONT_NBCATEGORY] = { 8, 16, 24, 32 }; -const int NbLine[TEXTUREFONT_NBCATEGORY] = { 4, 6, 4, 1 }; // Based on textsize -*/ - -// --------------------------------------------------------------------------- -inline uint32 CTextureFont::SLetterKey::getVal() -{ - // this limits Size to 6bits - // Large sizes already render wrong when many - // different glyphs are used due to limited texture atlas - uint8 eb = ((uint)Embolden) + ((uint)Oblique << 1); - if (FontGenerator == NULL) - return Char + ((Size&255)<<16) + (eb << 22); - else - return Char + ((Size&255)<<16) + (eb << 22) + ((FontGenerator->getUID()&0xFF)<<24); -} - // --------------------------------------------------------------------------- CTextureFont::CTextureFont() + : _CacheVersion(1), + _TextureSizeX(512), _TextureSizeY(512), _TextureMaxW(4096), _TextureMaxH(4096), + _PaddingL(0), _PaddingT(0), _PaddingR(1), _PaddingB(1), + _MinGlyphSize(5), _MaxGlyphSize(200), + _GlyphSizeStepMin(50), _GlyphSizeStep(5) { - uint i; - setFilterMode (ITexture::Linear, ITexture::LinearMipMapOff); setWrapS (ITexture::Repeat); @@ -75,53 +52,9 @@ CTextureFont::CTextureFont() setReleasable (false); - resize (TextureSizeX, TextureSizeY, CBitmap::Alpha); - for(i = 0; i < TextureSizeX*TextureSizeY; ++i) - getPixels()[i] = 0; - // convertToType (CBitmap::Alpha); + resize (_TextureSizeX, _TextureSizeY, CBitmap::Alpha, true); - sint posY = 0; - - for(i = 0; i < TEXTUREFONT_NBCATEGORY; ++i) - { - // Number of chars per cache - Letters[i].resize ((TextureSizeX/Categories[i])*NbLine[i]); - - for(uint32 j = 0; j < Letters[i].size(); ++j) - { - SLetterInfo &rLetter = Letters[i][j]; - rLetter.Char = 0xffff; - rLetter.FontGenerator = NULL; - rLetter.Size= 0; - rLetter.Embolden = false; - rLetter.Oblique = false; - - // The less recently used infos - if (j < Letters[i].size()-1) - rLetter.Next = &Letters[i][j+1]; - else - rLetter.Next = NULL; - - if (j > 0) - rLetter.Prev = &Letters[i][j-1]; - else - rLetter.Prev = NULL; - - rLetter.Cat = i; - - sint sizeX = TextureSizeX/Categories[i]; - rLetter.U = (Categories[i]*(j%sizeX)) / ((float)TextureSizeX); - rLetter.V = (posY + Categories[i]*((sint)(j/sizeX))) / ((float)TextureSizeY); - - ///////////////////////////////////////////////// - - rLetter.CharWidth = rLetter.CharHeight = 0; - rLetter.GlyphIndex = rLetter.Top = rLetter.Left = rLetter.AdvX = 0; - } - Front[i] = &Letters[i][0]; - Back[i] = &Letters[i][Letters[i].size()-1]; - posY += NbLine[i] * Categories[i]; - } + _AtlasNodes.push_back(CRect(0, 0, _TextureSizeX, _TextureSizeY)); } @@ -129,17 +62,16 @@ CTextureFont::~CTextureFont() { } - // --------------------------------------------------------------------------- void CTextureFont::dumpTextureFont(const char *filename) { CBitmap b; COFile f( filename ); - b.resize (TextureSizeX, TextureSizeY, CBitmap::RGBA); + b.resize (_TextureSizeX, _TextureSizeY, CBitmap::RGBA); CObjectVector&bits = b.getPixels(); CObjectVector&src = getPixels(); - for (uint i = 0; i < (TextureSizeX*TextureSizeY); ++i) + for (uint i = 0; i < (_TextureSizeX*_TextureSizeY); ++i) { bits[i*4+0] = bits[i*4+1] = bits[i*4+2] = bits[i*4+3] = src[i]; } @@ -147,242 +79,468 @@ void CTextureFont::dumpTextureFont(const char *filename) b.writeTGA (f, 32); } +// --------------------------------------------------------------------------- +bool CTextureFont::getNextTextureSize(uint32 &newW, uint32 &newH) const +{ + // width will be resized first (256x256 -> 512x256) + if (_TextureSizeX <= _TextureSizeY) + { + newW = _TextureSizeX * 2; + newH = _TextureSizeY; + } + else + { + newW = _TextureSizeX; + newH = _TextureSizeY * 2; + } + + // no more room + return newW <= _TextureMaxW && newH <= _TextureMaxH; +} // --------------------------------------------------------------------------- -// cat : categories where the letter is -// x : pos x of the letter -// y : pos y of the letter -void CTextureFont::rebuildLetter (sint cat, sint x, sint y) +// out of room, clear everything and rebuild glyphs on demand +// note: text will display wrong until glyphs get rendered again +void CTextureFont::clearAtlas() { - sint sizex = TextureSizeX / Categories[cat]; - sint index = x + y*sizex; - SLetterInfo &rLetter = Letters[cat][index]; + nlwarning("Glyph cache will be cleared."); - if (rLetter.FontGenerator == NULL) - return; + _AtlasNodes.clear(); + _AtlasNodes.push_back(CRect(0, 0, _TextureSizeX, _TextureSizeY)); - sint catTopY = 0; - sint c = 0; - while (c < cat) + // clear texture + _Data[0].fill(0); + + // clear glyph cache + for(uint i = 0; i< _Letters.size(); ++i) { - catTopY += NbLine[c] * Categories[c]; - ++c; + _Letters[i].glyph = NULL; } - // Destination position in pixel of the letter - sint posx = x * Categories[cat]; - sint posy = catTopY + y * Categories[cat]; + _GlyphCache.clear(); - uint32 pitch = 0; - uint8 *bitmap = rLetter.FontGenerator->getBitmap ( rLetter.Char, rLetter.Size, rLetter.Embolden, rLetter.Oblique, - rLetter.CharWidth, rLetter.CharHeight, - pitch, rLetter.Left, rLetter.Top, - rLetter.AdvX, rLetter.GlyphIndex ); + _CacheVersion++; - // Copy FreeType buffer - uint i; - for (i = 0; i < rLetter.CharHeight; ++i) + touch(); +} + +// --------------------------------------------------------------------------- +void CTextureFont::repackAtlas() +{ + repackAtlas(_TextureSizeX, _TextureSizeY); +} + +// --------------------------------------------------------------------------- +// backup old glyphs and move them to newly resized texture +// new atlas will be sorted if _GlyphCache is +void CTextureFont::repackAtlas(uint32 newW, uint32 newH) +{ + uint32 newCacheVersion = _CacheVersion+1; + + CBitmap btm; + uint32 oldW, oldH; + + oldW = _TextureSizeX; + oldH = _TextureSizeY; + btm.resize(oldW, oldH, CBitmap::Alpha, true); + btm.blit(this, 0, 0); + + // resize texture + if (_TextureSizeX != newW || _TextureSizeY != newH) { - uint8 *pDst = &_Data[0][posx + (posy+i)*TextureSizeY]; - uint8 *pSrc = &bitmap[i*pitch]; - for (uint j = 0; j < rLetter.CharWidth; ++j) + _TextureSizeX = newW; + _TextureSizeY = newH; + resize (_TextureSizeX, _TextureSizeY, CBitmap::Alpha, true); + } + else + { + _Data[0].fill(0); + } + + // release atlas and rebuild + _AtlasNodes.clear(); + _AtlasNodes.push_back(CRect(0, 0, _TextureSizeX, _TextureSizeY)); + + CObjectVector&src = btm.getPixels(); + for(std::list::iterator it = _GlyphCache.begin(); it != _GlyphCache.end(); ++it) + { + if (it->CacheVersion != _CacheVersion) { - *pDst = *pSrc; - ++pDst; - ++pSrc; + // TODO: must remove glyph from all letters before removing glyph from cache + //continue; + } + + SGlyphInfo &glyph = *it; + + glyph.CacheVersion = newCacheVersion; + + uint32 atlasX, atlasY; + if (reserveAtlas(glyph.W, glyph.H, atlasX, atlasY)) + { + for (uint y = 0; y < glyph.H; ++y) + { + uint8 *pDst = &_Data[0][(atlasY + y) * _TextureSizeX + atlasX]; + for (uint x = 0; x < glyph.W; ++x) + { + *pDst = src[(glyph.Y + y) * oldW + glyph.X + x]; + ++pDst; + } + } + + // TODO: dup code with renderGlyph + glyph.U0 = (atlasX+_PaddingL) / (float)_TextureSizeX; + glyph.V0 = (atlasY+_PaddingT) / (float)_TextureSizeY; + glyph.U1 = (atlasX+_PaddingL+glyph.CharWidth) / (float)_TextureSizeX; + glyph.V1 = (atlasY+_PaddingT+glyph.CharHeight) / (float)_TextureSizeY; + + glyph.X = atlasX; + glyph.Y = atlasY; } } - // Black border bottom and right - for (i = 0; i < rLetter.CharHeight+1; ++i) + _CacheVersion = newCacheVersion; + + // invalidate full texture + touch(); +} + +// --------------------------------------------------------------------------- +bool CTextureFont::resizeAtlas() +{ + uint32 newW, newH; + if (!getNextTextureSize(newW, newH)) { - _Data[0][posx + rLetter.CharWidth + (posy+i)*TextureSizeY] = 0; + nlwarning("Font texture at maximum (%d,%d). Resize failed.", _TextureSizeX, _TextureSizeY); + return false; } - for (i = 0; i < rLetter.CharWidth+1; ++i) - { - _Data[0][posx + i + (posy+rLetter.CharHeight)*TextureSizeY] = 0; - } - - /* - dumpTextureFont (this); - int a = 5; - a++; - */ + // resize and redraw + repackAtlas(newW, newH); + return true; } // --------------------------------------------------------------------------- void CTextureFont::doGenerate(bool async) { - // Rectangle invalidate ? - if (_ListInvalidRect.begin()!=_ListInvalidRect.end()) - { - // Yes, rebuild only those rectangles. - - // For each rectangle to compute - std::list::iterator ite=_ListInvalidRect.begin(); - while (ite!=_ListInvalidRect.end()) - { - // Compute rectangle coordinates - sint x = ite->left(); - sint y = ite->bottom(); - - // Look in which category is the rectangle - sint cat = 0; - sint catTopY = 0; - sint catBotY = NbLine[cat] * Categories[cat]; - while (y > catBotY) - { - if (y < catBotY) - break; - ++cat; - nlassert (cat < TEXTUREFONT_NBCATEGORY); - catTopY = catBotY; - catBotY += NbLine[cat] * Categories[cat]; - } - - x = x / Categories[cat]; - y = ite->top(); - y = y - catTopY; - y = y / Categories[cat]; - - rebuildLetter (cat, x, y); - - // Next rectangle - ite++; - } - } - else - { - for(int cat = 0; cat < TEXTUREFONT_NBCATEGORY; ++cat) - { - sint sizex = TextureSizeX / Categories[cat]; - sint sizey = NbLine[cat]; - for (sint y = 0; y < sizey; y++) - for (sint x = 0; x < sizex; x++) - { - rebuildLetter (cat, x, y); - } - } - } -/* - dumpTextureFont (this); - int a = 5; -*/ + /* + nlinfo("doGenerate: Letters(%d/%d), Glyphs(%d/%d)\n", _Letters.size(), _Letters.size() * sizeof(SLetterInfo), + _GlyphCache.size(), _GlyphCache.size() * sizeof(SGlyphInfo)); + //std::string fname = CFile::findNewFile("/tmp/font-texture.tga"); + std::string fname = toString("/tmp/font-texture-%p-%03d.tga", this, _CacheVersion); + dumpTextureFont (fname.c_str()); + */ } // --------------------------------------------------------------------------- -CTextureFont::SLetterInfo* CTextureFont::getLetterInfo (SLetterKey& k) +uint CTextureFont::fitRegion(uint index, uint width, uint height) { - sint cat; - uint32 nTmp = k.getVal(); - map::iterator itAccel = Accel.find (nTmp); - if (itAccel != Accel.end()) + if (_AtlasNodes[index].X + width > _TextureSizeX - 1) { - // Put it in the first place - SLetterInfo *pLetterToMove = itAccel->second; - cat = pLetterToMove->Cat; - if (pLetterToMove != Front[cat]) + return -1; + } + + uint x = _AtlasNodes[index].X; + uint y = _AtlasNodes[index].Y; + sint widthLeft = width; + + while(widthLeft > 0) + { + if (_AtlasNodes[index].Y > y) { - // unlink - nlassert(pLetterToMove->Prev); - pLetterToMove->Prev->Next = pLetterToMove->Next; - if (pLetterToMove == Back[cat]) - { - Back[cat] = pLetterToMove->Prev; - } - else - { - pLetterToMove->Next->Prev = pLetterToMove->Prev; - } - - // link to front - pLetterToMove->Prev = NULL; - pLetterToMove->Next = Front[cat]; - Front[cat]->Prev = pLetterToMove; - Front[cat] = pLetterToMove; + y = _AtlasNodes[index].Y; } - return pLetterToMove; + + // _AtlasNodes[0] for margin is not used here + if (_AtlasNodes[index].Y + height > _TextureSizeY - 1) + { + return -1; + } + + widthLeft -= _AtlasNodes[index].Width; + index++; } - // The letter is not already present - // Found the category of the new letter - uint32 width, height; + return y; +} - //k.FontGenerator->getSizes (k.Char, k.Size, width, height); - // \todo mat : Temp !!! Try to use freetype cache - uint32 nPitch, nGlyphIndex; - sint32 nLeft, nTop, nAdvX; - k.FontGenerator->getBitmap (k.Char, k.Size, k.Embolden, k.Oblique, width, height, nPitch, nLeft, nTop, - nAdvX, nGlyphIndex ); +bool CTextureFont::reserveAtlas(const uint32 width, const uint32 height, uint32 &x, uint32 &y) +{ + if (_AtlasNodes.empty()) + { + nlwarning("No available space in texture atlas (_AtlasNodes.empty() == true)"); + return false; + } - // Add 1 pixel space for black border to get correct category - cat = 0; - if (((sint)width+1 > Categories[TEXTUREFONT_NBCATEGORY-1]) || - ((sint)height+1 > Categories[TEXTUREFONT_NBCATEGORY-1])) + x = 0; + y = 0; + + sint bestIndex = -1; + sint bestWidth = _TextureSizeX; + sint bestHeight = _TextureSizeY; + + sint selY=0; + + for (uint i = 0; i < _AtlasNodes.size(); ++i) + { + selY = fitRegion(i, width, height); + if (selY >=0) + { + if (((selY + height) < bestHeight) || ((selY + height) == bestHeight && _AtlasNodes[i].Width > 0 && _AtlasNodes[i].Width < bestWidth)) + { + bestHeight = selY + height; + bestIndex = i; + bestWidth = _AtlasNodes[i].Width; + x = _AtlasNodes[i].X; + y = selY; + } + } + } + + if (bestIndex == -1) + { + x = 0; + y = 0; + return false; + } + + CRect r(x, y + height, width, 0); + _AtlasNodes.insert(_AtlasNodes.begin() + bestIndex, r); + + // shrink or remove nodes overlaping with newly inserted node + for(uint i = bestIndex+1; i< _AtlasNodes.size(); i++) + { + if (_AtlasNodes[i].X < (_AtlasNodes[i-1].X + _AtlasNodes[i-1].Width)) + { + sint shrink = _AtlasNodes[i-1].X + _AtlasNodes[i-1].Width - _AtlasNodes[i].X; + _AtlasNodes[i].X += shrink; + if (_AtlasNodes[i].Width > shrink) + { + _AtlasNodes[i].Width -= shrink; + break; + } + _AtlasNodes.erase(_AtlasNodes.begin() + i); + i--; + } + else break; + } + + // merge nearby nodes from same row + for(uint i = 0; i < _AtlasNodes.size() - 1; i++) + { + if (_AtlasNodes[i].Y == _AtlasNodes[i+1].Y) + { + _AtlasNodes[i].Width += _AtlasNodes[i+1].Width; + _AtlasNodes.erase(_AtlasNodes.begin() + i + 1); + i--; + } + } + + return true; +} + +// --------------------------------------------------------------------------- +// bitmap : texture data +// bitmapW : bitmap width +// bitmapH : bitmap height +// atlasX : pos x in font texture +// atlasY : pos y in font texture +void CTextureFont::copyGlyphBitmap(uint8* bitmap, uint32 bitmapW, uint32 bitmapH, uint32 atlasX, uint32 atlasY) +{ + for (uint bY = 0; bY < bitmapH; ++bY) + { + uint8 *pDst = &_Data[0][(atlasY+_PaddingT+bY) * _TextureSizeX+atlasX+_PaddingL]; + for (uint bX = 0; bX < bitmapW; ++bX) + { + *pDst = bitmap[bY * bitmapW+bX]; + ++pDst; + } + } + + if (_PaddingR > 0 || _PaddingB > 0 || _PaddingL > 0 || _PaddingT > 0) + { + for(uint i = 0; i<(bitmapH+_PaddingT+_PaddingB); ++i) + { + if (_PaddingT > 0) _Data[0][(atlasY + i) * _TextureSizeX + atlasX ] = 0; + if (_PaddingB > 0) _Data[0][(atlasY + i) * _TextureSizeX + atlasX + _PaddingL + bitmapW] = 0; + } + + for (uint i = 0; i<(bitmapW+_PaddingL+_PaddingR); ++i) + { + if (_PaddingL > 0) _Data[0][atlasY * _TextureSizeX + atlasX + i] = 0; + if (_PaddingB > 0) _Data[0][(atlasY + _PaddingT + bitmapH) * _TextureSizeX + atlasX + i] = 0; + } + } + + CRect r(atlasX, atlasY, bitmapW + _PaddingL + _PaddingR, bitmapH + _PaddingT + _PaddingB); + touchRect(r); +} + + +// --------------------------------------------------------------------------- +CTextureFont::SGlyphInfo* CTextureFont::renderLetterGlyph(SLetterInfo *letter, uint bitmapFontSize) +{ + uint32 nPitch; + sint32 left; + sint32 top; + sint32 advx; + uint32 charWidth; + uint32 charHeight; + uint32 glyphIndex; + + uint8 *bitmap = letter->FontGenerator->getBitmap (letter->Char, bitmapFontSize, letter->Embolden, letter->Oblique, + charWidth, charHeight, + nPitch, left, top, + advx, glyphIndex ); + + uint32 atlasX, atlasY; + uint32 rectW, rectH; + rectW = charWidth + _PaddingL + _PaddingR; + rectH = charHeight + _PaddingT + _PaddingB; + + if (!reserveAtlas(rectW, rectH, atlasX, atlasY)) + { + // no room return NULL; + } + copyGlyphBitmap(bitmap, charWidth, charHeight, atlasX, atlasY); - while (((sint)width+1 > Categories[cat]) || ((sint)height+1 > Categories[cat])) + SGlyphInfo* glyphInfo = NULL; { - ++cat; - nlassert (cat != TEXTUREFONT_NBCATEGORY); + // keep cache sorted by height (smaller first) + std::list::iterator it = _GlyphCache.begin(); + while(it != _GlyphCache.end() && it->CharHeight < charHeight) + { + ++it; + } + + it = _GlyphCache.insert(it, SGlyphInfo()); + glyphInfo = &(*it); } - // And replace the less recently used letter - SLetterKey k2; - k2.Char = Back[cat]->Char; - k2.FontGenerator = Back[cat]->FontGenerator; - k2.Size = Back[cat]->Size; - k2.Embolden = Back[cat]->Embolden; - k2.Oblique = Back[cat]->Oblique; + glyphInfo->GlyphIndex = glyphIndex; + glyphInfo->Size = bitmapFontSize; + glyphInfo->Embolden = letter->Embolden; + glyphInfo->Oblique = letter->Oblique; + glyphInfo->FontGenerator = letter->FontGenerator; + glyphInfo->CacheVersion = _CacheVersion; - itAccel = Accel.find (k2.getVal()); - if (itAccel != Accel.end()) + glyphInfo->U0 = (atlasX+_PaddingL) / (float)_TextureSizeX; + glyphInfo->V0 = (atlasY+_PaddingT) / (float)_TextureSizeY; + glyphInfo->U1 = (atlasX+_PaddingL+charWidth) / (float)_TextureSizeX; + glyphInfo->V1 = (atlasY+_PaddingT+charHeight) / (float)_TextureSizeY; + + glyphInfo->CharWidth = charWidth; + glyphInfo->CharHeight = charHeight; + + glyphInfo->X = atlasX; + glyphInfo->Y = atlasY; + glyphInfo->W = rectW; + glyphInfo->H = rectH; + + return glyphInfo; +} + + +// --------------------------------------------------------------------------- +CTextureFont::SGlyphInfo* CTextureFont::findLetterGlyph(SLetterInfo *letter, bool insert) +{ + uint bitmapFontSize = max((sint)_MinGlyphSize, min((sint)_MaxGlyphSize, letter->Size)); + if (_GlyphSizeStep > 1 && bitmapFontSize > _GlyphSizeStepMin) { - Accel.erase (itAccel); + uint size = (bitmapFontSize / _GlyphSizeStep) * _GlyphSizeStep; } - SLetterInfo *NewBack = Back[cat]->Prev; - NewBack->Next = NULL; - Back[cat]->Cat = cat; - Back[cat]->Char = k.Char; - Back[cat]->FontGenerator = k.FontGenerator; - Back[cat]->Size = k.Size; - Back[cat]->Embolden = k.Embolden; - Back[cat]->Oblique = k.Oblique; - Back[cat]->CharWidth = width; - Back[cat]->CharHeight = height; - Back[cat]->Top = nTop; - Back[cat]->Left = nLeft; - Back[cat]->AdvX = nAdvX; - Back[cat]->Prev = NULL; - Back[cat]->Next = Front[cat]; - Front[cat]->Prev = Back[cat]; - Front[cat] = Back[cat]; - Back[cat] = NewBack; - - Accel.insert (map::value_type(k.getVal(),Front[cat])); - - // Invalidate the zone - sint index = (sint)(Front[cat] - &Letters[cat][0]);// / sizeof (SLetterInfo); - sint sizex = TextureSizeX / Categories[cat]; - sint x = index % sizex; - sint y = index / sizex; - x = x * Categories[cat]; - y = y * Categories[cat]; - - sint c = 0; - while (c < cat) + // CacheVersion not checked, all glyphs in cache must be rendered on texture + for(std::list::iterator it = _GlyphCache.begin(); it != _GlyphCache.end(); ++it) { - y = y + NbLine[c] * Categories[c]; - ++c; + if (it->GlyphIndex == letter->GlyphIndex && + it->Size == bitmapFontSize && + it->Embolden == letter->Embolden && + it->Oblique == letter->Oblique && + it->FontGenerator == letter->FontGenerator) + { + return &(*it); + } } - // must update the char, WITH the black borders - CRect r (x, y, width+1, height+1); + if (insert) + { + return renderLetterGlyph(letter, bitmapFontSize); + } - touchRect (r); + return NULL; +} - return Front[cat]; +// --------------------------------------------------------------------------- +CTextureFont::SLetterInfo* CTextureFont::findLetter(SLetterKey &k, bool insert) +{ + // TODO: use std::map + for(uint i = 0; i < _Letters.size(); ++i) + { + if (_Letters[i].Char == k.Char && _Letters[i].Size == k.Size && + _Letters[i].Embolden == k.Embolden && _Letters[i].Oblique == k.Oblique && + _Letters[i].FontGenerator == k.FontGenerator) + { + return &_Letters[i]; + } + } + + if (insert) + { + _Letters.push_back(SLetterInfo()); + SLetterInfo* letter = &_Letters.back(); + + // get metrics for requested size + letter->Char = k.Char; + letter->Size = k.Size; + letter->Embolden = k.Embolden; + letter->Oblique = k.Oblique; + letter->FontGenerator = k.FontGenerator; + + uint32 nPitch; + letter->FontGenerator->getBitmap(letter->Char, letter->Size, letter->Embolden, letter->Oblique, + letter->CharWidth, letter->CharHeight, + nPitch, letter->Left, letter->Top, + letter->AdvX, letter->GlyphIndex ); + + return letter; + } + + return NULL; +} + +// --------------------------------------------------------------------------- +CTextureFont::SLetterInfo* CTextureFont::getLetterInfo (SLetterKey& k, bool render) +{ + // find already cached letter or create new one + SLetterInfo* letter = findLetter(k, true); + // letter not found (=NULL) or render not requested + if (!letter || !render) return letter; + + if (!letter->glyph || letter->glyph->CacheVersion != _CacheVersion) + { + // render glyph + letter->glyph = findLetterGlyph(letter, true); + if (letter->glyph == NULL) + { + // resize/repack and try again + if (!resizeAtlas()) repackAtlas(); + + letter->glyph = findLetterGlyph(letter, true); + if (letter->glyph == NULL) + { + // make room by clearing all glyphs and reduce max size for glyphs + clearAtlas(); + if (_MaxGlyphSize > _MinGlyphSize) + { + _MaxGlyphSize = max(_MinGlyphSize, _MaxGlyphSize - 10); + } + + letter->glyph = findLetterGlyph(letter, true); + } + } + } + + return letter; } } // NL3D diff --git a/code/ryzom/client/src/main_loop.cpp b/code/ryzom/client/src/main_loop.cpp index 4657f1dff..32b76391b 100644 --- a/code/ryzom/client/src/main_loop.cpp +++ b/code/ryzom/client/src/main_loop.cpp @@ -3419,6 +3419,22 @@ void displayDebugClusters() } +NLMISC_COMMAND(dumpFontTexture, "Write font texture to file", "") +{ + CInterfaceManager *im = CInterfaceManager::getInstance(); + if (TextContext) + { + std::string fname = CFile::findNewFile("font-texture.tga"); + TextContext->dumpCacheTexture(fname.c_str()); + im->displaySystemInfo(ucstring(fname + " created"), "SYS"); + } + else + { + im->displaySystemInfo(ucstring("Error: TextContext == NULL"), "SYS"); + } + return true; +} + // *************************************************************************** void inGamePatchUncompleteWarning() From 0334297c95c1aed33e3247c71022b3fd43dfcd75 Mon Sep 17 00:00:00 2001 From: AleaJactaEst Date: Sat, 3 Nov 2018 23:35:50 +0100 Subject: [PATCH 136/303] update CI to apply patch --- .gitlab-ci.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7366425c8..19bb68e75 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -59,7 +59,7 @@ Linux client build: # libxml2 : python-pyicu (support d'unicode), python-dev (support de... python) - apt-get install -y wget python-pyicu python-dev # Apply patch - - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) + - (for patchfile in $(cat patch/series); do echo "patch patch/$patchfile"; patch -f -Z -t -p 1 -i patch/$patchfile || exit 2; done) # Création de l'environnement de compilation - mkdir -p BUILD/x86_64 - cd BUILD/x86_64 @@ -144,7 +144,7 @@ Linux server debian_amd64_strech build: patch - apt-get install -y liblua5.2-0 liblua5.2-dev libluabind-dev libluabind0.9.1v5 # Apply patch - - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) + - (for patchfile in $(cat patch/series); do echo "patch patch/$patchfile"; patch -f -Z -t -p 1 -i patch/$patchfile || exit 2; done) # install squish - mkdir -p squish - (cd squish; wget -c https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/libsquish/squish-1.11.zip) @@ -224,7 +224,7 @@ Linux client debian_amd64_strech build: patch - apt-get install -y liblua5.2-0 liblua5.2-dev libluabind-dev libluabind0.9.1v5 libogg-dev libvorbis-dev # Apply patch - - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) + - (for patchfile in $(cat patch/series); do echo "patch patch/$patchfile"; patch -f -Z -t -p 1 -i patch/$patchfile || exit 2; done) # Build Curl - wget -q https://curl.haxx.se/download/curl-7.58.0.tar.gz -O curl.tar.gz - mkdir -p curl/build @@ -291,7 +291,7 @@ Linux client_static debian_amd64_strech build: patch - apt-get install -y liblua5.2-0 liblua5.2-dev # Apply patch - - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) + - (for patchfile in $(cat patch/series); do echo "patch patch/$patchfile"; patch -f -Z -t -p 1 -i patch/$patchfile || exit 2; done) # Build Curl - wget -q https://curl.haxx.se/download/curl-7.58.0.tar.gz -O curl.tar.gz - mkdir -p curl/build @@ -400,7 +400,7 @@ Linux client_static_debug debian_amd64_strech build: patch - apt-get install -y liblua5.2-0 liblua5.2-dev # Apply patch - - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) + - (for patchfile in $(cat patch/series); do echo "patch patch/$patchfile"; patch -f -Z -t -p 1 -i patch/$patchfile || exit 2; done) # Build Curl - wget -q https://curl.haxx.se/download/curl-7.58.0.tar.gz -O curl.tar.gz - mkdir -p curl/build @@ -476,7 +476,7 @@ Linux server_static debian_amd64_strech build: - apt-get dist-upgrade -y - DEBIAN_FRONTEND=noninteractive apt-get install -y apache2 apache2-utils autoconf autogen automake bison build-essential cmake cpputest default-libmysqlclient-dev fakeroot git libapache2-mod-php libboost-all-dev libfreetype6-dev libgif-dev libgl1-mesa-dev libjpeg62-turbo-dev liblua5.2-0 liblua5.2-dev liblzma-dev libogg-dev libopenal-dev libpng-dev libssh2-1-dev libssl-dev libtool libtool-bin libvorbis-dev libx11-dev libxml2-dev libxmu-dev libxrandr-dev libxrender-dev libxxf86vm-dev mercurial mysql-server php php-gd php-imagick php-mysql python3 python3-pip python3-bcrypt python3-venv rrdtool unzip wget zlib1g-dev # Apply patch - - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) + - (for patchfile in $(cat patch/series); do echo "patch patch/$patchfile"; patch -f -Z -t -p 1 -i patch/$patchfile || exit 2; done) # Build Curl - wget -q https://curl.haxx.se/download/curl-7.58.0.tar.gz -O curl.tar.gz - mkdir -p curl/build @@ -567,7 +567,7 @@ Linux server_static_debug debian_amd64_strech build: - apt-get dist-upgrade -y - DEBIAN_FRONTEND=noninteractive apt-get install -y apache2 apache2-utils autoconf autogen automake bison build-essential cmake cpputest default-libmysqlclient-dev fakeroot git libapache2-mod-php libboost-all-dev libfreetype6-dev libgif-dev libgl1-mesa-dev libjpeg62-turbo-dev liblua5.2-0 liblua5.2-dev liblzma-dev libogg-dev libopenal-dev libpng-dev libssh2-1-dev libssl-dev libtool libtool-bin libvorbis-dev libx11-dev libxml2-dev libxmu-dev libxrandr-dev libxrender-dev libxxf86vm-dev mercurial mysql-server php php-gd php-imagick php-mysql python3 python3-pip python3-bcrypt python3-venv rrdtool unzip wget zlib1g-dev # Apply patch - - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) + - (for patchfile in $(cat patch/series); do echo "patch patch/$patchfile"; patch -f -Z -t -p 1 -i patch/$patchfile || exit 2; done) # Build Curl - wget -q https://curl.haxx.se/download/curl-7.58.0.tar.gz -O curl.tar.gz - mkdir -p curl/build @@ -659,7 +659,7 @@ Linux client_static debian_i386_strech build: - apt-get install -y autoconf autogen automake bison build-essential cmake cpputest fakeroot libboost-all-dev libfreetype6-dev libgif-dev libgl1-mesa-dev libjpeg62-turbo-dev liblzma-dev libopenal-dev libpng-dev libssh2-1-dev libssl-dev libtool libtool-bin libx11-dev libxml2-dev libxmu-dev libxrandr-dev libxrender-dev libxxf86vm-dev mercurial rrdtool unzip wget zlib1g-dev patch - apt-get install -y liblua5.2-0 liblua5.2-dev # Apply patch - - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) + - (for patchfile in $(cat patch/series); do echo "patch patch/$patchfile"; patch -f -Z -t -p 1 -i patch/$patchfile || exit 2; done) # Build Curl - wget -q https://curl.haxx.se/download/curl-7.58.0.tar.gz -O curl.tar.gz - mkdir -p curl/build @@ -737,7 +737,7 @@ Linux client_static_debug debian_i386_strech build: - apt-get install -y autoconf autogen automake bison build-essential cmake cpputest fakeroot libboost-all-dev libfreetype6-dev libgif-dev libgl1-mesa-dev libjpeg62-turbo-dev liblzma-dev libopenal-dev libpng-dev libssh2-1-dev libssl-dev libtool libtool-bin libx11-dev libxml2-dev libxmu-dev libxrandr-dev libxrender-dev libxxf86vm-dev mercurial rrdtool unzip wget zlib1g-dev patch - apt-get install -y liblua5.2-0 liblua5.2-dev # Apply patch - - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) + - (for patchfile in $(cat patch/series); do echo "patch patch/$patchfile"; patch -f -Z -t -p 1 -i patch/$patchfile || exit 2; done) # Build Curl - wget -q https://curl.haxx.se/download/curl-7.58.0.tar.gz -O curl.tar.gz - mkdir -p curl/build @@ -852,7 +852,7 @@ Linux client fedora_amd64_27 build: zlib-devel patch # Apply patch - - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) + - (for patchfile in $(cat patch/series); do echo "patch patch/$patchfile"; patch -f -Z -t -p 1 -i patch/$patchfile || exit 2; done) # Action - mkdir -p code/build - (cd code/build ; export -p CPPFLAGS="-Wno-deprecated -Wno-deprecated-declarations"; cmake -G "Unix Makefiles" -DWITH_NEL=ON -DWITH_LUA52=ON -DWITH_RYZOM_PATCH=OFF -DWITH_RYZOM_CUSTOM_PATCH_SERVER=OFF -DWITH_NEL_TESTS=OFF -DWITH_RYZOM_CLIENT=ON -DWITH_DRIVER_OPENGL=ON -DWITH_DRIVER_OPENAL=ON -DWITH_NEL_SAMPLES=OFF -DWITH_SOUND=ON -DWITH_STATIC_CURL=OFF ..) @@ -912,7 +912,7 @@ Linux client ubuntu_amd64_17_10 build: zlib1g-dev - apt-get install -y liblua5.2-0 liblua5.2-dev libluabind-dev libluabind0.9.1v5 libogg-dev libvorbis-dev # Apply patch - - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) + - (for patchfile in $(cat patch/series); do echo "patch patch/$patchfile"; patch -f -Z -t -p 1 -i patch/$patchfile || exit 2; done) # Action - mkdir -p code/build - (cd code/build ; export -p CPPFLAGS="-Wno-deprecated -Wno-deprecated-declarations"; cmake -G "Unix Makefiles" -DWITH_NEL=ON -DWITH_LUA52=ON -DWITH_RYZOM_PATCH=OFF -DWITH_RYZOM_CUSTOM_PATCH_SERVER=OFF -DWITH_NEL_TESTS=OFF -DWITH_RYZOM_CLIENT=ON -DWITH_DRIVER_OPENGL=ON -DWITH_DRIVER_OPENAL=ON -DWITH_NEL_SAMPLES=OFF -DWITH_SOUND=ON -DWITH_STATIC_CURL=OFF ..) @@ -996,7 +996,7 @@ Linux client archlinux build: - cd ../.. - yaourt -Syyu --noconfirm --aur boost-build # Apply patch - - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) + - (for patchfile in $(cat patch/series); do echo "patch patch/$patchfile"; patch -f -Z -t -p 1 -i patch/$patchfile || exit 2; done) - patch -f -Z -t -p 1 -i patch/02_archlinux_allocator_static_assert_error.patch # Build - mkdir -p luabind From 967db4ce02a2580515b7e0b6c4601a88aa7c1070 Mon Sep 17 00:00:00 2001 From: AleaJactaEst Date: Sun, 4 Nov 2018 16:18:02 +0100 Subject: [PATCH 137/303] update patch libcrypto --- patch/libcrypto.patch | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/patch/libcrypto.patch b/patch/libcrypto.patch index daacdde3e..acb4d9b2a 100644 --- a/patch/libcrypto.patch +++ b/patch/libcrypto.patch @@ -1,9 +1,9 @@ diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt -index 43054b63e..4e422c0b5 100644 +index 4e5292f2a..40cc432b8 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt -@@ -445,6 +445,20 @@ IF(WITH_NEL) - SET(CURL_LIBRARIES ${CURL_LIBRARIES} ${IDN_LIBRARY}) +@@ -244,6 +244,20 @@ IF(WITH_NEL) + LIST(APPEND CURL_LIBRARIES ${IDN_LIBRARY}) ENDIF() + # Solve issue : "md5.c:(.text+0x12): undefined reference to `MD5_Init' @@ -20,6 +20,6 @@ index 43054b63e..4e422c0b5 100644 + ENDIF() + ENDIF() + - # CURL Macports version depends on libidn, libintl and libiconv too + # CURL Macports version can depend on libidn, libidn2, libintl, libpsl and libiconv too IF(APPLE) FIND_LIBRARY(INTL_LIBRARY intl) From d5dc1ac5fd8d4d0f1b029b69958121f5041a8db6 Mon Sep 17 00:00:00 2001 From: AleaJactaEst Date: Sun, 4 Nov 2018 16:49:51 +0100 Subject: [PATCH 138/303] update patch libicuuc --- patch/libicuuc.patch | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/patch/libicuuc.patch b/patch/libicuuc.patch index 56dc4453d..70651b0bb 100644 --- a/patch/libicuuc.patch +++ b/patch/libicuuc.patch @@ -1,5 +1,5 @@ diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt -index 4e422c0b5..e76be35f1 100644 +index 4e5292f2a..8c706ea94 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -153,6 +153,17 @@ IF(WITH_STATIC) @@ -20,3 +20,30 @@ index 4e422c0b5..e76be35f1 100644 ENDIF() ENDIF() +diff --git a/patch/libicuuc.patch b/patch/libicuuc.patch +index 56dc4453d..e69de29bb 100644 +--- a/patch/libicuuc.patch ++++ b/patch/libicuuc.patch +@@ -1,22 +0,0 @@ +-diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt +-index 4e422c0b5..e76be35f1 100644 +---- a/code/CMakeLists.txt +-+++ b/code/CMakeLists.txt +-@@ -153,6 +153,17 @@ IF(WITH_STATIC) +- IF(LIBLZMA_LIBRARIES) +- SET(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} ${LIBLZMA_LIBRARIES}) +- ENDIF() +-+ # under Linux, recent libxml2 versions are linked without libicuuc & libicudata +-+ IF(WITH_STATIC_EXTERNAL) +-+ find_library (LIBICUUC_LIBRARY NAMES icuuc) +-+ IF(LIBICUUC_LIBRARY) +-+ SET(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} ${LIBICUUC_LIBRARY}) +-+ ENDIF() +-+ find_library (LIBICUDATA_LIBRARY NAMES icudata) +-+ IF(LIBICUDATA_LIBRARY) +-+ SET(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} ${LIBICUDATA_LIBRARY}) +-+ ENDIF() +-+ ENDIF() +- ENDIF() +- ENDIF() +- From 22849c04722c1f69e574bd0dd2ec1cee2a6b95c2 Mon Sep 17 00:00:00 2001 From: AleaJactaEst Date: Sun, 4 Nov 2018 16:57:14 +0100 Subject: [PATCH 139/303] update patch libicuuc --- patch/libicuuc.patch | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/patch/libicuuc.patch b/patch/libicuuc.patch index 70651b0bb..ff52e2ab8 100644 --- a/patch/libicuuc.patch +++ b/patch/libicuuc.patch @@ -19,31 +19,3 @@ index 4e5292f2a..8c706ea94 100644 + ENDIF() ENDIF() ENDIF() - -diff --git a/patch/libicuuc.patch b/patch/libicuuc.patch -index 56dc4453d..e69de29bb 100644 ---- a/patch/libicuuc.patch -+++ b/patch/libicuuc.patch -@@ -1,22 +0,0 @@ --diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt --index 4e422c0b5..e76be35f1 100644 ----- a/code/CMakeLists.txt --+++ b/code/CMakeLists.txt --@@ -153,6 +153,17 @@ IF(WITH_STATIC) -- IF(LIBLZMA_LIBRARIES) -- SET(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} ${LIBLZMA_LIBRARIES}) -- ENDIF() --+ # under Linux, recent libxml2 versions are linked without libicuuc & libicudata --+ IF(WITH_STATIC_EXTERNAL) --+ find_library (LIBICUUC_LIBRARY NAMES icuuc) --+ IF(LIBICUUC_LIBRARY) --+ SET(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} ${LIBICUUC_LIBRARY}) --+ ENDIF() --+ find_library (LIBICUDATA_LIBRARY NAMES icudata) --+ IF(LIBICUDATA_LIBRARY) --+ SET(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} ${LIBICUDATA_LIBRARY}) --+ ENDIF() --+ ENDIF() -- ENDIF() -- ENDIF() -- From 86760f4736692b562fd69c816eb1c34c8ff01de4 Mon Sep 17 00:00:00 2001 From: AleaJactaEst Date: Sun, 4 Nov 2018 20:50:51 +0100 Subject: [PATCH 140/303] update CI to build client with libogg, libvorbis & luabind --- .gitlab-ci.yml | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 19bb68e75..cfb67ad2d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -72,6 +72,49 @@ Linux client build: - ./configure --disable-ldap --disable-ldaps --disable-rtsp --disable-dict --disable-ipv6 --disable-crypto-auth --disable-sspi --disable-tls-srp --without-gnutls --without-librtmp --without-libidn --disable-versioned-symbols --disable-pop3 --without-libssh2 --with-ssl - make install $optionproc - cd .. + # Build luabind + - mkdir -p luabind + - wget -q http://http.debian.net/debian/pool/main/l/luabind/luabind_0.9.1+dfsg.orig.tar.gz -O luabind.tar.gz + - wget -q http://http.debian.net/debian/pool/main/l/luabind/luabind_0.9.1+dfsg-11.debian.tar.xz -O luabind-debian.tar.xz + - tar xvf luabind.tar.gz -C luabind --strip 1 || exit 2 + - tar xvf luabind-debian.tar.xz -C luabind || exit 2 + - cd luabind + - for file in $(cat debian/patches/series); do patch -p1 < debian/patches/$file; done + - export -p DEB_HOST_MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH); bjam -d2 release debug install cflags="-fPIC $(dpkg-buildflags --get CFLAGS)" cxxflags="-fPIC $(dpkg-buildflags --get CXXFLAGS) -Wno-deprecated-declarations" linkflags=" $(dpkg-buildflags --get LDFLAGS)" + - export -p DEB_HOST_MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH); bjam -d2 release debug install link=static cflags="-fPIC $(dpkg-buildflags --get CFLAGS)" cxxflags="-fPIC $(dpkg-buildflags --get CXXFLAGS) -Wno-deprecated-declarations" linkflags=" $(dpkg-buildflags --get LDFLAGS)" + - cd .. + # Build libogg + - mkdir -p libogg/build + - wget -q http://http.debian.net/debian/pool/main/libo/libogg/libogg_1.3.2.orig.tar.gz -O libogg.tar.gz + - wget -q http://http.debian.net/debian/pool/main/libo/libogg/libogg_1.3.2-1.diff.gz -O libogg.diff.gz + - tar xvf libogg.tar.gz -C libogg --strip 1 || exit 2 + - gunzip libogg.diff.gz + - cd libogg + - patch -p1 < ../libogg.diff + - cd build + - ../configure --disable-maintainer-mode --host=$(dpkg-architecture -qDEB_HOST_GNU_TYPE) --build=$(dpkg-architecture -qDEB_BUILD_GNU_TYPE) --libdir=/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH) --enable-static --prefix=/usr CPPFLAGS="-D_FORTIFY_SOURCE=2" CFLAGS="-Wformat=2 -g -fPIC" CXXFLAGS="-Wformat=2 -g -fPIC" LDFLAGS="-Wl,-z,now" + - make + - make install + - cd ../.. + # Build libvorbis + - mkdir -p libvorbis + - wget -q http://security.debian.org/debian-security/pool/updates/main/libv/libvorbis/libvorbis_1.3.5.orig.tar.gz -O libvorbis.tar.gz + - tar xvf libvorbis.tar.gz -C libvorbis --strip 1 || exit 2 + # Get list package + - wget -q http://security.debian.org/debian-security/pool/updates/main/libv/libvorbis -O list_libvorbis + # get last patch for our release + - line=$(egrep '(libvorbis_1.3.5)(.*)(tar[.]xz)' list_libvorbis | tail -n 1) + # get only name of the patch + - tmp=${line#*href} ; tmp2=${tmp%%>*} ; tmp3=${tmp2#*\"} ; namepatch=${tmp3%\"*} + # download this patch + - wget -q http://security.debian.org/debian-security/pool/updates/main/libv/libvorbis/$namepatch -O libvorbis.debian.tar.xz + - tar xvf libvorbis.debian.tar.xz -C libvorbis || exit 2 + - cd libvorbis + - for file in $(cat debian/patches/series); do patch -p1 < debian/patches/$file; done + - ./configure --enable-static --with-pic + - make + - make install + - cd .. ## Compilation de Khanat # Configuration - cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/ -DCMAKE_BUILD_TYPE=Release -DWITH_RYZOM_SERVER=OFF -DWITH_RYZOM_TOOLS=OFF -DWITH_RYZOM_CLIENT=ON -DWITH_NEL_TESTS=OFF -DWITH_NEL_TOOLS=OFF -DWITH_NEL_SAMPLES=OFF -DWITH_STATIC=ON -DWITH_STATIC_DRIVERS=ON -DWITH_STATIC_EXTERNAL=ON -DWITH_UNIX_STRUCTURE=OFF -DWITH_INSTALL_LIBRARIES=OFF -DWITH_LUA52=ON ../../code From 586ec27ed31ff03e133257831e98208b7afe328e Mon Sep 17 00:00:00 2001 From: AleaJactaEst Date: Sun, 4 Nov 2018 22:08:54 +0100 Subject: [PATCH 141/303] adding debug message --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cfb67ad2d..06b9b1677 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -346,6 +346,7 @@ Linux client_static debian_amd64_strech build: - mkdir -p luabind - wget -q http://http.debian.net/debian/pool/main/l/luabind/luabind_0.9.1+dfsg.orig.tar.gz -O luabind.tar.gz - wget -q http://http.debian.net/debian/pool/main/l/luabind/luabind_0.9.1+dfsg-11.debian.tar.xz -O luabind-debian.tar.xz + - ls - tar xvf luabind.tar.gz -C luabind --strip 1 || exit 2 - tar xvf luabind-debian.tar.xz -C luabind || exit 2 - cd luabind From 06ab5b5f16edf05a52f9c84c745391bb1ec54922 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 18 Nov 2018 17:17:56 +0200 Subject: [PATCH 142/303] Fixed: Invalid LineMaxW with scaling --HG-- branch : experimental-ui-scaling --- code/nel/src/gui/view_text.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index 4355eb647..7ac1bf8a4 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -1412,7 +1412,6 @@ namespace NLGUI // *************************************************************************** void CViewText::setLineMaxW (sint nMaxW, bool invalidate) { - nMaxW *= _Scale; if(_LineMaxW!=nMaxW) { _LineMaxW = nMaxW; From 2877ece3c67a43ac9d47135ad55a8685bd39d860 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 18 Nov 2018 21:33:05 +0200 Subject: [PATCH 143/303] Changed: Add right click copy-to-clipboard action to chat --HG-- branch : develop --- code/ryzom/client/src/interface_v3/chat_text_manager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/ryzom/client/src/interface_v3/chat_text_manager.cpp b/code/ryzom/client/src/interface_v3/chat_text_manager.cpp index a9a682bf1..ae76eefcb 100644 --- a/code/ryzom/client/src/interface_v3/chat_text_manager.cpp +++ b/code/ryzom/client/src/interface_v3/chat_text_manager.cpp @@ -402,6 +402,10 @@ CViewBase *CChatTextManager::createMsgTextComplex(const ucstring &msg, NLMISC::C para->setSizeRef("w"); para->setResizeFromChildH(true); + // use right click because left click might be used to activate chat window + para->setRightClickHandler("copy_to_clipboard"); + para->setRightClickHandlerParams(msg.toUtf8()); + if (plaintext) { CViewBase *vt = createMsgTextSimple(msg, col, justified, NULL); From 8e53cd87e5dfa68f5bee8b1363058b8fc1004488 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 19 Nov 2018 11:26:31 +0200 Subject: [PATCH 144/303] Fixed: Zero width/height letters (ie space) should not be included in atlas --HG-- branch : develop --- code/nel/src/3d/texture_font.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/nel/src/3d/texture_font.cpp b/code/nel/src/3d/texture_font.cpp index eac8cb545..5977a8e5a 100644 --- a/code/nel/src/3d/texture_font.cpp +++ b/code/nel/src/3d/texture_font.cpp @@ -516,6 +516,9 @@ CTextureFont::SLetterInfo* CTextureFont::getLetterInfo (SLetterKey& k, bool rend // letter not found (=NULL) or render not requested if (!letter || !render) return letter; + // nothing to render, ie space char + if (letter->CharWidth == 0 || letter->CharHeight == 0) return letter; + if (!letter->glyph || letter->glyph->CacheVersion != _CacheVersion) { // render glyph From 8091bc8fb16658d99575cede2c3ff6ab324f3f2f Mon Sep 17 00:00:00 2001 From: AleaJactaEst Date: Thu, 29 Nov 2018 22:18:09 +0100 Subject: [PATCH 145/303] feature #36 patch_gen multi-thread --- code/ryzom/tools/patch_gen/CMakeLists.txt | 4 +- .../tools/patch_gen/patch_gen_common.cpp | 306 ++++++++++++------ code/ryzom/tools/patch_gen/patch_gen_common.h | 7 + code/ryzom/tools/patch_gen/patch_gen_main.cpp | 38 ++- 4 files changed, 252 insertions(+), 103 deletions(-) create mode 100644 code/ryzom/tools/patch_gen/patch_gen_common.h diff --git a/code/ryzom/tools/patch_gen/CMakeLists.txt b/code/ryzom/tools/patch_gen/CMakeLists.txt index 6cde9810b..d377fb99c 100644 --- a/code/ryzom/tools/patch_gen/CMakeLists.txt +++ b/code/ryzom/tools/patch_gen/CMakeLists.txt @@ -1,7 +1,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/ryzom/client/src/seven_zip) -SET(MAIN_SRC patch_gen_common.cpp patch_gen_main.cpp patch_gen_main.h) -SET(SERVICE_SRC patch_gen_common.cpp patch_gen_service.cpp patch_gen_service.h) +SET(MAIN_SRC patch_gen_common.cpp patch_gen_main.cpp patch_gen_main.h patch_gen_common.h) +SET(SERVICE_SRC patch_gen_common.cpp patch_gen_service.cpp patch_gen_service.h patch_gen_common.h) ADD_EXECUTABLE(patch_gen ${MAIN_SRC}) TARGET_LINK_LIBRARIES(patch_gen ryzom_sevenzip ryzom_gameshare nelmisc nelnet nelligo nelgeorges) diff --git a/code/ryzom/tools/patch_gen/patch_gen_common.cpp b/code/ryzom/tools/patch_gen/patch_gen_common.cpp index 8ba0d4c5e..9724f08db 100644 --- a/code/ryzom/tools/patch_gen/patch_gen_common.cpp +++ b/code/ryzom/tools/patch_gen/patch_gen_common.cpp @@ -20,6 +20,11 @@ #include #include +#include +#include +#include +#include +#include #include "game_share/bnp_patch.h" #include "nel/misc/path.h" @@ -28,12 +33,14 @@ #include "nel/misc/sstring.h" #include "game_share/singleton_registry.h" #include "seven_zip.h" +#include "patch_gen_main.h" using namespace std; using namespace NLMISC; #define PERSISTENT_TOKEN_FAMILY RyzomTokenFamily +unsigned int jobs_simultaneously = 1; //----------------------------------------------------------------------------- // Handy utility functions @@ -47,11 +54,11 @@ void normalisePackageDescriptionFileName(std::string& fileName) fileName+=".xml"; } -void GeneratePatch(const std::string& srcFileName,const std::string& destFileName,const std::string& patchFileName) +void GeneratePatch(const uint32 id, const std::string& srcFileName,const std::string& destFileName,const std::string& patchFileName) { std::string cmd = toString("xdelta delta %s %s %s", srcFileName.c_str(), destFileName.c_str(), patchFileName.c_str()); - nlinfo("Executing system command: %s", cmd.c_str()); + nlinfo("[id:%d] Executing system command: %s", id, cmd.c_str()); #ifdef NL_OS_WINDOWS _spawnlp(_P_WAIT, "xdelta.exe", "xdelta.exe", "delta", srcFileName.c_str(), destFileName.c_str(), patchFileName.c_str(), NULL); @@ -60,15 +67,15 @@ void GeneratePatch(const std::string& srcFileName,const std::string& destFileNam sint error = system (cmd.c_str()); if (error == 2) - nlwarning("'%s' failed with error code %d", cmd.c_str(), error); + nlwarning("[id:%d] '%s' failed with error code %d", id, cmd.c_str(), error); #endif // NL_OS_WINDOWS } -void ApplyPatch(const std::string& srcFileName,const std::string& destFileName,const std::string& patchFileName=std::string()) +void ApplyPatch(const uint32 id, const std::string& srcFileName,const std::string& destFileName,const std::string& patchFileName=std::string()) { std::string cmd = toString("xdelta patch %s %s %s", patchFileName.c_str(), srcFileName.c_str(), destFileName.c_str()); - nlinfo("Executing system command: %s", cmd.c_str()); + nlinfo("[id:%d] Executing system command: %s", id, cmd.c_str()); #ifdef NL_OS_WINDOWS _spawnlp(_P_WAIT, "xdelta.exe", "xdelta.exe", "patch",patchFileName.c_str(), srcFileName.c_str(), destFileName.c_str(), NULL); @@ -77,22 +84,157 @@ void ApplyPatch(const std::string& srcFileName,const std::string& destFileName,c sint error = system (cmd.c_str()); if (error == 2) - nlwarning("'%s' failed with error code %d", cmd.c_str(), error); + nlwarning("[id:%d] '%s' failed with error code %d", id, cmd.c_str(), error); #endif // NL_OS_WINDOWS } -void GenerateLZMA(const std::string &sourceFile, const std::string &outputFile) +void GenerateLZMA(const uint32 id, const std::string &sourceFile, const std::string &outputFile) { { - nlinfo("Compressing %s to %s using LZMA...", sourceFile.c_str(), outputFile.c_str()); + nlinfo("[id:%d] Compressing %s to %s using LZMA...", id, sourceFile.c_str(), outputFile.c_str()); } if (!packLZMA(sourceFile, outputFile)) { - nlwarning("LZMA compress failed"); + nlwarning("[id:%d, source:%s] LZMA compress failed", id, sourceFile.c_str()); } } +//----------------------------------------------------------------------------- +// class CTaskPackageDescription +//----------------------------------------------------------------------------- + +class CTaskPackageDescription +{ + bool deleteRefAfterDelta; + bool usingTemporaryFile; + uint32 id; + CBNPFile * _pbnpPtr; + std::string _BnpDirectory; + std::string _RefDirectory; + std::string _PatchDirectory; + std::string _RootDirectory; + const CBNPCategorySet * _pCategories; + +public: + CTaskPackageDescription(uint32 id, bool deleteRefAfterDelta, bool usingTemporaryFile, CBNPFile * _pbnpPtr, + std::string _BnpDirectory, std::string _RefDirectory, std::string _PatchDirectory, + std::string _RootDirectory, const CBNPCategorySet * _pCategories) + { + this->id = id; + this->deleteRefAfterDelta = deleteRefAfterDelta; + this->usingTemporaryFile = usingTemporaryFile; + this->_pbnpPtr = _pbnpPtr; + this->_BnpDirectory = _BnpDirectory; + this->_RefDirectory = _RefDirectory; + this->_PatchDirectory = _PatchDirectory; + this->_RootDirectory = _RootDirectory; + this->_pCategories = _pCategories; + } + void action() + { + nldebug("[id:%d] thread for %s : start", id, this->_pbnpPtr->getFileName().c_str()); + + std::string bnpFileName = _BnpDirectory + _pbnpPtr->getFileName(); + std::string refNameRoot = _RefDirectory + NLMISC::CFile::getFilenameWithoutExtension(bnpFileName); + std::string patchNameRoot = _PatchDirectory + NLMISC::CFile::getFilenameWithoutExtension(bnpFileName); + + + // get the last version number and the related file name + const CBNPFileVersion& curVersion= _pbnpPtr->getVersion(_pbnpPtr->versionCount()-1); + std::string curVersionFileName= refNameRoot+NLMISC::toString("_%05u.%s",curVersion.getVersionNumber(),NLMISC::CFile::getExtension(bnpFileName).c_str()); + std::string patchFileName= _PatchDirectory + toString("%05u/",curVersion.getVersionNumber())+NLMISC::CFile::getFilenameWithoutExtension(bnpFileName)+toString("_%05u",curVersion.getVersionNumber())+".patch"; + + // get the second last version number and the related file name + std::string prevVersionFileName; + if (_pbnpPtr->versionCount()==1) + { + prevVersionFileName= _RootDirectory + "empty_" + std::to_string(this->id); + CFile::createEmptyFile(prevVersionFileName); + usingTemporaryFile = true; + deleteRefAfterDelta= false; + } + else + { + const CBNPFileVersion& prevVersion= _pbnpPtr->getVersion(_pbnpPtr->versionCount()-2); + prevVersionFileName= refNameRoot+NLMISC::toString("_%05u.%s",prevVersion.getVersionNumber(),NLMISC::CFile::getExtension(bnpFileName).c_str()); + } + std::string refVersionFileName= prevVersionFileName; + + // create the subdirectory for this patch number + string versionSubDir = _PatchDirectory + toString("%05u/", curVersion.getVersionNumber()); + CFile::createDirectory(versionSubDir); + + // generate the lzma packed version of the bnp if needed (lzma file are slow to generate) + string lzmaFile = versionSubDir+CFile::getFilename(bnpFileName)+".lzma"; + if (!CFile::fileExists(lzmaFile)) + { + // build the lzma compression in a temp file (avoid leaving dirty file if the + // process cannot terminate) + GenerateLZMA(id, bnpFileName, lzmaFile+".tmp"); + // rename the tmp file + CFile::moveFile(lzmaFile, lzmaFile+".tmp"); + } + + // store the lzma file size in the descriptor + _pbnpPtr->getVersion(_pbnpPtr->versionCount()-1).set7ZipFileSize(CFile::getFileSize(lzmaFile)); + + // if we need to generate a new patch then do it and create the new ref file + if (!NLMISC::CFile::fileExists(curVersionFileName)) + { + nlinfo("- Creating patch: %s",patchFileName.c_str()); + + // in the case where we compress against a ref file... + if (!_pCategories->isFileIncremental(NLMISC::CFile::getFilename(bnpFileName))) + { + // setup the name of the reference file to patch against + refVersionFileName= _BnpDirectory+NLMISC::CFile::getFilenameWithoutExtension(bnpFileName)+"_.ref"; + + // delete the previous patch - because we only need the latest patch for non-incremental files + std::string lastPatch= _PatchDirectory + NLMISC::CFile::getFilenameWithoutExtension(prevVersionFileName)+".patch"; + if (NLMISC::CFile::fileExists(lastPatch.c_str())) + NLMISC::CFile::deleteFile(lastPatch.c_str()); + } + + // call xdelta to generate the patch + GeneratePatch(id, refVersionFileName, bnpFileName, patchFileName); + nlassert(NLMISC::CFile::fileExists(patchFileName)); + + uint32 nPatchSize = NLMISC::CFile::getFileSize(patchFileName); + _pbnpPtr->getVersion(_pbnpPtr->versionCount()-1).setPatchSize(nPatchSize); + + // apply the incremental patch to the old ref file to create the new ref file + // and ensure that the new ref file matches the BNP + ApplyPatch(id, refVersionFileName, curVersionFileName, patchFileName); + nlassert(NLMISC::CFile::fileExists(curVersionFileName)); + nlassert(NLMISC::CFile::thoroughFileCompare(bnpFileName, curVersionFileName)); + } + + // if we have a ref file still hanging about from the previous patch then delete it + if (NLMISC::CFile::fileExists(prevVersionFileName)) + { + NLMISC::CFile::deleteFile(prevVersionFileName); + } + nldebug("[id:%d] thread for %s : end", id, this->_pbnpPtr->getFileName().c_str()); + } +}; + +void threadWorker(std::mutex & mtx, std::queue & queueTask) +{ + while(true) + { + mtx.lock(); + if ( queueTask.empty()) + { + mtx.unlock(); + break; + } + CTaskPackageDescription task = queueTask.front(); + queueTask.pop(); + mtx.unlock(); + task.action(); + } +}; //----------------------------------------------------------------------------- // class CPackageDescription @@ -125,6 +267,8 @@ public: void updatePatchSizes(CBNPFileSet& packageIndex) const; + //void threadWorker(mutex & mtx, queue & queueTask) const; + // specialisation of IVersionNumberGenerator void grabVersionNumber(); uint32 getPackageVersionNumber(); @@ -334,96 +478,76 @@ void CPackageDescription::generatePatches(CBNPFileSet& packageIndex) const { nlinfo("Generating patches ..."); - for (uint32 i = packageIndex.fileCount(); i--;) + // Generate patch with Leader/Follower pattern + uint32 maxThread=jobs_simultaneously; + uint32 i; + std::mutex mtx; + struct SPrepareTask + { + uint32 fileSize; + uint32 id; + }; + struct SComparePrepareTask + { + bool operator()(const SPrepareTask& left, const SPrepareTask& right) const + { + return left.fileSize < right.fileSize; + } + }; + std::priority_queue, SComparePrepareTask > queuePrepareTask; + + std::queue queueTask; + std::vector workers; + + // Initialize queue task + if ( packageIndex.fileCount() < maxThread ) + maxThread = packageIndex.fileCount(); + + for (i = packageIndex.fileCount(); i--;) + { + struct SPrepareTask stask; + stask.id = i; + stask.fileSize = packageIndex.getFile(i).getVersion(packageIndex.getFile(i).versionCount()-1).getFileSize(); + queuePrepareTask.push(stask); + } + + // Reorder task Big file to small file + //getFileSize + std::priority_queue, SComparePrepareTask > queueSortedPrepareTask; + + + while ( ! queuePrepareTask.empty() ) { bool deleteRefAfterDelta = true; bool usingTemporaryFile = false; - // generate file name root - std::string bnpFileName = _BnpDirectory + packageIndex.getFile(i).getFileName(); - std::string refNameRoot = _RefDirectory + NLMISC::CFile::getFilenameWithoutExtension(bnpFileName); - std::string patchNameRoot = _PatchDirectory + NLMISC::CFile::getFilenameWithoutExtension(bnpFileName); + + struct SPrepareTask task = queuePrepareTask.top(); + queuePrepareTask.pop(); // if the file has no versions then skip on to the next file - if (packageIndex.getFile(i).versionCount()==0) + if (packageIndex.getFile(task.id).versionCount()==0) continue; - // get the last version number and the related file name - const CBNPFileVersion& curVersion= packageIndex.getFile(i).getVersion(packageIndex.getFile(i).versionCount()-1); - std::string curVersionFileName= refNameRoot+NLMISC::toString("_%05u.%s",curVersion.getVersionNumber(),NLMISC::CFile::getExtension(bnpFileName).c_str()); -// std::string patchFileName= patchNameRoot+NLMISC::toString("_%05d.patch",curVersion.getVersionNumber()); - std::string patchFileName= _PatchDirectory + toString("%05u/",curVersion.getVersionNumber())+NLMISC::CFile::getFilenameWithoutExtension(bnpFileName)+toString("_%05u",curVersion.getVersionNumber())+".patch"; - - // get the second last version number and the related file name - std::string prevVersionFileName; - if (packageIndex.getFile(i).versionCount()==1) - { - prevVersionFileName= _RootDirectory + "empty"; - CFile::createEmptyFile(prevVersionFileName); - usingTemporaryFile = true; - deleteRefAfterDelta= false; - } - else - { - const CBNPFileVersion& prevVersion= packageIndex.getFile(i).getVersion(packageIndex.getFile(i).versionCount()-2); - prevVersionFileName= refNameRoot+NLMISC::toString("_%05u.%s",prevVersion.getVersionNumber(),NLMISC::CFile::getExtension(bnpFileName).c_str()); - } - std::string refVersionFileName= prevVersionFileName; - - // create the subdirectory for this patch number - string versionSubDir = _PatchDirectory + toString("%05u/", curVersion.getVersionNumber()); - CFile::createDirectory(versionSubDir); - - // generate the lzma packed version of the bnp if needed (lzma file are slow to generate) - string lzmaFile = versionSubDir+CFile::getFilename(bnpFileName)+".lzma"; - if (!CFile::fileExists(lzmaFile)) - { - // build the lzma compression in a temp file (avoid leaving dirty file if the - // process cannot terminate) - GenerateLZMA(bnpFileName, lzmaFile+".tmp"); - // rename the tmp file - CFile::moveFile(lzmaFile, lzmaFile+".tmp"); - } - - // store the lzma file size in the descriptor - packageIndex.getFile(i).getVersion(packageIndex.getFile(i).versionCount()-1).set7ZipFileSize(CFile::getFileSize(lzmaFile)); - - // if we need to generate a new patch then do it and create the new ref file - if (!NLMISC::CFile::fileExists(curVersionFileName)) - { - nlinfo("- Creating patch: %s",patchFileName.c_str()); - - // in the case where we compress against a ref file... - if (!_Categories.isFileIncremental(NLMISC::CFile::getFilename(bnpFileName))) - { - // setup the name of the reference file to patch against - refVersionFileName= _BnpDirectory+NLMISC::CFile::getFilenameWithoutExtension(bnpFileName)+"_.ref"; - - // delete the previous patch - because we only need the latest patch for non-incremental files - std::string lastPatch= _PatchDirectory + NLMISC::CFile::getFilenameWithoutExtension(prevVersionFileName)+".patch"; - if (NLMISC::CFile::fileExists(lastPatch.c_str())) - NLMISC::CFile::deleteFile(lastPatch.c_str()); - } - - // call xdelta to generate the patch - GeneratePatch(refVersionFileName, bnpFileName, patchFileName); - nlassert(NLMISC::CFile::fileExists(patchFileName)); - - uint32 nPatchSize = NLMISC::CFile::getFileSize(patchFileName); - packageIndex.getFile(i).getVersion(packageIndex.getFile(i).versionCount()-1).setPatchSize(nPatchSize); - - // apply the incremental patch to the old ref file to create the new ref file - // and ensure that the new ref file matches the BNP - ApplyPatch(refVersionFileName, curVersionFileName, patchFileName); - nlassert(NLMISC::CFile::fileExists(curVersionFileName)); - nlassert(NLMISC::CFile::thoroughFileCompare(bnpFileName, curVersionFileName)); - } - - // if we have a ref file still hanging about from the previous patch then delete it - if (NLMISC::CFile::fileExists(prevVersionFileName)) - { - NLMISC::CFile::deleteFile(prevVersionFileName); - } + CTaskPackageDescription data(task.id, + deleteRefAfterDelta, + usingTemporaryFile, + & packageIndex.getFile(task.id), + std::ref(_BnpDirectory), + std::ref(_RefDirectory), + std::ref(_PatchDirectory), + std::ref(_RootDirectory), + & _Categories); + queueTask.push(data); } + + // launch thread workers + for(i=0;i::iterator it = workers.begin(); it != workers.end(); ++it) + it->join(); + NLMISC::DebugLog->displayNL("End thread"); } void CPackageDescription::createDirectories() const diff --git a/code/ryzom/tools/patch_gen/patch_gen_common.h b/code/ryzom/tools/patch_gen/patch_gen_common.h new file mode 100644 index 000000000..5333407e3 --- /dev/null +++ b/code/ryzom/tools/patch_gen/patch_gen_common.h @@ -0,0 +1,7 @@ +#ifndef PATCH_GEN_COMMON_H +#define PATCH_GEN_COMMON_H + +// We need to find other method to send global parameter/argument +extern unsigned int jobs_simultaneously; + +#endif // PATCH_GEN_COMMON_H diff --git a/code/ryzom/tools/patch_gen/patch_gen_main.cpp b/code/ryzom/tools/patch_gen/patch_gen_main.cpp index bc2e6bf66..d45eaff6b 100644 --- a/code/ryzom/tools/patch_gen/patch_gen_main.cpp +++ b/code/ryzom/tools/patch_gen/patch_gen_main.cpp @@ -17,6 +17,8 @@ #include "nel/misc/debug.h" #include "nel/misc/command.h" #include "nel/misc/sstring.h" +#include "nel/misc/cmd_args.h" +#include "patch_gen_common.h" //#include "game_share/handy_commands.h" //----------------------------------------------- @@ -26,27 +28,43 @@ int main(int argc,char** argv) { NLMISC::createDebug(); + // Parse Command Line. + NLMISC::CCmdArgs args; + + args.setDescription("Generate patch"); + args.addArg("j", "jobs", "jobs", "Specifies the number of jobs (commands) to run simultaneously"); + args.addAdditionalArg("CommandLine","command line (For a list of valid commands and their paramaters try help)",false,true); + // if there are no command line args then display a friendly message and exit - if (argc==1) + if (!args.parse(argc, argv)) { - NLMISC::InfoLog->displayNL("SYNTAX: %s ",argv[0]); - NLMISC::InfoLog->displayNL(""); - NLMISC::InfoLog->displayNL("For a list of valid commands and their paramaters try: %s help",argv[0]); - NLMISC::InfoLog->displayNL(""); - return 0; + args.displayHelp(); + return 1; + } + + // Analyze option + try + { + std::string cjobs = args.haveArg("j") ? args.getArg("j").front() : "1"; + jobs_simultaneously = (uint32) std::stoul(cjobs); + } catch (const std::invalid_argument) { + args.displayHelp(); + NLMISC::ErrorLog->displayNL("Bad value for parameter jobs"); + return 2; } // build the command line by concatnating input arguments (separating with spaces) + NLMISC::DebugLog->displayNL("param jobs:%u", jobs_simultaneously); + std::vector listargs = args.getAdditionalArg("CommandLine"); NLMISC::CSString commandline; - for (int i=1;i::iterator it = listargs.begin() ; it != listargs.end(); ++it) { - NLMISC::CSString s= argv[i]; - + NLMISC::CSString s = *it; // check whether the argument needs to be quote encapsulated if (s.contains(' ') && s[0]!='\"') s= "\""+ s+ "\""; - if (i>1) + if ( it != listargs.begin() ) commandline+=' '; commandline+= s; } From ab279d1c76d18d697242803814d89e168be21da8 Mon Sep 17 00:00:00 2001 From: AleaJactaEst Date: Fri, 30 Nov 2018 19:54:27 +0100 Subject: [PATCH 146/303] update image use to build --- .gitlab-ci.yml | 59 +++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7366425c8..fe255079e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -52,9 +52,9 @@ Linux client build: - echo "disableproc:$disableproc, nb core compile:$(nproc --ignore=$disableproc) optionproc:$optionproc" # Installation des dépendances #- echo "deb http://ftp.debian.org/debian/ jessie-backports non-free contrib main" >> /etc/apt/sources.list - - apt-get update - - apt-get -y upgrade - - apt-get install libxml2 -y g++ gcc cmake libcurl4-openssl-dev libgl1-mesa-dev libjpeg-dev libpng-dev libopenal-dev libfreetype6-dev libxxf86vm-dev libxrandr-dev libxrender-dev libvorbis-dev libluabind-dev libboost-dev libmysqlclient-dev libssl-dev liblzma-dev libxml2-dev makeself libgif-dev patch + - DEBIAN_FRONTEND=noninteractive apt-get update + - DEBIAN_FRONTEND=noninteractive apt-get upgrade -y + - DEBIAN_FRONTEND=noninteractive apt-get install libxml2 -y g++ gcc cmake libcurl4-openssl-dev libgl1-mesa-dev libjpeg-dev libpng-dev libopenal-dev libfreetype6-dev libxxf86vm-dev libxrandr-dev libxrender-dev libvorbis-dev libluabind-dev libboost-dev libmysqlclient-dev libssl-dev liblzma-dev libxml2-dev makeself libgif-dev patch # Installation des dépendances des dépendances statiques (à commenter si construction de Khanat en mode dynamique) # libxml2 : python-pyicu (support d'unicode), python-dev (support de... python) - apt-get install -y wget python-pyicu python-dev @@ -100,10 +100,9 @@ Linux server debian_amd64_strech build: image: amd64/debian:9 script: # Prepare environment - - apt-get update - - apt-get dist-upgrade -y + - DEBIAN_FRONTEND=noninteractive apt-get update + - DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y - DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server - - apt-get install -y git libcurl4-openssl-dev libfreetype6-dev @@ -188,8 +187,8 @@ Linux client debian_amd64_strech build: image: amd64/debian:9 script: # Prepare environment - - apt-get update - - apt-get dist-upgrade -y + - DEBIAN_FRONTEND=noninteractive apt-get update + - DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y - apt-get install -y autoconf autogen automake @@ -254,8 +253,8 @@ Linux client_static debian_amd64_strech build: image: amd64/debian:9 script: # Prepare environment - - apt-get update - - apt-get dist-upgrade -y + - DEBIAN_FRONTEND=noninteractive apt-get update + - DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y - apt-get install -y autoconf autogen @@ -363,8 +362,8 @@ Linux client_static_debug debian_amd64_strech build: image: amd64/debian:9 script: # Prepare environment - - apt-get update - - apt-get dist-upgrade -y + - DEBIAN_FRONTEND=noninteractive apt-get update + - DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y - apt-get install -y autoconf autogen @@ -472,8 +471,8 @@ Linux server_static debian_amd64_strech build: image: amd64/debian:9 script: # Prepare environment - - apt-get update - - apt-get dist-upgrade -y + - DEBIAN_FRONTEND=noninteractive apt-get update + - DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y - DEBIAN_FRONTEND=noninteractive apt-get install -y apache2 apache2-utils autoconf autogen automake bison build-essential cmake cpputest default-libmysqlclient-dev fakeroot git libapache2-mod-php libboost-all-dev libfreetype6-dev libgif-dev libgl1-mesa-dev libjpeg62-turbo-dev liblua5.2-0 liblua5.2-dev liblzma-dev libogg-dev libopenal-dev libpng-dev libssh2-1-dev libssl-dev libtool libtool-bin libvorbis-dev libx11-dev libxml2-dev libxmu-dev libxrandr-dev libxrender-dev libxxf86vm-dev mercurial mysql-server php php-gd php-imagick php-mysql python3 python3-pip python3-bcrypt python3-venv rrdtool unzip wget zlib1g-dev # Apply patch - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) @@ -563,8 +562,8 @@ Linux server_static_debug debian_amd64_strech build: image: amd64/debian:9 script: # Prepare environment - - apt-get update - - apt-get dist-upgrade -y + - DEBIAN_FRONTEND=noninteractive apt-get update + - DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y - DEBIAN_FRONTEND=noninteractive apt-get install -y apache2 apache2-utils autoconf autogen automake bison build-essential cmake cpputest default-libmysqlclient-dev fakeroot git libapache2-mod-php libboost-all-dev libfreetype6-dev libgif-dev libgl1-mesa-dev libjpeg62-turbo-dev liblua5.2-0 liblua5.2-dev liblzma-dev libogg-dev libopenal-dev libpng-dev libssh2-1-dev libssl-dev libtool libtool-bin libvorbis-dev libx11-dev libxml2-dev libxmu-dev libxrandr-dev libxrender-dev libxxf86vm-dev mercurial mysql-server php php-gd php-imagick php-mysql python3 python3-pip python3-bcrypt python3-venv rrdtool unzip wget zlib1g-dev # Apply patch - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) @@ -654,8 +653,8 @@ Linux client_static debian_i386_strech build: image: i386/debian:9 script: # Prepare environment - - apt-get update - - apt-get dist-upgrade -y + - DEBIAN_FRONTEND=noninteractive apt-get update + - DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y - apt-get install -y autoconf autogen automake bison build-essential cmake cpputest fakeroot libboost-all-dev libfreetype6-dev libgif-dev libgl1-mesa-dev libjpeg62-turbo-dev liblzma-dev libopenal-dev libpng-dev libssh2-1-dev libssl-dev libtool libtool-bin libx11-dev libxml2-dev libxmu-dev libxrandr-dev libxrender-dev libxxf86vm-dev mercurial rrdtool unzip wget zlib1g-dev patch - apt-get install -y liblua5.2-0 liblua5.2-dev # Apply patch @@ -732,9 +731,9 @@ Linux client_static_debug debian_i386_strech build: image: i386/debian:9 script: # Prepare environment - - apt-get update - - apt-get dist-upgrade -y - - apt-get install -y autoconf autogen automake bison build-essential cmake cpputest fakeroot libboost-all-dev libfreetype6-dev libgif-dev libgl1-mesa-dev libjpeg62-turbo-dev liblzma-dev libopenal-dev libpng-dev libssh2-1-dev libssl-dev libtool libtool-bin libx11-dev libxml2-dev libxmu-dev libxrandr-dev libxrender-dev libxxf86vm-dev mercurial rrdtool unzip wget zlib1g-dev patch + - DEBIAN_FRONTEND=noninteractive apt-get update + - DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y + - DEBIAN_FRONTEND=noninteractive apt-get install -y autoconf autogen automake bison build-essential cmake cpputest fakeroot libboost-all-dev libfreetype6-dev libgif-dev libgl1-mesa-dev libjpeg62-turbo-dev liblzma-dev libopenal-dev libpng-dev libssh2-1-dev libssl-dev libtool libtool-bin libx11-dev libxml2-dev libxmu-dev libxrandr-dev libxrender-dev libxxf86vm-dev mercurial rrdtool unzip wget zlib1g-dev patch - apt-get install -y liblua5.2-0 liblua5.2-dev # Apply patch - (for patchfile in $(cat patch/series); do if ! patch -Z -t -R -s -f --dry-run -p 1 -i patch/$patchfile; then patch -f -Z -t -p 1 -i patch/$patchfile || exit 2 ; fi;done) @@ -876,9 +875,9 @@ Linux client ubuntu_amd64_17_10 build: image: amd64/ubuntu:17.10 script: # Prepare environment - - apt-get update - - apt-get dist-upgrade -y - - apt-get install -y autoconf + - DEBIAN_FRONTEND=noninteractive apt-get update + - DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y + - DEBIAN_FRONTEND=noninteractive apt-get install -y autoconf autogen automake bison @@ -1033,9 +1032,9 @@ Windows client build: script: # Prepare environment - dpkg --add-architecture i386 - - apt-get update - - apt-get dist-upgrade -y - - apt-get install -y + - DEBIAN_FRONTEND=noninteractive apt-get update + - DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y + - DEBIAN_FRONTEND=noninteractive apt-get install -y p7zip-full binfmt-support libc6-i386 @@ -1098,7 +1097,7 @@ Linux client test: - mac-ci-build tags: - Docker - image: ubuntu:14.04 + image: ubuntu:18.04 script: # Test de l'installation initiale - ./khanat-$(echo $CI_BUILD_REF | head -c 7 )-$CI_PIPELINE_ID-Linux-x86_64.run @@ -1128,7 +1127,7 @@ Linux client test: - ryzomcore tags: - Docker - image: ubuntu:14.04 + image: ubuntu:18.04 script: - echo "pas encore de deployment" dependencies: @@ -1148,7 +1147,7 @@ Linux client test: - tags tags: - Docker - image: ubuntu:14.04 + image: ubuntu:18.04 script: - echo "pas encore de tag" dependencies: From fcac3986960a02eb2179f5e7f304676187d1925e Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 6 Dec 2018 15:19:54 +0200 Subject: [PATCH 147/303] Fixed: More fixes for LineMaxW with scaling --HG-- branch : experimental-ui-scaling --- code/nel/src/gui/view_text.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index 7ac1bf8a4..8d36c046d 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -920,9 +920,8 @@ namespace NLGUI // *************************************************************************** sint CViewText::getCurrentMultiLineMaxW() const { - sint maxw = ceilf(_LineMaxW * _Scale); if(_MultiLineMaxWOnly) - return maxw; + return _LineMaxW; else { sint offset = (sint)_XReal - (sint)_Parent->getXReal(); @@ -2021,7 +2020,7 @@ namespace NLGUI _W = (sint)ceilf(_Info.StringWidth / _Scale); // Rare case: clamp W => recompute slowly, cut letters - if(_Info.StringWidth > _LineMaxW) + if(_W > _LineMaxW) { TextContext->erase (_Index); @@ -2038,6 +2037,8 @@ namespace NLGUI dotWidth = si.StringWidth; } + // scale LineMaxW to actual font size + float fLineMaxW = (float)_LineMaxW * _Scale; float rWidthCurrentLine = 0; // for all the text if (_ClampRight) @@ -2048,7 +2049,7 @@ namespace NLGUI ucstring ucStrLetter; ucStrLetter= ucLetter; si = TextContext->getStringInfo (ucStrLetter); - if ((rWidthCurrentLine + si.StringWidth + dotWidth) > _LineMaxW) + if ((rWidthCurrentLine + si.StringWidth + dotWidth) > fLineMaxW) { break; } @@ -2074,7 +2075,7 @@ namespace NLGUI ucstring ucStrLetter; ucStrLetter= ucLetter; si = TextContext->getStringInfo (ucStrLetter); - if ((rWidthCurrentLine + si.StringWidth + dotWidth) > _LineMaxW) + if ((rWidthCurrentLine + si.StringWidth + dotWidth) > fLineMaxW) { break; } From b3205fded6f65bad9b0b93905b8f4af4e0efdd0e Mon Sep 17 00:00:00 2001 From: AleaJactaEst Date: Mon, 10 Dec 2018 23:27:11 +0100 Subject: [PATCH 148/303] include ryzom database.xml (and evaluate database_plr.cpp & database_plr.h) --- code/ryzom/common/data_common/database.xml | 10 ++-- .../entities_game_service/database_plr.cpp | 27 ++++++++--- .../src/entities_game_service/database_plr.h | 48 +++++++++++++------ 3 files changed, 58 insertions(+), 27 deletions(-) diff --git a/code/ryzom/common/data_common/database.xml b/code/ryzom/common/data_common/database.xml index d4fcb68aa..b308427ec 100644 --- a/code/ryzom/common/data_common/database.xml +++ b/code/ryzom/common/data_common/database.xml @@ -90,7 +90,7 @@ type="I32" /> + count="7"> @@ -504,7 +504,7 @@ @@ -1117,7 +1117,7 @@ type="I3" /> + count="7"> @@ -1527,7 +1527,7 @@ + count="7"> diff --git a/code/ryzom/server/src/entities_game_service/database_plr.cpp b/code/ryzom/server/src/entities_game_service/database_plr.cpp index b36f09328..8241106bb 100644 --- a/code/ryzom/server/src/entities_game_service/database_plr.cpp +++ b/code/ryzom/server/src/entities_game_service/database_plr.cpp @@ -1,3 +1,4 @@ + // Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // @@ -15,8 +16,20 @@ // along with this program. If not, see . ///////////////////////////////////////////////////////////////// -// WARNING : this is a generated file, don't change it ! +// +// +// +// +// +// WARNING : this is a generated file, don't change it ! +// +// +// +// +// +// ///////////////////////////////////////////////////////////////// + #include "stdpch.h" #include "database_plr.h" @@ -362,7 +375,7 @@ void CBankAccessor_PLR::TUSER::init(ICDBStructNode *parent) node = parent->getNode( ICDBStructNode::CTextId("IS_INVISIBLE"), false ); nlassert(node != NULL); _IS_INVISIBLE = node; - + node = parent->getNode( ICDBStructNode::CTextId("COUNTER"), false ); nlassert(node != NULL); _COUNTER = node; @@ -377,7 +390,7 @@ void CBankAccessor_PLR::TUSER::init(ICDBStructNode *parent) _SKILL_POINTS_[i].init(node, i); } - for (uint i=0; i<6; ++i) + for (uint i=0; i<7; ++i) { node = parent->getNode( ICDBStructNode::CTextId(NLMISC::toString("FACTION_POINTS_%u", i)), false ); nlassert(node != NULL); @@ -3130,7 +3143,7 @@ void CBankAccessor_PLR::TPACK_ANIMAL::init(ICDBStructNode *parent) // branch init - for (uint i=0; i<4; ++i) + for (uint i=0; i<7; ++i) { node = parent->getNode( ICDBStructNode::CTextId(NLMISC::toString("BEAST%u", i)), false ); nlassert(node != NULL); @@ -3180,10 +3193,10 @@ void CBankAccessor_PLR::TPACK_ANIMAL::TBEAST::init(ICDBStructNode *parent, uint nlassert(node != NULL); _DESPAWN = node; - // WARNING: let the value to true, else it'll corrupt backups - node = parent->getNode( ICDBStructNode::CTextId("NAME"), true ); + node = parent->getNode( ICDBStructNode::CTextId("NAME"), false ); nlassert(node != NULL); _NAME = node; + // branch init @@ -3363,7 +3376,7 @@ void CBankAccessor_PLR::TFAME::init(ICDBStructNode *parent) // branch init - for (uint i=0; i<6; ++i) + for (uint i=0; i<7; ++i) { node = parent->getNode( ICDBStructNode::CTextId(NLMISC::toString("PLAYER%u", i)), false ); nlassert(node != NULL); diff --git a/code/ryzom/server/src/entities_game_service/database_plr.h b/code/ryzom/server/src/entities_game_service/database_plr.h index 23da9b616..887ef483e 100644 --- a/code/ryzom/server/src/entities_game_service/database_plr.h +++ b/code/ryzom/server/src/entities_game_service/database_plr.h @@ -1,3 +1,7 @@ + + +#ifndef INCLUDED_database_PLR_H +#define INCLUDED_database_PLR_H // Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // @@ -14,11 +18,19 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . - -#ifndef INCLUDED_DATABASE_PLR_H -#define INCLUDED_DATABASE_PLR_H ///////////////////////////////////////////////////////////////// -// WARNING : this is a generated file, don't change it ! +// +// +// +// +// +// WARNING : this is a generated file, don't change it ! +// +// +// +// +// +// ///////////////////////////////////////////////////////////////// #include "nel/misc/string_common.h" @@ -493,7 +505,7 @@ inline void _getProp(const CCDBSynchronised &db, ICDBStructNode *node, NLMISC::C ICDBStructNode *_IS_INVISIBLE; ICDBStructNode *_COUNTER; TSKILL_POINTS_ _SKILL_POINTS_[4]; - TFACTION_POINTS_ _FACTION_POINTS_[6]; + TFACTION_POINTS_ _FACTION_POINTS_[7]; TRRPS_LEVELS _RRPS_LEVELS[6]; TNPC_CONTROL _NPC_CONTROL; @@ -956,6 +968,8 @@ inline void _getProp(const CCDBSynchronised &db, ICDBStructNode *node, NLMISC::C void setIS_INVISIBLE(CCDBSynchronised &dbGroup, bool value, bool forceSending = false) { + + _setProp(dbGroup, _IS_INVISIBLE, value, forceSending); } @@ -971,7 +985,7 @@ inline void _getProp(const CCDBSynchronised &db, ICDBStructNode *node, NLMISC::C { return _IS_INVISIBLE; } - + void setCOUNTER(CCDBSynchronised &dbGroup, uint8 value, bool forceSending = false) { @@ -1001,7 +1015,7 @@ inline void _getProp(const CCDBSynchronised &db, ICDBStructNode *node, NLMISC::C } TFACTION_POINTS_ &getFACTION_POINTS_(uint32 index) { - nlassert(index < 6); + nlassert(index < 7); return _FACTION_POINTS_[index]; } TRRPS_LEVELS &getRRPS_LEVELS(uint32 index) @@ -1319,7 +1333,7 @@ inline void _getProp(const CCDBSynchronised &db, ICDBStructNode *node, NLMISC::C } }; - + class TTARGET { public: @@ -9081,6 +9095,7 @@ inline void _getProp(const CCDBSynchronised &db, ICDBStructNode *node, NLMISC::C ICDBStructNode *_HUNGER; ICDBStructNode *_DESPAWN; ICDBStructNode *_NAME; + public: void init(ICDBStructNode *parent, uint index); @@ -9269,9 +9284,11 @@ inline void _getProp(const CCDBSynchronised &db, ICDBStructNode *node, NLMISC::C { return _DESPAWN; } - + void setNAME(CCDBSynchronised &dbGroup, uint32 value, bool forceSending = false) { + + _setProp(dbGroup, _NAME, value, forceSending); } @@ -9282,18 +9299,19 @@ inline void _getProp(const CCDBSynchronised &db, ICDBStructNode *node, NLMISC::C return value; } - + ICDBStructNode *getNAMECDBNode() { return _NAME; } + }; private: ICDBStructNode *_BranchNode; - TBEAST _BEAST[4]; + TBEAST _BEAST[7]; public: @@ -9307,7 +9325,7 @@ inline void _getProp(const CCDBSynchronised &db, ICDBStructNode *node, NLMISC::C TBEAST &getBEAST(uint32 index) { - nlassert(index < 4); + nlassert(index < 7); return _BEAST[index]; } @@ -9972,7 +9990,7 @@ inline void _getProp(const CCDBSynchronised &db, ICDBStructNode *node, NLMISC::C ICDBStructNode *_CIV_ALLEGIANCE; ICDBStructNode *_THRESHOLD_TRADE; ICDBStructNode *_THRESHOLD_KOS; - TPLAYER _PLAYER[6]; + TPLAYER _PLAYER[7]; TTRIBE _TRIBE[53]; @@ -10073,7 +10091,7 @@ inline void _getProp(const CCDBSynchronised &db, ICDBStructNode *node, NLMISC::C } TPLAYER &getPLAYER(uint32 index) { - nlassert(index < 6); + nlassert(index < 7); return _PLAYER[index]; } TTRIBE &getTRIBE(uint32 index) @@ -10708,4 +10726,4 @@ inline void _getProp(const CCDBSynchronised &db, ICDBStructNode *node, NLMISC::C }; -#endif // INCLUDED_DATABASE_PLR_H +#endif // INCLUDED_database_PLR_H From 2bbdbd82d531ca1c25f8b28234564482b38cd56f Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 20 Dec 2018 22:21:43 +0200 Subject: [PATCH 149/303] Changed: Set image and form input element ids so then can be accessed with lua --HG-- branch : develop --- code/nel/include/nel/gui/group_html.h | 2 +- code/nel/src/gui/group_html.cpp | 35 ++++++++++++++++++++------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index 9c48149bf..62d8fb1a0 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -366,7 +366,7 @@ namespace NLGUI void addString(const ucstring &str); // Add an image in the current paragraph - void addImage(const char *image, bool reloadImg=false, const CStyleParams &style = CStyleParams()); + void addImage(const std::string &id, const char *image, bool reloadImg=false, const CStyleParams &style = CStyleParams()); // Add a text area in the current paragraph CInterfaceGroup *addTextArea (const std::string &templateName, const char *name, uint rows, uint cols, bool multiLine, const ucstring &content, uint maxlength); diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index efea31898..ce9a8489d 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -1846,7 +1846,11 @@ namespace NLGUI { CStyleParams style; float tmpf; - + + std::string id; + if (present[MY_HTML_IMG_ID] && value[MY_HTML_IMG_ID]) + id = value[MY_HTML_IMG_ID]; + if (present[MY_HTML_IMG_WIDTH] && value[MY_HTML_IMG_WIDTH]) getPercentage(style.Width, tmpf, value[MY_HTML_IMG_WIDTH]); if (present[MY_HTML_IMG_HEIGHT] && value[MY_HTML_IMG_HEIGHT]) @@ -1880,13 +1884,13 @@ namespace NLGUI if (getA() && getParent () && getParent ()->getParent()) { string params = "name=" + getId() + "|url=" + getLink (); - addButton(CCtrlButton::PushButton, value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC], + addButton(CCtrlButton::PushButton, id, value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC], overSrc, "browse", params.c_str(), tooltip, style); } else if (tooltip || !overSrc.empty()) { - addButton(CCtrlButton::PushButton, value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC], + addButton(CCtrlButton::PushButton, id, value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC], overSrc, "", "", tooltip, style); } else @@ -1908,7 +1912,7 @@ namespace NLGUI reloadImg = true; } - addImage (value[MY_HTML_IMG_SRC], reloadImg, style); + addImage(id, value[MY_HTML_IMG_SRC], reloadImg, style); } } } @@ -1920,6 +1924,10 @@ namespace NLGUI // read general property string templateName; string minWidth; + string id; + + if (present[MY_HTML_INPUT_ID] && value[MY_HTML_INPUT_ID]) + id = value[MY_HTML_INPUT_ID]; // Widget template name if (present[MY_HTML_INPUT_Z_BTN_TMPL] && value[MY_HTML_INPUT_Z_BTN_TMPL]) @@ -2114,6 +2122,10 @@ namespace NLGUI { if (btnType == CCtrlButton::RadioButton) { + // override with 'id' because radio buttons share same name + if (!id.empty()) + checkbox->setId(id); + // group together buttons with same name CForm &form = _Forms.back(); bool notfound = true; @@ -4528,7 +4540,7 @@ namespace NLGUI // *************************************************************************** - void CGroupHTML::addImage(const char *img, bool reloadImg, const CStyleParams &style) + void CGroupHTML::addImage(const std::string &id, const char *img, bool reloadImg, const CStyleParams &style) { // In a paragraph ? if (!_Paragraph) @@ -4544,6 +4556,7 @@ namespace NLGUI // Not added ? CViewBitmap *newImage = new CViewBitmap (TCtorParam()); + newImage->setId(id); // // 1/ try to load the image with the old system (local files in bnp) @@ -4746,7 +4759,7 @@ namespace NLGUI // *************************************************************************** - CCtrlButton *CGroupHTML::addButton(CCtrlButton::EType type, const std::string &/* name */, const std::string &normalBitmap, const std::string &pushedBitmap, + CCtrlButton *CGroupHTML::addButton(CCtrlButton::EType type, const std::string &name, const std::string &normalBitmap, const std::string &pushedBitmap, const std::string &overBitmap, const char *actionHandler, const char *actionHandlerParams, const char *tooltip, const CStyleParams &style) { @@ -4759,6 +4772,10 @@ namespace NLGUI // Add the ctrl button CCtrlButton *ctrlButton = new CCtrlButton(TCtorParam()); + if (!name.empty()) + { + ctrlButton->setId(name); + } // Load only tga files.. (conversion in dds filename is done in the lookup procedure) string normal = normalBitmap.empty()?"":CFile::getPath(normalBitmap) + CFile::getFilenameWithoutExtension(normalBitmap) + ".tga"; @@ -4855,7 +4872,7 @@ namespace NLGUI getParagraph()->addChild (ctrlButton); paragraphChange (); - + setImageSize(ctrlButton, style); return ctrlButton; @@ -6004,12 +6021,12 @@ namespace NLGUI if (!url.empty()) { string params = "name=" + getId() + "|url=" + getLink (); - addButton(CCtrlButton::PushButton, ls.toString(1), ls.toString(1), ls.toString(1), + addButton(CCtrlButton::PushButton, "", ls.toString(1), ls.toString(1), "", "browse", params.c_str(), "", style); } else { - addImage(ls.toString(1), false, style); + addImage("", ls.toString(1), false, style); } From e1be4260d5c8f93e96507128cf8422e5dacce149 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Wed, 26 Dec 2018 18:16:21 +0200 Subject: [PATCH 150/303] Fixed: Audio mixer isEventMusicEnded status was always true. --HG-- branch : develop --- code/nel/src/sound/audio_mixer_user.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/src/sound/audio_mixer_user.cpp b/code/nel/src/sound/audio_mixer_user.cpp index 854a2c1dc..7ea0e5d6e 100644 --- a/code/nel/src/sound/audio_mixer_user.cpp +++ b/code/nel/src/sound/audio_mixer_user.cpp @@ -2759,7 +2759,7 @@ void CAudioMixerUser::setEventMusicVolume(float gain) bool CAudioMixerUser::isEventMusicEnded() { if (_MusicChannelFaders[EventMusicChannel].isInitOk()) - _MusicChannelFaders[EventMusicChannel].isEnded(); + return _MusicChannelFaders[EventMusicChannel].isEnded(); return true; } From 32109c7197f477b625c6e74bb0434ac56a75e215 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Wed, 26 Dec 2018 18:16:21 +0200 Subject: [PATCH 151/303] Changed: Wrong isEnded state for streaming file when still in waiting state. --HG-- branch : develop --- code/nel/src/sound/stream_file_source.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/src/sound/stream_file_source.cpp b/code/nel/src/sound/stream_file_source.cpp index 9a03ba2d8..4d490cfac 100644 --- a/code/nel/src/sound/stream_file_source.cpp +++ b/code/nel/src/sound/stream_file_source.cpp @@ -372,7 +372,7 @@ void CStreamFileSource::run() m_AudioDecoder = NULL; // _Playing cannot be used to detect play state because its required in cleanup // Using m_AudioDecoder in isEnded() may result race condition (decoder is only created after thread is started) - m_DecodingEnded = true; + m_DecodingEnded = !m_WaitingForPlay; } // drop buffers m_FreeBuffers = 3; From 798494ffbfa9c1e41bf149f4e49426e9c9810bf3 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Wed, 26 Dec 2018 18:21:35 +0200 Subject: [PATCH 152/303] Changed: Repeat/shuffle buttons to music player --HG-- branch : develop --- .../data/gamedev/interfaces_v3/compass.xml | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/compass.xml b/code/ryzom/client/data/gamedev/interfaces_v3/compass.xml index a88f49f44..969ce332c 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/compass.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/compass.xml @@ -11,6 +11,12 @@ + + @@ -33,11 +39,17 @@ global_color_normal="true" global_color_pushed="true" global_color_over="true" ondblclick_l="music_player" params_dblclick_l="song=#index" /> + - + + + + + + + + + + + + From fa16ca8dd9358e90f823c40a39dd7d77b569b826 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Wed, 26 Dec 2018 18:21:42 +0200 Subject: [PATCH 153/303] Changed: Merge music player play/pause button into one, add stop button --HG-- branch : develop --- .../data/gamedev/interfaces_v3/compass.xml | 42 ++++++++++++++----- .../client/src/interface_v3/music_player.cpp | 11 +++++ 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/compass.xml b/code/ryzom/client/data/gamedev/interfaces_v3/compass.xml index 969ce332c..fbc8495d8 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/compass.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/compass.xml @@ -17,6 +17,9 @@ + @@ -37,11 +40,11 @@ + ondblclick_l="music_player" params_dblclick_l="song=#index" /> - + @@ -50,6 +53,17 @@ + + + + + + + + + + + + + params_l="stop" + tooltip="uiMP3Stop" /> + + = 0 && index < (sint)_Songs.size()) @@ -208,6 +209,8 @@ void CMusicPlayer::play (sint index) _CurrentSong = _Songs[_CurrentSongIndex]; updatePlaylist(prevSongIndex); + + NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:MP3_PLAYING")->setValueBool(true); } } @@ -217,6 +220,7 @@ void CMusicPlayer::pause () { if(!SoundMngr) return; + // pause the music only if we are really playing (else risk to pause a background music!) if(_State==Playing) { @@ -225,6 +229,8 @@ void CMusicPlayer::pause () if (_PlayStart > 0) _PauseTime = CTime::getLocalTime() - _PlayStart; + + NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:MP3_PLAYING")->setValueBool(false); } } @@ -234,11 +240,14 @@ void CMusicPlayer::stop () { if(!SoundMngr) return; + // stop the music only if we are really playing (else risk to stop a background music!) SoundMngr->stopMusic(0); _State = Stopped; _PlayStart = 0; _PauseTime = 0; + + NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:MP3_PLAYING")->setValueBool(false); } // *************************************************************************** @@ -446,6 +455,8 @@ public: MusicPlayer.previous(); else if (Params == "play") MusicPlayer.play(); + else if (Params == "stop") + MusicPlayer.stop(); else if (Params == "pause") MusicPlayer.pause(); else if (Params == "next") From 2607db5b51174f3c5ffab1c90ef7f2b009c9281b Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 27 Dec 2018 09:02:07 +0200 Subject: [PATCH 154/303] Added: CGroupHTML::clearUndoRedo() lua function --HG-- branch : develop --- code/nel/include/nel/gui/group_html.h | 2 ++ code/nel/src/gui/group_html.cpp | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index 62d8fb1a0..dfd80dba9 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -270,6 +270,7 @@ namespace NLGUI void setURL(const std::string &url); + int luaClearUndoRedo(CLuaState &ls); int luaBrowse(CLuaState &ls); int luaRefresh(CLuaState &ls); int luaRemoveContent(CLuaState &ls); @@ -285,6 +286,7 @@ namespace NLGUI REFLECT_EXPORT_START(CGroupHTML, CGroupScrollText) REFLECT_LUA_METHOD("browse", luaBrowse) REFLECT_LUA_METHOD("refresh", luaRefresh) + REFLECT_LUA_METHOD("clearUndoRedo", luaClearUndoRedo) REFLECT_LUA_METHOD("removeContent", luaRemoveContent) REFLECT_LUA_METHOD("insertText", luaInsertText) REFLECT_LUA_METHOD("addString", luaAddString) diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index ce9a8489d..032ffb666 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -5912,6 +5912,15 @@ namespace NLGUI return true; } + int CGroupHTML::luaClearUndoRedo(CLuaState &ls) + { + const char *funcName = "clearUndoRedo"; + CLuaIHM::checkArgCount(ls, funcName, 0); + + clearUndoRedo(); + return 0; + } + // *************************************************************************** int CGroupHTML::luaBrowse(CLuaState &ls) { From 06c0f6800c0c1b933b6b274da02227d9f0b7d226 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 27 Dec 2018 09:03:02 +0200 Subject: [PATCH 155/303] Added: CGroupHTML::clearRefresh() lua function --HG-- branch : develop --- code/nel/include/nel/gui/group_html.h | 4 ++++ code/nel/src/gui/group_html.cpp | 19 ++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index dfd80dba9..7820cbd6a 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -262,6 +262,8 @@ namespace NLGUI void browseUndo (); // Redo browse: Browse the precedent url undoed. no op if none void browseRedo (); + // disable refresh button + void clearRefresh(); // clear undo/redo void clearUndoRedo(); @@ -270,6 +272,7 @@ namespace NLGUI void setURL(const std::string &url); + int luaClearRefresh(CLuaState &ls); int luaClearUndoRedo(CLuaState &ls); int luaBrowse(CLuaState &ls); int luaRefresh(CLuaState &ls); @@ -287,6 +290,7 @@ namespace NLGUI REFLECT_LUA_METHOD("browse", luaBrowse) REFLECT_LUA_METHOD("refresh", luaRefresh) REFLECT_LUA_METHOD("clearUndoRedo", luaClearUndoRedo) + REFLECT_LUA_METHOD("clearRefresh", luaClearRefresh) REFLECT_LUA_METHOD("removeContent", luaRemoveContent) REFLECT_LUA_METHOD("insertText", luaInsertText) REFLECT_LUA_METHOD("addString", luaAddString) diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 032ffb666..6c1444f5c 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -5787,6 +5787,13 @@ namespace NLGUI return false; } + // *************************************************************************** + void CGroupHTML::clearRefresh() + { + _URL.clear(); + updateRefreshButton(); + } + // *************************************************************************** void CGroupHTML::clearUndoRedo() { @@ -5873,7 +5880,7 @@ namespace NLGUI { CCtrlBaseButton *butRefresh = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(_BrowseRefreshButton)); - bool enabled = !_Browsing && !_Connecting; + bool enabled = !_Browsing && !_Connecting && !_URL.empty(); if(butRefresh) butRefresh->setFrozen(!enabled); } @@ -5912,6 +5919,16 @@ namespace NLGUI return true; } + int CGroupHTML::luaClearRefresh(CLuaState &ls) + { + const char *funcName = "clearRefresh"; + CLuaIHM::checkArgCount(ls, funcName, 0); + + clearRefresh(); + + return 0; + } + int CGroupHTML::luaClearUndoRedo(CLuaState &ls) { const char *funcName = "clearUndoRedo"; From d8638fa42bce3a10e53f529739b89009d327c082 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 27 Dec 2018 09:03:29 +0200 Subject: [PATCH 156/303] Changed: For ingame help html files, use english files as fallback. --HG-- branch : develop --- .../src/interface_v3/group_quick_help.cpp | 54 +++++++++++++++---- .../src/interface_v3/group_quick_help.h | 5 ++ 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/group_quick_help.cpp b/code/ryzom/client/src/interface_v3/group_quick_help.cpp index b3c2c1ecc..144dc9b9a 100644 --- a/code/ryzom/client/src/interface_v3/group_quick_help.cpp +++ b/code/ryzom/client/src/interface_v3/group_quick_help.cpp @@ -297,6 +297,49 @@ void CGroupQuickHelp::beginElement (uint element_number, const std::vector } } +// *************************************************************************** +std::string CGroupQuickHelp::getLanguageUrl(const std::string &href, std::string lang) const +{ + std::string uri = href; + + if (uri.size() < 5 || uri.substr(0, 5) == "http://" || uri.substr(0, 6) == "https://") + { + return uri; + } + + // modify uri such that '_??.html' ending contains current user language + if (uri.substr(uri.size()-5) == ".html") + { + if (uri.rfind("_") == uri.size() - 8) + { + uri = uri.substr(0, uri.size() - 8); + } + else + { + uri = uri.substr(0, uri.size() - 5); + } + uri += "_" + lang + ".html"; + + // files inside bnp (file:/gamedev.bnp@help_en.html) will always match with CPath::lookup() + std::string fname; + size_t pos = uri.find("@"); + if (pos != std::string::npos) + { + fname = uri.substr(pos+1); + } + else + { + fname = uri; + } + if (CPath::lookup(fname, false) == "" && lang != "en") + { + uri = getLanguageUrl(href, "en"); + } + } + + return uri; +} + // *************************************************************************** void CGroupQuickHelp::browse (const char *url) @@ -307,12 +350,7 @@ void CGroupQuickHelp::browse (const char *url) _IsQuickHelp = false; - string completeURL = url; - if (completeURL.substr(completeURL.size()-5, 5) == ".html") - { - completeURL = completeURL.substr(0, completeURL.size()-5); // Substract the ".html" - completeURL += "_" + ClientCfg.getHtmlLanguageCode() + ".html"; - } + string completeURL = getLanguageUrl(url, ClientCfg.getHtmlLanguageCode()); CGroupHTML::browse (completeURL.c_str()); } @@ -321,9 +359,7 @@ void CGroupQuickHelp::browse (const char *url) std::string CGroupQuickHelp::home() { - string completeURL = Home; - completeURL = completeURL.substr(0, completeURL.size()-5); // Substract the ".html" - completeURL += "_" + ClientCfg.getHtmlLanguageCode() + ".html"; + string completeURL = getLanguageUrl(Home, ClientCfg.getHtmlLanguageCode()); return completeURL; } diff --git a/code/ryzom/client/src/interface_v3/group_quick_help.h b/code/ryzom/client/src/interface_v3/group_quick_help.h index 76f863bf9..3dc1c8afa 100644 --- a/code/ryzom/client/src/interface_v3/group_quick_help.h +++ b/code/ryzom/client/src/interface_v3/group_quick_help.h @@ -53,6 +53,11 @@ private: virtual void browse (const char *url); virtual std::string home(); + // Modify uri with '.html' or '_??.html' ending to have current user language, + // If the uri is not found locally, then try "en" as fallback language + // ie. 'help_ru.html' does not exists, return 'help_en.html' + std::string getLanguageUrl(const std::string &href, std::string lang) const; + // Init parsing value void initParameters(); From 0099eb3ba4e8ec4420567eec04dc13fa4680baaf Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 27 Dec 2018 11:32:52 +0200 Subject: [PATCH 157/303] Changed: Do not restrict html font-family to inherit/monospace only. --HG-- branch : develop --- code/nel/src/gui/group_html.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 6c1444f5c..92431a3aa 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -6301,10 +6301,7 @@ namespace NLGUI if (it->second == "inherit") style.FontFamily = current.FontFamily; else - if (it->second == "monospace") - style.FontFamily = "monospace"; - else - style.FontFamily.clear(); + style.FontFamily = it->second; } else if (it->first == "font-weight") From c7d65c70637d667073e106bcdb6734d3a4b1c271 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 3 Jan 2019 20:05:00 +0200 Subject: [PATCH 158/303] Changed: Improve inventory search UI --HG-- branch : develop --- .../data/gamedev/interfaces_v3/widgets.xml | 137 ++++++++++++------ .../src/interface_v3/inventory_manager.cpp | 85 +++++++++-- 2 files changed, 167 insertions(+), 55 deletions(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml b/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml index 62c202815..10c36d6a4 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml @@ -2625,6 +2625,7 @@ @@ -6337,6 +6352,7 @@ x="0" y="0" posref="BL BL" + posparent="" dblink="" texture="" tooltip="" @@ -6345,6 +6361,7 @@ id="but_#id" button_type="toggle_button" posref="#posref" + posparent="but_#posparent" x="#x" y="#y" tx_normal="w_button_filter_off.tga" @@ -6371,6 +6388,7 @@ x="0" y="0" posref="BL BL" + posparent="" dblink="" texture="" tooltip="" @@ -6379,6 +6397,7 @@ id="but_#id" button_type="toggle_button" posref="#posref" + posparent="but_#posparent" x="#x" y="#y" tx_normal="w_button_filter_off.tga" @@ -6553,83 +6572,109 @@ texture="W_line_hor.tga" /> + + + + + + + - - - + onchange="inv_set_search" + on_focus_lost="inv_search_unfocus" + on_focus_lost_params="but_inv_search" /> diff --git a/code/ryzom/client/src/interface_v3/inventory_manager.cpp b/code/ryzom/client/src/interface_v3/inventory_manager.cpp index ea233b530..0d23e19ec 100644 --- a/code/ryzom/client/src/interface_v3/inventory_manager.cpp +++ b/code/ryzom/client/src/interface_v3/inventory_manager.cpp @@ -2528,25 +2528,92 @@ class CHandlerInvDrag : public IActionHandler }; REGISTER_ACTION_HANDLER( CHandlerInvDrag, "inv_drag" ); -// ********************************************************************************************************** -class CHandlerInvSetSearch : public IActionHandler +// *************************************************************************** +// show/hide edit box, set keyboard focus if 'show' +class CHandlerInvSearchButton : public IActionHandler { - void execute (CCtrlBase *pCaller, const std::string &sParams) + virtual void execute (CCtrlBase *pCaller, const string &sParams) + { + if (sParams.empty()) + { + nlwarning("inv_search_button: missing edit box shortid"); + return; + } + + CCtrlBaseButton* btn = dynamic_cast(pCaller); + if (!btn) + { + nlwarning("inv_search_button pCaller == NULL, caller must be CCtrlBaseButton with 'toggle_button' type"); + return; + } + + ucstring filter; + std::string id = btn->getParent()->getId() + ":" + sParams + ":eb"; + CGroupEditBox *eb = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(id)); + if (!eb) + { + nlwarning("inv_search_button: editbox (%s) not found\n", id.c_str()); + return; + } + + eb->getParent()->setActive(btn->getPushed()); + if (eb->getParent()->getActive()) + { + CWidgetManager::getInstance()->setCaptureKeyboard(eb); + eb->setSelectionAll(); + filter = eb->getInputString(); + } + + CDBGroupListSheetBag *pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(btn->getParent()->getId() + ":bag_list")); + if (pList != NULL) pList->setSearchFilter(filter); + + CDBGroupIconListBag *pIcons = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(btn->getParent()->getId() + ":bag_icons")); + if (pIcons != NULL) pIcons->setSearchFilter(filter); + } +}; +REGISTER_ACTION_HANDLER( CHandlerInvSearchButton, "inv_search_button" ); + +// *************************************************************************** +// if :eb is empty then hide edit box, unpush search button +class CHandlerInvSearchUnfocus : public IActionHandler +{ + virtual void execute (CCtrlBase *pCaller, const string &sParams) { if (!pCaller) return; CGroupEditBox *eb = dynamic_cast(pCaller); - if (!eb) return; - - CInterfaceManager *pIM = CInterfaceManager::getInstance(); + if (!eb || !eb->getInputString().empty()) return; // ui:interface:inventory:content:bag:iil:inv_query_eb:eb - string invId = pCaller->getParent()->getParent()->getId(); + std::string id = pCaller->getParent()->getParent()->getId() + ":" + sParams; + CCtrlBaseButton *btn = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(id)); + if (btn) btn->setPushed(false); - CDBGroupListSheetBag *pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(invId + ":bag_list")); + // hide :inv_query_eb + pCaller->getParent()->setActive(false); + + // clear filter + CAHManager::getInstance()->runActionHandler("inv_set_search", pCaller, ""); + } +}; +REGISTER_ACTION_HANDLER( CHandlerInvSearchUnfocus, "inv_search_unfocus" ); + +// ********************************************************************************************************** +// set inventory search string +class CHandlerInvSetSearch : public IActionHandler +{ + void execute (CCtrlBase *pCaller, const std::string &sParams) + { + CGroupEditBox *eb = dynamic_cast(pCaller); + if (!eb) return; + + // ui:interface:inventory:content:bag:iil:inv_query_eb:eb + std::string id = pCaller->getParent()->getParent()->getId(); + + CDBGroupListSheetBag *pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(id + ":bag_list")); if (pList != NULL) pList->setSearchFilter(eb->getInputString()); - CDBGroupIconListBag *pIcons = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(invId + ":bag_icons")); + CDBGroupIconListBag *pIcons = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(id + ":bag_icons")); if (pIcons != NULL) pIcons->setSearchFilter(eb->getInputString()); } }; From ef1977330b46d946c1a036dd23e901384cb7ec33 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 5 Jan 2019 21:10:14 +0200 Subject: [PATCH 159/303] Fixed: Glyph size step not taken into account. --HG-- branch : develop --- code/nel/src/3d/texture_font.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/src/3d/texture_font.cpp b/code/nel/src/3d/texture_font.cpp index 5977a8e5a..b40083516 100644 --- a/code/nel/src/3d/texture_font.cpp +++ b/code/nel/src/3d/texture_font.cpp @@ -446,7 +446,7 @@ CTextureFont::SGlyphInfo* CTextureFont::findLetterGlyph(SLetterInfo *letter, boo uint bitmapFontSize = max((sint)_MinGlyphSize, min((sint)_MaxGlyphSize, letter->Size)); if (_GlyphSizeStep > 1 && bitmapFontSize > _GlyphSizeStepMin) { - uint size = (bitmapFontSize / _GlyphSizeStep) * _GlyphSizeStep; + bitmapFontSize = (bitmapFontSize / _GlyphSizeStep) * _GlyphSizeStep; } // CacheVersion not checked, all glyphs in cache must be rendered on texture From 09cb6f56dda4583411ea64eaa395c958175c3805 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 5 Jan 2019 22:05:49 +0200 Subject: [PATCH 160/303] Changed: Move ui scale limits to client cfg --HG-- branch : develop --- code/ryzom/client/client_default.cfg | 6 ++++++ .../data/gamedev/interfaces_v3/game_config.xml | 16 +++++++++++++++- code/ryzom/client/src/client_cfg.cpp | 8 +++++++- code/ryzom/client/src/client_cfg.h | 7 +++---- .../src/interface_v3/action_handler_game.cpp | 4 ++-- 5 files changed, 33 insertions(+), 8 deletions(-) diff --git a/code/ryzom/client/client_default.cfg b/code/ryzom/client/client_default.cfg index 4ffddc935..950da08b6 100644 --- a/code/ryzom/client/client_default.cfg +++ b/code/ryzom/client/client_default.cfg @@ -320,6 +320,12 @@ CameraSpeedMin = 2.0; CameraSpeedMax = 100.0; CameraResetSpeed = 10.0; // Speed in radian/s +// Values for UI Scale +InterfaceScale = 1.0; +InterfaceScale_min = 0.8; +InterfaceScale_max = 2.0; +InterfaceScale_step = 0.05; + // Default values for map MaxMapScale = 2.0; R2EDMaxMapScale = 8.0; diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml b/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml index 2728e7854..c3b904f01 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml @@ -876,10 +876,17 @@ posparent="lum" x="0" y="-2" /> + @@ -3091,6 +3098,13 @@ realtime="true" widget="sbfloat" link="Gamma" /> + = MIN_INTERFACE_SCALE && scale <= MAX_INTERFACE_SCALE) + if (scale >= ClientCfg.InterfaceScale_min && scale <= ClientCfg.InterfaceScale_max) { ClientCfg.InterfaceScale = scale; ClientCfg.writeDouble("InterfaceScale", ClientCfg.InterfaceScale); @@ -3754,7 +3754,7 @@ class CHandlerSetInterfaceScale : public IActionHandler } } - ucstring help("/setuiscale "+toString("%.1f .. %.1f", MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE)); + ucstring help("/setuiscale "+toString("%.1f .. %.1f", ClientCfg.InterfaceScale_min, ClientCfg.InterfaceScale_max)); CInterfaceManager::getInstance()->displaySystemInfo(help); } }; From ef1a51d0e4e3541cf0461beecd015405ff3c82b5 Mon Sep 17 00:00:00 2001 From: inky Date: Sun, 6 Jan 2019 04:58:12 +0100 Subject: [PATCH 161/303] Fixed: Free animal in player trade. Player could free an animal already selected in trade. When abort, client was given a copy of the (ghost)item in bag. --HG-- branch : develop --- code/ryzom/client/src/interface_v3/action_handler_game.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/ryzom/client/src/interface_v3/action_handler_game.cpp b/code/ryzom/client/src/interface_v3/action_handler_game.cpp index 7120c3b9f..836a4df28 100644 --- a/code/ryzom/client/src/interface_v3/action_handler_game.cpp +++ b/code/ryzom/client/src/interface_v3/action_handler_game.cpp @@ -1532,7 +1532,8 @@ public: virtual void execute (CCtrlBase * /* pCaller */, const string &Params) { // free with no confirm - beastOrder ("free", Params, false); + if (!UserEntity->isBusy()) + beastOrder ("free", Params, false); } }; REGISTER_ACTION_HANDLER( CHandlerDoBeastFree, "do_beast_free") From ed3130216381e05627624206864eb867f390e49e Mon Sep 17 00:00:00 2001 From: inky Date: Mon, 7 Jan 2019 00:14:14 +0100 Subject: [PATCH 162/303] Changed: Random command has now private roll. --HG-- branch : develop --- code/ryzom/client/src/commands.cpp | 13 ++++++++----- code/ryzom/client/src/user_entity.cpp | 23 ++++++++++++++++++++++- code/ryzom/client/src/user_entity.h | 2 +- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/code/ryzom/client/src/commands.cpp b/code/ryzom/client/src/commands.cpp index 7c33edb90..e8c1178c8 100644 --- a/code/ryzom/client/src/commands.cpp +++ b/code/ryzom/client/src/commands.cpp @@ -475,14 +475,17 @@ bool randomFromString(std::string const& str, sint16& val, sint16 min = -32768, return false; } -NLMISC_COMMAND(random, "Roll a dice and say the result around","[] ") +NLMISC_COMMAND(random, "Roll a dice and say the result around","[] [h|ide]") { // Check parameters. - if (args.size()<1 || args.size()>2) + if (args.size() < 1 || args.size() > 3) return false; sint16 min = 1; sint16 max; + + bool hide = args[args.size()-1][0] == 'h'; + if (!randomFromString(args[0], max)) { CInterfaceManager *pIM = CInterfaceManager::getInstance(); @@ -491,13 +494,13 @@ NLMISC_COMMAND(random, "Roll a dice and say the result around","[] ") pIM->displaySystemInfo(msg); return false; } - if (args.size()==2) + if (args.size() > 1 && args[1][0] != 'h') { if (!randomFromString(args[1], min)) { CInterfaceManager *pIM = CInterfaceManager::getInstance(); ucstring msg = CI18N::get("uiRandomBadParameter"); - strFindReplace(msg, "%s", args[0] ); + strFindReplace(msg, "%s", args[1] ); pIM->displaySystemInfo(msg); return false; } @@ -506,7 +509,7 @@ NLMISC_COMMAND(random, "Roll a dice and say the result around","[] ") std::swap(min, max); if (UserEntity != NULL) - UserEntity->rollDice(min, max); + UserEntity->rollDice(min, max, hide); return true; } diff --git a/code/ryzom/client/src/user_entity.cpp b/code/ryzom/client/src/user_entity.cpp index 25096f304..81a9e5a3a 100644 --- a/code/ryzom/client/src/user_entity.cpp +++ b/code/ryzom/client/src/user_entity.cpp @@ -3091,8 +3091,29 @@ void CUserEntity::setAFK(bool b, string afkTxt) //----------------------------------------------- // rollDice //----------------------------------------------- -void CUserEntity::rollDice(sint16 min, sint16 max) +void CUserEntity::rollDice(sint16 min, sint16 max, bool local) { + if (local) + { + // no need to broadcast over network here + static NLMISC::CRandom* dice = (NLMISC::CRandom*)NULL; + if (!dice) + { + dice = new NLMISC::CRandom; + dice->srand(CTickEventHandler::getGameCycle()); + } + sint16 roll = min + (sint16)dice->rand(max-min); + + ucstring msg = CI18N::get("msgRollDiceLocal"); + strFindReplace(msg, "%min", std::to_string(min)); + strFindReplace(msg, "%max", std::to_string(max)); + strFindReplace(msg, "%roll", std::to_string(roll)); + + CInterfaceManager *pIM= CInterfaceManager::getInstance(); + + pIM->displaySystemInfo(msg, getStringCategory(msg, msg)); + return; + } const string msgName = "COMMAND:RANDOM"; CBitMemStream out; if (GenericMsgHeaderMngr.pushNameToStream(msgName, out)) diff --git a/code/ryzom/client/src/user_entity.h b/code/ryzom/client/src/user_entity.h index ae4730f32..8a4a27c16 100644 --- a/code/ryzom/client/src/user_entity.h +++ b/code/ryzom/client/src/user_entity.h @@ -225,7 +225,7 @@ public: void setAFK(bool b, std::string afkTxt=""); /// Roll a dice and tell the result around - void rollDice(sint16 min, sint16 max); + void rollDice(sint16 min, sint16 max, bool local); /// return true if user can engage melee combat, else return false and display system msg bool canEngageCombat(); From bc3572462299f72e92bb4ad08615846ab7ad9f23 Mon Sep 17 00:00:00 2001 From: Inky Date: Tue, 8 Jan 2019 02:33:18 +0100 Subject: [PATCH 163/303] Added: Inventory filter for animals --HG-- branch : develop --- .../src/interface_v3/inventory_manager.cpp | 18 ++++++++++++++++-- .../src/interface_v3/inventory_manager.h | 12 ++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/inventory_manager.cpp b/code/ryzom/client/src/interface_v3/inventory_manager.cpp index 0d23e19ec..5f9ff2d3b 100644 --- a/code/ryzom/client/src/interface_v3/inventory_manager.cpp +++ b/code/ryzom/client/src/interface_v3/inventory_manager.cpp @@ -2003,6 +2003,9 @@ bool SBagOptions::parse(xmlNodePtr cur, CInterfaceGroup * /* parentGroup */) prop = xmlGetProp (cur, (xmlChar*)"filter_tool"); if (prop) DbFilterTool = NLGUI::CDBManager::getInstance()->getDbProp(prop.str()); + prop = xmlGetProp (cur, (xmlChar*)"filter_pet"); + if (prop) DbFilterPet = NLGUI::CDBManager::getInstance()->getDbProp(prop.str()); + prop = xmlGetProp (cur, (xmlChar*)"filter_mp"); if (prop) DbFilterMP = NLGUI::CDBManager::getInstance()->getDbProp(prop.str()); @@ -2079,6 +2082,13 @@ bool SBagOptions::isSomethingChanged() LastDbFilterTool = (DbFilterTool->getValue8() != 0); } + if (DbFilterPet != NULL) + if ((DbFilterPet->getValue8() != 0) != LastDbFilterPet) + { + bRet = true; + LastDbFilterPet = (DbFilterPet->getValue8() != 0); + } + if (DbFilterMP != NULL) if ((DbFilterMP->getValue8() != 0) != LastDbFilterMP) { @@ -2117,6 +2127,7 @@ bool SBagOptions::canDisplay(CDBCtrlSheet *pCS) const bool bFilterArmor = getFilterArmor(); bool bFilterWeapon = getFilterWeapon(); bool bFilterTool = getFilterTool(); + bool bFilterPet = getFilterPet(); bool bFilterMP = getFilterMP(); bool bFilterMissMP = getFilterMissMP(); bool bFilterTP = getFilterTP(); @@ -2168,10 +2179,13 @@ bool SBagOptions::canDisplay(CDBCtrlSheet *pCS) const (pIS->Family == ITEMFAMILY::HARVEST_TOOL) || (pIS->Family == ITEMFAMILY::TAMING_TOOL) || (pIS->Family == ITEMFAMILY::TRAINING_TOOL) || - (pIS->Family == ITEMFAMILY::BAG) || - (pIS->Family == ITEMFAMILY::PET_ANIMAL_TICKET) ) + (pIS->Family == ITEMFAMILY::BAG)) if (!bFilterTool) bDisplay = false; + // Pet + if (pIS->Family == ITEMFAMILY::PET_ANIMAL_TICKET) + if (!bFilterPet) bDisplay = false; + // MP if ((pIS->Family == ITEMFAMILY::RAW_MATERIAL) && pIS->canBuildSomeItemPart()) if (!bFilterMP) bDisplay = false; diff --git a/code/ryzom/client/src/interface_v3/inventory_manager.h b/code/ryzom/client/src/interface_v3/inventory_manager.h index d1c5dbe8c..364874f36 100644 --- a/code/ryzom/client/src/interface_v3/inventory_manager.h +++ b/code/ryzom/client/src/interface_v3/inventory_manager.h @@ -509,6 +509,7 @@ struct SBagOptions NLMISC::CCDBNodeLeaf *DbFilterArmor; NLMISC::CCDBNodeLeaf *DbFilterWeapon; NLMISC::CCDBNodeLeaf *DbFilterTool; + NLMISC::CCDBNodeLeaf *DbFilterPet; NLMISC::CCDBNodeLeaf *DbFilterMP; NLMISC::CCDBNodeLeaf *DbFilterMissMP; NLMISC::CCDBNodeLeaf *DbFilterTP; @@ -516,6 +517,7 @@ struct SBagOptions bool LastDbFilterArmor; bool LastDbFilterWeapon; bool LastDbFilterTool; + bool LastDbFilterPet; bool LastDbFilterMP; bool LastDbFilterMissMP; bool LastDbFilterTP; @@ -529,8 +531,8 @@ struct SBagOptions SBagOptions() { InvType = CInventoryManager::InvUnknown; - DbFilterArmor = DbFilterWeapon = DbFilterTool = DbFilterMP = DbFilterMissMP = DbFilterTP = NULL; - LastDbFilterArmor = LastDbFilterWeapon = LastDbFilterTool = LastDbFilterMP = LastDbFilterMissMP = LastDbFilterTP = false; + DbFilterArmor = DbFilterWeapon = DbFilterTool = DbFilterPet = DbFilterMP = DbFilterMissMP = DbFilterTP = NULL; + LastDbFilterArmor = LastDbFilterWeapon = LastDbFilterTool = LastDbFilterPet = LastDbFilterMP = LastDbFilterMissMP = LastDbFilterTP = false; SearchFilterChanged = false; SearchQualityMin = 0; SearchQualityMax = 999; @@ -561,6 +563,12 @@ struct SBagOptions return (DbFilterTool->getValue8()!=0); } + bool getFilterPet() const + { + if (DbFilterPet == NULL) return true; + return (DbFilterPet->getValue8()!=0); + } + bool getFilterMP() const { if (DbFilterMP == NULL) return true; From dda8a36ee275c91415f3b345a601cd3f535e97a8 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 8 Jan 2019 11:31:50 +0200 Subject: [PATCH 164/303] Changed: Allow to set custom sizing chars for text --HG-- branch : develop --- code/nel/include/nel/gui/view_text.h | 6 +++ code/nel/src/gui/view_text.cpp | 69 ++++++++++++++++++++++------ 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/code/nel/include/nel/gui/view_text.h b/code/nel/include/nel/gui/view_text.h index aa1d83330..b9ef7211c 100644 --- a/code/nel/include/nel/gui/view_text.h +++ b/code/nel/include/nel/gui/view_text.h @@ -100,6 +100,9 @@ namespace NLGUI void setMultiMaxLine(uint l) { _MultiMaxLine = l; } void setMultiMinLine(uint l) { _MultiMinLine = l; } + // Override chars used to compute font size + void setFontSizing(const std::string &chars, const std::string &fallback); + // Force only a subset of letter to be displayed. Default is 0/0xFFFFFFFF void enableStringSelection(uint start, uint end); void disableStringSelection(); @@ -244,6 +247,9 @@ namespace NLGUI bool _Oblique; // width of the font in pixel. Just a Hint for tabing format (computed with '_') float _FontWidth; + // strings to use when computing font size + ucstring _FontSizingChars; + ucstring _FontSizingFallback; // height of the font in pixel. // use getFontHeight float _FontHeight; diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index 8d36c046d..03dd52701 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -97,7 +97,6 @@ namespace NLGUI _InvalidTextContext= true; _FirstLineX = 0; - computeFontSize (); _SingleLineTextClamped= false; _OverExtendViewText= false; @@ -110,6 +109,14 @@ namespace NLGUI _LetterColors = NULL; _Setuped= false; _AutoClampOffset = 0; + + // Letter size + // - "_" that should be the character with the lowest part + // - A with an accent for the highest part + _FontSizingChars.fromUtf8("_\xc3\x84"); + // fallback if SizingChars are not supported by font + _FontSizingFallback.fromUtf8("|"); + computeFontSize (); } // *************************************************************************** @@ -370,6 +377,16 @@ namespace NLGUI { return toString( _ContinuousUpdate ); } + else + if ( name == "sizing_chars" ) + { + return _FontSizingChars.toUtf8(); + } + else + if ( name == "sizing_fallback" ) + { + return _FontSizingFallback.toUtf8(); + } else return ""; } @@ -615,6 +632,18 @@ namespace NLGUI return true; } + else + if( name == "sizing_chars" ) + { + _FontSizingChars.fromUtf8(value); + return true; + } + else + if( name == "sizing_fallback" ) + { + _FontSizingFallback.fromUtf8(value); + return true; + } else return false; } @@ -679,6 +708,8 @@ namespace NLGUI xmlSetProp( node, BAD_CAST "clamp_right", BAD_CAST toString( _ClampRight ).c_str() ); xmlSetProp( node, BAD_CAST "auto_clamp_offset", BAD_CAST toString( _AutoClampOffset ).c_str() ); xmlSetProp( node, BAD_CAST "continuous_update", BAD_CAST toString( _ContinuousUpdate ).c_str() ); + xmlSetProp( node, BAD_CAST "sizing_chars", BAD_CAST _FontSizingChars.toUtf8().c_str() ); + xmlSetProp( node, BAD_CAST "sizing_fallback", BAD_CAST _FontSizingFallback.toUtf8().c_str() ); return true; } @@ -854,6 +885,17 @@ namespace NLGUI _ContinuousUpdate = convertBool(prop); } + // "_Ä" lowest/highest chars (underscore, A+diaeresis) + _FontSizingChars.fromUtf8("_\xc3\x84"); + prop = (char*) xmlGetProp( cur, (xmlChar*)"sizing_chars" ); + if (prop) + _FontSizingChars.fromUtf8((const char*)prop); + + // fallback if SizingChars are not supported by font + _FontSizingFallback.fromUtf8("|"); + prop = (char*) xmlGetProp( cur, (xmlChar*)"sizing_fallback" ); + if (prop) + _FontSizingFallback.fromUtf8((const char*)prop); computeFontSize (); } @@ -1325,6 +1367,15 @@ namespace NLGUI _FormatTags.clear(); } + // *************************************************************************** + void CViewText::setFontSizing(const std::string &chars, const std::string &fallback) + { + _FontSizingChars.clear(); + _FontSizingChars.fromUtf8(chars); + _FontSizingFallback.clear(); + _FontSizingFallback.fromUtf8(fallback); + } + // *************************************************************************** void CViewText::setFontName(const std::string &name) { @@ -2856,22 +2907,14 @@ namespace NLGUI TextContext->setOblique (_Oblique); // Letter size - ucstring chars; - // instead of using the height of "|" that depends on font, - // we're using 2 characters: - // - "_" that should be the character with the lowest part - // - A with an accent for the highest part - chars.fromUtf8("_\xc3\x84"); - - // for now we can't know that directly from UTextContext - UTextContext::CStringInfo si = TextContext->getStringInfo(chars); + UTextContext::CStringInfo si = TextContext->getStringInfo(_FontSizingChars); // font generator changes unknown glyphs to dot '.'. use fallback if it looks odd if (_FontSize > (si.StringHeight + si.StringLine)) { - chars.fromUtf8("|"); - si = TextContext->getStringInfo(chars); + si = TextContext->getStringInfo(_FontSizingFallback); } + // add a padding of 1 pixel else the top will be truncated _FontHeight = si.StringHeight + 1; _FontLegHeight = si.StringLine; @@ -2880,7 +2923,7 @@ namespace NLGUI si = TextContext->getStringInfo(ucstring(" ")); _SpaceWidth = si.StringWidth; - // Font Width + // Font Width (used for ) si = TextContext->getStringInfo(ucstring("_")); _FontWidth = si.StringWidth; } From 8b69d673be7ff09d9ca21298ebe9a17585830b21 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 8 Jan 2019 11:32:01 +0200 Subject: [PATCH 165/303] Changed: Allow to set font size without adding global font size coef --HG-- branch : develop --- code/nel/include/nel/gui/view_text.h | 3 +- code/nel/src/gui/view_text.cpp | 61 +++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/code/nel/include/nel/gui/view_text.h b/code/nel/include/nel/gui/view_text.h index b9ef7211c..5fe86dee5 100644 --- a/code/nel/include/nel/gui/view_text.h +++ b/code/nel/include/nel/gui/view_text.h @@ -82,7 +82,7 @@ namespace NLGUI void setText (const ucstring &text); void setFontName (const std::string &name); - void setFontSize (sint nFontSize); + void setFontSize (sint nFontSize, bool coef = true); void setEmbolden (bool nEmbolden); void setOblique (bool nOblique); void setColor (const NLMISC::CRGBA &color); @@ -243,6 +243,7 @@ namespace NLGUI std::string _FontName; /// the font size sint _FontSize; + bool _FontSizeCoef; bool _Embolden; bool _Oblique; // width of the font in pixel. Just a Hint for tabing format (computed with '_') diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index 03dd52701..e991d8170 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -65,6 +65,7 @@ namespace NLGUI _FontSize = 12 + CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont ).getValSInt32(); + _FontSizeCoef = true; _FontName.clear(); _Embolden = false; _Oblique = false; @@ -141,6 +142,7 @@ namespace NLGUI setupDefault (); _FontSize = FontSize + CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); + _FontSizeCoef = true; _Color = Color; _Shadow = Shadow; _ShadowOutline = ShadowOutline; @@ -185,6 +187,7 @@ namespace NLGUI _PosRef = vt._PosRef; _FontSize = vt._FontSize; + _FontSizeCoef = vt._FontSizeCoef; _Embolden = vt._Embolden; _Oblique = vt._Oblique; _Underlined = vt._Underlined; @@ -248,9 +251,15 @@ namespace NLGUI else if( name == "fontsize" ) { - return toString( - _FontSize - CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont ).getValSInt32() - ); + if (_FontSizeCoef) + return toString(_FontSize - CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont ).getValSInt32()); + + return toString(_FontSize); + } + else + if ( name == "fontsize_coef" ) + { + return toString(_FontSizeCoef); } else if( name == "fontweight" ) @@ -425,6 +434,22 @@ namespace NLGUI return true; } else + if( name == "fontsize_coef" ) + { + bool b; + bool oldValue = _FontSizeCoef; + if (fromString( value, b) ) + _FontSizeCoef = b; + // must only change font size when current state changes + if (_FontSizeCoef != oldValue) + { + if (_FontSizeCoef) + _FontSize += CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont ).getValSInt32(); + else + _FontSize -= CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont ).getValSInt32(); + } + } + else if( name == "fontweight" ) { if (value == "bold") @@ -653,10 +678,11 @@ namespace NLGUI { xmlSetProp( node, BAD_CAST "color", BAD_CAST toString( _Color ).c_str() ); xmlSetProp( node, BAD_CAST "global_color", BAD_CAST toString( _ModulateGlobalColor ).c_str() ); - xmlSetProp( node, BAD_CAST "fontsize", - BAD_CAST toString( - _FontSize - CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont ).getValSInt32() - ).c_str() ); + + sint32 fontSize = _FontSize; + if (_FontSizeCoef) fontSize -= CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont ).getValSInt32(); + xmlSetProp( node, BAD_CAST "fontsize", BAD_CAST toString(fontSize).c_str() ); + xmlSetProp( node, BAD_CAST "fontsize_coef", BAD_CAST toString(_FontSizeCoef).c_str() ); std::string fontweight("normal"); if (_Embolden) @@ -755,6 +781,16 @@ namespace NLGUI _FontSize += CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); } + prop = (char*) xmlGetProp( cur, (xmlChar*)"fontsize_coef" ); + _FontSizeCoef = true; + if (prop) + { + _FontSizeCoef = convertBool(prop); + if (!_FontSizeCoef) + _FontSize -= CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); + } + + prop = (char*) xmlGetProp( cur, (xmlChar*)"fontweight" ); _Embolden = false; if (prop) @@ -1395,9 +1431,11 @@ namespace NLGUI } // *************************************************************************** - void CViewText::setFontSize (sint nFontSize) + void CViewText::setFontSize (sint nFontSize, bool coef) { - _FontSize = nFontSize + CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); + _FontSize = nFontSize; + if (coef) _FontSize += CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); + _FontSizeCoef = coef; computeFontSize (); invalidateContent(); } @@ -1405,7 +1443,10 @@ namespace NLGUI // *************************************************************************** sint CViewText::getFontSize() const { - return _FontSize - CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); + if (_FontSizeCoef) + return _FontSize - CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); + + return _FontSize; } // *************************************************************************** From a7b931353c356bb09b597bd0bf5857a5fc37e43d Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 8 Jan 2019 11:39:02 +0200 Subject: [PATCH 166/303] Changed: Fixes for client local/debug mode --HG-- branch : develop --- .../ryzom/client/src/interface_v3/action_handler_game.cpp | 4 ++-- code/ryzom/client/src/interface_v3/group_html_webig.cpp | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/action_handler_game.cpp b/code/ryzom/client/src/interface_v3/action_handler_game.cpp index 836a4df28..c5faa16d9 100644 --- a/code/ryzom/client/src/interface_v3/action_handler_game.cpp +++ b/code/ryzom/client/src/interface_v3/action_handler_game.cpp @@ -4238,7 +4238,7 @@ public: string fileName = getParam(sParams, "music"); // don't play if db is in init stage - if (IngameDbMngr.initInProgress()) return; + if (!ClientCfg.Local && IngameDbMngr.initInProgress()) return; if(SoundMngr) SoundMngr->playEventMusic(fileName, xFade, loop); @@ -4260,7 +4260,7 @@ public: string fileName= getParam(sParams, "music"); // don't play if db is in init stage - if (IngameDbMngr.initInProgress()) return; + if (!ClientCfg.Local && IngameDbMngr.initInProgress()) return; if(SoundMngr) SoundMngr->stopEventMusic(fileName, xFade); diff --git a/code/ryzom/client/src/interface_v3/group_html_webig.cpp b/code/ryzom/client/src/interface_v3/group_html_webig.cpp index fe2fa5229..66cfecdad 100644 --- a/code/ryzom/client/src/interface_v3/group_html_webig.cpp +++ b/code/ryzom/client/src/interface_v3/group_html_webig.cpp @@ -54,7 +54,7 @@ REGISTER_ACTION_HANDLER( CHandlerBrowseHome, "browse_home"); static string getWebAuthKey() { - if(!UserEntity) return ""; + if(!UserEntity || !NetMngr.getLoginCookie().isValid()) return ""; // authkey = uint32 cid = NetMngr.getLoginCookie().getUserId() * 16 + PlayerSelectedSlot; @@ -83,7 +83,7 @@ void addWebIGParams (string &url, bool trustedDomain) { url += string("&cid=") + toString(cid) + string("&authkey=") + getWebAuthKey(); - + if (url.find('$') != string::npos) { strFindReplace(url, "$gender$", GSGENDER::toString(UserEntity->getGender())); @@ -304,6 +304,8 @@ CGroupHTMLAuth::~CGroupHTMLAuth() void CGroupHTMLAuth::addHTTPGetParams (string &url, bool trustedDomain) { + if(!UserEntity || !NetMngr.getLoginCookie().isValid()) return; + addWebIGParams(url, trustedDomain); } @@ -311,7 +313,7 @@ void CGroupHTMLAuth::addHTTPGetParams (string &url, bool trustedDomain) void CGroupHTMLAuth::addHTTPPostParams (SFormFields &formfields, bool trustedDomain) { - if(!UserEntity) return; + if(!UserEntity || !NetMngr.getLoginCookie().isValid()) return; uint32 cid = NetMngr.getLoginCookie().getUserId() * 16 + PlayerSelectedSlot; formfields.add("shardid", toString(CharacterHomeSessionId)); From 6c1d44bc511ec470165ae196574bf5613a62c866 Mon Sep 17 00:00:00 2001 From: Inky Date: Tue, 8 Jan 2019 03:07:40 +0100 Subject: [PATCH 167/303] Added: sendMsgToServerUseItem lua bind --HG-- branch : develop --- code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp | 11 +++++++++++ code/ryzom/client/src/interface_v3/lua_ihm_ryzom.h | 1 + 2 files changed, 12 insertions(+) diff --git a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp index 36780f9e5..01b4dd786 100644 --- a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp +++ b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp @@ -540,6 +540,7 @@ void CLuaIHMRyzom::RegisterRyzomFunctions(NLGUI::CLuaState &ls) LUABIND_FUNC(getClientCfg), LUABIND_FUNC(sendMsgToServer), LUABIND_FUNC(sendMsgToServerPvpTag), + LUABIND_FUNC(sendMsgToServerUseItem), LUABIND_FUNC(isGuildQuitAvailable), LUABIND_FUNC(sortGuildMembers), LUABIND_FUNC(getNbGuildMembers), @@ -3326,6 +3327,16 @@ void CLuaIHMRyzom::sendMsgToServerPvpTag(bool pvpTag) ::sendMsgToServer("PVP:PVP_TAG", tag); } +// *************************************************************************** +void CLuaIHMRyzom::sendMsgToServerUseItem(sint32 slot) +{ + //H_AUTO(Lua_CLuaIHM_sendMsgToServerUseItem) + uint8 u8n1 = (uint8)((uint16)slot >> 8); + uint8 u8n2 = (uint8)((uint16)slot & 0x00FF); + + ::sendMsgToServer("ITEM:USE_ITEM", u8n1, u8n2); +} + // *************************************************************************** bool CLuaIHMRyzom::isGuildQuitAvailable() { diff --git a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.h b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.h index fa8e57c9c..7a733f7aa 100644 --- a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.h +++ b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.h @@ -198,6 +198,7 @@ private: static std::string getClientCfg(const std::string &varName); static void sendMsgToServer(const std::string &msgName); static void sendMsgToServerPvpTag(bool pvpTag); + static void sendMsgToServerUseItem(sint32 slot); static bool isGuildQuitAvailable(); static void sortGuildMembers(); static sint32 getNbGuildMembers(); From ec9a0e6d38585bedd89858ffe76e140e5521b8c5 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 13 Jan 2019 09:08:08 +0200 Subject: [PATCH 168/303] Fixed: Crash in lua getWeatherValue() when continent was not loaded --HG-- branch : develop --- code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp index 01b4dd786..a599cd18b 100644 --- a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp +++ b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp @@ -1688,7 +1688,13 @@ int CLuaIHMRyzom::getWeatherValue(CLuaState &ls) CLuaIHM::checkArgCount(ls, funcName, 0); uint64 currDay = RT.getRyzomDay(); float currHour = (float) RT.getRyzomTime(); - ls.push(::getBlendedWeather(currDay, currHour, *WeatherFunctionParams, ContinentMngr.cur()->WeatherFunction)); + float weather = 0.f; + if (ContinentMngr.cur()) + { + weather = ::getBlendedWeather(currDay, currHour, *WeatherFunctionParams, ContinentMngr.cur()->WeatherFunction); + } + + ls.push(weather); return 1; } From f4ade875a3516eaa9f1a32e92fd18ef5b6cf9205 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 19 Jan 2019 22:26:36 +0200 Subject: [PATCH 169/303] Added: CViewText centered text mode option. --HG-- branch : develop --- code/nel/include/nel/gui/view_text.h | 2 +- code/nel/src/gui/view_text.cpp | 27 +++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/code/nel/include/nel/gui/view_text.h b/code/nel/include/nel/gui/view_text.h index 5fe86dee5..195db5a62 100644 --- a/code/nel/include/nel/gui/view_text.h +++ b/code/nel/include/nel/gui/view_text.h @@ -37,7 +37,7 @@ namespace NLGUI class CViewText : public CViewBase { public: - enum TTextMode { ClipWord, DontClipWord, Justified }; + enum TTextMode { ClipWord, DontClipWord, Justified, Centered }; public: DECLARE_UI_CLASS(CViewText) diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index e991d8170..d04d3df2e 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -312,6 +312,9 @@ namespace NLGUI case Justified: return "justified"; break; + + case Centered: + return "centered"; } return ""; @@ -522,6 +525,9 @@ namespace NLGUI else if( value == "justified" ) _TextMode = Justified; + else + if( value == "centered" ) + _TextMode = Centered; return true; } @@ -716,6 +722,10 @@ namespace NLGUI case Justified: just = "justified"; break; + + case Centered: + just = "centered"; + break; } xmlSetProp( node, BAD_CAST "justification", BAD_CAST just.c_str() ); @@ -843,6 +853,7 @@ namespace NLGUI if (nlstricmp("clip_word", (const char *) prop) == 0) _TextMode = ClipWord; else if (nlstricmp("dont_clip_word", (const char *) prop) == 0) _TextMode = DontClipWord; else if (nlstricmp("justified", (const char *) prop) == 0) _TextMode = Justified; + else if (nlstricmp("centered", (const char *) prop) == 0) _TextMode = Centered; else nlwarning(" bad text mode"); } @@ -1195,7 +1206,18 @@ namespace NLGUI { CLine &currLine = *_Lines[i]; // current x position - float px = (float) (_XReal * _Scale + ((i==0) ? (sint)_FirstLineX : 0)); + float px = (float) (_XReal * _Scale + ((i==0) ? _FirstLineX : 0.f)); + + // Center line to computed maximum line width (_WReal) + // + // Does not give most accurate result when _WReal is much smaller than parent, + // but _WReal also defines mouseover hotspot/tooltip area. + // + // May not work correctly in CGroupParagraph (multiple text elements). + // + if (_TextMode == Centered) + px += (float)(_WReal * _Scale - (currLine.getWidth() + (i == 0 ? _FirstLineX : 0.f)) )/ 2.f; + // draw each words of the line for(uint k = 0; k < currLine.getNumWords(); ++k) { @@ -2039,6 +2061,7 @@ namespace NLGUI switch(_TextMode) { case ClipWord: updateTextContextMultiLine(nMaxWidth); break; + case Centered: // fallthru to DontClipWord case DontClipWord: updateTextContextMultiLineJustified(nMaxWidth, false); break; case Justified: updateTextContextMultiLineJustified(nMaxWidth, true); break; } @@ -2869,7 +2892,7 @@ namespace NLGUI return (sint32)ceilf(_FontHeight / _Scale); } // If we can't clip the words, return the size of the largest word - else if ((_TextMode == DontClipWord) || (_TextMode == Justified)) + else if ((_TextMode == DontClipWord) || (_TextMode == Justified) || (_TextMode == Centered)) { NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(_FontName); TextContext->setHotSpot (UTextContext::BottomLeft); From 8c51bbc808bcb02de04a11f200dbb12a73bfbfbe Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 19 Jan 2019 22:28:13 +0200 Subject: [PATCH 170/303] Fixed: typo --HG-- branch : develop --- code/nel/src/gui/view_text.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index d04d3df2e..47f128d96 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -350,7 +350,7 @@ namespace NLGUI return toString( _Underlined ); } else - if( name == "strikthrough" ) + if( name == "strikethrough" ) { return toString( _StrikeThrough ); } From 4e515eedf000bd1e86ab669cde5e914eef081452 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 22 Jan 2019 20:00:06 +0200 Subject: [PATCH 171/303] Added: game:onLoadMap lua event to allow override map texture as needed --HG-- branch : develop --- .../client/data/gamedev/interfaces_v3/map.lua | 42 +++++++++ .../client/data/gamedev/interfaces_v3/map.xml | 4 + .../client/src/interface_v3/group_map.cpp | 88 ++++++++++++++++++- .../ryzom/client/src/interface_v3/group_map.h | 22 +++++ .../register_interface_elements.cpp | 1 + 5 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 code/ryzom/client/data/gamedev/interfaces_v3/map.lua diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/map.lua b/code/ryzom/client/data/gamedev/interfaces_v3/map.lua new file mode 100644 index 000000000..609d18b28 --- /dev/null +++ b/code/ryzom/client/data/gamedev/interfaces_v3/map.lua @@ -0,0 +1,42 @@ +-- +-- custom maps +-- + +if (game==nil) then + game= {}; +end + +-- alternative textures for maps +game.mapTextures = {} +-- game.mapTextures["zorai_map.tga"] = "tryker_map.tga" + +-- register alternative texture for map +function game:setAltMap(mapName, altMap) + self.mapTextures[mapName] = altMap +end + +-- remove alternative map texture +function game:removeAltMap(mapName) + self.mapTextures[mapName] = nil +end + +-- map = getUI("ui:interface:map:content:map_content:actual_map") +function game:onLoadMap(map) + -- debugInfo("onLoadMap(id=".. map.id ..", texture=".. map.texture ..")"); + + -- if alt view not enabled + if getDbProp("UI:VARIABLES:SHOW_ALT_MAP") == 0 or map:isIsland() then + return + end + + local texture = map.texture + if self.mapTextures[texture] ~= nil then + -- debugInfo("-- using ".. self.mapTextures[texture] .." for " .. texture) + return self.mapTextures[texture] + end +end + +-- register map overrride +-- game:setAltMap("fyros_map.tga", "fyros_map_sp.tga") + + diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/map.xml b/code/ryzom/client/data/gamedev/interfaces_v3/map.xml index 0f1ab111c..b93028b82 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/map.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/map.xml @@ -2,6 +2,10 @@ + + + + diff --git a/code/ryzom/client/src/interface_v3/group_map.cpp b/code/ryzom/client/src/interface_v3/group_map.cpp index e6cfcf824..9de74bcc7 100644 --- a/code/ryzom/client/src/interface_v3/group_map.cpp +++ b/code/ryzom/client/src/interface_v3/group_map.cpp @@ -38,6 +38,7 @@ #include "../sheet_manager.h" // for MaxNumPeopleInTeam #include "../global.h" #include "nel/gui/ctrl_quad.h" +#include "nel/gui/lua_ihm.h" // #include "nel/misc/xml_auto_ptr.h" #include "game_share/mission_desc.h" @@ -403,6 +404,7 @@ CGroupMap::CGroupMap(const TCtorParam ¶m) _MaxH = 2000; //_MinW = 50; _MapTF = NULL; + _MapTexture.clear(); _PlayerPosMaterial = NULL; _PlayerPosTF = NULL; _MapTexW = 0; @@ -462,6 +464,8 @@ CGroupMap::CGroupMap(const TCtorParam ¶m) _PanStartDateInMs = 0; _DeltaTimeBeforePanInMs = 0; _DeltaPosBeforePan = 0; + // + _LuaLoadMapEntered = false; } //============================================================================================================ @@ -2070,16 +2074,62 @@ void CGroupMap::loadPlayerPos() _PlayerPosMaterial.setTexture(_PlayerPosTF); } +//============================================================================================================ +void CGroupMap::reload() +{ + if (!_CurMap || !getActive()) return; + + SMap* current = _CurMap; + _CurMap = NULL; + + setMap(current); +} + //============================================================================================================ void CGroupMap::loadMap() { _MapLoadFailure = true; if (!_CurMap) return; - const std::string &mapName = _CurMap->BitmapName; - std::string fullName = NLMISC::CPath::lookup(mapName, false, false); + + _MapTexture = _CurMap->BitmapName; + + // call lua game:onLoadMap() function if present + // avoid deadlock if called recursively + if (!_LuaLoadMapEntered) + { + _LuaLoadMapEntered = true; + CLuaState *ls = CLuaManager::getInstance().getLuaState(); + + CLuaStackRestorer lsr(ls, ls->getTop()); + ls->pushGlobalTable(); + + CLuaObject game(*ls); + game = game["game"]; + if (!game["onLoadMap"].isNil()) + { + uint numArg = 1; + uint numResult = 1; + + CLuaIHM::pushReflectableOnStack(*ls, this); + if (game.callMethodByNameNoThrow("onLoadMap", numArg, numResult)) + { + if (ls->isString(1)) + { + if (!NLMISC::CPath::lookup(ls->toString(1), false, false).empty()) + _MapTexture = ls->toString(1); + else + nlwarning("Custom map texture not found '%s' for map '%s'", ls->toString(1), _MapTexture.c_str()); + } + } + } + + _LuaLoadMapEntered = false; + } + + std::string fullName = NLMISC::CPath::lookup(_MapTexture, false, false); if (fullName.empty()) { - nlwarning("Can't find map %s", mapName.c_str()); + nlwarning("Can't find map %s", _MapTexture.c_str()); return; } uint32 w, h; @@ -2098,7 +2148,7 @@ void CGroupMap::loadMap() } else { - nlwarning("Can't open map %s", mapName.c_str()); + nlwarning("Can't open map %s", _MapTexture.c_str()); return; } _MapTF = Driver->createTextureFile(fullName); @@ -3322,6 +3372,36 @@ SMap *CGroupMap::getParentMap(SMap *map) return NULL; } +//========================================================================================================= +std::string CGroupMap::getContinentName() const +{ + if (_CurMap == NULL) return ""; + + return toLower(_CurMap->ContinentName); +} + +//========================================================================================================= +std::string CGroupMap::getMapTexture() const +{ + return toLower(_MapTexture); +} + +//========================================================================================================= +int CGroupMap::luaReload(CLuaState &ls) +{ + CLuaIHM::checkArgCount(ls, "reload", 0); + reload(); + return 0; +} + +//========================================================================================================= +int CGroupMap::luaIsIsland(CLuaState &ls) +{ + CLuaIHM::checkArgCount(ls, "isIsland", 0); + ls.push(_IsIsland); + return 1; +} + ///////////////////// // ACTION HANDLERS // diff --git a/code/ryzom/client/src/interface_v3/group_map.h b/code/ryzom/client/src/interface_v3/group_map.h index 52980c0d8..baf273779 100644 --- a/code/ryzom/client/src/interface_v3/group_map.h +++ b/code/ryzom/client/src/interface_v3/group_map.h @@ -114,6 +114,17 @@ public: */ virtual void onUpdate(CGroupMap &/* owner */) {} }; + + REFLECT_EXPORT_START(CGroupMap, CInterfaceGroup) + REFLECT_STRING("continent", getContinentName, dummySet); + REFLECT_STRING("texture", getMapTexture, dummySet); + REFLECT_LUA_METHOD("isIsland", luaIsIsland); + REFLECT_LUA_METHOD("reload", luaReload); + REFLECT_EXPORT_END + + int luaReload(CLuaState &ls); + int luaIsIsland(CLuaState &ls); + public: CGroupMap(const TCtorParam ¶m); virtual ~CGroupMap(); @@ -134,6 +145,14 @@ public: void setMap(const std::string &mapName); void setMap(SMap *map); + // return current continent + std::string getContinentName() const; + // return currently displayed map texture + std::string getMapTexture() const; + + // reload current map texture + void reload(); + // pan the map of the given number of pixels void pan(sint32 dx, sint32 dy); @@ -323,6 +342,7 @@ private: CContinent *_CurContinent; // the last continent for which the map was displayed (can be NULL if world) NLMISC::CVector2f _MapMinCorner; // In world coordinates NLMISC::CVector2f _MapMaxCorner; + std::string _MapTexture; // currently displayed map texture bool _IsIsland; // true if current map is an island (island bitmap need not to be raised to the next // power of 2 @@ -499,6 +519,8 @@ private: // r2 islands std::vector _Islands; + // guard against recursive calls + bool _LuaLoadMapEntered; private: void loadPlayerPos(); diff --git a/code/ryzom/client/src/interface_v3/register_interface_elements.cpp b/code/ryzom/client/src/interface_v3/register_interface_elements.cpp index 6ce0029bf..203cac03a 100644 --- a/code/ryzom/client/src/interface_v3/register_interface_elements.cpp +++ b/code/ryzom/client/src/interface_v3/register_interface_elements.cpp @@ -34,6 +34,7 @@ void registerInterfaceElements() CViewPointerRyzom::forceLinking(); REGISTER_REFLECTABLE_CLASS(CViewRadar, CViewBase); + REGISTER_REFLECTABLE_CLASS(CGroupMap, CInterfaceGroup); REGISTER_REFLECTABLE_CLASS(CDBCtrlSheet, CCtrlDraggable); REGISTER_REFLECTABLE_CLASS(IListSheetBase, CInterfaceGroup); REGISTER_REFLECTABLE_CLASS(CInterface3DScene, CInterfaceGroup); From 2694cdb7890e11dfe40a627132e9f382f65063a4 Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Fri, 25 Jan 2019 23:46:38 +0800 Subject: [PATCH 172/303] Set up CI --- azure-pipelines.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 azure-pipelines.yml diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 000000000..39541fd7d --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,23 @@ +jobs: + - job: ubuntu16 + pool: + vmImage: 'Ubuntu-16.04' + steps: + - script: | + sudo apt-get update + sudo apt-get upgrade -y + sudo apt-get install liblua5.1-dev libluabind-dev libcpptest-dev -y + sudo apt-get install libogg-dev libvorbis-dev libopenal-dev -y + sudo apt-get install libgif-dev libfreetype6-dev -y + sudo apt-get install libxml2-dev -y + displayName: 'Dependencies' + - script: | + mkdir build + cmake --version + cd build + cmake -DWITH_NEL_TESTS=ON -DWITH_NEL_SAMPLES=ON -DWITH_LUA51=ON -DWITH_RYZOM_SERVER=ON -DWITH_RYZOM_TOOLS=ON -DWITH_NEL_TOOLS=ON ../code + cat build/CMakeCache.txt + displayName: 'CMake' + - script: | + make -j`nproc` + displayName: 'Make' \ No newline at end of file From 4c84748bace4a7dac3910b6b01633408f1bdeb29 Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Fri, 25 Jan 2019 23:59:35 +0800 Subject: [PATCH 173/303] Update --- azure-pipelines.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 39541fd7d..1d200d1bc 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -5,7 +5,10 @@ jobs: steps: - script: | sudo apt-get update - sudo apt-get upgrade -y + sudo apt-get install cmake build-essential -y + sudo apt-get install libmysqlclient15-dev -y + sudo apt-get install bison autoconf automake -y + sudo apt-get install libpng12-dev libjpeg62-dev -y sudo apt-get install liblua5.1-dev libluabind-dev libcpptest-dev -y sudo apt-get install libogg-dev libvorbis-dev libopenal-dev -y sudo apt-get install libgif-dev libfreetype6-dev -y From 7661d49bf0722502bf903c91cd4032c36b9b3ebd Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Sat, 26 Jan 2019 00:03:07 +0800 Subject: [PATCH 174/303] Update --- azure-pipelines.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 1d200d1bc..e100d14d4 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -13,6 +13,7 @@ jobs: sudo apt-get install libogg-dev libvorbis-dev libopenal-dev -y sudo apt-get install libgif-dev libfreetype6-dev -y sudo apt-get install libxml2-dev -y + sudo apt-get install libcurl4-openssl-dev -y displayName: 'Dependencies' - script: | mkdir build From 397f5b15072fa34445fc120a1a9ab82762af713a Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Sat, 26 Jan 2019 00:07:21 +0800 Subject: [PATCH 175/303] Update --- azure-pipelines.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e100d14d4..a4695291e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -6,7 +6,7 @@ jobs: - script: | sudo apt-get update sudo apt-get install cmake build-essential -y - sudo apt-get install libmysqlclient15-dev -y + sudo apt-get install libmysqlclient-dev -y sudo apt-get install bison autoconf automake -y sudo apt-get install libpng12-dev libjpeg62-dev -y sudo apt-get install liblua5.1-dev libluabind-dev libcpptest-dev -y @@ -14,6 +14,7 @@ jobs: sudo apt-get install libgif-dev libfreetype6-dev -y sudo apt-get install libxml2-dev -y sudo apt-get install libcurl4-openssl-dev -y + sudo apt-get install libsquish-dev -y displayName: 'Dependencies' - script: | mkdir build From bd274c5ad04081f663d233e56ca8f3041748afdd Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Sat, 26 Jan 2019 00:11:23 +0800 Subject: [PATCH 176/303] Update --- azure-pipelines.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a4695291e..89562087c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -14,13 +14,12 @@ jobs: sudo apt-get install libgif-dev libfreetype6-dev -y sudo apt-get install libxml2-dev -y sudo apt-get install libcurl4-openssl-dev -y - sudo apt-get install libsquish-dev -y displayName: 'Dependencies' - script: | mkdir build cmake --version cd build - cmake -DWITH_NEL_TESTS=ON -DWITH_NEL_SAMPLES=ON -DWITH_LUA51=ON -DWITH_RYZOM_SERVER=ON -DWITH_RYZOM_TOOLS=ON -DWITH_NEL_TOOLS=ON ../code + cmake -DWITH_NEL_TESTS=OFF -DWITH_NEL_SAMPLES=ON -DWITH_LUA51=ON -DWITH_RYZOM_SERVER=ON -DWITH_RYZOM_TOOLS=OFF -DWITH_NEL_TOOLS=OFF ../code cat build/CMakeCache.txt displayName: 'CMake' - script: | From 61b1509048589ed1cdc696cd769376165904bbc0 Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Sat, 26 Jan 2019 00:14:36 +0800 Subject: [PATCH 177/303] Update --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 89562087c..2ede2a7e8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -20,7 +20,7 @@ jobs: cmake --version cd build cmake -DWITH_NEL_TESTS=OFF -DWITH_NEL_SAMPLES=ON -DWITH_LUA51=ON -DWITH_RYZOM_SERVER=ON -DWITH_RYZOM_TOOLS=OFF -DWITH_NEL_TOOLS=OFF ../code - cat build/CMakeCache.txt + cat CMakeCache.txt displayName: 'CMake' - script: | make -j`nproc` From f4ff5e0d2567f3780f5b7c5e173c433bee90f7e0 Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Sat, 26 Jan 2019 00:17:22 +0800 Subject: [PATCH 178/303] Update --- azure-pipelines.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 2ede2a7e8..6ad47eba4 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -23,5 +23,6 @@ jobs: cat CMakeCache.txt displayName: 'CMake' - script: | + cd build make -j`nproc` displayName: 'Make' \ No newline at end of file From 86195393dbbc7e4d76bf12bb6c38991c6240d833 Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Sat, 26 Jan 2019 00:41:31 +0800 Subject: [PATCH 179/303] Update: Pipeline script --- azure-pipelines.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 6ad47eba4..6e0f2b2a7 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -4,8 +4,14 @@ jobs: vmImage: 'Ubuntu-16.04' steps: - script: | + sudo apt-get update + sudo apt-get install -y software-properties-common + sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install cmake build-essential -y + sudo apt-get install gcc-8 g++-8 -y + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 60 + sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-8 60 sudo apt-get install libmysqlclient-dev -y sudo apt-get install bison autoconf automake -y sudo apt-get install libpng12-dev libjpeg62-dev -y From a888ce008050e1feba00b37b6f4a28b33d172cc0 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 28 Jan 2019 11:40:52 +0200 Subject: [PATCH 180/303] Changed: Make border duplication as default for build interface --HG-- branch : develop --- code/nel/tools/3d/build_interface/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/nel/tools/3d/build_interface/main.cpp b/code/nel/tools/3d/build_interface/main.cpp index 58c97e513..ed7f220b5 100644 --- a/code/nel/tools/3d/build_interface/main.cpp +++ b/code/nel/tools/3d/build_interface/main.cpp @@ -214,7 +214,7 @@ int main(int argc, char **argv) args.addArg("x", "extract", "", "Extract all interface elements from to ."); args.addAdditionalArg("output_filename", "PNG or TGA file to generate", true); args.addAdditionalArg("input_path", "Path that containts interfaces elements", false); - args.addArg("b", "border", "", "Duplicate icon border to allow bilinear filtering"); + args.addArg("", "no-border", "", "Disable border duplication. Enabled by default"); if (!args.parse(argc, argv)) return 1; @@ -229,10 +229,10 @@ int main(int argc, char **argv) } // - uint borderSize = 0; - if (args.haveArg("b")) + uint borderSize = 1; + if (args.haveLongArg("no-border")) { - borderSize = 1; + borderSize = 0; } // extract all interface elements From d97f5b1a8bad84b4fb5c238a7b1aa20487e5a620 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 28 Jan 2019 11:40:52 +0200 Subject: [PATCH 181/303] Changed: Enable UI bilinear filtering by default. Requires new atlases to be generated --HG-- branch : develop --- code/ryzom/client/client_default.cfg | 5 +++++ code/ryzom/client/src/client_cfg.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/code/ryzom/client/client_default.cfg b/code/ryzom/client/client_default.cfg index 950da08b6..11bd62b5b 100644 --- a/code/ryzom/client/client_default.cfg +++ b/code/ryzom/client/client_default.cfg @@ -326,6 +326,11 @@ InterfaceScale_min = 0.8; InterfaceScale_max = 2.0; InterfaceScale_step = 0.05; +// Enable biliner filtering for UI textures +// Texture atlas needs to be generated with border duplication +// or there will be visible texture bleeding +BilinearUI = 1; + // Default values for map MaxMapScale = 2.0; R2EDMaxMapScale = 8.0; diff --git a/code/ryzom/client/src/client_cfg.cpp b/code/ryzom/client/src/client_cfg.cpp index e1ab87c02..ea81cd980 100644 --- a/code/ryzom/client/src/client_cfg.cpp +++ b/code/ryzom/client/src/client_cfg.cpp @@ -304,7 +304,7 @@ CClientConfig::CClientConfig() InterfaceScale_min = 0.8f; InterfaceScale_max = 2.0f; InterfaceScale_step = 0.05; - BilinearUI = false; + BilinearUI = true; VREnable = false; VRDisplayDevice = "Auto"; From 1f1bd9fb8f5486a9295cc7b7e3529c934d1f88d3 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 29 Jan 2019 00:34:38 +0200 Subject: [PATCH 182/303] Changed: Allow to override scroll bar texture width/height --HG-- branch : develop --- code/nel/include/nel/gui/ctrl_scroll.h | 1 + code/nel/src/gui/ctrl_scroll.cpp | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/code/nel/include/nel/gui/ctrl_scroll.h b/code/nel/include/nel/gui/ctrl_scroll.h index cf01ada78..a22da2cbd 100644 --- a/code/nel/include/nel/gui/ctrl_scroll.h +++ b/code/nel/include/nel/gui/ctrl_scroll.h @@ -175,6 +175,7 @@ namespace NLGUI bool _CallingAH : 1; bool _Cancelable : 1; // true if the slider may be cancelled when pressed on the mouse right button bool _Frozen : 1; + bool _Scale : 1; // For Target Scroller only: the target offset step in pixel. sint32 _TargetStepX; diff --git a/code/nel/src/gui/ctrl_scroll.cpp b/code/nel/src/gui/ctrl_scroll.cpp index acdaa15f5..e97bd8cd4 100644 --- a/code/nel/src/gui/ctrl_scroll.cpp +++ b/code/nel/src/gui/ctrl_scroll.cpp @@ -68,6 +68,7 @@ namespace NLGUI _StepValue = 0; _TileM = false; _Frozen = false; + _Scale = false; } // ------------------------------------------------------------------------------------------------ @@ -108,6 +109,11 @@ namespace NLGUI return getTextureTopOrRight(); } else + if( name == "scale" ) + { + return toString( _Scale ); + } + else if( name == "vertical" ) { return toString( _Vertical ); @@ -244,6 +250,14 @@ namespace NLGUI return; } else + if( name =="scale" ) + { + bool b; + if (fromString( value, b ) ) + _Scale = b; + return; + } + else if( name == "vertical" ) { bool b; @@ -408,6 +422,7 @@ namespace NLGUI xmlSetProp( node, BAD_CAST "tx_bottomleft", BAD_CAST getTextureBottomOrLeft().c_str() ); xmlSetProp( node, BAD_CAST "tx_middle", BAD_CAST getTextureMiddle().c_str() ); xmlSetProp( node, BAD_CAST "tx_topright", BAD_CAST getTextureTopOrRight().c_str() ); + xmlSetProp( node, BAD_CAST "scale", BAD_CAST toString( _Scale ).c_str() ); xmlSetProp( node, BAD_CAST "vertical", BAD_CAST toString( _Vertical ).c_str() ); std::string align; @@ -480,6 +495,10 @@ namespace NLGUI if(prop) setTextureTopOrRight(string((const char*)prop)); else setTextureTopOrRight ("w_scroll_l0_t.tga"); + // Override texture size (w for vertical, h for horizontal) + prop = (char*) xmlGetProp( node, (xmlChar*)"scale" ); + if (prop) _Scale = convertBool((const char*)prop); + // Read properties prop = (char*) xmlGetProp( node, (xmlChar*)"vertical" ); if (prop) _Vertical = convertBool((const char*)prop); @@ -606,13 +625,13 @@ namespace NLGUI if (_Vertical) { - _W = w; + if (!_Scale) _W = w; _H = _Target->getMaxHReal(); } else { _W = _Target->getMaxWReal(); - _H = h; + if (!_Scale) _H = h; } CCtrlBase::updateCoords (); From 5a1a167de91056c074e73aff026a0847063b6e38 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 29 Jan 2019 00:37:34 +0200 Subject: [PATCH 183/303] Added: Scroll bar for main chat tabs --HG-- branch : develop --- .../gamedev/interfaces_v3/interaction.xml | 20 ++++++++++++++++++- .../client/src/interface_v3/chat_window.cpp | 9 +++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/interaction.xml b/code/ryzom/client/data/gamedev/interfaces_v3/interaction.xml index f4ab98453..90432bcff 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/interaction.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/interaction.xml @@ -1042,7 +1042,9 @@ h="24" posref="TL TL" x="0" - y="-4"> + y="-4" + max_w="0" + max_sizeref="w"> + + + + setHeaderColor(desc.HeaderColor); + + // because root group was created from template, element from scrollbar target attribute was not created yet + CInterfaceGroup *pIG = w->getContainer()->getGroup("header_opened:channel_select"); + if (pIG) + { + CCtrlScroll *sb = dynamic_cast(w->getContainer()->getCtrl("channel_scroll")); + if (sb) sb->setTarget(pIG); + } + return w; } else From 07d9107b6bc2dc2578dda299395344d82c6ffe7e Mon Sep 17 00:00:00 2001 From: Nimetu Date: Wed, 30 Jan 2019 23:54:18 +0200 Subject: [PATCH 184/303] Fixed: build interface border duplication --HG-- branch : develop --- code/nel/tools/3d/build_interface/main.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/code/nel/tools/3d/build_interface/main.cpp b/code/nel/tools/3d/build_interface/main.cpp index ed7f220b5..2f0cc88bd 100644 --- a/code/nel/tools/3d/build_interface/main.cpp +++ b/code/nel/tools/3d/build_interface/main.cpp @@ -421,8 +421,17 @@ int main(int argc, char **argv) NLMISC::CBitmap *tmp = new NLMISC::CBitmap; tmp->resize(pBtmp->getWidth(), pBtmp->getHeight()); tmp->blit(pBtmp, 0, 0); + // corners tmp->resample(tmp->getWidth() + borderSize * 2, tmp->getHeight() + borderSize * 2); + // top, bottom + tmp->blit(pBtmp, borderSize, 0); + tmp->blit(pBtmp, borderSize, borderSize*2); + // left, right + tmp->blit(pBtmp, 0, borderSize); + tmp->blit(pBtmp, borderSize*2, borderSize); + // center tmp->blit(pBtmp, borderSize, borderSize); + delete pBtmp; pBtmp = tmp; } From 5e68a4e293455f3cc647aaf3c2bd3e380be77c20 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 11 Feb 2019 12:45:15 +0200 Subject: [PATCH 185/303] Fixed: Loss of precision when calculating text line width --HG-- branch : develop --- code/nel/include/nel/gui/view_text.h | 4 ++-- code/nel/src/gui/view_text.cpp | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code/nel/include/nel/gui/view_text.h b/code/nel/include/nel/gui/view_text.h index 195db5a62..fa5f74b84 100644 --- a/code/nel/include/nel/gui/view_text.h +++ b/code/nel/include/nel/gui/view_text.h @@ -442,9 +442,9 @@ namespace NLGUI // Clear all the lines and free their datas void clearLines(); // Update in the case of a multiline text - void updateTextContextMultiLine(uint nMaxWidth); + void updateTextContextMultiLine(float nMaxWidth); // Update in the case of a multiline text with justification - void updateTextContextMultiLineJustified(uint nMaxWidth, bool expandSpaces); + void updateTextContextMultiLineJustified(float nMaxWidth, bool expandSpaces); // Recompute font size info void computeFontSize (); diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index 47f128d96..45adbe245 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -1628,7 +1628,7 @@ namespace NLGUI // *************************************************************************** - void CViewText::updateTextContextMultiLine(uint nMaxWidth) + void CViewText::updateTextContextMultiLine(float nMaxWidth) { ucchar ucLetter; UTextContext::CStringInfo si; @@ -1741,7 +1741,7 @@ namespace NLGUI } // *************************************************************************** - void CViewText::updateTextContextMultiLineJustified(uint nMaxWidth, bool expandSpaces) + void CViewText::updateTextContextMultiLineJustified(float nMaxWidth, bool expandSpaces) { NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(_FontName); UTextContext::CStringInfo si; @@ -1847,10 +1847,10 @@ namespace NLGUI } // // Does the word go beyond the end of line ? - if (!lineFeed && newLineWidth > (float) nMaxWidth) + if (!lineFeed && newLineWidth > nMaxWidth) { // Have we enough room for this word on a line ? - bool roomForThisWord = (numWordsInLine > 0) || ( (newLineWidth - lineWidth) < (float) nMaxWidth ); + bool roomForThisWord = (numWordsInLine > 0) || ( (newLineWidth - lineWidth) < nMaxWidth ); // not enough room for that word // If it is the only word of the line, just split it @@ -1927,7 +1927,7 @@ namespace NLGUI word.build(wordValue, *TextContext, numSpaces); word.Format= wordFormat; _Lines.push_back(TLineSPtr(new CLine)); - float roomForSpaces = (float) nMaxWidth - word.Info.StringWidth; + float roomForSpaces = nMaxWidth - word.Info.StringWidth; if (expandSpaces && numSpaces != 0) { _Lines.back()->setSpaceWidth(roomForSpaces / (float) numSpaces); From 0e4048661c0dbcce8744d6dcc7c5807d2606fec3 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 11 Feb 2019 12:45:37 +0200 Subject: [PATCH 186/303] Fixed: Copy to clipboard mangles utf8 chars --HG-- branch : develop --- code/nel/src/gui/action_handler.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/nel/src/gui/action_handler.cpp b/code/nel/src/gui/action_handler.cpp index 2d2246937..e4809c00f 100644 --- a/code/nel/src/gui/action_handler.cpp +++ b/code/nel/src/gui/action_handler.cpp @@ -748,8 +748,12 @@ namespace NLGUI { virtual void execute (CCtrlBase *pCaller, const std::string ¶ms) { - if (!CViewRenderer::getInstance()->getDriver()->copyTextToClipboard(params)) + ucstring s; + s.fromUtf8(params); + if (!CViewRenderer::getInstance()->getDriver()->copyTextToClipboard(s)) + { nlwarning("Copy to clipboard failed: '%s'", params.c_str()); + } } }; REGISTER_ACTION_HANDLER(CAHCopyToClipboard, "copy_to_clipboard"); From 838dd14d15fa8d2682da9b7c0daa8dac7ef4e243 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 11 Feb 2019 14:32:13 +0200 Subject: [PATCH 187/303] Changed: Use popup menu for chat-copy function --HG-- branch : develop --- code/nel/include/nel/gui/group_paragraph.h | 7 +++ code/nel/src/gui/group_paragraph.cpp | 6 ++- .../gamedev/interfaces_v3/interaction.xml | 9 ++++ .../src/interface_v3/chat_text_manager.cpp | 43 ++++++++++++++++++- 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/code/nel/include/nel/gui/group_paragraph.h b/code/nel/include/nel/gui/group_paragraph.h index 0004850fa..02f948582 100644 --- a/code/nel/include/nel/gui/group_paragraph.h +++ b/code/nel/include/nel/gui/group_paragraph.h @@ -206,6 +206,11 @@ namespace NLGUI invalidateContent(); } + /// temporarily enable mouse over effect + // will be automatically disabled when mouse leaves element + void enableTempOver() { _TempOver = true; } + void disableTempOver() { _TempOver = false; } + /// \from CInterfaceElement void onInvalidateContent(); sint32 getMaxUsedW() const; @@ -233,6 +238,8 @@ namespace NLGUI // Do we have a color under the element pointed by the mouse bool _Over; + // Temporarily force mouse over effect. Deactivated when mouse moves away + bool _TempOver; // If over is true so we have a color NLMISC::CRGBA _OverColor; diff --git a/code/nel/src/gui/group_paragraph.cpp b/code/nel/src/gui/group_paragraph.cpp index d7d50af2e..63ebc967d 100644 --- a/code/nel/src/gui/group_paragraph.cpp +++ b/code/nel/src/gui/group_paragraph.cpp @@ -52,6 +52,7 @@ namespace NLGUI _MinW= 0; _MinH= 0; _Over = false; + _TempOver = false; _OverColor = CRGBA(255,255,255,32); _OverElt = -1; _LastW = 0; @@ -967,7 +968,7 @@ namespace NLGUI // TEMP TEMP //CViewRenderer &rVR = *CViewRenderer::getInstance(); //rVR.drawRotFlipBitmap _RenderLayer, (_XReal, _YReal, _WReal, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(0,255,0,255) ); - if (_Over) + if (_Over || _TempOver) { CViewRenderer &rVR = *CViewRenderer::getInstance(); @@ -1052,7 +1053,10 @@ namespace NLGUI _OverElt = -1; if (!isIn(eventDesc.getX(), eventDesc.getY())) + { + _TempOver = false; return false; + } for (uint32 i = 0; i < _Elements.size(); ++i) if (_Elements[i].Element->getActive()) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/interaction.xml b/code/ryzom/client/data/gamedev/interfaces_v3/interaction.xml index 90432bcff..ef30966ee 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/interaction.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/interaction.xml @@ -3173,4 +3173,13 @@ params="game:chatUrlBrowse()" /> + + + + diff --git a/code/ryzom/client/src/interface_v3/chat_text_manager.cpp b/code/ryzom/client/src/interface_v3/chat_text_manager.cpp index ae76eefcb..51179cf29 100644 --- a/code/ryzom/client/src/interface_v3/chat_text_manager.cpp +++ b/code/ryzom/client/src/interface_v3/chat_text_manager.cpp @@ -28,6 +28,9 @@ using namespace NLMISC; CChatTextManager* CChatTextManager::_Instance = NULL; +// last selected chat from 'copy_chat_popup' action handler +static std::string LastSelectedChat; + //================================================================================= CChatTextManager::CChatTextManager() : _TextFontSize(NULL), @@ -403,7 +406,7 @@ CViewBase *CChatTextManager::createMsgTextComplex(const ucstring &msg, NLMISC::C para->setResizeFromChildH(true); // use right click because left click might be used to activate chat window - para->setRightClickHandler("copy_to_clipboard"); + para->setRightClickHandler("copy_chat_popup"); para->setRightClickHandlerParams(msg.toUtf8()); if (plaintext) @@ -526,3 +529,41 @@ void CChatTextManager::reset () _TextShadowed = NULL; _ShowTimestamps = NULL; } + +// *************************************************************************** +// Called when we right click on a chat line +class CHandlerCopyChatPopup: public IActionHandler +{ +public: + virtual void execute(CCtrlBase *pCaller, const string ¶ms ) + { + if (pCaller == NULL) return; + + LastSelectedChat = params; + + CGroupParagraph *pGP = dynamic_cast(pCaller); + if (pGP) pGP->enableTempOver(); + + CWidgetManager::getInstance()->enableModalWindow (pCaller, "ui:interface:chat_copy_action_menu"); + } +}; +REGISTER_ACTION_HANDLER( CHandlerCopyChatPopup, "copy_chat_popup"); + +// *************************************************************************** +// Called when we right click on a chat line and choose 'copy' from context menu +class CHandlerCopyChat: public IActionHandler +{ +public: + virtual void execute(CCtrlBase *pCaller, const string ¶ms ) + { + if (pCaller == NULL) return; + + CGroupParagraph *pGP = dynamic_cast(pCaller); + if (pGP) pGP->disableTempOver(); + + CAHManager::getInstance()->runActionHandler("copy_to_clipboard", NULL, LastSelectedChat); + CWidgetManager::getInstance()->disableModalWindow(); + } +}; +REGISTER_ACTION_HANDLER( CHandlerCopyChat, "copy_chat"); + From 3a5bb966a85909418968f68473786cd9958e3b17 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Wed, 13 Feb 2019 14:52:07 +0200 Subject: [PATCH 188/303] Fixed: ffmpeg deocde getLength function was placeholder --HG-- branch : develop --- code/nel/src/sound/audio_decoder_ffmpeg.cpp | 26 +++++++++------------ 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/code/nel/src/sound/audio_decoder_ffmpeg.cpp b/code/nel/src/sound/audio_decoder_ffmpeg.cpp index dea8368d2..158c0ddc3 100644 --- a/code/nel/src/sound/audio_decoder_ffmpeg.cpp +++ b/code/nel/src/sound/audio_decoder_ffmpeg.cpp @@ -287,18 +287,7 @@ bool CAudioDecoderFfmpeg::getInfo(NLMISC::IStream *stream, std::string &artist, } } - if (ffmpeg._FormatContext->duration != AV_NOPTS_VALUE) - { - length = ffmpeg._FormatContext->duration * av_q2d(AV_TIME_BASE_Q); - } - else if (ffmpeg._FormatContext->streams[ffmpeg._AudioStreamIndex]->duration != AV_NOPTS_VALUE) - { - length = ffmpeg._FormatContext->streams[ffmpeg._AudioStreamIndex]->duration * av_q2d(ffmpeg._FormatContext->streams[ffmpeg._AudioStreamIndex]->time_base); - } - else - { - length = 0.f; - } + length = ffmpeg.getLength(); return true; } @@ -420,9 +409,16 @@ bool CAudioDecoderFfmpeg::isMusicEnded() float CAudioDecoderFfmpeg::getLength() { - printf(">> CAudioDecoderFfmpeg::getLength\n"); - // TODO: return (float)ov_time_total(&_OggVorbisFile, -1); - return 0.f; + float length = 0.f; + if (_FormatContext->duration != AV_NOPTS_VALUE) + { + length = _FormatContext->duration * av_q2d(AV_TIME_BASE_Q); + } + else if (_FormatContext->streams[_AudioStreamIndex]->duration != AV_NOPTS_VALUE) + { + length = _FormatContext->streams[_AudioStreamIndex]->duration * av_q2d(_FormatContext->streams[_AudioStreamIndex]->time_base); + } + return length; } void CAudioDecoderFfmpeg::setLooping(bool loop) From 4a31913c60eba1284e0aabd2b4ba4e0309136260 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 14 Feb 2019 16:04:07 +0200 Subject: [PATCH 189/303] Changed: Target command to support keyword search. --HG-- branch : develop --- .../data/gamedev/interfaces_v3/commands.xml | 14 +-- code/ryzom/client/src/entities.cpp | 56 +++++++++ code/ryzom/client/src/entities.h | 6 + .../src/interface_v3/action_handler_game.cpp | 112 +++++++++--------- 4 files changed, 120 insertions(+), 68 deletions(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml b/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml index 13356083c..e236e43c8 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml @@ -78,17 +78,11 @@ - - + + - - - - - - - - + + diff --git a/code/ryzom/client/src/entities.cpp b/code/ryzom/client/src/entities.cpp index 7d16e51dc..495471da1 100644 --- a/code/ryzom/client/src/entities.cpp +++ b/code/ryzom/client/src/entities.cpp @@ -2334,7 +2334,63 @@ CEntityCL *CEntityManager::getEntityByName (uint32 stringId) const } //----------------------------------------------- +CEntityCL *CEntityManager::getEntityByKeywords (const std::vector &keywords, bool onlySelectable) const +{ + if (keywords.empty()) return NULL; + std::vector lcKeywords; + lcKeywords.resize(keywords.size()); + for(uint k = 0; k < keywords.size(); k++) + { + lcKeywords[k] = toLower(keywords[k]); + } + + const NLMISC::CVectorD &userPosD = UserEntity->pos(); + const uint count = (uint)_Entities.size(); + uint selectedEntityId = 0; + float selectedEntityDist = FLT_MAX; + for(uint i = 0; i < count; ++i) + { + if (!_Entities[i]) continue; + + if (onlySelectable && !_Entities[i]->properties().selectable()) continue; + + ucstring lcName; + lcName = toLower(_Entities[i]->getDisplayName()); + if (lcName.empty()) continue; + + bool match = true; + for (uint k = 0; k < lcKeywords.size(); ++k) + { + if (lcName.find(lcKeywords[k]) == ucstring::npos) + { + match = false; + break; + } + } + + if (match) + { + const NLMISC::CVectorD &targetPosD = _Entities[i]->pos(); + + float deltaX = (float) targetPosD.x - (float) userPosD.x; + float deltaY = (float) targetPosD.y - (float) userPosD.y; + float dist = (float)sqrt(deltaX * deltaX + deltaY * deltaY); + if (dist < selectedEntityDist) + { + selectedEntityDist = dist; + selectedEntityId = i; + } + } + } + + if (selectedEntityDist != FLT_MAX) + return _Entities[selectedEntityId]; + else + return NULL; +} + +//----------------------------------------------- CEntityCL *CEntityManager::getEntityByName (const ucstring &name, bool caseSensitive, bool complete) const { ucstring source = name; diff --git a/code/ryzom/client/src/entities.h b/code/ryzom/client/src/entities.h index fb8504fc1..1151a367d 100644 --- a/code/ryzom/client/src/entities.h +++ b/code/ryzom/client/src/entities.h @@ -302,6 +302,12 @@ public: * \param complete : if true, the name must match the full name of the entity. */ CEntityCL *getEntityByName (const ucstring &name, bool caseSensitive, bool complete) const; + /** + * Case insensitive match against entity name. All listed keywords must match. + * \param keywords to match + * \param onlySelectable : if true, match only entity that can be selected + */ + CEntityCL *getEntityByKeywords (const std::vector &keywords, bool onlySelectable) const; CEntityCL *getEntityBySheetName (const std::string &sheet) const; /// Get an entity by dataset index. Returns NULL if the entity is not found. CEntityCL *getEntityByCompressedIndex(TDataSetIndex compressedIndex) const; diff --git a/code/ryzom/client/src/interface_v3/action_handler_game.cpp b/code/ryzom/client/src/interface_v3/action_handler_game.cpp index c5faa16d9..2f91cb9a5 100644 --- a/code/ryzom/client/src/interface_v3/action_handler_game.cpp +++ b/code/ryzom/client/src/interface_v3/action_handler_game.cpp @@ -2416,70 +2416,66 @@ class CAHTarget : public IActionHandler { virtual void execute (CCtrlBase * /* pCaller */, const string &Params) { - // Get the entity name to target ucstring entityName; - entityName.fromUtf8 (getParam (Params, "entity")); - bool preferCompleteMatch = (getParam (Params, "prefer_complete_match") != "0"); + entityName.fromUtf8(getParam(Params, "entity")); + if (entityName.empty()) return; + + string completeMatch = getParam(Params, "prefer_complete_match"); bool quiet = (getParam (Params, "quiet") == "true"); - if (!entityName.empty()) + vector keywords; + NLMISC::splitUCString(entityName, ucstring(" "), keywords); + if (!keywords.empty() && keywords[0].size() > 0 && keywords[0][0] == (ucchar)'"') { - CEntityCL *entity = NULL; - if (preferCompleteMatch) - { - // Try to get the entity with complete match first - entity = EntitiesMngr.getEntityByName (entityName, false, true); - } - - if (entity == NULL) - { - // Get the entity with a partial match - entity = EntitiesMngr.getEntityByName (entityName, false, false); - } + // entity name is in quotes, do old style match with 'starts with' filter + // search for optional second parameter from old command for prefer_complete_match param + keywords.clear(); - if (entity == NULL) - { - //Get the entity with a sheetName - entity = EntitiesMngr.getEntityBySheetName(entityName.toUtf8()); - } - - if (entity) - { - CCharacterCL *character = dynamic_cast(entity); - if (character != NULL) - { - if(character->isSelectableBySpace()) - { - nldebug("isSelectableBySpace"); - } - else - { - nldebug("is not isSelectableBySpace"); - } - } - if(entity->properties().selectable()) - { - nldebug("is prop selectable"); - } - else - { - // to avoid campfire selection exploit #316 - nldebug("is not prop selectable"); - CInterfaceManager *pIM= CInterfaceManager::getInstance(); - if(!quiet) - pIM->displaySystemInfo(CI18N::get("uiTargetErrorCmd")); - return; - } + ucstring::size_type lastOf = entityName.rfind(ucstring("\"")); + if (lastOf == 0) + lastOf = ucstring::npos; - // Select the entity - UserEntity->selection(entity->slot()); - } - else - { - CInterfaceManager *pIM= CInterfaceManager::getInstance(); - if(!quiet) - pIM->displaySystemInfo(CI18N::get("uiTargetErrorCmd")); - } + // override the value only when there is no 'prefer_complete_match' parameter set + if (completeMatch.empty() && lastOf < entityName.size()) + completeMatch = trim(entityName.substr(lastOf+1).toUtf8()); + + entityName = entityName.substr(1, lastOf-1); + } + + // late check because only possible if doing 'starts-with' search + bool preferCompleteMatch = (completeMatch != "0"); + + CEntityCL *entity = NULL; + if (preferCompleteMatch) + { + // Try to get the entity with complete match first + entity = EntitiesMngr.getEntityByName (entityName, false, true); + } + + if (entity == NULL && !keywords.empty()) + { + entity = EntitiesMngr.getEntityByKeywords(keywords, true); + } + + if (entity == NULL) + { + // Get the entity with a partial match using 'starts with' search + entity = EntitiesMngr.getEntityByName(entityName, false, false); + } + + if (entity == NULL) + { + //Get the entity with a sheetName + entity = EntitiesMngr.getEntityBySheetName(entityName.toUtf8()); + } + + if (entity && entity->properties().selectable() && !entity->getDisplayName().empty()) + { + UserEntity->selection(entity->slot()); + } + else if (!quiet) + { + CInterfaceManager::getInstance()->displaySystemInfo(CI18N::get("uiTargetErrorCmd")); } } }; From 1e6027c9708a137d36142ae65164fbb9b4a5fd0a Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 18 Feb 2019 13:46:39 +0200 Subject: [PATCH 190/303] Added: mp3 decoder based dr_mp3 single file library --HG-- branch : develop --- .../nel/include/nel/sound/audio_decoder_mp3.h | 96 + code/nel/include/nel/sound/decoder/dr_mp3.h | 3566 +++++++++++++++++ code/nel/src/sound/CMakeLists.txt | 1 + code/nel/src/sound/audio_decoder.cpp | 19 + code/nel/src/sound/audio_decoder_mp3.cpp | 221 + 5 files changed, 3903 insertions(+) create mode 100644 code/nel/include/nel/sound/audio_decoder_mp3.h create mode 100644 code/nel/include/nel/sound/decoder/dr_mp3.h create mode 100644 code/nel/src/sound/audio_decoder_mp3.cpp diff --git a/code/nel/include/nel/sound/audio_decoder_mp3.h b/code/nel/include/nel/sound/audio_decoder_mp3.h new file mode 100644 index 000000000..fac2e2693 --- /dev/null +++ b/code/nel/include/nel/sound/audio_decoder_mp3.h @@ -0,0 +1,96 @@ +// NeL - MMORPG Framework +// Copyright (C) 2018 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef NLSOUND_AUDIO_DECODER_MP3_H +#define NLSOUND_AUDIO_DECODER_MP3_H +#include + +#include + +// disable drmp3_init_file() +#define DR_MP3_NO_STDIO +#include + +namespace NLSOUND { + +/** + * \brief CAudioDecoderMP3 + * \date 2019-01-13 12:39GMT + * \author Meelis Mägi (Nimetu) + * CAudioDecoderMP3 + * Create trough IAudioDecoder, type "mp3" + */ +class CAudioDecoderMP3 : public IAudioDecoder +{ +protected: + NLMISC::IStream *_Stream; + + bool _IsSupported; + bool _Loop; + bool _IsMusicEnded; + sint32 _StreamOffset; + sint32 _StreamSize; + + drmp3 _Decoder; + + // set to total pcm frames after getLength() is called + uint64 _PCMFrameCount; + +public: + CAudioDecoderMP3(NLMISC::IStream *stream, bool loop); + virtual ~CAudioDecoderMP3(); + + inline NLMISC::IStream *getStream() { return _Stream; } + inline sint32 getStreamSize() { return _StreamSize; } + inline sint32 getStreamOffset() { return _StreamOffset; } + + // Return true if mp3 is valid + bool isFormatSupported() const; + + /// Get information on a music file (only ID3v1 tag is read. + static bool getInfo(NLMISC::IStream *stream, std::string &artist, std::string &title, float &length); + + /// Get how many bytes the music buffer requires for output minimum. + virtual uint32 getRequiredBytes(); + + /// Get an amount of bytes between minimum and maximum (can be lower than minimum if at end). + virtual uint32 getNextBytes(uint8 *buffer, uint32 minimum, uint32 maximum); + + /// Get the amount of channels (2 is stereo) in output. + virtual uint8 getChannels(); + + /// Get the samples per second (often 44100) in output. + virtual uint getSamplesPerSec(); + + /// Get the bits per sample (often 16) in output. + virtual uint8 getBitsPerSample(); + + /// Get if the music has ended playing (never true if loop). + virtual bool isMusicEnded(); + + /// Get the total time in seconds. + virtual float getLength(); + + /// Set looping + virtual void setLooping(bool loop); + +}; /* class CAudioDecoderMP3 */ + +} /* namespace NLSOUND */ + +#endif // NLSOUND_AUDIO_DECODER_MP3_H + +/* end of file */ diff --git a/code/nel/include/nel/sound/decoder/dr_mp3.h b/code/nel/include/nel/sound/decoder/dr_mp3.h new file mode 100644 index 000000000..465438bf5 --- /dev/null +++ b/code/nel/include/nel/sound/decoder/dr_mp3.h @@ -0,0 +1,3566 @@ +// MP3 audio decoder. Public domain. See "unlicense" statement at the end of this file. +// dr_mp3 - v0.4.1 - 2018-12-30 +// +// David Reid - mackron@gmail.com +// +// Based off minimp3 (https://github.com/lieff/minimp3) which is where the real work was done. See the bottom of this file for +// differences between minimp3 and dr_mp3. + +// USAGE +// ===== +// dr_mp3 is a single-file library. To use it, do something like the following in one .c file. +// #define DR_MP3_IMPLEMENTATION +// #include "dr_mp3.h" +// +// You can then #include this file in other parts of the program as you would with any other header file. To decode audio data, +// do something like the following: +// +// drmp3 mp3; +// if (!drmp3_init_file(&mp3, "MySong.mp3", NULL)) { +// // Failed to open file +// } +// +// ... +// +// drmp3_uint64 framesRead = drmp3_read_pcm_frames_f32(pMP3, framesToRead, pFrames); +// +// The drmp3 object is transparent so you can get access to the channel count and sample rate like so: +// +// drmp3_uint32 channels = mp3.channels; +// drmp3_uint32 sampleRate = mp3.sampleRate; +// +// The third parameter of drmp3_init_file() in the example above allows you to control the output channel count and sample rate. It +// is a pointer to a drmp3_config object. Setting any of the variables of this object to 0 will cause dr_mp3 to use defaults. +// +// The example above initializes a decoder from a file, but you can also initialize it from a block of memory and read and seek +// callbacks with drmp3_init_memory() and drmp3_init() respectively. +// +// You do not need to do any annoying memory management when reading PCM frames - this is all managed internally. You can request +// any number of PCM frames in each call to drmp3_read_pcm_frames_f32() and it will return as many PCM frames as it can, up to the +// requested amount. +// +// You can also decode an entire file in one go with drmp3_open_and_read_f32(), drmp3_open_memory_and_read_f32() and +// drmp3_open_file_and_read_f32(). +// +// +// OPTIONS +// ======= +// #define these options before including this file. +// +// #define DR_MP3_NO_STDIO +// Disable drmp3_init_file(), etc. +// +// #define DR_MP3_NO_SIMD +// Disable SIMD optimizations. + +#ifndef dr_mp3_h +#define dr_mp3_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#if defined(_MSC_VER) && _MSC_VER < 1600 +typedef signed char drmp3_int8; +typedef unsigned char drmp3_uint8; +typedef signed short drmp3_int16; +typedef unsigned short drmp3_uint16; +typedef signed int drmp3_int32; +typedef unsigned int drmp3_uint32; +typedef signed __int64 drmp3_int64; +typedef unsigned __int64 drmp3_uint64; +#else +#include +typedef int8_t drmp3_int8; +typedef uint8_t drmp3_uint8; +typedef int16_t drmp3_int16; +typedef uint16_t drmp3_uint16; +typedef int32_t drmp3_int32; +typedef uint32_t drmp3_uint32; +typedef int64_t drmp3_int64; +typedef uint64_t drmp3_uint64; +#endif +typedef drmp3_uint8 drmp3_bool8; +typedef drmp3_uint32 drmp3_bool32; +#define DRMP3_TRUE 1 +#define DRMP3_FALSE 0 + +#define DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME 1152 +#define DRMP3_MAX_SAMPLES_PER_FRAME (DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME*2) + + +// Low Level Push API +// ================== +typedef struct +{ + int frame_bytes, channels, hz, layer, bitrate_kbps; +} drmp3dec_frame_info; + +typedef struct +{ + float mdct_overlap[2][9*32], qmf_state[15*2*32]; + int reserv, free_format_bytes; + unsigned char header[4], reserv_buf[511]; +} drmp3dec; + +// Initializes a low level decoder. +void drmp3dec_init(drmp3dec *dec); + +// Reads a frame from a low level decoder. +int drmp3dec_decode_frame(drmp3dec *dec, const unsigned char *mp3, int mp3_bytes, void *pcm, drmp3dec_frame_info *info); + +// Helper for converting between f32 and s16. +void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, int num_samples); + + + + +// Main API (Pull API) +// =================== + +typedef struct drmp3_src drmp3_src; +typedef drmp3_uint64 (* drmp3_src_read_proc)(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut, void* pUserData); // Returns the number of frames that were read. + +typedef enum +{ + drmp3_src_algorithm_none, + drmp3_src_algorithm_linear +} drmp3_src_algorithm; + +#define DRMP3_SRC_CACHE_SIZE_IN_FRAMES 512 +typedef struct +{ + drmp3_src* pSRC; + float pCachedFrames[2 * DRMP3_SRC_CACHE_SIZE_IN_FRAMES]; + drmp3_uint32 cachedFrameCount; + drmp3_uint32 iNextFrame; +} drmp3_src_cache; + +typedef struct +{ + drmp3_uint32 sampleRateIn; + drmp3_uint32 sampleRateOut; + drmp3_uint32 channels; + drmp3_src_algorithm algorithm; + drmp3_uint32 cacheSizeInFrames; // The number of frames to read from the client at a time. +} drmp3_src_config; + +struct drmp3_src +{ + drmp3_src_config config; + drmp3_src_read_proc onRead; + void* pUserData; + float bin[256]; + drmp3_src_cache cache; // <-- For simplifying and optimizing client -> memory reading. + union + { + struct + { + double alpha; + drmp3_bool32 isPrevFramesLoaded : 1; + drmp3_bool32 isNextFramesLoaded : 1; + } linear; + } algo; +}; + +typedef enum +{ + drmp3_seek_origin_start, + drmp3_seek_origin_current +} drmp3_seek_origin; + +typedef struct +{ + drmp3_uint64 seekPosInBytes; // Points to the first byte of an MP3 frame. + drmp3_uint64 pcmFrameIndex; // The index of the PCM frame this seek point targets. + drmp3_uint16 mp3FramesToDiscard; // The number of whole MP3 frames to be discarded before pcmFramesToDiscard. + drmp3_uint16 pcmFramesToDiscard; // The number of leading samples to read and discard. These are discarded after mp3FramesToDiscard. +} drmp3_seek_point; + +// Callback for when data is read. Return value is the number of bytes actually read. +// +// pUserData [in] The user data that was passed to drmp3_init(), drmp3_open() and family. +// pBufferOut [out] The output buffer. +// bytesToRead [in] The number of bytes to read. +// +// Returns the number of bytes actually read. +// +// A return value of less than bytesToRead indicates the end of the stream. Do _not_ return from this callback until +// either the entire bytesToRead is filled or you have reached the end of the stream. +typedef size_t (* drmp3_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead); + +// Callback for when data needs to be seeked. +// +// pUserData [in] The user data that was passed to drmp3_init(), drmp3_open() and family. +// offset [in] The number of bytes to move, relative to the origin. Will never be negative. +// origin [in] The origin of the seek - the current position or the start of the stream. +// +// Returns whether or not the seek was successful. +// +// Whether or not it is relative to the beginning or current position is determined by the "origin" parameter which +// will be either drmp3_seek_origin_start or drmp3_seek_origin_current. +typedef drmp3_bool32 (* drmp3_seek_proc)(void* pUserData, int offset, drmp3_seek_origin origin); + +typedef struct +{ + drmp3_uint32 outputChannels; + drmp3_uint32 outputSampleRate; +} drmp3_config; + +typedef struct +{ + drmp3dec decoder; + drmp3dec_frame_info frameInfo; + drmp3_uint32 channels; + drmp3_uint32 sampleRate; + drmp3_read_proc onRead; + drmp3_seek_proc onSeek; + void* pUserData; + drmp3_uint32 mp3FrameChannels; // The number of channels in the currently loaded MP3 frame. Internal use only. + drmp3_uint32 mp3FrameSampleRate; // The sample rate of the currently loaded MP3 frame. Internal use only. + drmp3_uint32 pcmFramesConsumedInMP3Frame; + drmp3_uint32 pcmFramesRemainingInMP3Frame; + drmp3_uint8 pcmFrames[sizeof(float)*DRMP3_MAX_SAMPLES_PER_FRAME]; // <-- Multipled by sizeof(float) to ensure there's enough room for DR_MP3_FLOAT_OUTPUT. + drmp3_uint64 currentPCMFrame; // The current PCM frame, globally, based on the output sample rate. Mainly used for seeking. + drmp3_uint64 streamCursor; // The current byte the decoder is sitting on in the raw stream. + drmp3_src src; + drmp3_seek_point* pSeekPoints; // NULL by default. Set with drmp3_bind_seek_table(). Memory is owned by the client. dr_mp3 will never attempt to free this pointer. + drmp3_uint32 seekPointCount; // The number of items in pSeekPoints. When set to 0 assumes to no seek table. Defaults to zero. + size_t dataSize; + size_t dataCapacity; + drmp3_uint8* pData; + drmp3_bool32 atEnd : 1; + struct + { + const drmp3_uint8* pData; + size_t dataSize; + size_t currentReadPos; + } memory; // Only used for decoders that were opened against a block of memory. +} drmp3; + +// Initializes an MP3 decoder. +// +// onRead [in] The function to call when data needs to be read from the client. +// onSeek [in] The function to call when the read position of the client data needs to move. +// pUserData [in, optional] A pointer to application defined data that will be passed to onRead and onSeek. +// +// Returns true if successful; false otherwise. +// +// Close the loader with drmp3_uninit(). +// +// See also: drmp3_init_file(), drmp3_init_memory(), drmp3_uninit() +drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_config* pConfig); + +// Initializes an MP3 decoder from a block of memory. +// +// This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for +// the lifetime of the drmp3 object. +// +// The buffer should contain the contents of the entire MP3 file. +drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_config* pConfig); + +#ifndef DR_MP3_NO_STDIO +// Initializes an MP3 decoder from a file. +// +// This holds the internal FILE object until drmp3_uninit() is called. Keep this in mind if you're caching drmp3 +// objects because the operating system may restrict the number of file handles an application can have open at +// any given time. +drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* filePath, const drmp3_config* pConfig); +#endif + +// Uninitializes an MP3 decoder. +void drmp3_uninit(drmp3* pMP3); + +// Reads PCM frames as interleaved 32-bit IEEE floating point PCM. +// +// Note that framesToRead specifies the number of PCM frames to read, _not_ the number of MP3 frames. +drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 framesToRead, float* pBufferOut); + +// Seeks to a specific frame. +// +// Note that this is _not_ an MP3 frame, but rather a PCM frame. +drmp3_bool32 drmp3_seek_to_pcm_frame(drmp3* pMP3, drmp3_uint64 frameIndex); + +// Calculates the total number of PCM frames in the MP3 stream. Cannot be used for infinite streams such as internet +// radio. Runs in linear time. Returns 0 on error. +drmp3_uint64 drmp3_get_pcm_frame_count(drmp3* pMP3); + +// Calculates the total number of MP3 frames in the MP3 stream. Cannot be used for infinite streams such as internet +// radio. Runs in linear time. Returns 0 on error. +drmp3_uint64 drmp3_get_mp3_frame_count(drmp3* pMP3); + +// Calculates the seekpoints based on PCM frames. This is slow. +// +// pSeekpoint count is a pointer to a uint32 containing the seekpoint count. On input it contains the desired count. +// On output it contains the actual count. The reason for this design is that the client may request too many +// seekpoints, in which case dr_mp3 will return a corrected count. +// +// Note that seektable seeking is not quite sample exact when the MP3 stream contains inconsistent sample rates. +drmp3_bool32 drmp3_calculate_seek_points(drmp3* pMP3, drmp3_uint32* pSeekPointCount, drmp3_seek_point* pSeekPoints); + +// Binds a seek table to the decoder. +// +// This does _not_ make a copy of pSeekPoints - it only references it. It is up to the application to ensure this +// remains valid while it is bound to the decoder. +// +// Use drmp3_calculate_seek_points() to calculate the seek points. +drmp3_bool32 drmp3_bind_seek_table(drmp3* pMP3, drmp3_uint32 seekPointCount, drmp3_seek_point* pSeekPoints); + + + +// Opens an decodes an entire MP3 stream as a single operation. +// +// pConfig is both an input and output. On input it contains what you want. On output it contains what you got. +// +// Free the returned pointer with drmp3_free(). +float* drmp3_open_and_read_f32(drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount); +float* drmp3_open_memory_and_read_f32(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount); +#ifndef DR_MP3_NO_STDIO +float* drmp3_open_file_and_read_f32(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount); +#endif + +// Frees any memory that was allocated by a public drmp3 API. +void drmp3_free(void* p); + +#ifdef __cplusplus +} +#endif +#endif // dr_mp3_h + + +///////////////////////////////////////////////////// +// +// IMPLEMENTATION +// +///////////////////////////////////////////////////// +#ifdef DR_MP3_IMPLEMENTATION +#include +#include +#include +#include // For INT_MAX + +// Disable SIMD when compiling with TCC for now. +#if defined(__TINYC__) +#define DR_MP3_NO_SIMD +#endif + +#define DRMP3_OFFSET_PTR(p, offset) ((void*)((drmp3_uint8*)(p) + (offset))) + +#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */ +#ifndef DRMP3_MAX_FRAME_SYNC_MATCHES +#define DRMP3_MAX_FRAME_SYNC_MATCHES 10 +#endif + +#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */ + +#define DRMP3_MAX_BITRESERVOIR_BYTES 511 +#define DRMP3_SHORT_BLOCK_TYPE 2 +#define DRMP3_STOP_BLOCK_TYPE 3 +#define DRMP3_MODE_MONO 3 +#define DRMP3_MODE_JOINT_STEREO 1 +#define DRMP3_HDR_SIZE 4 +#define DRMP3_HDR_IS_MONO(h) (((h[3]) & 0xC0) == 0xC0) +#define DRMP3_HDR_IS_MS_STEREO(h) (((h[3]) & 0xE0) == 0x60) +#define DRMP3_HDR_IS_FREE_FORMAT(h) (((h[2]) & 0xF0) == 0) +#define DRMP3_HDR_IS_CRC(h) (!((h[1]) & 1)) +#define DRMP3_HDR_TEST_PADDING(h) ((h[2]) & 0x2) +#define DRMP3_HDR_TEST_MPEG1(h) ((h[1]) & 0x8) +#define DRMP3_HDR_TEST_NOT_MPEG25(h) ((h[1]) & 0x10) +#define DRMP3_HDR_TEST_I_STEREO(h) ((h[3]) & 0x10) +#define DRMP3_HDR_TEST_MS_STEREO(h) ((h[3]) & 0x20) +#define DRMP3_HDR_GET_STEREO_MODE(h) (((h[3]) >> 6) & 3) +#define DRMP3_HDR_GET_STEREO_MODE_EXT(h) (((h[3]) >> 4) & 3) +#define DRMP3_HDR_GET_LAYER(h) (((h[1]) >> 1) & 3) +#define DRMP3_HDR_GET_BITRATE(h) ((h[2]) >> 4) +#define DRMP3_HDR_GET_SAMPLE_RATE(h) (((h[2]) >> 2) & 3) +#define DRMP3_HDR_GET_MY_SAMPLE_RATE(h) (DRMP3_HDR_GET_SAMPLE_RATE(h) + (((h[1] >> 3) & 1) + ((h[1] >> 4) & 1))*3) +#define DRMP3_HDR_IS_FRAME_576(h) ((h[1] & 14) == 2) +#define DRMP3_HDR_IS_LAYER_1(h) ((h[1] & 6) == 6) + +#define DRMP3_BITS_DEQUANTIZER_OUT -1 +#define DRMP3_MAX_SCF (255 + DRMP3_BITS_DEQUANTIZER_OUT*4 - 210) +#define DRMP3_MAX_SCFI ((DRMP3_MAX_SCF + 3) & ~3) + +#define DRMP3_MIN(a, b) ((a) > (b) ? (b) : (a)) +#define DRMP3_MAX(a, b) ((a) < (b) ? (b) : (a)) + +#if !defined(DR_MP3_NO_SIMD) + +#if !defined(DR_MP3_ONLY_SIMD) && (defined(_M_X64) || defined(_M_ARM64) || defined(__x86_64__) || defined(__aarch64__)) +/* x64 always have SSE2, arm64 always have neon, no need for generic code */ +#define DR_MP3_ONLY_SIMD +#endif + +#if (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))) || ((defined(__i386__) || defined(__x86_64__)) && defined(__SSE2__)) +#if defined(_MSC_VER) +#include +#endif +#include +#define DRMP3_HAVE_SSE 1 +#define DRMP3_HAVE_SIMD 1 +#define DRMP3_VSTORE _mm_storeu_ps +#define DRMP3_VLD _mm_loadu_ps +#define DRMP3_VSET _mm_set1_ps +#define DRMP3_VADD _mm_add_ps +#define DRMP3_VSUB _mm_sub_ps +#define DRMP3_VMUL _mm_mul_ps +#define DRMP3_VMAC(a, x, y) _mm_add_ps(a, _mm_mul_ps(x, y)) +#define DRMP3_VMSB(a, x, y) _mm_sub_ps(a, _mm_mul_ps(x, y)) +#define DRMP3_VMUL_S(x, s) _mm_mul_ps(x, _mm_set1_ps(s)) +#define DRMP3_VREV(x) _mm_shuffle_ps(x, x, _MM_SHUFFLE(0, 1, 2, 3)) +typedef __m128 drmp3_f4; +#if defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD) +#define drmp3_cpuid __cpuid +#else +static __inline__ __attribute__((always_inline)) void drmp3_cpuid(int CPUInfo[], const int InfoType) +{ +#if defined(__PIC__) + __asm__ __volatile__( +#if defined(__x86_64__) + "push %%rbx\n" + "cpuid\n" + "xchgl %%ebx, %1\n" + "pop %%rbx\n" +#else + "xchgl %%ebx, %1\n" + "cpuid\n" + "xchgl %%ebx, %1\n" +#endif + : "=a" (CPUInfo[0]), "=r" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3]) + : "a" (InfoType)); +#else + __asm__ __volatile__( + "cpuid" + : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3]) + : "a" (InfoType)); +#endif +} +#endif +static int drmp3_have_simd() +{ +#ifdef DR_MP3_ONLY_SIMD + return 1; +#else + static int g_have_simd; + int CPUInfo[4]; +#ifdef MINIMP3_TEST + static int g_counter; + if (g_counter++ > 100) + return 0; +#endif + if (g_have_simd) + goto end; + drmp3_cpuid(CPUInfo, 0); + if (CPUInfo[0] > 0) + { + drmp3_cpuid(CPUInfo, 1); + g_have_simd = (CPUInfo[3] & (1 << 26)) + 1; /* SSE2 */ + return g_have_simd - 1; + } + +end: + return g_have_simd - 1; +#endif +} +#elif defined(__ARM_NEON) || defined(__aarch64__) +#include +#define DRMP3_HAVE_SIMD 1 +#define DRMP3_VSTORE vst1q_f32 +#define DRMP3_VLD vld1q_f32 +#define DRMP3_VSET vmovq_n_f32 +#define DRMP3_VADD vaddq_f32 +#define DRMP3_VSUB vsubq_f32 +#define DRMP3_VMUL vmulq_f32 +#define DRMP3_VMAC(a, x, y) vmlaq_f32(a, x, y) +#define DRMP3_VMSB(a, x, y) vmlsq_f32(a, x, y) +#define DRMP3_VMUL_S(x, s) vmulq_f32(x, vmovq_n_f32(s)) +#define DRMP3_VREV(x) vcombine_f32(vget_high_f32(vrev64q_f32(x)), vget_low_f32(vrev64q_f32(x))) +typedef float32x4_t drmp3_f4; +static int drmp3_have_simd() +{ /* TODO: detect neon for !DR_MP3_ONLY_SIMD */ + return 1; +} +#else +#define DRMP3_HAVE_SIMD 0 +#ifdef DR_MP3_ONLY_SIMD +#error DR_MP3_ONLY_SIMD used, but SSE/NEON not enabled +#endif +#endif + +#else + +#define DRMP3_HAVE_SIMD 0 + +#endif + +typedef struct +{ + const drmp3_uint8 *buf; + int pos, limit; +} drmp3_bs; + +typedef struct +{ + float scf[3*64]; + drmp3_uint8 total_bands, stereo_bands, bitalloc[64], scfcod[64]; +} drmp3_L12_scale_info; + +typedef struct +{ + drmp3_uint8 tab_offset, code_tab_width, band_count; +} drmp3_L12_subband_alloc; + +typedef struct +{ + const drmp3_uint8 *sfbtab; + drmp3_uint16 part_23_length, big_values, scalefac_compress; + drmp3_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb; + drmp3_uint8 table_select[3], region_count[3], subblock_gain[3]; + drmp3_uint8 preflag, scalefac_scale, count1_table, scfsi; +} drmp3_L3_gr_info; + +typedef struct +{ + drmp3_bs bs; + drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES]; + drmp3_L3_gr_info gr_info[4]; + float grbuf[2][576], scf[40], syn[18 + 15][2*32]; + drmp3_uint8 ist_pos[2][39]; +} drmp3dec_scratch; + +static void drmp3_bs_init(drmp3_bs *bs, const drmp3_uint8 *data, int bytes) +{ + bs->buf = data; + bs->pos = 0; + bs->limit = bytes*8; +} + +static drmp3_uint32 drmp3_bs_get_bits(drmp3_bs *bs, int n) +{ + drmp3_uint32 next, cache = 0, s = bs->pos & 7; + int shl = n + s; + const drmp3_uint8 *p = bs->buf + (bs->pos >> 3); + if ((bs->pos += n) > bs->limit) + return 0; + next = *p++ & (255 >> s); + while ((shl -= 8) > 0) + { + cache |= next << shl; + next = *p++; + } + return cache | (next >> -shl); +} + +static int drmp3_hdr_valid(const drmp3_uint8 *h) +{ + return h[0] == 0xff && + ((h[1] & 0xF0) == 0xf0 || (h[1] & 0xFE) == 0xe2) && + (DRMP3_HDR_GET_LAYER(h) != 0) && + (DRMP3_HDR_GET_BITRATE(h) != 15) && + (DRMP3_HDR_GET_SAMPLE_RATE(h) != 3); +} + +static int drmp3_hdr_compare(const drmp3_uint8 *h1, const drmp3_uint8 *h2) +{ + return drmp3_hdr_valid(h2) && + ((h1[1] ^ h2[1]) & 0xFE) == 0 && + ((h1[2] ^ h2[2]) & 0x0C) == 0 && + !(DRMP3_HDR_IS_FREE_FORMAT(h1) ^ DRMP3_HDR_IS_FREE_FORMAT(h2)); +} + +static unsigned drmp3_hdr_bitrate_kbps(const drmp3_uint8 *h) +{ + static const drmp3_uint8 halfrate[2][3][15] = { + { { 0,4,8,12,16,20,24,28,32,40,48,56,64,72,80 }, { 0,4,8,12,16,20,24,28,32,40,48,56,64,72,80 }, { 0,16,24,28,32,40,48,56,64,72,80,88,96,112,128 } }, + { { 0,16,20,24,28,32,40,48,56,64,80,96,112,128,160 }, { 0,16,24,28,32,40,48,56,64,80,96,112,128,160,192 }, { 0,16,32,48,64,80,96,112,128,144,160,176,192,208,224 } }, + }; + return 2*halfrate[!!DRMP3_HDR_TEST_MPEG1(h)][DRMP3_HDR_GET_LAYER(h) - 1][DRMP3_HDR_GET_BITRATE(h)]; +} + +static unsigned drmp3_hdr_sample_rate_hz(const drmp3_uint8 *h) +{ + static const unsigned g_hz[3] = { 44100, 48000, 32000 }; + return g_hz[DRMP3_HDR_GET_SAMPLE_RATE(h)] >> (int)!DRMP3_HDR_TEST_MPEG1(h) >> (int)!DRMP3_HDR_TEST_NOT_MPEG25(h); +} + +static unsigned drmp3_hdr_frame_samples(const drmp3_uint8 *h) +{ + return DRMP3_HDR_IS_LAYER_1(h) ? 384 : (1152 >> (int)DRMP3_HDR_IS_FRAME_576(h)); +} + +static int drmp3_hdr_frame_bytes(const drmp3_uint8 *h, int free_format_size) +{ + int frame_bytes = drmp3_hdr_frame_samples(h)*drmp3_hdr_bitrate_kbps(h)*125/drmp3_hdr_sample_rate_hz(h); + if (DRMP3_HDR_IS_LAYER_1(h)) + { + frame_bytes &= ~3; /* slot align */ + } + return frame_bytes ? frame_bytes : free_format_size; +} + +static int drmp3_hdr_padding(const drmp3_uint8 *h) +{ + return DRMP3_HDR_TEST_PADDING(h) ? (DRMP3_HDR_IS_LAYER_1(h) ? 4 : 1) : 0; +} + +#ifndef DR_MP3_ONLY_MP3 +static const drmp3_L12_subband_alloc *drmp3_L12_subband_alloc_table(const drmp3_uint8 *hdr, drmp3_L12_scale_info *sci) +{ + const drmp3_L12_subband_alloc *alloc; + int mode = DRMP3_HDR_GET_STEREO_MODE(hdr); + int nbands, stereo_bands = (mode == DRMP3_MODE_MONO) ? 0 : (mode == DRMP3_MODE_JOINT_STEREO) ? (DRMP3_HDR_GET_STEREO_MODE_EXT(hdr) << 2) + 4 : 32; + + if (DRMP3_HDR_IS_LAYER_1(hdr)) + { + static const drmp3_L12_subband_alloc g_alloc_L1[] = { { 76, 4, 32 } }; + alloc = g_alloc_L1; + nbands = 32; + } else if (!DRMP3_HDR_TEST_MPEG1(hdr)) + { + static const drmp3_L12_subband_alloc g_alloc_L2M2[] = { { 60, 4, 4 }, { 44, 3, 7 }, { 44, 2, 19 } }; + alloc = g_alloc_L2M2; + nbands = 30; + } else + { + static const drmp3_L12_subband_alloc g_alloc_L2M1[] = { { 0, 4, 3 }, { 16, 4, 8 }, { 32, 3, 12 }, { 40, 2, 7 } }; + int sample_rate_idx = DRMP3_HDR_GET_SAMPLE_RATE(hdr); + unsigned kbps = drmp3_hdr_bitrate_kbps(hdr) >> (int)(mode != DRMP3_MODE_MONO); + if (!kbps) /* free-format */ + { + kbps = 192; + } + + alloc = g_alloc_L2M1; + nbands = 27; + if (kbps < 56) + { + static const drmp3_L12_subband_alloc g_alloc_L2M1_lowrate[] = { { 44, 4, 2 }, { 44, 3, 10 } }; + alloc = g_alloc_L2M1_lowrate; + nbands = sample_rate_idx == 2 ? 12 : 8; + } else if (kbps >= 96 && sample_rate_idx != 1) + { + nbands = 30; + } + } + + sci->total_bands = (drmp3_uint8)nbands; + sci->stereo_bands = (drmp3_uint8)DRMP3_MIN(stereo_bands, nbands); + + return alloc; +} + +static void drmp3_L12_read_scalefactors(drmp3_bs *bs, drmp3_uint8 *pba, drmp3_uint8 *scfcod, int bands, float *scf) +{ + static const float g_deq_L12[18*3] = { +#define DRMP3_DQ(x) 9.53674316e-07f/x, 7.56931807e-07f/x, 6.00777173e-07f/x + DRMP3_DQ(3),DRMP3_DQ(7),DRMP3_DQ(15),DRMP3_DQ(31),DRMP3_DQ(63),DRMP3_DQ(127),DRMP3_DQ(255),DRMP3_DQ(511),DRMP3_DQ(1023),DRMP3_DQ(2047),DRMP3_DQ(4095),DRMP3_DQ(8191),DRMP3_DQ(16383),DRMP3_DQ(32767),DRMP3_DQ(65535),DRMP3_DQ(3),DRMP3_DQ(5),DRMP3_DQ(9) + }; + int i, m; + for (i = 0; i < bands; i++) + { + float s = 0; + int ba = *pba++; + int mask = ba ? 4 + ((19 >> scfcod[i]) & 3) : 0; + for (m = 4; m; m >>= 1) + { + if (mask & m) + { + int b = drmp3_bs_get_bits(bs, 6); + s = g_deq_L12[ba*3 - 6 + b % 3]*(1 << 21 >> b/3); + } + *scf++ = s; + } + } +} + +static void drmp3_L12_read_scale_info(const drmp3_uint8 *hdr, drmp3_bs *bs, drmp3_L12_scale_info *sci) +{ + static const drmp3_uint8 g_bitalloc_code_tab[] = { + 0,17, 3, 4, 5,6,7, 8,9,10,11,12,13,14,15,16, + 0,17,18, 3,19,4,5, 6,7, 8, 9,10,11,12,13,16, + 0,17,18, 3,19,4,5,16, + 0,17,18,16, + 0,17,18,19, 4,5,6, 7,8, 9,10,11,12,13,14,15, + 0,17,18, 3,19,4,5, 6,7, 8, 9,10,11,12,13,14, + 0, 2, 3, 4, 5,6,7, 8,9,10,11,12,13,14,15,16 + }; + const drmp3_L12_subband_alloc *subband_alloc = drmp3_L12_subband_alloc_table(hdr, sci); + + int i, k = 0, ba_bits = 0; + const drmp3_uint8 *ba_code_tab = g_bitalloc_code_tab; + + for (i = 0; i < sci->total_bands; i++) + { + drmp3_uint8 ba; + if (i == k) + { + k += subband_alloc->band_count; + ba_bits = subband_alloc->code_tab_width; + ba_code_tab = g_bitalloc_code_tab + subband_alloc->tab_offset; + subband_alloc++; + } + ba = ba_code_tab[drmp3_bs_get_bits(bs, ba_bits)]; + sci->bitalloc[2*i] = ba; + if (i < sci->stereo_bands) + { + ba = ba_code_tab[drmp3_bs_get_bits(bs, ba_bits)]; + } + sci->bitalloc[2*i + 1] = sci->stereo_bands ? ba : 0; + } + + for (i = 0; i < 2*sci->total_bands; i++) + { + sci->scfcod[i] = (drmp3_uint8)(sci->bitalloc[i] ? DRMP3_HDR_IS_LAYER_1(hdr) ? 2 : drmp3_bs_get_bits(bs, 2) : 6); + } + + drmp3_L12_read_scalefactors(bs, sci->bitalloc, sci->scfcod, sci->total_bands*2, sci->scf); + + for (i = sci->stereo_bands; i < sci->total_bands; i++) + { + sci->bitalloc[2*i + 1] = 0; + } +} + +static int drmp3_L12_dequantize_granule(float *grbuf, drmp3_bs *bs, drmp3_L12_scale_info *sci, int group_size) +{ + int i, j, k, choff = 576; + for (j = 0; j < 4; j++) + { + float *dst = grbuf + group_size*j; + for (i = 0; i < 2*sci->total_bands; i++) + { + int ba = sci->bitalloc[i]; + if (ba != 0) + { + if (ba < 17) + { + int half = (1 << (ba - 1)) - 1; + for (k = 0; k < group_size; k++) + { + dst[k] = (float)((int)drmp3_bs_get_bits(bs, ba) - half); + } + } else + { + unsigned mod = (2 << (ba - 17)) + 1; /* 3, 5, 9 */ + unsigned code = drmp3_bs_get_bits(bs, mod + 2 - (mod >> 3)); /* 5, 7, 10 */ + for (k = 0; k < group_size; k++, code /= mod) + { + dst[k] = (float)((int)(code % mod - mod/2)); + } + } + } + dst += choff; + choff = 18 - choff; + } + } + return group_size*4; +} + +static void drmp3_L12_apply_scf_384(drmp3_L12_scale_info *sci, const float *scf, float *dst) +{ + int i, k; + memcpy(dst + 576 + sci->stereo_bands*18, dst + sci->stereo_bands*18, (sci->total_bands - sci->stereo_bands)*18*sizeof(float)); + for (i = 0; i < sci->total_bands; i++, dst += 18, scf += 6) + { + for (k = 0; k < 12; k++) + { + dst[k + 0] *= scf[0]; + dst[k + 576] *= scf[3]; + } + } +} +#endif + +static int drmp3_L3_read_side_info(drmp3_bs *bs, drmp3_L3_gr_info *gr, const drmp3_uint8 *hdr) +{ + static const drmp3_uint8 g_scf_long[8][23] = { + { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 }, + { 12,12,12,12,12,12,16,20,24,28,32,40,48,56,64,76,90,2,2,2,2,2,0 }, + { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 }, + { 6,6,6,6,6,6,8,10,12,14,16,18,22,26,32,38,46,54,62,70,76,36,0 }, + { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 }, + { 4,4,4,4,4,4,6,6,8,8,10,12,16,20,24,28,34,42,50,54,76,158,0 }, + { 4,4,4,4,4,4,6,6,6,8,10,12,16,18,22,28,34,40,46,54,54,192,0 }, + { 4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102,26,0 } + }; + static const drmp3_uint8 g_scf_short[8][40] = { + { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 }, + { 8,8,8,8,8,8,8,8,8,12,12,12,16,16,16,20,20,20,24,24,24,28,28,28,36,36,36,2,2,2,2,2,2,2,2,2,26,26,26,0 }, + { 4,4,4,4,4,4,4,4,4,6,6,6,6,6,6,8,8,8,10,10,10,14,14,14,18,18,18,26,26,26,32,32,32,42,42,42,18,18,18,0 }, + { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,32,32,32,44,44,44,12,12,12,0 }, + { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 }, + { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,22,22,22,30,30,30,56,56,56,0 }, + { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,6,6,6,10,10,10,12,12,12,14,14,14,16,16,16,20,20,20,26,26,26,66,66,66,0 }, + { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,12,12,12,16,16,16,20,20,20,26,26,26,34,34,34,42,42,42,12,12,12,0 } + }; + static const drmp3_uint8 g_scf_mixed[8][40] = { + { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 }, + { 12,12,12,4,4,4,8,8,8,12,12,12,16,16,16,20,20,20,24,24,24,28,28,28,36,36,36,2,2,2,2,2,2,2,2,2,26,26,26,0 }, + { 6,6,6,6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,14,14,14,18,18,18,26,26,26,32,32,32,42,42,42,18,18,18,0 }, + { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,32,32,32,44,44,44,12,12,12,0 }, + { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 }, + { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,22,22,22,30,30,30,56,56,56,0 }, + { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,6,6,6,10,10,10,12,12,12,14,14,14,16,16,16,20,20,20,26,26,26,66,66,66,0 }, + { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,8,8,8,12,12,12,16,16,16,20,20,20,26,26,26,34,34,34,42,42,42,12,12,12,0 } + }; + + unsigned tables, scfsi = 0; + int main_data_begin, part_23_sum = 0; + int sr_idx = DRMP3_HDR_GET_MY_SAMPLE_RATE(hdr); sr_idx -= (sr_idx != 0); + int gr_count = DRMP3_HDR_IS_MONO(hdr) ? 1 : 2; + + if (DRMP3_HDR_TEST_MPEG1(hdr)) + { + gr_count *= 2; + main_data_begin = drmp3_bs_get_bits(bs, 9); + scfsi = drmp3_bs_get_bits(bs, 7 + gr_count); + } else + { + main_data_begin = drmp3_bs_get_bits(bs, 8 + gr_count) >> gr_count; + } + + do + { + if (DRMP3_HDR_IS_MONO(hdr)) + { + scfsi <<= 4; + } + gr->part_23_length = (drmp3_uint16)drmp3_bs_get_bits(bs, 12); + part_23_sum += gr->part_23_length; + gr->big_values = (drmp3_uint16)drmp3_bs_get_bits(bs, 9); + if (gr->big_values > 288) + { + return -1; + } + gr->global_gain = (drmp3_uint8)drmp3_bs_get_bits(bs, 8); + gr->scalefac_compress = (drmp3_uint16)drmp3_bs_get_bits(bs, DRMP3_HDR_TEST_MPEG1(hdr) ? 4 : 9); + gr->sfbtab = g_scf_long[sr_idx]; + gr->n_long_sfb = 22; + gr->n_short_sfb = 0; + if (drmp3_bs_get_bits(bs, 1)) + { + gr->block_type = (drmp3_uint8)drmp3_bs_get_bits(bs, 2); + if (!gr->block_type) + { + return -1; + } + gr->mixed_block_flag = (drmp3_uint8)drmp3_bs_get_bits(bs, 1); + gr->region_count[0] = 7; + gr->region_count[1] = 255; + if (gr->block_type == DRMP3_SHORT_BLOCK_TYPE) + { + scfsi &= 0x0F0F; + if (!gr->mixed_block_flag) + { + gr->region_count[0] = 8; + gr->sfbtab = g_scf_short[sr_idx]; + gr->n_long_sfb = 0; + gr->n_short_sfb = 39; + } else + { + gr->sfbtab = g_scf_mixed[sr_idx]; + gr->n_long_sfb = DRMP3_HDR_TEST_MPEG1(hdr) ? 8 : 6; + gr->n_short_sfb = 30; + } + } + tables = drmp3_bs_get_bits(bs, 10); + tables <<= 5; + gr->subblock_gain[0] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3); + gr->subblock_gain[1] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3); + gr->subblock_gain[2] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3); + } else + { + gr->block_type = 0; + gr->mixed_block_flag = 0; + tables = drmp3_bs_get_bits(bs, 15); + gr->region_count[0] = (drmp3_uint8)drmp3_bs_get_bits(bs, 4); + gr->region_count[1] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3); + gr->region_count[2] = 255; + } + gr->table_select[0] = (drmp3_uint8)(tables >> 10); + gr->table_select[1] = (drmp3_uint8)((tables >> 5) & 31); + gr->table_select[2] = (drmp3_uint8)((tables) & 31); + gr->preflag = (drmp3_uint8)(DRMP3_HDR_TEST_MPEG1(hdr) ? drmp3_bs_get_bits(bs, 1) : (gr->scalefac_compress >= 500)); + gr->scalefac_scale = (drmp3_uint8)drmp3_bs_get_bits(bs, 1); + gr->count1_table = (drmp3_uint8)drmp3_bs_get_bits(bs, 1); + gr->scfsi = (drmp3_uint8)((scfsi >> 12) & 15); + scfsi <<= 4; + gr++; + } while(--gr_count); + + if (part_23_sum + bs->pos > bs->limit + main_data_begin*8) + { + return -1; + } + + return main_data_begin; +} + +static void drmp3_L3_read_scalefactors(drmp3_uint8 *scf, drmp3_uint8 *ist_pos, const drmp3_uint8 *scf_size, const drmp3_uint8 *scf_count, drmp3_bs *bitbuf, int scfsi) +{ + int i, k; + for (i = 0; i < 4 && scf_count[i]; i++, scfsi *= 2) + { + int cnt = scf_count[i]; + if (scfsi & 8) + { + memcpy(scf, ist_pos, cnt); + } else + { + int bits = scf_size[i]; + if (!bits) + { + memset(scf, 0, cnt); + memset(ist_pos, 0, cnt); + } else + { + int max_scf = (scfsi < 0) ? (1 << bits) - 1 : -1; + for (k = 0; k < cnt; k++) + { + int s = drmp3_bs_get_bits(bitbuf, bits); + ist_pos[k] = (drmp3_uint8)(s == max_scf ? -1 : s); + scf[k] = (drmp3_uint8)s; + } + } + } + ist_pos += cnt; + scf += cnt; + } + scf[0] = scf[1] = scf[2] = 0; +} + +static float drmp3_L3_ldexp_q2(float y, int exp_q2) +{ + static const float g_expfrac[4] = { 9.31322575e-10f,7.83145814e-10f,6.58544508e-10f,5.53767716e-10f }; + int e; + do + { + e = DRMP3_MIN(30*4, exp_q2); + y *= g_expfrac[e & 3]*(1 << 30 >> (e >> 2)); + } while ((exp_q2 -= e) > 0); + return y; +} + +static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *ist_pos, drmp3_bs *bs, const drmp3_L3_gr_info *gr, float *scf, int ch) +{ + static const drmp3_uint8 g_scf_partitions[3][28] = { + { 6,5,5, 5,6,5,5,5,6,5, 7,3,11,10,0,0, 7, 7, 7,0, 6, 6,6,3, 8, 8,5,0 }, + { 8,9,6,12,6,9,9,9,6,9,12,6,15,18,0,0, 6,15,12,0, 6,12,9,6, 6,18,9,0 }, + { 9,9,6,12,9,9,9,9,9,9,12,6,18,18,0,0,12,12,12,0,12, 9,9,6,15,12,9,0 } + }; + const drmp3_uint8 *scf_partition = g_scf_partitions[!!gr->n_short_sfb + !gr->n_long_sfb]; + drmp3_uint8 scf_size[4], iscf[40]; + int i, scf_shift = gr->scalefac_scale + 1, gain_exp, scfsi = gr->scfsi; + float gain; + + if (DRMP3_HDR_TEST_MPEG1(hdr)) + { + static const drmp3_uint8 g_scfc_decode[16] = { 0,1,2,3, 12,5,6,7, 9,10,11,13, 14,15,18,19 }; + int part = g_scfc_decode[gr->scalefac_compress]; + scf_size[1] = scf_size[0] = (drmp3_uint8)(part >> 2); + scf_size[3] = scf_size[2] = (drmp3_uint8)(part & 3); + } else + { + static const drmp3_uint8 g_mod[6*4] = { 5,5,4,4,5,5,4,1,4,3,1,1,5,6,6,1,4,4,4,1,4,3,1,1 }; + int k, modprod, sfc, ist = DRMP3_HDR_TEST_I_STEREO(hdr) && ch; + sfc = gr->scalefac_compress >> ist; + for (k = ist*3*4; sfc >= 0; sfc -= modprod, k += 4) + { + for (modprod = 1, i = 3; i >= 0; i--) + { + scf_size[i] = (drmp3_uint8)(sfc / modprod % g_mod[k + i]); + modprod *= g_mod[k + i]; + } + } + scf_partition += k; + scfsi = -16; + } + drmp3_L3_read_scalefactors(iscf, ist_pos, scf_size, scf_partition, bs, scfsi); + + if (gr->n_short_sfb) + { + int sh = 3 - scf_shift; + for (i = 0; i < gr->n_short_sfb; i += 3) + { + iscf[gr->n_long_sfb + i + 0] += gr->subblock_gain[0] << sh; + iscf[gr->n_long_sfb + i + 1] += gr->subblock_gain[1] << sh; + iscf[gr->n_long_sfb + i + 2] += gr->subblock_gain[2] << sh; + } + } else if (gr->preflag) + { + static const drmp3_uint8 g_preamp[10] = { 1,1,1,1,2,2,3,3,3,2 }; + for (i = 0; i < 10; i++) + { + iscf[11 + i] += g_preamp[i]; + } + } + + gain_exp = gr->global_gain + DRMP3_BITS_DEQUANTIZER_OUT*4 - 210 - (DRMP3_HDR_IS_MS_STEREO(hdr) ? 2 : 0); + gain = drmp3_L3_ldexp_q2(1 << (DRMP3_MAX_SCFI/4), DRMP3_MAX_SCFI - gain_exp); + for (i = 0; i < (int)(gr->n_long_sfb + gr->n_short_sfb); i++) + { + scf[i] = drmp3_L3_ldexp_q2(gain, iscf[i] << scf_shift); + } +} + +static const float g_drmp3_pow43[129 + 16] = { + 0,-1,-2.519842f,-4.326749f,-6.349604f,-8.549880f,-10.902724f,-13.390518f,-16.000000f,-18.720754f,-21.544347f,-24.463781f,-27.473142f,-30.567351f,-33.741992f,-36.993181f, + 0,1,2.519842f,4.326749f,6.349604f,8.549880f,10.902724f,13.390518f,16.000000f,18.720754f,21.544347f,24.463781f,27.473142f,30.567351f,33.741992f,36.993181f,40.317474f,43.711787f,47.173345f,50.699631f,54.288352f,57.937408f,61.644865f,65.408941f,69.227979f,73.100443f,77.024898f,81.000000f,85.024491f,89.097188f,93.216975f,97.382800f,101.593667f,105.848633f,110.146801f,114.487321f,118.869381f,123.292209f,127.755065f,132.257246f,136.798076f,141.376907f,145.993119f,150.646117f,155.335327f,160.060199f,164.820202f,169.614826f,174.443577f,179.305980f,184.201575f,189.129918f,194.090580f,199.083145f,204.107210f,209.162385f,214.248292f,219.364564f,224.510845f,229.686789f,234.892058f,240.126328f,245.389280f,250.680604f,256.000000f,261.347174f,266.721841f,272.123723f,277.552547f,283.008049f,288.489971f,293.998060f,299.532071f,305.091761f,310.676898f,316.287249f,321.922592f,327.582707f,333.267377f,338.976394f,344.709550f,350.466646f,356.247482f,362.051866f,367.879608f,373.730522f,379.604427f,385.501143f,391.420496f,397.362314f,403.326427f,409.312672f,415.320884f,421.350905f,427.402579f,433.475750f,439.570269f,445.685987f,451.822757f,457.980436f,464.158883f,470.357960f,476.577530f,482.817459f,489.077615f,495.357868f,501.658090f,507.978156f,514.317941f,520.677324f,527.056184f,533.454404f,539.871867f,546.308458f,552.764065f,559.238575f,565.731879f,572.243870f,578.774440f,585.323483f,591.890898f,598.476581f,605.080431f,611.702349f,618.342238f,625.000000f,631.675540f,638.368763f,645.079578f +}; + +static float drmp3_L3_pow_43(int x) +{ + float frac; + int sign, mult = 256; + + if (x < 129) + { + return g_drmp3_pow43[16 + x]; + } + + if (x < 1024) + { + mult = 16; + x <<= 3; + } + + sign = 2*x & 64; + frac = (float)((x & 63) - sign) / ((x & ~63) + sign); + return g_drmp3_pow43[16 + ((x + sign) >> 6)]*(1.f + frac*((4.f/3) + frac*(2.f/9)))*mult; +} + +static void drmp3_L3_huffman(float *dst, drmp3_bs *bs, const drmp3_L3_gr_info *gr_info, const float *scf, int layer3gr_limit) +{ + static const drmp3_int16 tabs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 785,785,785,785,784,784,784,784,513,513,513,513,513,513,513,513,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256, + -255,1313,1298,1282,785,785,785,785,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,290,288, + -255,1313,1298,1282,769,769,769,769,529,529,529,529,529,529,529,529,528,528,528,528,528,528,528,528,512,512,512,512,512,512,512,512,290,288, + -253,-318,-351,-367,785,785,785,785,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,819,818,547,547,275,275,275,275,561,560,515,546,289,274,288,258, + -254,-287,1329,1299,1314,1312,1057,1057,1042,1042,1026,1026,784,784,784,784,529,529,529,529,529,529,529,529,769,769,769,769,768,768,768,768,563,560,306,306,291,259, + -252,-413,-477,-542,1298,-575,1041,1041,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-383,-399,1107,1092,1106,1061,849,849,789,789,1104,1091,773,773,1076,1075,341,340,325,309,834,804,577,577,532,532,516,516,832,818,803,816,561,561,531,531,515,546,289,289,288,258, + -252,-429,-493,-559,1057,1057,1042,1042,529,529,529,529,529,529,529,529,784,784,784,784,769,769,769,769,512,512,512,512,512,512,512,512,-382,1077,-415,1106,1061,1104,849,849,789,789,1091,1076,1029,1075,834,834,597,581,340,340,339,324,804,833,532,532,832,772,818,803,817,787,816,771,290,290,290,290,288,258, + -253,-349,-414,-447,-463,1329,1299,-479,1314,1312,1057,1057,1042,1042,1026,1026,785,785,785,785,784,784,784,784,769,769,769,769,768,768,768,768,-319,851,821,-335,836,850,805,849,341,340,325,336,533,533,579,579,564,564,773,832,578,548,563,516,321,276,306,291,304,259, + -251,-572,-733,-830,-863,-879,1041,1041,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-511,-527,-543,1396,1351,1381,1366,1395,1335,1380,-559,1334,1138,1138,1063,1063,1350,1392,1031,1031,1062,1062,1364,1363,1120,1120,1333,1348,881,881,881,881,375,374,359,373,343,358,341,325,791,791,1123,1122,-703,1105,1045,-719,865,865,790,790,774,774,1104,1029,338,293,323,308,-799,-815,833,788,772,818,803,816,322,292,307,320,561,531,515,546,289,274,288,258, + -251,-525,-605,-685,-765,-831,-846,1298,1057,1057,1312,1282,785,785,785,785,784,784,784,784,769,769,769,769,512,512,512,512,512,512,512,512,1399,1398,1383,1367,1382,1396,1351,-511,1381,1366,1139,1139,1079,1079,1124,1124,1364,1349,1363,1333,882,882,882,882,807,807,807,807,1094,1094,1136,1136,373,341,535,535,881,775,867,822,774,-591,324,338,-671,849,550,550,866,864,609,609,293,336,534,534,789,835,773,-751,834,804,308,307,833,788,832,772,562,562,547,547,305,275,560,515,290,290, + -252,-397,-477,-557,-622,-653,-719,-735,-750,1329,1299,1314,1057,1057,1042,1042,1312,1282,1024,1024,785,785,785,785,784,784,784,784,769,769,769,769,-383,1127,1141,1111,1126,1140,1095,1110,869,869,883,883,1079,1109,882,882,375,374,807,868,838,881,791,-463,867,822,368,263,852,837,836,-543,610,610,550,550,352,336,534,534,865,774,851,821,850,805,593,533,579,564,773,832,578,578,548,548,577,577,307,276,306,291,516,560,259,259, + -250,-2107,-2507,-2764,-2909,-2974,-3007,-3023,1041,1041,1040,1040,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-767,-1052,-1213,-1277,-1358,-1405,-1469,-1535,-1550,-1582,-1614,-1647,-1662,-1694,-1726,-1759,-1774,-1807,-1822,-1854,-1886,1565,-1919,-1935,-1951,-1967,1731,1730,1580,1717,-1983,1729,1564,-1999,1548,-2015,-2031,1715,1595,-2047,1714,-2063,1610,-2079,1609,-2095,1323,1323,1457,1457,1307,1307,1712,1547,1641,1700,1699,1594,1685,1625,1442,1442,1322,1322,-780,-973,-910,1279,1278,1277,1262,1276,1261,1275,1215,1260,1229,-959,974,974,989,989,-943,735,478,478,495,463,506,414,-1039,1003,958,1017,927,942,987,957,431,476,1272,1167,1228,-1183,1256,-1199,895,895,941,941,1242,1227,1212,1135,1014,1014,490,489,503,487,910,1013,985,925,863,894,970,955,1012,847,-1343,831,755,755,984,909,428,366,754,559,-1391,752,486,457,924,997,698,698,983,893,740,740,908,877,739,739,667,667,953,938,497,287,271,271,683,606,590,712,726,574,302,302,738,736,481,286,526,725,605,711,636,724,696,651,589,681,666,710,364,467,573,695,466,466,301,465,379,379,709,604,665,679,316,316,634,633,436,436,464,269,424,394,452,332,438,363,347,408,393,448,331,422,362,407,392,421,346,406,391,376,375,359,1441,1306,-2367,1290,-2383,1337,-2399,-2415,1426,1321,-2431,1411,1336,-2447,-2463,-2479,1169,1169,1049,1049,1424,1289,1412,1352,1319,-2495,1154,1154,1064,1064,1153,1153,416,390,360,404,403,389,344,374,373,343,358,372,327,357,342,311,356,326,1395,1394,1137,1137,1047,1047,1365,1392,1287,1379,1334,1364,1349,1378,1318,1363,792,792,792,792,1152,1152,1032,1032,1121,1121,1046,1046,1120,1120,1030,1030,-2895,1106,1061,1104,849,849,789,789,1091,1076,1029,1090,1060,1075,833,833,309,324,532,532,832,772,818,803,561,561,531,560,515,546,289,274,288,258, + -250,-1179,-1579,-1836,-1996,-2124,-2253,-2333,-2413,-2477,-2542,-2574,-2607,-2622,-2655,1314,1313,1298,1312,1282,785,785,785,785,1040,1040,1025,1025,768,768,768,768,-766,-798,-830,-862,-895,-911,-927,-943,-959,-975,-991,-1007,-1023,-1039,-1055,-1070,1724,1647,-1103,-1119,1631,1767,1662,1738,1708,1723,-1135,1780,1615,1779,1599,1677,1646,1778,1583,-1151,1777,1567,1737,1692,1765,1722,1707,1630,1751,1661,1764,1614,1736,1676,1763,1750,1645,1598,1721,1691,1762,1706,1582,1761,1566,-1167,1749,1629,767,766,751,765,494,494,735,764,719,749,734,763,447,447,748,718,477,506,431,491,446,476,461,505,415,430,475,445,504,399,460,489,414,503,383,474,429,459,502,502,746,752,488,398,501,473,413,472,486,271,480,270,-1439,-1455,1357,-1471,-1487,-1503,1341,1325,-1519,1489,1463,1403,1309,-1535,1372,1448,1418,1476,1356,1462,1387,-1551,1475,1340,1447,1402,1386,-1567,1068,1068,1474,1461,455,380,468,440,395,425,410,454,364,467,466,464,453,269,409,448,268,432,1371,1473,1432,1417,1308,1460,1355,1446,1459,1431,1083,1083,1401,1416,1458,1445,1067,1067,1370,1457,1051,1051,1291,1430,1385,1444,1354,1415,1400,1443,1082,1082,1173,1113,1186,1066,1185,1050,-1967,1158,1128,1172,1097,1171,1081,-1983,1157,1112,416,266,375,400,1170,1142,1127,1065,793,793,1169,1033,1156,1096,1141,1111,1155,1080,1126,1140,898,898,808,808,897,897,792,792,1095,1152,1032,1125,1110,1139,1079,1124,882,807,838,881,853,791,-2319,867,368,263,822,852,837,866,806,865,-2399,851,352,262,534,534,821,836,594,594,549,549,593,593,533,533,848,773,579,579,564,578,548,563,276,276,577,576,306,291,516,560,305,305,275,259, + -251,-892,-2058,-2620,-2828,-2957,-3023,-3039,1041,1041,1040,1040,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-511,-527,-543,-559,1530,-575,-591,1528,1527,1407,1526,1391,1023,1023,1023,1023,1525,1375,1268,1268,1103,1103,1087,1087,1039,1039,1523,-604,815,815,815,815,510,495,509,479,508,463,507,447,431,505,415,399,-734,-782,1262,-815,1259,1244,-831,1258,1228,-847,-863,1196,-879,1253,987,987,748,-767,493,493,462,477,414,414,686,669,478,446,461,445,474,429,487,458,412,471,1266,1264,1009,1009,799,799,-1019,-1276,-1452,-1581,-1677,-1757,-1821,-1886,-1933,-1997,1257,1257,1483,1468,1512,1422,1497,1406,1467,1496,1421,1510,1134,1134,1225,1225,1466,1451,1374,1405,1252,1252,1358,1480,1164,1164,1251,1251,1238,1238,1389,1465,-1407,1054,1101,-1423,1207,-1439,830,830,1248,1038,1237,1117,1223,1148,1236,1208,411,426,395,410,379,269,1193,1222,1132,1235,1221,1116,976,976,1192,1162,1177,1220,1131,1191,963,963,-1647,961,780,-1663,558,558,994,993,437,408,393,407,829,978,813,797,947,-1743,721,721,377,392,844,950,828,890,706,706,812,859,796,960,948,843,934,874,571,571,-1919,690,555,689,421,346,539,539,944,779,918,873,932,842,903,888,570,570,931,917,674,674,-2575,1562,-2591,1609,-2607,1654,1322,1322,1441,1441,1696,1546,1683,1593,1669,1624,1426,1426,1321,1321,1639,1680,1425,1425,1305,1305,1545,1668,1608,1623,1667,1592,1638,1666,1320,1320,1652,1607,1409,1409,1304,1304,1288,1288,1664,1637,1395,1395,1335,1335,1622,1636,1394,1394,1319,1319,1606,1621,1392,1392,1137,1137,1137,1137,345,390,360,375,404,373,1047,-2751,-2767,-2783,1062,1121,1046,-2799,1077,-2815,1106,1061,789,789,1105,1104,263,355,310,340,325,354,352,262,339,324,1091,1076,1029,1090,1060,1075,833,833,788,788,1088,1028,818,818,803,803,561,561,531,531,816,771,546,546,289,274,288,258, + -253,-317,-381,-446,-478,-509,1279,1279,-811,-1179,-1451,-1756,-1900,-2028,-2189,-2253,-2333,-2414,-2445,-2511,-2526,1313,1298,-2559,1041,1041,1040,1040,1025,1025,1024,1024,1022,1007,1021,991,1020,975,1019,959,687,687,1018,1017,671,671,655,655,1016,1015,639,639,758,758,623,623,757,607,756,591,755,575,754,559,543,543,1009,783,-575,-621,-685,-749,496,-590,750,749,734,748,974,989,1003,958,988,973,1002,942,987,957,972,1001,926,986,941,971,956,1000,910,985,925,999,894,970,-1071,-1087,-1102,1390,-1135,1436,1509,1451,1374,-1151,1405,1358,1480,1420,-1167,1507,1494,1389,1342,1465,1435,1450,1326,1505,1310,1493,1373,1479,1404,1492,1464,1419,428,443,472,397,736,526,464,464,486,457,442,471,484,482,1357,1449,1434,1478,1388,1491,1341,1490,1325,1489,1463,1403,1309,1477,1372,1448,1418,1433,1476,1356,1462,1387,-1439,1475,1340,1447,1402,1474,1324,1461,1371,1473,269,448,1432,1417,1308,1460,-1711,1459,-1727,1441,1099,1099,1446,1386,1431,1401,-1743,1289,1083,1083,1160,1160,1458,1445,1067,1067,1370,1457,1307,1430,1129,1129,1098,1098,268,432,267,416,266,400,-1887,1144,1187,1082,1173,1113,1186,1066,1050,1158,1128,1143,1172,1097,1171,1081,420,391,1157,1112,1170,1142,1127,1065,1169,1049,1156,1096,1141,1111,1155,1080,1126,1154,1064,1153,1140,1095,1048,-2159,1125,1110,1137,-2175,823,823,1139,1138,807,807,384,264,368,263,868,838,853,791,867,822,852,837,866,806,865,790,-2319,851,821,836,352,262,850,805,849,-2399,533,533,835,820,336,261,578,548,563,577,532,532,832,772,562,562,547,547,305,275,560,515,290,290,288,258 }; + static const drmp3_uint8 tab32[] = { 130,162,193,209,44,28,76,140,9,9,9,9,9,9,9,9,190,254,222,238,126,94,157,157,109,61,173,205}; + static const drmp3_uint8 tab33[] = { 252,236,220,204,188,172,156,140,124,108,92,76,60,44,28,12 }; + static const drmp3_int16 tabindex[2*16] = { 0,32,64,98,0,132,180,218,292,364,426,538,648,746,0,1126,1460,1460,1460,1460,1460,1460,1460,1460,1842,1842,1842,1842,1842,1842,1842,1842 }; + static const drmp3_uint8 g_linbits[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,6,8,10,13,4,5,6,7,8,9,11,13 }; + +#define DRMP3_PEEK_BITS(n) (bs_cache >> (32 - n)) +#define DRMP3_FLUSH_BITS(n) { bs_cache <<= (n); bs_sh += (n); } +#define DRMP3_CHECK_BITS while (bs_sh >= 0) { bs_cache |= (drmp3_uint32)*bs_next_ptr++ << bs_sh; bs_sh -= 8; } +#define DRMP3_BSPOS ((bs_next_ptr - bs->buf)*8 - 24 + bs_sh) + + float one = 0.0f; + int ireg = 0, big_val_cnt = gr_info->big_values; + const drmp3_uint8 *sfb = gr_info->sfbtab; + const drmp3_uint8 *bs_next_ptr = bs->buf + bs->pos/8; + drmp3_uint32 bs_cache = (((bs_next_ptr[0]*256u + bs_next_ptr[1])*256u + bs_next_ptr[2])*256u + bs_next_ptr[3]) << (bs->pos & 7); + int pairs_to_decode, np, bs_sh = (bs->pos & 7) - 8; + bs_next_ptr += 4; + + while (big_val_cnt > 0) + { + int tab_num = gr_info->table_select[ireg]; + int sfb_cnt = gr_info->region_count[ireg++]; + const drmp3_int16 *codebook = tabs + tabindex[tab_num]; + int linbits = g_linbits[tab_num]; + do + { + np = *sfb++ / 2; + pairs_to_decode = DRMP3_MIN(big_val_cnt, np); + one = *scf++; + do + { + int j, w = 5; + int leaf = codebook[DRMP3_PEEK_BITS(w)]; + while (leaf < 0) + { + DRMP3_FLUSH_BITS(w); + w = leaf & 7; + leaf = codebook[DRMP3_PEEK_BITS(w) - (leaf >> 3)]; + } + DRMP3_FLUSH_BITS(leaf >> 8); + + for (j = 0; j < 2; j++, dst++, leaf >>= 4) + { + int lsb = leaf & 0x0F; + if (lsb == 15 && linbits) + { + lsb += DRMP3_PEEK_BITS(linbits); + DRMP3_FLUSH_BITS(linbits); + DRMP3_CHECK_BITS; + *dst = one*drmp3_L3_pow_43(lsb)*((int32_t)bs_cache < 0 ? -1: 1); + } else + { + *dst = g_drmp3_pow43[16 + lsb - 16*(bs_cache >> 31)]*one; + } + DRMP3_FLUSH_BITS(lsb ? 1 : 0); + } + DRMP3_CHECK_BITS; + } while (--pairs_to_decode); + } while ((big_val_cnt -= np) > 0 && --sfb_cnt >= 0); + } + + for (np = 1 - big_val_cnt;; dst += 4) + { + const drmp3_uint8 *codebook_count1 = (gr_info->count1_table) ? tab33 : tab32; + int leaf = codebook_count1[DRMP3_PEEK_BITS(4)]; + if (!(leaf & 8)) + { + leaf = codebook_count1[(leaf >> 3) + (bs_cache << 4 >> (32 - (leaf & 3)))]; + } + DRMP3_FLUSH_BITS(leaf & 7); + if (DRMP3_BSPOS > layer3gr_limit) + { + break; + } +#define DRMP3_RELOAD_SCALEFACTOR if (!--np) { np = *sfb++/2; if (!np) break; one = *scf++; } +#define DRMP3_DEQ_COUNT1(s) if (leaf & (128 >> s)) { dst[s] = ((drmp3_int32)bs_cache < 0) ? -one : one; DRMP3_FLUSH_BITS(1) } + DRMP3_RELOAD_SCALEFACTOR; + DRMP3_DEQ_COUNT1(0); + DRMP3_DEQ_COUNT1(1); + DRMP3_RELOAD_SCALEFACTOR; + DRMP3_DEQ_COUNT1(2); + DRMP3_DEQ_COUNT1(3); + DRMP3_CHECK_BITS; + } + + bs->pos = layer3gr_limit; +} + +static void drmp3_L3_midside_stereo(float *left, int n) +{ + int i = 0; + float *right = left + 576; +#if DRMP3_HAVE_SIMD + if (drmp3_have_simd()) for (; i < n - 3; i += 4) + { + drmp3_f4 vl = DRMP3_VLD(left + i); + drmp3_f4 vr = DRMP3_VLD(right + i); + DRMP3_VSTORE(left + i, DRMP3_VADD(vl, vr)); + DRMP3_VSTORE(right + i, DRMP3_VSUB(vl, vr)); + } +#endif + for (; i < n; i++) + { + float a = left[i]; + float b = right[i]; + left[i] = a + b; + right[i] = a - b; + } +} + +static void drmp3_L3_intensity_stereo_band(float *left, int n, float kl, float kr) +{ + int i; + for (i = 0; i < n; i++) + { + left[i + 576] = left[i]*kr; + left[i] = left[i]*kl; + } +} + +static void drmp3_L3_stereo_top_band(const float *right, const drmp3_uint8 *sfb, int nbands, int max_band[3]) +{ + int i, k; + + max_band[0] = max_band[1] = max_band[2] = -1; + + for (i = 0; i < nbands; i++) + { + for (k = 0; k < sfb[i]; k += 2) + { + if (right[k] != 0 || right[k + 1] != 0) + { + max_band[i % 3] = i; + break; + } + } + right += sfb[i]; + } +} + +static void drmp3_L3_stereo_process(float *left, const drmp3_uint8 *ist_pos, const drmp3_uint8 *sfb, const drmp3_uint8 *hdr, int max_band[3], int mpeg2_sh) +{ + static const float g_pan[7*2] = { 0,1,0.21132487f,0.78867513f,0.36602540f,0.63397460f,0.5f,0.5f,0.63397460f,0.36602540f,0.78867513f,0.21132487f,1,0 }; + unsigned i, max_pos = DRMP3_HDR_TEST_MPEG1(hdr) ? 7 : 64; + + for (i = 0; sfb[i]; i++) + { + unsigned ipos = ist_pos[i]; + if ((int)i > max_band[i % 3] && ipos < max_pos) + { + float kl, kr, s = DRMP3_HDR_TEST_MS_STEREO(hdr) ? 1.41421356f : 1; + if (DRMP3_HDR_TEST_MPEG1(hdr)) + { + kl = g_pan[2*ipos]; + kr = g_pan[2*ipos + 1]; + } else + { + kl = 1; + kr = drmp3_L3_ldexp_q2(1, (ipos + 1) >> 1 << mpeg2_sh); + if (ipos & 1) + { + kl = kr; + kr = 1; + } + } + drmp3_L3_intensity_stereo_band(left, sfb[i], kl*s, kr*s); + } else if (DRMP3_HDR_TEST_MS_STEREO(hdr)) + { + drmp3_L3_midside_stereo(left, sfb[i]); + } + left += sfb[i]; + } +} + +static void drmp3_L3_intensity_stereo(float *left, drmp3_uint8 *ist_pos, const drmp3_L3_gr_info *gr, const drmp3_uint8 *hdr) +{ + int max_band[3], n_sfb = gr->n_long_sfb + gr->n_short_sfb; + int i, max_blocks = gr->n_short_sfb ? 3 : 1; + + drmp3_L3_stereo_top_band(left + 576, gr->sfbtab, n_sfb, max_band); + if (gr->n_long_sfb) + { + max_band[0] = max_band[1] = max_band[2] = DRMP3_MAX(DRMP3_MAX(max_band[0], max_band[1]), max_band[2]); + } + for (i = 0; i < max_blocks; i++) + { + int default_pos = DRMP3_HDR_TEST_MPEG1(hdr) ? 3 : 0; + int itop = n_sfb - max_blocks + i; + int prev = itop - max_blocks; + ist_pos[itop] = (drmp3_uint8)(max_band[i] >= prev ? default_pos : ist_pos[prev]); + } + drmp3_L3_stereo_process(left, ist_pos, gr->sfbtab, hdr, max_band, gr[1].scalefac_compress & 1); +} + +static void drmp3_L3_reorder(float *grbuf, float *scratch, const drmp3_uint8 *sfb) +{ + int i, len; + float *src = grbuf, *dst = scratch; + + for (;0 != (len = *sfb); sfb += 3, src += 2*len) + { + for (i = 0; i < len; i++, src++) + { + *dst++ = src[0*len]; + *dst++ = src[1*len]; + *dst++ = src[2*len]; + } + } + memcpy(grbuf, scratch, (dst - scratch)*sizeof(float)); +} + +static void drmp3_L3_antialias(float *grbuf, int nbands) +{ + static const float g_aa[2][8] = { + {0.85749293f,0.88174200f,0.94962865f,0.98331459f,0.99551782f,0.99916056f,0.99989920f,0.99999316f}, + {0.51449576f,0.47173197f,0.31337745f,0.18191320f,0.09457419f,0.04096558f,0.01419856f,0.00369997f} + }; + + for (; nbands > 0; nbands--, grbuf += 18) + { + int i = 0; +#if DRMP3_HAVE_SIMD + if (drmp3_have_simd()) for (; i < 8; i += 4) + { + drmp3_f4 vu = DRMP3_VLD(grbuf + 18 + i); + drmp3_f4 vd = DRMP3_VLD(grbuf + 14 - i); + drmp3_f4 vc0 = DRMP3_VLD(g_aa[0] + i); + drmp3_f4 vc1 = DRMP3_VLD(g_aa[1] + i); + vd = DRMP3_VREV(vd); + DRMP3_VSTORE(grbuf + 18 + i, DRMP3_VSUB(DRMP3_VMUL(vu, vc0), DRMP3_VMUL(vd, vc1))); + vd = DRMP3_VADD(DRMP3_VMUL(vu, vc1), DRMP3_VMUL(vd, vc0)); + DRMP3_VSTORE(grbuf + 14 - i, DRMP3_VREV(vd)); + } +#endif +#ifndef DR_MP3_ONLY_SIMD + for(; i < 8; i++) + { + float u = grbuf[18 + i]; + float d = grbuf[17 - i]; + grbuf[18 + i] = u*g_aa[0][i] - d*g_aa[1][i]; + grbuf[17 - i] = u*g_aa[1][i] + d*g_aa[0][i]; + } +#endif + } +} + +static void drmp3_L3_dct3_9(float *y) +{ + float s0, s1, s2, s3, s4, s5, s6, s7, s8, t0, t2, t4; + + s0 = y[0]; s2 = y[2]; s4 = y[4]; s6 = y[6]; s8 = y[8]; + t0 = s0 + s6*0.5f; + s0 -= s6; + t4 = (s4 + s2)*0.93969262f; + t2 = (s8 + s2)*0.76604444f; + s6 = (s4 - s8)*0.17364818f; + s4 += s8 - s2; + + s2 = s0 - s4*0.5f; + y[4] = s4 + s0; + s8 = t0 - t2 + s6; + s0 = t0 - t4 + t2; + s4 = t0 + t4 - s6; + + s1 = y[1]; s3 = y[3]; s5 = y[5]; s7 = y[7]; + + s3 *= 0.86602540f; + t0 = (s5 + s1)*0.98480775f; + t4 = (s5 - s7)*0.34202014f; + t2 = (s1 + s7)*0.64278761f; + s1 = (s1 - s5 - s7)*0.86602540f; + + s5 = t0 - s3 - t2; + s7 = t4 - s3 - t0; + s3 = t4 + s3 - t2; + + y[0] = s4 - s7; + y[1] = s2 + s1; + y[2] = s0 - s3; + y[3] = s8 + s5; + y[5] = s8 - s5; + y[6] = s0 + s3; + y[7] = s2 - s1; + y[8] = s4 + s7; +} + +static void drmp3_L3_imdct36(float *grbuf, float *overlap, const float *window, int nbands) +{ + int i, j; + static const float g_twid9[18] = { + 0.73727734f,0.79335334f,0.84339145f,0.88701083f,0.92387953f,0.95371695f,0.97629601f,0.99144486f,0.99904822f,0.67559021f,0.60876143f,0.53729961f,0.46174861f,0.38268343f,0.30070580f,0.21643961f,0.13052619f,0.04361938f + }; + + for (j = 0; j < nbands; j++, grbuf += 18, overlap += 9) + { + float co[9], si[9]; + co[0] = -grbuf[0]; + si[0] = grbuf[17]; + for (i = 0; i < 4; i++) + { + si[8 - 2*i] = grbuf[4*i + 1] - grbuf[4*i + 2]; + co[1 + 2*i] = grbuf[4*i + 1] + grbuf[4*i + 2]; + si[7 - 2*i] = grbuf[4*i + 4] - grbuf[4*i + 3]; + co[2 + 2*i] = -(grbuf[4*i + 3] + grbuf[4*i + 4]); + } + drmp3_L3_dct3_9(co); + drmp3_L3_dct3_9(si); + + si[1] = -si[1]; + si[3] = -si[3]; + si[5] = -si[5]; + si[7] = -si[7]; + + i = 0; + +#if DRMP3_HAVE_SIMD + if (drmp3_have_simd()) for (; i < 8; i += 4) + { + drmp3_f4 vovl = DRMP3_VLD(overlap + i); + drmp3_f4 vc = DRMP3_VLD(co + i); + drmp3_f4 vs = DRMP3_VLD(si + i); + drmp3_f4 vr0 = DRMP3_VLD(g_twid9 + i); + drmp3_f4 vr1 = DRMP3_VLD(g_twid9 + 9 + i); + drmp3_f4 vw0 = DRMP3_VLD(window + i); + drmp3_f4 vw1 = DRMP3_VLD(window + 9 + i); + drmp3_f4 vsum = DRMP3_VADD(DRMP3_VMUL(vc, vr1), DRMP3_VMUL(vs, vr0)); + DRMP3_VSTORE(overlap + i, DRMP3_VSUB(DRMP3_VMUL(vc, vr0), DRMP3_VMUL(vs, vr1))); + DRMP3_VSTORE(grbuf + i, DRMP3_VSUB(DRMP3_VMUL(vovl, vw0), DRMP3_VMUL(vsum, vw1))); + vsum = DRMP3_VADD(DRMP3_VMUL(vovl, vw1), DRMP3_VMUL(vsum, vw0)); + DRMP3_VSTORE(grbuf + 14 - i, DRMP3_VREV(vsum)); + } +#endif + for (; i < 9; i++) + { + float ovl = overlap[i]; + float sum = co[i]*g_twid9[9 + i] + si[i]*g_twid9[0 + i]; + overlap[i] = co[i]*g_twid9[0 + i] - si[i]*g_twid9[9 + i]; + grbuf[i] = ovl*window[0 + i] - sum*window[9 + i]; + grbuf[17 - i] = ovl*window[9 + i] + sum*window[0 + i]; + } + } +} + +static void drmp3_L3_idct3(float x0, float x1, float x2, float *dst) +{ + float m1 = x1*0.86602540f; + float a1 = x0 - x2*0.5f; + dst[1] = x0 + x2; + dst[0] = a1 + m1; + dst[2] = a1 - m1; +} + +static void drmp3_L3_imdct12(float *x, float *dst, float *overlap) +{ + static const float g_twid3[6] = { 0.79335334f,0.92387953f,0.99144486f, 0.60876143f,0.38268343f,0.13052619f }; + float co[3], si[3]; + int i; + + drmp3_L3_idct3(-x[0], x[6] + x[3], x[12] + x[9], co); + drmp3_L3_idct3(x[15], x[12] - x[9], x[6] - x[3], si); + si[1] = -si[1]; + + for (i = 0; i < 3; i++) + { + float ovl = overlap[i]; + float sum = co[i]*g_twid3[3 + i] + si[i]*g_twid3[0 + i]; + overlap[i] = co[i]*g_twid3[0 + i] - si[i]*g_twid3[3 + i]; + dst[i] = ovl*g_twid3[2 - i] - sum*g_twid3[5 - i]; + dst[5 - i] = ovl*g_twid3[5 - i] + sum*g_twid3[2 - i]; + } +} + +static void drmp3_L3_imdct_short(float *grbuf, float *overlap, int nbands) +{ + for (;nbands > 0; nbands--, overlap += 9, grbuf += 18) + { + float tmp[18]; + memcpy(tmp, grbuf, sizeof(tmp)); + memcpy(grbuf, overlap, 6*sizeof(float)); + drmp3_L3_imdct12(tmp, grbuf + 6, overlap + 6); + drmp3_L3_imdct12(tmp + 1, grbuf + 12, overlap + 6); + drmp3_L3_imdct12(tmp + 2, overlap, overlap + 6); + } +} + +static void drmp3_L3_change_sign(float *grbuf) +{ + int b, i; + for (b = 0, grbuf += 18; b < 32; b += 2, grbuf += 36) + for (i = 1; i < 18; i += 2) + grbuf[i] = -grbuf[i]; +} + +static void drmp3_L3_imdct_gr(float *grbuf, float *overlap, unsigned block_type, unsigned n_long_bands) +{ + static const float g_mdct_window[2][18] = { + { 0.99904822f,0.99144486f,0.97629601f,0.95371695f,0.92387953f,0.88701083f,0.84339145f,0.79335334f,0.73727734f,0.04361938f,0.13052619f,0.21643961f,0.30070580f,0.38268343f,0.46174861f,0.53729961f,0.60876143f,0.67559021f }, + { 1,1,1,1,1,1,0.99144486f,0.92387953f,0.79335334f,0,0,0,0,0,0,0.13052619f,0.38268343f,0.60876143f } + }; + if (n_long_bands) + { + drmp3_L3_imdct36(grbuf, overlap, g_mdct_window[0], n_long_bands); + grbuf += 18*n_long_bands; + overlap += 9*n_long_bands; + } + if (block_type == DRMP3_SHORT_BLOCK_TYPE) + drmp3_L3_imdct_short(grbuf, overlap, 32 - n_long_bands); + else + drmp3_L3_imdct36(grbuf, overlap, g_mdct_window[block_type == DRMP3_STOP_BLOCK_TYPE], 32 - n_long_bands); +} + +static void drmp3_L3_save_reservoir(drmp3dec *h, drmp3dec_scratch *s) +{ + int pos = (s->bs.pos + 7)/8u; + int remains = s->bs.limit/8u - pos; + if (remains > DRMP3_MAX_BITRESERVOIR_BYTES) + { + pos += remains - DRMP3_MAX_BITRESERVOIR_BYTES; + remains = DRMP3_MAX_BITRESERVOIR_BYTES; + } + if (remains > 0) + { + memmove(h->reserv_buf, s->maindata + pos, remains); + } + h->reserv = remains; +} + +static int drmp3_L3_restore_reservoir(drmp3dec *h, drmp3_bs *bs, drmp3dec_scratch *s, int main_data_begin) +{ + int frame_bytes = (bs->limit - bs->pos)/8; + int bytes_have = DRMP3_MIN(h->reserv, main_data_begin); + memcpy(s->maindata, h->reserv_buf + DRMP3_MAX(0, h->reserv - main_data_begin), DRMP3_MIN(h->reserv, main_data_begin)); + memcpy(s->maindata + bytes_have, bs->buf + bs->pos/8, frame_bytes); + drmp3_bs_init(&s->bs, s->maindata, bytes_have + frame_bytes); + return h->reserv >= main_data_begin; +} + +static void drmp3_L3_decode(drmp3dec *h, drmp3dec_scratch *s, drmp3_L3_gr_info *gr_info, int nch) +{ + int ch; + + for (ch = 0; ch < nch; ch++) + { + int layer3gr_limit = s->bs.pos + gr_info[ch].part_23_length; + drmp3_L3_decode_scalefactors(h->header, s->ist_pos[ch], &s->bs, gr_info + ch, s->scf, ch); + drmp3_L3_huffman(s->grbuf[ch], &s->bs, gr_info + ch, s->scf, layer3gr_limit); + } + + if (DRMP3_HDR_TEST_I_STEREO(h->header)) + { + drmp3_L3_intensity_stereo(s->grbuf[0], s->ist_pos[1], gr_info, h->header); + } else if (DRMP3_HDR_IS_MS_STEREO(h->header)) + { + drmp3_L3_midside_stereo(s->grbuf[0], 576); + } + + for (ch = 0; ch < nch; ch++, gr_info++) + { + int aa_bands = 31; + int n_long_bands = (gr_info->mixed_block_flag ? 2 : 0) << (int)(DRMP3_HDR_GET_MY_SAMPLE_RATE(h->header) == 2); + + if (gr_info->n_short_sfb) + { + aa_bands = n_long_bands - 1; + drmp3_L3_reorder(s->grbuf[ch] + n_long_bands*18, s->syn[0], gr_info->sfbtab + gr_info->n_long_sfb); + } + + drmp3_L3_antialias(s->grbuf[ch], aa_bands); + drmp3_L3_imdct_gr(s->grbuf[ch], h->mdct_overlap[ch], gr_info->block_type, n_long_bands); + drmp3_L3_change_sign(s->grbuf[ch]); + } +} + +static void drmp3d_DCT_II(float *grbuf, int n) +{ + static const float g_sec[24] = { + 10.19000816f,0.50060302f,0.50241929f,3.40760851f,0.50547093f,0.52249861f,2.05778098f,0.51544732f,0.56694406f,1.48416460f,0.53104258f,0.64682180f,1.16943991f,0.55310392f,0.78815460f,0.97256821f,0.58293498f,1.06067765f,0.83934963f,0.62250412f,1.72244716f,0.74453628f,0.67480832f,5.10114861f + }; + int i, k = 0; +#if DRMP3_HAVE_SIMD + if (drmp3_have_simd()) for (; k < n; k += 4) + { + drmp3_f4 t[4][8], *x; + float *y = grbuf + k; + + for (x = t[0], i = 0; i < 8; i++, x++) + { + drmp3_f4 x0 = DRMP3_VLD(&y[i*18]); + drmp3_f4 x1 = DRMP3_VLD(&y[(15 - i)*18]); + drmp3_f4 x2 = DRMP3_VLD(&y[(16 + i)*18]); + drmp3_f4 x3 = DRMP3_VLD(&y[(31 - i)*18]); + drmp3_f4 t0 = DRMP3_VADD(x0, x3); + drmp3_f4 t1 = DRMP3_VADD(x1, x2); + drmp3_f4 t2 = DRMP3_VMUL_S(DRMP3_VSUB(x1, x2), g_sec[3*i + 0]); + drmp3_f4 t3 = DRMP3_VMUL_S(DRMP3_VSUB(x0, x3), g_sec[3*i + 1]); + x[0] = DRMP3_VADD(t0, t1); + x[8] = DRMP3_VMUL_S(DRMP3_VSUB(t0, t1), g_sec[3*i + 2]); + x[16] = DRMP3_VADD(t3, t2); + x[24] = DRMP3_VMUL_S(DRMP3_VSUB(t3, t2), g_sec[3*i + 2]); + } + for (x = t[0], i = 0; i < 4; i++, x += 8) + { + drmp3_f4 x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7], xt; + xt = DRMP3_VSUB(x0, x7); x0 = DRMP3_VADD(x0, x7); + x7 = DRMP3_VSUB(x1, x6); x1 = DRMP3_VADD(x1, x6); + x6 = DRMP3_VSUB(x2, x5); x2 = DRMP3_VADD(x2, x5); + x5 = DRMP3_VSUB(x3, x4); x3 = DRMP3_VADD(x3, x4); + x4 = DRMP3_VSUB(x0, x3); x0 = DRMP3_VADD(x0, x3); + x3 = DRMP3_VSUB(x1, x2); x1 = DRMP3_VADD(x1, x2); + x[0] = DRMP3_VADD(x0, x1); + x[4] = DRMP3_VMUL_S(DRMP3_VSUB(x0, x1), 0.70710677f); + x5 = DRMP3_VADD(x5, x6); + x6 = DRMP3_VMUL_S(DRMP3_VADD(x6, x7), 0.70710677f); + x7 = DRMP3_VADD(x7, xt); + x3 = DRMP3_VMUL_S(DRMP3_VADD(x3, x4), 0.70710677f); + x5 = DRMP3_VSUB(x5, DRMP3_VMUL_S(x7, 0.198912367f)); /* rotate by PI/8 */ + x7 = DRMP3_VADD(x7, DRMP3_VMUL_S(x5, 0.382683432f)); + x5 = DRMP3_VSUB(x5, DRMP3_VMUL_S(x7, 0.198912367f)); + x0 = DRMP3_VSUB(xt, x6); xt = DRMP3_VADD(xt, x6); + x[1] = DRMP3_VMUL_S(DRMP3_VADD(xt, x7), 0.50979561f); + x[2] = DRMP3_VMUL_S(DRMP3_VADD(x4, x3), 0.54119611f); + x[3] = DRMP3_VMUL_S(DRMP3_VSUB(x0, x5), 0.60134488f); + x[5] = DRMP3_VMUL_S(DRMP3_VADD(x0, x5), 0.89997619f); + x[6] = DRMP3_VMUL_S(DRMP3_VSUB(x4, x3), 1.30656302f); + x[7] = DRMP3_VMUL_S(DRMP3_VSUB(xt, x7), 2.56291556f); + } + + if (k > n - 3) + { +#if DRMP3_HAVE_SSE +#define DRMP3_VSAVE2(i, v) _mm_storel_pi((__m64 *)(void*)&y[i*18], v) +#else +#define DRMP3_VSAVE2(i, v) vst1_f32((float32_t *)&y[i*18], vget_low_f32(v)) +#endif + for (i = 0; i < 7; i++, y += 4*18) + { + drmp3_f4 s = DRMP3_VADD(t[3][i], t[3][i + 1]); + DRMP3_VSAVE2(0, t[0][i]); + DRMP3_VSAVE2(1, DRMP3_VADD(t[2][i], s)); + DRMP3_VSAVE2(2, DRMP3_VADD(t[1][i], t[1][i + 1])); + DRMP3_VSAVE2(3, DRMP3_VADD(t[2][1 + i], s)); + } + DRMP3_VSAVE2(0, t[0][7]); + DRMP3_VSAVE2(1, DRMP3_VADD(t[2][7], t[3][7])); + DRMP3_VSAVE2(2, t[1][7]); + DRMP3_VSAVE2(3, t[3][7]); + } else + { +#define DRMP3_VSAVE4(i, v) DRMP3_VSTORE(&y[i*18], v) + for (i = 0; i < 7; i++, y += 4*18) + { + drmp3_f4 s = DRMP3_VADD(t[3][i], t[3][i + 1]); + DRMP3_VSAVE4(0, t[0][i]); + DRMP3_VSAVE4(1, DRMP3_VADD(t[2][i], s)); + DRMP3_VSAVE4(2, DRMP3_VADD(t[1][i], t[1][i + 1])); + DRMP3_VSAVE4(3, DRMP3_VADD(t[2][1 + i], s)); + } + DRMP3_VSAVE4(0, t[0][7]); + DRMP3_VSAVE4(1, DRMP3_VADD(t[2][7], t[3][7])); + DRMP3_VSAVE4(2, t[1][7]); + DRMP3_VSAVE4(3, t[3][7]); + } + } else +#endif +#ifdef DR_MP3_ONLY_SIMD + {} +#else + for (; k < n; k++) + { + float t[4][8], *x, *y = grbuf + k; + + for (x = t[0], i = 0; i < 8; i++, x++) + { + float x0 = y[i*18]; + float x1 = y[(15 - i)*18]; + float x2 = y[(16 + i)*18]; + float x3 = y[(31 - i)*18]; + float t0 = x0 + x3; + float t1 = x1 + x2; + float t2 = (x1 - x2)*g_sec[3*i + 0]; + float t3 = (x0 - x3)*g_sec[3*i + 1]; + x[0] = t0 + t1; + x[8] = (t0 - t1)*g_sec[3*i + 2]; + x[16] = t3 + t2; + x[24] = (t3 - t2)*g_sec[3*i + 2]; + } + for (x = t[0], i = 0; i < 4; i++, x += 8) + { + float x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7], xt; + xt = x0 - x7; x0 += x7; + x7 = x1 - x6; x1 += x6; + x6 = x2 - x5; x2 += x5; + x5 = x3 - x4; x3 += x4; + x4 = x0 - x3; x0 += x3; + x3 = x1 - x2; x1 += x2; + x[0] = x0 + x1; + x[4] = (x0 - x1)*0.70710677f; + x5 = x5 + x6; + x6 = (x6 + x7)*0.70710677f; + x7 = x7 + xt; + x3 = (x3 + x4)*0.70710677f; + x5 -= x7*0.198912367f; /* rotate by PI/8 */ + x7 += x5*0.382683432f; + x5 -= x7*0.198912367f; + x0 = xt - x6; xt += x6; + x[1] = (xt + x7)*0.50979561f; + x[2] = (x4 + x3)*0.54119611f; + x[3] = (x0 - x5)*0.60134488f; + x[5] = (x0 + x5)*0.89997619f; + x[6] = (x4 - x3)*1.30656302f; + x[7] = (xt - x7)*2.56291556f; + + } + for (i = 0; i < 7; i++, y += 4*18) + { + y[0*18] = t[0][i]; + y[1*18] = t[2][i] + t[3][i] + t[3][i + 1]; + y[2*18] = t[1][i] + t[1][i + 1]; + y[3*18] = t[2][i + 1] + t[3][i] + t[3][i + 1]; + } + y[0*18] = t[0][7]; + y[1*18] = t[2][7] + t[3][7]; + y[2*18] = t[1][7]; + y[3*18] = t[3][7]; + } +#endif +} + +#ifndef DR_MP3_FLOAT_OUTPUT +typedef drmp3_int16 drmp3d_sample_t; + +static drmp3_int16 drmp3d_scale_pcm(float sample) +{ + if (sample >= 32766.5) return (drmp3_int16) 32767; + if (sample <= -32767.5) return (drmp3_int16)-32768; + drmp3_int16 s = (drmp3_int16)(sample + .5f); + s -= (s < 0); /* away from zero, to be compliant */ + return (drmp3_int16)s; +} +#else +typedef float drmp3d_sample_t; + +static float drmp3d_scale_pcm(float sample) +{ + return sample*(1.f/32768.f); +} +#endif + +static void drmp3d_synth_pair(drmp3d_sample_t *pcm, int nch, const float *z) +{ + float a; + a = (z[14*64] - z[ 0]) * 29; + a += (z[ 1*64] + z[13*64]) * 213; + a += (z[12*64] - z[ 2*64]) * 459; + a += (z[ 3*64] + z[11*64]) * 2037; + a += (z[10*64] - z[ 4*64]) * 5153; + a += (z[ 5*64] + z[ 9*64]) * 6574; + a += (z[ 8*64] - z[ 6*64]) * 37489; + a += z[ 7*64] * 75038; + pcm[0] = drmp3d_scale_pcm(a); + + z += 2; + a = z[14*64] * 104; + a += z[12*64] * 1567; + a += z[10*64] * 9727; + a += z[ 8*64] * 64019; + a += z[ 6*64] * -9975; + a += z[ 4*64] * -45; + a += z[ 2*64] * 146; + a += z[ 0*64] * -5; + pcm[16*nch] = drmp3d_scale_pcm(a); +} + +static void drmp3d_synth(float *xl, drmp3d_sample_t *dstl, int nch, float *lins) +{ + int i; + float *xr = xl + 576*(nch - 1); + drmp3d_sample_t *dstr = dstl + (nch - 1); + + static const float g_win[] = { + -1,26,-31,208,218,401,-519,2063,2000,4788,-5517,7134,5959,35640,-39336,74992, + -1,24,-35,202,222,347,-581,2080,1952,4425,-5879,7640,5288,33791,-41176,74856, + -1,21,-38,196,225,294,-645,2087,1893,4063,-6237,8092,4561,31947,-43006,74630, + -1,19,-41,190,227,244,-711,2085,1822,3705,-6589,8492,3776,30112,-44821,74313, + -1,17,-45,183,228,197,-779,2075,1739,3351,-6935,8840,2935,28289,-46617,73908, + -1,16,-49,176,228,153,-848,2057,1644,3004,-7271,9139,2037,26482,-48390,73415, + -2,14,-53,169,227,111,-919,2032,1535,2663,-7597,9389,1082,24694,-50137,72835, + -2,13,-58,161,224,72,-991,2001,1414,2330,-7910,9592,70,22929,-51853,72169, + -2,11,-63,154,221,36,-1064,1962,1280,2006,-8209,9750,-998,21189,-53534,71420, + -2,10,-68,147,215,2,-1137,1919,1131,1692,-8491,9863,-2122,19478,-55178,70590, + -3,9,-73,139,208,-29,-1210,1870,970,1388,-8755,9935,-3300,17799,-56778,69679, + -3,8,-79,132,200,-57,-1283,1817,794,1095,-8998,9966,-4533,16155,-58333,68692, + -4,7,-85,125,189,-83,-1356,1759,605,814,-9219,9959,-5818,14548,-59838,67629, + -4,7,-91,117,177,-106,-1428,1698,402,545,-9416,9916,-7154,12980,-61289,66494, + -5,6,-97,111,163,-127,-1498,1634,185,288,-9585,9838,-8540,11455,-62684,65290 + }; + float *zlin = lins + 15*64; + const float *w = g_win; + + zlin[4*15] = xl[18*16]; + zlin[4*15 + 1] = xr[18*16]; + zlin[4*15 + 2] = xl[0]; + zlin[4*15 + 3] = xr[0]; + + zlin[4*31] = xl[1 + 18*16]; + zlin[4*31 + 1] = xr[1 + 18*16]; + zlin[4*31 + 2] = xl[1]; + zlin[4*31 + 3] = xr[1]; + + drmp3d_synth_pair(dstr, nch, lins + 4*15 + 1); + drmp3d_synth_pair(dstr + 32*nch, nch, lins + 4*15 + 64 + 1); + drmp3d_synth_pair(dstl, nch, lins + 4*15); + drmp3d_synth_pair(dstl + 32*nch, nch, lins + 4*15 + 64); + +#if DRMP3_HAVE_SIMD + if (drmp3_have_simd()) for (i = 14; i >= 0; i--) + { +#define DRMP3_VLOAD(k) drmp3_f4 w0 = DRMP3_VSET(*w++); drmp3_f4 w1 = DRMP3_VSET(*w++); drmp3_f4 vz = DRMP3_VLD(&zlin[4*i - 64*k]); drmp3_f4 vy = DRMP3_VLD(&zlin[4*i - 64*(15 - k)]); +#define DRMP3_V0(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0)) ; a = DRMP3_VSUB(DRMP3_VMUL(vz, w0), DRMP3_VMUL(vy, w1)); } +#define DRMP3_V1(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(b, DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0))); a = DRMP3_VADD(a, DRMP3_VSUB(DRMP3_VMUL(vz, w0), DRMP3_VMUL(vy, w1))); } +#define DRMP3_V2(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(b, DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0))); a = DRMP3_VADD(a, DRMP3_VSUB(DRMP3_VMUL(vy, w1), DRMP3_VMUL(vz, w0))); } + drmp3_f4 a, b; + zlin[4*i] = xl[18*(31 - i)]; + zlin[4*i + 1] = xr[18*(31 - i)]; + zlin[4*i + 2] = xl[1 + 18*(31 - i)]; + zlin[4*i + 3] = xr[1 + 18*(31 - i)]; + zlin[4*i + 64] = xl[1 + 18*(1 + i)]; + zlin[4*i + 64 + 1] = xr[1 + 18*(1 + i)]; + zlin[4*i - 64 + 2] = xl[18*(1 + i)]; + zlin[4*i - 64 + 3] = xr[18*(1 + i)]; + + DRMP3_V0(0) DRMP3_V2(1) DRMP3_V1(2) DRMP3_V2(3) DRMP3_V1(4) DRMP3_V2(5) DRMP3_V1(6) DRMP3_V2(7) + + { +#ifndef DR_MP3_FLOAT_OUTPUT +#if DRMP3_HAVE_SSE + static const drmp3_f4 g_max = { 32767.0f, 32767.0f, 32767.0f, 32767.0f }; + static const drmp3_f4 g_min = { -32768.0f, -32768.0f, -32768.0f, -32768.0f }; + __m128i pcm8 = _mm_packs_epi32(_mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(a, g_max), g_min)), + _mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(b, g_max), g_min))); + dstr[(15 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 1); + dstr[(17 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 5); + dstl[(15 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 0); + dstl[(17 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 4); + dstr[(47 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 3); + dstr[(49 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 7); + dstl[(47 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 2); + dstl[(49 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 6); +#else + int16x4_t pcma, pcmb; + a = DRMP3_VADD(a, DRMP3_VSET(0.5f)); + b = DRMP3_VADD(b, DRMP3_VSET(0.5f)); + pcma = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(a), vreinterpretq_s32_u32(vcltq_f32(a, DRMP3_VSET(0))))); + pcmb = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(b), vreinterpretq_s32_u32(vcltq_f32(b, DRMP3_VSET(0))))); + vst1_lane_s16(dstr + (15 - i)*nch, pcma, 1); + vst1_lane_s16(dstr + (17 + i)*nch, pcmb, 1); + vst1_lane_s16(dstl + (15 - i)*nch, pcma, 0); + vst1_lane_s16(dstl + (17 + i)*nch, pcmb, 0); + vst1_lane_s16(dstr + (47 - i)*nch, pcma, 3); + vst1_lane_s16(dstr + (49 + i)*nch, pcmb, 3); + vst1_lane_s16(dstl + (47 - i)*nch, pcma, 2); + vst1_lane_s16(dstl + (49 + i)*nch, pcmb, 2); +#endif +#else + static const drmp3_f4 g_scale = { 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f }; + a = DRMP3_VMUL(a, g_scale); + b = DRMP3_VMUL(b, g_scale); +#if DRMP3_HAVE_SSE + _mm_store_ss(dstr + (15 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1))); + _mm_store_ss(dstr + (17 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(1, 1, 1, 1))); + _mm_store_ss(dstl + (15 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0))); + _mm_store_ss(dstl + (17 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(0, 0, 0, 0))); + _mm_store_ss(dstr + (47 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3))); + _mm_store_ss(dstr + (49 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 3, 3, 3))); + _mm_store_ss(dstl + (47 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2))); + _mm_store_ss(dstl + (49 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(2, 2, 2, 2))); +#else + vst1q_lane_f32(dstr + (15 - i)*nch, a, 1); + vst1q_lane_f32(dstr + (17 + i)*nch, b, 1); + vst1q_lane_f32(dstl + (15 - i)*nch, a, 0); + vst1q_lane_f32(dstl + (17 + i)*nch, b, 0); + vst1q_lane_f32(dstr + (47 - i)*nch, a, 3); + vst1q_lane_f32(dstr + (49 + i)*nch, b, 3); + vst1q_lane_f32(dstl + (47 - i)*nch, a, 2); + vst1q_lane_f32(dstl + (49 + i)*nch, b, 2); +#endif +#endif /* DR_MP3_FLOAT_OUTPUT */ + } + } else +#endif +#ifdef DR_MP3_ONLY_SIMD + {} +#else + for (i = 14; i >= 0; i--) + { +#define DRMP3_LOAD(k) float w0 = *w++; float w1 = *w++; float *vz = &zlin[4*i - k*64]; float *vy = &zlin[4*i - (15 - k)*64]; +#define DRMP3_S0(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] = vz[j]*w1 + vy[j]*w0, a[j] = vz[j]*w0 - vy[j]*w1; } +#define DRMP3_S1(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] += vz[j]*w1 + vy[j]*w0, a[j] += vz[j]*w0 - vy[j]*w1; } +#define DRMP3_S2(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] += vz[j]*w1 + vy[j]*w0, a[j] += vy[j]*w1 - vz[j]*w0; } + float a[4], b[4]; + + zlin[4*i] = xl[18*(31 - i)]; + zlin[4*i + 1] = xr[18*(31 - i)]; + zlin[4*i + 2] = xl[1 + 18*(31 - i)]; + zlin[4*i + 3] = xr[1 + 18*(31 - i)]; + zlin[4*(i + 16)] = xl[1 + 18*(1 + i)]; + zlin[4*(i + 16) + 1] = xr[1 + 18*(1 + i)]; + zlin[4*(i - 16) + 2] = xl[18*(1 + i)]; + zlin[4*(i - 16) + 3] = xr[18*(1 + i)]; + + DRMP3_S0(0) DRMP3_S2(1) DRMP3_S1(2) DRMP3_S2(3) DRMP3_S1(4) DRMP3_S2(5) DRMP3_S1(6) DRMP3_S2(7) + + dstr[(15 - i)*nch] = drmp3d_scale_pcm(a[1]); + dstr[(17 + i)*nch] = drmp3d_scale_pcm(b[1]); + dstl[(15 - i)*nch] = drmp3d_scale_pcm(a[0]); + dstl[(17 + i)*nch] = drmp3d_scale_pcm(b[0]); + dstr[(47 - i)*nch] = drmp3d_scale_pcm(a[3]); + dstr[(49 + i)*nch] = drmp3d_scale_pcm(b[3]); + dstl[(47 - i)*nch] = drmp3d_scale_pcm(a[2]); + dstl[(49 + i)*nch] = drmp3d_scale_pcm(b[2]); + } +#endif +} + +static void drmp3d_synth_granule(float *qmf_state, float *grbuf, int nbands, int nch, drmp3d_sample_t *pcm, float *lins) +{ + int i; + for (i = 0; i < nch; i++) + { + drmp3d_DCT_II(grbuf + 576*i, nbands); + } + + memcpy(lins, qmf_state, sizeof(float)*15*64); + + for (i = 0; i < nbands; i += 2) + { + drmp3d_synth(grbuf + i, pcm + 32*nch*i, nch, lins + i*64); + } +#ifndef DR_MP3_NONSTANDARD_BUT_LOGICAL + if (nch == 1) + { + for (i = 0; i < 15*64; i += 2) + { + qmf_state[i] = lins[nbands*64 + i]; + } + } else +#endif + { + memcpy(qmf_state, lins + nbands*64, sizeof(float)*15*64); + } +} + +static int drmp3d_match_frame(const drmp3_uint8 *hdr, int mp3_bytes, int frame_bytes) +{ + int i, nmatch; + for (i = 0, nmatch = 0; nmatch < DRMP3_MAX_FRAME_SYNC_MATCHES; nmatch++) + { + i += drmp3_hdr_frame_bytes(hdr + i, frame_bytes) + drmp3_hdr_padding(hdr + i); + if (i + DRMP3_HDR_SIZE > mp3_bytes) + return nmatch > 0; + if (!drmp3_hdr_compare(hdr, hdr + i)) + return 0; + } + return 1; +} + +static int drmp3d_find_frame(const drmp3_uint8 *mp3, int mp3_bytes, int *free_format_bytes, int *ptr_frame_bytes) +{ + int i, k; + for (i = 0; i < mp3_bytes - DRMP3_HDR_SIZE; i++, mp3++) + { + if (drmp3_hdr_valid(mp3)) + { + int frame_bytes = drmp3_hdr_frame_bytes(mp3, *free_format_bytes); + int frame_and_padding = frame_bytes + drmp3_hdr_padding(mp3); + + for (k = DRMP3_HDR_SIZE; !frame_bytes && k < DRMP3_MAX_FREE_FORMAT_FRAME_SIZE && i + 2*k < mp3_bytes - DRMP3_HDR_SIZE; k++) + { + if (drmp3_hdr_compare(mp3, mp3 + k)) + { + int fb = k - drmp3_hdr_padding(mp3); + int nextfb = fb + drmp3_hdr_padding(mp3 + k); + if (i + k + nextfb + DRMP3_HDR_SIZE > mp3_bytes || !drmp3_hdr_compare(mp3, mp3 + k + nextfb)) + continue; + frame_and_padding = k; + frame_bytes = fb; + *free_format_bytes = fb; + } + } + + if ((frame_bytes && i + frame_and_padding <= mp3_bytes && + drmp3d_match_frame(mp3, mp3_bytes - i, frame_bytes)) || + (!i && frame_and_padding == mp3_bytes)) + { + *ptr_frame_bytes = frame_and_padding; + return i; + } + *free_format_bytes = 0; + } + } + *ptr_frame_bytes = 0; + return i; +} + +void drmp3dec_init(drmp3dec *dec) +{ + dec->header[0] = 0; +} + +int drmp3dec_decode_frame(drmp3dec *dec, const unsigned char *mp3, int mp3_bytes, void *pcm, drmp3dec_frame_info *info) +{ + int i = 0, igr, frame_size = 0, success = 1; + const drmp3_uint8 *hdr; + drmp3_bs bs_frame[1]; + drmp3dec_scratch scratch; + + if (mp3_bytes > 4 && dec->header[0] == 0xff && drmp3_hdr_compare(dec->header, mp3)) + { + frame_size = drmp3_hdr_frame_bytes(mp3, dec->free_format_bytes) + drmp3_hdr_padding(mp3); + if (frame_size != mp3_bytes && (frame_size + DRMP3_HDR_SIZE > mp3_bytes || !drmp3_hdr_compare(mp3, mp3 + frame_size))) + { + frame_size = 0; + } + } + if (!frame_size) + { + memset(dec, 0, sizeof(drmp3dec)); + i = drmp3d_find_frame(mp3, mp3_bytes, &dec->free_format_bytes, &frame_size); + if (!frame_size || i + frame_size > mp3_bytes) + { + info->frame_bytes = i; + return 0; + } + } + + hdr = mp3 + i; + memcpy(dec->header, hdr, DRMP3_HDR_SIZE); + info->frame_bytes = i + frame_size; + info->channels = DRMP3_HDR_IS_MONO(hdr) ? 1 : 2; + info->hz = drmp3_hdr_sample_rate_hz(hdr); + info->layer = 4 - DRMP3_HDR_GET_LAYER(hdr); + info->bitrate_kbps = drmp3_hdr_bitrate_kbps(hdr); + + drmp3_bs_init(bs_frame, hdr + DRMP3_HDR_SIZE, frame_size - DRMP3_HDR_SIZE); + if (DRMP3_HDR_IS_CRC(hdr)) + { + drmp3_bs_get_bits(bs_frame, 16); + } + + if (info->layer == 3) + { + int main_data_begin = drmp3_L3_read_side_info(bs_frame, scratch.gr_info, hdr); + if (main_data_begin < 0 || bs_frame->pos > bs_frame->limit) + { + drmp3dec_init(dec); + return 0; + } + success = drmp3_L3_restore_reservoir(dec, bs_frame, &scratch, main_data_begin); + if (success && pcm != NULL) + { + for (igr = 0; igr < (DRMP3_HDR_TEST_MPEG1(hdr) ? 2 : 1); igr++, pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*576*info->channels)) + { + memset(scratch.grbuf[0], 0, 576*2*sizeof(float)); + drmp3_L3_decode(dec, &scratch, scratch.gr_info + igr*info->channels, info->channels); + drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 18, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]); + } + } + drmp3_L3_save_reservoir(dec, &scratch); + } else + { +#ifdef DR_MP3_ONLY_MP3 + return 0; +#else + if (pcm == NULL) { + return drmp3_hdr_frame_samples(hdr); + } + + drmp3_L12_scale_info sci[1]; + drmp3_L12_read_scale_info(hdr, bs_frame, sci); + + memset(scratch.grbuf[0], 0, 576*2*sizeof(float)); + for (i = 0, igr = 0; igr < 3; igr++) + { + if (12 == (i += drmp3_L12_dequantize_granule(scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1))) + { + i = 0; + drmp3_L12_apply_scf_384(sci, sci->scf + igr, scratch.grbuf[0]); + drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 12, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]); + memset(scratch.grbuf[0], 0, 576*2*sizeof(float)); + pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*384*info->channels); + } + if (bs_frame->pos > bs_frame->limit) + { + drmp3dec_init(dec); + return 0; + } + } +#endif + } + + return success*drmp3_hdr_frame_samples(dec->header); +} + +void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, int num_samples) +{ + if(num_samples > 0) + { + int i = 0; +#if DRMP3_HAVE_SIMD + int aligned_count = num_samples & ~7; + for(; i < aligned_count; i+=8) + { + static const drmp3_f4 g_scale = { 32768.0f, 32768.0f, 32768.0f, 32768.0f }; + drmp3_f4 a = DRMP3_VMUL(DRMP3_VLD(&in[i ]), g_scale); + drmp3_f4 b = DRMP3_VMUL(DRMP3_VLD(&in[i+4]), g_scale); +#if DRMP3_HAVE_SSE + static const drmp3_f4 g_max = { 32767.0f, 32767.0f, 32767.0f, 32767.0f }; + static const drmp3_f4 g_min = { -32768.0f, -32768.0f, -32768.0f, -32768.0f }; + __m128i pcm8 = _mm_packs_epi32(_mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(a, g_max), g_min)), + _mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(b, g_max), g_min))); + out[i ] = (drmp3_int16)_mm_extract_epi16(pcm8, 0); + out[i+1] = (drmp3_int16)_mm_extract_epi16(pcm8, 1); + out[i+2] = (drmp3_int16)_mm_extract_epi16(pcm8, 2); + out[i+3] = (drmp3_int16)_mm_extract_epi16(pcm8, 3); + out[i+4] = (drmp3_int16)_mm_extract_epi16(pcm8, 4); + out[i+5] = (drmp3_int16)_mm_extract_epi16(pcm8, 5); + out[i+6] = (drmp3_int16)_mm_extract_epi16(pcm8, 6); + out[i+7] = (drmp3_int16)_mm_extract_epi16(pcm8, 7); +#else + int16x4_t pcma, pcmb; + a = DRMP3_VADD(a, DRMP3_VSET(0.5f)); + b = DRMP3_VADD(b, DRMP3_VSET(0.5f)); + pcma = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(a), vreinterpretq_s32_u32(vcltq_f32(a, DRMP3_VSET(0))))); + pcmb = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(b), vreinterpretq_s32_u32(vcltq_f32(b, DRMP3_VSET(0))))); + vst1_lane_s16(out+i , pcma, 0); + vst1_lane_s16(out+i+1, pcma, 1); + vst1_lane_s16(out+i+2, pcma, 2); + vst1_lane_s16(out+i+3, pcma, 3); + vst1_lane_s16(out+i+4, pcmb, 0); + vst1_lane_s16(out+i+5, pcmb, 1); + vst1_lane_s16(out+i+6, pcmb, 2); + vst1_lane_s16(out+i+7, pcmb, 3); +#endif + } +#endif + for(; i < num_samples; i++) + { + float sample = in[i] * 32768.0f; + if (sample >= 32766.5) + out[i] = (drmp3_int16) 32767; + else if (sample <= -32767.5) + out[i] = (drmp3_int16)-32768; + else + { + short s = (drmp3_int16)(sample + .5f); + s -= (s < 0); /* away from zero, to be compliant */ + out[i] = s; + } + } + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +// +// Main Public API +// +/////////////////////////////////////////////////////////////////////////////// + +#if defined(SIZE_MAX) + #define DRMP3_SIZE_MAX SIZE_MAX +#else + #if defined(_WIN64) || defined(_LP64) || defined(__LP64__) + #define DRMP3_SIZE_MAX ((drmp3_uint64)0xFFFFFFFFFFFFFFFF) + #else + #define DRMP3_SIZE_MAX 0xFFFFFFFF + #endif +#endif + +// Options. +#ifndef DR_MP3_DEFAULT_CHANNELS +#define DR_MP3_DEFAULT_CHANNELS 2 +#endif +#ifndef DR_MP3_DEFAULT_SAMPLE_RATE +#define DR_MP3_DEFAULT_SAMPLE_RATE 44100 +#endif +#ifndef DRMP3_SEEK_LEADING_MP3_FRAMES +#define DRMP3_SEEK_LEADING_MP3_FRAMES 2 +#endif + + +// Standard library stuff. +#ifndef DRMP3_ASSERT +#include +#define DRMP3_ASSERT(expression) assert(expression) +#endif +#ifndef DRMP3_COPY_MEMORY +#define DRMP3_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz)) +#endif +#ifndef DRMP3_ZERO_MEMORY +#define DRMP3_ZERO_MEMORY(p, sz) memset((p), 0, (sz)) +#endif +#define DRMP3_ZERO_OBJECT(p) DRMP3_ZERO_MEMORY((p), sizeof(*(p))) +#ifndef DRMP3_MALLOC +#define DRMP3_MALLOC(sz) malloc((sz)) +#endif +#ifndef DRMP3_REALLOC +#define DRMP3_REALLOC(p, sz) realloc((p), (sz)) +#endif +#ifndef DRMP3_FREE +#define DRMP3_FREE(p) free((p)) +#endif + +#define drmp3_assert DRMP3_ASSERT +#define drmp3_copy_memory DRMP3_COPY_MEMORY +#define drmp3_zero_memory DRMP3_ZERO_MEMORY +#define drmp3_zero_object DRMP3_ZERO_OBJECT +#define drmp3_malloc DRMP3_MALLOC +#define drmp3_realloc DRMP3_REALLOC + +#define drmp3_countof(x) (sizeof(x) / sizeof(x[0])) +#define drmp3_max(x, y) (((x) > (y)) ? (x) : (y)) +#define drmp3_min(x, y) (((x) < (y)) ? (x) : (y)) + +#define DRMP3_DATA_CHUNK_SIZE 16384 // The size in bytes of each chunk of data to read from the MP3 stream. minimp3 recommends 16K. + +static inline float drmp3_mix_f32(float x, float y, float a) +{ + return x*(1-a) + y*a; +} + +static void drmp3_blend_f32(float* pOut, float* pInA, float* pInB, float factor, drmp3_uint32 channels) +{ + for (drmp3_uint32 i = 0; i < channels; ++i) { + pOut[i] = drmp3_mix_f32(pInA[i], pInB[i], factor); + } +} + +void drmp3_src_cache_init(drmp3_src* pSRC, drmp3_src_cache* pCache) +{ + drmp3_assert(pSRC != NULL); + drmp3_assert(pCache != NULL); + + pCache->pSRC = pSRC; + pCache->cachedFrameCount = 0; + pCache->iNextFrame = 0; +} + +drmp3_uint64 drmp3_src_cache_read_frames(drmp3_src_cache* pCache, drmp3_uint64 frameCount, float* pFramesOut) +{ + drmp3_assert(pCache != NULL); + drmp3_assert(pCache->pSRC != NULL); + drmp3_assert(pCache->pSRC->onRead != NULL); + drmp3_assert(frameCount > 0); + drmp3_assert(pFramesOut != NULL); + + drmp3_uint32 channels = pCache->pSRC->config.channels; + + drmp3_uint64 totalFramesRead = 0; + while (frameCount > 0) { + // If there's anything in memory go ahead and copy that over first. + drmp3_uint64 framesRemainingInMemory = pCache->cachedFrameCount - pCache->iNextFrame; + drmp3_uint64 framesToReadFromMemory = frameCount; + if (framesToReadFromMemory > framesRemainingInMemory) { + framesToReadFromMemory = framesRemainingInMemory; + } + + drmp3_copy_memory(pFramesOut, pCache->pCachedFrames + pCache->iNextFrame*channels, (drmp3_uint32)(framesToReadFromMemory * channels * sizeof(float))); + pCache->iNextFrame += (drmp3_uint32)framesToReadFromMemory; + + totalFramesRead += framesToReadFromMemory; + frameCount -= framesToReadFromMemory; + if (frameCount == 0) { + break; + } + + + // At this point there are still more frames to read from the client, so we'll need to reload the cache with fresh data. + drmp3_assert(frameCount > 0); + pFramesOut += framesToReadFromMemory * channels; + + pCache->iNextFrame = 0; + pCache->cachedFrameCount = 0; + + drmp3_uint32 framesToReadFromClient = drmp3_countof(pCache->pCachedFrames) / pCache->pSRC->config.channels; + if (framesToReadFromClient > pCache->pSRC->config.cacheSizeInFrames) { + framesToReadFromClient = pCache->pSRC->config.cacheSizeInFrames; + } + + pCache->cachedFrameCount = (drmp3_uint32)pCache->pSRC->onRead(pCache->pSRC, framesToReadFromClient, pCache->pCachedFrames, pCache->pSRC->pUserData); + + + // Get out of this loop if nothing was able to be retrieved. + if (pCache->cachedFrameCount == 0) { + break; + } + } + + return totalFramesRead; +} + + +drmp3_uint64 drmp3_src_read_frames_passthrough(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut, drmp3_bool32 flush); +drmp3_uint64 drmp3_src_read_frames_linear(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut, drmp3_bool32 flush); + +drmp3_bool32 drmp3_src_init(const drmp3_src_config* pConfig, drmp3_src_read_proc onRead, void* pUserData, drmp3_src* pSRC) +{ + if (pSRC == NULL) return DRMP3_FALSE; + drmp3_zero_object(pSRC); + + if (pConfig == NULL || onRead == NULL) return DRMP3_FALSE; + if (pConfig->channels == 0 || pConfig->channels > 2) return DRMP3_FALSE; + + pSRC->config = *pConfig; + pSRC->onRead = onRead; + pSRC->pUserData = pUserData; + + if (pSRC->config.cacheSizeInFrames > DRMP3_SRC_CACHE_SIZE_IN_FRAMES || pSRC->config.cacheSizeInFrames == 0) { + pSRC->config.cacheSizeInFrames = DRMP3_SRC_CACHE_SIZE_IN_FRAMES; + } + + drmp3_src_cache_init(pSRC, &pSRC->cache); + return DRMP3_TRUE; +} + +drmp3_bool32 drmp3_src_set_input_sample_rate(drmp3_src* pSRC, drmp3_uint32 sampleRateIn) +{ + if (pSRC == NULL) return DRMP3_FALSE; + + // Must have a sample rate of > 0. + if (sampleRateIn == 0) { + return DRMP3_FALSE; + } + + pSRC->config.sampleRateIn = sampleRateIn; + return DRMP3_TRUE; +} + +drmp3_bool32 drmp3_src_set_output_sample_rate(drmp3_src* pSRC, drmp3_uint32 sampleRateOut) +{ + if (pSRC == NULL) return DRMP3_FALSE; + + // Must have a sample rate of > 0. + if (sampleRateOut == 0) { + return DRMP3_FALSE; + } + + pSRC->config.sampleRateOut = sampleRateOut; + return DRMP3_TRUE; +} + +drmp3_uint64 drmp3_src_read_frames_ex(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut, drmp3_bool32 flush) +{ + if (pSRC == NULL || frameCount == 0 || pFramesOut == NULL) return 0; + + drmp3_src_algorithm algorithm = pSRC->config.algorithm; + + // Always use passthrough if the sample rates are the same. + if (pSRC->config.sampleRateIn == pSRC->config.sampleRateOut) { + algorithm = drmp3_src_algorithm_none; + } + + // Could just use a function pointer instead of a switch for this... + switch (algorithm) + { + case drmp3_src_algorithm_none: return drmp3_src_read_frames_passthrough(pSRC, frameCount, pFramesOut, flush); + case drmp3_src_algorithm_linear: return drmp3_src_read_frames_linear(pSRC, frameCount, pFramesOut, flush); + default: return 0; + } +} + +drmp3_uint64 drmp3_src_read_frames(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut) +{ + return drmp3_src_read_frames_ex(pSRC, frameCount, pFramesOut, DRMP3_FALSE); +} + +drmp3_uint64 drmp3_src_read_frames_passthrough(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut, drmp3_bool32 flush) +{ + drmp3_assert(pSRC != NULL); + drmp3_assert(frameCount > 0); + drmp3_assert(pFramesOut != NULL); + + (void)flush; // Passthrough need not care about flushing. + return pSRC->onRead(pSRC, frameCount, pFramesOut, pSRC->pUserData); +} + +drmp3_uint64 drmp3_src_read_frames_linear(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut, drmp3_bool32 flush) +{ + drmp3_assert(pSRC != NULL); + drmp3_assert(frameCount > 0); + drmp3_assert(pFramesOut != NULL); + + // For linear SRC, the bin is only 2 frames: 1 prior, 1 future. + + // Load the bin if necessary. + if (!pSRC->algo.linear.isPrevFramesLoaded) { + drmp3_uint64 framesRead = drmp3_src_cache_read_frames(&pSRC->cache, 1, pSRC->bin); + if (framesRead == 0) { + return 0; + } + pSRC->algo.linear.isPrevFramesLoaded = DRMP3_TRUE; + } + if (!pSRC->algo.linear.isNextFramesLoaded) { + drmp3_uint64 framesRead = drmp3_src_cache_read_frames(&pSRC->cache, 1, pSRC->bin + pSRC->config.channels); + if (framesRead == 0) { + return 0; + } + pSRC->algo.linear.isNextFramesLoaded = DRMP3_TRUE; + } + + double factor = (double)pSRC->config.sampleRateIn / pSRC->config.sampleRateOut; + + drmp3_uint64 totalFramesRead = 0; + while (frameCount > 0) { + // The bin is where the previous and next frames are located. + float* pPrevFrame = pSRC->bin; + float* pNextFrame = pSRC->bin + pSRC->config.channels; + + drmp3_blend_f32((float*)pFramesOut, pPrevFrame, pNextFrame, (float)pSRC->algo.linear.alpha, pSRC->config.channels); + + pSRC->algo.linear.alpha += factor; + + // The new alpha value is how we determine whether or not we need to read fresh frames. + drmp3_uint32 framesToReadFromClient = (drmp3_uint32)pSRC->algo.linear.alpha; + pSRC->algo.linear.alpha = pSRC->algo.linear.alpha - framesToReadFromClient; + + for (drmp3_uint32 i = 0; i < framesToReadFromClient; ++i) { + for (drmp3_uint32 j = 0; j < pSRC->config.channels; ++j) { + pPrevFrame[j] = pNextFrame[j]; + } + + drmp3_uint64 framesRead = drmp3_src_cache_read_frames(&pSRC->cache, 1, pNextFrame); + if (framesRead == 0) { + for (drmp3_uint32 j = 0; j < pSRC->config.channels; ++j) { + pNextFrame[j] = 0; + } + + if (pSRC->algo.linear.isNextFramesLoaded) { + pSRC->algo.linear.isNextFramesLoaded = DRMP3_FALSE; + } else { + if (flush) { + pSRC->algo.linear.isPrevFramesLoaded = DRMP3_FALSE; + } + } + + break; + } + } + + pFramesOut = (drmp3_uint8*)pFramesOut + (1 * pSRC->config.channels * sizeof(float)); + frameCount -= 1; + totalFramesRead += 1; + + // If there's no frames available we need to get out of this loop. + if (!pSRC->algo.linear.isNextFramesLoaded && (!flush || !pSRC->algo.linear.isPrevFramesLoaded)) { + break; + } + } + + return totalFramesRead; +} + + +static size_t drmp3__on_read(drmp3* pMP3, void* pBufferOut, size_t bytesToRead) +{ + size_t bytesRead = pMP3->onRead(pMP3->pUserData, pBufferOut, bytesToRead); + pMP3->streamCursor += bytesRead; + return bytesRead; +} + +static drmp3_bool32 drmp3__on_seek(drmp3* pMP3, int offset, drmp3_seek_origin origin) +{ + drmp3_assert(offset >= 0); + + if (!pMP3->onSeek(pMP3->pUserData, offset, origin)) { + return DRMP3_FALSE; + } + + if (origin == drmp3_seek_origin_start) { + pMP3->streamCursor = (drmp3_uint64)offset; + } else { + pMP3->streamCursor += offset; + } + + return DRMP3_TRUE; +} + +static drmp3_bool32 drmp3__on_seek_64(drmp3* pMP3, drmp3_uint64 offset, drmp3_seek_origin origin) +{ + if (offset <= 0x7FFFFFFF) { + return drmp3__on_seek(pMP3, (int)offset, origin); + } + + + // Getting here "offset" is too large for a 32-bit integer. We just keep seeking forward until we hit the offset. + if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, drmp3_seek_origin_start)) { + return DRMP3_FALSE; + } + + offset -= 0x7FFFFFFF; + while (offset > 0) { + if (offset <= 0x7FFFFFFF) { + if (!drmp3__on_seek(pMP3, (int)offset, drmp3_seek_origin_current)) { + return DRMP3_FALSE; + } + offset = 0; + } else { + if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, drmp3_seek_origin_current)) { + return DRMP3_FALSE; + } + offset -= 0x7FFFFFFF; + } + } + + return DRMP3_TRUE; +} + + + + +static drmp3_uint32 drmp3_decode_next_frame_ex(drmp3* pMP3, drmp3d_sample_t* pPCMFrames, drmp3_bool32 discard) +{ + drmp3_assert(pMP3 != NULL); + drmp3_assert(pMP3->onRead != NULL); + + if (pMP3->atEnd) { + return 0; + } + + drmp3_uint32 pcmFramesRead = 0; + do { + // minimp3 recommends doing data submission in 16K chunks. If we don't have at least 16K bytes available, get more. + if (pMP3->dataSize < DRMP3_DATA_CHUNK_SIZE) { + if (pMP3->dataCapacity < DRMP3_DATA_CHUNK_SIZE) { + pMP3->dataCapacity = DRMP3_DATA_CHUNK_SIZE; + drmp3_uint8* pNewData = (drmp3_uint8*)drmp3_realloc(pMP3->pData, pMP3->dataCapacity); + if (pNewData == NULL) { + return 0; // Out of memory. + } + + pMP3->pData = pNewData; + } + + size_t bytesRead = drmp3__on_read(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize)); + if (bytesRead == 0) { + if (pMP3->dataSize == 0) { + pMP3->atEnd = DRMP3_TRUE; + return 0; // No data. + } + } + + pMP3->dataSize += bytesRead; + } + + if (pMP3->dataSize > INT_MAX) { + pMP3->atEnd = DRMP3_TRUE; + return 0; // File too big. + } + + drmp3dec_frame_info info; + pcmFramesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->pData, (int)pMP3->dataSize, pPCMFrames, &info); // <-- Safe size_t -> int conversion thanks to the check above. + + // Consume the data. + size_t leftoverDataSize = (pMP3->dataSize - (size_t)info.frame_bytes); + if (info.frame_bytes > 0) { + memmove(pMP3->pData, pMP3->pData + info.frame_bytes, leftoverDataSize); + pMP3->dataSize = leftoverDataSize; + } + + // pcmFramesRead will be equal to 0 if decoding failed. If it is zero and info.frame_bytes > 0 then we have successfully + // decoded the frame. A special case is if we are wanting to discard the frame, in which case we return successfully. + if (pcmFramesRead > 0 || (info.frame_bytes > 0 && discard)) { + pcmFramesRead = drmp3_hdr_frame_samples(pMP3->decoder.header); + pMP3->pcmFramesConsumedInMP3Frame = 0; + pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead; + pMP3->mp3FrameChannels = info.channels; + pMP3->mp3FrameSampleRate = info.hz; + drmp3_src_set_input_sample_rate(&pMP3->src, pMP3->mp3FrameSampleRate); + break; + } else if (info.frame_bytes == 0) { + // Need more data. minimp3 recommends doing data submission in 16K chunks. + if (pMP3->dataCapacity == pMP3->dataSize) { + // No room. Expand. + pMP3->dataCapacity += DRMP3_DATA_CHUNK_SIZE; + drmp3_uint8* pNewData = (drmp3_uint8*)drmp3_realloc(pMP3->pData, pMP3->dataCapacity); + if (pNewData == NULL) { + return 0; // Out of memory. + } + + pMP3->pData = pNewData; + } + + // Fill in a chunk. + size_t bytesRead = drmp3__on_read(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize)); + if (bytesRead == 0) { + pMP3->atEnd = DRMP3_TRUE; + return 0; // Error reading more data. + } + + pMP3->dataSize += bytesRead; + } + } while (DRMP3_TRUE); + + return pcmFramesRead; +} + +static drmp3_uint32 drmp3_decode_next_frame(drmp3* pMP3) +{ + drmp3_assert(pMP3 != NULL); + return drmp3_decode_next_frame_ex(pMP3, (drmp3d_sample_t*)pMP3->pcmFrames, DRMP3_FALSE); +} + +#if 0 +static drmp3_uint32 drmp3_seek_next_frame(drmp3* pMP3) +{ + drmp3_assert(pMP3 != NULL); + + drmp3_uint32 pcmFrameCount = drmp3_decode_next_frame_ex(pMP3, NULL); + if (pcmFrameCount == 0) { + return 0; + } + + // We have essentially just skipped past the frame, so just set the remaining samples to 0. + pMP3->currentPCMFrame += pcmFrameCount; + pMP3->pcmFramesConsumedInMP3Frame = pcmFrameCount; + pMP3->pcmFramesRemainingInMP3Frame = 0; + + return pcmFrameCount; +} +#endif + +static drmp3_uint64 drmp3_read_src(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut, void* pUserData) +{ + drmp3* pMP3 = (drmp3*)pUserData; + drmp3_assert(pMP3 != NULL); + drmp3_assert(pMP3->onRead != NULL); + + float* pFramesOutF = (float*)pFramesOut; + drmp3_uint64 totalFramesRead = 0; + + while (frameCount > 0) { + // Read from the in-memory buffer first. + while (pMP3->pcmFramesRemainingInMP3Frame > 0 && frameCount > 0) { + drmp3d_sample_t* frames = (drmp3d_sample_t*)pMP3->pcmFrames; +#ifndef DR_MP3_FLOAT_OUTPUT + if (pMP3->mp3FrameChannels == 1) { + if (pMP3->channels == 1) { + // Mono -> Mono. + pFramesOutF[0] = frames[pMP3->pcmFramesConsumedInMP3Frame] / 32768.0f; + } else { + // Mono -> Stereo. + pFramesOutF[0] = frames[pMP3->pcmFramesConsumedInMP3Frame] / 32768.0f; + pFramesOutF[1] = frames[pMP3->pcmFramesConsumedInMP3Frame] / 32768.0f; + } + } else { + if (pMP3->channels == 1) { + // Stereo -> Mono + float sample = 0; + sample += frames[(pMP3->pcmFramesConsumedInMP3Frame*pMP3->mp3FrameChannels)+0] / 32768.0f; + sample += frames[(pMP3->pcmFramesConsumedInMP3Frame*pMP3->mp3FrameChannels)+1] / 32768.0f; + pFramesOutF[0] = sample * 0.5f; + } else { + // Stereo -> Stereo + pFramesOutF[0] = frames[(pMP3->pcmFramesConsumedInMP3Frame*pMP3->mp3FrameChannels)+0] / 32768.0f; + pFramesOutF[1] = frames[(pMP3->pcmFramesConsumedInMP3Frame*pMP3->mp3FrameChannels)+1] / 32768.0f; + } + } +#else + if (pMP3->mp3FrameChannels == 1) { + if (pMP3->channels == 1) { + // Mono -> Mono. + pFramesOutF[0] = frames[pMP3->pcmFramesConsumedInMP3Frame]; + } else { + // Mono -> Stereo. + pFramesOutF[0] = frames[pMP3->pcmFramesConsumedInMP3Frame]; + pFramesOutF[1] = frames[pMP3->pcmFramesConsumedInMP3Frame]; + } + } else { + if (pMP3->channels == 1) { + // Stereo -> Mono + float sample = 0; + sample += frames[(pMP3->pcmFramesConsumedInMP3Frame*pMP3->mp3FrameChannels)+0]; + sample += frames[(pMP3->pcmFramesConsumedInMP3Frame*pMP3->mp3FrameChannels)+1]; + pFramesOutF[0] = sample * 0.5f; + } else { + // Stereo -> Stereo + pFramesOutF[0] = frames[(pMP3->pcmFramesConsumedInMP3Frame*pMP3->mp3FrameChannels)+0]; + pFramesOutF[1] = frames[(pMP3->pcmFramesConsumedInMP3Frame*pMP3->mp3FrameChannels)+1]; + } + } +#endif + + pMP3->pcmFramesConsumedInMP3Frame += 1; + pMP3->pcmFramesRemainingInMP3Frame -= 1; + totalFramesRead += 1; + frameCount -= 1; + pFramesOutF += pSRC->config.channels; + } + + if (frameCount == 0) { + break; + } + + drmp3_assert(pMP3->pcmFramesRemainingInMP3Frame == 0); + + // At this point we have exhausted our in-memory buffer so we need to re-fill. Note that the sample rate may have changed + // at this point which means we'll also need to update our sample rate conversion pipeline. + if (drmp3_decode_next_frame(pMP3) == 0) { + break; + } + } + + return totalFramesRead; +} + +drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_config* pConfig) +{ + drmp3_assert(pMP3 != NULL); + drmp3_assert(onRead != NULL); + + // This function assumes the output object has already been reset to 0. Do not do that here, otherwise things will break. + drmp3dec_init(&pMP3->decoder); + + // The config can be null in which case we use defaults. + drmp3_config config; + if (pConfig != NULL) { + config = *pConfig; + } else { + drmp3_zero_object(&config); + } + + pMP3->channels = config.outputChannels; + if (pMP3->channels == 0) { + pMP3->channels = DR_MP3_DEFAULT_CHANNELS; + } + + // Cannot have more than 2 channels. + if (pMP3->channels > 2) { + pMP3->channels = 2; + } + + pMP3->sampleRate = config.outputSampleRate; + if (pMP3->sampleRate == 0) { + pMP3->sampleRate = DR_MP3_DEFAULT_SAMPLE_RATE; + } + + pMP3->onRead = onRead; + pMP3->onSeek = onSeek; + pMP3->pUserData = pUserData; + + // We need a sample rate converter for converting the sample rate from the MP3 frames to the requested output sample rate. + drmp3_src_config srcConfig; + drmp3_zero_object(&srcConfig); + srcConfig.sampleRateIn = DR_MP3_DEFAULT_SAMPLE_RATE; + srcConfig.sampleRateOut = pMP3->sampleRate; + srcConfig.channels = pMP3->channels; + srcConfig.algorithm = drmp3_src_algorithm_linear; + if (!drmp3_src_init(&srcConfig, drmp3_read_src, pMP3, &pMP3->src)) { + drmp3_uninit(pMP3); + return DRMP3_FALSE; + } + + // Decode the first frame to confirm that it is indeed a valid MP3 stream. + if (!drmp3_decode_next_frame(pMP3)) { + drmp3_uninit(pMP3); + return DRMP3_FALSE; // Not a valid MP3 stream. + } + + return DRMP3_TRUE; +} + +drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_config* pConfig) +{ + if (pMP3 == NULL || onRead == NULL) { + return DRMP3_FALSE; + } + + drmp3_zero_object(pMP3); + return drmp3_init_internal(pMP3, onRead, onSeek, pUserData, pConfig); +} + + +static size_t drmp3__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead) +{ + drmp3* pMP3 = (drmp3*)pUserData; + drmp3_assert(pMP3 != NULL); + drmp3_assert(pMP3->memory.dataSize >= pMP3->memory.currentReadPos); + + size_t bytesRemaining = pMP3->memory.dataSize - pMP3->memory.currentReadPos; + if (bytesToRead > bytesRemaining) { + bytesToRead = bytesRemaining; + } + + if (bytesToRead > 0) { + drmp3_copy_memory(pBufferOut, pMP3->memory.pData + pMP3->memory.currentReadPos, bytesToRead); + pMP3->memory.currentReadPos += bytesToRead; + } + + return bytesToRead; +} + +static drmp3_bool32 drmp3__on_seek_memory(void* pUserData, int byteOffset, drmp3_seek_origin origin) +{ + drmp3* pMP3 = (drmp3*)pUserData; + drmp3_assert(pMP3 != NULL); + + if (origin == drmp3_seek_origin_current) { + if (byteOffset > 0) { + if (pMP3->memory.currentReadPos + byteOffset > pMP3->memory.dataSize) { + byteOffset = (int)(pMP3->memory.dataSize - pMP3->memory.currentReadPos); // Trying to seek too far forward. + } + } else { + if (pMP3->memory.currentReadPos < (size_t)-byteOffset) { + byteOffset = -(int)pMP3->memory.currentReadPos; // Trying to seek too far backwards. + } + } + + // This will never underflow thanks to the clamps above. + pMP3->memory.currentReadPos += byteOffset; + } else { + if ((drmp3_uint32)byteOffset <= pMP3->memory.dataSize) { + pMP3->memory.currentReadPos = byteOffset; + } else { + pMP3->memory.currentReadPos = pMP3->memory.dataSize; // Trying to seek too far forward. + } + } + + return DRMP3_TRUE; +} + +drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_config* pConfig) +{ + if (pMP3 == NULL) { + return DRMP3_FALSE; + } + + drmp3_zero_object(pMP3); + + if (pData == NULL || dataSize == 0) { + return DRMP3_FALSE; + } + + pMP3->memory.pData = (const drmp3_uint8*)pData; + pMP3->memory.dataSize = dataSize; + pMP3->memory.currentReadPos = 0; + + return drmp3_init_internal(pMP3, drmp3__on_read_memory, drmp3__on_seek_memory, pMP3, pConfig); +} + + +#ifndef DR_MP3_NO_STDIO +#include + +static size_t drmp3__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead) +{ + return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData); +} + +static drmp3_bool32 drmp3__on_seek_stdio(void* pUserData, int offset, drmp3_seek_origin origin) +{ + return fseek((FILE*)pUserData, offset, (origin == drmp3_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0; +} + +drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* filePath, const drmp3_config* pConfig) +{ + FILE* pFile; +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (fopen_s(&pFile, filePath, "rb") != 0) { + return DRMP3_FALSE; + } +#else + pFile = fopen(filePath, "rb"); + if (pFile == NULL) { + return DRMP3_FALSE; + } +#endif + + return drmp3_init(pMP3, drmp3__on_read_stdio, drmp3__on_seek_stdio, (void*)pFile, pConfig); +} +#endif + +void drmp3_uninit(drmp3* pMP3) +{ + if (pMP3 == NULL) { + return; + } + +#ifndef DR_MP3_NO_STDIO + if (pMP3->onRead == drmp3__on_read_stdio) { + fclose((FILE*)pMP3->pUserData); + } +#endif + + drmp3_free(pMP3->pData); +} + +drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 framesToRead, float* pBufferOut) +{ + if (pMP3 == NULL || pMP3->onRead == NULL) { + return 0; + } + + drmp3_uint64 totalFramesRead = 0; + + if (pBufferOut == NULL) { + float temp[4096]; + while (framesToRead > 0) { + drmp3_uint64 framesToReadRightNow = sizeof(temp)/sizeof(temp[0]) / pMP3->channels; + if (framesToReadRightNow > framesToRead) { + framesToReadRightNow = framesToRead; + } + + drmp3_uint64 framesJustRead = drmp3_read_pcm_frames_f32(pMP3, framesToReadRightNow, temp); + if (framesJustRead == 0) { + break; + } + + framesToRead -= framesJustRead; + totalFramesRead += framesJustRead; + } + } else { + totalFramesRead = drmp3_src_read_frames_ex(&pMP3->src, framesToRead, pBufferOut, DRMP3_TRUE); + pMP3->currentPCMFrame += totalFramesRead; + } + + return totalFramesRead; +} + +void drmp3_reset(drmp3* pMP3) +{ + drmp3_assert(pMP3 != NULL); + + pMP3->pcmFramesConsumedInMP3Frame = 0; + pMP3->pcmFramesRemainingInMP3Frame = 0; + pMP3->currentPCMFrame = 0; + pMP3->dataSize = 0; + pMP3->atEnd = DRMP3_FALSE; + pMP3->src.bin[0] = 0; + pMP3->src.bin[1] = 0; + pMP3->src.bin[2] = 0; + pMP3->src.bin[3] = 0; + pMP3->src.cache.cachedFrameCount = 0; + pMP3->src.cache.iNextFrame = 0; + pMP3->src.algo.linear.alpha = 0; + pMP3->src.algo.linear.isNextFramesLoaded = 0; + pMP3->src.algo.linear.isPrevFramesLoaded = 0; + //drmp3_zero_object(&pMP3->decoder); + drmp3dec_init(&pMP3->decoder); +} + +drmp3_bool32 drmp3_seek_to_start_of_stream(drmp3* pMP3) +{ + drmp3_assert(pMP3 != NULL); + drmp3_assert(pMP3->onSeek != NULL); + + // Seek to the start of the stream to begin with. + if (!drmp3__on_seek(pMP3, 0, drmp3_seek_origin_start)) { + return DRMP3_FALSE; + } + + // Clear any cached data. + drmp3_reset(pMP3); + return DRMP3_TRUE; +} + +float drmp3_get_cached_pcm_frame_count_from_src(drmp3* pMP3) +{ + return (pMP3->src.cache.cachedFrameCount - pMP3->src.cache.iNextFrame) + (float)pMP3->src.algo.linear.alpha; +} + +float drmp3_get_pcm_frames_remaining_in_mp3_frame(drmp3* pMP3) +{ + float factor = (float)pMP3->src.config.sampleRateOut / (float)pMP3->src.config.sampleRateIn; + float frameCountPreSRC = drmp3_get_cached_pcm_frame_count_from_src(pMP3) + pMP3->pcmFramesRemainingInMP3Frame; + return frameCountPreSRC * factor; +} + +// NOTE ON SEEKING +// =============== +// The seeking code below is a complete mess and is broken for cases when the sample rate changes. The problem +// is with the resampling and the crappy resampler used by dr_mp3. What needs to happen is the following: +// +// 1) The resampler needs to be replaced. +// 2) The resampler has state which needs to be updated whenever an MP3 frame is decoded outside of +// drmp3_read_pcm_frames_f32(). The resampler needs an API to "flush" some imaginary input so that it's +// state is updated accordingly. + +drmp3_bool32 drmp3_seek_forward_by_pcm_frames__brute_force(drmp3* pMP3, drmp3_uint64 frameOffset) +{ +#if 0 + // MP3 is a bit annoying when it comes to seeking because of the bit reservoir. It basically means that an MP3 frame can possibly + // depend on some of the data of prior frames. This means it's not as simple as seeking to the first byte of the MP3 frame that + // contains the sample because that MP3 frame will need the data from the previous MP3 frame (which we just seeked past!). To + // resolve this we seek past a number of MP3 frames up to a point, and then read-and-discard the remainder. + drmp3_uint64 maxFramesToReadAndDiscard = (drmp3_uint64)(DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME * 3 * ((float)pMP3->src.config.sampleRateOut / (float)pMP3->src.config.sampleRateIn)); + + // Now get rid of leading whole frames. + while (frameOffset > maxFramesToReadAndDiscard) { + float pcmFramesRemainingInCurrentMP3FrameF = drmp3_get_pcm_frames_remaining_in_mp3_frame(pMP3); + drmp3_uint32 pcmFramesRemainingInCurrentMP3Frame = (drmp3_uint32)pcmFramesRemainingInCurrentMP3FrameF; + if (frameOffset > pcmFramesRemainingInCurrentMP3Frame) { + frameOffset -= pcmFramesRemainingInCurrentMP3Frame; + pMP3->currentPCMFrame += pcmFramesRemainingInCurrentMP3Frame; + pMP3->pcmFramesConsumedInMP3Frame += pMP3->pcmFramesRemainingInMP3Frame; + pMP3->pcmFramesRemainingInMP3Frame = 0; + } else { + break; + } + + drmp3_uint32 pcmFrameCount = drmp3_decode_next_frame_ex(pMP3, pMP3->pcmFrames, DRMP3_FALSE); + if (pcmFrameCount == 0) { + break; + } + } + + // The last step is to read-and-discard any remaining PCM frames to make it sample-exact. + drmp3_uint64 framesRead = drmp3_read_pcm_frames_f32(pMP3, frameOffset, NULL); + if (framesRead != frameOffset) { + return DRMP3_FALSE; + } +#else + // Just using a dumb read-and-discard for now pending updates to the resampler. + drmp3_uint64 framesRead = drmp3_read_pcm_frames_f32(pMP3, frameOffset, NULL); + if (framesRead != frameOffset) { + return DRMP3_FALSE; + } +#endif + + return DRMP3_TRUE; +} + +drmp3_bool32 drmp3_seek_to_pcm_frame__brute_force(drmp3* pMP3, drmp3_uint64 frameIndex) +{ + drmp3_assert(pMP3 != NULL); + + if (frameIndex == pMP3->currentPCMFrame) { + return DRMP3_TRUE; + } + + // If we're moving foward we just read from where we're at. Otherwise we need to move back to the start of + // the stream and read from the beginning. + //drmp3_uint64 framesToReadAndDiscard; + if (frameIndex < pMP3->currentPCMFrame) { + // Moving backward. Move to the start of the stream and then move forward. + if (!drmp3_seek_to_start_of_stream(pMP3)) { + return DRMP3_FALSE; + } + } + + drmp3_assert(frameIndex >= pMP3->currentPCMFrame); + return drmp3_seek_forward_by_pcm_frames__brute_force(pMP3, (frameIndex - pMP3->currentPCMFrame)); +} + +drmp3_bool32 drmp3_find_closest_seek_point(drmp3* pMP3, drmp3_uint64 frameIndex, drmp3_uint32* pSeekPointIndex) +{ + drmp3_assert(pSeekPointIndex != NULL); + + if (frameIndex < pMP3->pSeekPoints[0].pcmFrameIndex) { + return DRMP3_FALSE; + } + + // Linear search for simplicity to begin with while I'm getting this thing working. Once it's all working change this to a binary search. + for (drmp3_uint32 iSeekPoint = 0; iSeekPoint < pMP3->seekPointCount; ++iSeekPoint) { + if (pMP3->pSeekPoints[iSeekPoint].pcmFrameIndex > frameIndex) { + break; // Found it. + } + + *pSeekPointIndex = iSeekPoint; + } + + return DRMP3_TRUE; +} + +drmp3_bool32 drmp3_seek_to_pcm_frame__seek_table(drmp3* pMP3, drmp3_uint64 frameIndex) +{ + drmp3_assert(pMP3 != NULL); + drmp3_assert(pMP3->pSeekPoints != NULL); + drmp3_assert(pMP3->seekPointCount > 0); + + drmp3_seek_point seekPoint; + + // If there is no prior seekpoint it means the target PCM frame comes before the first seek point. Just assume a seekpoint at the start of the file in this case. + drmp3_uint32 priorSeekPointIndex; + if (drmp3_find_closest_seek_point(pMP3, frameIndex, &priorSeekPointIndex)) { + seekPoint = pMP3->pSeekPoints[priorSeekPointIndex]; + } else { + seekPoint.seekPosInBytes = 0; + seekPoint.pcmFrameIndex = 0; + seekPoint.mp3FramesToDiscard = 0; + seekPoint.pcmFramesToDiscard = 0; + } + + // First thing to do is seek to the first byte of the relevant MP3 frame. + if (!drmp3__on_seek_64(pMP3, seekPoint.seekPosInBytes, drmp3_seek_origin_start)) { + return DRMP3_FALSE; // Failed to seek. + } + + // Clear any cached data. + drmp3_reset(pMP3); + + // Whole MP3 frames need to be discarded first. + for (drmp3_uint16 iMP3Frame = 0; iMP3Frame < seekPoint.mp3FramesToDiscard; ++iMP3Frame) { + // Pass in non-null for the last frame because we want to ensure the sample rate converter is preloaded correctly. + drmp3d_sample_t* pPCMFrames = NULL; + if (iMP3Frame == seekPoint.mp3FramesToDiscard-1) { + pPCMFrames = (drmp3d_sample_t*)pMP3->pcmFrames; + } + + // We first need to decode the next frame, and then we need to flush the resampler. + drmp3_uint32 pcmFramesReadPreSRC = drmp3_decode_next_frame_ex(pMP3, pPCMFrames, DRMP3_TRUE); + if (pcmFramesReadPreSRC == 0) { + return DRMP3_FALSE; + } + } + + // We seeked to an MP3 frame in the raw stream so we need to make sure the current PCM frame is set correctly. + pMP3->currentPCMFrame = seekPoint.pcmFrameIndex - seekPoint.pcmFramesToDiscard; + + // Update resampler. This is wrong. Need to instead update it on a per MP3 frame basis. Also broken for cases when + // the sample rate is being reduced in my testing. Should work fine when the input and output sample rate is the same + // or a clean multiple. + pMP3->src.algo.linear.alpha = pMP3->currentPCMFrame * ((double)pMP3->src.config.sampleRateIn / pMP3->src.config.sampleRateOut); + pMP3->src.algo.linear.alpha = pMP3->src.algo.linear.alpha - (drmp3_uint32)(pMP3->src.algo.linear.alpha); + if (pMP3->src.algo.linear.alpha > 0) { + pMP3->src.algo.linear.isPrevFramesLoaded = 1; + } + + // Now at this point we can follow the same process as the brute force technique where we just skip over unnecessary MP3 frames and then + // read-and-discard at least 2 whole MP3 frames. + drmp3_uint64 leftoverFrames = frameIndex - pMP3->currentPCMFrame; + return drmp3_seek_forward_by_pcm_frames__brute_force(pMP3, leftoverFrames); +} + +drmp3_bool32 drmp3_seek_to_pcm_frame(drmp3* pMP3, drmp3_uint64 frameIndex) +{ + if (pMP3 == NULL || pMP3->onSeek == NULL) { + return DRMP3_FALSE; + } + + if (frameIndex == 0) { + return drmp3_seek_to_start_of_stream(pMP3); + } + + // Use the seek table if we have one. + if (pMP3->pSeekPoints != NULL && pMP3->seekPointCount > 0) { + return drmp3_seek_to_pcm_frame__seek_table(pMP3, frameIndex); + } else { + return drmp3_seek_to_pcm_frame__brute_force(pMP3, frameIndex); + } +} + +drmp3_bool32 drmp3_get_mp3_and_pcm_frame_count(drmp3* pMP3, drmp3_uint64* pMP3FrameCount, drmp3_uint64* pPCMFrameCount) +{ + if (pMP3 == NULL) { + return DRMP3_FALSE; + } + + // The way this works is we move back to the start of the stream, iterate over each MP3 frame and calculate the frame count based + // on our output sample rate, the seek back to the PCM frame we were sitting on before calling this function. + + // The stream must support seeking for this to work. + if (pMP3->onSeek == NULL) { + return DRMP3_FALSE; + } + + // We'll need to seek back to where we were, so grab the PCM frame we're currently sitting on so we can restore later. + drmp3_uint64 currentPCMFrame = pMP3->currentPCMFrame; + + if (!drmp3_seek_to_start_of_stream(pMP3)) { + return DRMP3_FALSE; + } + + drmp3_uint64 totalPCMFrameCount = 0; + drmp3_uint64 totalMP3FrameCount = 0; + + float totalPCMFrameCountFractionalPart = 0; // <-- With resampling there will be a fractional part to each MP3 frame that we need to accumulate. + for (;;) { + drmp3_uint32 pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL, DRMP3_FALSE); + if (pcmFramesInCurrentMP3FrameIn == 0) { + break; + } + + float srcRatio = (float)pMP3->mp3FrameSampleRate / (float)pMP3->sampleRate; + drmp3_assert(srcRatio > 0); + + float pcmFramesInCurrentMP3FrameOutF = totalPCMFrameCountFractionalPart + (pcmFramesInCurrentMP3FrameIn / srcRatio); + drmp3_uint32 pcmFramesInCurrentMP3FrameOut = (drmp3_uint32)pcmFramesInCurrentMP3FrameOutF; + totalPCMFrameCountFractionalPart = pcmFramesInCurrentMP3FrameOutF - pcmFramesInCurrentMP3FrameOut; + totalPCMFrameCount += pcmFramesInCurrentMP3FrameOut; + totalMP3FrameCount += 1; + } + + // Finally, we need to seek back to where we were. + if (!drmp3_seek_to_start_of_stream(pMP3)) { + return DRMP3_FALSE; + } + + if (!drmp3_seek_to_pcm_frame(pMP3, currentPCMFrame)) { + return DRMP3_FALSE; + } + + if (pMP3FrameCount != NULL) { + *pMP3FrameCount = totalMP3FrameCount; + } + if (pPCMFrameCount != NULL) { + *pPCMFrameCount = totalPCMFrameCount; + } + + return DRMP3_TRUE; +} + +drmp3_uint64 drmp3_get_pcm_frame_count(drmp3* pMP3) +{ + drmp3_uint64 totalPCMFrameCount; + if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, NULL, &totalPCMFrameCount)) { + return 0; + } + + return totalPCMFrameCount; +} + +drmp3_uint64 drmp3_get_mp3_frame_count(drmp3* pMP3) +{ + drmp3_uint64 totalMP3FrameCount; + if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, &totalMP3FrameCount, NULL)) { + return 0; + } + + return totalMP3FrameCount; +} + +void drmp3__accumulate_running_pcm_frame_count(drmp3* pMP3, drmp3_uint32 pcmFrameCountIn, drmp3_uint64* pRunningPCMFrameCount, float* pRunningPCMFrameCountFractionalPart) +{ + float srcRatio = (float)pMP3->mp3FrameSampleRate / (float)pMP3->sampleRate; + drmp3_assert(srcRatio > 0); + + float pcmFrameCountOutF = *pRunningPCMFrameCountFractionalPart + (pcmFrameCountIn / srcRatio); + drmp3_uint32 pcmFrameCountOut = (drmp3_uint32)pcmFrameCountOutF; + *pRunningPCMFrameCountFractionalPart = pcmFrameCountOutF - pcmFrameCountOut; + *pRunningPCMFrameCount += pcmFrameCountOut; +} + +typedef struct +{ + drmp3_uint64 bytePos; + drmp3_uint64 pcmFrameIndex; // <-- After sample rate conversion. +} drmp3__seeking_mp3_frame_info; + +drmp3_bool32 drmp3_calculate_seek_points(drmp3* pMP3, drmp3_uint32* pSeekPointCount, drmp3_seek_point* pSeekPoints) +{ + if (pMP3 == NULL || pSeekPointCount == NULL || pSeekPoints == NULL) { + return DRMP3_FALSE; // Invalid args. + } + + drmp3_uint32 seekPointCount = *pSeekPointCount; + if (seekPointCount == 0) { + return DRMP3_FALSE; // The client has requested no seek points. Consider this to be invalid arguments since the client has probably not intended this. + } + + // We'll need to seek back to the current sample after calculating the seekpoints so we need to go ahead and grab the current location at the top. + drmp3_uint64 currentPCMFrame = pMP3->currentPCMFrame; + + // We never do more than the total number of MP3 frames and we limit it to 32-bits. + drmp3_uint64 totalMP3FrameCount; + drmp3_uint64 totalPCMFrameCount; + if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, &totalMP3FrameCount, &totalPCMFrameCount)) { + return DRMP3_FALSE; + } + + // If there's less than DRMP3_SEEK_LEADING_MP3_FRAMES+1 frames we just report 1 seek point which will be the very start of the stream. + if (totalMP3FrameCount < DRMP3_SEEK_LEADING_MP3_FRAMES+1) { + seekPointCount = 1; + pSeekPoints[0].seekPosInBytes = 0; + pSeekPoints[0].pcmFrameIndex = 0; + pSeekPoints[0].mp3FramesToDiscard = 0; + pSeekPoints[0].pcmFramesToDiscard = 0; + } else { + if (seekPointCount > totalMP3FrameCount-1) { + seekPointCount = (drmp3_uint32)totalMP3FrameCount-1; + } + + drmp3_uint64 pcmFramesBetweenSeekPoints = totalPCMFrameCount / (seekPointCount+1); + + // Here is where we actually calculate the seek points. We need to start by moving the start of the stream. We then enumerate over each + // MP3 frame. + if (!drmp3_seek_to_start_of_stream(pMP3)) { + return DRMP3_FALSE; + } + + // We need to cache the byte positions of the previous MP3 frames. As a new MP3 frame is iterated, we cycle the byte positions in this + // array. The value in the first item in this array is the byte position that will be reported in the next seek point. + drmp3__seeking_mp3_frame_info mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES+1]; + + drmp3_uint64 runningPCMFrameCount = 0; + float runningPCMFrameCountFractionalPart = 0; + + // We need to initialize the array of MP3 byte positions for the leading MP3 frames. + for (int iMP3Frame = 0; iMP3Frame < DRMP3_SEEK_LEADING_MP3_FRAMES+1; ++iMP3Frame) { + // The byte position of the next frame will be the stream's cursor position, minus whatever is sitting in the buffer. + drmp3_assert(pMP3->streamCursor >= pMP3->dataSize); + mp3FrameInfo[iMP3Frame].bytePos = pMP3->streamCursor - pMP3->dataSize; + mp3FrameInfo[iMP3Frame].pcmFrameIndex = runningPCMFrameCount; + + // We need to get information about this frame so we can know how many samples it contained. + drmp3_uint32 pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL, DRMP3_FALSE); + if (pcmFramesInCurrentMP3FrameIn == 0) { + return DRMP3_FALSE; // This should never happen. + } + + drmp3__accumulate_running_pcm_frame_count(pMP3, pcmFramesInCurrentMP3FrameIn, &runningPCMFrameCount, &runningPCMFrameCountFractionalPart); + } + + // At this point we will have extracted the byte positions of the leading MP3 frames. We can now start iterating over each seek point and + // calculate them. + drmp3_uint64 nextTargetPCMFrame = 0; + for (drmp3_uint32 iSeekPoint = 0; iSeekPoint < seekPointCount; ++iSeekPoint) { + nextTargetPCMFrame += pcmFramesBetweenSeekPoints; + + for (;;) { + if (nextTargetPCMFrame < runningPCMFrameCount) { + // The next seek point is in the current MP3 frame. + pSeekPoints[iSeekPoint].seekPosInBytes = mp3FrameInfo[0].bytePos; + pSeekPoints[iSeekPoint].pcmFrameIndex = nextTargetPCMFrame; + pSeekPoints[iSeekPoint].mp3FramesToDiscard = DRMP3_SEEK_LEADING_MP3_FRAMES; + pSeekPoints[iSeekPoint].pcmFramesToDiscard = (drmp3_uint16)(nextTargetPCMFrame - mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES-1].pcmFrameIndex); + break; + } else { + // The next seek point is not in the current MP3 frame, so continue on to the next one. The first thing to do is cycle the cached + // MP3 frame info. + for (size_t i = 0; i < drmp3_countof(mp3FrameInfo)-1; ++i) { + mp3FrameInfo[i] = mp3FrameInfo[i+1]; + } + + // Cache previous MP3 frame info. + mp3FrameInfo[drmp3_countof(mp3FrameInfo)-1].bytePos = pMP3->streamCursor - pMP3->dataSize; + mp3FrameInfo[drmp3_countof(mp3FrameInfo)-1].pcmFrameIndex = runningPCMFrameCount; + + // Go to the next MP3 frame. This shouldn't ever fail, but just in case it does we just set the seek point and break. If it happens, it + // should only ever do it for the last seek point. + drmp3_uint32 pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL, DRMP3_TRUE); + if (pcmFramesInCurrentMP3FrameIn == 0) { + pSeekPoints[iSeekPoint].seekPosInBytes = mp3FrameInfo[0].bytePos; + pSeekPoints[iSeekPoint].pcmFrameIndex = nextTargetPCMFrame; + pSeekPoints[iSeekPoint].mp3FramesToDiscard = DRMP3_SEEK_LEADING_MP3_FRAMES; + pSeekPoints[iSeekPoint].pcmFramesToDiscard = (drmp3_uint16)(nextTargetPCMFrame - mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES-1].pcmFrameIndex); + break; + } + + drmp3__accumulate_running_pcm_frame_count(pMP3, pcmFramesInCurrentMP3FrameIn, &runningPCMFrameCount, &runningPCMFrameCountFractionalPart); + } + } + } + + // Finally, we need to seek back to where we were. + if (!drmp3_seek_to_start_of_stream(pMP3)) { + return DRMP3_FALSE; + } + if (!drmp3_seek_to_pcm_frame(pMP3, currentPCMFrame)) { + return DRMP3_FALSE; + } + } + + *pSeekPointCount = seekPointCount; + return DRMP3_TRUE; +} + +drmp3_bool32 drmp3_bind_seek_table(drmp3* pMP3, drmp3_uint32 seekPointCount, drmp3_seek_point* pSeekPoints) +{ + if (pMP3 == NULL) { + return DRMP3_FALSE; + } + + if (seekPointCount == 0 || pSeekPoints == NULL) { + // Unbinding. + pMP3->seekPointCount = 0; + pMP3->pSeekPoints = NULL; + } else { + // Binding. + pMP3->seekPointCount = seekPointCount; + pMP3->pSeekPoints = pSeekPoints; + } + + return DRMP3_TRUE; +} + + +float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount) +{ + drmp3_assert(pMP3 != NULL); + + drmp3_uint64 totalFramesRead = 0; + drmp3_uint64 framesCapacity = 0; + float* pFrames = NULL; + + float temp[4096]; + for (;;) { + drmp3_uint64 framesToReadRightNow = drmp3_countof(temp) / pMP3->channels; + drmp3_uint64 framesJustRead = drmp3_read_pcm_frames_f32(pMP3, framesToReadRightNow, temp); + if (framesJustRead == 0) { + break; + } + + // Reallocate the output buffer if there's not enough room. + if (framesCapacity < totalFramesRead + framesJustRead) { + framesCapacity *= 2; + if (framesCapacity < totalFramesRead + framesJustRead) { + framesCapacity = totalFramesRead + framesJustRead; + } + + drmp3_uint64 newFramesBufferSize = framesCapacity*pMP3->channels*sizeof(float); + if (newFramesBufferSize > DRMP3_SIZE_MAX) { + break; + } + + float* pNewFrames = (float*)drmp3_realloc(pFrames, (size_t)newFramesBufferSize); + if (pNewFrames == NULL) { + drmp3_free(pFrames); + break; + } + + pFrames = pNewFrames; + } + + drmp3_copy_memory(pFrames + totalFramesRead*pMP3->channels, temp, (size_t)(framesJustRead*pMP3->channels*sizeof(float))); + totalFramesRead += framesJustRead; + + // If the number of frames we asked for is less that what we actually read it means we've reached the end. + if (framesJustRead != framesToReadRightNow) { + break; + } + } + + if (pConfig != NULL) { + pConfig->outputChannels = pMP3->channels; + pConfig->outputSampleRate = pMP3->sampleRate; + } + + drmp3_uninit(pMP3); + + if (pTotalFrameCount) *pTotalFrameCount = totalFramesRead; + return pFrames; +} + +float* drmp3_open_and_read_f32(drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount) +{ + drmp3 mp3; + if (!drmp3_init(&mp3, onRead, onSeek, pUserData, pConfig)) { + return NULL; + } + + return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount); +} + +float* drmp3_open_memory_and_read_f32(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount) +{ + drmp3 mp3; + if (!drmp3_init_memory(&mp3, pData, dataSize, pConfig)) { + return NULL; + } + + return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount); +} + +#ifndef DR_MP3_NO_STDIO +float* drmp3_open_file_and_read_f32(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount) +{ + drmp3 mp3; + if (!drmp3_init_file(&mp3, filePath, pConfig)) { + return NULL; + } + + return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount); +} +#endif + +void drmp3_free(void* p) +{ + DRMP3_FREE(p); +} + +#endif /*DR_MP3_IMPLEMENTATION*/ + + +// DIFFERENCES BETWEEN minimp3 AND dr_mp3 +// ====================================== +// - First, keep in mind that minimp3 (https://github.com/lieff/minimp3) is where all the real work was done. All of the +// code relating to the actual decoding remains mostly unmodified, apart from some namespacing changes. +// - dr_mp3 adds a pulling style API which allows you to deliver raw data via callbacks. So, rather than pushing data +// to the decoder, the decoder _pulls_ data from your callbacks. +// - In addition to callbacks, a decoder can be initialized from a block of memory and a file. +// - The dr_mp3 pull API reads PCM frames rather than whole MP3 frames. +// - dr_mp3 adds convenience APIs for opening and decoding entire files in one go. +// - dr_mp3 is fully namespaced, including the implementation section, which is more suitable when compiling projects +// as a single translation unit (aka unity builds). At the time of writing this, a unity build is not possible when +// using minimp3 in conjunction with stb_vorbis. dr_mp3 addresses this. + + +// REVISION HISTORY +// ================ +// +// v0.4.1 - 2018-12-30 +// - Fix a warning. +// +// v0.4.0 - 2018-12-16 +// - API CHANGE: Rename some APIs: +// - drmp3_read_f32 -> to drmp3_read_pcm_frames_f32 +// - drmp3_seek_to_frame -> drmp3_seek_to_pcm_frame +// - drmp3_open_and_decode_f32 -> drmp3_open_and_read_f32 +// - drmp3_open_and_decode_memory_f32 -> drmp3_open_memory_and_read_f32 +// - drmp3_open_and_decode_file_f32 -> drmp3_open_file_and_read_f32 +// - Add drmp3_get_pcm_frame_count(). +// - Add drmp3_get_mp3_frame_count(). +// - Improve seeking performance. +// +// v0.3.2 - 2018-09-11 +// - Fix a couple of memory leaks. +// - Bring up to date with minimp3. +// +// v0.3.1 - 2018-08-25 +// - Fix C++ build. +// +// v0.3.0 - 2018-08-25 +// - Bring up to date with minimp3. This has a minor API change: the "pcm" parameter of drmp3dec_decode_frame() has +// been changed from short* to void* because it can now output both s16 and f32 samples, depending on whether or +// not the DR_MP3_FLOAT_OUTPUT option is set. +// +// v0.2.11 - 2018-08-08 +// - Fix a bug where the last part of a file is not read. +// +// v0.2.10 - 2018-08-07 +// - Improve 64-bit detection. +// +// v0.2.9 - 2018-08-05 +// - Fix C++ build on older versions of GCC. +// - Bring up to date with minimp3. +// +// v0.2.8 - 2018-08-02 +// - Fix compilation errors with older versions of GCC. +// +// v0.2.7 - 2018-07-13 +// - Bring up to date with minimp3. +// +// v0.2.6 - 2018-07-12 +// - Bring up to date with minimp3. +// +// v0.2.5 - 2018-06-22 +// - Bring up to date with minimp3. +// +// v0.2.4 - 2018-05-12 +// - Bring up to date with minimp3. +// +// v0.2.3 - 2018-04-29 +// - Fix TCC build. +// +// v0.2.2 - 2018-04-28 +// - Fix bug when opening a decoder from memory. +// +// v0.2.1 - 2018-04-27 +// - Efficiency improvements when the decoder reaches the end of the stream. +// +// v0.2 - 2018-04-21 +// - Bring up to date with minimp3. +// - Start using major.minor.revision versioning. +// +// v0.1d - 2018-03-30 +// - Bring up to date with minimp3. +// +// v0.1c - 2018-03-11 +// - Fix C++ build error. +// +// v0.1b - 2018-03-07 +// - Bring up to date with minimp3. +// +// v0.1a - 2018-02-28 +// - Fix compilation error on GCC/Clang. +// - Fix some warnings. +// +// v0.1 - 2018-02-xx +// - Initial versioned release. + + +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ + +/* + https://github.com/lieff/minimp3 + To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. + This software is distributed without any warranty. + See . +*/ diff --git a/code/nel/src/sound/CMakeLists.txt b/code/nel/src/sound/CMakeLists.txt index 7b9eebc9f..d2c47387e 100644 --- a/code/nel/src/sound/CMakeLists.txt +++ b/code/nel/src/sound/CMakeLists.txt @@ -62,6 +62,7 @@ FILE(GLOB STREAM FILE(GLOB STREAM_FILE audio_decoder.cpp ../../include/nel/sound/audio_decoder.h audio_decoder_vorbis.cpp ../../include/nel/sound/audio_decoder_vorbis.h + audio_decoder_mp3.cpp ../../include/nel/sound/audio_decoder_mp3.h audio_decoder_ffmpeg.cpp ../../include/nel/sound/audio_decoder_ffmpeg.h stream_file_sound.cpp ../../include/nel/sound/stream_file_sound.h stream_file_source.cpp ../../include/nel/sound/stream_file_source.h diff --git a/code/nel/src/sound/audio_decoder.cpp b/code/nel/src/sound/audio_decoder.cpp index f0eb80efd..d849ed770 100644 --- a/code/nel/src/sound/audio_decoder.cpp +++ b/code/nel/src/sound/audio_decoder.cpp @@ -36,6 +36,7 @@ // Project includes #include +#include #ifdef FFMPEG_ENABLED #include @@ -102,6 +103,10 @@ IAudioDecoder *IAudioDecoder::createAudioDecoder(const std::string &type, NLMISC { return new CAudioDecoderVorbis(stream, loop); } + else if (type_lower == "mp3") + { + return new CAudioDecoderMP3(stream, loop); + } else { nlwarning("Music file type unknown: '%s'", type_lower.c_str()); @@ -139,6 +144,16 @@ bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, st nlwarning("Unable to open: '%s'", filepath.c_str()); } + else if (type_lower == "mp3") + { + CIFile ifile; + ifile.setCacheFileOnOpen(false); + ifile.allowBNPCacheFileOnOpen(false); + if (ifile.open(lookup)) + return CAudioDecoderMP3::getInfo(&ifile, artist, title, length); + + nlwarning("Unable to open: '%s'", filepath.c_str()); + } else { nlwarning("Music file type unknown: '%s'", type_lower.c_str()); @@ -157,6 +172,10 @@ void IAudioDecoder::getMusicExtensions(std::vector &extensions) { extensions.push_back("ogg"); } + if (std::find(extensions.begin(), extensions.end(), "mp3") == extensions.end()) + { + extensions.push_back("mp3"); + } #ifdef FFMPEG_ENABLED extensions.push_back("mp3"); extensions.push_back("flac"); diff --git a/code/nel/src/sound/audio_decoder_mp3.cpp b/code/nel/src/sound/audio_decoder_mp3.cpp new file mode 100644 index 000000000..bef0aad71 --- /dev/null +++ b/code/nel/src/sound/audio_decoder_mp3.cpp @@ -0,0 +1,221 @@ +// NeL - MMORPG Framework +// Copyright (C) 2018 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "stdsound.h" + +#include + +#define DR_MP3_IMPLEMENTATION +#include + +using namespace std; +using namespace NLMISC; +using namespace NLSOUND; + +namespace NLSOUND { + +// callback for drmp3 +static size_t drmp3_read(void* pUserData, void* pBufferOut, size_t bytesToRead) +{ + NLSOUND::CAudioDecoderMP3 *decoder = static_cast(pUserData); + NLMISC::IStream *stream = decoder->getStream(); + nlassert(stream->isReading()); + + uint32 available = decoder->getStreamSize() - stream->getPos(); + if (available == 0) + return 0; + + if (bytesToRead > available) + bytesToRead = available; + + stream->serialBuffer((uint8 *)pBufferOut, bytesToRead); + return bytesToRead; +} + +// callback for drmp3 +static drmp3_bool32 drmp3_seek(void* pUserData, int offset, drmp3_seek_origin origin) +{ + NLSOUND::CAudioDecoderMP3 *decoder = static_cast(pUserData); + NLMISC::IStream *stream = decoder->getStream(); + nlassert(stream->isReading()); + + NLMISC::IStream::TSeekOrigin seekOrigin; + if (origin == drmp3_seek_origin_start) + seekOrigin = NLMISC::IStream::begin; + else if (origin == drmp3_seek_origin_current) + seekOrigin = NLMISC::IStream::current; + else + return false; + + stream->seek((sint32) offset, seekOrigin); + return true; +} + +// these should always be 44100Hz/16bit/2ch +#define MP3_SAMPLE_RATE 44100 +#define MP3_BITS_PER_SAMPLE 16 +#define MP3_CHANNELS 2 + +CAudioDecoderMP3::CAudioDecoderMP3(NLMISC::IStream *stream, bool loop) +: IAudioDecoder(), + _Stream(stream), _Loop(loop), _IsMusicEnded(false), _StreamSize(0), _IsSupported(false), _PCMFrameCount(0) +{ + _StreamOffset = stream->getPos(); + stream->seek(0, NLMISC::IStream::end); + _StreamSize = stream->getPos(); + stream->seek(_StreamOffset, NLMISC::IStream::begin); + + drmp3_config config; + config.outputChannels = MP3_CHANNELS; + config.outputSampleRate = MP3_SAMPLE_RATE; + + _IsSupported = drmp3_init(&_Decoder, &drmp3_read, &drmp3_seek, this, &config); + if (!_IsSupported) + { + nlwarning("MP3: Decoder failed to read stream"); + } +} + +CAudioDecoderMP3::~CAudioDecoderMP3() +{ + drmp3_uninit(&_Decoder); +} + +bool CAudioDecoderMP3::isFormatSupported() const +{ + return _IsSupported; +} + +/// Get information on a music file. +bool CAudioDecoderMP3::getInfo(NLMISC::IStream *stream, std::string &artist, std::string &title, float &length) +{ + CAudioDecoderMP3 mp3(stream, false); + if (!mp3.isFormatSupported()) + { + title.clear(); + artist.clear(); + length = 0.f; + + return false; + } + length = mp3.getLength(); + + // ID3v1 + stream->seek(-128, NLMISC::IStream::end); + { + uint8 buf[128]; + stream->serialBuffer(buf, 128); + + if(buf[0] == 'T' && buf[1] == 'A' && buf[2] == 'G') + { + uint i; + for(i = 0; i < 30; ++i) if (buf[3+i] == '\0') break; + artist.assign((char *)&buf[3], i); + + for(i = 0; i < 30; ++i) if (buf[33+i] == '\0') break; + title.assign((char *)&buf[33], i); + } + } + + return true; +} + +uint32 CAudioDecoderMP3::getRequiredBytes() +{ + return 0; // no minimum requirement of bytes to buffer out +} + +uint32 CAudioDecoderMP3::getNextBytes(uint8 *buffer, uint32 minimum, uint32 maximum) +{ + if (_IsMusicEnded) return 0; + nlassert(minimum <= maximum); // can't have this.. + + // TODO: CStreamFileSource::play() will stall when there is no frames on warmup + // supported can be set false if there is an issue creating converter + if (!_IsSupported) + { + _IsMusicEnded = true; + return 1; + } + + sint16 *pFrameBufferOut = (sint16 *)buffer; + uint32 bytesPerFrame = MP3_BITS_PER_SAMPLE / 8 * _Decoder.channels; + + uint32 totalFramesRead = 0; + uint32 framesToRead = minimum / bytesPerFrame; + while(framesToRead > 0) + { + float tempBuffer[4096]; + uint64 tempFrames = drmp3_countof(tempBuffer) / _Decoder.channels; + + if (tempFrames > framesToRead) + tempFrames = framesToRead; + + tempFrames = drmp3_read_pcm_frames_f32(&_Decoder, tempFrames, tempBuffer); + if (tempFrames == 0) + break; + + drmp3dec_f32_to_s16(tempBuffer, pFrameBufferOut, tempFrames * _Decoder.channels); + pFrameBufferOut += tempFrames * _Decoder.channels; + + framesToRead -= tempFrames; + totalFramesRead += tempFrames; + } + + _IsMusicEnded = (framesToRead > 0); + return totalFramesRead * bytesPerFrame; +} + +uint8 CAudioDecoderMP3::getChannels() +{ + return _Decoder.channels; +} + +uint CAudioDecoderMP3::getSamplesPerSec() +{ + return _Decoder.sampleRate; +} + +uint8 CAudioDecoderMP3::getBitsPerSample() +{ + return MP3_BITS_PER_SAMPLE; +} + +bool CAudioDecoderMP3::isMusicEnded() +{ + return _IsMusicEnded; +} + +float CAudioDecoderMP3::getLength() +{ + // cached because drmp3_get_pcm_frame_count is reading full file + if (_PCMFrameCount == 0) + { + _PCMFrameCount = drmp3_get_pcm_frame_count(&_Decoder); + } + + return _PCMFrameCount / (float) _Decoder.sampleRate; +} + +void CAudioDecoderMP3::setLooping(bool loop) +{ + _Loop = loop; +} + +} /* namespace NLSOUND */ + +/* end of file */ From 1635330a14f695770ac92aeae7585ed0580608c4 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 18 Feb 2019 22:22:25 +0200 Subject: [PATCH 191/303] Fixed: Possible crash when queued buffers are already empty --HG-- branch : develop --- code/nel/src/sound/driver/openal/source_al.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/src/sound/driver/openal/source_al.cpp b/code/nel/src/sound/driver/openal/source_al.cpp index 825d9f1e9..b35dbe201 100644 --- a/code/nel/src/sound/driver/openal/source_al.cpp +++ b/code/nel/src/sound/driver/openal/source_al.cpp @@ -194,7 +194,7 @@ uint CSourceAL::countStreamingBuffers() const // a bit ugly here, but makes a much easier/simpler implementation on both drivers ALint buffersProcessed; alGetSourcei(_Source, AL_BUFFERS_PROCESSED, &buffersProcessed); - while (buffersProcessed) + while (buffersProcessed && !_QueuedBuffers.empty()) { ALuint bufferName = _QueuedBuffers.front()->bufferName(); alSourceUnqueueBuffers(_Source, 1, &bufferName); From 70e40339a1c7c211541bf0f39b131b1df3fe5647 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 22 Feb 2019 18:57:56 +0200 Subject: [PATCH 192/303] Fixed: Possible use after free and null pointer issues --HG-- branch : develop --- code/nel/src/sound/audio_decoder_mp3.cpp | 5 ++++- code/nel/src/sound/complex_source.cpp | 4 +++- code/nel/src/sound/driver/openal/source_al.cpp | 4 ++++ code/nel/src/sound/sample_bank_manager.cpp | 15 ++++++++------- code/nel/src/sound/stream_source.cpp | 2 +- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/code/nel/src/sound/audio_decoder_mp3.cpp b/code/nel/src/sound/audio_decoder_mp3.cpp index bef0aad71..dc740bec0 100644 --- a/code/nel/src/sound/audio_decoder_mp3.cpp +++ b/code/nel/src/sound/audio_decoder_mp3.cpp @@ -92,7 +92,10 @@ CAudioDecoderMP3::CAudioDecoderMP3(NLMISC::IStream *stream, bool loop) CAudioDecoderMP3::~CAudioDecoderMP3() { - drmp3_uninit(&_Decoder); + if (_IsSupported) + { + drmp3_uninit(&_Decoder); + } } bool CAudioDecoderMP3::isFormatSupported() const diff --git a/code/nel/src/sound/complex_source.cpp b/code/nel/src/sound/complex_source.cpp index 103c6cc60..3caee06f6 100644 --- a/code/nel/src/sound/complex_source.cpp +++ b/code/nel/src/sound/complex_source.cpp @@ -704,7 +704,9 @@ void CComplexSource::checkup() for (; first != last; ++first) { USource *source = *first; - if (source != NULL && source->getSound()->getLooping() && !source->isPlaying()) + if (source == NULL) + continue; + if (source->getSound()->getLooping() && !source->isPlaying()) source->play(); if (source->getSound()->getSoundType() != CSound::SOUND_SIMPLE) static_cast(source)->checkup(); diff --git a/code/nel/src/sound/driver/openal/source_al.cpp b/code/nel/src/sound/driver/openal/source_al.cpp index b35dbe201..439da980d 100644 --- a/code/nel/src/sound/driver/openal/source_al.cpp +++ b/code/nel/src/sound/driver/openal/source_al.cpp @@ -194,6 +194,10 @@ uint CSourceAL::countStreamingBuffers() const // a bit ugly here, but makes a much easier/simpler implementation on both drivers ALint buffersProcessed; alGetSourcei(_Source, AL_BUFFERS_PROCESSED, &buffersProcessed); + if (buffersProcessed && _QueuedBuffers.empty()) + { + nlwarning("AL: QueuedBuffers is empty, but OpenAL buffers processed > 0"); + } while (buffersProcessed && !_QueuedBuffers.empty()) { ALuint bufferName = _QueuedBuffers.front()->bufferName(); diff --git a/code/nel/src/sound/sample_bank_manager.cpp b/code/nel/src/sound/sample_bank_manager.cpp index 996c59f1e..6f6728bca 100644 --- a/code/nel/src/sound/sample_bank_manager.cpp +++ b/code/nel/src/sound/sample_bank_manager.cpp @@ -82,13 +82,14 @@ void CSampleBankManager::init(NLGEORGES::UFormElm *mixerConfig) TFilteredBank fb; std::string bankName; NLGEORGES::UFormElm *realBank = NULL; - realBank->getArrayNode(&realBank, j); - - realBank->getValueByName(bankName, ".SampleBank"); - fb.BankName = CStringMapper::map(bankName); - realBank->getValueByName(fb.Filter, ".Filter"); - - vfb.push_back(fb); + realBanks->getArrayNode(&realBank, j); + if (realBank != 0) + { + realBank->getValueByName(bankName, ".SampleBank"); + fb.BankName = CStringMapper::map(bankName); + realBank->getValueByName(fb.Filter, ".Filter"); + vfb.push_back(fb); + } } } diff --git a/code/nel/src/sound/stream_source.cpp b/code/nel/src/sound/stream_source.cpp index 9bd48ff25..537a4c24d 100644 --- a/code/nel/src/sound/stream_source.cpp +++ b/code/nel/src/sound/stream_source.cpp @@ -92,7 +92,7 @@ void CStreamSource::releasePhysicalSource() // free the track pSource->stop(); pSource->setStreaming(false); - mixer->freeTrack(m_Track); + if (mixer) mixer->freeTrack(m_Track); m_Track = NULL; } } From 4cbed9f9570f7beb059768e616b773d51789f918 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 22 Feb 2019 18:57:56 +0200 Subject: [PATCH 193/303] Fixed: Looping sound or crash during teleport with OpenAL driver --HG-- branch : develop --- code/nel/src/sound/driver/openal/source_al.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/nel/src/sound/driver/openal/source_al.cpp b/code/nel/src/sound/driver/openal/source_al.cpp index 439da980d..3cc0dd328 100644 --- a/code/nel/src/sound/driver/openal/source_al.cpp +++ b/code/nel/src/sound/driver/openal/source_al.cpp @@ -121,6 +121,11 @@ void CSourceAL::setStreaming(bool streaming) alTestError(); _Buffer = NULL; _IsStreaming = streaming; + if (_IsStreaming) + { + // make sure looping is disabled on OpenAL side + setLooping(false); + } } /* Set the buffer that will be played (no streaming) From ac68a37f1bfa349a63761c423b982882a225cfb8 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 28 Feb 2019 15:01:51 +0200 Subject: [PATCH 194/303] Changed: Move user landmarks from icfg to own xml file --HG-- branch : develop --- code/ryzom/client/src/continent_manager.cpp | 175 ++++++++++++++- code/ryzom/client/src/continent_manager.h | 7 +- code/ryzom/client/src/far_tp.cpp | 1 + .../client/src/interface_v3/group_map.cpp | 2 +- .../src/interface_v3/interface_manager.cpp | 210 ++++++++++++++++-- .../src/interface_v3/interface_manager.h | 13 ++ .../src/interface_v3/parser_modules.cpp | 21 ++ .../client/src/interface_v3/parser_modules.h | 9 + 8 files changed, 411 insertions(+), 27 deletions(-) diff --git a/code/ryzom/client/src/continent_manager.cpp b/code/ryzom/client/src/continent_manager.cpp index fe9067a4f..56a11cf63 100644 --- a/code/ryzom/client/src/continent_manager.cpp +++ b/code/ryzom/client/src/continent_manager.cpp @@ -488,8 +488,177 @@ CContinent *CContinentManager::get(const std::string &contName) return NULL; } -void CContinentManager::serialUserLandMarks(NLMISC::IStream &f) +void CContinentManager::writeTo(xmlNodePtr node) const { + // + // + // + // ... + // + for(TContinents::const_iterator it = _Continents.begin(); it != _Continents.end(); ++it) + { + std::string name = it->first; + xmlNodePtr contNode = xmlNewChild(node, NULL, (const xmlChar*)"landmarks", NULL); + xmlSetProp(contNode, (const xmlChar*)"continent", (const xmlChar*)name.c_str()); + xmlSetProp(contNode, (const xmlChar*)"type", (const xmlChar*)"user"); + + if (it->second && it->second->UserLandMarks.size() > 0) + { + for(uint i = 0; i< it->second->UserLandMarks.size(); ++i) + { + const CUserLandMark& lm = it->second->UserLandMarks[i]; + + xmlNodePtr lmNode = xmlNewChild(contNode, NULL, (const xmlChar*)"landmark", NULL); + xmlSetProp(lmNode, (const xmlChar*)"type", (const xmlChar*)toString("%d", (uint32)lm.Type).c_str()); + xmlSetProp(lmNode, (const xmlChar*)"x", (const xmlChar*)toString("%.2f", lm.Pos.x).c_str()); + xmlSetProp(lmNode, (const xmlChar*)"y", (const xmlChar*)toString("%.2f", lm.Pos.y).c_str()); + + // sanitize ascii control chars + // libxml will encode other special chars itself + std::string title = lm.Title.toUtf8(); + for(uint i = 0; i< title.size(); i++) + { + if (title[i] < ' ' && title[i] != '\n' && title[i] != '\t') + { + title[i] = '?'; + } + } + xmlSetProp(lmNode, (const xmlChar*)"title", (const xmlChar*)title.c_str()); + } + } + } +} + +void CContinentManager::readFrom(xmlNodePtr node) +{ + CXMLAutoPtr prop; + + // + // + // ... + // + std::string continent; + prop = xmlGetProp(node, (xmlChar*)"continent"); + if (!prop) + { + nlwarning("Ignore landmarks group 'continent' attribute."); + return; + } + continent = (const char*)prop; + + TContinents::iterator itContinent = _Continents.find(continent); + if (itContinent == _Continents.end() || !itContinent->second) + { + nlwarning("Ignore landmarks group with unknown 'continent' '%s'", continent.c_str()); + return; + } + + std::string lmtype; + prop = xmlGetProp(node, (xmlChar*)"type"); + if (!prop) + { + nlwarning("Ignore landmarks group without 'type' attribute."); + return; + } + lmtype = toLower((const char*)prop); + if (lmtype != "user") + { + nlwarning("Ignore landmarks group with type '%s', expected 'user'.", lmtype.c_str()); + return; + } + + node = node->children; + while(node) + { + if (stricmp((char*)node->name, "landmark") != 0) + { + nlwarning("Ignore invalid node '%s' under landmarks group", (const char*)node->name); + + node = node->next; + continue; + } + + bool add = true; + CUserLandMark lm; + + prop = xmlGetProp(node, (xmlChar*)"type"); + if (prop) + fromString((const char*)prop, lm.Type); + else + nlwarning("Using default value for landmark type"); + + prop = xmlGetProp(node, (xmlChar*)"x"); + if (prop) + { + fromString((const char*)prop, lm.Pos.x); + } + else + { + nlwarning("Landmark missing 'x' attribute"); + add = false; + } + + prop = xmlGetProp(node, (xmlChar*)"y"); + if (prop) + { + fromString((const char*)prop, lm.Pos.y); + } + else + { + nlwarning("Landmark missing 'y' attribute"); + add = false; + } + + prop = xmlGetProp(node, (xmlChar*)"title"); + if (prop) + { + lm.Title.fromUtf8((const char*)prop); + } + else + { + nlwarning("Landmark missing 'title' attribute"); + add = false; + } + + if (add) + { + // before adding, check for duplicate + // duplicates might be read from .icfg before .xml is read + add = true; + for(uint i = 0; i< itContinent->second->UserLandMarks.size(); ++i) + { + const CUserLandMark& test = itContinent->second->UserLandMarks[i]; + uint xdiff = abs(test.Pos.x - lm.Pos.x) * 100; + uint ydiff = abs(test.Pos.y - lm.Pos.y) * 100; + if (xdiff == 0 && ydiff == 0) + { + add = false; + break; + } + } + + if (add) + { + itContinent->second->UserLandMarks.push_back(lm); + } + else + { + nlwarning("Ignore landmark with duplicate pos (continent:'%s', x:%.2f, y:%.2f, type:%d, title:'%s')", continent.c_str(), lm.Pos.x, lm.Pos.y, (uint8)lm.Type, lm.Title.toUtf8().c_str()); + } + } + else + { + nlwarning("Landmark not added"); + } + + node = node->next; + } +} + +uint32 CContinentManager::serialUserLandMarks(NLMISC::IStream &f) +{ + uint32 totalLandmarks = 0; + f.serialVersion(1); if (!f.isReading()) { @@ -502,6 +671,7 @@ void CContinentManager::serialUserLandMarks(NLMISC::IStream &f) if (it->second) { f.serialCont(it->second->UserLandMarks); + totalLandmarks += it->second->UserLandMarks.size(); } else { @@ -522,6 +692,7 @@ void CContinentManager::serialUserLandMarks(NLMISC::IStream &f) if (it != _Continents.end() && it->second) { f.serialCont(it->second->UserLandMarks); + totalLandmarks += it->second->UserLandMarks.size(); } else { @@ -530,6 +701,8 @@ void CContinentManager::serialUserLandMarks(NLMISC::IStream &f) } } } + + return totalLandmarks; } diff --git a/code/ryzom/client/src/continent_manager.h b/code/ryzom/client/src/continent_manager.h index c51498967..1a0641627 100644 --- a/code/ryzom/client/src/continent_manager.h +++ b/code/ryzom/client/src/continent_manager.h @@ -109,8 +109,13 @@ public: const std::string &getCurrentContinentSelectName(); + // load / save all user landmarks in xml format + void writeTo(xmlNodePtr node) const; + void readFrom(xmlNodePtr node); + // load / saves all user landMarks - void serialUserLandMarks(NLMISC::IStream &f); + // \return number of landmarks loaded or saved + uint32 serialUserLandMarks(NLMISC::IStream &f); // rebuild visible landmarks on current map void updateUserLandMarks(); diff --git a/code/ryzom/client/src/far_tp.cpp b/code/ryzom/client/src/far_tp.cpp index 577477ea2..92a8bbe3a 100644 --- a/code/ryzom/client/src/far_tp.cpp +++ b/code/ryzom/client/src/far_tp.cpp @@ -1298,6 +1298,7 @@ void CFarTP::sendReady() pIM->loadKeys(); CWidgetManager::getInstance()->hideAllWindows(); pIM->loadInterfaceConfig(); + pIM->loadLandmarks(); } else { diff --git a/code/ryzom/client/src/interface_v3/group_map.cpp b/code/ryzom/client/src/interface_v3/group_map.cpp index 9de74bcc7..28eb5e1e3 100644 --- a/code/ryzom/client/src/interface_v3/group_map.cpp +++ b/code/ryzom/client/src/interface_v3/group_map.cpp @@ -2715,7 +2715,7 @@ CCtrlButton *CGroupMap::addUserLandMark(const NLMISC::CVector2f &pos, const ucst addLandMark(_UserLM, pos, title, getUserLandMarkOptions((uint32)_CurContinent->UserLandMarks.size() - 1)); // Save the config file each time a user landmark is created - CInterfaceManager::getInstance()->saveConfig(); + CInterfaceManager::getInstance()->saveLandmarks(); return _UserLM.back(); } diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 7684accd8..bc606f939 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -458,6 +458,7 @@ CInterfaceManager::CInterfaceManager() parser->addModule( "command", new CCommandParser() ); parser->addModule( "key", new CKeyParser() ); parser->addModule( "macro", new CMacroParser() ); + parser->addModule( "landmarks", new CLandmarkParser() ); parser->setCacheUIParsing( ClientCfg.CacheUIParsing ); CViewRenderer::setDriver( Driver ); @@ -982,6 +983,9 @@ void CInterfaceManager::initInGame() // Interface config loadInterfaceConfig(); + //Load user landmarks + loadLandmarks(); + // Must do extra init for people interaction after load PeopleInterraction.initAfterLoad(); @@ -1217,6 +1221,22 @@ void CInterfaceManager::configureQuitDialogBox() } } +// ------------------------------------------------------------------------------------------------ +// +std::string CInterfaceManager::getSaveFileName(const std::string &module, const std::string &ext, bool useShared) const +{ + string filename = "save/" + module + "_" + PlayerSelectedFileName + "." + ext; + if (useShared && !CFile::fileExists(filename)) + { + string sharedFile = "save/shared_" + module + "." + ext; + if (CFile::fileExists(sharedFile)) + { + return sharedFile; + } + } + return filename; +} + // ------------------------------------------------------------------------------------------------ void CInterfaceManager::loadKeys() { @@ -1228,26 +1248,19 @@ void CInterfaceManager::loadKeys() vector xmlFilesToParse; // Does the keys file exist ? - string userKeyFileName = "save/keys_"+PlayerSelectedFileName+".xml"; + string userKeyFileName = getSaveFileName("keys", "xml"); if (CFile::fileExists(userKeyFileName) && CFile::getFileSize(userKeyFileName) > 0) { // Load the user key file xmlFilesToParse.push_back (userKeyFileName); } - else - { - string filename = "save/shared_keys.xml"; - if(CFile::fileExists(filename) && CFile::getFileSize(filename) > 0) - { - xmlFilesToParse.push_back(filename); - } - } + // Load the default key (but don't replace existings bounds, see keys.xml "key_def_no_replace") xmlFilesToParse.push_back ("keys.xml"); if (!parseInterface (xmlFilesToParse, true)) { - badXMLParseMessageBox(); + createFileBackup("Error loading keys", userKeyFileName); } _KeysLoaded = true; @@ -1260,10 +1273,7 @@ void CInterfaceManager::loadInterfaceConfig() if (ClientCfg.R2EDEnabled) // in R2ED mode the CEditor class deals with it return; - string filename = "save/interface_" + PlayerSelectedFileName + ".icfg"; - if (!CFile::fileExists(filename)) - filename = "save/shared_interface.icfg"; - + string filename = getSaveFileName("interface", "icfg"); loadConfig(filename); // Invalidate coords of changed groups _ConfigLoaded = true; @@ -1680,6 +1690,7 @@ bool CInterfaceManager::loadConfig (const string &filename) uint32 nNbMode; CInterfaceConfig ic; bool lastInGameScreenResLoaded= false; + uint32 nbLandmarks = 0; try { sint ver = f.serialVersion(ICFG_STREAM_VERSION); @@ -1775,7 +1786,7 @@ bool CInterfaceManager::loadConfig (const string &filename) } // Load user landmarks - ContinentMngr.serialUserLandMarks(f); + nbLandmarks = ContinentMngr.serialUserLandMarks(f); CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp( "SERVER:INTERFACES:NB_BONUS_LANDMARKS" ); if ( pNL ) @@ -1809,10 +1820,9 @@ bool CInterfaceManager::loadConfig (const string &filename) catch(const NLMISC::EStream &) { f.close(); - string sFileNameBackup = sFileName+"backup"; - if (CFile::fileExists(sFileNameBackup)) - CFile::deleteFile(sFileNameBackup); - CFile::moveFile(sFileNameBackup, sFileName); + + createFileBackup("Config loading failed", sFileName); + nlwarning("Config loading failed : restore default"); vector v; if (!ClientCfg.R2EDEnabled) @@ -1823,6 +1833,35 @@ bool CInterfaceManager::loadConfig (const string &filename) } f.close(); + if (nbLandmarks > 0) + { + // use copy for backup so on save proper shared/player icfg file is used + createFileBackup("Landmarks will be migrated to xml", sFileName, true); + + // if icfg is interface_player.icfg, then landmarks must also be loaded/saved to player file + if (nlstricmp(sFileName.substr(0, 12), "save/shared_") != 0) + { + string lmfile = getSaveFileName("landmarks", "xml", false); + if (!CFile::fileExists(lmfile)) + { + // create placeholder player landmarks file so saveLandmarks will use it + // even if shared landmarks file exists + COFile f; + if (f.open(lmfile, false, false, true)) + { + std::string xml; + xml = "\n"; + f.serialBuffer((uint8 *)xml.c_str(), xml.size()); + f.close(); + } + } + } + + // merge .icfg landmarks with landmarks.xml + loadLandmarks(); + saveLandmarks(); + } + // *** If saved resolution is different from the current one setuped, must fix positions in _Modes if(lastInGameScreenResLoaded) { @@ -1877,6 +1916,88 @@ public: } }; +bool CInterfaceManager::saveLandmarks(bool verbose) const +{ + bool ret = true; + + if (!ClientCfg.R2EDEnabled) + { + uint8 currMode = getMode(); + + string filename = getSaveFileName("landmarks", "xml"); + if (verbose) CInterfaceManager::getInstance()->displaySystemInfo("Saving " + filename); + ret = saveLandmarks(filename); + } + + return ret; +} + +bool CInterfaceManager::loadLandmarks() +{ + // Does the keys file exist ? + string filename = getSaveFileName("landmarks", "xml"); + + CIFile f; + string sFileName; + sFileName = NLMISC::CPath::lookup (filename, false); + if (sFileName.empty() || !f.open(sFileName)) + return false; + + bool ret = false; + vector xmlFilesToParse; + xmlFilesToParse.push_back (filename); + + //ContinentMngr.serialUserLandMarks(node); + if (!parseInterface (xmlFilesToParse, true)) + { + f.close(); + + createFileBackup("Error while loading landmarks", filename); + + ret = false; + } + + return ret; +} + +bool CInterfaceManager::saveLandmarks(const std::string &filename) const +{ + nlinfo( "Saving landmarks : %s", filename.c_str() ); + + bool ret = false; + try + { + COFile f; + + // using temporary file, so no f.close() unless its a success + if (f.open(filename, false, false, true)) + { + COXml xmlStream; + xmlStream.init (&f); + + xmlDocPtr doc = xmlStream.getDocument (); + xmlNodePtr node = xmlNewDocNode(doc, NULL, (const xmlChar*)"interface_config", NULL); + xmlDocSetRootElement (doc, node); + + ContinentMngr.writeTo(node); + + // Flush the stream + xmlStream.flush(); + + // Close the stream + f.close (); + + ret = true; + } + } + catch (const Exception &e) + { + nlwarning ("Error while writing the file %s : %s.", filename.c_str(), e.what ()); + } + + return ret; +} + // ------------------------------------------------------------------------------------------------ // bool CInterfaceManager::saveConfig (bool verbose) @@ -1887,9 +2008,7 @@ bool CInterfaceManager::saveConfig (bool verbose) { uint8 currMode = getMode(); - string filename = "save/interface_" + PlayerSelectedFileName + ".icfg"; - if (!CFile::fileExists(filename) && CFile::fileExists("save/shared_interface.icfg")) - filename = "save/shared_interface.icfg"; + string filename = getSaveFileName("interface", "icfg"); if (verbose) CInterfaceManager::getInstance()->displaySystemInfo("Saving " + filename); ret = saveConfig(filename); @@ -2004,8 +2123,13 @@ bool CInterfaceManager::saveConfig (const string &filename) CTaskBarManager *pTBM= CTaskBarManager::getInstance(); pTBM->serial(f); - // Save user landmarks - ContinentMngr.serialUserLandMarks(f); + //ContinentMngr.serialUserLandMarks(f); + // empty landmarks block for compatibility + { + f.serialVersion(1); + uint32 numCont = 0; + f.serial(numCont); + } // Info Windows position. CInterfaceHelp::serialInfoWindows(f); @@ -2972,6 +3096,7 @@ class CAHSaveUI : public IActionHandler { CInterfaceManager::getInstance()->saveKeys(true); CInterfaceManager::getInstance()->saveConfig(true); + CInterfaceManager::getInstance()->saveLandmarks(true); } }; REGISTER_ACTION_HANDLER (CAHSaveUI, "save_ui"); @@ -4135,3 +4260,40 @@ bool CInterfaceManager::parseTokens(ucstring& ucstr) ucstr = str; return true;; } + +std::string CInterfaceManager::getNextBackupName(std::string filename) +{ + std::string ts = getTimestampHuman("%Y-%m-%d"); + + if (!ts.empty()) + { + std::string::size_type pos = filename.find_last_of('.'); + if (pos == std::string::npos) + filename = filename + "_" + ts + "_"; + else + filename = filename.substr(0, pos) + "_" + ts + "_" + filename.substr(pos); + } + + // filename_YYYY-MM-DD_000.ext + return CFile::findNewFile(filename); +} + +void CInterfaceManager::createFileBackup(const std::string &message, const std::string &filename, bool useCopy) +{ + std::string backupName = getNextBackupName(filename); + nlwarning("%s: '%s'.", message.c_str(), filename.c_str()); + if (!backupName.empty()) + { + if (useCopy) + { + nlwarning("Backup copy saved as '%s'", backupName.c_str()); + CFile::copyFile(backupName, filename); + } + else + { + nlwarning("File renamed to '%s'", backupName.c_str()); + CFile::moveFile(backupName, filename); + } + } +} + diff --git a/code/ryzom/client/src/interface_v3/interface_manager.h b/code/ryzom/client/src/interface_v3/interface_manager.h index 652d692b3..488dbe0a5 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.h +++ b/code/ryzom/client/src/interface_v3/interface_manager.h @@ -203,6 +203,19 @@ public: /// Load a set of xml files bool parseInterface (const std::vector &xmlFileNames, bool reload, bool isFilename = true); + /// return new filename that can be used to backup original file + std::string getNextBackupName(std::string filename); + /// copy/rename filename for backup and show error in log + void createFileBackup(const std::string &message, const std::string &filename, bool useCopy = false); + + /// select player/shared file name from 'save' folder' + std::string getSaveFileName(const std::string &module, const std::string &ext, bool useShared = true) const; + + /// Load / save user landmarks in .xml format + bool loadLandmarks (); + bool saveLandmarks (bool verbose = false) const; + bool saveLandmarks (const std::string &filename) const; + // Load/Save position, size, etc.. of windows bool loadConfig (const std::string &filename); // Save config to default location, if verbose is true, display message in game sysinfo diff --git a/code/ryzom/client/src/interface_v3/parser_modules.cpp b/code/ryzom/client/src/interface_v3/parser_modules.cpp index b540900a4..2d2c7cb60 100644 --- a/code/ryzom/client/src/interface_v3/parser_modules.cpp +++ b/code/ryzom/client/src/interface_v3/parser_modules.cpp @@ -24,6 +24,7 @@ #include "../commands.h" #include "interface_3d_scene.h" #include "nel/misc/i_xml.h" +#include "../continent_manager.h" using namespace NLMISC; @@ -31,6 +32,8 @@ using namespace NLMISC; #include "../client_cfg.h" #endif +extern CContinentManager ContinentMngr; + CIF3DSceneParser::CIF3DSceneParser() { parsingStage |= ( Resolved | GroupChildren ); @@ -529,3 +532,21 @@ bool CMacroParser::parse( xmlNodePtr cur, NLGUI::CInterfaceGroup *parentGroup ) return true; } +CLandmarkParser::CLandmarkParser() +{ + parsingStage |= Unresolved; +} + +CLandmarkParser::~CLandmarkParser() +{ +} + +bool CLandmarkParser::parse( xmlNodePtr cur, NLGUI::CInterfaceGroup *parentGroup ) +{ + H_AUTO(parseLandmark) + + ContinentMngr.readFrom(cur); + + return true; +} + diff --git a/code/ryzom/client/src/interface_v3/parser_modules.h b/code/ryzom/client/src/interface_v3/parser_modules.h index 9a2bf76b9..f816f8d39 100644 --- a/code/ryzom/client/src/interface_v3/parser_modules.h +++ b/code/ryzom/client/src/interface_v3/parser_modules.h @@ -76,4 +76,13 @@ public: bool parse( xmlNodePtr cur, CInterfaceGroup *parentGroup ); }; +class CLandmarkParser : public CInterfaceParser::IParserModule +{ +public: + CLandmarkParser(); + ~CLandmarkParser(); + + bool parse( xmlNodePtr cur, CInterfaceGroup *parentGroup ); +}; + #endif From 2f0a831d528abe3f378b182c05dc87c41c5d0090 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 28 Feb 2019 17:26:51 +0200 Subject: [PATCH 195/303] Fixed: Invalid comparison of signed value --HG-- branch : develop --- code/ryzom/client/src/continent_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ryzom/client/src/continent_manager.cpp b/code/ryzom/client/src/continent_manager.cpp index 56a11cf63..c4b5cc693 100644 --- a/code/ryzom/client/src/continent_manager.cpp +++ b/code/ryzom/client/src/continent_manager.cpp @@ -518,7 +518,7 @@ void CContinentManager::writeTo(xmlNodePtr node) const std::string title = lm.Title.toUtf8(); for(uint i = 0; i< title.size(); i++) { - if (title[i] < ' ' && title[i] != '\n' && title[i] != '\t') + if (title[i] >= '\0' && title[i] < ' ' && title[i] != '\n' && title[i] != '\t') { title[i] = '?'; } From ab7ad10796d102ba6320d9ccdc11d25fba0bddfa Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 1 Mar 2019 00:22:43 +0200 Subject: [PATCH 196/303] Fixed: Save landmarks immediately on change --HG-- branch : develop --- code/ryzom/client/src/interface_v3/group_map.cpp | 3 +++ code/ryzom/client/src/interface_v3/interface_manager.cpp | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/code/ryzom/client/src/interface_v3/group_map.cpp b/code/ryzom/client/src/interface_v3/group_map.cpp index 28eb5e1e3..e9864b61b 100644 --- a/code/ryzom/client/src/interface_v3/group_map.cpp +++ b/code/ryzom/client/src/interface_v3/group_map.cpp @@ -2739,6 +2739,7 @@ void CGroupMap::removeUserLandMark(CCtrlButton *button) updateUserLandMarks(); } + CInterfaceManager::getInstance()->saveLandmarks(); return; } } @@ -2758,6 +2759,8 @@ void CGroupMap::updateUserLandMark(CCtrlButton *button, const ucstring &newTitle updateLandMarkButton(_UserLM[k], getUserLandMarkOptions(k)); button->setDefaultContextHelp(newTitle); + + CInterfaceManager::getInstance()->saveLandmarks(); return; } } diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index bc606f939..80c6c552b 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -3096,7 +3096,6 @@ class CAHSaveUI : public IActionHandler { CInterfaceManager::getInstance()->saveKeys(true); CInterfaceManager::getInstance()->saveConfig(true); - CInterfaceManager::getInstance()->saveLandmarks(true); } }; REGISTER_ACTION_HANDLER (CAHSaveUI, "save_ui"); From 21f15a47bc59c7851e6331e0671c590f10c72316 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 9 Mar 2019 12:59:58 +0100 Subject: [PATCH 197/303] Fixed: If no profile found, don't process the default one --HG-- branch : develop --- .../client/ryzom_installer/src/configfile.cpp | 4 ++-- .../client/ryzom_installer/src/mainwindow.cpp | 16 ++++++++++++++++ .../ryzom_installer/src/operationdialog.cpp | 6 ++++++ .../ryzom_installer/src/uninstalldialog.cpp | 3 +++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp b/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp index 889dec9cb..d23119b27 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp @@ -290,8 +290,8 @@ CProfile CConfigFile::getProfile(const QString &id) const if (m_profiles[i].id == id) return m_profiles[i]; } - // default profile - return getProfile(); + // no profile + return NoProfile; } void CConfigFile::setProfile(int i, const CProfile &profile) diff --git a/code/ryzom/tools/client/ryzom_installer/src/mainwindow.cpp b/code/ryzom/tools/client/ryzom_installer/src/mainwindow.cpp index e89a1f07d..16e0c8bad 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/mainwindow.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/mainwindow.cpp @@ -103,6 +103,10 @@ void CMainWindow::updateButtons() CConfigFile *config = CConfigFile::getInstance(); const CProfile &profile = config->getProfile(profileIndex); + + // wrong profile + if (profile.id.isEmpty()) return; + const CServer &server = config->getServer(profile.server); // get full path of client executable @@ -125,6 +129,10 @@ void CMainWindow::onPlayClicked() CConfigFile *config = CConfigFile::getInstance(); const CProfile &profile = config->getProfile(profileIndex); + + // wrong profile + if (profile.id.isEmpty()) return; + const CServer &server = config->getServer(profile.server); // get full path of client executable @@ -162,6 +170,10 @@ void CMainWindow::onConfigureClicked() CConfigFile *config = CConfigFile::getInstance(); const CProfile &profile = config->getProfile(profileIndex); + + // wrong profile + if (profile.id.isEmpty()) return; + const CServer &server = config->getServer(profile.server); // get full path of configuration executable @@ -310,6 +322,10 @@ void CMainWindow::onProfileChanged(int profileIndex) CConfigFile *config = CConfigFile::getInstance(); CProfile profile = config->getProfile(profileIndex); + + // wrong profile + if (profile.id.isEmpty()) return; + CServer server = config->getServer(profile.server); // load changelog diff --git a/code/ryzom/tools/client/ryzom_installer/src/operationdialog.cpp b/code/ryzom/tools/client/ryzom_installer/src/operationdialog.cpp index ec0a21714..e9d6fdebd 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/operationdialog.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/operationdialog.cpp @@ -926,6 +926,9 @@ bool COperationDialog::createProfileShortcuts(const QString &profileId) const CProfile &profile = config->getProfile(profileId); + // wrong profile + if (profile.id.isEmpty()) return false; + m_currentOperation = tr("Creating shortcuts for profile %1...").arg(profile.id); profile.createShortcuts(); @@ -1080,6 +1083,9 @@ void COperationDialog::addComponentsProfiles() { const CProfile &profile = config->getProfile(profileId); + // wrong profile + if (profile.id.isEmpty()) continue; + profile.createShortcuts(); profile.createClientConfig(); } diff --git a/code/ryzom/tools/client/ryzom_installer/src/uninstalldialog.cpp b/code/ryzom/tools/client/ryzom_installer/src/uninstalldialog.cpp index 1330a16bf..e346d7a00 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/uninstalldialog.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/uninstalldialog.cpp @@ -257,6 +257,9 @@ void CUninstallDialog::updateSizes() { const CProfile &profile = config->getProfile(it.key()); + // wrong profile + if (profile.id.isEmpty()) continue; + qint64 bytes = getDirectorySize(profile.getDirectory(), true); emit updateSize(it.value(), qBytesToHumanReadable(bytes)); From 78c39850ae576188fb5d0329a1aa7a1cd14368b3 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 9 Mar 2019 13:00:59 +0100 Subject: [PATCH 198/303] Fixed: Check profile details in backup profiles if deleted --HG-- branch : develop --- .../tools/client/ryzom_installer/src/configfile.cpp | 10 ++++++++++ .../tools/client/ryzom_installer/src/configfile.h | 1 + .../client/ryzom_installer/src/operationdialog.cpp | 13 ++++++++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp b/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp index d23119b27..7b61bda7e 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp @@ -264,6 +264,16 @@ const CServer& CConfigFile::getServer(const QString &id) const return getServer(); } +CProfile CConfigFile::getBackupProfile(const QString &id) const +{ + for (int i = 0; i < m_backupProfiles.size(); ++i) + { + if (m_backupProfiles[i].id == id) return m_backupProfiles[i]; + } + + return NoProfile; +} + void CConfigFile::backupProfiles() { m_backupProfiles = m_profiles; diff --git a/code/ryzom/tools/client/ryzom_installer/src/configfile.h b/code/ryzom/tools/client/ryzom_installer/src/configfile.h index baa815bd8..6480c1f87 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/configfile.h +++ b/code/ryzom/tools/client/ryzom_installer/src/configfile.h @@ -53,6 +53,7 @@ public: void setProfiles(const CProfiles &profiles) { m_profiles = profiles; } CProfiles getBackupProfiles() const { return m_backupProfiles; } + CProfile getBackupProfile(const QString &id) const; void backupProfiles(); QString getLanguage() const { return m_language; } diff --git a/code/ryzom/tools/client/ryzom_installer/src/operationdialog.cpp b/code/ryzom/tools/client/ryzom_installer/src/operationdialog.cpp index e9d6fdebd..fe01509ab 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/operationdialog.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/operationdialog.cpp @@ -1105,6 +1105,9 @@ void COperationDialog::deleteComponentsProfiles() CConfigFile *config = CConfigFile::getInstance(); + // some profiles have been removed, use backup profiles + bool useBackup = !config->getBackupProfiles().isEmpty(); + int i = 0; foreach(const QString &profileId, m_removeComponents.profiles) @@ -1115,7 +1118,11 @@ void COperationDialog::deleteComponentsProfiles() return; } - const CProfile &profile = config->getProfile(profileId); + // only search in backup profiles, because they are already deleted in profiles + const CProfile &profile = useBackup ? config->getBackupProfile(profileId):config->getProfile(profileId); + + // already deleted profile + if (profile.id.isEmpty()) continue; emit progress(i++, profile.name); @@ -1134,8 +1141,8 @@ void COperationDialog::deleteComponentsProfiles() profile.deleteShortcuts(); - // delete profile - config->removeProfile(profileId); + // delete profile if still used + if (!useBackup) config->removeProfile(profileId); } emit success(m_removeComponents.profiles.size()); From d62c139ee0d0d7e9363392810329135a19c3cddb Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 12 Mar 2019 20:02:43 +0200 Subject: [PATCH 199/303] Changed: Parse html style attribute --HG-- branch : develop --- code/nel/include/nel/gui/group_html.h | 5 +++ code/nel/include/nel/gui/libwww.h | 8 ++++ code/nel/src/gui/group_html.cpp | 60 ++++++++++++++++++++------- code/nel/src/gui/libwww.cpp | 11 +++++ 4 files changed, 68 insertions(+), 16 deletions(-) diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index 7820cbd6a..8b296f114 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -105,6 +105,7 @@ namespace NLGUI Height=-1; MaxWidth=-1; MaxHeight=-1; + BackgroundColor=NLMISC::CRGBA::Black; } uint FontSize; uint FontWeight; @@ -119,6 +120,7 @@ namespace NLGUI sint32 Height; sint32 MaxWidth; sint32 MaxHeight; + NLMISC::CRGBA BackgroundColor; }; // ImageDownload system @@ -345,6 +347,9 @@ namespace NLGUI // Get Home URL virtual std::string home(); + // Clear style stack and restore default style + void resetCssStyle(); + // Parse style html tag TStyle parseStyle(const std::string &str_styles); diff --git a/code/nel/include/nel/gui/libwww.h b/code/nel/include/nel/gui/libwww.h index 9c6579f1f..112cae7d7 100644 --- a/code/nel/include/nel/gui/libwww.h +++ b/code/nel/include/nel/gui/libwww.h @@ -49,6 +49,14 @@ namespace NLGUI #undef HTML_ATTR #define HTML_ATTR(t,a) MY_HTML_##t##_##a + enum + { + HTML_ATTR(HTML,DIR) = 0, + HTML_ATTR(HTML,LANG), + HTML_ATTR(HTML,VERSION), + HTML_ATTR(HTML,STYLE), + }; + enum { HTML_ATTR(A,ACCESSKEY) = 0, diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 92431a3aa..7b81ef746 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -1489,6 +1489,13 @@ namespace NLGUI // Paragraph ? switch(element_number) { + case HTML_HTML: + if (present[MY_HTML_HTML_STYLE] && value[MY_HTML_HTML_STYLE]) + getStyleParams(value[MY_HTML_HTML_STYLE], _StyleDefault); + + _Style = _StyleDefault; + setBackgroundColor(_Style.BackgroundColor); + break; case HTML_HEAD: _ReadingHeadTag = !_IgnoreHeadTag; _IgnoreHeadTag = true; @@ -1708,18 +1715,22 @@ namespace NLGUI break; case HTML_BODY: { - if (present[HTML_BODY_BGCOLOR] && value[HTML_BODY_BGCOLOR]) - { - CRGBA bgColor; - if (scanHTMLColor(value[HTML_BODY_BGCOLOR], bgColor)) - setBackgroundColor (bgColor); - } - + pushStyle(); + string style; if (present[HTML_BODY_STYLE] && value[HTML_BODY_STYLE]) style = value[HTML_BODY_STYLE]; - - + + if (!style.empty()) + getStyleParams(style, _Style); + + CRGBA bgColor = _Style.BackgroundColor; + if (present[HTML_BODY_BGCOLOR] && value[HTML_BODY_BGCOLOR]) + scanHTMLColor(value[HTML_BODY_BGCOLOR], bgColor); + + if (bgColor != _Style.BackgroundColor) + setBackgroundColor(bgColor); + if (!style.empty()) { TStyle styles = parseStyle(style); @@ -1743,10 +1754,6 @@ namespace NLGUI image = image.substr(4, image.size()-5); setBackground (image, scale, repeat); } - - // set default text style from - getStyleParams(style, _StyleDefault); - _Style = _StyleDefault; } } break; @@ -2737,6 +2744,9 @@ namespace NLGUI case HTML_HEAD: _ReadingHeadTag = false; break; + case HTML_BODY: + popStyle(); + break; case HTML_FONT: popStyle(); break; @@ -4915,9 +4925,7 @@ namespace NLGUI _IgnoreBaseUrlTag = false; // reset style - _StyleDefault = CStyleParams(); - _Style = _StyleDefault; - _StyleParams.clear(); + resetCssStyle(); // TR @@ -6252,6 +6260,18 @@ namespace NLGUI return uri.toString(); } + // *************************************************************************** + void CGroupHTML::resetCssStyle() + { + _StyleDefault = CStyleParams(); + _StyleDefault.TextColor = TextColor; + _StyleDefault.FontSize = TextFontSize; + _StyleDefault.BackgroundColor = BgColor; + + _Style = _StyleDefault; + _StyleParams.clear(); + } + // *************************************************************************** // CGroupHTML::CStyleParams style; // style.FontSize; // font-size: 10px; @@ -6485,6 +6505,14 @@ namespace NLGUI if (fromString(it->second, b)) style.GlobalColor = b; } + else + if (it->first == "background-color") + { + if (it->second == "inherit") + style.BackgroundColor = current.backgroundColor; + else + scanHTMLColor(it->second.c_str(), style.BackgroundColor); + } } } diff --git a/code/nel/src/gui/libwww.cpp b/code/nel/src/gui/libwww.cpp index f00a92749..bb32fd5b6 100644 --- a/code/nel/src/gui/libwww.cpp +++ b/code/nel/src/gui/libwww.cpp @@ -47,6 +47,15 @@ namespace NLGUI #undef HTML_ATTR #define HTML_ATTR(a,b) { (char*) #b } + HTAttr html_attr[] = + { + HTML_ATTR(HTML,DIR), + HTML_ATTR(HTML,LANG), + HTML_ATTR(HTML,VERSION), + HTML_ATTR(HTML,STYLE), + { 0 } + }; + HTAttr a_attr[] = { HTML_ATTR(A,ACCESSKEY), @@ -469,6 +478,8 @@ namespace NLGUI // Change the HTML DTD SGML_dtd *HTML_DTD = HTML_dtd (); + HTML_DTD->tags[HTML_HTML].attributes = html_attr; + HTML_DTD->tags[HTML_HTML].number_of_attributes = sizeof(html_attr) / sizeof(HTAttr) - 1; HTML_DTD->tags[HTML_TABLE].attributes = table_attr; HTML_DTD->tags[HTML_TABLE].number_of_attributes = sizeof(table_attr) / sizeof(HTAttr) - 1; HTML_DTD->tags[HTML_TR].attributes = tr_attr; From b6d3ff8323c17a5c7b382fad601ccd75e244552a Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 12 Mar 2019 20:03:34 +0200 Subject: [PATCH 200/303] Changed: Parse css pt/em/rem size values --HG-- branch : develop --- code/nel/include/nel/gui/libwww.h | 3 + code/nel/src/gui/group_html.cpp | 96 +++++++++++++++++++++++++++---- code/nel/src/gui/libwww.cpp | 31 ++++++++++ 3 files changed, 118 insertions(+), 12 deletions(-) diff --git a/code/nel/include/nel/gui/libwww.h b/code/nel/include/nel/gui/libwww.h index 112cae7d7..84eeb01e9 100644 --- a/code/nel/include/nel/gui/libwww.h +++ b/code/nel/include/nel/gui/libwww.h @@ -280,6 +280,9 @@ namespace NLGUI #undef HTML_ATTR // *************************************************************************** + // Read a CSS length value, return true if one of supported units '%, rem, em, px, pt' + // On failure: 'value' and 'unit' values are undefined + bool getCssLength (float &value, std::string &unit, const std::string &str); // Read a width HTML parameter. "100" or "100%". Returns true if percent (0 ~ 1) else false bool getPercentage (sint32 &width, float &percent, const char *str); diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 7b81ef746..514bccf15 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -1851,10 +1851,11 @@ namespace NLGUI // Get the string name if (present[MY_HTML_IMG_SRC] && value[MY_HTML_IMG_SRC]) { - CStyleParams style; float tmpf; - std::string id; + CStyleParams style; + style.FontSize = _Style.FontSize; + if (present[MY_HTML_IMG_ID] && value[MY_HTML_IMG_ID]) id = value[MY_HTML_IMG_ID]; @@ -2190,6 +2191,7 @@ namespace NLGUI if (!(_Forms.empty())) { CStyleParams style; + style.FontSize = _Style.FontSize; // A select box string name; @@ -2699,6 +2701,7 @@ namespace NLGUI if (sep) { CStyleParams style; + style.FontSize = _Style.FontSize; style.TextColor = CRGBA(120, 120, 120, 255); style.Height = 0; style.Width = 0; @@ -6291,22 +6294,39 @@ namespace NLGUI float tmpf; TStyle styles = parseStyle(styleString); TStyle::iterator it; + + // first pass: get font-size for 'em' sizes for (it=styles.begin(); it != styles.end(); ++it) { if (it->first == "font-size") { if (it->second == "inherit") + { style.FontSize = current.FontSize; + } else { - float tmp; - sint size = 0; - getPercentage (size, tmp, it->second.c_str()); - if (size > 0) - style.FontSize = size; + std::string unit; + if (getCssLength(tmpf, unit, it->second.c_str())) + { + if (unit == "rem") + style.FontSize = _StyleDefault.FontSize * tmpf; + else if (unit == "em") + style.FontSize = current.FontSize * tmpf; + else if (unit == "pt") + style.FontSize = tmpf / 0.75f; + else if (unit == "%") + style.FontSize = current.FontSize * tmpf / 100.f; + else + style.FontSize = tmpf; + } } } - else + } + + // second pass: rest of style + for (it=styles.begin(); it != styles.end(); ++it) + { if (it->first == "font-style") { if (it->second == "inherit") @@ -6485,16 +6505,68 @@ namespace NLGUI } else if (it->first == "width") - getPercentage(style.Width, tmpf, it->second.c_str()); + { + std::string unit; + if (getCssLength(tmpf, unit, it->second.c_str())) + { + if (unit == "rem") + style.Width = tmpf * _StyleDefault.FontSize; + else if (unit == "em") + style.Width = tmpf * style.FontSize; + else if (unit == "pt") + style.FontSize = tmpf / 0.75f; + else + style.Width = tmpf; + } + } else if (it->first == "height") - getPercentage(style.Height, tmpf, it->second.c_str()); + { + std::string unit; + if (getCssLength(tmpf, unit, it->second.c_str())) + { + if (unit == "rem") + style.Height = tmpf * _StyleDefault.FontSize; + else if (unit == "em") + style.Height = tmpf * style.FontSize; + else if (unit == "pt") + style.FontSize = tmpf / 0.75f; + else + style.Height = tmpf; + } + } else if (it->first == "max-width") - getPercentage(style.MaxWidth, tmpf, it->second.c_str()); + { + std::string unit; + if (getCssLength(tmpf, unit, it->second.c_str())) + { + if (unit == "rem") + style.MaxWidth = tmpf * _StyleDefault.FontSize; + else if (unit == "em") + style.MaxWidth = tmpf * style.FontSize; + else if (unit == "pt") + style.FontSize = tmpf / 0.75f; + else + style.MaxWidth = tmpf; + } + } else if (it->first == "max-height") - getPercentage(style.MaxHeight, tmpf, it->second.c_str()); + { + std::string unit; + if (getCssLength(tmpf, unit, it->second.c_str())) + { + if (unit == "rem") + style.MaxHeight = tmpf * _StyleDefault.FontSize; + else if (unit == "em") + style.MaxHeight = tmpf * style.FontSize; + else if (unit == "pt") + style.FontSize = tmpf / 0.75f; + else + style.MaxHeight = tmpf; + } + } else if (it->first == "-ryzom-modulate-color") { diff --git a/code/nel/src/gui/libwww.cpp b/code/nel/src/gui/libwww.cpp index bb32fd5b6..ca8920b14 100644 --- a/code/nel/src/gui/libwww.cpp +++ b/code/nel/src/gui/libwww.cpp @@ -293,6 +293,37 @@ namespace NLGUI }; // *************************************************************************** + bool getCssLength (float &value, std::string &unit, const std::string &str) + { + std::string::size_type pos = 0; + std::string::size_type len = str.size(); + if (len == 1 && str[0] == '.') + { + return false; + } + + while(pos < len) + { + bool isNumeric = (str[pos] >= '0' && str[pos] <= '9') + || (pos == 0 && str[pos] == '.') + || (pos > 0 && str[pos] == '.' && str[pos-1] >= '0' && str[pos-1] <= '9'); + if (!isNumeric) + { + break; + } + + pos++; + } + + unit = toLower(str.substr(pos)); + if (unit == "%" || unit == "rem" || unit == "em" || unit == "px" || unit == "pt") + { + std::string tmpstr = str.substr(0, pos); + return fromString(tmpstr, value); + } + + return false; + } // Read a width HTML parameter. "100" or "100%". Returns true if percent (0 ~ 1) else false bool getPercentage (sint32 &width, float &percent, const char *str) From 69f73ba28ba18ccfbdcca954fd06c9988c20f13b Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 14 Mar 2019 14:57:55 +0200 Subject: [PATCH 201/303] Changed: Add hmin attribute to text button --HG-- branch : develop --- code/nel/include/nel/gui/ctrl_text_button.h | 8 +++++-- code/nel/src/gui/ctrl_text_button.cpp | 26 ++++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/code/nel/include/nel/gui/ctrl_text_button.h b/code/nel/include/nel/gui/ctrl_text_button.h index 69898639d..367e527f8 100644 --- a/code/nel/include/nel/gui/ctrl_text_button.h +++ b/code/nel/include/nel/gui/ctrl_text_button.h @@ -111,6 +111,9 @@ namespace NLGUI sint32 getWMin() const { return _WMin; } void setWMin( sint32 wmin ) { _WMin = wmin; } + sint32 getHMin() const { return _HMin; } + void setHMin( sint32 hmin ) { _HMin = hmin; } + // Compute Size according to bitmap and Text (Ensure as big as possible button) sint32 getWMax() const; @@ -122,6 +125,7 @@ namespace NLGUI REFLECT_SINT32("text_x", getTextX, setTextX) REFLECT_SINT32("wmargin", getWMargin, setWMargin) REFLECT_SINT32("wmin", getWMin, setWMin) + REFLECT_SINT32("hmin", getHMin, setHMin) REFLECT_LUA_METHOD("getViewText", luaGetViewText) REFLECT_EXPORT_END @@ -151,8 +155,8 @@ namespace NLGUI sint32 _BmpLeftW, _BmpMiddleW, _BmpRightW, _BmpH; // Value to add to TextW to get button W. sint32 _WMargin; - // Min W Value - sint32 _WMin; + // Min W, H Value + sint32 _WMin, _HMin; sint32 _TextY; sint32 _TextX; THotSpot _TextPosRef; diff --git a/code/nel/src/gui/ctrl_text_button.cpp b/code/nel/src/gui/ctrl_text_button.cpp index 6e1fab26e..9775b1b07 100644 --- a/code/nel/src/gui/ctrl_text_button.cpp +++ b/code/nel/src/gui/ctrl_text_button.cpp @@ -46,6 +46,7 @@ namespace NLGUI _BmpLeftW= _BmpMiddleW= _BmpRightW= _BmpH= 0; _WMargin= 0; _WMin= 0; + _HMin= 0; _TextX= 0; _TextY= 0; _Setuped= false; @@ -124,6 +125,11 @@ namespace NLGUI return toString( _WMin ); } else + if( name == "hmin" ) + { + return toString( _HMin ); + } + else if( name == "hardtext" ) { if( _ViewText != NULL ) @@ -296,6 +302,14 @@ namespace NLGUI return; } else + if( name == "hmin" ) + { + sint32 i; + if( fromString( value, i ) ) + _HMin = i; + return; + } + else if( name == "hardtext" ) { if( _ViewText != NULL ) @@ -469,6 +483,7 @@ namespace NLGUI xmlNewProp( node, BAD_CAST "wmargin", BAD_CAST toString( _WMargin ).c_str() ); xmlNewProp( node, BAD_CAST "wmin", BAD_CAST toString( _WMin ).c_str() ); + xmlNewProp( node, BAD_CAST "hmin", BAD_CAST toString( _HMin ).c_str() ); xmlNewProp( node, BAD_CAST "hardtext", BAD_CAST _ViewText->getText().toString().c_str() ); xmlNewProp( node, BAD_CAST "text_y", BAD_CAST toString( _TextY ).c_str() ); xmlNewProp( node, BAD_CAST "text_x", BAD_CAST toString( _TextX ).c_str() ); @@ -519,7 +534,6 @@ namespace NLGUI return false; } - // *** Read Textures. prop = (char*) xmlGetProp( cur, (xmlChar*)"tx_normal" ); if (prop) @@ -604,6 +618,15 @@ namespace NLGUI // _WMin is at least the size of All W Bitmaps _WMin= max(_WMin, _BmpLeftW + _BmpMiddleW + _BmpRightW); + // hmin + _HMin= 0; + prop = (char*) xmlGetProp( cur, (xmlChar*)"hmin" ); + if (prop) + { + fromString((const char *) prop, _HMin); + } + _HMin= max(_HMin, _BmpH); + // TextY _TextY= 0; prop = (char*) xmlGetProp( cur, (xmlChar*)"text_y" ); @@ -900,6 +923,7 @@ namespace NLGUI if (!(_SizeRef & 2)) { _H= max(_BmpH, _ViewText->getH()); + _H= max(_H, _HMin); } CViewBase::updateCoords(); From 64e54f24c1d923c074e1cc4f3442a82543827c63 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 14 Mar 2019 22:59:33 +0200 Subject: [PATCH 202/303] Changed: Form element styling --HG-- branch : develop --- code/nel/include/nel/gui/ctrl_text_button.h | 7 + code/nel/include/nel/gui/dbgroup_combo_box.h | 1 + code/nel/include/nel/gui/group_html.h | 8 ++ code/nel/include/nel/gui/group_menu.h | 3 + code/nel/src/gui/ctrl_text_button.cpp | 37 ++++++ code/nel/src/gui/dbgroup_combo_box.cpp | 9 ++ code/nel/src/gui/group_html.cpp | 133 ++++++++++++++++--- code/nel/src/gui/group_menu.cpp | 6 + 8 files changed, 188 insertions(+), 16 deletions(-) diff --git a/code/nel/include/nel/gui/ctrl_text_button.h b/code/nel/include/nel/gui/ctrl_text_button.h index 367e527f8..e88ec81e1 100644 --- a/code/nel/include/nel/gui/ctrl_text_button.h +++ b/code/nel/include/nel/gui/ctrl_text_button.h @@ -117,6 +117,13 @@ namespace NLGUI // Compute Size according to bitmap and Text (Ensure as big as possible button) sint32 getWMax() const; + // Set texture directly without _l.tga, _m.tga, _r.tga convention + // Texture size is only read from normal textures + // If updateHeight == false, then _BmpH will keep its value + void setTexture(const std::string &l, const std::string &m, const std::string &r, bool updateHeight = true); + 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); + int luaGetViewText(CLuaState &ls); REFLECT_EXPORT_START(CCtrlTextButton, CCtrlBaseButton) diff --git a/code/nel/include/nel/gui/dbgroup_combo_box.h b/code/nel/include/nel/gui/dbgroup_combo_box.h index 87e6d758a..723afbdc0 100644 --- a/code/nel/include/nel/gui/dbgroup_combo_box.h +++ b/code/nel/include/nel/gui/dbgroup_combo_box.h @@ -85,6 +85,7 @@ namespace NLGUI // view text void setViewText(const ucstring & text); ucstring getViewText() const; + CViewText *getViewText(); void setTexture(uint i, const ucstring &texture); diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index 8b296f114..71d7b9ff0 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -33,6 +33,7 @@ typedef std::map TStyle; namespace NLGUI { class CCtrlButton; + class CCtrlTextButton; class CCtrlScroll; class CGroupList; class CGroupMenu; @@ -105,7 +106,9 @@ namespace NLGUI Height=-1; MaxWidth=-1; MaxHeight=-1; + BorderWidth=1; BackgroundColor=NLMISC::CRGBA::Black; + BackgroundColorOver=NLMISC::CRGBA::Black; } uint FontSize; uint FontWeight; @@ -120,7 +123,9 @@ namespace NLGUI sint32 Height; sint32 MaxWidth; sint32 MaxHeight; + sint32 BorderWidth; NLMISC::CRGBA BackgroundColor; + NLMISC::CRGBA BackgroundColorOver; }; // ImageDownload system @@ -857,6 +862,9 @@ namespace NLGUI void setImage(CViewBase *view, const std::string &file, const TImageType type); void setImageSize(CViewBase *view, const CStyleParams &style = CStyleParams()); + void setTextButtonStyle(CCtrlTextButton *ctrlButton, const CStyleParams &style); + void setTextStyle(CViewText *pVT, const CStyleParams &style); + // BnpDownload system void initBnpDownload(); void checkBnpDownload(); diff --git a/code/nel/include/nel/gui/group_menu.h b/code/nel/include/nel/gui/group_menu.h index d4f940088..cfe91f7f9 100644 --- a/code/nel/include/nel/gui/group_menu.h +++ b/code/nel/include/nel/gui/group_menu.h @@ -351,6 +351,9 @@ namespace NLGUI void setMinW(sint32 minW); void setMinH(sint32 minH); + // change fontsize for new menu items + void setFontSize(uint32 fontSize); + // Gray a line on the RootMenu void setGrayedLine(uint line, bool g); diff --git a/code/nel/src/gui/ctrl_text_button.cpp b/code/nel/src/gui/ctrl_text_button.cpp index 9775b1b07..d10dfa0c9 100644 --- a/code/nel/src/gui/ctrl_text_button.cpp +++ b/code/nel/src/gui/ctrl_text_button.cpp @@ -728,6 +728,43 @@ namespace NLGUI return true; } + // *************************************************************************** + void CCtrlTextButton::setTexture(const std::string &l, const std::string &m, const std::string &r, bool updateHeight) + { + nlctassert(NumTexture==3); + _TextureIdNormal[0].setTexture(l.c_str()); + _TextureIdNormal[1].setTexture(m.c_str()); + _TextureIdNormal[2].setTexture(r.c_str()); + + sint32 newH; + + // Compute Bmp Sizes + CViewRenderer &rVR = *CViewRenderer::getInstance(); + rVR.getTextureSizeFromId(_TextureIdNormal[0], _BmpLeftW, newH); + rVR.getTextureSizeFromId(_TextureIdNormal[1], _BmpMiddleW, newH); + rVR.getTextureSizeFromId(_TextureIdNormal[2], _BmpRightW, newH); + + if (updateHeight) _BmpH = newH; + } + + // *************************************************************************** + void CCtrlTextButton::setTexturePushed(const std::string &l, const std::string &m, const std::string &r) + { + nlctassert(NumTexture==3); + _TextureIdPushed[0].setTexture(l.c_str()); + _TextureIdPushed[1].setTexture(m.c_str()); + _TextureIdPushed[2].setTexture(r.c_str()); + } + + // *************************************************************************** + void CCtrlTextButton::setTextureOver(const std::string &l, const std::string &m, const std::string &r) + { + nlctassert(NumTexture==3); + _TextureIdOver[0].setTexture(l.c_str()); + _TextureIdOver[1].setTexture(m.c_str()); + _TextureIdOver[2].setTexture(r.c_str()); + } + // *************************************************************************** void CCtrlTextButton::draw () { diff --git a/code/nel/src/gui/dbgroup_combo_box.cpp b/code/nel/src/gui/dbgroup_combo_box.cpp index 2afd8c570..5893c0b72 100644 --- a/code/nel/src/gui/dbgroup_combo_box.cpp +++ b/code/nel/src/gui/dbgroup_combo_box.cpp @@ -473,6 +473,12 @@ namespace NLGUI return _ViewText->getText(); } + // *************************************************************************** + CViewText *CDBGroupComboBox::getViewText() + { + return _ViewText; + } + // *************************************************************************** std::string CDBGroupComboBox::getSelectionText() const { @@ -633,6 +639,9 @@ namespace NLGUI { nlassert(groupMenu); + if (_ViewText) + groupMenu->setFontSize(_ViewText->getFontSize()); + // Setup the menu with combo action. groupMenu->reset(); for(uint i=0; i treating it like "display: inline-block;" + if (style.Width > 0) ctrlButton->setWMin(_Style.Width); + if (style.Height > 0) ctrlButton->setHMin(_Style.Height); + + CViewText *pVT = ctrlButton->getViewText(); + if (pVT) + { + setTextStyle(pVT, _Style); + } + + if (_Style.BackgroundColor.A > 0) + { + if (_Style.BackgroundColorOver.A == 0) + _Style.BackgroundColorOver = _Style.BackgroundColor; + + ctrlButton->setColor(_Style.BackgroundColor); + ctrlButton->setColorOver(_Style.BackgroundColorOver); + ctrlButton->setTexture("", "blank.tga", "", false); + ctrlButton->setTextureOver("", "blank.tga", ""); + ctrlButton->setProperty("force_text_over", "true"); + } + else if (_Style.BackgroundColorOver.A > 0) + { + ctrlButton->setColorOver(_Style.BackgroundColorOver); + ctrlButton->setProperty("force_text_over", "true"); + ctrlButton->setTextureOver("blank.tga", "blank.tga", "blank.tga"); + } + } + + void CGroupHTML::setTextStyle(CViewText *pVT, const CStyleParams &style) + { + if (pVT) + { + pVT->setFontSize(style.FontSize); + pVT->setColor(style.TextColor); + pVT->setColor(style.TextColor); + pVT->setFontName(style.FontFamily); + pVT->setFontSize(style.FontSize); + pVT->setEmbolden(style.FontWeight >= FONT_WEIGHT_BOLD); + pVT->setOblique(style.FontOblique); + pVT->setUnderlined(style.Underlined); + pVT->setStrikeThrough(style.StrikeThrough); + if (style.TextShadow.Enabled) + { + pVT->setShadow(true); + pVT->setShadowColor(style.TextShadow.Color); + pVT->setShadowOutline(style.TextShadow.Outline); + pVT->setShadowOffset(style.TextShadow.X, style.TextShadow.Y); + } + } + } + // Get an url and return the local filename with the path where the url image should be string CGroupHTML::localImageName(const string &url) { @@ -1556,6 +1610,10 @@ namespace NLGUI _Style.TextColor = LinkColor; _Style.Underlined = true; _Style.GlobalColor = LinkColorGlobalColor; + _Style.BackgroundColor.A = 0; + _Style.BackgroundColorOver.A = 0; + _Style.Width = -1; + _Style.Height = -1; if (present[HTML_A_STYLE] && value[HTML_A_STYLE]) getStyleParams(value[HTML_A_STYLE], _Style); @@ -1956,6 +2014,13 @@ namespace NLGUI _Style.FontSize = TextFontSize; _Style.FontWeight = FONT_WEIGHT_NORMAL; _Style.FontOblique = false; + _Style.TextShadow = STextShadow(true); + _Style.Width = -1; + _Style.Height = -1; + // by default background texture is transparent, + // using alpha value to decide if to change it to 'blank.tga' for coloring + _Style.BackgroundColor.A = 0; + _Style.BackgroundColorOver.A = 0; // Global color flag if (present[MY_HTML_INPUT_GLOBAL_COLOR]) @@ -2058,6 +2123,8 @@ namespace NLGUI } ctrlButton->setText(ucstring::makeFromUtf8(text)); + + setTextButtonStyle(ctrlButton, _Style); } getParagraph()->addChild (buttonGroup); paragraphChange (); @@ -2226,6 +2293,7 @@ namespace NLGUI sb->setMinH(style.Height); sb->setMaxVisibleLine(size); + sb->setFontSize(style.FontSize); } entry.SelectBox = sb; @@ -2234,6 +2302,14 @@ namespace NLGUI { CDBGroupComboBox *cb = addComboBox(DefaultFormSelectGroup, name.c_str()); entry.ComboBox = cb; + + if (cb) + { + // create view text + cb->updateCoords(); + if (cb->getViewText()) + setTextStyle(cb->getViewText(), style); + } } _Forms.back().Entries.push_back (entry); } @@ -2460,6 +2536,9 @@ namespace NLGUI _Style.FontOblique = false; _Style.FontSize = TextFontSize; _Style.TextShadow = STextShadow(true); + _Style.Width = -1; + _Style.Height = -1; + _Style.BackgroundColor.A = 0; if (present[MY_HTML_TEXTAREA_STYLE] && value[MY_HTML_TEXTAREA_STYLE]) getStyleParams(value[MY_HTML_TEXTAREA_STYLE], _Style); @@ -4494,6 +4573,8 @@ namespace NLGUI // Translate the tooltip ctrlButton->setDefaultContextHelp(ucstring::makeFromUtf8(getLinkTitle())); ctrlButton->setText(tmpStr); + + setTextButtonStyle(ctrlButton, _Style); } getParagraph()->addChild (buttonGroup); paragraphChange (); @@ -4516,23 +4597,10 @@ namespace NLGUI } } newLink->setText(tmpStr); - newLink->setColor(_Style.TextColor); - newLink->setFontName(_Style.FontFamily); - newLink->setFontSize(_Style.FontSize); - newLink->setEmbolden(embolden); - newLink->setOblique(_Style.FontOblique); - newLink->setUnderlined(_Style.Underlined); - newLink->setStrikeThrough(_Style.StrikeThrough); newLink->setMultiLineSpace((uint)((float)(_Style.FontSize)*LineSpaceFontFactor)); newLink->setMultiLine(true); newLink->setModulateGlobalColor(_Style.GlobalColor); - if (_Style.TextShadow.Enabled) - { - newLink->setShadow(true); - newLink->setShadowColor(_Style.TextShadow.Color); - newLink->setShadowOutline(_Style.TextShadow.Outline); - newLink->setShadowOffset(_Style.TextShadow.X, _Style.TextShadow.Y); - } + setTextStyle(newLink, _Style); // newLink->setLineAtBottom (true); registerAnchor(newLink); @@ -4638,6 +4706,10 @@ namespace NLGUI _CurrentViewLink = NULL; { + // override cols/rows values from style + if (_Style.Width > 0) cols = _Style.Width / _Style.FontSize; + if (_Style.Height > 0) rows = _Style.Height / _Style.FontSize; + // Not added ? std::vector > templateParams; templateParams.push_back (std::pair ("w", toString (cols*_Style.FontSize))); @@ -4675,7 +4747,18 @@ namespace NLGUI // Set the content CGroupEditBox *eb = dynamic_cast(textArea->getGroup("eb")); if (eb) + { eb->setInputString(decodeHTMLEntities(content)); + if (_Style.BackgroundColor.A > 0) + { + CViewBitmap *bg = dynamic_cast(eb->getView("bg")); + if (bg) + { + bg->setTexture("blank.tga"); + bg->setColor(_Style.BackgroundColor); + } + } + } textArea->invalidateCoords(); getParagraph()->addChild (textArea); @@ -6327,6 +6410,16 @@ namespace NLGUI // second pass: rest of style for (it=styles.begin(); it != styles.end(); ++it) { + if (it->first == "border") + { + sint32 b; + if (it->second == "none") + style.BorderWidth = 0; + else + if (fromString(it->second, b)) + style.BorderWidth = b; + } + else if (it->first == "font-style") { if (it->second == "inherit") @@ -6581,10 +6674,18 @@ namespace NLGUI if (it->first == "background-color") { if (it->second == "inherit") - style.BackgroundColor = current.backgroundColor; + style.BackgroundColor = current.BackgroundColor; else scanHTMLColor(it->second.c_str(), style.BackgroundColor); } + else + if (it->first == "-ryzom-background-color-over") + { + if (it->second == "inherit") + style.BackgroundColorOver = current.BackgroundColorOver; + else + scanHTMLColor(it->second.c_str(), style.BackgroundColorOver); + } } } diff --git a/code/nel/src/gui/group_menu.cpp b/code/nel/src/gui/group_menu.cpp index 7d002cfd6..d8b3452ed 100644 --- a/code/nel/src/gui/group_menu.cpp +++ b/code/nel/src/gui/group_menu.cpp @@ -2561,6 +2561,12 @@ namespace NLGUI } } + // ------------------------------------------------------------------------------------------------ + void CGroupMenu::setFontSize(uint fontSize) + { + _FontSize = fontSize; + } + // ------------------------------------------------------------------------------------------------ uint CGroupMenu::getNumLine() const { From dafd8cf7f7beceab7cce63a389c40b4d4fe1ab60 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 15 Mar 2019 15:41:02 +0200 Subject: [PATCH 203/303] Changed: Add font inherit style rule --HG-- branch : develop --- code/nel/src/gui/group_html.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index d36747a8d..783861f45 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -6381,6 +6381,17 @@ namespace NLGUI // first pass: get font-size for 'em' sizes for (it=styles.begin(); it != styles.end(); ++it) { + if (it->first == "font") + { + if (it->second == "inherit") + { + style.FontSize = current.FontSize; + style.FontFamily = current.FontFamily; + style.FontWeight = current.FontWeight; + style.FontOblique = current.FontOblique; + } + } + else if (it->first == "font-size") { if (it->second == "inherit") From 24767a86dfc26ed4e55e3b7f2cf4f91a58c7508e Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 15 Mar 2019 15:41:02 +0200 Subject: [PATCH 204/303] Fixed: CSS inherit rules --HG-- branch : develop --- code/nel/include/nel/gui/group_html.h | 2 +- code/nel/src/gui/group_html.cpp | 73 +++++++++++++-------------- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index 71d7b9ff0..20584b04e 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -796,7 +796,7 @@ namespace NLGUI static TGroupHtmlByUIDMap _GroupHtmlByUID; // read style attribute - void getStyleParams(const std::string &styleString, CStyleParams &style, bool inherit = true); + void getStyleParams(const std::string &styleString, CStyleParams &style, const CStyleParams ¤t); void applyCssMinMax(sint32 &width, sint32 &height, sint32 minw=0, sint32 minh=0, sint32 maxw=0, sint32 maxh=0); // load and render local html file (from bnp for example) diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 783861f45..2b4786a79 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -1545,7 +1545,7 @@ namespace NLGUI { case HTML_HTML: if (present[MY_HTML_HTML_STYLE] && value[MY_HTML_HTML_STYLE]) - getStyleParams(value[MY_HTML_HTML_STYLE], _StyleDefault); + getStyleParams(value[MY_HTML_HTML_STYLE], _StyleDefault, _StyleDefault); _Style = _StyleDefault; setBackgroundColor(_Style.BackgroundColor); @@ -1616,7 +1616,7 @@ namespace NLGUI _Style.Height = -1; if (present[HTML_A_STYLE] && value[HTML_A_STYLE]) - getStyleParams(value[HTML_A_STYLE], _Style); + getStyleParams(value[HTML_A_STYLE], _Style, _StyleParams.back()); _A.push_back(true); _Link.push_back (""); @@ -1669,7 +1669,7 @@ namespace NLGUI style = value[MY_HTML_DIV_STYLE]; if (!style.empty()) - getStyleParams(style, _Style); + getStyleParams(style, _Style, _StyleParams.back()); // use generic template system if (_TrustedDomain && !instClass.empty() && instClass == "ryzom-ui-grouptemplate") @@ -1780,7 +1780,7 @@ namespace NLGUI style = value[HTML_BODY_STYLE]; if (!style.empty()) - getStyleParams(style, _Style); + getStyleParams(style, _Style, _StyleParams.back()); CRGBA bgColor = _Style.BackgroundColor; if (present[HTML_BODY_BGCOLOR] && value[HTML_BODY_BGCOLOR]) @@ -1841,7 +1841,7 @@ namespace NLGUI _Style.TextColor = H1Color; _Style.GlobalColor = H1ColorGlobalColor; if (present[MY_HTML_H1_STYLE] && value[MY_HTML_H1_STYLE]) - getStyleParams(value[MY_HTML_H1_STYLE], _Style); + getStyleParams(value[MY_HTML_H1_STYLE], _Style, _StyleParams.back()); } break; case HTML_H2: @@ -1853,7 +1853,7 @@ namespace NLGUI _Style.TextColor = H2Color; _Style.GlobalColor = H2ColorGlobalColor; if (present[MY_HTML_H2_STYLE] && value[MY_HTML_H2_STYLE]) - getStyleParams(value[MY_HTML_H2_STYLE], _Style); + getStyleParams(value[MY_HTML_H2_STYLE], _Style, _StyleParams.back()); } break; case HTML_H3: @@ -1865,7 +1865,7 @@ namespace NLGUI _Style.TextColor = H3Color; _Style.GlobalColor = H3ColorGlobalColor; if (present[MY_HTML_H3_STYLE] && value[MY_HTML_H3_STYLE]) - getStyleParams(value[MY_HTML_H3_STYLE], _Style); + getStyleParams(value[MY_HTML_H3_STYLE], _Style, _StyleParams.back()); } break; case HTML_H4: @@ -1877,7 +1877,7 @@ namespace NLGUI _Style.TextColor = H4Color; _Style.GlobalColor = H4ColorGlobalColor; if (present[MY_HTML_H4_STYLE] && value[MY_HTML_H4_STYLE]) - getStyleParams(value[MY_HTML_H4_STYLE], _Style); + getStyleParams(value[MY_HTML_H4_STYLE], _Style, _StyleParams.back()); } break; case HTML_H5: @@ -1889,7 +1889,7 @@ namespace NLGUI _Style.TextColor = H5Color; _Style.GlobalColor = H5ColorGlobalColor; if (present[MY_HTML_H5_STYLE] && value[MY_HTML_H5_STYLE]) - getStyleParams(value[MY_HTML_H5_STYLE], _Style); + getStyleParams(value[MY_HTML_H5_STYLE], _Style, _StyleParams.back()); } break; case HTML_H6: @@ -1901,7 +1901,7 @@ namespace NLGUI _Style.TextColor = H6Color; _Style.GlobalColor = H6ColorGlobalColor; if (present[MY_HTML_H6_STYLE] && value[MY_HTML_H6_STYLE]) - getStyleParams(value[MY_HTML_H6_STYLE], _Style); + getStyleParams(value[MY_HTML_H6_STYLE], _Style, _StyleParams.back()); } break; case HTML_IMG: @@ -1928,7 +1928,7 @@ namespace NLGUI // width, height from inline css if (present[MY_HTML_IMG_STYLE] && value[MY_HTML_IMG_STYLE]) - getStyleParams(value[MY_HTML_IMG_STYLE], style); + getStyleParams(value[MY_HTML_IMG_STYLE], style, _Style); // Tooltip const char *tooltip = NULL; @@ -2032,7 +2032,7 @@ namespace NLGUI tooltip = value[MY_HTML_INPUT_ALT]; if (present[MY_HTML_INPUT_STYLE] && value[MY_HTML_INPUT_STYLE]) - getStyleParams(value[MY_HTML_INPUT_STYLE], _Style); + getStyleParams(value[MY_HTML_INPUT_STYLE], _Style, _StyleParams.back()); string type = toLower(value[MY_HTML_INPUT_TYPE]); if (type == "image") @@ -2258,7 +2258,6 @@ namespace NLGUI if (!(_Forms.empty())) { CStyleParams style; - style.FontSize = _Style.FontSize; // A select box string name; @@ -2272,7 +2271,7 @@ namespace NLGUI if (present[HTML_SELECT_MULTIPLE] && value[HTML_SELECT_MULTIPLE]) multiple = true; if (present[HTML_SELECT_STYLE] && value[HTML_SELECT_STYLE]) - getStyleParams(value[HTML_SELECT_STYLE], style); + getStyleParams(value[HTML_SELECT_STYLE], style, _Style); CGroupHTML::CForm::CEntry entry; entry.Name = name; @@ -2356,7 +2355,7 @@ namespace NLGUI pushStyle(); if (present[HTML_LI_STYLE] && value[HTML_LI_STYLE]) - getStyleParams(value[HTML_LI_STYLE], _Style); + getStyleParams(value[HTML_LI_STYLE], _Style, _StyleParams.back()); ucstring str; str.fromUtf8(_UL.back().getListMarkerText()); @@ -2379,7 +2378,7 @@ namespace NLGUI newParagraph(PBeginSpace); pushStyle(); if (present[MY_HTML_P_STYLE] && value[MY_HTML_P_STYLE]) - getStyleParams(value[MY_HTML_P_STYLE], _Style); + getStyleParams(value[MY_HTML_P_STYLE], _Style, _StyleParams.back()); } break; case HTML_PRE: @@ -2388,7 +2387,7 @@ namespace NLGUI _Style.FontFamily = "monospace"; if (present[HTML_PRE_STYLE] && value[HTML_PRE_STYLE]) - getStyleParams(value[HTML_PRE_STYLE], _Style); + getStyleParams(value[HTML_PRE_STYLE], _Style, _StyleParams.back()); _PRE.push_back(true); @@ -2416,7 +2415,7 @@ namespace NLGUI if (present[MY_HTML_TABLE_CELLPADDING] && value[MY_HTML_TABLE_CELLPADDING]) fromString(value[MY_HTML_TABLE_CELLPADDING], table->CellPadding); if (present[MY_HTML_TABLE_STYLE] && value[MY_HTML_TABLE_STYLE]) - getStyleParams(value[MY_HTML_TABLE_STYLE], _Style); + getStyleParams(value[MY_HTML_TABLE_STYLE], _Style, _StyleParams.back()); table->setMarginLeft(getIndent()); addHtmlGroup (table, 0); @@ -2446,7 +2445,7 @@ namespace NLGUI } if (present[MY_HTML_TD_STYLE] && value[MY_HTML_TD_STYLE]) - getStyleParams(value[MY_HTML_TD_STYLE], _Style); + getStyleParams(value[MY_HTML_TD_STYLE], _Style, _StyleParams.back()); CGroupTable *table = getTable(); if (table) @@ -2541,7 +2540,7 @@ namespace NLGUI _Style.BackgroundColor.A = 0; if (present[MY_HTML_TEXTAREA_STYLE] && value[MY_HTML_TEXTAREA_STYLE]) - getStyleParams(value[MY_HTML_TEXTAREA_STYLE], _Style); + getStyleParams(value[MY_HTML_TEXTAREA_STYLE], _Style, _StyleParams.back()); // Got one form ? if (!(_Forms.empty())) @@ -2597,7 +2596,7 @@ namespace NLGUI pushStyle(); if (present[MY_HTML_TR_STYLE] && value[MY_HTML_TR_STYLE]) - getStyleParams(value[MY_HTML_TR_STYLE], _Style); + getStyleParams(value[MY_HTML_TR_STYLE], _Style, _StyleParams.back()); } break; case HTML_UL: @@ -2614,7 +2613,7 @@ namespace NLGUI pushStyle(); if (present[HTML_UL_STYLE] && value[HTML_UL_STYLE]) - getStyleParams(value[HTML_UL_STYLE], _Style); + getStyleParams(value[HTML_UL_STYLE], _Style, _StyleParams.back()); break; case HTML_OBJECT: _ObjectType.clear(); @@ -2637,7 +2636,7 @@ namespace NLGUI pushStyle(); if (present[MY_HTML_SPAN_STYLE] && value[MY_HTML_SPAN_STYLE]) - getStyleParams(value[MY_HTML_SPAN_STYLE], _Style); + getStyleParams(value[MY_HTML_SPAN_STYLE], _Style, _StyleParams.back()); } break; case HTML_DEL: @@ -2681,7 +2680,7 @@ namespace NLGUI endParagraph(); pushStyle(); if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE]) - getStyleParams(value[HTML_GEN_STYLE], _Style); + getStyleParams(value[HTML_GEN_STYLE], _Style, _StyleParams.back()); } break; case HTML_DT: @@ -2704,7 +2703,7 @@ namespace NLGUI pushStyle(); _Style.FontWeight = FONT_WEIGHT_BOLD; if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE]) - getStyleParams(value[HTML_GEN_STYLE], _Style); + getStyleParams(value[HTML_GEN_STYLE], _Style, _StyleParams.back()); if (!_LI) { @@ -2739,7 +2738,7 @@ namespace NLGUI pushStyle(); if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE]) - getStyleParams(value[HTML_GEN_STYLE], _Style); + getStyleParams(value[HTML_GEN_STYLE], _Style, _StyleParams.back()); if (!_LI) { @@ -2763,7 +2762,7 @@ namespace NLGUI if (present[HTML_OL_TYPE] && value[HTML_OL_TYPE]) type = value[HTML_OL_TYPE]; if (present[HTML_OL_STYLE] && value[HTML_OL_STYLE]) - getStyleParams(value[HTML_OL_STYLE], _Style); + getStyleParams(value[HTML_OL_STYLE], _Style, _StyleParams.back()); _UL.push_back(HTMLOListElement(start, type)); // if LI is already present @@ -2786,7 +2785,7 @@ namespace NLGUI style.Width = 0; if (present[HTML_HR_STYLE] && value[HTML_HR_STYLE]) - getStyleParams(value[HTML_HR_STYLE], style); + getStyleParams(value[HTML_HR_STYLE], style, _Style); CViewBitmap *bitmap = dynamic_cast(sep->getView("hr")); if (bitmap) @@ -6364,16 +6363,8 @@ namespace NLGUI // style.TextColor; // color: #ABCDEF; // style.Underlined; // text-decoration: underline; text-decoration-line: underline; // style.StrikeThrough; // text-decoration: line-through; text-decoration-line: line-through; - void CGroupHTML::getStyleParams(const std::string &styleString, CStyleParams &style, bool inherit) + void CGroupHTML::getStyleParams(const std::string &styleString, CStyleParams &style, const CStyleParams ¤t) { - const CStyleParams current = _Style; - - if (inherit) - { - style.Underlined = current.Underlined; - style.StrikeThrough = current.StrikeThrough; - } - float tmpf; TStyle styles = parseStyle(styleString); TStyle::iterator it; @@ -6698,6 +6689,14 @@ namespace NLGUI scanHTMLColor(it->second.c_str(), style.BackgroundColorOver); } } + + // if outer element has underline set, then inner element cannot remove it + if (current.Underlined) + style.Underlined = current.Underlined; + + // if outer element has line-through set, then inner element cannot remove it + if (current.StrikeThrough) + style.StrikeThrough = current.StrikeThrough; } // *************************************************************************** From eee4684b0c7db1beb204eb50abce27d5412763a7 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 15 Mar 2019 15:41:02 +0200 Subject: [PATCH 205/303] Fixed: Invalid window mode switch in some cases. --HG-- branch : develop --- code/ryzom/client/src/init.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index b653127f4..d80cfda00 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -1096,23 +1096,21 @@ void prelogInit() UDriver::CMode mode; - bool forceWindowed1024x768 = true; - if (Driver->getCurrentScreenMode(mode)) { - // if screen mode lower than 1024x768, use same mode in fullscreen - if (mode.Width <= 1024 && mode.Height <= 768) + // use current mode if its smaller than 1024x768 + // mode should be windowed already, but incase its not, use the mode as is + if (mode.Windowed && (mode.Width > 1024 && mode.Height > 768)) { - mode.Windowed = false; - forceWindowed1024x768 = false; + mode.Width = 1024; + mode.Height = 768; } } - - if (forceWindowed1024x768) + else { - mode.Width = 1024; - mode.Height = 768; - mode.Windowed = true; + mode.Width = 1024; + mode.Height = 768; + mode.Windowed = true; } // Disable Hardware Vertex Program. From 4e7d33729742d43c906a72f72d5264ab0b2e8c3c Mon Sep 17 00:00:00 2001 From: Nimetu Date: Wed, 20 Mar 2019 12:25:15 +0200 Subject: [PATCH 206/303] Changed: Only capture mouse for freeview or when button is held and mouse is moving --HG-- branch : develop --- code/ryzom/client/src/input.cpp | 36 +++++++++++++++------------------ code/ryzom/client/src/input.h | 3 --- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/code/ryzom/client/src/input.cpp b/code/ryzom/client/src/input.cpp index bf90d92bd..d554002ed 100644 --- a/code/ryzom/client/src/input.cpp +++ b/code/ryzom/client/src/input.cpp @@ -84,9 +84,6 @@ bool InitMouseWithCursor (bool hardware) MouseHardware = hardware; CViewPointer::setHWMouse( hardware ); - // Update mouse information - UpdateMouse (); - if (InitMouseFirstTime) { InitMouseFirstTime = false; @@ -129,16 +126,6 @@ bool IsMouseCursorHardware () return MouseHardware; } -// ********************************************************************************* -// Set the mouse mode. Call this method once per frame to update window size -void UpdateMouse () -{ - if (!Driver->isSystemCursorCaptured()) - { - DownMouseButtons = 0; - } -} - // ********************************************************************************* // Use this method to toggle the mouse (freelook <- cursor) void SetMouseFreeLook () @@ -160,7 +147,6 @@ void SetMouseFreeLook () pointer->show (false); } } - UpdateMouse (); } } @@ -202,7 +188,6 @@ void SetMouseCursor (bool updatePos) } MouseFreeLook = false; - UpdateMouse (); // Integer coordinates sint ix = (sint)(x*(float)width+0.5f); @@ -253,7 +238,6 @@ void SetMouseCursor (bool updatePos) void SetMouseSpeed (float speed) { MouseCursorSpeed = speed; - UpdateMouse (); } // ********************************************************************************* @@ -261,12 +245,27 @@ void SetMouseSpeed (float speed) void SetMouseAcceleration (uint accel) { MouseCursorAcceleration = accel; - UpdateMouse (); } // ********************************************************************************* void HandleSystemCursorCapture(const CEvent &event) { + static bool mouseCaptured = false; + + // capture on first move event after button is held down or free look is activated + if (event == EventMouseMoveId && !mouseCaptured && (MouseFreeLook || DownMouseButtons != 0)) + { + mouseCaptured = true; + Driver->setCapture(true); + } + + // release when button is released and not in free look + if (mouseCaptured && !MouseFreeLook && DownMouseButtons == 0) + { + mouseCaptured = false; + Driver->setCapture(false); + } + if (event == EventMouseDownId) { CEventMouseDown &em = (CEventMouseDown &) event; @@ -279,8 +278,6 @@ void HandleSystemCursorCapture(const CEvent &event) cursor->setPointerMiddleDown(em.Button == middleButton); cursor->setPointerRightDown(em.Button == rightButton); } - - Driver->setCapture(true); } if (event == EventMouseUpId) @@ -297,7 +294,6 @@ void HandleSystemCursorCapture(const CEvent &event) cursor->setPointerMiddleDown(false); cursor->setPointerRightDown(false); } - Driver->setCapture(false); } } diff --git a/code/ryzom/client/src/input.h b/code/ryzom/client/src/input.h index e7579d375..60288416d 100644 --- a/code/ryzom/client/src/input.h +++ b/code/ryzom/client/src/input.h @@ -44,9 +44,6 @@ bool InitMouseWithCursor (bool hardware); // Is mouse cursor hardware ? bool IsMouseCursorHardware (); -// Set the mouse mode. Call this method once per frame to update window size -void UpdateMouse (); - // Use this method to toggle the mouse (freelook <- cursor) void SetMouseFreeLook (); From f23fa7b0fe287ef7b1b900fee6663f57b8d9c51f Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 28 Mar 2019 14:44:58 +0200 Subject: [PATCH 207/303] Added: const char* version of toLower() --HG-- branch : develop --- code/nel/include/nel/misc/common.h | 1 + code/nel/src/misc/common.cpp | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/code/nel/include/nel/misc/common.h b/code/nel/include/nel/misc/common.h index eb70fce9e..d5d59b130 100644 --- a/code/nel/include/nel/misc/common.h +++ b/code/nel/include/nel/misc/common.h @@ -222,6 +222,7 @@ inline double isValidDouble (double v) * \param str a string to transform to lower case */ +std::string toLower ( const char *str ); std::string toLower ( const std::string &str ); void toLower ( char *str ); char toLower ( const char ch ); // convert only one character diff --git a/code/nel/src/misc/common.cpp b/code/nel/src/misc/common.cpp index 48e6e9845..72f29eb82 100644 --- a/code/nel/src/misc/common.cpp +++ b/code/nel/src/misc/common.cpp @@ -591,6 +591,22 @@ NLMISC_CATEGORISED_COMMAND(nel,stohr, "Convert a second number into an human rea return true; } +std::string toLower(const char *str) +{ + if (!str) return ""; + + uint len = strlen(str); + string res; + res.reserve(len); + for(uint i = 0; i < len; i++) + { + if( (str[i] >= 'A') && (str[i] <= 'Z') ) + res += str[i] - 'A' + 'a'; + else + res += str[i]; + } + return res; +} std::string toLower(const std::string &str) { From d67a9ccdb538299bc082d63b9043772f813607ae Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 25 Apr 2019 08:28:45 +0300 Subject: [PATCH 208/303] Backed out changeset: ce73fd40aa54 --HG-- branch : develop --- code/nel/src/misc/file.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/src/misc/file.cpp b/code/nel/src/misc/file.cpp index 54ffdfbc6..414a10e5a 100644 --- a/code/nel/src/misc/file.cpp +++ b/code/nel/src/misc/file.cpp @@ -185,7 +185,7 @@ bool CIFile::open(const std::string &path, bool text) // Bigfile or xml pack access requested ? string::size_type pos; - if (!CFile::fileExists(path) && (pos = path.find('@')) != string::npos) + if ((pos = path.find('@')) != string::npos) { // check for a double @ to identify XML pack file if (pos+1 < path.size() && path[pos+1] == '@') From f065b7f7479aa2da1691a8290bfd0e9fd2d67c71 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 25 Apr 2019 08:38:23 +0300 Subject: [PATCH 209/303] Fixed: Opening local file with @ char in filename --HG-- branch : develop --- code/nel/src/misc/file.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/nel/src/misc/file.cpp b/code/nel/src/misc/file.cpp index 414a10e5a..7eae0f6a5 100644 --- a/code/nel/src/misc/file.cpp +++ b/code/nel/src/misc/file.cpp @@ -237,7 +237,9 @@ bool CIFile::open(const std::string &path, bool text) } } } - else + + // not in bnp, but may have '@' in the name + if (_F == NULL) { _IsInBigFile = false; _IsInXMLPackFile = false; From 82f084982a45947cd203b628833f0841ba930092 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 29 Apr 2019 14:10:19 +0300 Subject: [PATCH 210/303] Fixed: Reusing CIFile to load from bnp and from regular files. --HG-- branch : develop --- code/nel/src/misc/file.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/nel/src/misc/file.cpp b/code/nel/src/misc/file.cpp index 7eae0f6a5..63b27e768 100644 --- a/code/nel/src/misc/file.cpp +++ b/code/nel/src/misc/file.cpp @@ -157,6 +157,14 @@ bool CIFile::open(const std::string &path, bool text) close(); + if ((_IsInBigFile || _IsInXMLPackFile) && path.find('@') == string::npos) + { + // CIFile can be reused to load file from bnp and from regular files. + // Last open happened to be inside bnp and close() may not set _F to NULL. + // Opening regular file will fail as _F points to bnp file. + _F = NULL; + } + // can't open empty filename if(path.empty ()) return false; From 7f41881be7b05bddc2a050c860fd845c3831de9e Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 29 Apr 2019 15:03:32 +0300 Subject: [PATCH 211/303] Changed: Split http parsing from CGroupHTML --HG-- branch : develop --- code/nel/include/nel/gui/group_html.h | 8 ++- code/nel/include/nel/gui/html_parser.h | 52 +++++++++++++++++++ code/nel/src/gui/group_html.cpp | 26 ++++++++++ ...{group_html_parser.cpp => html_parser.cpp} | 37 +++++-------- 4 files changed, 94 insertions(+), 29 deletions(-) create mode 100644 code/nel/include/nel/gui/html_parser.h rename code/nel/src/gui/{group_html_parser.cpp => html_parser.cpp} (89%) diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index 55daa3c52..b21841f8c 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -151,7 +151,7 @@ namespace NLGUI virtual void browse (const char *url); // parse html string using libxml2 parser - virtual bool parseHtml(std::string htmlString); + bool parseHtml(const std::string &htmlString); // Refresh void refresh(); @@ -346,10 +346,6 @@ namespace NLGUI // the current request is terminated virtual void requestTerminated(); - // libxml2 html parser functions - void htmlElement(xmlNode *node, int element_number); - void htmlWalkDOM(xmlNode *a_node); - // Get Home URL virtual std::string home(); @@ -815,6 +811,8 @@ namespace NLGUI void buildHTTPPostParams (SFormFields &formfields); private: + friend class CHtmlParser; + // decode all HTML entities static ucstring decodeHTMLEntities(const ucstring &str); diff --git a/code/nel/include/nel/gui/html_parser.h b/code/nel/include/nel/gui/html_parser.h new file mode 100644 index 000000000..132c4ac88 --- /dev/null +++ b/code/nel/include/nel/gui/html_parser.h @@ -0,0 +1,52 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CL_HTML_PARSER_H +#define CL_HTML_PARSER_H + +#include "nel/misc/types_nl.h" + +namespace NLGUI +{ + class CGroupHTML; + + /** + * \brief HTML parsing + * \date 2019-03-15 10:50 GMT + * \author Meelis Mägi (Nimetu) + */ + class CHtmlParser + { + public: + CHtmlParser(CGroupHTML *group) : _GroupHtml(group) + {} + + bool parseHtml(std::string htmlString); + + private: + // libxml2 html parser functions + void htmlElement(xmlNode *node, int element_number); + void parseNode(xmlNode *a_node); + + private: + + CGroupHTML *_GroupHtml; + }; + +} + +#endif + diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 0bdebf865..36d0eab7f 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -48,6 +48,7 @@ #include "nel/gui/http_cache.h" #include "nel/gui/http_hsts.h" #include "nel/gui/curl_certificates.h" +#include "nel/gui/html_parser.h" #include @@ -6049,6 +6050,19 @@ namespace NLGUI return true; } + // *************************************************************************** + int CGroupHTML::luaParseHtml(CLuaState &ls) + { + const char *funcName = "parseHtml"; + CLuaIHM::checkArgCount(ls, funcName, 1); + CLuaIHM::checkArgType(ls, funcName, 1, LUA_TSTRING); + std::string html = ls.toString(1); + + parseHtml(html); + + return 0; + } + int CGroupHTML::luaClearRefresh(CLuaState &ls) { const char *funcName = "clearRefresh"; @@ -6284,6 +6298,18 @@ namespace NLGUI browse(url.c_str()); } + // *************************************************************************** + bool CGroupHTML::parseHtml(const std::string &htmlString) + { + CHtmlParser html(this); + + bool result = html.parseHtml(htmlString); + if (result) + _DocumentHtml = htmlString; + + return result; + } + // *************************************************************************** inline bool isDigit(ucchar c, uint base = 16) { diff --git a/code/nel/src/gui/group_html_parser.cpp b/code/nel/src/gui/html_parser.cpp similarity index 89% rename from code/nel/src/gui/group_html_parser.cpp rename to code/nel/src/gui/html_parser.cpp index 0069fd77d..8470d0524 100644 --- a/code/nel/src/gui/group_html_parser.cpp +++ b/code/nel/src/gui/html_parser.cpp @@ -17,13 +17,14 @@ #include "stdpch.h" +#include "nel/gui/html_parser.h" + #include #include #include "nel/misc/types_nl.h" #include "nel/gui/libwww.h" #include "nel/gui/group_html.h" -#include "nel/gui/lua_ihm.h" using namespace std; using namespace NLMISC; @@ -35,7 +36,7 @@ using namespace NLMISC; namespace NLGUI { // *************************************************************************** - void CGroupHTML::htmlElement(xmlNode *node, int element_number) + void CHtmlParser::htmlElement(xmlNode *node, int element_number) { SGML_dtd *HTML_DTD = HTML_dtd (); @@ -65,30 +66,30 @@ namespace NLGUI } } - beginElement(element_number, present, value); + _GroupHtml->beginElement(element_number, present, value); } else { - beginUnparsedElement((const char *)(node->name), xmlStrlen(node->name)); + _GroupHtml->beginUnparsedElement((const char *)(node->name), xmlStrlen(node->name)); } // recursive - text content / child nodes - htmlWalkDOM(node->children); + parseNode(node->children); // closing tag if (element_number < HTML_ELEMENTS) { - endElement(element_number); + _GroupHtml->endElement(element_number); } else { - endUnparsedElement((const char *)(node->name), xmlStrlen(node->name)); + _GroupHtml->endUnparsedElement((const char *)(node->name), xmlStrlen(node->name)); } } // *************************************************************************** // recursive function to walk html document - void CGroupHTML::htmlWalkDOM(xmlNode *a_node) + void CHtmlParser::parseNode(xmlNode *a_node) { SGML_dtd *HTML_DTD = HTML_dtd (); @@ -98,7 +99,7 @@ namespace NLGUI { if (node->type == XML_TEXT_NODE) { - addText((const char *)(node->content), xmlStrlen(node->content)); + _GroupHtml->addText((const char *)(node->content), xmlStrlen(node->content)); } else if (node->type == XML_ELEMENT_NODE) @@ -297,7 +298,7 @@ namespace NLGUI } // *************************************************************************** - bool CGroupHTML::parseHtml(std::string htmlString) + bool CHtmlParser::parseHtml(std::string htmlString) { htmlParserCtxtPtr parser = htmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL, XML_CHAR_ENCODING_UTF8); if (!parser) @@ -320,7 +321,7 @@ namespace NLGUI xmlNode *root = xmlDocGetRootElement(parser->myDoc); if (root) { - htmlWalkDOM(root); + parseNode(root); } else { @@ -339,18 +340,6 @@ namespace NLGUI return success; } - // *************************************************************************** - int CGroupHTML::luaParseHtml(CLuaState &ls) - { - const char *funcName = "parseHtml"; - CLuaIHM::checkArgCount(ls, funcName, 1); - CLuaIHM::checkArgType(ls, funcName, 1, LUA_TSTRING); - std::string html = ls.toString(1); - - parseHtml(html); - - return 0; - } - } + From c107bdc56f7e88aaf2ee310de29e07ea3008668f Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 29 Mar 2019 15:03:39 +0200 Subject: [PATCH 212/303] Changed: Split css style from CGroupHTML --HG-- branch : develop --- code/nel/include/nel/gui/css_parser.h | 39 + code/nel/include/nel/gui/css_style.h | 141 +++ code/nel/include/nel/gui/group_html.h | 96 +- code/nel/include/nel/gui/libwww.h | 7 +- code/nel/src/gui/css_parser.cpp | 58 ++ code/nel/src/gui/css_style.cpp | 496 ++++++++++ code/nel/src/gui/group_html.cpp | 1258 +++++-------------------- code/nel/src/gui/libwww.cpp | 362 +++++++ 8 files changed, 1342 insertions(+), 1115 deletions(-) create mode 100644 code/nel/include/nel/gui/css_parser.h create mode 100644 code/nel/include/nel/gui/css_style.h create mode 100644 code/nel/src/gui/css_parser.cpp create mode 100644 code/nel/src/gui/css_style.cpp diff --git a/code/nel/include/nel/gui/css_parser.h b/code/nel/include/nel/gui/css_parser.h new file mode 100644 index 000000000..cb4cea62e --- /dev/null +++ b/code/nel/include/nel/gui/css_parser.h @@ -0,0 +1,39 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CL_CSS_PARSER_H +#define CL_CSS_PARSER_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/css_style.h" + +namespace NLGUI +{ + /** + * \brief CSS style parsing + * \date 2019-03-15 10:50 GMT + * \author Meelis Mägi (Nimetu) + */ + class CCssParser { + public: + // parse style declaration, eg "color: red; font-size: 10px;" + static TStyle parseDecls(const std::string &styleString); + }; + +}//namespace + +#endif // CL_CSS_PARSER_H + diff --git a/code/nel/include/nel/gui/css_style.h b/code/nel/include/nel/gui/css_style.h new file mode 100644 index 000000000..2a854a6d9 --- /dev/null +++ b/code/nel/include/nel/gui/css_style.h @@ -0,0 +1,141 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CL_CSS_STYLE_H +#define CL_CSS_STYLE_H + +#include "nel/misc/types_nl.h" +#include "nel/misc/rgba.h" + +namespace NLGUI +{ + typedef std::map TStyle; + + /** + * \brief CSS style rules + * \date 2019-03-15 10:50 GMT + * \author Meelis Mägi (Nimetu) + */ + class CStyleParams + { + public: + struct STextShadow + { + public: + STextShadow(bool enabled = false, bool outline = false, sint32 x=1, sint32 y=1, NLMISC::CRGBA color=NLMISC::CRGBA::Black) + : Enabled(enabled), Outline(outline), X(x), Y(y), Color(color) + { } + + bool Enabled; + bool Outline; + sint32 X; + sint32 Y; + NLMISC::CRGBA Color; + }; + public: + CStyleParams () : FontFamily(""), TextColor(255,255,255,255), TextShadow() + { + FontSize=10; + FontWeight=400; + FontOblique=false; + Underlined=false; + StrikeThrough=false; + GlobalColor=false; + Width=-1; + Height=-1; + MaxWidth=-1; + MaxHeight=-1; + BorderWidth=1; + BackgroundColor=NLMISC::CRGBA::Black; + BackgroundColorOver=NLMISC::CRGBA::Black; + } + uint FontSize; + uint FontWeight; + bool FontOblique; + std::string FontFamily; + NLMISC::CRGBA TextColor; + STextShadow TextShadow; + bool GlobalColor; + bool Underlined; + bool StrikeThrough; + sint32 Width; + sint32 Height; + sint32 MaxWidth; + sint32 MaxHeight; + sint32 BorderWidth; + NLMISC::CRGBA BackgroundColor; + NLMISC::CRGBA BackgroundColorOver; + }; + + class CCssStyle { + public: + + + // 'browser' style, overwriten with '' + CStyleParams Root; + + // current element style + CStyleParams Current; + + private: + std::vector _StyleStack; + + // test if str is one of "thin/medium/thick" and return its pixel value + bool scanCssLength(const std::string& str, uint32 &px) const; + + // read style attribute + void getStyleParams(const std::string &styleString, CStyleParams &style, const CStyleParams ¤t) const; + + public: + void reset(); + + inline uint getFontSizeSmaller() const + { + if (Current.FontSize < 5) + return 3; + return Current.FontSize-2; + } + + inline void pushStyle() + { + _StyleStack.push_back(Current); + } + + inline void popStyle() + { + if (_StyleStack.empty()) + Current = Root; + else + { + Current = _StyleStack.back(); + _StyleStack.pop_back(); + } + } + + // apply style string to this.Root + void applyRootStyle(const std::string &styleString); + + // apply style string to this.Current + void applyStyle(const std::string &styleString); + + void applyCssMinMax(sint32 &width, sint32 &height, sint32 minw=0, sint32 minh=0, sint32 maxw=0, sint32 maxh=0) const; + + }; + +}//namespace + +#endif // CL_CSS_STYLE_H + diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index b21841f8c..d8935f431 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -24,12 +24,11 @@ #include "nel/gui/ctrl_button.h" #include "nel/gui/group_table.h" #include "nel/gui/libwww_types.h" +#include "nel/gui/css_style.h" // forward declaration typedef void CURLM; -typedef std::map TStyle; - namespace NLGUI { class CCtrlButton; @@ -76,58 +75,6 @@ namespace NLGUI static SWebOptions options; - // text-shadow - struct STextShadow - { - public: - STextShadow(bool enabled = false, bool outline = false, sint32 x=1, sint32 y=1, NLMISC::CRGBA color=NLMISC::CRGBA::Black) - : Enabled(enabled), Outline(outline), X(x), Y(y), Color(color) - { } - - bool Enabled; - bool Outline; - sint32 X; - sint32 Y; - NLMISC::CRGBA Color; - }; - - class CStyleParams - { - public: - CStyleParams () : FontFamily(""), TextColor(255,255,255,255), TextShadow() - { - FontSize=10; - FontWeight=400; - FontOblique=false; - Underlined=false; - StrikeThrough=false; - GlobalColor=false; - Width=-1; - Height=-1; - MaxWidth=-1; - MaxHeight=-1; - BorderWidth=1; - BackgroundColor=NLMISC::CRGBA::Black; - BackgroundColorOver=NLMISC::CRGBA::Black; - } - uint FontSize; - uint FontWeight; - bool FontOblique; - std::string FontFamily; - NLMISC::CRGBA TextColor; - STextShadow TextShadow; - bool GlobalColor; - bool Underlined; - bool StrikeThrough; - sint32 Width; - sint32 Height; - sint32 MaxWidth; - sint32 MaxHeight; - sint32 BorderWidth; - NLMISC::CRGBA BackgroundColor; - NLMISC::CRGBA BackgroundColorOver; - }; - // ImageDownload system enum TDataType {ImgType= 0, BnpType}; enum TImageType {NormalImage=0, OverImage}; @@ -535,33 +482,8 @@ namespace NLGUI // IL mode bool _LI; - // Current active style - CStyleParams _Style; - // Default style - CStyleParams _StyleDefault; - // Nested style stack - std::vector _StyleParams; - inline void pushStyle() - { - _StyleParams.push_back(_Style); - } - inline void popStyle() - { - if (_StyleParams.empty()) - _Style = _StyleDefault; - else - { - _Style = _StyleParams.back(); - _StyleParams.pop_back(); - } - } - - inline uint getFontSizeSmaller() const - { - if (_Style.FontSize < 5) - return 3; - return _Style.FontSize-2; - } + // Keep track of current element style + CCssStyle _Style; // Current link std::vector _Link; @@ -625,14 +547,6 @@ namespace NLGUI return _TR.back(); } - std::vector _TextShadow; - inline STextShadow getTextShadow() const - { - if (_TextShadow.empty()) - return STextShadow(); - return _TextShadow.back(); - } - // Forms class CForm { @@ -794,10 +708,6 @@ namespace NLGUI typedef std::map > TGroupHtmlByUIDMap; static TGroupHtmlByUIDMap _GroupHtmlByUID; - // read style attribute - void getStyleParams(const std::string &styleString, CStyleParams &style, const CStyleParams ¤t); - void applyCssMinMax(sint32 &width, sint32 &height, sint32 minw=0, sint32 minh=0, sint32 maxw=0, sint32 maxh=0); - // load and render local html file (from bnp for example) void doBrowseLocalFile(const std::string &filename); diff --git a/code/nel/include/nel/gui/libwww.h b/code/nel/include/nel/gui/libwww.h index 84eeb01e9..d7fe1251c 100644 --- a/code/nel/include/nel/gui/libwww.h +++ b/code/nel/include/nel/gui/libwww.h @@ -276,9 +276,14 @@ namespace NLGUI HTML_ATTR(H6,STYLE), }; - #undef HTML_ATTR + // *************************************************************************** + // Read HTML color value from src and set dest + // Can handle #rgb(a), #rrggbb(aa) or rgb()/rgba(), hsl(), hsla() formats + // or color name directly + bool scanHTMLColor(const char *src, NLMISC::CRGBA &dest); + // *************************************************************************** // Read a CSS length value, return true if one of supported units '%, rem, em, px, pt' // On failure: 'value' and 'unit' values are undefined diff --git a/code/nel/src/gui/css_parser.cpp b/code/nel/src/gui/css_parser.cpp new file mode 100644 index 000000000..c45121824 --- /dev/null +++ b/code/nel/src/gui/css_parser.cpp @@ -0,0 +1,58 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdpch.h" + +#include +#include "nel/misc/types_nl.h" +#include "nel/gui/css_parser.h" +#include "nel/gui/css_style.h" + +using namespace NLMISC; + +#ifdef DEBUG_NEW +#define new DEBUG_NEW +#endif + +namespace NLGUI +{ + // *************************************************************************** + // Parse style declarations style, eg. "color:red; font-size: 10px;" + // + // key is converted to lowercase + // value is left as is + TStyle CCssParser::parseDecls(const std::string &styleString) + { + TStyle styles; + std::vector elements; + NLMISC::splitString(styleString, ";", elements); + + for(uint i = 0; i < elements.size(); ++i) + { + std::string::size_type pos; + pos = elements[i].find_first_of(':'); + if (pos != std::string::npos) + { + std::string key = trim(toLower(elements[i].substr(0, pos))); + std::string value = trim(elements[i].substr(pos+1)); + styles[key] = value; + } + } + + return styles; + } +} // namespace + diff --git a/code/nel/src/gui/css_style.cpp b/code/nel/src/gui/css_style.cpp new file mode 100644 index 000000000..9d4b665bb --- /dev/null +++ b/code/nel/src/gui/css_style.cpp @@ -0,0 +1,496 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdpch.h" + +#include +#include "nel/misc/types_nl.h" +#include "nel/gui/css_style.h" +#include "nel/gui/css_parser.h" +#include "nel/gui/libwww.h" + +using namespace NLMISC; + +#ifdef DEBUG_NEW +#define new DEBUG_NEW +#endif + +namespace NLGUI +{ + // *************************************************************************** + void CCssStyle::reset() + { + _StyleStack.clear(); + + Root = CStyleParams(); + Current = CStyleParams(); + } + + // *************************************************************************** + void CCssStyle::applyRootStyle(const std::string &styleString) + { + getStyleParams(styleString, Root, Root); + } + + // *************************************************************************** + void CCssStyle::applyStyle(const std::string &styleString) + { + if (_StyleStack.empty()) + { + getStyleParams(styleString, Current, Root); + } + else + { + getStyleParams(styleString, Current, _StyleStack.back()); + } + } + + bool CCssStyle::scanCssLength(const std::string& str, uint32 &px) const + { + if (fromString(str, px)) + return true; + + if (str == "thin") + { + px = 1; + return true; + } + if (str == "medium") + { + px = 3; + return true; + } + if (str == "thick") + { + px = 5; + return true; + } + + return false; + } + + // *************************************************************************** + // CStyleParams style; + // style.FontSize; // font-size: 10px; + // style.TextColor; // color: #ABCDEF; + // style.Underlined; // text-decoration: underline; text-decoration-line: underline; + // style.StrikeThrough; // text-decoration: line-through; text-decoration-line: line-through; + void CCssStyle::getStyleParams(const std::string &styleString, CStyleParams &style, const CStyleParams ¤t) const + { + float tmpf; + TStyle styles = CCssParser::parseDecls(styleString); + TStyle::iterator it; + + // first pass: get font-size for 'em' sizes + for (it=styles.begin(); it != styles.end(); ++it) + { + if (it->first == "font") + { + if (it->second == "inherit") + { + style.FontSize = current.FontSize; + style.FontFamily = current.FontFamily; + style.FontWeight = current.FontWeight; + style.FontOblique = current.FontOblique; + } + } + else + if (it->first == "font-size") + { + if (it->second == "inherit") + { + style.FontSize = current.FontSize; + } + else + { + std::string unit; + if (getCssLength(tmpf, unit, it->second.c_str())) + { + if (unit == "rem") + style.FontSize = Root.FontSize * tmpf; + else if (unit == "em") + style.FontSize = current.FontSize * tmpf; + else if (unit == "pt") + style.FontSize = tmpf / 0.75f; + else if (unit == "%") + style.FontSize = current.FontSize * tmpf / 100.f; + else + style.FontSize = tmpf; + } + } + } + } + + // second pass: rest of style + for (it=styles.begin(); it != styles.end(); ++it) + { + if (it->first == "border") + { + sint32 b; + if (it->second == "none") + style.BorderWidth = 0; + else + if (fromString(it->second, b)) + style.BorderWidth = b; + } + else + if (it->first == "font-style") + { + if (it->second == "inherit") + style.FontOblique = current.FontOblique; + else + if (it->second == "italic" || it->second == "oblique") + style.FontOblique = true; + } + else + if (it->first == "font-family") + { + if (it->second == "inherit") + style.FontFamily = current.FontFamily; + else + style.FontFamily = it->second; + } + else + if (it->first == "font-weight") + { + // https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight + uint weight = 400; + if (it->second == "inherit") + weight = current.FontWeight; + else + if (it->second == "normal") + weight = 400; + else + if (it->second == "bold") + weight = 700; + else + if (it->second == "lighter") + { + const uint lighter[] = {100, 100, 100, 100, 100, 400, 400, 700, 700}; + uint index = current.FontWeight / 100 - 1; + clamp(index, 1u, 9u); + weight = lighter[index-1]; + } + else + if (it->second == "bolder") + { + const uint bolder[] = {400, 400, 400, 700, 700, 900, 900, 900, 900}; + uint index = current.FontWeight / 100 + 1; + clamp(index, 1u, 9u); + weight = bolder[index-1]; + } + else + if (fromString(it->second, weight)) + { + weight = (weight / 100); + clamp(weight, 1u, 9u); + weight *= 100; + } + style.FontWeight = weight; + } + else + if (it->first == "color") + if (it->second == "inherit") + style.TextColor = current.TextColor; + else + scanHTMLColor(it->second.c_str(), style.TextColor); + else + if (it->first == "text-decoration" || it->first == "text-decoration-line") + { + std::string prop(toLower(it->second)); + style.Underlined = (prop.find("underline") != std::string::npos); + style.StrikeThrough = (prop.find("line-through") != std::string::npos); + } + else + if (it->first == "text-stroke" || it->first == "-webkit-text-stroke") + { + // text-stroke: length || color + bool success = false; + uint px = 0; + CRGBA color; + std::vector parts; + NLMISC::splitString(it->second, " ", parts); + if (parts.size() == 1) + { + success = scanCssLength(parts[0], px); + if (!success) + success = scanHTMLColor(parts[0].c_str(), color); + } + else if (parts.size() == 2) + { + success = scanCssLength(parts[0], px); + if (success) + success = scanHTMLColor(parts[1].c_str(), color); + else + { + success = scanHTMLColor(parts[0].c_str(), color); + success = success && scanCssLength(parts[1], px); + } + } + + // do not disable shadow if one is already set + if (success) + { + style.TextShadow.Enabled = (px > 0); + style.TextShadow.Color = color; + style.TextShadow.X = px; + style.TextShadow.Y = px; + style.TextShadow.Outline = true; + } + } + else + if (it->first == "text-shadow") + { + if (it->second == "none") + style.TextShadow = CStyleParams::STextShadow(false); + else + if (it->second == "inherit") + style.TextShadow = current.TextShadow; + else + { + // text-shadow: offset-x offset-y | blur | #color + // text-shadow: #color | offset-x offset-y + bool success = true; + std::string prop(it->second); + size_t pos; + pos = prop.find_first_of(",\n\r"); + if (pos != std::string::npos) + prop = prop.substr(0, pos); + + std::vector parts; + NLMISC::splitString(prop, " ", parts); + switch(parts.size()) + { + case 1: + { + success = scanHTMLColor(it->second.c_str(), style.TextShadow.Color); + break; + } + // no case 2: + case 3: + { + if (!fromString(parts[0], style.TextShadow.X)) + { + success = scanHTMLColor(parts[0].c_str(), style.TextShadow.Color); + success = success && fromString(parts[1], style.TextShadow.X); + success = success && fromString(parts[2], style.TextShadow.Y); + } + else + { + success = fromString(parts[1], style.TextShadow.Y); + success = success && scanHTMLColor(parts[2].c_str(), style.TextShadow.Color); + } + break; + } + case 4: + { + if (!fromString(parts[0], style.TextShadow.X)) + { + success = scanHTMLColor(parts[0].c_str(), style.TextShadow.Color); + success = success && fromString(parts[1], style.TextShadow.X); + success = success && fromString(parts[2], style.TextShadow.Y); + // ignore blur [3] + } + else + { + success = fromString(parts[0], style.TextShadow.X); + success = success && fromString(parts[1], style.TextShadow.Y); + // ignore blur [2] + success = success && scanHTMLColor(parts[3].c_str(), style.TextShadow.Color); + } + break; + } + default: + { + // unsupported rule + break; + } + } + + style.TextShadow.Enabled = success; + } + } + else + if (it->first == "width") + { + std::string unit; + if (getCssLength(tmpf, unit, it->second.c_str())) + { + if (unit == "rem") + style.Width = tmpf * Root.FontSize; + else if (unit == "em") + style.Width = tmpf * style.FontSize; + else if (unit == "pt") + style.FontSize = tmpf / 0.75f; + else + style.Width = tmpf; + } + } + else + if (it->first == "height") + { + std::string unit; + if (getCssLength(tmpf, unit, it->second.c_str())) + { + if (unit == "rem") + style.Height = tmpf * Root.FontSize; + else if (unit == "em") + style.Height = tmpf * style.FontSize; + else if (unit == "pt") + style.FontSize = tmpf / 0.75f; + else + style.Height = tmpf; + } + } + else + if (it->first == "max-width") + { + std::string unit; + if (getCssLength(tmpf, unit, it->second.c_str())) + { + if (unit == "rem") + style.MaxWidth = tmpf * Root.FontSize; + else if (unit == "em") + style.MaxWidth = tmpf * style.FontSize; + else if (unit == "pt") + style.FontSize = tmpf / 0.75f; + else + style.MaxWidth = tmpf; + } + } + else + if (it->first == "max-height") + { + std::string unit; + if (getCssLength(tmpf, unit, it->second.c_str())) + { + if (unit == "rem") + style.MaxHeight = tmpf * Root.FontSize; + else if (unit == "em") + style.MaxHeight = tmpf * style.FontSize; + else if (unit == "pt") + style.FontSize = tmpf / 0.75f; + else + style.MaxHeight = tmpf; + } + } + else + if (it->first == "-ryzom-modulate-color") + { + bool b; + if (it->second == "inherit") + style.GlobalColor = current.GlobalColor; + else + if (fromString(it->second, b)) + style.GlobalColor = b; + } + else + if (it->first == "background-color") + { + if (it->second == "inherit") + style.BackgroundColor = current.BackgroundColor; + else + scanHTMLColor(it->second.c_str(), style.BackgroundColor); + } + else + if (it->first == "-ryzom-background-color-over") + { + if (it->second == "inherit") + style.BackgroundColorOver = current.BackgroundColorOver; + else + scanHTMLColor(it->second.c_str(), style.BackgroundColorOver); + } + } + + // if outer element has underline set, then inner element cannot remove it + if (current.Underlined) + style.Underlined = current.Underlined; + + // if outer element has line-through set, then inner element cannot remove it + if (current.StrikeThrough) + style.StrikeThrough = current.StrikeThrough; + } + + // *************************************************************************** + void CCssStyle::applyCssMinMax(sint32 &width, sint32 &height, sint32 minw, sint32 minh, sint32 maxw, sint32 maxh) const + { + if (maxw <= 0) maxw = width; + if (maxh <= 0) maxh = height; + + maxw = std::max(minw, maxw); + maxh = std::max(minh, maxh); + + float ratio = (float) width / std::max(1, height); + if (width > maxw) + { + width = maxw; + height = std::max((sint32)(maxw /ratio), minh); + } + if (width < minw) + { + width = minw; + height = std::min((sint32)(minw / ratio), maxh); + } + if (height > maxh) + { + width = std::max((sint32)(maxh * ratio), minw); + height = maxh; + } + if (height < minh) + { + width = std::min((sint32)(minh * ratio), maxw); + height = minh; + } + if (width > maxw && height > maxh) + { + if (maxw/width <= maxh/height) + { + width = maxw; + height = std::max(minh, (sint32)(maxw / ratio)); + } + else + { + width = std::max(minw, (sint32)(maxh * ratio)); + height = maxh; + } + } + if (width < minw && height < minh) + { + if (minw / width <= minh / height) + { + width = std::min(maxw, (sint32)(minh * ratio)); + height = minh; + } + else + { + width = minw; + height = std::min(maxh, (sint32)(minw / ratio)); + } + } + if (width < minw && height > maxh) + { + width = minw; + height = maxh; + } + if (width > maxw && height < minh) + { + width = maxw; + height = minh; + } + } + +} // namespace + diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 36d0eab7f..ba21c6af1 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -357,7 +357,7 @@ namespace NLGUI // apply max-width, max-height rules if asked if (maxw > -1 || maxh > -1) { - applyCssMinMax(width, height, 0, 0, maxw, maxh); + _Style.applyCssMinMax(width, height, 0, 0, maxw, maxh); changed = true; } @@ -386,29 +386,33 @@ namespace NLGUI void CGroupHTML::setTextButtonStyle(CCtrlTextButton *ctrlButton, const CStyleParams &style) { // this will also set size for treating it like "display: inline-block;" - if (style.Width > 0) ctrlButton->setWMin(_Style.Width); - if (style.Height > 0) ctrlButton->setHMin(_Style.Height); + if (style.Width > 0) ctrlButton->setWMin(style.Width); + if (style.Height > 0) ctrlButton->setHMin(style.Height); CViewText *pVT = ctrlButton->getViewText(); if (pVT) { - setTextStyle(pVT, _Style); + setTextStyle(pVT, style); } - if (_Style.BackgroundColor.A > 0) + if (style.BackgroundColor.A > 0) { - if (_Style.BackgroundColorOver.A == 0) - _Style.BackgroundColorOver = _Style.BackgroundColor; - - ctrlButton->setColor(_Style.BackgroundColor); - ctrlButton->setColorOver(_Style.BackgroundColorOver); + ctrlButton->setColor(style.BackgroundColor); + if (style.BackgroundColorOver.A == 0) + { + ctrlButton->setColorOver(style.BackgroundColor); + } + else + { + ctrlButton->setColorOver(style.BackgroundColorOver); + } ctrlButton->setTexture("", "blank.tga", "", false); ctrlButton->setTextureOver("", "blank.tga", ""); ctrlButton->setProperty("force_text_over", "true"); } - else if (_Style.BackgroundColorOver.A > 0) + else if (style.BackgroundColorOver.A > 0) { - ctrlButton->setColorOver(_Style.BackgroundColorOver); + ctrlButton->setColorOver(style.BackgroundColorOver); ctrlButton->setProperty("force_text_over", "true"); ctrlButton->setTextureOver("blank.tga", "blank.tga", "blank.tga"); } @@ -1027,7 +1031,7 @@ namespace NLGUI TStyle CGroupHTML::parseStyle (const string &str_styles) { - TStyle styles; + TStyle styles; vector elements; NLMISC::splitString(str_styles, ";", elements); @@ -1149,392 +1153,6 @@ namespace NLGUI _CellParams.push_back (cellParams); \ } - static bool scanCssLength(const std::string& str, uint32 &px) - { - if (fromString(str, px)) - return true; - - if (str == "thin") - { - px = 1; - return true; - } - if (str == "medium") - { - px = 3; - return true; - } - if (str == "thick") - { - px = 5; - return true; - } - - return false; - } - - static bool isHexa(char c) - { - return isdigit(c) || (tolower(c) >= 'a' && tolower(c) <= 'f'); - } - - static uint8 convertHexa(char c) - { - return (uint8) (tolower(c) - (isdigit(c) ? '0' : ('a' - 10))); - } - - // scan a color component, and return pointer to next position - static const char *scanColorComponent(const char *src, uint8 &intensity) - { - if (!src) return NULL; - if (!isHexa(*src)) return NULL; - uint8 value = convertHexa(*src++) << 4; - if (!isHexa(*src)) return NULL; - value += convertHexa(*src++); - intensity = value; - return src; - } - - static float hueToRgb(float m1, float m2, float h) - { - if (h < 0) h += 1.0f; - if (h > 1) h -= 1.0f; - if (h*6 < 1.0f) return m1 + (m2 - m1)*h*6; - if (h*2 < 1.0f) return m2; - if (h*3 < 2.0f) return m1 + (m2 - m1) * (2.0f/3.0f - h)*6; - return m1; - } - - static void hslToRgb(float h, float s, float l, CRGBA &result) - { - float m1, m2; - if (l <= 0.5f) - m2 = l * (s + 1.0f); - else - m2 = l + s - l * s; - m1 = l*2 - m2; - - result.R = 255 * hueToRgb(m1, m2, h + 1.0f/3.0f); - result.G = 255 * hueToRgb(m1, m2, h); - result.B = 255 * hueToRgb(m1, m2, h - 1.0f/3.0f); - result.A = 255; - } - - class CNameToCol - { - public: - const char *Name; - CRGBA Color; - CNameToCol(const char *name, CRGBA color) : Name(name), Color(color) {} - }; - - static CNameToCol htmlColorNameToRGBA[] = - { - CNameToCol("AliceBlue", CRGBA(0xF0, 0xF8, 0xFF)), - CNameToCol("AntiqueWhite", CRGBA(0xFA, 0xEB, 0xD7)), - CNameToCol("Aqua", CRGBA(0x00, 0xFF, 0xFF)), - CNameToCol("Aquamarine", CRGBA(0x7F, 0xFF, 0xD4)), - CNameToCol("Azure", CRGBA(0xF0, 0xFF, 0xFF)), - CNameToCol("Beige", CRGBA(0xF5, 0xF5, 0xDC)), - CNameToCol("Bisque", CRGBA(0xFF, 0xE4, 0xC4)), - CNameToCol("Black", CRGBA(0x00, 0x00, 0x00)), - CNameToCol("BlanchedAlmond", CRGBA(0xFF, 0xEB, 0xCD)), - CNameToCol("Blue", CRGBA(0x00, 0x00, 0xFF)), - CNameToCol("BlueViolet", CRGBA(0x8A, 0x2B, 0xE2)), - CNameToCol("Brown", CRGBA(0xA5, 0x2A, 0x2A)), - CNameToCol("BurlyWood", CRGBA(0xDE, 0xB8, 0x87)), - CNameToCol("CadetBlue", CRGBA(0x5F, 0x9E, 0xA0)), - CNameToCol("Chartreuse", CRGBA(0x7F, 0xFF, 0x00)), - CNameToCol("Chocolate", CRGBA(0xD2, 0x69, 0x1E)), - CNameToCol("Coral", CRGBA(0xFF, 0x7F, 0x50)), - CNameToCol("CornflowerBlue", CRGBA(0x64, 0x95, 0xED)), - CNameToCol("Cornsilk", CRGBA(0xFF, 0xF8, 0xDC)), - CNameToCol("Crimson", CRGBA(0xDC, 0x14, 0x3C)), - CNameToCol("Cyan", CRGBA(0x00, 0xFF, 0xFF)), - CNameToCol("DarkBlue", CRGBA(0x00, 0x00, 0x8B)), - CNameToCol("DarkCyan", CRGBA(0x00, 0x8B, 0x8B)), - CNameToCol("DarkGoldenRod", CRGBA(0xB8, 0x86, 0x0B)), - CNameToCol("DarkGray", CRGBA(0xA9, 0xA9, 0xA9)), - CNameToCol("DarkGreen", CRGBA(0x00, 0x64, 0x00)), - CNameToCol("DarkKhaki", CRGBA(0xBD, 0xB7, 0x6B)), - CNameToCol("DarkMagenta", CRGBA(0x8B, 0x00, 0x8B)), - CNameToCol("DarkOliveGreen", CRGBA(0x55, 0x6B, 0x2F)), - CNameToCol("Darkorange", CRGBA(0xFF, 0x8C, 0x00)), - CNameToCol("DarkOrchid", CRGBA(0x99, 0x32, 0xCC)), - CNameToCol("DarkRed", CRGBA(0x8B, 0x00, 0x00)), - CNameToCol("DarkSalmon", CRGBA(0xE9, 0x96, 0x7A)), - CNameToCol("DarkSeaGreen", CRGBA(0x8F, 0xBC, 0x8F)), - CNameToCol("DarkSlateBlue", CRGBA(0x48, 0x3D, 0x8B)), - CNameToCol("DarkSlateGray", CRGBA(0x2F, 0x4F, 0x4F)), - CNameToCol("DarkTurquoise", CRGBA(0x00, 0xCE, 0xD1)), - CNameToCol("DarkViolet", CRGBA(0x94, 0x00, 0xD3)), - CNameToCol("DeepPink", CRGBA(0xFF, 0x14, 0x93)), - CNameToCol("DeepSkyBlue", CRGBA(0x00, 0xBF, 0xFF)), - CNameToCol("DimGray", CRGBA(0x69, 0x69, 0x69)), - CNameToCol("DodgerBlue", CRGBA(0x1E, 0x90, 0xFF)), - CNameToCol("Feldspar", CRGBA(0xD1, 0x92, 0x75)), - CNameToCol("FireBrick", CRGBA(0xB2, 0x22, 0x22)), - CNameToCol("FloralWhite", CRGBA(0xFF, 0xFA, 0xF0)), - CNameToCol("ForestGreen", CRGBA(0x22, 0x8B, 0x22)), - CNameToCol("Fuchsia", CRGBA(0xFF, 0x00, 0xFF)), - CNameToCol("Gainsboro", CRGBA(0xDC, 0xDC, 0xDC)), - CNameToCol("GhostWhite", CRGBA(0xF8, 0xF8, 0xFF)), - CNameToCol("Gold", CRGBA(0xFF, 0xD7, 0x00)), - CNameToCol("GoldenRod", CRGBA(0xDA, 0xA5, 0x20)), - CNameToCol("Gray", CRGBA(0x80, 0x80, 0x80)), - CNameToCol("Green", CRGBA(0x00, 0x80, 0x00)), - CNameToCol("GreenYellow", CRGBA(0xAD, 0xFF, 0x2F)), - CNameToCol("HoneyDew", CRGBA(0xF0, 0xFF, 0xF0)), - CNameToCol("HotPink", CRGBA(0xFF, 0x69, 0xB4)), - CNameToCol("IndianRed ", CRGBA(0xCD, 0x5C, 0x5C)), - CNameToCol("Indigo ", CRGBA(0x4B, 0x00, 0x82)), - CNameToCol("Ivory", CRGBA(0xFF, 0xFF, 0xF0)), - CNameToCol("Khaki", CRGBA(0xF0, 0xE6, 0x8C)), - CNameToCol("Lavender", CRGBA(0xE6, 0xE6, 0xFA)), - CNameToCol("LavenderBlush", CRGBA(0xFF, 0xF0, 0xF5)), - CNameToCol("LawnGreen", CRGBA(0x7C, 0xFC, 0x00)), - CNameToCol("LemonChiffon", CRGBA(0xFF, 0xFA, 0xCD)), - CNameToCol("LightBlue", CRGBA(0xAD, 0xD8, 0xE6)), - CNameToCol("LightCoral", CRGBA(0xF0, 0x80, 0x80)), - CNameToCol("LightCyan", CRGBA(0xE0, 0xFF, 0xFF)), - CNameToCol("LightGoldenRodYellow", CRGBA(0xFA, 0xFA, 0xD2)), - CNameToCol("LightGrey", CRGBA(0xD3, 0xD3, 0xD3)), - CNameToCol("LightGreen", CRGBA(0x90, 0xEE, 0x90)), - CNameToCol("LightPink", CRGBA(0xFF, 0xB6, 0xC1)), - CNameToCol("LightSalmon", CRGBA(0xFF, 0xA0, 0x7A)), - CNameToCol("LightSeaGreen", CRGBA(0x20, 0xB2, 0xAA)), - CNameToCol("LightSkyBlue", CRGBA(0x87, 0xCE, 0xFA)), - CNameToCol("LightSlateBlue", CRGBA(0x84, 0x70, 0xFF)), - CNameToCol("LightSlateGray", CRGBA(0x77, 0x88, 0x99)), - CNameToCol("LightSteelBlue", CRGBA(0xB0, 0xC4, 0xDE)), - CNameToCol("LightYellow", CRGBA(0xFF, 0xFF, 0xE0)), - CNameToCol("Lime", CRGBA(0x00, 0xFF, 0x00)), - CNameToCol("LimeGreen", CRGBA(0x32, 0xCD, 0x32)), - CNameToCol("Linen", CRGBA(0xFA, 0xF0, 0xE6)), - CNameToCol("Magenta", CRGBA(0xFF, 0x00, 0xFF)), - CNameToCol("Maroon", CRGBA(0x80, 0x00, 0x00)), - CNameToCol("MediumAquaMarine", CRGBA(0x66, 0xCD, 0xAA)), - CNameToCol("MediumBlue", CRGBA(0x00, 0x00, 0xCD)), - CNameToCol("MediumOrchid", CRGBA(0xBA, 0x55, 0xD3)), - CNameToCol("MediumPurple", CRGBA(0x93, 0x70, 0xD8)), - CNameToCol("MediumSeaGreen", CRGBA(0x3C, 0xB3, 0x71)), - CNameToCol("MediumSlateBlue", CRGBA(0x7B, 0x68, 0xEE)), - CNameToCol("MediumSpringGreen", CRGBA(0x00, 0xFA, 0x9A)), - CNameToCol("MediumTurquoise", CRGBA(0x48, 0xD1, 0xCC)), - CNameToCol("MediumVioletRed", CRGBA(0xC7, 0x15, 0x85)), - CNameToCol("MidnightBlue", CRGBA(0x19, 0x19, 0x70)), - CNameToCol("MintCream", CRGBA(0xF5, 0xFF, 0xFA)), - CNameToCol("MistyRose", CRGBA(0xFF, 0xE4, 0xE1)), - CNameToCol("Moccasin", CRGBA(0xFF, 0xE4, 0xB5)), - CNameToCol("NavajoWhite", CRGBA(0xFF, 0xDE, 0xAD)), - CNameToCol("Navy", CRGBA(0x00, 0x00, 0x80)), - CNameToCol("OldLace", CRGBA(0xFD, 0xF5, 0xE6)), - CNameToCol("Olive", CRGBA(0x80, 0x80, 0x00)), - CNameToCol("OliveDrab", CRGBA(0x6B, 0x8E, 0x23)), - CNameToCol("Orange", CRGBA(0xFF, 0xA5, 0x00)), - CNameToCol("OrangeRed", CRGBA(0xFF, 0x45, 0x00)), - CNameToCol("Orchid", CRGBA(0xDA, 0x70, 0xD6)), - CNameToCol("PaleGoldenRod", CRGBA(0xEE, 0xE8, 0xAA)), - CNameToCol("PaleGreen", CRGBA(0x98, 0xFB, 0x98)), - CNameToCol("PaleTurquoise", CRGBA(0xAF, 0xEE, 0xEE)), - CNameToCol("PaleVioletRed", CRGBA(0xD8, 0x70, 0x93)), - CNameToCol("PapayaWhip", CRGBA(0xFF, 0xEF, 0xD5)), - CNameToCol("PeachPuff", CRGBA(0xFF, 0xDA, 0xB9)), - CNameToCol("Peru", CRGBA(0xCD, 0x85, 0x3F)), - CNameToCol("Pink", CRGBA(0xFF, 0xC0, 0xCB)), - CNameToCol("Plum", CRGBA(0xDD, 0xA0, 0xDD)), - CNameToCol("PowderBlue", CRGBA(0xB0, 0xE0, 0xE6)), - CNameToCol("Purple", CRGBA(0x80, 0x00, 0x80)), - CNameToCol("Red", CRGBA(0xFF, 0x00, 0x00)), - CNameToCol("RosyBrown", CRGBA(0xBC, 0x8F, 0x8F)), - CNameToCol("RoyalBlue", CRGBA(0x41, 0x69, 0xE1)), - CNameToCol("SaddleBrown", CRGBA(0x8B, 0x45, 0x13)), - CNameToCol("Salmon", CRGBA(0xFA, 0x80, 0x72)), - CNameToCol("SandyBrown", CRGBA(0xF4, 0xA4, 0x60)), - CNameToCol("SeaGreen", CRGBA(0x2E, 0x8B, 0x57)), - CNameToCol("SeaShell", CRGBA(0xFF, 0xF5, 0xEE)), - CNameToCol("Sienna", CRGBA(0xA0, 0x52, 0x2D)), - CNameToCol("Silver", CRGBA(0xC0, 0xC0, 0xC0)), - CNameToCol("SkyBlue", CRGBA(0x87, 0xCE, 0xEB)), - CNameToCol("SlateBlue", CRGBA(0x6A, 0x5A, 0xCD)), - CNameToCol("SlateGray", CRGBA(0x70, 0x80, 0x90)), - CNameToCol("Snow", CRGBA(0xFF, 0xFA, 0xFA)), - CNameToCol("SpringGreen", CRGBA(0x00, 0xFF, 0x7F)), - CNameToCol("SteelBlue", CRGBA(0x46, 0x82, 0xB4)), - CNameToCol("Tan", CRGBA(0xD2, 0xB4, 0x8C)), - CNameToCol("Teal", CRGBA(0x00, 0x80, 0x80)), - CNameToCol("Thistle", CRGBA(0xD8, 0xBF, 0xD8)), - CNameToCol("Tomato", CRGBA(0xFF, 0x63, 0x47)), - CNameToCol("Turquoise", CRGBA(0x40, 0xE0, 0xD0)), - CNameToCol("Violet", CRGBA(0xEE, 0x82, 0xEE)), - CNameToCol("VioletRed", CRGBA(0xD0, 0x20, 0x90)), - CNameToCol("Wheat", CRGBA(0xF5, 0xDE, 0xB3)), - CNameToCol("White", CRGBA(0xFF, 0xFF, 0xFF)), - CNameToCol("WhiteSmoke", CRGBA(0xF5, 0xF5, 0xF5)), - CNameToCol("Yellow", CRGBA(0xFF, 0xFF, 0x00)), - CNameToCol("YellowGreen", CRGBA(0x9A, 0xCD, 0x32)) - }; - - // scan a color from a HTML form (#rrggbb format) - bool scanHTMLColor(const char *src, CRGBA &dest) - { - if (!src || *src == '\0') return false; - if (*src == '#') - { - ++src; - if (strlen(src) == 3 || strlen(src) == 4) - { - bool hasAlpha = (strlen(src) == 4); - // check RGB for valid hex - if (isHexa(src[0]) && isHexa(src[1]) && isHexa(src[2])) - { - // check optional A for valid hex - if (hasAlpha && !isHexa(src[3])) return false; - - dest.R = convertHexa(src[0]); - dest.G = convertHexa(src[1]); - dest.B = convertHexa(src[2]); - - dest.R = dest.R << 4 | dest.R; - dest.G = dest.G << 4 | dest.G; - dest.B = dest.B << 4 | dest.B; - - if (hasAlpha) - { - dest.A = convertHexa(src[3]); - dest.A = dest.A << 4 | dest.A; - } - else - dest.A = 255; - - return true; - } - - return false; - } - - CRGBA result; - src = scanColorComponent(src, result.R); if (!src) return false; - src = scanColorComponent(src, result.G); if (!src) return false; - src = scanColorComponent(src, result.B); if (!src) return false; - src = scanColorComponent(src, result.A); - if (!src) - { - // Alpha is optional - result.A = 255; - } - dest = result; - return true; - } - - if (strnicmp(src, "rgb(", 4) == 0 || strnicmp(src, "rgba(", 5) == 0) - { - src += 4; - if (*src == '(') src++; - - vector parts; - NLMISC::splitString(src, ",", parts); - if (parts.size() >= 3) - { - CRGBA result; - sint tmpv; - float tmpf; - - // R - if (getPercentage(tmpv, tmpf, parts[0].c_str())) tmpv = 255 * tmpf; - clamp(tmpv, 0, 255); - result.R = tmpv; - - // G - if (getPercentage(tmpv, tmpf, parts[1].c_str())) tmpv = 255 * tmpf; - clamp(tmpv, 0, 255); - result.G = tmpv; - - // B - if (getPercentage(tmpv, tmpf, parts[2].c_str())) tmpv = 255 * tmpf; - clamp(tmpv, 0, 255); - result.B = tmpv; - - // A - if (parts.size() == 4) - { - if (!fromString(parts[3], tmpf)) return false; - if (parts[3].find_first_of("%") != std::string::npos) - tmpf /= 100; - - tmpv = 255 * tmpf; - clamp(tmpv, 0, 255); - result.A = tmpv; - } - else - result.A = 255; - - dest = result; - return true; - } - - return false; - } - - if (strnicmp(src, "hsl(", 4) == 0 || strnicmp(src, "hsla(", 5) == 0) - { - src += 4; - if (*src == '(') src++; - - vector parts; - NLMISC::splitString(src, ",", parts); - if (parts.size() >= 3) - { - sint tmpv; - float h, s, l; - // hue - if (!fromString(parts[0], tmpv)) return false; - tmpv = ((tmpv % 360) + 360) % 360; - h = (float) tmpv / 360.0f; - - // saturation - if (!getPercentage(tmpv, s, parts[1].c_str())) return false; - clamp(s, 0.0f, 1.0f); - - // lightness - if (!getPercentage(tmpv, l, parts[2].c_str())) return false; - clamp(l, 0.0f, 1.0f); - - CRGBA result; - hslToRgb(h, s, l, result); - - // A - if (parts.size() == 4) - { - float tmpf; - if (!fromString(parts[3], tmpf)) return false; - if (parts[3].find_first_of("%") != std::string::npos) - tmpf /= 100; - clamp(tmpf, 0.0f, 1.0f); - result.A = 255 * tmpf; - } - - dest = result; - return true; - } - - return false; - } - - { - // slow but should suffice for now - for(uint k = 0; k < sizeofarray(htmlColorNameToRGBA); ++k) - { - if (nlstricmp(src, htmlColorNameToRGBA[k].Name) == 0) - { - dest = htmlColorNameToRGBA[k].Color; - return true; - } - } - return false; - } - } - // *************************************************************************** void CGroupHTML::beginElement (uint element_number, const std::vector &present, const std::vector &value) @@ -1546,10 +1164,10 @@ namespace NLGUI { case HTML_HTML: if (present[MY_HTML_HTML_STYLE] && value[MY_HTML_HTML_STYLE]) - getStyleParams(value[MY_HTML_HTML_STYLE], _StyleDefault, _StyleDefault); + _Style.applyRootStyle(value[MY_HTML_HTML_STYLE]); - _Style = _StyleDefault; - setBackgroundColor(_Style.BackgroundColor); + _Style.Current = _Style.Root; + setBackgroundColor(_Style.Current.BackgroundColor); break; case HTML_HEAD: _ReadingHeadTag = !_IgnoreHeadTag; @@ -1607,17 +1225,17 @@ namespace NLGUI { registerAnchorName(MY_HTML_A); - pushStyle(); - _Style.TextColor = LinkColor; - _Style.Underlined = true; - _Style.GlobalColor = LinkColorGlobalColor; - _Style.BackgroundColor.A = 0; - _Style.BackgroundColorOver.A = 0; - _Style.Width = -1; - _Style.Height = -1; + _Style.pushStyle(); + _Style.Current.TextColor = LinkColor; + _Style.Current.Underlined = true; + _Style.Current.GlobalColor = LinkColorGlobalColor; + _Style.Current.BackgroundColor.A = 0; + _Style.Current.BackgroundColorOver.A = 0; + _Style.Current.Width = -1; + _Style.Current.Height = -1; if (present[HTML_A_STYLE] && value[HTML_A_STYLE]) - getStyleParams(value[HTML_A_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[HTML_A_STYLE]); _A.push_back(true); _Link.push_back (""); @@ -1656,7 +1274,7 @@ namespace NLGUI { _BlockLevelElement.push_back(true); registerAnchorName(MY_HTML_DIV); - pushStyle(); + _Style.pushStyle(); if (present[MY_HTML_DIV_NAME] && value[MY_HTML_DIV_NAME]) _DivName = value[MY_HTML_DIV_NAME]; @@ -1670,7 +1288,7 @@ namespace NLGUI style = value[MY_HTML_DIV_STYLE]; if (!style.empty()) - getStyleParams(style, _Style, _StyleParams.back()); + _Style.applyStyle(style); // use generic template system if (_TrustedDomain && !instClass.empty() && instClass == "ryzom-ui-grouptemplate") @@ -1746,19 +1364,19 @@ namespace NLGUI break; case HTML_FONT: { - pushStyle(); + _Style.pushStyle(); if (present[HTML_FONT_COLOR] && value[HTML_FONT_COLOR]) { CRGBA color; if (scanHTMLColor(value[HTML_FONT_COLOR], color)) - _Style.TextColor = color; + _Style.Current.TextColor = color; } if (present[HTML_FONT_SIZE] && value[HTML_FONT_SIZE]) { uint fontsize; fromString(value[HTML_FONT_SIZE], fontsize); - _Style.FontSize = fontsize; + _Style.Current.FontSize = fontsize; } } break; @@ -1774,20 +1392,20 @@ namespace NLGUI break; case HTML_BODY: { - pushStyle(); + _Style.pushStyle(); string style; if (present[HTML_BODY_STYLE] && value[HTML_BODY_STYLE]) style = value[HTML_BODY_STYLE]; if (!style.empty()) - getStyleParams(style, _Style, _StyleParams.back()); + _Style.applyStyle(style); - CRGBA bgColor = _Style.BackgroundColor; + CRGBA bgColor = _Style.Current.BackgroundColor; if (present[HTML_BODY_BGCOLOR] && value[HTML_BODY_BGCOLOR]) scanHTMLColor(value[HTML_BODY_BGCOLOR], bgColor); - if (bgColor != _Style.BackgroundColor) + if (bgColor != _Style.Current.BackgroundColor) setBackgroundColor(bgColor); if (!style.empty()) @@ -1837,72 +1455,72 @@ namespace NLGUI { registerAnchorName(MY_HTML_H1); newParagraph(PBeginSpace); - pushStyle(); - _Style.FontSize = H1FontSize; - _Style.TextColor = H1Color; - _Style.GlobalColor = H1ColorGlobalColor; + _Style.pushStyle(); + _Style.Current.FontSize = H1FontSize; + _Style.Current.TextColor = H1Color; + _Style.Current.GlobalColor = H1ColorGlobalColor; if (present[MY_HTML_H1_STYLE] && value[MY_HTML_H1_STYLE]) - getStyleParams(value[MY_HTML_H1_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[MY_HTML_H1_STYLE]); } break; case HTML_H2: { registerAnchorName(MY_HTML_H2); newParagraph(PBeginSpace); - pushStyle(); - _Style.FontSize = H2FontSize; - _Style.TextColor = H2Color; - _Style.GlobalColor = H2ColorGlobalColor; + _Style.pushStyle(); + _Style.Current.FontSize = H2FontSize; + _Style.Current.TextColor = H2Color; + _Style.Current.GlobalColor = H2ColorGlobalColor; if (present[MY_HTML_H2_STYLE] && value[MY_HTML_H2_STYLE]) - getStyleParams(value[MY_HTML_H2_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[MY_HTML_H2_STYLE]); } break; case HTML_H3: { registerAnchorName(MY_HTML_H3); newParagraph(PBeginSpace); - pushStyle(); - _Style.FontSize = H3FontSize; - _Style.TextColor = H3Color; - _Style.GlobalColor = H3ColorGlobalColor; + _Style.pushStyle(); + _Style.Current.FontSize = H3FontSize; + _Style.Current.TextColor = H3Color; + _Style.Current.GlobalColor = H3ColorGlobalColor; if (present[MY_HTML_H3_STYLE] && value[MY_HTML_H3_STYLE]) - getStyleParams(value[MY_HTML_H3_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[MY_HTML_H3_STYLE]); } break; case HTML_H4: { registerAnchorName(MY_HTML_H4); newParagraph(PBeginSpace); - pushStyle(); - _Style.FontSize = H4FontSize; - _Style.TextColor = H4Color; - _Style.GlobalColor = H4ColorGlobalColor; + _Style.pushStyle(); + _Style.Current.FontSize = H4FontSize; + _Style.Current.TextColor = H4Color; + _Style.Current.GlobalColor = H4ColorGlobalColor; if (present[MY_HTML_H4_STYLE] && value[MY_HTML_H4_STYLE]) - getStyleParams(value[MY_HTML_H4_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[MY_HTML_H4_STYLE]); } break; case HTML_H5: { registerAnchorName(MY_HTML_H5); newParagraph(PBeginSpace); - pushStyle(); - _Style.FontSize = H5FontSize; - _Style.TextColor = H5Color; - _Style.GlobalColor = H5ColorGlobalColor; + _Style.pushStyle(); + _Style.Current.FontSize = H5FontSize; + _Style.Current.TextColor = H5Color; + _Style.Current.GlobalColor = H5ColorGlobalColor; if (present[MY_HTML_H5_STYLE] && value[MY_HTML_H5_STYLE]) - getStyleParams(value[MY_HTML_H5_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[MY_HTML_H5_STYLE]); } break; case HTML_H6: { registerAnchorName(MY_HTML_H6); newParagraph(PBeginSpace); - pushStyle(); - _Style.FontSize = H6FontSize; - _Style.TextColor = H6Color; - _Style.GlobalColor = H6ColorGlobalColor; + _Style.pushStyle(); + _Style.Current.FontSize = H6FontSize; + _Style.Current.TextColor = H6Color; + _Style.Current.GlobalColor = H6ColorGlobalColor; if (present[MY_HTML_H6_STYLE] && value[MY_HTML_H6_STYLE]) - getStyleParams(value[MY_HTML_H6_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[MY_HTML_H6_STYLE]); } break; case HTML_IMG: @@ -1912,24 +1530,24 @@ namespace NLGUI { float tmpf; std::string id; - CStyleParams style; - style.FontSize = _Style.FontSize; + + _Style.pushStyle(); if (present[MY_HTML_IMG_ID] && value[MY_HTML_IMG_ID]) id = value[MY_HTML_IMG_ID]; if (present[MY_HTML_IMG_WIDTH] && value[MY_HTML_IMG_WIDTH]) - getPercentage(style.Width, tmpf, value[MY_HTML_IMG_WIDTH]); + getPercentage(_Style.Current.Width, tmpf, value[MY_HTML_IMG_WIDTH]); if (present[MY_HTML_IMG_HEIGHT] && value[MY_HTML_IMG_HEIGHT]) - getPercentage(style.Height, tmpf, value[MY_HTML_IMG_HEIGHT]); + getPercentage(_Style.Current.Height, tmpf, value[MY_HTML_IMG_HEIGHT]); // Get the global color name if (present[MY_HTML_IMG_GLOBAL_COLOR]) - style.GlobalColor = true; + _Style.Current.GlobalColor = true; // width, height from inline css if (present[MY_HTML_IMG_STYLE] && value[MY_HTML_IMG_STYLE]) - getStyleParams(value[MY_HTML_IMG_STYLE], style, _Style); + _Style.applyStyle(value[MY_HTML_IMG_STYLE]); // Tooltip const char *tooltip = NULL; @@ -1952,13 +1570,13 @@ namespace NLGUI { string params = "name=" + getId() + "|url=" + getLink (); addButton(CCtrlButton::PushButton, id, value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC], - overSrc, "browse", params.c_str(), tooltip, style); + overSrc, "browse", params.c_str(), tooltip, _Style.Current); } else if (tooltip || !overSrc.empty()) { addButton(CCtrlButton::PushButton, id, value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC], - overSrc, "", "", tooltip, style); + overSrc, "", "", tooltip, _Style.Current); } else { @@ -1979,8 +1597,10 @@ namespace NLGUI reloadImg = true; } - addImage(id, value[MY_HTML_IMG_SRC], reloadImg, style); + addImage(id, value[MY_HTML_IMG_SRC], reloadImg, _Style.Current); } + + _Style.popStyle(); } } break; @@ -2010,22 +1630,22 @@ namespace NLGUI if (present[MY_HTML_INPUT_TYPE] && value[MY_HTML_INPUT_TYPE]) { // by default not inherited, font family defaults to system font - pushStyle(); - _Style.TextColor = TextColor; - _Style.FontSize = TextFontSize; - _Style.FontWeight = FONT_WEIGHT_NORMAL; - _Style.FontOblique = false; - _Style.TextShadow = STextShadow(true); - _Style.Width = -1; - _Style.Height = -1; + _Style.pushStyle(); + _Style.Current.TextColor = TextColor; + _Style.Current.FontSize = TextFontSize; + _Style.Current.FontWeight = FONT_WEIGHT_NORMAL; + _Style.Current.FontOblique = false; + _Style.Current.TextShadow = CStyleParams::STextShadow(true); + _Style.Current.Width = -1; + _Style.Current.Height = -1; // by default background texture is transparent, // using alpha value to decide if to change it to 'blank.tga' for coloring - _Style.BackgroundColor.A = 0; - _Style.BackgroundColorOver.A = 0; + _Style.Current.BackgroundColor.A = 0; + _Style.Current.BackgroundColorOver.A = 0; // Global color flag if (present[MY_HTML_INPUT_GLOBAL_COLOR]) - _Style.GlobalColor = true; + _Style.Current.GlobalColor = true; // Tooltip const char *tooltip = NULL; @@ -2033,7 +1653,7 @@ namespace NLGUI tooltip = value[MY_HTML_INPUT_ALT]; if (present[MY_HTML_INPUT_STYLE] && value[MY_HTML_INPUT_STYLE]) - getStyleParams(value[MY_HTML_INPUT_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[MY_HTML_INPUT_STYLE]); string type = toLower(value[MY_HTML_INPUT_TYPE]); if (type == "image") @@ -2053,7 +1673,7 @@ namespace NLGUI // Add the ctrl button addButton (CCtrlButton::PushButton, name, normal, pushed.empty()?normal:pushed, over, - "html_submit_form", param.c_str(), tooltip, _Style); + "html_submit_form", param.c_str(), tooltip, _Style.Current); } if (type == "button" || type == "submit") { @@ -2108,7 +1728,7 @@ namespace NLGUI if (!ctrlButton) ctrlButton = dynamic_cast(buttonGroup->getCtrl("b")); if (ctrlButton) { - ctrlButton->setModulateGlobalColorAll (_Style.GlobalColor); + ctrlButton->setModulateGlobalColorAll (_Style.Current.GlobalColor); // Translate the tooltip if (tooltip) @@ -2125,7 +1745,7 @@ namespace NLGUI ctrlButton->setText(ucstring::makeFromUtf8(text)); - setTextButtonStyle(ctrlButton, _Style); + setTextButtonStyle(ctrlButton, _Style.Current); } getParagraph()->addChild (buttonGroup); paragraphChange (); @@ -2193,7 +1813,7 @@ namespace NLGUI checked = (present[MY_HTML_INPUT_CHECKED] && value[MY_HTML_INPUT_CHECKED]); // Add the ctrl button - CCtrlButton *checkbox = addButton (btnType, name, normal, pushed, over, "", "", tooltip, _Style); + CCtrlButton *checkbox = addButton (btnType, name, normal, pushed, over, "", "", tooltip, _Style.Current); if (checkbox) { if (btnType == CCtrlButton::RadioButton) @@ -2251,14 +1871,16 @@ namespace NLGUI } } - popStyle(); + _Style.popStyle(); } } break; case HTML_SELECT: if (!(_Forms.empty())) { - CStyleParams style; + _Style.pushStyle(); + _Style.Current.Width = -1; + _Style.Current.Height = -1; // A select box string name; @@ -2272,7 +1894,7 @@ namespace NLGUI if (present[HTML_SELECT_MULTIPLE] && value[HTML_SELECT_MULTIPLE]) multiple = true; if (present[HTML_SELECT_STYLE] && value[HTML_SELECT_STYLE]) - getStyleParams(value[HTML_SELECT_STYLE], style, _Style); + _Style.applyStyle(value[HTML_SELECT_STYLE]); CGroupHTML::CForm::CEntry entry; entry.Name = name; @@ -2286,14 +1908,14 @@ namespace NLGUI if (size < 1) size = 4; - if (style.Width > -1) - sb->setMinW(style.Width); + if (_Style.Current.Width > -1) + sb->setMinW(_Style.Current.Width); - if (style.Height > -1) - sb->setMinH(style.Height); + if (_Style.Current.Height > -1) + sb->setMinH(_Style.Current.Height); sb->setMaxVisibleLine(size); - sb->setFontSize(style.FontSize); + sb->setFontSize(_Style.Current.FontSize); } entry.SelectBox = sb; @@ -2308,10 +1930,12 @@ namespace NLGUI // create view text cb->updateCoords(); if (cb->getViewText()) - setTextStyle(cb->getViewText(), style); + setTextStyle(cb->getViewText(), _Style.Current); } } _Forms.back().Entries.push_back (entry); + + _Style.popStyle(); } break; case HTML_OPTION: @@ -2354,9 +1978,9 @@ namespace NLGUI if (present[HTML_LI_VALUE] && value[HTML_LI_VALUE]) fromString(value[HTML_LI_VALUE], _UL.back().Value); - pushStyle(); + _Style.pushStyle(); if (present[HTML_LI_STYLE] && value[HTML_LI_STYLE]) - getStyleParams(value[HTML_LI_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[HTML_LI_STYLE]); ucstring str; str.fromUtf8(_UL.back().getListMarkerText()); @@ -2377,18 +2001,18 @@ namespace NLGUI case HTML_P: { newParagraph(PBeginSpace); - pushStyle(); + _Style.pushStyle(); if (present[MY_HTML_P_STYLE] && value[MY_HTML_P_STYLE]) - getStyleParams(value[MY_HTML_P_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[MY_HTML_P_STYLE]); } break; case HTML_PRE: { - pushStyle(); - _Style.FontFamily = "monospace"; + _Style.pushStyle(); + _Style.Current.FontFamily = "monospace"; if (present[HTML_PRE_STYLE] && value[HTML_PRE_STYLE]) - getStyleParams(value[HTML_PRE_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[HTML_PRE_STYLE]); _PRE.push_back(true); @@ -2396,7 +2020,7 @@ namespace NLGUI break; case HTML_TABLE: { - pushStyle(); + _Style.pushStyle(); registerAnchorName(MY_HTML_TABLE); // Get cells parameters @@ -2416,7 +2040,7 @@ namespace NLGUI if (present[MY_HTML_TABLE_CELLPADDING] && value[MY_HTML_TABLE_CELLPADDING]) fromString(value[MY_HTML_TABLE_CELLPADDING], table->CellPadding); if (present[MY_HTML_TABLE_STYLE] && value[MY_HTML_TABLE_STYLE]) - getStyleParams(value[MY_HTML_TABLE_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[MY_HTML_TABLE_STYLE]); table->setMarginLeft(getIndent()); addHtmlGroup (table, 0); @@ -2436,17 +2060,17 @@ namespace NLGUI // Get cells parameters getCellsParameters (MY_HTML_TD, true); - pushStyle(); + _Style.pushStyle(); if (element_number == HTML_TH) { - _Style.FontWeight = FONT_WEIGHT_BOLD; + _Style.Current.FontWeight = FONT_WEIGHT_BOLD; // center if not specified otherwise. TD/TH present/value arrays have same indices if (!(present[MY_HTML_TD_ALIGN] && value[MY_HTML_TD_ALIGN])) _CellParams.back().Align = CGroupCell::Center; } if (present[MY_HTML_TD_STYLE] && value[MY_HTML_TD_STYLE]) - getStyleParams(value[MY_HTML_TD_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[MY_HTML_TD_STYLE]); CGroupTable *table = getTable(); if (table) @@ -2527,21 +2151,21 @@ namespace NLGUI } break; case HTML_TEXTAREA: - pushStyle(); + _Style.pushStyle(); _PRE.push_back(true); // not inherited by default, font family defaults to system font - _Style.TextColor = TextColor; - _Style.FontWeight = FONT_WEIGHT_NORMAL; - _Style.FontOblique = false; - _Style.FontSize = TextFontSize; - _Style.TextShadow = STextShadow(true); - _Style.Width = -1; - _Style.Height = -1; - _Style.BackgroundColor.A = 0; + _Style.Current.TextColor = TextColor; + _Style.Current.FontWeight = FONT_WEIGHT_NORMAL; + _Style.Current.FontOblique = false; + _Style.Current.FontSize = TextFontSize; + _Style.Current.TextShadow = CStyleParams::STextShadow(true); + _Style.Current.Width = -1; + _Style.Current.Height = -1; + _Style.Current.BackgroundColor.A = 0; if (present[MY_HTML_TEXTAREA_STYLE] && value[MY_HTML_TEXTAREA_STYLE]) - getStyleParams(value[MY_HTML_TEXTAREA_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[MY_HTML_TEXTAREA_STYLE]); // Got one form ? if (!(_Forms.empty())) @@ -2595,9 +2219,9 @@ namespace NLGUI if (!_TR.empty()) _TR.back() = true; - pushStyle(); + _Style.pushStyle(); if (present[MY_HTML_TR_STYLE] && value[MY_HTML_TR_STYLE]) - getStyleParams(value[MY_HTML_TR_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[MY_HTML_TR_STYLE]); } break; case HTML_UL: @@ -2612,9 +2236,9 @@ namespace NLGUI _Indent.push_back(getIndent() + ULIndent); endParagraph(); - pushStyle(); + _Style.pushStyle(); if (present[HTML_UL_STYLE] && value[HTML_UL_STYLE]) - getStyleParams(value[HTML_UL_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[HTML_UL_STYLE]); break; case HTML_OBJECT: _ObjectType.clear(); @@ -2634,40 +2258,40 @@ namespace NLGUI break; case HTML_SPAN: { - pushStyle(); + _Style.pushStyle(); if (present[MY_HTML_SPAN_STYLE] && value[MY_HTML_SPAN_STYLE]) - getStyleParams(value[MY_HTML_SPAN_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[MY_HTML_SPAN_STYLE]); } break; case HTML_DEL: { - pushStyle(); - _Style.StrikeThrough = true; + _Style.pushStyle(); + _Style.Current.StrikeThrough = true; } break; case HTML_U: { - pushStyle(); - _Style.Underlined = true; + _Style.pushStyle(); + _Style.Current.Underlined = true; } break; case HTML_EM: { - pushStyle(); - _Style.FontOblique = true; + _Style.pushStyle(); + _Style.Current.FontOblique = true; } break; case HTML_STRONG: { - pushStyle(); - _Style.FontWeight = FONT_WEIGHT_BOLD; + _Style.pushStyle(); + _Style.Current.FontWeight = FONT_WEIGHT_BOLD; } break; case HTML_SMALL: { - pushStyle(); - _Style.FontSize = getFontSizeSmaller(); + _Style.pushStyle(); + _Style.Current.FontSize = _Style.getFontSizeSmaller(); } break; case HTML_STYLE: @@ -2679,9 +2303,9 @@ namespace NLGUI _DL.push_back(HTMLDListElement()); _LI = _DL.size() > 1 || !_UL.empty(); endParagraph(); - pushStyle(); + _Style.pushStyle(); if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE]) - getStyleParams(value[HTML_GEN_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[HTML_GEN_STYLE]); } break; case HTML_DT: @@ -2692,19 +2316,19 @@ namespace NLGUI { _DL.back().DD = false; popIfNotEmpty(_Indent); - popStyle(); + _Style.popStyle(); } // close if still open if (_DL.back().DT) - popStyle(); + _Style.popStyle(); _DL.back().DT = true; - pushStyle(); - _Style.FontWeight = FONT_WEIGHT_BOLD; + _Style.pushStyle(); + _Style.Current.FontWeight = FONT_WEIGHT_BOLD; if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE]) - getStyleParams(value[HTML_GEN_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[HTML_GEN_STYLE]); if (!_LI) { @@ -2724,22 +2348,22 @@ namespace NLGUI if (_DL.back().DT) { _DL.back().DT = false; - popStyle(); + _Style.popStyle(); } if (_DL.back().DD) { _DL.back().DD = false; - popStyle(); + _Style.popStyle(); popIfNotEmpty(_Indent); } _DL.back().DD = true; _Indent.push_back(getIndent() + ULIndent); - pushStyle(); + _Style.pushStyle(); if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE]) - getStyleParams(value[HTML_GEN_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[HTML_GEN_STYLE]); if (!_LI) { @@ -2754,7 +2378,7 @@ namespace NLGUI break; case HTML_OL: { - pushStyle(); + _Style.pushStyle(); sint32 start = 1; std::string type("1"); @@ -2763,7 +2387,7 @@ namespace NLGUI if (present[HTML_OL_TYPE] && value[HTML_OL_TYPE]) type = value[HTML_OL_TYPE]; if (present[HTML_OL_STYLE] && value[HTML_OL_STYLE]) - getStyleParams(value[HTML_OL_STYLE], _Style, _StyleParams.back()); + _Style.applyStyle(value[HTML_OL_STYLE]); _UL.push_back(HTMLOListElement(start, type)); // if LI is already present @@ -2779,34 +2403,35 @@ namespace NLGUI CInterfaceGroup *sep = CWidgetManager::getInstance()->getParser()->createGroupInstance("html_hr", "", NULL, 0); if (sep) { - CStyleParams style; - style.FontSize = _Style.FontSize; - style.TextColor = CRGBA(120, 120, 120, 255); - style.Height = 0; - style.Width = 0; + _Style.pushStyle(); + _Style.Current.TextColor = CRGBA(120, 120, 120, 255); + _Style.Current.Height = -1; + _Style.Current.Width = -1; if (present[HTML_HR_STYLE] && value[HTML_HR_STYLE]) - getStyleParams(value[HTML_HR_STYLE], style, _Style); + _Style.applyStyle(value[HTML_HR_STYLE]); CViewBitmap *bitmap = dynamic_cast(sep->getView("hr")); if (bitmap) { - bitmap->setColor(style.TextColor); - if (style.Width > 0) + bitmap->setColor(_Style.Current.TextColor); + if (_Style.Current.Width > 0) { - clamp(style.Width, 1, 32000); - bitmap->setW(style.Width); + clamp(_Style.Current.Width, 1, 32000); + bitmap->setW(_Style.Current.Width); bitmap->setSizeRef(CInterfaceElement::none); } - if (style.Height > 0) + if (_Style.Current.Height > 0) { - clamp(style.Height, 1, 1000); - bitmap->setH(style.Height); + clamp(_Style.Current.Height, 1, 1000); + bitmap->setH(_Style.Current.Height); } } getParagraph()->addChild(sep); endParagraph(); + + _Style.popStyle(); } } break; @@ -2827,13 +2452,13 @@ namespace NLGUI _ReadingHeadTag = false; break; case HTML_BODY: - popStyle(); + _Style.popStyle(); break; case HTML_FONT: - popStyle(); + _Style.popStyle(); break; case HTML_A: - popStyle(); + _Style.popStyle(); popIfNotEmpty (_A); popIfNotEmpty (_Link); popIfNotEmpty (_LinkTitle); @@ -2845,19 +2470,19 @@ namespace NLGUI case HTML_H4: case HTML_H5: case HTML_H6: - popStyle(); + _Style.popStyle(); endParagraph(); break; case HTML_P: - popStyle(); + _Style.popStyle(); endParagraph(); break; case HTML_PRE: - popStyle(); + _Style.popStyle(); popIfNotEmpty (_PRE); break; case HTML_DIV: - popStyle(); + _Style.popStyle(); if (isBlockLevelElement()) { endParagraph(); @@ -2868,7 +2493,7 @@ namespace NLGUI break; case HTML_TABLE: - popStyle(); + _Style.popStyle(); popIfNotEmpty (_CellParams); popIfNotEmpty (_TR); popIfNotEmpty (_Cells); @@ -2880,13 +2505,13 @@ namespace NLGUI case HTML_TH: // no break; case HTML_TD: - popStyle(); + _Style.popStyle(); popIfNotEmpty (_CellParams); if (!_Cells.empty()) _Cells.back() = NULL; break; case HTML_TR: - popStyle(); + _Style.popStyle(); popIfNotEmpty (_CellParams); break; case HTML_TEXTAREA: @@ -2905,7 +2530,7 @@ namespace NLGUI } } - popStyle(); + _Style.popStyle(); popIfNotEmpty (_PRE); } break; @@ -3013,14 +2638,14 @@ namespace NLGUI if (!_UL.empty()) { endParagraph(); - popStyle(); + _Style.popStyle(); popIfNotEmpty(_UL); popIfNotEmpty(_Indent); } break; case HTML_LI: { - popStyle(); + _Style.popStyle(); } break; case HTML_DL: @@ -3031,25 +2656,25 @@ namespace NLGUI // unclosed DT if (_DL.back().DT) { - popStyle(); + _Style.popStyle(); } // unclosed DD if (_DL.back().DD) { popIfNotEmpty(_Indent); - popStyle(); + _Style.popStyle(); } popIfNotEmpty (_DL); - popStyle(); + _Style.popStyle(); } break; case HTML_DT: if (!_DL.empty()) { if (_DL.back().DT) - popStyle(); + _Style.popStyle(); _DL.back().DT = false; } break; @@ -3061,27 +2686,27 @@ namespace NLGUI { _DL.back().DD = false; popIfNotEmpty(_Indent); - popStyle(); + _Style.popStyle(); } } break; case HTML_SPAN: - popStyle(); + _Style.popStyle(); break; case HTML_DEL: - popStyle(); + _Style.popStyle(); break; case HTML_U: - popStyle(); + _Style.popStyle(); break; case HTML_EM: - popStyle(); + _Style.popStyle(); break; case HTML_STRONG: - popStyle(); + _Style.popStyle(); break; case HTML_SMALL: - popStyle(); + _Style.popStyle(); break; case HTML_STYLE: case HTML_SCRIPT: @@ -4508,34 +4133,36 @@ namespace NLGUI paragraphChange (); } + CStyleParams &style = _Style.Current; + // Text added ? bool added = false; - bool embolden = _Style.FontWeight >= FONT_WEIGHT_BOLD; + bool embolden = style.FontWeight >= FONT_WEIGHT_BOLD; // Number of child in this paragraph if (_CurrentViewLink) { bool skipLine = !_CurrentViewLink->getText().empty() && *(_CurrentViewLink->getText().rbegin()) == (ucchar) '\n'; - bool sameShadow = _Style.TextShadow.Enabled && _CurrentViewLink->getShadow(); - if (sameShadow && _Style.TextShadow.Enabled) + bool sameShadow = style.TextShadow.Enabled && _CurrentViewLink->getShadow(); + if (sameShadow && style.TextShadow.Enabled) { sint sx, sy; _CurrentViewLink->getShadowOffset(sx, sy); - sameShadow = (_Style.TextShadow.Color == _CurrentViewLink->getShadowColor()); - sameShadow = sameShadow && (_Style.TextShadow.Outline == _CurrentViewLink->getShadowOutline()); - sameShadow = sameShadow && (_Style.TextShadow.X == sx) && (_Style.TextShadow.Y == sy); + sameShadow = (style.TextShadow.Color == _CurrentViewLink->getShadowColor()); + sameShadow = sameShadow && (style.TextShadow.Outline == _CurrentViewLink->getShadowOutline()); + sameShadow = sameShadow && (style.TextShadow.X == sx) && (style.TextShadow.Y == sy); } // Compatible with current parameters ? if (!skipLine && sameShadow && - (_Style.TextColor == _CurrentViewLink->getColor()) && - (_Style.FontFamily == _CurrentViewLink->getFontName()) && - (_Style.FontSize == (uint)_CurrentViewLink->getFontSize()) && - (_Style.Underlined == _CurrentViewLink->getUnderlined()) && - (_Style.StrikeThrough == _CurrentViewLink->getStrikeThrough()) && + (style.TextColor == _CurrentViewLink->getColor()) && + (style.FontFamily == _CurrentViewLink->getFontName()) && + (style.FontSize == (uint)_CurrentViewLink->getFontSize()) && + (style.Underlined == _CurrentViewLink->getUnderlined()) && + (style.StrikeThrough == _CurrentViewLink->getStrikeThrough()) && (embolden == _CurrentViewLink->getEmbolden()) && - (_Style.FontOblique == _CurrentViewLink->getOblique()) && + (style.FontOblique == _CurrentViewLink->getOblique()) && (getLink() == _CurrentViewLink->Link) && - (_Style.GlobalColor == _CurrentViewLink->getModulateGlobalColor())) + (style.GlobalColor == _CurrentViewLink->getModulateGlobalColor())) { // Concat the text _CurrentViewLink->setText(_CurrentViewLink->getText()+tmpStr); @@ -4574,7 +4201,7 @@ namespace NLGUI ctrlButton->setDefaultContextHelp(ucstring::makeFromUtf8(getLinkTitle())); ctrlButton->setText(tmpStr); - setTextButtonStyle(ctrlButton, _Style); + setTextButtonStyle(ctrlButton, style); } getParagraph()->addChild (buttonGroup); paragraphChange (); @@ -4597,10 +4224,10 @@ namespace NLGUI } } newLink->setText(tmpStr); - newLink->setMultiLineSpace((uint)((float)(_Style.FontSize)*LineSpaceFontFactor)); + newLink->setMultiLineSpace((uint)((float)(style.FontSize)*LineSpaceFontFactor)); newLink->setMultiLine(true); - newLink->setModulateGlobalColor(_Style.GlobalColor); - setTextStyle(newLink, _Style); + newLink->setModulateGlobalColor(style.GlobalColor); + setTextStyle(newLink, style); // newLink->setLineAtBottom (true); registerAnchor(newLink); @@ -4705,22 +4332,23 @@ namespace NLGUI // No more text in this text view _CurrentViewLink = NULL; + CStyleParams &style = _Style.Current; { // override cols/rows values from style - if (_Style.Width > 0) cols = _Style.Width / _Style.FontSize; - if (_Style.Height > 0) rows = _Style.Height / _Style.FontSize; + if (style.Width > 0) cols = style.Width / style.FontSize; + if (style.Height > 0) rows = style.Height / style.FontSize; // Not added ? std::vector > templateParams; - templateParams.push_back (std::pair ("w", toString (cols*_Style.FontSize))); + templateParams.push_back (std::pair ("w", toString (cols*style.FontSize))); templateParams.push_back (std::pair ("id", name)); templateParams.push_back (std::pair ("prompt", "")); templateParams.push_back (std::pair ("multiline", multiLine?"true":"false")); - templateParams.push_back (std::pair ("fontsize", toString (_Style.FontSize))); - templateParams.push_back (std::pair ("color", _Style.TextColor.toString())); - if (_Style.FontWeight >= FONT_WEIGHT_BOLD) + templateParams.push_back (std::pair ("fontsize", toString (style.FontSize))); + templateParams.push_back (std::pair ("color", style.TextColor.toString())); + if (style.FontWeight >= FONT_WEIGHT_BOLD) templateParams.push_back (std::pair ("fontweight", "bold")); - if (_Style.FontOblique) + if (style.FontOblique) templateParams.push_back (std::pair ("fontstyle", "oblique")); if (multiLine) templateParams.push_back (std::pair ("multi_min_line", toString(rows))); @@ -4729,13 +4357,13 @@ namespace NLGUI templateParams.push_back (std::pair ("enter_recover_focus", "false")); if (maxlength > 0) templateParams.push_back (std::pair ("max_num_chars", toString(maxlength))); - templateParams.push_back (std::pair ("shadow", toString(_Style.TextShadow.Enabled))); - if (_Style.TextShadow.Enabled) + templateParams.push_back (std::pair ("shadow", toString(style.TextShadow.Enabled))); + if (style.TextShadow.Enabled) { - templateParams.push_back (std::pair ("shadow_x", toString(_Style.TextShadow.X))); - templateParams.push_back (std::pair ("shadow_y", toString(_Style.TextShadow.Y))); - templateParams.push_back (std::pair ("shadow_color", _Style.TextShadow.Color.toString())); - templateParams.push_back (std::pair ("shadow_outline", toString(_Style.TextShadow.Outline))); + templateParams.push_back (std::pair ("shadow_x", toString(style.TextShadow.X))); + templateParams.push_back (std::pair ("shadow_y", toString(style.TextShadow.Y))); + templateParams.push_back (std::pair ("shadow_color", style.TextShadow.Color.toString())); + templateParams.push_back (std::pair ("shadow_outline", toString(style.TextShadow.Outline))); } CInterfaceGroup *textArea = CWidgetManager::getInstance()->getParser()->createGroupInstance (templateName.c_str(), @@ -4749,13 +4377,13 @@ namespace NLGUI if (eb) { eb->setInputString(decodeHTMLEntities(content)); - if (_Style.BackgroundColor.A > 0) + if (style.BackgroundColor.A > 0) { CViewBitmap *bg = dynamic_cast(eb->getView("bg")); if (bg) { bg->setTexture("blank.tga"); - bg->setColor(_Style.BackgroundColor); + bg->setColor(style.BackgroundColor); } } } @@ -6411,423 +6039,11 @@ namespace NLGUI // *************************************************************************** void CGroupHTML::resetCssStyle() { - _StyleDefault = CStyleParams(); - _StyleDefault.TextColor = TextColor; - _StyleDefault.FontSize = TextFontSize; - _StyleDefault.BackgroundColor = BgColor; - - _Style = _StyleDefault; - _StyleParams.clear(); - } - - // *************************************************************************** - // CGroupHTML::CStyleParams style; - // style.FontSize; // font-size: 10px; - // style.TextColor; // color: #ABCDEF; - // style.Underlined; // text-decoration: underline; text-decoration-line: underline; - // style.StrikeThrough; // text-decoration: line-through; text-decoration-line: line-through; - void CGroupHTML::getStyleParams(const std::string &styleString, CStyleParams &style, const CStyleParams ¤t) - { - float tmpf; - TStyle styles = parseStyle(styleString); - TStyle::iterator it; - - // first pass: get font-size for 'em' sizes - for (it=styles.begin(); it != styles.end(); ++it) - { - if (it->first == "font") - { - if (it->second == "inherit") - { - style.FontSize = current.FontSize; - style.FontFamily = current.FontFamily; - style.FontWeight = current.FontWeight; - style.FontOblique = current.FontOblique; - } - } - else - if (it->first == "font-size") - { - if (it->second == "inherit") - { - style.FontSize = current.FontSize; - } - else - { - std::string unit; - if (getCssLength(tmpf, unit, it->second.c_str())) - { - if (unit == "rem") - style.FontSize = _StyleDefault.FontSize * tmpf; - else if (unit == "em") - style.FontSize = current.FontSize * tmpf; - else if (unit == "pt") - style.FontSize = tmpf / 0.75f; - else if (unit == "%") - style.FontSize = current.FontSize * tmpf / 100.f; - else - style.FontSize = tmpf; - } - } - } - } - - // second pass: rest of style - for (it=styles.begin(); it != styles.end(); ++it) - { - if (it->first == "border") - { - sint32 b; - if (it->second == "none") - style.BorderWidth = 0; - else - if (fromString(it->second, b)) - style.BorderWidth = b; - } - else - if (it->first == "font-style") - { - if (it->second == "inherit") - style.FontOblique = current.FontOblique; - else - if (it->second == "italic" || it->second == "oblique") - style.FontOblique = true; - } - else - if (it->first == "font-family") - { - if (it->second == "inherit") - style.FontFamily = current.FontFamily; - else - style.FontFamily = it->second; - } - else - if (it->first == "font-weight") - { - // https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight - uint weight = 400; - if (it->second == "inherit") - weight = current.FontWeight; - else - if (it->second == "normal") - weight = 400; - else - if (it->second == "bold") - weight = 700; - else - if (it->second == "lighter") - { - const uint lighter[] = {100, 100, 100, 100, 100, 400, 400, 700, 700}; - uint index = current.FontWeight / 100 - 1; - clamp(index, 1u, 9u); - weight = lighter[index-1]; - } - else - if (it->second == "bolder") - { - const uint bolder[] = {400, 400, 400, 700, 700, 900, 900, 900, 900}; - uint index = current.FontWeight / 100 + 1; - clamp(index, 1u, 9u); - weight = bolder[index-1]; - } - else - if (fromString(it->second, weight)) - { - weight = (weight / 100); - clamp(weight, 1u, 9u); - weight *= 100; - } - style.FontWeight = weight; - } - else - if (it->first == "color") - if (it->second == "inherit") - style.TextColor = current.TextColor; - else - scanHTMLColor(it->second.c_str(), style.TextColor); - else - if (it->first == "text-decoration" || it->first == "text-decoration-line") - { - std::string prop(toLower(it->second)); - style.Underlined = (prop.find("underline") != std::string::npos); - style.StrikeThrough = (prop.find("line-through") != std::string::npos); - } - else - if (it->first == "text-stroke" || it->first == "-webkit-text-stroke") - { - // text-stroke: length || color - bool success = false; - uint px = 0; - CRGBA color; - std::vector parts; - NLMISC::splitString(it->second, " ", parts); - if (parts.size() == 1) - { - success = scanCssLength(parts[0], px); - if (!success) - success = scanHTMLColor(parts[0].c_str(), color); - } - else if (parts.size() == 2) - { - success = scanCssLength(parts[0], px); - if (success) - success = scanHTMLColor(parts[1].c_str(), color); - else - { - success = scanHTMLColor(parts[0].c_str(), color); - success = success && scanCssLength(parts[1], px); - } - } - - // do not disable shadow if one is already set - if (success) - { - style.TextShadow.Enabled = (px > 0); - style.TextShadow.Color = color; - style.TextShadow.X = px; - style.TextShadow.Y = px; - style.TextShadow.Outline = true; - } - } - else - if (it->first == "text-shadow") - { - if (it->second == "none") - style.TextShadow = STextShadow(false); - else - if (it->second == "inherit") - style.TextShadow = current.TextShadow; - else - { - // text-shadow: offset-x offset-y | blur | #color - // text-shadow: #color | offset-x offset-y - bool success = true; - std::string prop(it->second); - size_t pos; - pos = prop.find_first_of(",\n\r"); - if (pos != std::string::npos) - prop = prop.substr(0, pos); - - std::vector parts; - NLMISC::splitString(prop, " ", parts); - switch(parts.size()) - { - case 1: - { - success = scanHTMLColor(it->second.c_str(), style.TextShadow.Color); - break; - } - // no case 2: - case 3: - { - if (!fromString(parts[0], style.TextShadow.X)) - { - success = scanHTMLColor(parts[0].c_str(), style.TextShadow.Color); - success = success && fromString(parts[1], style.TextShadow.X); - success = success && fromString(parts[2], style.TextShadow.Y); - } - else - { - success = fromString(parts[1], style.TextShadow.Y); - success = success && scanHTMLColor(parts[2].c_str(), style.TextShadow.Color); - } - break; - } - case 4: - { - if (!fromString(parts[0], style.TextShadow.X)) - { - success = scanHTMLColor(parts[0].c_str(), style.TextShadow.Color); - success = success && fromString(parts[1], style.TextShadow.X); - success = success && fromString(parts[2], style.TextShadow.Y); - // ignore blur [3] - } - else - { - success = fromString(parts[0], style.TextShadow.X); - success = success && fromString(parts[1], style.TextShadow.Y); - // ignore blur [2] - success = success && scanHTMLColor(parts[3].c_str(), style.TextShadow.Color); - } - break; - } - default: - { - // unsupported rule - break; - } - } - - style.TextShadow.Enabled = success; - } - } - else - if (it->first == "width") - { - std::string unit; - if (getCssLength(tmpf, unit, it->second.c_str())) - { - if (unit == "rem") - style.Width = tmpf * _StyleDefault.FontSize; - else if (unit == "em") - style.Width = tmpf * style.FontSize; - else if (unit == "pt") - style.FontSize = tmpf / 0.75f; - else - style.Width = tmpf; - } - } - else - if (it->first == "height") - { - std::string unit; - if (getCssLength(tmpf, unit, it->second.c_str())) - { - if (unit == "rem") - style.Height = tmpf * _StyleDefault.FontSize; - else if (unit == "em") - style.Height = tmpf * style.FontSize; - else if (unit == "pt") - style.FontSize = tmpf / 0.75f; - else - style.Height = tmpf; - } - } - else - if (it->first == "max-width") - { - std::string unit; - if (getCssLength(tmpf, unit, it->second.c_str())) - { - if (unit == "rem") - style.MaxWidth = tmpf * _StyleDefault.FontSize; - else if (unit == "em") - style.MaxWidth = tmpf * style.FontSize; - else if (unit == "pt") - style.FontSize = tmpf / 0.75f; - else - style.MaxWidth = tmpf; - } - } - else - if (it->first == "max-height") - { - std::string unit; - if (getCssLength(tmpf, unit, it->second.c_str())) - { - if (unit == "rem") - style.MaxHeight = tmpf * _StyleDefault.FontSize; - else if (unit == "em") - style.MaxHeight = tmpf * style.FontSize; - else if (unit == "pt") - style.FontSize = tmpf / 0.75f; - else - style.MaxHeight = tmpf; - } - } - else - if (it->first == "-ryzom-modulate-color") - { - bool b; - if (it->second == "inherit") - style.GlobalColor = current.GlobalColor; - else - if (fromString(it->second, b)) - style.GlobalColor = b; - } - else - if (it->first == "background-color") - { - if (it->second == "inherit") - style.BackgroundColor = current.BackgroundColor; - else - scanHTMLColor(it->second.c_str(), style.BackgroundColor); - } - else - if (it->first == "-ryzom-background-color-over") - { - if (it->second == "inherit") - style.BackgroundColorOver = current.BackgroundColorOver; - else - scanHTMLColor(it->second.c_str(), style.BackgroundColorOver); - } - } - - // if outer element has underline set, then inner element cannot remove it - if (current.Underlined) - style.Underlined = current.Underlined; - - // if outer element has line-through set, then inner element cannot remove it - if (current.StrikeThrough) - style.StrikeThrough = current.StrikeThrough; - } - - // *************************************************************************** - void CGroupHTML::applyCssMinMax(sint32 &width, sint32 &height, sint32 minw, sint32 minh, sint32 maxw, sint32 maxh) - { - if (maxw <= 0) maxw = width; - if (maxh <= 0) maxh = height; - - maxw = std::max(minw, maxw); - maxh = std::max(minh, maxh); - - float ratio = (float) width / std::max(1, height); - if (width > maxw) - { - width = maxw; - height = std::max((sint32)(maxw /ratio), minh); - } - if (width < minw) - { - width = minw; - height = std::min((sint32)(minw / ratio), maxh); - } - if (height > maxh) - { - width = std::max((sint32)(maxh * ratio), minw); - height = maxh; - } - if (height < minh) - { - width = std::min((sint32)(minh * ratio), maxw); - height = minh; - } - if (width > maxw && height > maxh) - { - if (maxw/width <= maxh/height) - { - width = maxw; - height = std::max(minh, (sint32)(maxw / ratio)); - } - else - { - width = std::max(minw, (sint32)(maxh * ratio)); - height = maxh; - } - } - if (width < minw && height < minh) - { - if (minw / width <= minh / height) - { - width = std::min(maxw, (sint32)(minh * ratio)); - height = minh; - } - else - { - width = minw; - height = std::min(maxh, (sint32)(minw / ratio)); - } - } - if (width < minw && height > maxh) - { - width = minw; - height = maxh; - } - if (width > maxw && height < minh) - { - width = maxw; - height = minh; - } + _Style.reset(); + _Style.Root.TextColor = TextColor; + _Style.Root.FontSize = TextFontSize; + _Style.Root.BackgroundColor = BgColor; + _Style.Current = _Style.Root; } // *************************************************************************** diff --git a/code/nel/src/gui/libwww.cpp b/code/nel/src/gui/libwww.cpp index ca8920b14..50cac24bf 100644 --- a/code/nel/src/gui/libwww.cpp +++ b/code/nel/src/gui/libwww.cpp @@ -345,6 +345,368 @@ namespace NLGUI } } + static bool isHexa(char c) + { + return isdigit(c) || (tolower(c) >= 'a' && tolower(c) <= 'f'); + } + + static uint8 convertHexa(char c) + { + return (uint8) (tolower(c) - (isdigit(c) ? '0' : ('a' - 10))); + } + + // scan a color component, and return pointer to next position + static const char *scanColorComponent(const char *src, uint8 &intensity) + { + if (!src) return NULL; + if (!isHexa(*src)) return NULL; + uint8 value = convertHexa(*src++) << 4; + if (!isHexa(*src)) return NULL; + value += convertHexa(*src++); + intensity = value; + return src; + } + + static float hueToRgb(float m1, float m2, float h) + { + if (h < 0) h += 1.0f; + if (h > 1) h -= 1.0f; + if (h*6 < 1.0f) return m1 + (m2 - m1)*h*6; + if (h*2 < 1.0f) return m2; + if (h*3 < 2.0f) return m1 + (m2 - m1) * (2.0f/3.0f - h)*6; + return m1; + } + + static void hslToRgb(float h, float s, float l, CRGBA &result) + { + float m1, m2; + if (l <= 0.5f) + m2 = l * (s + 1.0f); + else + m2 = l + s - l * s; + m1 = l*2 - m2; + + result.R = 255 * hueToRgb(m1, m2, h + 1.0f/3.0f); + result.G = 255 * hueToRgb(m1, m2, h); + result.B = 255 * hueToRgb(m1, m2, h - 1.0f/3.0f); + result.A = 255; + } + + class CNameToCol + { + public: + const char *Name; + CRGBA Color; + CNameToCol(const char *name, CRGBA color) : Name(name), Color(color) {} + }; + + static CNameToCol htmlColorNameToRGBA[] = + { + CNameToCol("AliceBlue", CRGBA(0xF0, 0xF8, 0xFF)), + CNameToCol("AntiqueWhite", CRGBA(0xFA, 0xEB, 0xD7)), + CNameToCol("Aqua", CRGBA(0x00, 0xFF, 0xFF)), + CNameToCol("Aquamarine", CRGBA(0x7F, 0xFF, 0xD4)), + CNameToCol("Azure", CRGBA(0xF0, 0xFF, 0xFF)), + CNameToCol("Beige", CRGBA(0xF5, 0xF5, 0xDC)), + CNameToCol("Bisque", CRGBA(0xFF, 0xE4, 0xC4)), + CNameToCol("Black", CRGBA(0x00, 0x00, 0x00)), + CNameToCol("BlanchedAlmond", CRGBA(0xFF, 0xEB, 0xCD)), + CNameToCol("Blue", CRGBA(0x00, 0x00, 0xFF)), + CNameToCol("BlueViolet", CRGBA(0x8A, 0x2B, 0xE2)), + CNameToCol("Brown", CRGBA(0xA5, 0x2A, 0x2A)), + CNameToCol("BurlyWood", CRGBA(0xDE, 0xB8, 0x87)), + CNameToCol("CadetBlue", CRGBA(0x5F, 0x9E, 0xA0)), + CNameToCol("Chartreuse", CRGBA(0x7F, 0xFF, 0x00)), + CNameToCol("Chocolate", CRGBA(0xD2, 0x69, 0x1E)), + CNameToCol("Coral", CRGBA(0xFF, 0x7F, 0x50)), + CNameToCol("CornflowerBlue", CRGBA(0x64, 0x95, 0xED)), + CNameToCol("Cornsilk", CRGBA(0xFF, 0xF8, 0xDC)), + CNameToCol("Crimson", CRGBA(0xDC, 0x14, 0x3C)), + CNameToCol("Cyan", CRGBA(0x00, 0xFF, 0xFF)), + CNameToCol("DarkBlue", CRGBA(0x00, 0x00, 0x8B)), + CNameToCol("DarkCyan", CRGBA(0x00, 0x8B, 0x8B)), + CNameToCol("DarkGoldenRod", CRGBA(0xB8, 0x86, 0x0B)), + CNameToCol("DarkGray", CRGBA(0xA9, 0xA9, 0xA9)), + CNameToCol("DarkGreen", CRGBA(0x00, 0x64, 0x00)), + CNameToCol("DarkKhaki", CRGBA(0xBD, 0xB7, 0x6B)), + CNameToCol("DarkMagenta", CRGBA(0x8B, 0x00, 0x8B)), + CNameToCol("DarkOliveGreen", CRGBA(0x55, 0x6B, 0x2F)), + CNameToCol("Darkorange", CRGBA(0xFF, 0x8C, 0x00)), + CNameToCol("DarkOrchid", CRGBA(0x99, 0x32, 0xCC)), + CNameToCol("DarkRed", CRGBA(0x8B, 0x00, 0x00)), + CNameToCol("DarkSalmon", CRGBA(0xE9, 0x96, 0x7A)), + CNameToCol("DarkSeaGreen", CRGBA(0x8F, 0xBC, 0x8F)), + CNameToCol("DarkSlateBlue", CRGBA(0x48, 0x3D, 0x8B)), + CNameToCol("DarkSlateGray", CRGBA(0x2F, 0x4F, 0x4F)), + CNameToCol("DarkTurquoise", CRGBA(0x00, 0xCE, 0xD1)), + CNameToCol("DarkViolet", CRGBA(0x94, 0x00, 0xD3)), + CNameToCol("DeepPink", CRGBA(0xFF, 0x14, 0x93)), + CNameToCol("DeepSkyBlue", CRGBA(0x00, 0xBF, 0xFF)), + CNameToCol("DimGray", CRGBA(0x69, 0x69, 0x69)), + CNameToCol("DodgerBlue", CRGBA(0x1E, 0x90, 0xFF)), + CNameToCol("Feldspar", CRGBA(0xD1, 0x92, 0x75)), + CNameToCol("FireBrick", CRGBA(0xB2, 0x22, 0x22)), + CNameToCol("FloralWhite", CRGBA(0xFF, 0xFA, 0xF0)), + CNameToCol("ForestGreen", CRGBA(0x22, 0x8B, 0x22)), + CNameToCol("Fuchsia", CRGBA(0xFF, 0x00, 0xFF)), + CNameToCol("Gainsboro", CRGBA(0xDC, 0xDC, 0xDC)), + CNameToCol("GhostWhite", CRGBA(0xF8, 0xF8, 0xFF)), + CNameToCol("Gold", CRGBA(0xFF, 0xD7, 0x00)), + CNameToCol("GoldenRod", CRGBA(0xDA, 0xA5, 0x20)), + CNameToCol("Gray", CRGBA(0x80, 0x80, 0x80)), + CNameToCol("Green", CRGBA(0x00, 0x80, 0x00)), + CNameToCol("GreenYellow", CRGBA(0xAD, 0xFF, 0x2F)), + CNameToCol("HoneyDew", CRGBA(0xF0, 0xFF, 0xF0)), + CNameToCol("HotPink", CRGBA(0xFF, 0x69, 0xB4)), + CNameToCol("IndianRed ", CRGBA(0xCD, 0x5C, 0x5C)), + CNameToCol("Indigo ", CRGBA(0x4B, 0x00, 0x82)), + CNameToCol("Ivory", CRGBA(0xFF, 0xFF, 0xF0)), + CNameToCol("Khaki", CRGBA(0xF0, 0xE6, 0x8C)), + CNameToCol("Lavender", CRGBA(0xE6, 0xE6, 0xFA)), + CNameToCol("LavenderBlush", CRGBA(0xFF, 0xF0, 0xF5)), + CNameToCol("LawnGreen", CRGBA(0x7C, 0xFC, 0x00)), + CNameToCol("LemonChiffon", CRGBA(0xFF, 0xFA, 0xCD)), + CNameToCol("LightBlue", CRGBA(0xAD, 0xD8, 0xE6)), + CNameToCol("LightCoral", CRGBA(0xF0, 0x80, 0x80)), + CNameToCol("LightCyan", CRGBA(0xE0, 0xFF, 0xFF)), + CNameToCol("LightGoldenRodYellow", CRGBA(0xFA, 0xFA, 0xD2)), + CNameToCol("LightGrey", CRGBA(0xD3, 0xD3, 0xD3)), + CNameToCol("LightGreen", CRGBA(0x90, 0xEE, 0x90)), + CNameToCol("LightPink", CRGBA(0xFF, 0xB6, 0xC1)), + CNameToCol("LightSalmon", CRGBA(0xFF, 0xA0, 0x7A)), + CNameToCol("LightSeaGreen", CRGBA(0x20, 0xB2, 0xAA)), + CNameToCol("LightSkyBlue", CRGBA(0x87, 0xCE, 0xFA)), + CNameToCol("LightSlateBlue", CRGBA(0x84, 0x70, 0xFF)), + CNameToCol("LightSlateGray", CRGBA(0x77, 0x88, 0x99)), + CNameToCol("LightSteelBlue", CRGBA(0xB0, 0xC4, 0xDE)), + CNameToCol("LightYellow", CRGBA(0xFF, 0xFF, 0xE0)), + CNameToCol("Lime", CRGBA(0x00, 0xFF, 0x00)), + CNameToCol("LimeGreen", CRGBA(0x32, 0xCD, 0x32)), + CNameToCol("Linen", CRGBA(0xFA, 0xF0, 0xE6)), + CNameToCol("Magenta", CRGBA(0xFF, 0x00, 0xFF)), + CNameToCol("Maroon", CRGBA(0x80, 0x00, 0x00)), + CNameToCol("MediumAquaMarine", CRGBA(0x66, 0xCD, 0xAA)), + CNameToCol("MediumBlue", CRGBA(0x00, 0x00, 0xCD)), + CNameToCol("MediumOrchid", CRGBA(0xBA, 0x55, 0xD3)), + CNameToCol("MediumPurple", CRGBA(0x93, 0x70, 0xD8)), + CNameToCol("MediumSeaGreen", CRGBA(0x3C, 0xB3, 0x71)), + CNameToCol("MediumSlateBlue", CRGBA(0x7B, 0x68, 0xEE)), + CNameToCol("MediumSpringGreen", CRGBA(0x00, 0xFA, 0x9A)), + CNameToCol("MediumTurquoise", CRGBA(0x48, 0xD1, 0xCC)), + CNameToCol("MediumVioletRed", CRGBA(0xC7, 0x15, 0x85)), + CNameToCol("MidnightBlue", CRGBA(0x19, 0x19, 0x70)), + CNameToCol("MintCream", CRGBA(0xF5, 0xFF, 0xFA)), + CNameToCol("MistyRose", CRGBA(0xFF, 0xE4, 0xE1)), + CNameToCol("Moccasin", CRGBA(0xFF, 0xE4, 0xB5)), + CNameToCol("NavajoWhite", CRGBA(0xFF, 0xDE, 0xAD)), + CNameToCol("Navy", CRGBA(0x00, 0x00, 0x80)), + CNameToCol("OldLace", CRGBA(0xFD, 0xF5, 0xE6)), + CNameToCol("Olive", CRGBA(0x80, 0x80, 0x00)), + CNameToCol("OliveDrab", CRGBA(0x6B, 0x8E, 0x23)), + CNameToCol("Orange", CRGBA(0xFF, 0xA5, 0x00)), + CNameToCol("OrangeRed", CRGBA(0xFF, 0x45, 0x00)), + CNameToCol("Orchid", CRGBA(0xDA, 0x70, 0xD6)), + CNameToCol("PaleGoldenRod", CRGBA(0xEE, 0xE8, 0xAA)), + CNameToCol("PaleGreen", CRGBA(0x98, 0xFB, 0x98)), + CNameToCol("PaleTurquoise", CRGBA(0xAF, 0xEE, 0xEE)), + CNameToCol("PaleVioletRed", CRGBA(0xD8, 0x70, 0x93)), + CNameToCol("PapayaWhip", CRGBA(0xFF, 0xEF, 0xD5)), + CNameToCol("PeachPuff", CRGBA(0xFF, 0xDA, 0xB9)), + CNameToCol("Peru", CRGBA(0xCD, 0x85, 0x3F)), + CNameToCol("Pink", CRGBA(0xFF, 0xC0, 0xCB)), + CNameToCol("Plum", CRGBA(0xDD, 0xA0, 0xDD)), + CNameToCol("PowderBlue", CRGBA(0xB0, 0xE0, 0xE6)), + CNameToCol("Purple", CRGBA(0x80, 0x00, 0x80)), + CNameToCol("Red", CRGBA(0xFF, 0x00, 0x00)), + CNameToCol("RosyBrown", CRGBA(0xBC, 0x8F, 0x8F)), + CNameToCol("RoyalBlue", CRGBA(0x41, 0x69, 0xE1)), + CNameToCol("SaddleBrown", CRGBA(0x8B, 0x45, 0x13)), + CNameToCol("Salmon", CRGBA(0xFA, 0x80, 0x72)), + CNameToCol("SandyBrown", CRGBA(0xF4, 0xA4, 0x60)), + CNameToCol("SeaGreen", CRGBA(0x2E, 0x8B, 0x57)), + CNameToCol("SeaShell", CRGBA(0xFF, 0xF5, 0xEE)), + CNameToCol("Sienna", CRGBA(0xA0, 0x52, 0x2D)), + CNameToCol("Silver", CRGBA(0xC0, 0xC0, 0xC0)), + CNameToCol("SkyBlue", CRGBA(0x87, 0xCE, 0xEB)), + CNameToCol("SlateBlue", CRGBA(0x6A, 0x5A, 0xCD)), + CNameToCol("SlateGray", CRGBA(0x70, 0x80, 0x90)), + CNameToCol("Snow", CRGBA(0xFF, 0xFA, 0xFA)), + CNameToCol("SpringGreen", CRGBA(0x00, 0xFF, 0x7F)), + CNameToCol("SteelBlue", CRGBA(0x46, 0x82, 0xB4)), + CNameToCol("Tan", CRGBA(0xD2, 0xB4, 0x8C)), + CNameToCol("Teal", CRGBA(0x00, 0x80, 0x80)), + CNameToCol("Thistle", CRGBA(0xD8, 0xBF, 0xD8)), + CNameToCol("Tomato", CRGBA(0xFF, 0x63, 0x47)), + CNameToCol("Turquoise", CRGBA(0x40, 0xE0, 0xD0)), + CNameToCol("Violet", CRGBA(0xEE, 0x82, 0xEE)), + CNameToCol("VioletRed", CRGBA(0xD0, 0x20, 0x90)), + CNameToCol("Wheat", CRGBA(0xF5, 0xDE, 0xB3)), + CNameToCol("White", CRGBA(0xFF, 0xFF, 0xFF)), + CNameToCol("WhiteSmoke", CRGBA(0xF5, 0xF5, 0xF5)), + CNameToCol("Yellow", CRGBA(0xFF, 0xFF, 0x00)), + CNameToCol("YellowGreen", CRGBA(0x9A, 0xCD, 0x32)) + }; + + // scan a color from a HTML form (#rrggbb format) + bool scanHTMLColor(const char *src, CRGBA &dest) + { + if (!src || *src == '\0') return false; + if (*src == '#') + { + ++src; + if (strlen(src) == 3 || strlen(src) == 4) + { + bool hasAlpha = (strlen(src) == 4); + // check RGB for valid hex + if (isHexa(src[0]) && isHexa(src[1]) && isHexa(src[2])) + { + // check optional A for valid hex + if (hasAlpha && !isHexa(src[3])) return false; + + dest.R = convertHexa(src[0]); + dest.G = convertHexa(src[1]); + dest.B = convertHexa(src[2]); + + dest.R = dest.R << 4 | dest.R; + dest.G = dest.G << 4 | dest.G; + dest.B = dest.B << 4 | dest.B; + + if (hasAlpha) + { + dest.A = convertHexa(src[3]); + dest.A = dest.A << 4 | dest.A; + } + else + dest.A = 255; + + return true; + } + + return false; + } + + CRGBA result; + src = scanColorComponent(src, result.R); if (!src) return false; + src = scanColorComponent(src, result.G); if (!src) return false; + src = scanColorComponent(src, result.B); if (!src) return false; + src = scanColorComponent(src, result.A); + if (!src) + { + // Alpha is optional + result.A = 255; + } + dest = result; + return true; + } + + if (strnicmp(src, "rgb(", 4) == 0 || strnicmp(src, "rgba(", 5) == 0) + { + src += 4; + if (*src == '(') src++; + + std::vector parts; + NLMISC::splitString(src, ",", parts); + if (parts.size() >= 3) + { + CRGBA result; + sint tmpv; + float tmpf; + + // R + if (getPercentage(tmpv, tmpf, parts[0].c_str())) tmpv = 255 * tmpf; + clamp(tmpv, 0, 255); + result.R = tmpv; + + // G + if (getPercentage(tmpv, tmpf, parts[1].c_str())) tmpv = 255 * tmpf; + clamp(tmpv, 0, 255); + result.G = tmpv; + + // B + if (getPercentage(tmpv, tmpf, parts[2].c_str())) tmpv = 255 * tmpf; + clamp(tmpv, 0, 255); + result.B = tmpv; + + // A + if (parts.size() == 4) + { + if (!fromString(parts[3], tmpf)) return false; + if (parts[3].find_first_of("%") != std::string::npos) + tmpf /= 100; + + tmpv = 255 * tmpf; + clamp(tmpv, 0, 255); + result.A = tmpv; + } + else + result.A = 255; + + dest = result; + return true; + } + + return false; + } + + if (strnicmp(src, "hsl(", 4) == 0 || strnicmp(src, "hsla(", 5) == 0) + { + src += 4; + if (*src == '(') src++; + + std::vector parts; + NLMISC::splitString(src, ",", parts); + if (parts.size() >= 3) + { + sint tmpv; + float h, s, l; + // hue + if (!fromString(parts[0], tmpv)) return false; + tmpv = ((tmpv % 360) + 360) % 360; + h = (float) tmpv / 360.0f; + + // saturation + if (!getPercentage(tmpv, s, parts[1].c_str())) return false; + clamp(s, 0.0f, 1.0f); + + // lightness + if (!getPercentage(tmpv, l, parts[2].c_str())) return false; + clamp(l, 0.0f, 1.0f); + + CRGBA result; + hslToRgb(h, s, l, result); + + // A + if (parts.size() == 4) + { + float tmpf; + if (!fromString(parts[3], tmpf)) return false; + if (parts[3].find_first_of("%") != std::string::npos) + tmpf /= 100; + clamp(tmpf, 0.0f, 1.0f); + result.A = 255 * tmpf; + } + + dest = result; + return true; + } + + return false; + } + + { + // slow but should suffice for now + for(uint k = 0; k < sizeofarray(htmlColorNameToRGBA); ++k) + { + if (nlstricmp(src, htmlColorNameToRGBA[k].Name) == 0) + { + dest = htmlColorNameToRGBA[k].Color; + return true; + } + } + return false; + } + } + // *************************************************************************** CRGBA getColor (const char *color) From aede4dbab7b9871772ed01ede1b361c2f6af174b Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 29 Apr 2019 15:03:55 +0300 Subject: [PATCH 213/303] Added: relative/absolute font size values for css --HG-- branch : develop --- code/nel/src/gui/css_style.cpp | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/code/nel/src/gui/css_style.cpp b/code/nel/src/gui/css_style.cpp index 9d4b665bb..35d28717e 100644 --- a/code/nel/src/gui/css_style.cpp +++ b/code/nel/src/gui/css_style.cpp @@ -114,6 +114,41 @@ namespace NLGUI { style.FontSize = current.FontSize; } + else if (it->second == "x-small") + { + style.FontSize = 10; // 62.5% + } + else if (it->second == "small") + { + style.FontSize = 13; // 80%; + } + else if (it->second == "medium") + { + style.FontSize = 16; // 100%; + } + else if (it->second == "large") + { + style.FontSize = 18; // 112.5% + } + else if (it->second == "x-large") + { + style.FontSize = 24; // 150% + } + else if (it->second == "xx-large") + { + style.FontSize = 32; // 200%; + } + else if (it->second == "smaller") + { + if (style.FontSize < 5) + style.FontSize = 3; + else + style.FontSize -= 2; + } + else if (it->second == "larger") + { + style.FontSize += 2; + } else { std::string unit; From 9587e9bcefbe4182d542e1e163ade517b25da705 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 29 Apr 2019 15:03:55 +0300 Subject: [PATCH 214/303] Added: transparent, currentcolor values for background-color --HG-- branch : develop --- code/nel/src/gui/css_style.cpp | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/code/nel/src/gui/css_style.cpp b/code/nel/src/gui/css_style.cpp index 35d28717e..8fc1207d2 100644 --- a/code/nel/src/gui/css_style.cpp +++ b/code/nel/src/gui/css_style.cpp @@ -95,8 +95,21 @@ namespace NLGUI TStyle::iterator it; // first pass: get font-size for 'em' sizes + // get TextColor value used as 'currentcolor' for (it=styles.begin(); it != styles.end(); ++it) { + if (it->first == "color") + { + if (it->second == "inherit") + { + style.TextColor = current.TextColor; + } + else + { + scanHTMLColor(it->second.c_str(), style.TextColor); + } + } + else if (it->first == "font") { if (it->second == "inherit") @@ -237,12 +250,6 @@ namespace NLGUI style.FontWeight = weight; } else - if (it->first == "color") - if (it->second == "inherit") - style.TextColor = current.TextColor; - else - scanHTMLColor(it->second.c_str(), style.TextColor); - else if (it->first == "text-decoration" || it->first == "text-decoration-line") { std::string prop(toLower(it->second)); @@ -437,6 +444,10 @@ namespace NLGUI { if (it->second == "inherit") style.BackgroundColor = current.BackgroundColor; + else if (it->second == "transparent") + style.BackgroundColor = CRGBA(0, 0, 0, 0); + else if (it->second == "currentcolor") + style.BackgroundColorOver = style.TextColor; else scanHTMLColor(it->second.c_str(), style.BackgroundColor); } @@ -445,6 +456,10 @@ namespace NLGUI { if (it->second == "inherit") style.BackgroundColorOver = current.BackgroundColorOver; + else if (it->second == "transparent") + style.BackgroundColorOver = CRGBA(0, 0, 0, 0); + else if (it->second == "currentcolor") + style.BackgroundColorOver = style.TextColor; else scanHTMLColor(it->second.c_str(), style.BackgroundColorOver); } From fb54672815daa322bcb8b76aed120ef3decb8769 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 5 Apr 2019 21:57:42 +0300 Subject: [PATCH 215/303] Changed: Implement HTML renderer with CSS styling --HG-- branch : develop --- code/nel/include/nel/gui/css_parser.h | 113 +- code/nel/include/nel/gui/css_selector.h | 107 + code/nel/include/nel/gui/css_style.h | 90 +- code/nel/include/nel/gui/group_html.h | 125 +- code/nel/include/nel/gui/html_element.h | 86 + code/nel/include/nel/gui/html_parser.h | 20 +- code/nel/include/nel/gui/libwww.h | 3 + code/nel/include/nel/misc/common.h | 11 + code/nel/src/gui/css_parser.cpp | 658 +++++ code/nel/src/gui/css_selector.cpp | 314 +++ code/nel/src/gui/css_style.cpp | 494 +++- code/nel/src/gui/group_html.cpp | 2438 +++++++++++++++-- code/nel/src/gui/html_element.cpp | 168 ++ code/nel/src/gui/html_parser.cpp | 188 +- code/nel/src/gui/libwww.cpp | 10 + code/nel/src/gui/libwww_types.cpp | 2 + .../src/interface_v3/group_quick_help.cpp | 58 +- .../src/interface_v3/group_quick_help.h | 3 +- 18 files changed, 4587 insertions(+), 301 deletions(-) create mode 100644 code/nel/include/nel/gui/css_selector.h create mode 100644 code/nel/include/nel/gui/html_element.h create mode 100644 code/nel/src/gui/css_selector.cpp create mode 100644 code/nel/src/gui/html_element.cpp diff --git a/code/nel/include/nel/gui/css_parser.h b/code/nel/include/nel/gui/css_parser.h index cb4cea62e..cfaf03caa 100644 --- a/code/nel/include/nel/gui/css_parser.h +++ b/code/nel/include/nel/gui/css_parser.h @@ -19,6 +19,7 @@ #include "nel/misc/types_nl.h" #include "nel/gui/css_style.h" +#include "nel/gui/css_selector.h" namespace NLGUI { @@ -31,8 +32,118 @@ namespace NLGUI public: // parse style declaration, eg "color: red; font-size: 10px;" static TStyle parseDecls(const std::string &styleString); - }; + // parse css stylesheet + void parseStylesheet(const std::string &cssString, std::vector &rules); + + private: + // stylesheet currently parsed + ucstring _Style; + // keep track of current position in _Style + size_t _Position; + + std::vector _Rules; + + private: + // @media ( .. ) { .. } + void readAtRule(); + + // a#id.class[attr=val] { .. } + void readRule(); + + // move past whitespace + void skipWhitespace(); + + // skip valid IDENT + bool skipIdentifier(); + + // skip over {}, (), or [] block + void skipBlock(); + + // skip over string quoted with ' or " + void skipString(); + + // backslash escape + void escape(); + + // normalize newline chars and remove comments + void preprocess(); + + // parse selectors + combinators + std::vector parse_selector(const ucstring &sel, std::string &pseudoElement) const; + + // parse selector and style + void parseRule(const ucstring &selectorString, const ucstring &styleString); + + inline bool is_eof() const + { + return _Position >= _Style.size(); + } + + inline bool is_whitespace(ucchar ch) const + { + return (ch == (ucchar)' ' || ch == (ucchar)'\t' || ch == (ucchar)'\n'); + } + + inline bool is_hex(ucchar ch) const + { + return ((ch >= (ucchar)'0' && ch <= (ucchar)'9') || + (ch >= (ucchar)'a' && ch <= (ucchar)'f') || + (ch >= (ucchar)'A' && ch <= (ucchar)'F')); + } + + inline bool maybe_escape() const + { + // escaping newline (\n) only allowed inside strings + return (_Style.size() - _Position) >= 1 && _Style[_Position] == (ucchar)'\\' && _Style[_Position+1] != '\n'; + } + + inline bool is_quote(ucchar ch) const + { + return ch== (ucchar)'"' || ch == (ucchar)'\''; + } + + inline bool is_block_open(ucchar ch) const + { + return ch == (ucchar)'{' || ch == (ucchar)'[' || ch == (ucchar)'('; + } + + inline bool is_block_close(ucchar ch, ucchar open) const + { + return ((open == '{' && ch == (ucchar)'}') || + (open == '[' && ch == (ucchar)']') || + (open == '(' && ch == (ucchar)')')); + } + + inline bool is_comment_open() const + { + if (_Position+1 > _Style.size()) + return false; + + return _Style[_Position] == (ucchar)'/' && _Style[_Position+1] == (ucchar)'*'; + } + + inline bool is_nonascii(ucchar ch) const + { + return ch >= 0x80 /*&& ch <= 255*/; + } + + inline bool is_alpha(ucchar ch) const + { + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); + } + + inline bool is_digit(ucchar ch) const + { + return ch >= '0' && ch <= '9'; + } + + inline bool is_nmchar(ucchar ch) const + { + // checking escape here does not check if next char is '\n' or not + return ch == '_' || ch == '-' || is_alpha(ch) || is_digit(ch) || is_nonascii(ch) || ch == '\\'/*is_escape(ch)*/; + } + }; }//namespace #endif // CL_CSS_PARSER_H diff --git a/code/nel/include/nel/gui/css_selector.h b/code/nel/include/nel/gui/css_selector.h new file mode 100644 index 000000000..84b039089 --- /dev/null +++ b/code/nel/include/nel/gui/css_selector.h @@ -0,0 +1,107 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CL_CSS_SELECTOR_H +#define CL_CSS_SELECTOR_H + +#include "nel/misc/types_nl.h" + +namespace NLGUI +{ + class CHtmlElement; + + /** + * \brief CSS selector + * \date 2019-03-15 10:50 GMT + * \author Meelis Mägi (Nimetu) + */ + class CCssSelector + { + public: + enum ECombinator { + NONE = 0, + GENERAL_CHILD, + ADJACENT_SIBLING, + GENERAL_SIBLING, + CHILD_OF + }; + + struct SAttribute { + std::string key; + std::string value; + char op; // =, ~, |, ^, $, * + SAttribute(const std::string &k, const std::string &v, char o) + :key(k),value(v),op(o) + {} + }; + + std::string Element; + std::string Id; + std::vector Class; + std::vector Attr; + std::vector PseudoClass; + + // css combinator or \0 missing (first element) + char Combinator; + + public: + // TODO: rewrite for ECombinator enum + CCssSelector(std::string elm="", std::string id="", std::string cls="", char comb = '\0'); + + // helper for sorting + uint32 specificity() const; + + // set classes used, eg 'class1 class2' + void setClass(const std::string &cls); + + // add attribute to selector + // ' ' op means 'key exists, ignore value' + void addAttribute(const std::string &key, const std::string &val = "", char op = ' '); + + // add pseudo class to selector, eg 'first-child' + void addPseudoClass(const std::string &key); + + // true if no rules have been defined + bool empty() const + { + return Element.empty() && Id.empty() && Class.empty() && Attr.empty() && PseudoClass.empty(); + } + + // Test current selector to html DOM element + // NOTE: Does not check combinator + bool match(const CHtmlElement &elm) const; + + private: + bool matchClass(const CHtmlElement &elm) const; + bool matchAttributes(const CHtmlElement &elm) const; + bool matchPseudoClass(const CHtmlElement &elm) const; + + // match An+B rule to child index (1 based) + bool matchNth(sint childNr, sint a, sint b) const; + + // parse nth-child string to 'a' and 'b' components + // :nth-child(odd) + // :nth-child(even) + // :nth-child(An+B) + // :nth-child(-An+b) + void parseNth(const std::string &pseudo, sint &a, sint &b) const; + + }; + +}//namespace + +#endif // CL_CSS_SELECTOR_H + diff --git a/code/nel/include/nel/gui/css_style.h b/code/nel/include/nel/gui/css_style.h index 2a854a6d9..dea4a1f43 100644 --- a/code/nel/include/nel/gui/css_style.h +++ b/code/nel/include/nel/gui/css_style.h @@ -19,9 +19,12 @@ #include "nel/misc/types_nl.h" #include "nel/misc/rgba.h" +#include "nel/gui/css_selector.h" namespace NLGUI { + class CHtmlElement; + typedef std::map TStyle; /** @@ -44,7 +47,7 @@ namespace NLGUI sint32 X; sint32 Y; NLMISC::CRGBA Color; - }; + }; public: CStyleParams () : FontFamily(""), TextColor(255,255,255,255), TextShadow() { @@ -62,6 +65,19 @@ namespace NLGUI BackgroundColor=NLMISC::CRGBA::Black; BackgroundColorOver=NLMISC::CRGBA::Black; } + + bool hasStyle(const std::string &key) const + { + return StyleRules.find(key) != StyleRules.end(); + } + + std::string getStyle(const std::string &key) const + { + TStyle::const_iterator it = StyleRules.find(key); + return (it != StyleRules.end() ? it->second : ""); + } + + public: uint FontSize; uint FontWeight; bool FontOblique; @@ -78,11 +94,26 @@ namespace NLGUI sint32 BorderWidth; NLMISC::CRGBA BackgroundColor; NLMISC::CRGBA BackgroundColorOver; + + std::string WhiteSpace; + std::string TextAlign; + std::string VerticalAlign; + + TStyle StyleRules; }; class CCssStyle { public: + struct SStyleRule { + std::vector Selector; + TStyle Properties; + // pseudo element like ':before' + std::string PseudoElement; + + // returns selector specificity + uint specificity() const; + }; // 'browser' style, overwriten with '' CStyleParams Root; @@ -90,18 +121,37 @@ namespace NLGUI // current element style CStyleParams Current; + // known style rules sorted by specificity + std::vector _StyleRules; + private: std::vector _StyleStack; - // test if str is one of "thin/medium/thick" and return its pixel value + // test if str is one of "thin/medium/thick" and return its pixel value bool scanCssLength(const std::string& str, uint32 &px) const; // read style attribute void getStyleParams(const std::string &styleString, CStyleParams &style, const CStyleParams ¤t) const; + void getStyleParams(const TStyle &styleRules, CStyleParams &style, const CStyleParams ¤t) const; + + // merge src into dest by overwriting key in dest + void merge(TStyle &dst, const TStyle &src) const; + + // match selector to dom path + bool match(const std::vector &selector, const CHtmlElement &elm) const; + + // parse 'background' into 'background-color', 'background-image', etc + void parseBackgroundShorthand(const std::string &value, CStyleParams &style) const; public: void reset(); + // parse tag or css file content + void parseStylesheet(const std::string &styleString); + + // set element style from matching css rules + void getStyleFor(CHtmlElement &elm) const; + inline uint getFontSizeSmaller() const { if (Current.FontSize < 5) @@ -109,15 +159,29 @@ namespace NLGUI return Current.FontSize-2; } + sint styleStackIndex = 0; + inline void pushStyle() { + styleStackIndex++; _StyleStack.push_back(Current); + + Current.Width=-1; + Current.Height=-1; + Current.MaxWidth=-1; + Current.MaxHeight=-1; + Current.BorderWidth=1; + + Current.StyleRules.clear(); } inline void popStyle() { + styleStackIndex--; if (_StyleStack.empty()) + { Current = Root; + } else { Current = _StyleStack.back(); @@ -125,16 +189,32 @@ namespace NLGUI } } - // apply style string to this.Root + // apply style to this.Root void applyRootStyle(const std::string &styleString); + void applyRootStyle(const TStyle &styleRules); - // apply style string to this.Current + // apply style to this.Current void applyStyle(const std::string &styleString); + void applyStyle(const TStyle &styleRules); void applyCssMinMax(sint32 &width, sint32 &height, sint32 minw=0, sint32 minh=0, sint32 maxw=0, sint32 maxh=0) const; - }; + // check if current style property matches value + bool checkStyle(const std::string &key, const std::string &val) const + { + return Current.hasStyle(key) && Current.getStyle(key) == val; + } + bool hasStyle(const std::string &key) const + { + return Current.hasStyle(key); + } + + std::string getStyle(const std::string &key) const + { + return Current.getStyle(key); + } + }; }//namespace #endif // CL_CSS_STYLE_H diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index d8935f431..6a8760533 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -24,6 +24,7 @@ #include "nel/gui/ctrl_button.h" #include "nel/gui/group_table.h" #include "nel/gui/libwww_types.h" +#include "nel/gui/html_element.h" #include "nel/gui/css_style.h" // forward declaration @@ -76,7 +77,7 @@ namespace NLGUI static SWebOptions options; // ImageDownload system - enum TDataType {ImgType= 0, BnpType}; + enum TDataType {ImgType= 0, BnpType, StylesheetType}; enum TImageType {NormalImage=0, OverImage}; // Constructor @@ -97,6 +98,9 @@ namespace NLGUI // Browse virtual void browse (const char *url); + // load css from local file and insert into active stylesheet collection + void parseStylesheetFile(const std::string &fname); + // parse html string using libxml2 parser bool parseHtml(const std::string &htmlString); @@ -273,16 +277,10 @@ namespace NLGUI virtual void addText (const char * buf, int len); // A new begin HTML element has been parsed ( for exemple) - virtual void beginElement (uint element_number, const std::vector &present, const std::vector &value); + virtual void beginElement(CHtmlElement &elm); // A new end HTML element has been parsed ( for exemple) - virtual void endElement (uint element_number); - - // A new begin unparsed element has been found - virtual void beginUnparsedElement(const char *buffer, int length); - - // A new end unparsed element has been found - virtual void endUnparsedElement(const char *buffer, int length); + virtual void endElement(CHtmlElement &elm); // Add GET params to the url virtual void addHTTPGetParams (std::string &url, bool trustedDomain); @@ -296,6 +294,9 @@ namespace NLGUI // Get Home URL virtual std::string home(); + // parse dom node and all child nodes recursively + void renderDOM(CHtmlElement &elm); + // Clear style stack and restore default style void resetCssStyle(); @@ -326,7 +327,7 @@ namespace NLGUI void addString(const ucstring &str); // Add an image in the current paragraph - void addImage(const std::string &id, const char *image, bool reloadImg=false, const CStyleParams &style = CStyleParams()); + void addImage(const std::string &id, const std::string &img, bool reloadImg=false, const CStyleParams &style = CStyleParams()); // Add a text area in the current paragraph CInterfaceGroup *addTextArea (const std::string &templateName, const char *name, uint rows, uint cols, bool multiLine, const ucstring &content, uint maxlength); @@ -365,6 +366,14 @@ namespace NLGUI // Current URL std::string _DocumentUrl; std::string _DocumentDomain; + std::string _DocumentHtml; // not updated, only set by first render + // If true, then render _DocumentHtml on next update (replaces content) + bool _RenderNextTime; + // true if renderer is waiting for css files to finish downloading (link rel=stylesheet) + bool _WaitingForStylesheet; + // list of css file urls that are queued up for download + std::vector _StylesheetQueue; + // Valid base href was found bool _IgnoreBaseUrlTag; // Fragment from loading url @@ -484,6 +493,11 @@ namespace NLGUI // Keep track of current element style CCssStyle _Style; + CHtmlElement _HtmlDOM; + CHtmlElement *_CurrentHTMLElement; + // Backup of CurrentHTMLElement->nextSibling before ::beginElement() is called + // for luaParseHtml() to insert nodes into right place in right order + CHtmlElement *_CurrentHTMLNextSibling; // Current link std::vector _Link; @@ -722,6 +736,12 @@ namespace NLGUI private: friend class CHtmlParser; + // TODO: beginElement is overwritten in client quick help class, merge it here? + void beginElementDeprecated(uint element_number, const std::vector &present, const std::vector &value); + void endElementDeprecated(uint element_number); + + // move src->Children into CurrentHtmlElement.parent.children element + void spliceFragment(std::list::iterator src); // decode all HTML entities static ucstring decodeHTMLEntities(const ucstring &str); @@ -764,6 +784,8 @@ namespace NLGUI int RunningCurls; bool startCurlDownload(CDataDownload &download); + void finishCurlDownload(CDataDownload &download); + void pumpCurlDownloads(); void initImageDownload(); void checkImageDownload(); @@ -782,11 +804,94 @@ namespace NLGUI bool addBnpDownload(std::string url, const std::string &action, const std::string &script, const std::string &md5sum); std::string localBnpName(const std::string &url); + // add css file from to download queue + void addStylesheetDownload(std::vector links); + void releaseDownloads(); void checkDownloads(); // HtmlType download finished void htmlDownloadFinished(const std::string &content, const std::string &type, long code); + + // stylesheet finished downloading. if local file does not exist, then it failed (404) + void cssDownloadFinished(const std::string &url, const std::string &local); + + // read common table/tr/td parameters and push them to _CellParams + void getCellsParameters(const CHtmlElement &elm, bool inherit); + + // render _HtmlDOM + void renderDocument(); + + // :before, :after rendering + void renderPseudoElement(const std::string &pseudo, const CHtmlElement &elm); + + // HTML elements + void htmlA(const CHtmlElement &elm); + void htmlAend(const CHtmlElement &elm); + void htmlBASE(const CHtmlElement &elm); + void htmlBODY(const CHtmlElement &elm); + void htmlBR(const CHtmlElement &elm); + void htmlDD(const CHtmlElement &elm); + void htmlDDend(const CHtmlElement &elm); + //void htmlDEL(const CHtmlElement &elm); + void htmlDIV(const CHtmlElement &elm); + void htmlDIVend(const CHtmlElement &elm); + void htmlDL(const CHtmlElement &elm); + void htmlDLend(const CHtmlElement &elm); + void htmlDT(const CHtmlElement &elm); + void htmlDTend(const CHtmlElement &elm); + //void htmlEM(const CHtmlElement &elm); + void htmlFONT(const CHtmlElement &elm); + void htmlFORM(const CHtmlElement &elm); + void htmlH(const CHtmlElement &elm); + void htmlHend(const CHtmlElement &elm); + void htmlHEAD(const CHtmlElement &elm); + void htmlHEADend(const CHtmlElement &elm); + void htmlHR(const CHtmlElement &elm); + void htmlHTML(const CHtmlElement &elm); + void htmlI(const CHtmlElement &elm); + void htmlIend(const CHtmlElement &elm); + void htmlIMG(const CHtmlElement &elm); + void htmlINPUT(const CHtmlElement &elm); + void htmlLI(const CHtmlElement &elm); + void htmlLIend(const CHtmlElement &elm); + void htmlLUA(const CHtmlElement &elm); + void htmlLUAend(const CHtmlElement &elm); + void htmlMETA(const CHtmlElement &elm); + void htmlOBJECT(const CHtmlElement &elm); + void htmlOBJECTend(const CHtmlElement &elm); + void htmlOL(const CHtmlElement &elm); + void htmlOLend(const CHtmlElement &elm); + void htmlOPTION(const CHtmlElement &elm); + void htmlOPTIONend(const CHtmlElement &elm); + void htmlP(const CHtmlElement &elm); + void htmlPend(const CHtmlElement &elm); + void htmlPRE(const CHtmlElement &elm); + void htmlPREend(const CHtmlElement &elm); + void htmlSCRIPT(const CHtmlElement &elm); + void htmlSCRIPTend(const CHtmlElement &elm); + void htmlSELECT(const CHtmlElement &elm); + void htmlSELECTend(const CHtmlElement &elm); + //void htmlSMALL(const CHtmlElement &elm); + //void htmlSPAN(const CHtmlElement &elm); + //void htmlSTRONG(const CHtmlElement &elm); + void htmlSTYLE(const CHtmlElement &elm); + void htmlSTYLEend(const CHtmlElement &elm); + void htmlTABLE(const CHtmlElement &elm); + void htmlTABLEend(const CHtmlElement &elm); + void htmlTD(const CHtmlElement &elm); + void htmlTDend(const CHtmlElement &elm); + void htmlTEXTAREA(const CHtmlElement &elm); + void htmlTEXTAREAend(const CHtmlElement &elm); + void htmlTH(const CHtmlElement &elm); + void htmlTHend(const CHtmlElement &elm); + void htmlTITLE(const CHtmlElement &elm); + void htmlTITLEend(const CHtmlElement &elm); + void htmlTR(const CHtmlElement &elm); + void htmlTRend(const CHtmlElement &elm); + //void htmlU(const CHtmlElement &elm); + void htmlUL(const CHtmlElement &elm); + void htmlULend(const CHtmlElement &elm); }; // adapter group that store y offset for inputs inside an html form diff --git a/code/nel/include/nel/gui/html_element.h b/code/nel/include/nel/gui/html_element.h new file mode 100644 index 000000000..bac681c1c --- /dev/null +++ b/code/nel/include/nel/gui/html_element.h @@ -0,0 +1,86 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CL_HTML_ELEMENT_H +#define CL_HTML_ELEMENT_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/css_style.h" + +namespace NLGUI +{ + /** + * \brief HTML element + * \date 2019-04-25 18:23 GMT + * \author Meelis Mägi (Nimetu) + */ + class CHtmlElement + { + public: + enum ENodeType { + NONE = 0, + ELEMENT_NODE = 1, + TEXT_NODE = 3, + }; + + uint ID; // libwww element enum + ENodeType Type; + std::string Value; // text node value or element node name + std::map Attributes; + std::list Children; + + // class names for css matching + std::set ClassNames; + + // defined style and :before/:after pseudo elements + TStyle Style; + TStyle StyleBefore; + TStyle StyleAfter; + + // hierarchy + CHtmlElement *parent; + CHtmlElement *previousSibling; + CHtmlElement *nextSibling; + + // n'th ELEMENT_NODE in parent.Children, for :nth-child() rules + uint childIndex; + + CHtmlElement(ENodeType type = NONE, std::string value = ""); + + // returns true if rhs is same pointer + friend bool operator==(const CHtmlElement &lhs, const CHtmlElement &rhs) + { + return &lhs == &rhs; + } + + bool hasAttribute(const std::string &key) const; + + bool hasNonEmptyAttribute(const std::string &key) const; + + std::string getAttribute(const std::string &key) const; + + bool hasClass(const std::string &key) const; + + // update Children index/parent/next/prevSibling pointers + void reindexChilds(); + + // debug + std::string toString(bool tree = false, uint depth = 0) const; + }; +} + +#endif + diff --git a/code/nel/include/nel/gui/html_parser.h b/code/nel/include/nel/gui/html_parser.h index 132c4ac88..760640234 100644 --- a/code/nel/include/nel/gui/html_parser.h +++ b/code/nel/include/nel/gui/html_parser.h @@ -21,7 +21,7 @@ namespace NLGUI { - class CGroupHTML; + class CHtmlElement; /** * \brief HTML parsing @@ -31,21 +31,21 @@ namespace NLGUI class CHtmlParser { public: - CHtmlParser(CGroupHTML *group) : _GroupHtml(group) - {} + bool parseHtml(std::string htmlString) const; - bool parseHtml(std::string htmlString); + // parse html string into DOM, extract + bool useStyle = true; + if (elm.hasAttribute("media")) + { + std::string media = trim(toLower(elm.Attributes["media"])); + useStyle = media.empty() || media.find("all") != std::string::npos || media.find("screen") != std::string::npos; + + //