From 32a144a2827ce13472956681be2d7d35e71b8618 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Tue, 14 Oct 2014 23:45:08 +0200 Subject: [PATCH 01/87] Shadow should not be taken into account for font height, breaks vertical centering --- 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 815007723..a70194c7b 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -2547,8 +2547,8 @@ namespace NLGUI // Letter size UTextContext::CStringInfo si = TextContext->getStringInfo(ucstring("|")); // for now we can't now that directly from UTextContext - _FontHeight = (uint) si.StringHeight + (_Shadow?(_ShadowOutline?2:1):0); - _FontLegHeight = (uint) si.StringLine + (_Shadow?(_ShadowOutline?2:1):0); + _FontHeight = (uint) si.StringHeight; // + (_Shadow?(_ShadowOutline?2:1):0); + _FontLegHeight = (uint) si.StringLine; // + (_Shadow?(_ShadowOutline?2:1):0); // Space width si = TextContext->getStringInfo(ucstring(" ")); From de026fe48cf73990e8d8b8fb734f37fd1e514d04 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Tue, 14 Oct 2014 23:45:08 +0200 Subject: [PATCH 02/87] Don't use I18N when the required ui prefix is not in the tooltip text (convention actually dictates uitt as tooltip prefix) --- 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 a70194c7b..db069a29d 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -2834,7 +2834,8 @@ namespace NLGUI pTooltip->setId(_Id+"_tt"+toString(i)); pTooltip->setAvoidResizeParent(avoidResizeParent()); pTooltip->setRenderLayer(getRenderLayer()); - pTooltip->setDefaultContextHelp(CI18N::get(tempTooltips[i].toString())); + bool isI18N = tempTooltips[i].size() >= 2 && tempTooltips[i][0] == 'u' && tempTooltips[i][1] == 'i'; + pTooltip->setDefaultContextHelp(isI18N ? CI18N::get(tempTooltips[i].toString()) : tempTooltips[i]); pTooltip->setParentPos(this); pTooltip->setParentPosRef(Hotspot_BR); pTooltip->setPosRef(Hotspot_BR); From dc17e72ad3b386d23dcb61ba6693d0c0a9a00fba Mon Sep 17 00:00:00 2001 From: kaetemi Date: Thu, 16 Oct 2014 02:00:45 +0200 Subject: [PATCH 03/87] Higher quality outline, visual difference is relevant only for black --- code/nel/include/nel/3d/text_context.h | 85 ++++++++++++++++++++------ 1 file changed, 65 insertions(+), 20 deletions(-) diff --git a/code/nel/include/nel/3d/text_context.h b/code/nel/include/nel/3d/text_context.h index 064a0ef64..8cf7ad7f0 100644 --- a/code/nel/include/nel/3d/text_context.h +++ b/code/nel/include/nel/3d/text_context.h @@ -147,12 +147,21 @@ public: CRGBA bkup = rCS.Color; rCS.Color = _ShadeColor; rCS.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); - rCS.render2D(*_Driver, x+_ShadeExtent, z-_ShadeExtent, _HotSpot, _ScaleX, _ScaleZ); if (_ShadeOutline) { - rCS.render2D(*_Driver, x-_ShadeExtent, z-_ShadeExtent, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x-_ShadeExtent, z+_ShadeExtent, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x+_ShadeExtent, z+_ShadeExtent, _HotSpot, _ScaleX, _ScaleZ); + 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); + } + else + { + rCS.render2D(*_Driver, x+_ShadeExtent, z-_ShadeExtent, _HotSpot, _ScaleX, _ScaleZ); } rCS.Color= bkup; } @@ -171,12 +180,21 @@ public: CRGBA bkup = rCS.Color; rCS.Color= _ShadeColor; rCS.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); - rCS.render2DClip(*_Driver, rdrBuffer, x+_ShadeExtent, z-_ShadeExtent, xmin, ymin, xmax, ymax); if (_ShadeOutline) { - rCS.render2DClip(*_Driver, rdrBuffer, x-_ShadeExtent, z-_ShadeExtent, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x-_ShadeExtent, z+_ShadeExtent, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x+_ShadeExtent, z+_ShadeExtent, xmin, ymin, xmax, ymax); + 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); + } + else + { + rCS.render2DClip(*_Driver, rdrBuffer, x+_ShadeExtent, z-_ShadeExtent, xmin, ymin, xmax, ymax); } rCS.Color= bkup; } @@ -195,12 +213,21 @@ public: CRGBA bkup = rCS.Color; rCS.Color= _ShadeColor; rCS.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+_ShadeExtent, y-_ShadeExtent, depth, xmin, ymin, xmax, ymax); if (_ShadeOutline) { - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-_ShadeExtent, y-_ShadeExtent, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-_ShadeExtent, y+_ShadeExtent, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+_ShadeExtent, y+_ShadeExtent, depth, xmin, ymin, xmax, ymax); + 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); + } + else + { + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+_ShadeExtent, y-_ShadeExtent, depth, xmin, ymin, xmax, ymax); } rCS.Color= bkup; } @@ -221,12 +248,21 @@ public: CRGBA bkup = _TempString.Color; _TempString.Color = _ShadeColor; _TempString.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); - _TempString.render2D(*_Driver,x+_ShadeExtent,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); if (_ShadeOutline) { - _TempString.render2D(*_Driver,x-_ShadeExtent,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x-_ShadeExtent,z+_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x+_ShadeExtent,z+_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); + 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); + } + else + { + _TempString.render2D(*_Driver,x+_ShadeExtent,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); } _TempString.Color = bkup; } @@ -251,12 +287,21 @@ public: CRGBA bkup = _TempString.Color; _TempString.Color = _ShadeColor; _TempString.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); - _TempString.render2D(*_Driver,x+_ShadeExtent,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); if (_ShadeOutline) { - _TempString.render2D(*_Driver,x-_ShadeExtent,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x-_ShadeExtent,z+_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x+_ShadeExtent,z+_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); + 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); + } + else + { + _TempString.render2D(*_Driver,x+_ShadeExtent,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); } _TempString.Color = bkup; } From 8432b9eddc4942adc89b6a7ca3148e6d2f50c2b9 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Thu, 16 Oct 2014 02:00:53 +0200 Subject: [PATCH 04/87] Maybe solves #210 --- code/ryzom/client/src/main_loop.cpp | 2 ++ code/ryzom/client/src/motion/user_controls.cpp | 4 ++++ code/ryzom/client/src/motion/user_controls.h | 2 ++ 3 files changed, 8 insertions(+) diff --git a/code/ryzom/client/src/main_loop.cpp b/code/ryzom/client/src/main_loop.cpp index f6d921ff8..9b39c53c9 100644 --- a/code/ryzom/client/src/main_loop.cpp +++ b/code/ryzom/client/src/main_loop.cpp @@ -1013,6 +1013,7 @@ bool mainLoop() SetMouseCursor (); // Set the cursor. ContextCur.context("STAND BY"); + UserControls.reset(); // set the default box for keyboard setDefaultChatWindow(PeopleInterraction.ChatGroup.Window); @@ -2463,6 +2464,7 @@ bool mainLoop() SetMouseCursor (); // Set the cursor. ContextCur.context("STAND BY"); + UserControls.reset(); // set the default box for keyboard CChatWindow *defaultChatWindow; diff --git a/code/ryzom/client/src/motion/user_controls.cpp b/code/ryzom/client/src/motion/user_controls.cpp index 285848120..897cba9c1 100644 --- a/code/ryzom/client/src/motion/user_controls.cpp +++ b/code/ryzom/client/src/motion/user_controls.cpp @@ -174,6 +174,10 @@ void CUserControls::init() }// init // +void CUserControls::reset() +{ + init(); +} //----------------------------------------------- // needReleaseForward : diff --git a/code/ryzom/client/src/motion/user_controls.h b/code/ryzom/client/src/motion/user_controls.h index eb4de2020..018b2c8e9 100644 --- a/code/ryzom/client/src/motion/user_controls.h +++ b/code/ryzom/client/src/motion/user_controls.h @@ -152,6 +152,8 @@ public: /// Constructor CUserControls(); + void reset(); + /// Return the string associated to the motion Mode. std::string modeStr() const; /// Return the motion Mode. From b24f979569833d8eb8c3c9739fe6520d9420832b Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sat, 12 Jul 2014 18:19:25 +0200 Subject: [PATCH 05/87] Add callback template class --- code/nel/include/nel/misc/callback.h | 327 ++++++++++++++++++ code/nel/samples/misc/CMakeLists.txt | 1 + code/nel/samples/misc/callback/CMakeLists.txt | 9 + code/nel/samples/misc/callback/main.cpp | 62 ++++ 4 files changed, 399 insertions(+) create mode 100644 code/nel/include/nel/misc/callback.h create mode 100644 code/nel/samples/misc/callback/CMakeLists.txt create mode 100644 code/nel/samples/misc/callback/main.cpp diff --git a/code/nel/include/nel/misc/callback.h b/code/nel/include/nel/misc/callback.h new file mode 100644 index 000000000..ca5140f6f --- /dev/null +++ b/code/nel/include/nel/misc/callback.h @@ -0,0 +1,327 @@ +/* + +Copyright (c) 2009-2014, Jan BOON +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef NLMISC_CALLBACK_H +#define NLMISC_CALLBACK_H +#include + +// STL includes + +// NeL includes +#include + +// Project includes + +namespace NLMISC { + +#define NLMISC_CALLBACK_TEMPLATE \ +/** \ + * \brief NLMISC_CALLBACK_ARGS_CLASS \ + * \date 2009-03-03 18:09GMT \ + * \author Jan BOON \ + * Callback template \ + */ \ +template \ +class NLMISC_CALLBACK_ARGS_CLASS \ +{ \ + /* Very simple reference counting callback base */ \ + class CCallbackBase \ + { \ + public: \ + CCallbackBase() : m_RefCount(0) \ + { \ + \ + } \ + \ + virtual ~CCallbackBase() \ + { \ + nlassert(!m_RefCount); \ + } \ + \ + void refAdd() \ + { \ + ++m_RefCount; \ + } \ + \ + void refRemove() \ + { \ + --m_RefCount; \ + if (!m_RefCount) \ + delete this; \ + } \ + \ + virtual TReturn callback(NLMISC_CALLBACK_ARGS_DECL) = 0; \ + \ + virtual bool equals(const CCallbackBase *callbackBase) = 0; \ + \ + /* disable copy */ \ + CCallbackBase(const CCallbackBase &); \ + CCallbackBase &operator=(const CCallbackBase &); \ + \ + private: \ + uint m_RefCount; \ + }; \ + \ + typedef TReturn TCallbackFunction(NLMISC_CALLBACK_ARGS_DECL); \ + class CCallbackFunction : public CCallbackBase \ + { \ + public: \ + CCallbackFunction(TCallbackFunction *callbackFunction) : m_CallbackFunction(callbackFunction) \ + { \ + nlassert(m_CallbackFunction); \ + } \ + \ + virtual ~CCallbackFunction() \ + { \ + m_CallbackFunction = NULL; \ + } \ + \ + virtual TReturn callback(NLMISC_CALLBACK_ARGS_DECL) \ + { \ + return m_CallbackFunction(NLMISC_CALLBACK_ARGS_IMPL); \ + } \ + \ + virtual bool equals(const CCallbackBase *callbackBase) \ + { \ + const CCallbackFunction *callbackFunction = \ + dynamic_cast(callbackBase); \ + if (!callbackFunction) return false; \ + return m_CallbackFunction == callbackFunction->m_CallbackFunction; \ + } \ + \ + private: \ + TCallbackFunction *m_CallbackFunction; \ + }; \ + \ + template \ + class CCallbackMethod : public CCallbackBase \ + { \ + typedef TReturn (TClass::*TCallbackMethod)(NLMISC_CALLBACK_ARGS_DECL); \ + public: \ + CCallbackMethod(TClass *callbackObject, TCallbackMethod callbackMethod) : m_CallbackObject(callbackObject), m_CallbackMethod(callbackMethod) \ + { \ + nlassert(m_CallbackObject); \ + nlassert(m_CallbackMethod); \ + } \ + \ + virtual ~CCallbackMethod() \ + { \ + m_CallbackObject = NULL; \ + m_CallbackMethod = NULL; \ + } \ + \ + virtual TReturn callback(NLMISC_CALLBACK_ARGS_DECL) \ + { \ + return (m_CallbackObject->*m_CallbackMethod)(NLMISC_CALLBACK_ARGS_IMPL); \ + } \ + \ + virtual bool equals(const CCallbackBase *callbackBase) \ + { \ + const CCallbackMethod *callbackMethod = \ + dynamic_cast(callbackBase); \ + if (!callbackMethod) return false; \ + return m_CallbackObject == callbackMethod->m_CallbackObject \ + && m_CallbackMethod == callbackMethod->m_CallbackMethod; \ + } \ + \ + private: \ + TClass *m_CallbackObject; \ + TCallbackMethod m_CallbackMethod; \ + }; \ + \ +public: \ + CCallback() : m_CallbackBase(NULL) \ + { \ + \ + } \ + \ + CCallback(TCallbackFunction *callbackFunction) : m_CallbackBase(new CCallbackFunction(callbackFunction)) \ + { \ + nlassert(m_CallbackBase); \ + m_CallbackBase->refAdd(); \ + } \ + \ + template \ + CCallback(TClass *callbackObject, TReturn (TClass::*callbackMethod)(NLMISC_CALLBACK_ARGS_DECL)) : m_CallbackBase(new CCallbackMethod(callbackObject, callbackMethod)) \ + { \ + nlassert(m_CallbackBase); \ + m_CallbackBase->refAdd(); \ + } \ + \ + CCallback(const CCallback &callback) \ + { \ + m_CallbackBase = callback.m_CallbackBase; \ + if (m_CallbackBase) \ + m_CallbackBase->refAdd(); \ + } \ + \ + CCallback &operator=(const CCallback &callback) \ + { \ + if (m_CallbackBase != callback.m_CallbackBase) \ + { \ + if (m_CallbackBase) \ + m_CallbackBase->refRemove(); \ + m_CallbackBase = callback.m_CallbackBase; \ + if (m_CallbackBase) \ + m_CallbackBase->refAdd(); \ + } \ + return *this; \ + } \ + \ + ~CCallback() \ + { \ + if (m_CallbackBase) \ + { \ + m_CallbackBase->refRemove(); \ + m_CallbackBase = NULL; \ + } \ + } \ + \ + TReturn callback(NLMISC_CALLBACK_ARGS_DECL) \ + { \ + nlassert(m_CallbackBase); \ + return m_CallbackBase->callback(NLMISC_CALLBACK_ARGS_IMPL); \ + } \ + \ + TReturn operator()(NLMISC_CALLBACK_ARGS_DECL) \ + { \ + nlassert(m_CallbackBase); \ + return m_CallbackBase->callback(NLMISC_CALLBACK_ARGS_IMPL); \ + } \ + \ + bool valid() const \ + { \ + return m_CallbackBase != NULL; \ + } \ + \ + operator bool() const \ + { \ + return m_CallbackBase != NULL; \ + } \ + \ + bool operator==(const CCallback &callback) \ + { \ + return m_CallbackBase->equals(callback.m_CallbackBase); \ + } \ + \ +private: \ + CCallbackBase *m_CallbackBase; \ + \ +}; /* class CCallback */ \ + +template +class CCallback; + +#define NLMISC_CALLBACK_ARGS_CLASS CCallback +#define NLMISC_CALLBACK_ARGS_TYPENAME +#define NLMISC_CALLBACK_ARGS_DECL +#define NLMISC_CALLBACK_ARGS_IMPL +NLMISC_CALLBACK_TEMPLATE +#undef NLMISC_CALLBACK_ARGS_CLASS +#undef NLMISC_CALLBACK_ARGS_TYPENAME +#undef NLMISC_CALLBACK_ARGS_DECL +#undef NLMISC_CALLBACK_ARGS_IMPL + +#define NLMISC_CALLBACK_ARGS_CLASS CCallback +#define NLMISC_CALLBACK_ARGS_TYPENAME , typename TArgsA +#define NLMISC_CALLBACK_ARGS_DECL TArgsA argsA +#define NLMISC_CALLBACK_ARGS_IMPL argsA +NLMISC_CALLBACK_TEMPLATE +#undef NLMISC_CALLBACK_ARGS_CLASS +#undef NLMISC_CALLBACK_ARGS_TYPENAME +#undef NLMISC_CALLBACK_ARGS_DECL +#undef NLMISC_CALLBACK_ARGS_IMPL + +#define NLMISC_CALLBACK_ARGS_CLASS CCallback +#define NLMISC_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB +#define NLMISC_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB +#define NLMISC_CALLBACK_ARGS_IMPL argsA, argsB +NLMISC_CALLBACK_TEMPLATE +#undef NLMISC_CALLBACK_ARGS_CLASS +#undef NLMISC_CALLBACK_ARGS_TYPENAME +#undef NLMISC_CALLBACK_ARGS_DECL +#undef NLMISC_CALLBACK_ARGS_IMPL + +#define NLMISC_CALLBACK_ARGS_CLASS CCallback +#define NLMISC_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC +#define NLMISC_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC +#define NLMISC_CALLBACK_ARGS_IMPL argsA, argsB, argsC +NLMISC_CALLBACK_TEMPLATE +#undef NLMISC_CALLBACK_ARGS_CLASS +#undef NLMISC_CALLBACK_ARGS_TYPENAME +#undef NLMISC_CALLBACK_ARGS_DECL +#undef NLMISC_CALLBACK_ARGS_IMPL + +#define NLMISC_CALLBACK_ARGS_CLASS CCallback +#define NLMISC_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC, typename TArgsD +#define NLMISC_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC, TArgsD argsD +#define NLMISC_CALLBACK_ARGS_IMPL argsA, argsB, argsC, argsD +NLMISC_CALLBACK_TEMPLATE +#undef NLMISC_CALLBACK_ARGS_CLASS +#undef NLMISC_CALLBACK_ARGS_TYPENAME +#undef NLMISC_CALLBACK_ARGS_DECL +#undef NLMISC_CALLBACK_ARGS_IMPL + +#define NLMISC_CALLBACK_ARGS_CLASS CCallback +#define NLMISC_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC, typename TArgsD, typename TArgsE +#define NLMISC_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC, TArgsD argsD, TArgsE argsE +#define NLMISC_CALLBACK_ARGS_IMPL argsA, argsB, argsC, argsD, argsE +NLMISC_CALLBACK_TEMPLATE +#undef NLMISC_CALLBACK_ARGS_CLASS +#undef NLMISC_CALLBACK_ARGS_TYPENAME +#undef NLMISC_CALLBACK_ARGS_DECL +#undef NLMISC_CALLBACK_ARGS_IMPL + +#define NLMISC_CALLBACK_ARGS_CLASS CCallback +#define NLMISC_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC, typename TArgsD, typename TArgsE, typename TArgsF +#define NLMISC_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC, TArgsD argsD, TArgsE argsE, TArgsF argsF +#define NLMISC_CALLBACK_ARGS_IMPL argsA, argsB, argsC, argsD, argsE, argsF +NLMISC_CALLBACK_TEMPLATE +#undef NLMISC_CALLBACK_ARGS_CLASS +#undef NLMISC_CALLBACK_ARGS_TYPENAME +#undef NLMISC_CALLBACK_ARGS_DECL +#undef NLMISC_CALLBACK_ARGS_IMPL + +#define NLMISC_CALLBACK_ARGS_CLASS CCallback +#define NLMISC_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC, typename TArgsD, typename TArgsE, typename TArgsF, typename TArgsG +#define NLMISC_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC, TArgsD argsD, TArgsE argsE, TArgsF argsF, TArgsG argsG +#define NLMISC_CALLBACK_ARGS_IMPL argsA, argsB, argsC, argsD, argsE, argsF, argsG +NLMISC_CALLBACK_TEMPLATE +#undef NLMISC_CALLBACK_ARGS_CLASS +#undef NLMISC_CALLBACK_ARGS_TYPENAME +#undef NLMISC_CALLBACK_ARGS_DECL +#undef NLMISC_CALLBACK_ARGS_IMPL +#undef NLMISC_CALLBACK_ARGS_CLASSNAME + +#undef NLMISC_CALLBACK_TEMPLATE + +} /* namespace NLMISC */ + +#endif /* #ifndef NLMISC_CALLBACK_H */ + +/* end of file */ diff --git a/code/nel/samples/misc/CMakeLists.txt b/code/nel/samples/misc/CMakeLists.txt index 753b418ae..d00a54952 100644 --- a/code/nel/samples/misc/CMakeLists.txt +++ b/code/nel/samples/misc/CMakeLists.txt @@ -1,3 +1,4 @@ +ADD_SUBDIRECTORY(callback) ADD_SUBDIRECTORY(command) ADD_SUBDIRECTORY(configfile) ADD_SUBDIRECTORY(debug) diff --git a/code/nel/samples/misc/callback/CMakeLists.txt b/code/nel/samples/misc/callback/CMakeLists.txt new file mode 100644 index 000000000..62626b0a7 --- /dev/null +++ b/code/nel/samples/misc/callback/CMakeLists.txt @@ -0,0 +1,9 @@ +FILE(GLOB SRC *.cpp) + +ADD_EXECUTABLE(nl_sample_callback ${SRC}) + +TARGET_LINK_LIBRARIES(nl_sample_callback nelmisc) +NL_DEFAULT_PROPS(nl_sample_callback "NeL, Samples, Misc: Callback") +NL_ADD_RUNTIME_FLAGS(nl_sample_callback) + +INSTALL(TARGETS nl_sample_callback RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT samplesmisc) diff --git a/code/nel/samples/misc/callback/main.cpp b/code/nel/samples/misc/callback/main.cpp new file mode 100644 index 000000000..157f3b259 --- /dev/null +++ b/code/nel/samples/misc/callback/main.cpp @@ -0,0 +1,62 @@ +/* + +Copyright (c) 2014, Jan BOON +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include +#include + +class CTestClass +{ +public: + void helloWorld(int y) + { + nldebug("Method call: %i, %i", y, x); + } + int x; +}; + +void functionCall(int i) +{ + nldebug("Function call: %i", i); +} + +typedef NLMISC::CCallback TCallbackType; + +int main(int argc, char **argv) +{ + CTestClass tc; + tc.x = 42; + + TCallbackType cbMethod = TCallbackType(&tc, &CTestClass::helloWorld); + TCallbackType cbFunction = TCallbackType(functionCall); + cbMethod(100); + cbFunction(99); + + getchar(); + + return EXIT_SUCCESS; +} From 80e2d7fa35d584db9694e44ab501c952892303c8 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 12 Oct 2014 17:43:18 +0300 Subject: [PATCH 06/87] Fix table cellpadding --- code/nel/src/gui/group_table.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/code/nel/src/gui/group_table.cpp b/code/nel/src/gui/group_table.cpp index 2fdd7e364..ffebca4ea 100644 --- a/code/nel/src/gui/group_table.cpp +++ b/code/nel/src/gui/group_table.cpp @@ -937,10 +937,10 @@ namespace NLGUI } } - cell->setX(currentX); - cell->setW(_Columns[column].Width); + cell->setX(currentX - CellPadding); + cell->setW(_Columns[column].Width + CellPadding*2); - cell->Group->setX(alignmentX+cell->LeftMargin); + cell->Group->setX(alignmentX + cell->LeftMargin + CellPadding); cell->Group->setW(_Columns[column].Width - widthReduceX); cell->Group->CInterfaceElement::updateCoords(); @@ -989,9 +989,9 @@ namespace NLGUI } } - cell->setY(currentY); - cell->setH (_Rows[row].Height); - cell->Group->setY(-alignmentY); + cell->setY(currentY + CellPadding); + cell->setH (_Rows[row].Height + 2*CellPadding); + cell->Group->setY(-(alignmentY + CellPadding)); } // Resize the table @@ -1179,7 +1179,7 @@ namespace NLGUI if (!_Columns.empty() && !_Rows.empty() && BgColor.A) { - sint32 border = Border + CellSpacing + CellPadding; + sint32 border = Border + CellSpacing; if (border) { CRGBA finalColor; @@ -1197,20 +1197,20 @@ namespace NLGUI rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal-border, _YReal+border, border, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor); // Draw the inside borders - sint32 insideWidth = 2*CellPadding + CellSpacing; + sint32 insideWidth = CellSpacing; if (insideWidth) { // Draw the inside verticals uint i; - sint32 x = _XReal + _Columns[0].Width + border; + sint32 x = _XReal + border + _Columns[0].Width + 2*CellPadding; for (i=1; i<_Columns.size(); i++) { rVR.drawRotFlipBitmap (_RenderLayer, x, _YReal+border, insideWidth, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor); - x += _Columns[i].Width + insideWidth; + x += _Columns[i].Width + 2*CellPadding + insideWidth; } // Draw the inside horizontals - sint32 y = _YReal + _HReal - border - _Rows[0].Height; + sint32 y = _YReal + _HReal - border - _Rows[0].Height - 2*CellPadding; if (_Rows[0].Height != 0) { y -= insideWidth; @@ -1223,10 +1223,10 @@ namespace NLGUI { for (j=0; j<_Columns.size(); j++) { - rVR.drawRotFlipBitmap (_RenderLayer, x, y, _Columns[j].Width, insideWidth, 0, false, rVR.getBlankTextureId(), finalColor); - x += _Columns[j].Width + insideWidth; + rVR.drawRotFlipBitmap (_RenderLayer, x, y, _Columns[j].Width + 2*CellPadding, insideWidth, 0, false, rVR.getBlankTextureId(), finalColor); + x += _Columns[j].Width + 2*CellPadding + insideWidth; } - y -= _Rows[i].Height+ insideWidth; + y -= _Rows[i].Height + insideWidth + 2*CellPadding; } } } From 13b947861d2f53c54a3252b0a72fb4abe285c944 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 13 Oct 2014 01:10:46 +0300 Subject: [PATCH 07/87] Add bordercolor attribute to table tag --- code/nel/include/nel/gui/group_table.h | 1 + code/nel/include/nel/gui/libwww.h | 1 + code/nel/src/gui/group_html.cpp | 2 ++ code/nel/src/gui/group_table.cpp | 21 +++++++++++++++++++++ code/nel/src/gui/libwww.cpp | 1 + 5 files changed, 26 insertions(+) diff --git a/code/nel/include/nel/gui/group_table.h b/code/nel/include/nel/gui/group_table.h index 60d3d9e63..f41b1c074 100644 --- a/code/nel/include/nel/gui/group_table.h +++ b/code/nel/include/nel/gui/group_table.h @@ -142,6 +142,7 @@ namespace NLGUI // Table borders sint32 Border; + NLMISC::CRGBA BorderColor; sint32 CellPadding; sint32 CellSpacing; diff --git a/code/nel/include/nel/gui/libwww.h b/code/nel/include/nel/gui/libwww.h index ec23cafd2..6a744b8c0 100644 --- a/code/nel/include/nel/gui/libwww.h +++ b/code/nel/include/nel/gui/libwww.h @@ -79,6 +79,7 @@ namespace NLGUI HTML_ATTR(TABLE,ALIGN) = 0, HTML_ATTR(TABLE,BGCOLOR), HTML_ATTR(TABLE,BORDER), + HTML_ATTR(TABLE,BORDERCOLOR), HTML_ATTR(TABLE,CELLPADDING), HTML_ATTR(TABLE,CELLSPACING), HTML_ATTR(TABLE,CLASS), diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 1a2ae5b4b..56398a10a 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -1453,6 +1453,8 @@ namespace NLGUI getPercentage (table->ForceWidthMin, table->TableRatio, value[MY_HTML_TABLE_WIDTH]); if (present[MY_HTML_TABLE_BORDER] && value[MY_HTML_TABLE_BORDER]) fromString(value[MY_HTML_TABLE_BORDER], table->Border); + if (present[MY_HTML_TABLE_BORDERCOLOR] && value[MY_HTML_TABLE_BORDERCOLOR]) + table->BorderColor = getColor (value[MY_HTML_TABLE_BORDERCOLOR]); if (present[MY_HTML_TABLE_CELLSPACING] && value[MY_HTML_TABLE_CELLSPACING]) fromString(value[MY_HTML_TABLE_CELLSPACING], table->CellSpacing); if (present[MY_HTML_TABLE_CELLPADDING] && value[MY_HTML_TABLE_CELLPADDING]) diff --git a/code/nel/src/gui/group_table.cpp b/code/nel/src/gui/group_table.cpp index ffebca4ea..d7933b934 100644 --- a/code/nel/src/gui/group_table.cpp +++ b/code/nel/src/gui/group_table.cpp @@ -559,6 +559,7 @@ namespace NLGUI TableRatio = 0.f; ForceWidthMin = 0; Border=0; + BorderColor = CRGBA(127, 127, 127, 255); CellPadding=0; CellSpacing=0; ContinuousUpdate = false; @@ -1243,6 +1244,11 @@ namespace NLGUI return toString( Border ); } else + if( name == "bordercolor" ) + { + return toString( BorderColor ); + } + else if( name == "cellpadding" ) { return toString( CellPadding ); @@ -1279,6 +1285,14 @@ namespace NLGUI return; } else + if( name == "bordercolor" ) + { + CRGBA c; + if( fromString( value, c ) ) + BorderColor = c; + return; + } + else if( name == "cellpadding" ) { sint32 i; @@ -1321,6 +1335,7 @@ namespace NLGUI xmlSetProp( node, BAD_CAST "type", BAD_CAST "table" ); xmlSetProp( node, BAD_CAST "border", BAD_CAST toString( Border ).c_str() ); + xmlSetProp( node, BAD_CAST "bordercolor", BAD_CAST toString( BorderColor ).c_str() ); xmlSetProp( node, BAD_CAST "cellpadding", BAD_CAST toString( CellPadding ).c_str() ); xmlSetProp( node, BAD_CAST "cellspacing", BAD_CAST toString( CellSpacing ).c_str() ); xmlSetProp( node, BAD_CAST "bgcolor", BAD_CAST toString( BgColor ).c_str() ); @@ -1345,6 +1360,12 @@ namespace NLGUI fromString((const char*)ptr, Border); } // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"bordercolor" ); + if (ptr) + { + BorderColor = convertColor((const char*)ptr); + } + // ptr = (char*) xmlGetProp( cur, (xmlChar*)"cellpadding" ); if (ptr) { diff --git a/code/nel/src/gui/libwww.cpp b/code/nel/src/gui/libwww.cpp index 0b759a7aa..b17d1cccb 100644 --- a/code/nel/src/gui/libwww.cpp +++ b/code/nel/src/gui/libwww.cpp @@ -86,6 +86,7 @@ namespace NLGUI HTML_ATTR(TABLE,ALIGN), HTML_ATTR(TABLE,BGCOLOR), HTML_ATTR(TABLE,BORDER), + HTML_ATTR(TABLE,BORDERCOLOR), HTML_ATTR(TABLE,CELLPADDING), HTML_ATTR(TABLE,CELLSPACING), HTML_ATTR(TABLE,CLASS), From d938a90da6a58c2da8bba20978e5a1860e5c49c3 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 13 Oct 2014 01:59:20 +0300 Subject: [PATCH 08/87] Render table and cell borders --- code/nel/src/gui/group_table.cpp | 50 ++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/code/nel/src/gui/group_table.cpp b/code/nel/src/gui/group_table.cpp index d7933b934..7c6a95b24 100644 --- a/code/nel/src/gui/group_table.cpp +++ b/code/nel/src/gui/group_table.cpp @@ -499,6 +499,29 @@ namespace NLGUI } } + // Get the parent table + if (getParent ()) + { + CGroupTable *table = static_cast (getParent ()); + if (table->Border) { + CRGBA lighter = blend(table->BorderColor, CRGBA::White, 0.5f); + + CRGBA borderColorTL; + borderColorTL.modulateFromColor (lighter, CWidgetManager::getInstance()->getGlobalColor()); + borderColorTL.A = (uint8) (((uint16) table->CurrentAlpha * (uint16) borderColorTL.A) >> 8); + + CRGBA borderColorBR; + borderColorBR.modulateFromColor (table->BorderColor, CWidgetManager::getInstance()->getGlobalColor()); + borderColorBR.A = (uint8) (((uint16) table->CurrentAlpha * (uint16) borderColorBR.A) >> 8); + + CViewRenderer &rVR = *CViewRenderer::getInstance(); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, 1, 0, false, rVR.getBlankTextureId(), borderColorTL ); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), borderColorBR ); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_HReal-1, _WReal, 1, 0, false, rVR.getBlankTextureId(), borderColorBR ); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal-1, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), borderColorTL ); + } + } + CInterfaceGroup::draw (); } @@ -1178,10 +1201,10 @@ namespace NLGUI if (gr == NULL) CurrentAlpha = 255; - if (!_Columns.empty() && !_Rows.empty() && BgColor.A) + if (!_Columns.empty() && !_Rows.empty()) { sint32 border = Border + CellSpacing; - if (border) + if (border && BgColor.A) { CRGBA finalColor; finalColor.modulateFromColor (BgColor, CWidgetManager::getInstance()->getGlobalColor()); @@ -1232,6 +1255,29 @@ namespace NLGUI } } } + + if (Border) { + CViewRenderer &rVR = *CViewRenderer::getInstance(); + + CRGBA borderColorTL; + CRGBA lighter = blend(BorderColor, CRGBA::White, 0.5f); + borderColorTL.modulateFromColor (lighter, CWidgetManager::getInstance()->getGlobalColor()); + borderColorTL.A = CurrentAlpha; + + CRGBA borderColorBR; + borderColorBR.modulateFromColor (BorderColor, CWidgetManager::getInstance()->getGlobalColor()); + borderColorBR.A = CurrentAlpha; + + // beveled table border + for (sint32 i=0; i Date: Tue, 14 Oct 2014 15:26:14 +0300 Subject: [PATCH 09/87] Add rowspan and colspan attributes --- code/nel/include/nel/gui/group_table.h | 2 ++ code/nel/src/gui/group_html.cpp | 8 ++++++ code/nel/src/gui/group_table.cpp | 36 ++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/code/nel/include/nel/gui/group_table.h b/code/nel/include/nel/gui/group_table.h index f41b1c074..f161c04f9 100644 --- a/code/nel/include/nel/gui/group_table.h +++ b/code/nel/include/nel/gui/group_table.h @@ -78,6 +78,8 @@ namespace NLGUI // The Width you want in pixel. This is the parameter sint32 WidthWanted; + sint32 ColSpan; + sint32 RowSpan; // The min height of the cell sint32 Height; diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 56398a10a..6266ea769 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -1519,11 +1519,19 @@ namespace NLGUI } } } + + if (present[MY_HTML_TD_COLSPAN] && value[MY_HTML_TD_COLSPAN]) + fromString(value[MY_HTML_TD_COLSPAN], _Cells.back()->ColSpan); + if (present[MY_HTML_TD_ROWSPAN] && value[MY_HTML_TD_ROWSPAN]) + fromString(value[MY_HTML_TD_ROWSPAN], _Cells.back()->RowSpan); + _Cells.back()->BgColor = _CellParams.back().BgColor; _Cells.back()->Align = _CellParams.back().Align; _Cells.back()->VAlign = _CellParams.back().VAlign; _Cells.back()->LeftMargin = _CellParams.back().LeftMargin; _Cells.back()->NoWrap = _CellParams.back().NoWrap; + _Cells.back()->ColSpan = std::max(1, _Cells.back()->ColSpan); + _Cells.back()->RowSpan = std::max(1, _Cells.back()->RowSpan); float temp; if (present[MY_HTML_TD_WIDTH] && value[MY_HTML_TD_WIDTH]) diff --git a/code/nel/src/gui/group_table.cpp b/code/nel/src/gui/group_table.cpp index 7c6a95b24..677260dbb 100644 --- a/code/nel/src/gui/group_table.cpp +++ b/code/nel/src/gui/group_table.cpp @@ -44,6 +44,8 @@ namespace NLGUI TableRatio = 0.f; WidthWanted = 0; Height = 0; + ColSpan = 1; + RowSpan = 1; Group = new CInterfaceGroup(CViewBase::TCtorParam()); Align = Left; VAlign = Top; @@ -249,6 +251,22 @@ namespace NLGUI AddChildW = b; return; } + else + if (name == "colspan" ) + { + sint32 i; + if (fromString( value, i ) ) + ColSpan = std::max(1, i); + return; + } + else + if (name == "rowspan" ) + { + sint32 i; + if (fromString( value, i ) ) + RowSpan = std::max(1, i); + return; + } else CInterfaceGroup::setProperty( name, value ); } @@ -310,6 +328,8 @@ namespace NLGUI xmlSetProp( node, BAD_CAST "ignore_max_width", BAD_CAST toString( IgnoreMaxWidth ).c_str() ); xmlSetProp( node, BAD_CAST "ignore_min_width", BAD_CAST toString( IgnoreMinWidth ).c_str() ); xmlSetProp( node, BAD_CAST "add_child_w", BAD_CAST toString( AddChildW ).c_str() ); + xmlSetProp( node, BAD_CAST "colspan", BAD_CAST toString( ColSpan ).c_str() ); + xmlSetProp( node, BAD_CAST "rowspan", BAD_CAST toString( RowSpan ).c_str() ); return node; } @@ -422,6 +442,22 @@ namespace NLGUI { AddChildW = convertBool(ptr); } + // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"colspan" ); + if (ptr) + { + sint32 i; + if (fromString((const char*)ptr, i)) + ColSpan = std::max(1, i); + } + // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"rowspan" ); + if (ptr) + { + sint32 i; + if (fromString((const char*)ptr, i)) + RowSpan = std::max(1, i); + } return true; } From 66ca0729489b9cb0d89016e638e00a186d86e9a8 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 14 Oct 2014 15:29:06 +0300 Subject: [PATCH 10/87] Render table with rowspan, colspan. Borders, if enabled, adds +1 to cell padding. --- code/nel/include/nel/gui/group_table.h | 4 +- code/nel/src/gui/group_table.cpp | 201 ++++++++++++++++--------- 2 files changed, 134 insertions(+), 71 deletions(-) diff --git a/code/nel/include/nel/gui/group_table.h b/code/nel/include/nel/gui/group_table.h index f161c04f9..746078908 100644 --- a/code/nel/include/nel/gui/group_table.h +++ b/code/nel/include/nel/gui/group_table.h @@ -80,6 +80,7 @@ namespace NLGUI sint32 ColSpan; sint32 RowSpan; + sint32 TableColumnIndex; // The min height of the cell sint32 Height; @@ -194,13 +195,14 @@ namespace NLGUI WidthMax = 0; WidthWanted = 0; TableRatio = 0; - Height = 0; + RowSpan = 1; } sint32 Width; sint32 Height; sint32 WidthWanted; sint32 WidthMax; float TableRatio; + sint32 RowSpan; }; // Table row diff --git a/code/nel/src/gui/group_table.cpp b/code/nel/src/gui/group_table.cpp index 677260dbb..386cbacbd 100644 --- a/code/nel/src/gui/group_table.cpp +++ b/code/nel/src/gui/group_table.cpp @@ -46,6 +46,7 @@ namespace NLGUI Height = 0; ColSpan = 1; RowSpan = 1; + TableColumnIndex = 0; Group = new CInterfaceGroup(CViewBase::TCtorParam()); Align = Left; VAlign = Top; @@ -618,7 +619,7 @@ namespace NLGUI TableRatio = 0.f; ForceWidthMin = 0; Border=0; - BorderColor = CRGBA(127, 127, 127, 255); + BorderColor = CRGBA(32, 32, 32, 255); CellPadding=0; CellSpacing=0; ContinuousUpdate = false; @@ -752,35 +753,75 @@ namespace NLGUI // New cell ? if (cell->NewLine) + { + while (column < _Columns.size()) + { + if (_Columns[column].RowSpan > 1) + _Columns[column].RowSpan--; + column++; + } column = 0; + } // Resize the array if (column>=_Columns.size()) _Columns.resize(column+1); + // Handle rowspan from previous row + while (_Columns[column].RowSpan > 1) + { + _Columns[column].RowSpan--; + column++; + // if previous row had less elements, then we missing columns + if (column>=_Columns.size()) + _Columns.resize(column+1); + } + + // remember column index for later use + cell->TableColumnIndex = column; + + // new column, set rowspan from current + _Columns[column].RowSpan = cell->RowSpan; + float colspan = 1.f / cell->ColSpan; + float rowspan = 1.f / cell->RowSpan; + // Update sizes - if (cellWidth > _Columns[column].Width) - _Columns[column].Width = cellWidth; - if (cell->WidthMax > _Columns[column].WidthMax) - _Columns[column].WidthMax = cell->WidthMax; - if (cell->TableRatio > _Columns[column].TableRatio) - _Columns[column].TableRatio = cell->TableRatio; - if (cell->WidthWanted + additionnalWidth > _Columns[column].WidthWanted) - _Columns[column].WidthWanted = cell->WidthWanted + additionnalWidth; - if (cell->Height > _Columns[column].Height) - _Columns[column].Height = cell->Height; + if (cellWidth*colspan > _Columns[column].Width) + _Columns[column].Width = cellWidth*colspan; + if (cell->WidthMax*colspan > _Columns[column].WidthMax) + _Columns[column].WidthMax = cell->WidthMax*colspan; + if (cell->TableRatio*colspan > _Columns[column].TableRatio) + _Columns[column].TableRatio = cell->TableRatio*colspan; + if (cell->WidthWanted*colspan + additionnalWidth > _Columns[column].WidthWanted) + _Columns[column].WidthWanted = (sint32)(cell->WidthWanted*colspan) + additionnalWidth; if (_Columns[column].WidthWanted + additionnalWidth) _Columns[column].WidthMax = _Columns[column].WidthWanted + additionnalWidth; if (_Columns[column].WidthWanted > _Columns[column].Width) _Columns[column].Width = _Columns[column].WidthWanted; + if (cell->ColSpan > 1) { + // copy this info to all spanned columns, create new columns as needed + uint newsize = column + cell->ColSpan - 1; + if (newsize >= _Columns.size()) + _Columns.resize(newsize+1); + for(uint span = 0; span < cell->ColSpan -1; span++){ + column++; + _Columns[column].Width = _Columns[column-1].Width; + _Columns[column].WidthMax = _Columns[column-1].WidthMax; + _Columns[column].TableRatio = _Columns[column-1].TableRatio; + _Columns[column].WidthWanted = _Columns[column-1].WidthWanted; + _Columns[column].RowSpan = _Columns[column-1].RowSpan; + } + } + // Next column column++; } // Width of cells and table borders - sint32 borderWidth = 2*Border + ((sint32)_Columns.size()+1) * CellSpacing + ((sint32)_Columns.size()*2) * CellPadding; + sint32 padding = CellPadding + (Border ? 1 : 0); + sint32 borderWidth = 2*Border + ((sint32)_Columns.size()+1) * CellSpacing + ((sint32)_Columns.size()*2) * padding; // Get the width sint32 tableWidthMax = ForceWidthMin?ForceWidthMin:_LastParentW; // getWReal(); @@ -862,7 +903,6 @@ namespace NLGUI // Some space ? space = finalWidth - tableWidth; - if (space > 0) { // Then add in wanted Width cells @@ -952,6 +992,18 @@ namespace NLGUI } } } + + // If there is still space left, then sum up column widths + // and add all the remaining space to final column. + if (space > 0) + { + sint32 innerWidth = 0; + for(i=0;i<_Columns.size();i++) + innerWidth += _Columns[i].Width; + + if (innerWidth > 0 && finalWidth > innerWidth) + _Columns[_Columns.size()-1].Width += finalWidth - innerWidth; + } } } } @@ -962,7 +1014,8 @@ namespace NLGUI column = 0; sint32 row = 0; - sint32 currentX = Border + CellSpacing + CellPadding; + sint32 currentX = Border + CellSpacing + padding; + _Rows.clear (); for (i=0; i<_Cells.size(); i++) { @@ -971,25 +1024,41 @@ namespace NLGUI if (cell->NewLine) { column = 0; - currentX = Border + CellSpacing + CellPadding; + currentX = Border + CellSpacing + padding; + _Rows.push_back(CRow()); } + if (cell->TableColumnIndex > 0) + { + // we have active rowspan, must add up 'skipped' columns + for( ; columnTableColumnIndex; column++) + currentX += _Columns[column].Width + padding*2 + CellSpacing; + } + // Set the x and width // Check align sint32 alignmentX = 0; sint32 widthReduceX = 0; - if (cell->WidthMax < _Columns[column].Width) + sint32 columnWidth = _Columns[column].Width; + if (cell->ColSpan > 1) + { + // scan ahead and add up column widths as they might be different + for(int j = 1; jColSpan; j++) + columnWidth += CellSpacing + padding*2 + _Columns[column+j].Width; + } + + if (cell->WidthMax < columnWidth) { switch (cell->Align) { case CGroupCell::Center: - alignmentX = (_Columns[column].Width - cell->WidthMax) / 2; + alignmentX = (columnWidth - cell->WidthMax) / 2; widthReduceX = alignmentX * 2; break; case CGroupCell::Right: - alignmentX = _Columns[column].Width - cell->WidthMax; + alignmentX = columnWidth - cell->WidthMax; widthReduceX = alignmentX; break; default: @@ -997,11 +1066,11 @@ namespace NLGUI } } - cell->setX(currentX - CellPadding); - cell->setW(_Columns[column].Width + CellPadding*2); + cell->setX(currentX - padding); + cell->setW(columnWidth + padding*2); - cell->Group->setX(alignmentX + cell->LeftMargin + CellPadding); - cell->Group->setW(_Columns[column].Width - widthReduceX); + cell->Group->setX(alignmentX + cell->LeftMargin + padding); + cell->Group->setW(columnWidth - widthReduceX); cell->Group->CInterfaceElement::updateCoords(); // Update coords to get H @@ -1009,16 +1078,17 @@ namespace NLGUI cell->Group->updateCoords(); // Resize the row array - _Rows.back().Height = std::max(cell->Height, std::max(_Rows.back().Height, (sint32)cell->Group->getH())); + float rowspan = 1 / cell->RowSpan; + _Rows.back().Height = std::max((sint32)(cell->Height*rowspan), std::max(_Rows.back().Height, (sint32)(cell->Group->getH()*rowspan))); // Next column - currentX += _Columns[column].Width + 2*CellPadding + CellSpacing; - column ++; + currentX += columnWidth + 2*padding + CellSpacing; + column += cell->ColSpan; } // Set cell Y row = 0; - sint32 currentY = -(Border + CellSpacing + CellPadding); + sint32 currentY = -(Border + CellSpacing + padding); for (i=0; i<_Cells.size(); i++) { // New cell ? @@ -1027,37 +1097,45 @@ namespace NLGUI { if (_Rows[row].Height != 0) { - currentY -= _Rows[row].Height + 2*CellPadding + CellSpacing; + currentY -= _Rows[row].Height + 2*padding + CellSpacing; } row++; } // Check align sint32 alignmentY = 0; - if ((sint32)cell->Group->getH() < _Rows[row].Height) + sint32 rowHeight = _Rows[row].Height; + if (cell->RowSpan > 1) + { + // we need to scan down and add up row heights + int k = std::min((sint32)_Rows.size(), row + cell->RowSpan); + for(int j=row+1; jGroup->getH() < rowHeight) { switch (cell->VAlign) { case CGroupCell::Middle: - alignmentY = (_Rows[row].Height - (sint32)cell->Group->getH()) / 2; + alignmentY = (rowHeight - (sint32)cell->Group->getH()) / 2; break; case CGroupCell::Bottom: - alignmentY = _Rows[row].Height - (sint32)cell->Group->getH(); + alignmentY = rowHeight - (sint32)cell->Group->getH(); break; default: break; } } - cell->setY(currentY + CellPadding); - cell->setH (_Rows[row].Height + 2*CellPadding); - cell->Group->setY(-(alignmentY + CellPadding)); + cell->setY(currentY + padding); + cell->setH (rowHeight + 2*padding); + cell->Group->setY(-(alignmentY + padding)); } // Resize the table setW(finalWidth+borderWidth-_LastParentW); if (!_Rows.empty()) - currentY -= _Rows[row].Height + CellPadding + CellSpacing + Border; + currentY -= _Rows[row].Height + padding + CellSpacing + Border; setH(-currentY); // All done @@ -1246,53 +1324,35 @@ namespace NLGUI finalColor.modulateFromColor (BgColor, CWidgetManager::getInstance()->getGlobalColor()); finalColor.A = CurrentAlpha; - // Draw the top and bottom lines + // Draw the top line CViewRenderer &rVR = *CViewRenderer::getInstance(); - rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, border, 0, false, rVR.getBlankTextureId(), finalColor); rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal-border+_HReal, _WReal, border, 0, false, rVR.getBlankTextureId(), finalColor); - // Draw the left and right lines - sint32 insideHeight = std::max((sint32)0, (sint32)_HReal - (sint32)2*border); - rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+border, border, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor); - rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal-border, _YReal+border, border, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor); + // Draw the left line + sint32 insideHeight = std::max((sint32)0, (sint32)_HReal - (sint32)border); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, border, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor); // Draw the inside borders - sint32 insideWidth = CellSpacing; - if (insideWidth) + if (CellSpacing) { - // Draw the inside verticals uint i; - sint32 x = _XReal + border + _Columns[0].Width + 2*CellPadding; - for (i=1; i<_Columns.size(); i++) + sint32 x, y; + for (i=0; i<_Cells.size(); i++) { - rVR.drawRotFlipBitmap (_RenderLayer, x, _YReal+border, insideWidth, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor); - x += _Columns[i].Width + 2*CellPadding + insideWidth; - } + CGroupCell *cell = _Cells[i]; - // Draw the inside horizontals - sint32 y = _YReal + _HReal - border - _Rows[0].Height - 2*CellPadding; - if (_Rows[0].Height != 0) - { - y -= insideWidth; - } - for (i=1; i<_Rows.size(); i++) - { - uint j; - x = _XReal + border; - if (_Rows[i].Height != 0) - { - for (j=0; j<_Columns.size(); j++) - { - rVR.drawRotFlipBitmap (_RenderLayer, x, y, _Columns[j].Width + 2*CellPadding, insideWidth, 0, false, rVR.getBlankTextureId(), finalColor); - x += _Columns[j].Width + 2*CellPadding + insideWidth; - } - y -= _Rows[i].Height + insideWidth + 2*CellPadding; - } + x = cell->getXReal(); + y = cell->getYReal() - CellSpacing; + // right + rVR.drawRotFlipBitmap (_RenderLayer, x + cell->getW(), y, CellSpacing, cell->getH() + CellSpacing, 0, false, rVR.getBlankTextureId(), finalColor); + // bottom + rVR.drawRotFlipBitmap (_RenderLayer, x, y, cell->getW(), CellSpacing, 0, false, rVR.getBlankTextureId(), finalColor); } } - } - if (Border) { + } + if (Border) + { CViewRenderer &rVR = *CViewRenderer::getInstance(); CRGBA borderColorTL; @@ -1305,7 +1365,8 @@ namespace NLGUI borderColorBR.A = CurrentAlpha; // beveled table border - for (sint32 i=0; i Date: Wed, 15 Oct 2014 00:02:38 +0300 Subject: [PATCH 11/87] Change table defaults valign=middle, cellpadding=1, cellspacing=2 --- code/nel/include/nel/gui/group_html.h | 2 +- code/nel/src/gui/group_table.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index ba34af2dd..21d609af3 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -528,7 +528,7 @@ namespace NLGUI CCellParams () : BgColor(0,0,0,0) { Align = CGroupCell::Left; - VAlign = CGroupCell::Top; + VAlign = CGroupCell::Middle; LeftMargin = 0; NoWrap = false; } diff --git a/code/nel/src/gui/group_table.cpp b/code/nel/src/gui/group_table.cpp index 386cbacbd..65ed2d93d 100644 --- a/code/nel/src/gui/group_table.cpp +++ b/code/nel/src/gui/group_table.cpp @@ -49,7 +49,7 @@ namespace NLGUI TableColumnIndex = 0; Group = new CInterfaceGroup(CViewBase::TCtorParam()); Align = Left; - VAlign = Top; + VAlign = Middle; LeftMargin = 0; NoWrap = false; IgnoreMaxWidth = false; @@ -620,8 +620,8 @@ namespace NLGUI ForceWidthMin = 0; Border=0; BorderColor = CRGBA(32, 32, 32, 255); - CellPadding=0; - CellSpacing=0; + CellPadding=1; + CellSpacing=2; ContinuousUpdate = false; } From a24400c0590ea7d83b0ec5657a5ed7e8b364ff36 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 18 Oct 2014 00:15:51 +0300 Subject: [PATCH 12/87] Fix crash when using textarea without form --- code/nel/src/gui/group_html.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 1a2ae5b4b..d42e1fed3 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -1681,21 +1681,19 @@ namespace NLGUI break; case HTML_TEXTAREA: { - // Add the editbox - // nlinfo("textarea temp '%s'", _TextAreaTemplate.c_str()); - // nlinfo("textarea name '%s'", _TextAreaName.c_str()); - // nlinfo("textarea %d %d", _TextAreaRow, _TextAreaCols); - // nlinfo("textarea content '%s'", _TextAreaContent.toUtf8().c_str()); - CInterfaceGroup *textArea = addTextArea (_TextAreaTemplate, _TextAreaName.c_str (), _TextAreaRow, _TextAreaCols, true, _TextAreaContent, _TextAreaMaxLength); - if (textArea) - { - // Add the text area to the form - CGroupHTML::CForm::CEntry entry; - entry.Name = _TextAreaName; - entry.TextArea = textArea; - _Forms.back().Entries.push_back (entry); - } _TextArea = false; + if (!(_Forms.empty())) + { + CInterfaceGroup *textArea = addTextArea (_TextAreaTemplate, _TextAreaName.c_str (), _TextAreaRow, _TextAreaCols, true, _TextAreaContent, _TextAreaMaxLength); + if (textArea) + { + // Add the text area to the form + CGroupHTML::CForm::CEntry entry; + entry.Name = _TextAreaName; + entry.TextArea = textArea; + _Forms.back().Entries.push_back (entry); + } + } } break; case HTML_TITLE: From 754a0ff04d1b718bde6a97908621bdb41b5e7705 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 18 Oct 2014 01:20:56 +0300 Subject: [PATCH 13/87] Fix html img not showing on some cases, clean up addImage method --- code/nel/src/gui/group_html.cpp | 132 ++++++++++---------------------- 1 file changed, 39 insertions(+), 93 deletions(-) diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index d42e1fed3..7de0ab96b 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -3153,111 +3153,57 @@ namespace NLGUI void CGroupHTML::addImage(const char *img, bool globalColor, bool reloadImg) { // In a paragraph ? - if (_Paragraph) + if (!_Paragraph) { - string finalUrl; + newParagraph (0); + paragraphChange (); + } + string finalUrl; + + // No more text in this text view + _CurrentViewLink = NULL; + + // Not added ? + CViewBitmap *newImage = new CViewBitmap (TCtorParam()); + + // + // 1/ try to load the image with the old system (local files in bnp) + // + string image = CFile::getPath(img) + CFile::getFilenameWithoutExtension(img) + ".tga"; + if (lookupLocalFile (finalUrl, image.c_str(), false)) + { + newImage->setRenderLayer(getRenderLayer()+1); + image = finalUrl; + } + else + { // - // 1/ try to load the image with the old system (local files in bnp) + // 2/ if it doesn't work, try to load the image in cache // - string image = CFile::getPath(img) + CFile::getFilenameWithoutExtension(img) + ".tga"; - if (lookupLocalFile (finalUrl, image.c_str(), false)) + image = localImageName(img); + if (!reloadImg && lookupLocalFile (finalUrl, image.c_str(), false)) { - // No more text in this text view - _CurrentViewLink = NULL; - - // Not added ? - CViewBitmap *newImage = new CViewBitmap (TCtorParam()); - /* todo link in image - if (getA()) - { - newImage->Link = getLink(); - newImage->setHTMLView (this); - }*/ - newImage->setRenderLayer(getRenderLayer()+1); - newImage->setTexture (finalUrl); - newImage->setModulateGlobalColor(globalColor); - - /* todo link in image - if (getA()) - getParagraph()->addChildLink(newImage); - else*/ - getParagraph()->addChild(newImage); - paragraphChange (); + // don't display image that are not power of 2 + uint32 w, h; + CBitmap::loadSize (image, w, h); + if (w == 0 || h == 0 || ((!NLMISC::isPowerOf2(w) || !NLMISC::isPowerOf2(h)) && !NL3D::CTextureFile::supportNonPowerOfTwoTextures())) + image.clear(); } else { // - // 2/ if it doesn't work, try to load the image in cache + // 3/ if it doesn't work, display a placeholder and ask to dl the image into the cache // - image = localImageName(img); - if (!reloadImg && lookupLocalFile (finalUrl, image.c_str(), false)) - { - // No more text in this text view - _CurrentViewLink = NULL; - - // Not added ? - CViewBitmap *newImage = new CViewBitmap (TCtorParam()); - /* todo link in image - if (getA()) - { - newImage->Link = getLink(); - newImage->setHTMLView (this); - }*/ - - // don't display image that are not power of 2 - uint32 w, h; - CBitmap::loadSize (image, w, h); - if (w == 0 || h == 0 || ((!NLMISC::isPowerOf2(w) || !NLMISC::isPowerOf2(h)) && !NL3D::CTextureFile::supportNonPowerOfTwoTextures())) - image.clear(); - - newImage->setTexture (image); - // newImage->setTexture (finalUrl); - newImage->setModulateGlobalColor(globalColor); - - /* todo link in image - if (getA()) - getParagraph()->addChildLink(newImage); - else*/ - getParagraph()->addChild(newImage); - paragraphChange (); - } - else - { - - // - // 3/ if it doesn't work, display a placeholder and ask to dl the image into the cache - // - image = "web_del.tga"; - if (lookupLocalFile (finalUrl, image.c_str(), false)) - { - // No more text in this text view - _CurrentViewLink = NULL; - - // Not added ? - CViewBitmap *newImage = new CViewBitmap (TCtorParam()); - /* todo link in image - if (getA()) - { - newImage->Link = getLink(); - newImage->setHTMLView (this); - }*/ - newImage->setTexture (image); - // newImage->setTexture (finalUrl); - newImage->setModulateGlobalColor(globalColor); - - addImageDownload(img, newImage); - - /* todo link in image - if (getA()) - getParagraph()->addChildLink(newImage); - else*/ - getParagraph()->addChild(newImage); - paragraphChange (); - } - } + image = "web_del.tga"; + addImageDownload(img, newImage); } } + newImage->setTexture (image); + newImage->setModulateGlobalColor(globalColor); + + getParagraph()->addChild(newImage); + paragraphChange (); } // *************************************************************************** From 6245a68f766c58df36211170d32931fa2148ede7 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Fri, 7 Nov 2014 19:02:50 +0100 Subject: [PATCH 14/87] Change patchman example domain --- .../patchman_cfg/admin_install/bin/startup | 4 +- .../admin_install/bin/sync_rrd_graphs.sh | 2 +- .../admin_executor_service_default.mini01.cfg | 2 +- .../admin_executor_service_default.std01.cfg | 2 +- .../admin_install/patchman/patchman_list | 42 ++++---- .../patchman/patchman_service.default.cfg | 4 +- .../patchman/patchman_service.mini01.cfg | 4 +- .../patchman_service.mini01_bridge.cfg | 2 +- .../patchman/patchman_service.std01.cfg | 4 +- .../patchman/special_patchman_list | 6 +- .../admin_install/patchman_service_local.cfg | 2 +- .../server/patchman_cfg/shard_ctrl_mini01.txt | 30 +++--- .../server/patchman_cfg/shard_ctrl_std01.txt | 96 +++++++++---------- .../terminal_mini01/patchman_service.cfg | 4 +- 14 files changed, 102 insertions(+), 102 deletions(-) diff --git a/code/ryzom/server/patchman_cfg/admin_install/bin/startup b/code/ryzom/server/patchman_cfg/admin_install/bin/startup index 16bf59fd3..a63c6a3f7 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/bin/startup +++ b/code/ryzom/server/patchman_cfg/admin_install/bin/startup @@ -4,8 +4,8 @@ cd /srv/core rm */*.state */*/*.launch_ctrl */*/*.state /bin/bash /srv/core/bin/admin start -# special case for the "ep1.std01.ryzomcore.org" machine - start the admin tool graph sync script -if [ $(hostname) = "ep1.std01.ryzomcore.org" ] +# special case for the "ep1.std01.ryzomcore.local" machine - start the admin tool graph sync script +if [ $(hostname) = "ep1.std01.ryzomcore.local" ] then nohup /bin/sh /srv/core/bin/sync_rrd_graphs.sh & fi diff --git a/code/ryzom/server/patchman_cfg/admin_install/bin/sync_rrd_graphs.sh b/code/ryzom/server/patchman_cfg/admin_install/bin/sync_rrd_graphs.sh index b23fc285b..cc78fbaf1 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/bin/sync_rrd_graphs.sh +++ b/code/ryzom/server/patchman_cfg/admin_install/bin/sync_rrd_graphs.sh @@ -4,7 +4,7 @@ echo Launched: $(date) while true do # retrieve ATS files from ATS admin tool machine - rsync -t ep1.std01.ryzomcore.org:ats/graph_datas/* /srv/core/mini01/rrd_graphs/ + rsync -t ep1.std01.ryzomcore.local:ats/graph_datas/* /srv/core/mini01/rrd_graphs/ # deal with live files - duplicate files that correspond to unique services to aid with graphing of su & co cd /srv/core/std01/rrd_graphs/ diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/admin_executor_service_default.mini01.cfg b/code/ryzom/server/patchman_cfg/admin_install/patchman/admin_executor_service_default.mini01.cfg index bc7be84e9..0e8af6ed9 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/admin_executor_service_default.mini01.cfg +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/admin_executor_service_default.mini01.cfg @@ -10,7 +10,7 @@ AESAliasName= "aes"; DontUseStdIn = 0; // Adress ofthe admin service (default port is 49996) -ASHost = "ep1.mini01.ryzomcore.org"; +ASHost = "ep1.mini01.ryzomcore.local"; // Config for AES AESPort = "46712"; diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/admin_executor_service_default.std01.cfg b/code/ryzom/server/patchman_cfg/admin_install/patchman/admin_executor_service_default.std01.cfg index 7bfb80b27..7a4176b93 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/admin_executor_service_default.std01.cfg +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/admin_executor_service_default.std01.cfg @@ -10,7 +10,7 @@ AESAliasName= "aes"; DontUseStdIn = 0; // Adress ofthe admin service (default port is 49996) -ASHost = "ep1.std01.ryzomcore.org"; +ASHost = "ep1.std01.ryzomcore.local"; // Config for AES AESPort = "46702"; diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_list b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_list index e90230704..9a9341e9a 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_list +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_list @@ -1,23 +1,23 @@ // default values for different sites -mini01 ep1.mini01.ryzomcore.org -std01 ep1.std01.ryzomcore.org -std01 su1.std01.ryzomcore.org -std01 pd1.std01.ryzomcore.org -std01 pd2.std01.ryzomcore.org -std01 pd3.std01.ryzomcore.org -std01 pd4.std01.ryzomcore.org -std01 mla1.std01.ryzomcore.org -std01 mla2.std01.ryzomcore.org -std01 mla3.std01.ryzomcore.org -std01 mla4.std01.ryzomcore.org -std01 mla5.std01.ryzomcore.org -std01 mlb1.std01.ryzomcore.org -std01 mlb2.std01.ryzomcore.org -std01 mlb3.std01.ryzomcore.org -std01 mlb4.std01.ryzomcore.org -std01 mlb5.std01.ryzomcore.org -std01 rra1.std01.ryzomcore.org -std01 rra2.std01.ryzomcore.org -std01 rrb1.std01.ryzomcore.org -std01 rrb2.std01.ryzomcore.org +mini01 ep1.mini01.ryzomcore.local +std01 ep1.std01.ryzomcore.local +std01 su1.std01.ryzomcore.local +std01 pd1.std01.ryzomcore.local +std01 pd2.std01.ryzomcore.local +std01 pd3.std01.ryzomcore.local +std01 pd4.std01.ryzomcore.local +std01 mla1.std01.ryzomcore.local +std01 mla2.std01.ryzomcore.local +std01 mla3.std01.ryzomcore.local +std01 mla4.std01.ryzomcore.local +std01 mla5.std01.ryzomcore.local +std01 mlb1.std01.ryzomcore.local +std01 mlb2.std01.ryzomcore.local +std01 mlb3.std01.ryzomcore.local +std01 mlb4.std01.ryzomcore.local +std01 mlb5.std01.ryzomcore.local +std01 rra1.std01.ryzomcore.local +std01 rra2.std01.ryzomcore.local +std01 rrb1.std01.ryzomcore.local +std01 rrb2.std01.ryzomcore.local diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.default.cfg b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.default.cfg index 981654046..184fca55a 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.default.cfg +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.default.cfg @@ -10,7 +10,7 @@ StartCommands = // Create a gateway module on layer 3 transport and open it "moduleManager.createModule StandardGateway bridge_gw", "bridge_gw.transportAdd L3Client l3client", - "bridge_gw.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.org:44749)", + "bridge_gw.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.local:44749)", //------------------------------------------------------------------------------ @@ -19,7 +19,7 @@ StartCommands = // Create a gateway module on layer 3 transport and open it "moduleManager.createModule StandardGateway spm_gw", "spm_gw.transportAdd L3Client l3client", - "spm_gw.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.org:44752)", + "spm_gw.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.local:44752)", //------------------------------------------------------------------------------ diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.mini01.cfg b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.mini01.cfg index 41c283b63..0bd04c5eb 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.mini01.cfg +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.mini01.cfg @@ -10,7 +10,7 @@ StartCommands = // Create a gateway module on layer 3 transport and open it "moduleManager.createModule StandardGateway bridge_gw", "bridge_gw.transportAdd L3Client l3client", - "bridge_gw.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.org:44749)", + "bridge_gw.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.local:44749)", //------------------------------------------------------------------------------ @@ -19,7 +19,7 @@ StartCommands = // Create a gateway module on layer 3 transport and open it "moduleManager.createModule StandardGateway spm_gw", "spm_gw.transportAdd L3Client l3client", - "spm_gw.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.org:44751)", + "spm_gw.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.local:44751)", //------------------------------------------------------------------------------ diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.mini01_bridge.cfg b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.mini01_bridge.cfg index 32166d6bf..737177202 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.mini01_bridge.cfg +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.mini01_bridge.cfg @@ -43,7 +43,7 @@ StartCommands += // Create a gateway module on layer 3 transport and open it "moduleManager.createModule StandardGateway spm_gw", "spm_gw.transportAdd L3Client l3client", - "spm_gw.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.org:44751)", + "spm_gw.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.local:44751)", //------------------------------------------------------------------------------ diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.std01.cfg b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.std01.cfg index e8c2d5787..8fc5a64c9 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.std01.cfg +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.std01.cfg @@ -10,7 +10,7 @@ StartCommands = // Create a gateway module on layer 3 transport and open it "moduleManager.createModule StandardGateway bridge_gw", "bridge_gw.transportAdd L3Client l3client", - "bridge_gw.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.org:44749)", + "bridge_gw.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.local:44749)", //------------------------------------------------------------------------------ @@ -19,7 +19,7 @@ StartCommands = // Create a gateway module on layer 3 transport and open it "moduleManager.createModule StandardGateway spm_gw", "spm_gw.transportAdd L3Client l3client", - "spm_gw.transportCmd l3client(connect addr=ep1.std01.ryzomcore.org:44752)", + "spm_gw.transportCmd l3client(connect addr=ep1.std01.ryzomcore.local:44752)", //------------------------------------------------------------------------------ diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/special_patchman_list b/code/ryzom/server/patchman_cfg/admin_install/patchman/special_patchman_list index b42636e55..bb1114027 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/special_patchman_list +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/special_patchman_list @@ -1,10 +1,10 @@ // mini01 - mini manager -mini01_spm ep1.mini01.ryzomcore.org -mini01_bridge ep1.mini01.ryzomcore.org +mini01_spm ep1.mini01.ryzomcore.local +mini01_bridge ep1.mini01.ryzomcore.local // std01 - std manager -std01_spm ep1.std01.ryzomcore.org +std01_spm ep1.std01.ryzomcore.local diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman_service_local.cfg b/code/ryzom/server/patchman_cfg/admin_install/patchman_service_local.cfg index 45f2afe3f..5b2f35f5f 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman_service_local.cfg +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman_service_local.cfg @@ -1 +1 @@ -SPAHost = "ep1.mini01.ryzomcore.org"; +SPAHost = "ep1.mini01.ryzomcore.local"; diff --git a/code/ryzom/server/patchman_cfg/shard_ctrl_mini01.txt b/code/ryzom/server/patchman_cfg/shard_ctrl_mini01.txt index a17f6f922..e09f106ac 100644 --- a/code/ryzom/server/patchman_cfg/shard_ctrl_mini01.txt +++ b/code/ryzom/server/patchman_cfg/shard_ctrl_mini01.txt @@ -30,15 +30,15 @@ define domain_mini01 // domain hosts cfg AESHost = "localhost"; - cfg SUHost = "ep1.mini01.ryzomcore.org"; - cfg MFSHost = "ep1.mini01.ryzomcore.org"; - cfg BSHost = "ep1.mini01.ryzomcore.org:49990"; - cfg SlaveBSHost= "ep1.mini01.ryzomcore.org:49991"; - cfg MasterLGSHost = "ep1.mini01.ryzomcore.org"; - cfg SlaveLGSHost = "ep1.mini01.ryzomcore.org"; - cfg LGSBSHost = "ep1.mini01.ryzomcore.org"; - cfg DBHost = "localhost"; // FIXME "sql.core.ryzomcore.org"; - cfgAfter WebSrvHost = "http://ep1.mini01.ryzomcore.org:50000/"; + cfg SUHost = "ep1.mini01.ryzomcore.local"; + cfg MFSHost = "ep1.mini01.ryzomcore.local"; + cfg BSHost = "ep1.mini01.ryzomcore.local:49990"; + cfg SlaveBSHost= "ep1.mini01.ryzomcore.local:49991"; + cfg MasterLGSHost = "ep1.mini01.ryzomcore.local"; + cfg SlaveLGSHost = "ep1.mini01.ryzomcore.local"; + cfg LGSBSHost = "ep1.mini01.ryzomcore.local"; + cfg DBHost = "ep1.mini01.ryzomcore.local"; + cfgAfter WebSrvHost = "http://ep1.mini01.ryzomcore.local:50000/"; // initial config files cfgFile ../cfg/00_base.cfg @@ -84,7 +84,7 @@ define shard_mini01_unifier use exe_set_std_lgs_slave use backup_lgs cfg DBPass = DBNelPass; - host ep1.mini01.ryzomcore.org + host ep1.mini01.ryzomcore.local // shard mainland01 ---------------- @@ -95,10 +95,10 @@ define shard_mini01_mainland01 cfg ShardId = 301; cfg BasePort = 52000; cfg SaveFilesDirectory="mini01_mainland01/"; - cfg NSHost = "ep1.mini01.ryzomcore.org"; - cfg FSListenHost = "ep1.mini01.ryzomcore.org"; + cfg NSHost = "ep1.mini01.ryzomcore.local"; + cfg FSListenHost = "ep1.mini01.ryzomcore.local"; cfgFile ../cfg/02_shard_type_mini_mainland.cfg - host ep1.mini01.ryzomcore.org + host ep1.mini01.ryzomcore.local // shard ring01 -------------------- @@ -110,7 +110,7 @@ define shard_mini01_ring01 cfg BasePort = 52400; cfg SaveFilesDirectory="mini01_ring01/"; cfg NSPort = 51100; - cfg NSHost = "ep1.mini01.ryzomcore.org" + 51100; + cfg NSHost = "ep1.mini01.ryzomcore.local" + 51100; cfgFile ../cfg/02_shard_type_std_ring.cfg - host ep1.mini01.ryzomcore.org + host ep1.mini01.ryzomcore.local diff --git a/code/ryzom/server/patchman_cfg/shard_ctrl_std01.txt b/code/ryzom/server/patchman_cfg/shard_ctrl_std01.txt index 311261110..5492d6af3 100644 --- a/code/ryzom/server/patchman_cfg/shard_ctrl_std01.txt +++ b/code/ryzom/server/patchman_cfg/shard_ctrl_std01.txt @@ -32,15 +32,15 @@ define domain_std01 // domain hosts cfg AESHost = "localhost"; - cfg SUHost = "su1.std01.ryzomcore.org"; - cfg MFSHost = "su1.std01.ryzomcore.org"; - cfg BSHost = "pd1.std01.ryzomcore.org:49990"; // Backup service host for domain - cfg SlaveBSHost= "pd2.std01.ryzomcore.org:49991"; - cfg MasterLGSHost = "pd3.std01.ryzomcore.org"; - cfg SlaveLGSHost = "pd4.std01.ryzomcore.org"; - cfg LGSBSHost = "csr.core.ryzomcore.org"; // Backup service host for log service - cfg DBHost = "sql.core.ryzomcore.org"; - cfgAfter WebSrvHost = "http://su1.std01.ryzomcore.org:50000/"; + cfg SUHost = "su1.std01.ryzomcore.local"; + cfg MFSHost = "su1.std01.ryzomcore.local"; + cfg BSHost = "pd1.std01.ryzomcore.local:49990"; // Backup service host for domain + cfg SlaveBSHost= "pd2.std01.ryzomcore.local:49991"; + cfg MasterLGSHost = "pd3.std01.ryzomcore.local"; + cfg SlaveLGSHost = "pd4.std01.ryzomcore.local"; + cfg LGSBSHost = "csr.core.ryzomcore.local"; // Backup service host for log service + cfg DBHost = "sql.core.ryzomcore.local"; + cfgAfter WebSrvHost = "http://su1.std01.ryzomcore.local:50000/"; // initial config files cfgFile ../cfg/00_base.cfg @@ -86,11 +86,11 @@ define shard_std01_unifier define shard_exe_set_std01_ras use ras - host ep1.std01.ryzomcore.org + host ep1.std01.ryzomcore.local define shard_exe_set_std01_unifier use exe_set_std_unifier - host su1.std01.ryzomcore.org + host su1.std01.ryzomcore.local cfg DBPass = DBNelPass; @@ -106,30 +106,30 @@ define shard_std01_mainland01 cfg ShardId = 101; cfg BasePort = 51000; cfg SaveFilesDirectory="std01_mainland01/"; - cfg NSHost = "mla1.std01.ryzomcore.org"; + cfg NSHost = "mla1.std01.ryzomcore.local"; cfgFile ../cfg/02_shard_type_std_mainland.cfg define shard_exe_set_std01_mainland01_be01 use exe_set_std_mainland_be01 - host mla1.std01.ryzomcore.org + host mla1.std01.ryzomcore.local define shard_exe_set_std01_mainland01_be02 use exe_set_std_mainland_be02 - host mla2.std01.ryzomcore.org + host mla2.std01.ryzomcore.local define shard_exe_set_std01_mainland01_be03 use exe_set_std_mainland_be03 - host mla3.std01.ryzomcore.org + host mla3.std01.ryzomcore.local define shard_exe_set_std01_mainland01_fe01 use exe_set_std_mainland_fe - host mla4.std01.ryzomcore.org - cfg FSListenHost = "mla4.std01.ryzomcore.org"; + host mla4.std01.ryzomcore.local + cfg FSListenHost = "mla4.std01.ryzomcore.local"; define shard_exe_set_std01_mainland01_fe02 use exe_set_std_mainland_fe - host mla5.std01.ryzomcore.org - cfg FSListenHost = "mla5.std01.ryzomcore.org"; + host mla5.std01.ryzomcore.local + cfg FSListenHost = "mla5.std01.ryzomcore.local"; // shard mainland02 ---------------- @@ -144,30 +144,30 @@ define shard_std01_mainland02 cfg ShardId = 102; cfg BasePort = 51100; cfg SaveFilesDirectory="std01_mainland02/"; - cfg NSHost = "mlb1.std01.ryzomcore.org"; + cfg NSHost = "mlb1.std01.ryzomcore.local"; cfgFile ../cfg/02_shard_type_std_mainland.cfg define shard_exe_set_std01_mainland02_be01 use exe_set_std_mainland_be01 - host mlb1.std01.ryzomcore.org + host mlb1.std01.ryzomcore.local define shard_exe_set_std01_mainland02_be02 use exe_set_std_mainland_be02 - host mlb2.std01.ryzomcore.org + host mlb2.std01.ryzomcore.local define shard_exe_set_std01_mainland02_be03 use exe_set_std_mainland_be03 - host mlb3.std01.ryzomcore.org + host mlb3.std01.ryzomcore.local define shard_exe_set_std01_mainland02_fe01 use exe_set_std_mainland_fe - host mlb4.std01.ryzomcore.org - cfg FSListenHost = "mlb4.std01.ryzomcore.org"; + host mlb4.std01.ryzomcore.local + cfg FSListenHost = "mlb4.std01.ryzomcore.local"; define shard_exe_set_std01_mainland02_fe02 use exe_set_std_mainland_fe - host mlb5.std01.ryzomcore.org - cfg FSListenHost = "mlb5.std01.ryzomcore.org"; + host mlb5.std01.ryzomcore.local + cfg FSListenHost = "mlb5.std01.ryzomcore.local"; // shard ring01 -------------------- @@ -179,17 +179,17 @@ define shard_std01_ring01 cfg ShardId = 201; cfg BasePort = 51400; cfg SaveFilesDirectory="std01_ring01/"; - cfg NSHost = "rra1.std01.ryzomcore.org"; + cfg NSHost = "rra1.std01.ryzomcore.local"; cfgFile ../cfg/02_shard_type_std_ring.cfg define shard_exe_set_std01_ring01_be use exe_set_std_ring_be - host rra1.std01.ryzomcore.org + host rra1.std01.ryzomcore.local define shard_exe_set_std01_ring01_fe use exe_set_std_ring_fe - host rra2.std01.ryzomcore.org - cfg FSListenHost = "rra2.std01.ryzomcore.org"; + host rra2.std01.ryzomcore.local + cfg FSListenHost = "rra2.std01.ryzomcore.local"; // shard ring02 -------------------- @@ -201,17 +201,17 @@ define shard_std01_ring02 cfg ShardId = 202; cfg BasePort = 51500; cfg SaveFilesDirectory="std01_ring02/"; - cfg NSHost = "rrb1.std01.ryzomcore.org"; + cfg NSHost = "rrb1.std01.ryzomcore.local"; cfgFile ../cfg/02_shard_type_std_ring.cfg define shard_exe_set_std01_ring02_be use exe_set_std_ring_be - host rrb1.std01.ryzomcore.org + host rrb1.std01.ryzomcore.local define shard_exe_set_std01_ring02_fe use exe_set_std_ring_fe - host rrb2.std01.ryzomcore.org - cfg FSListenHost = "rrb2.std01.ryzomcore.org"; + host rrb2.std01.ryzomcore.local + cfg FSListenHost = "rrb2.std01.ryzomcore.local"; // the std01 backup domain ---------- @@ -260,7 +260,7 @@ define shard_std01_backup_ras shard std01_backup_ras cfg ShardId = 100; use ras - host ep1.std01.ryzomcore.org + host ep1.std01.ryzomcore.local // the main backup pair ------------ @@ -273,15 +273,15 @@ define shard_std01_backup define shard_exe_set_std01_backup_master name bs_master use exe_set_std_backup_master - host pd1.std01.ryzomcore.org + host pd1.std01.ryzomcore.local define shard_exe_set_std01_backup_slave name bs_slave // hack to workaround bug in backup service // use exe_set_std_backup_slave use exe_set_std01_backup_slave - host pd2.std01.ryzomcore.org - cfgAfter MasterBSHost = "pd1.std01.ryzomcore.org:49990"; + host pd2.std01.ryzomcore.local + cfgAfter MasterBSHost = "pd1.std01.ryzomcore.local:49990"; // hack to workaround bug in backup service define exe_set_std01_backup_slave @@ -312,27 +312,27 @@ define shard_std01_lgs cfg L3SlaveLGSPort = 49993; cfg LGSBSPort = 49994; cfg L3LGSBSPort = 49995; - cfg MasterLGSHost = "pd3.std01.ryzomcore.org"; - cfg SlaveLGSHost = "pd4.std01.ryzomcore.org"; - cfg LGSBSHost = "csr.core.ryzomcore.org"; + cfg MasterLGSHost = "pd3.std01.ryzomcore.local"; + cfg SlaveLGSHost = "pd4.std01.ryzomcore.local"; + cfg LGSBSHost = "csr.core.ryzomcore.local"; define shard_exe_set_std01_lgs_primary name lgs_primary use raes use exe_set_std_lgs_master - host pd3.std01.ryzomcore.org + host pd3.std01.ryzomcore.local define shard_exe_set_std01_lgs_secondary name lgs_secondary use raes use exe_set_std_lgs_slave - host pd4.std01.ryzomcore.org + host pd4.std01.ryzomcore.local define shard_exe_set_std01_lgs_bs name lgs_bs use raes use backup_lgs - host csr.core.ryzomcore.org + host csr.core.ryzomcore.local // the std01 las domain ------------- @@ -365,7 +365,7 @@ define shard_std01_las_ras shard std01_las_ras cfg ShardId = 100; use ras - host ep1.std01.ryzomcore.org + host ep1.std01.ryzomcore.local // master las ---------------------- @@ -378,7 +378,7 @@ define shard_std01_las_master use las_mainland02 use las_ring01 use las_ring02 - host pd3.std01.ryzomcore.org + host pd3.std01.ryzomcore.local define las_mainland01 cfgAfter StartCommands += {"PDRootDirectory /srv/core/backup01/save_shard_pd/std01_mainland01/pds"}; @@ -415,7 +415,7 @@ define shard_std01_las_slave use las_mainland02_slave use las_ring01_slave use las_ring02_slave - host pd4.std01.ryzomcore.org + host pd4.std01.ryzomcore.local define las_mainland01_slave cfgAfter StartCommands += {"PDRootDirectory /srv/core/backup01/save_shard_pd/std01_mainland01/pds"}; diff --git a/code/ryzom/server/patchman_cfg/terminal_mini01/patchman_service.cfg b/code/ryzom/server/patchman_cfg/terminal_mini01/patchman_service.cfg index 351a8614a..c6a336c02 100644 --- a/code/ryzom/server/patchman_cfg/terminal_mini01/patchman_service.cfg +++ b/code/ryzom/server/patchman_cfg/terminal_mini01/patchman_service.cfg @@ -41,12 +41,12 @@ StartCommands += // bridge gateway // "moduleManager.createModule StandardGateway gw1", // "gw1.transportAdd L3Client l3client", -// "gw1.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.org:44748)", +// "gw1.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.local:44748)", // ats spm gateway "moduleManager.createModule StandardGateway gw2", "gw2.transportAdd L3Client l3client", - "gw2.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.org:44751)", + "gw2.transportCmd l3client(connect addr=ep1.mini01.ryzomcore.local:44751)", //------------------------------------------------------------------------------ From 0e119941b684786661a26e830df2ac1d009773a0 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Fri, 7 Nov 2014 19:16:45 +0100 Subject: [PATCH 15/87] Update default patchman cfg --- .../patchman_cfg/default/ai_service.cfg | 24 +++---- .../default/dynamic_scenario_service.cfg | 9 +++ .../default/log_analyser_service.cfg | 5 ++ .../server/patchman_cfg/default/ryzom_as.cfg | 2 +- .../patchman_cfg/shard_ctrl_definitions.txt | 66 +++++++++++-------- 5 files changed, 64 insertions(+), 42 deletions(-) create mode 100644 code/ryzom/server/patchman_cfg/default/dynamic_scenario_service.cfg create mode 100644 code/ryzom/server/patchman_cfg/default/log_analyser_service.cfg diff --git a/code/ryzom/server/patchman_cfg/default/ai_service.cfg b/code/ryzom/server/patchman_cfg/default/ai_service.cfg index 72b278cc0..5f3882759 100644 --- a/code/ryzom/server/patchman_cfg/default/ai_service.cfg +++ b/code/ryzom/server/patchman_cfg/default/ai_service.cfg @@ -322,21 +322,21 @@ StartCommandsWhenMirrorReadyRing = "createDynamicAIInstance 10000", "loadPrimitiveFile dummy.primitive", - "loadContinent r2_forest", - "createDynamicAIInstance 10001", - "loadPrimitiveFile dummy.primitive", +// "loadContinent r2_forest", +// "createDynamicAIInstance 10001", +// "loadPrimitiveFile dummy.primitive", - "loadContinent r2_lakes", - "createDynamicAIInstance 10003", - "loadPrimitiveFile dummy.primitive", +// "loadContinent r2_lakes", +// "createDynamicAIInstance 10003", +// "loadPrimitiveFile dummy.primitive", - "loadContinent r2_jungle", - "createDynamicAIInstance 10002", - "loadPrimitiveFile dummy.primitive", +// "loadContinent r2_jungle", +// "createDynamicAIInstance 10002", +// "loadPrimitiveFile dummy.primitive", - "loadContinent r2_roots", - "createDynamicAIInstance 10004", - "loadPrimitiveFile dummy.primitive", +// "loadContinent r2_roots", +// "createDynamicAIInstance 10004", +// "loadPrimitiveFile dummy.primitive", // "spawnInstances", "updateAI", diff --git a/code/ryzom/server/patchman_cfg/default/dynamic_scenario_service.cfg b/code/ryzom/server/patchman_cfg/default/dynamic_scenario_service.cfg new file mode 100644 index 000000000..e6d5942ac --- /dev/null +++ b/code/ryzom/server/patchman_cfg/default/dynamic_scenario_service.cfg @@ -0,0 +1,9 @@ + +DelayBeforeStartAct = 1; +MaxNpcs = 300; +MaxStaticObjects = 200; + +StartCommands += +{ + "unifiedNetwork.addService ShardUnifier ( address="+SUAddress+" sendId external autoRetry )", +}; diff --git a/code/ryzom/server/patchman_cfg/default/log_analyser_service.cfg b/code/ryzom/server/patchman_cfg/default/log_analyser_service.cfg new file mode 100644 index 000000000..355984ff5 --- /dev/null +++ b/code/ryzom/server/patchman_cfg/default/log_analyser_service.cfg @@ -0,0 +1,5 @@ + +DontUseNS = 1; + +QueryTimeout = 300; +LinePerPage = 50; diff --git a/code/ryzom/server/patchman_cfg/default/ryzom_as.cfg b/code/ryzom/server/patchman_cfg/default/ryzom_as.cfg index 2755403b7..4227bac69 100644 --- a/code/ryzom/server/patchman_cfg/default/ryzom_as.cfg +++ b/code/ryzom/server/patchman_cfg/default/ryzom_as.cfg @@ -1,7 +1,7 @@ DontUseNS = 1; RRDToolPath = "rrdtool"; -RRDVarPath = "../graph_datas"; +RRDVarPath = "../rrd_graphs"; // Variables required to be defined by other cfgs //AESHost="localhost"; diff --git a/code/ryzom/server/patchman_cfg/shard_ctrl_definitions.txt b/code/ryzom/server/patchman_cfg/shard_ctrl_definitions.txt index 87bd0ce4d..8deb9f533 100644 --- a/code/ryzom/server/patchman_cfg/shard_ctrl_definitions.txt +++ b/code/ryzom/server/patchman_cfg/shard_ctrl_definitions.txt @@ -26,7 +26,7 @@ define exe_set_mini_ring define exe_set_mini_mainland use raes use ms_mini_mainland - use ais_newbyland + use ais_newbieland use egs_mainland use gpms_mainland use ios_mainland @@ -100,7 +100,7 @@ define exe_set_std_mainland_be03 define exe_set_std_mainland_be03_basics // use ais_matis // use ais_tryker - use ais_newbyland + use ais_newbieland // unifier and co ------------------ @@ -170,12 +170,14 @@ define ais_ring cmdLine ai_service -C. -L. --nobreak --writepid -mCommon:Ring use ais data data_r2_desert - data data_r2_forest - data data_r2_jungle - data data_r2_lakes - data data_r2_roots + // data data_r2_forest + // data data_r2_jungle + // data data_r2_lakes + // data data_r2_roots define ais_mainland + name ais + cmdLine ai_service -C. -L. --nobreak --writepid -mCommon:Indoors:Newbieland:Post use ais data data_mainland_common_primitives data data_newbieland_primitives @@ -188,8 +190,8 @@ define ais_mini_mainland cmdLine ai_service -C. -L. --nobreak --writepid -mCommon:Indoors:Newbieland:Post use ais_mainland -define ais_newbyland - name ais_newbyland +define ais_newbieland + name ais_newbieland cmdLine ai_service -C. -L. --nobreak --writepid -mCommon:Indoors:Newbieland:Post use ais data data_mainland_common_primitives @@ -213,36 +215,40 @@ define bms_master use bms cmdLine backup_service -C. -L. --nobreak --writepid -P49990 //cfg #include "../live/cfg/backup_module_service_master.cfg" + cfg #include "../live/service_backup_service/backup_service.cfg" cfgAfter ListeningPort = 49990; cfgAfter L3ListeningPort = 49950; cfgAfter WebPort = 49970; cfgAfter BSReadState = 1; - cfgAfter SaveShardRoot = "../save_shard/"; + cfgAfter SaveShardRoot = "../save_shard_bs/"; define bms_master2 use bms cmdLine backup_service -C. -L. --nobreak --writepid -P49994 //cfg #include "../live/cfg/backup_module_service_master.cfg" + cfg #include "../live/service_backup_service/backup_service.cfg" cfgAfter ListeningPort = 49994; cfgAfter L3ListeningPort = 49954; cfgAfter WebPort = 49974; cfgAfter BSReadState = 1; - cfgAfter SaveShardRoot = "../save_shard/"; + cfgAfter SaveShardRoot = "../save_shard_bs/"; define bms_slave use bms cmdLine backup_service -C. -L. --nobreak --writepid -P49991 - cfg #include "../live/cfg/backup_module_service_slave.cfg" + //cfg #include "../live/cfg/backup_module_service_slave.cfg" + cfg #include "../live/service_backup_service/backup_service.cfg" cfgAfter ListeningPort = 49991; cfgAfter L3ListeningPort = 49951; cfgAfter WebPort = 49971; cfgAfter BSReadState = 0; - cfgAfter SaveShardRoot = "../save_shard/"; + cfgAfter SaveShardRoot = "../save_shard_bs/"; define bms_pd_master use bms cmdLine backup_service -C. -L. --nobreak --writepid -P49992 //cfg #include "../live/cfg/backup_module_service_master.cfg" + cfg #include "../live/service_backup_service/backup_service.cfg" cfgAfter ListeningPort = 49992; cfgAfter L3ListeningPort = 49952; cfgAfter WebPort = 49972; @@ -252,7 +258,8 @@ define bms_pd_master define bms_pd_slave use bms cmdLine backup_service -C. -L. --nobreak --writepid -P49993 - cfg #include "../live/cfg/backup_module_service_slave.cfg" + //cfg #include "../live/cfg/backup_module_service_slave.cfg" + cfg #include "../live/service_backup_service/backup_service.cfg" cfgAfter ListeningPort = 49993; cfgAfter L3ListeningPort = 49953; cfgAfter WebPort = 49973; @@ -263,6 +270,7 @@ define backup_lgs use bms cmdLine backup_service -C. -L. --nobreak --writepid -P49994 //cfg #include "../live/cfg/backup_module_service_master.cfg" + cfg #include "../live/service_backup_service/backup_service.cfg" cfgAfter ListeningPort = 49994; cfgAfter L3ListeningPort = 49995; cfgAfter WebPort = 49972; @@ -320,7 +328,7 @@ define dss define dss_ring use dss - cfg #include "../live/cfg/dynamic_scenario_service_ring.cfg" + // cfg #include "../live/cfg/dynamic_scenario_service_ring.cfg" // egs ----------------------------- @@ -374,17 +382,17 @@ define egs_mainland define egs_ring use egs data data_mainland_common_primitives - data data_newbieland_primitives - data data_newbieland - data data_indoors - cfg #include "../live/cfg/entities_game_service_ring.cfg" + // data data_newbieland_primitives + // data data_newbieland + // data data_indoors + //cfg #include "../live/cfg/entities_game_service_ring.cfg" // care cfg UsedContinents = cfg { cfg "r2_desert", "10000", - cfg "r2_forest", "10001", - cfg "r2_jungle", "10002", - cfg "r2_lakes", "10003", - cfg "r2_roots", "10004", + // cfg "r2_forest", "10001", + // cfg "r2_jungle", "10002", + // cfg "r2_lakes", "10003", + // cfg "r2_roots", "10004", cfg }; cfgAfter MaxXPGainPerPlayer = 30.0; cfgAfter DeathXPFactor = 0.0; @@ -460,16 +468,16 @@ define gpms_mainland use gpms data data_newbieland data data_indoors - cfg #include "../live/cfg/gpm_service_mainland.cfg" + //cfg #include "../live/cfg/gpm_service_mainland.cfg" define gpms_ring use gpms data data_r2_desert - data data_r2_forest - data data_r2_jungle - data data_r2_lakes - data data_r2_roots - cfg #include "../live/cfg/gpm_service_ring.cfg" + // data data_r2_forest + // data data_r2_jungle + // data data_r2_lakes + // data data_r2_roots + //cfg #include "../live/cfg/gpm_service_ring.cfg" // pdss ---------------------------- @@ -534,7 +542,7 @@ define ios_mainland define ios_ring use ios - cfg #include "../live/cfg/input_output_service_ring.cfg" + //cfg #include "../live/cfg/input_output_service_ring.cfg" // las ----------------------------- From a2457910c4d8a1c3d395010de87e3b08988694fb Mon Sep 17 00:00:00 2001 From: kaetemi Date: Fri, 7 Nov 2014 19:17:43 +0100 Subject: [PATCH 16/87] Backed out merge changeset: 361eb082ec5e Does not compile. FindLibLZMA missing on Ubunty 12.04 LTS --- code/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index e0f3fe7ba..071554e06 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -110,10 +110,6 @@ FIND_PACKAGE(Jpeg) IF(WITH_STATIC_LIBXML2) SET(LIBXML2_DEFINITIONS ${LIBXML2_DEFINITIONS} -DLIBXML_STATIC) - IF(NOT WIN32 AND NOT APPLE) - FIND_PACKAGE(LibLZMA REQUIRED) - SET(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} ${LIBLZMA_LIBRARIES}) - ENDIF(NOT WIN32 AND NOT APPLE) ENDIF(WITH_STATIC_LIBXML2) IF(WITH_STATIC) From feeccbdea858735563262fc9109a9f5b42a49031 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Fri, 7 Nov 2014 19:21:05 +0100 Subject: [PATCH 17/87] Update default path --- .../server/patchman_cfg/terminal_mini01/terminal_mini01.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ryzom/server/patchman_cfg/terminal_mini01/terminal_mini01.bat b/code/ryzom/server/patchman_cfg/terminal_mini01/terminal_mini01.bat index 7f61bfa59..90e11d5d6 100644 --- a/code/ryzom/server/patchman_cfg/terminal_mini01/terminal_mini01.bat +++ b/code/ryzom/server/patchman_cfg/terminal_mini01/terminal_mini01.bat @@ -1,2 +1,2 @@ @echo off -start S:\devw_x86\bin\Release\ryzom_patchman_service.exe --nolog -C. -L. \ No newline at end of file +start R:\build\bin\Release\ryzom_patchman_service.exe --nolog -C. -L. \ No newline at end of file From aee9f17acb6390d75d706c549f12a1ecb21e1925 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Fri, 7 Nov 2014 19:32:18 +0100 Subject: [PATCH 18/87] Fix patchman scripts --- .../patchman_cfg/admin_install/bin/admin | 6 +- .../admin_install/bin/run_forever | 2 +- .../admin_install/patchman/loop_patchman.sh | 1 + .../patchman/loop_patchman_once.sh | 8 +- .../patchman/loop_special_patchman.sh | 2 +- .../admin_install/patchman/make_next_live.sh | 4 +- .../patchman/patchman_service.default.cfg | 7 -- .../patchman/patchman_service.mini01.cfg | 7 -- .../patchman/patchman_service.std01.cfg | 7 -- .../patchman/patchman_service_base_linux.cfg | 7 +- .../patchman/service_launcher.sh | 74 ++++++++++--------- .../patchman_cfg/default/ai_service.cfg | 6 +- 12 files changed, 62 insertions(+), 69 deletions(-) diff --git a/code/ryzom/server/patchman_cfg/admin_install/bin/admin b/code/ryzom/server/patchman_cfg/admin_install/bin/admin index c7cfa2fb6..f48de0d15 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/bin/admin +++ b/code/ryzom/server/patchman_cfg/admin_install/bin/admin @@ -99,14 +99,14 @@ then for f in $DOMAIN_LIST do # see if we're setup to run this domain - if [ -e /srv/core/${f}.screen.rc ] && [ -e /srv/core/bin/${f} ] + if [ -e /srv/core/${f}.screen.rc ] && [ -e /srv/core/bin/domain_${f} ] then # see whether the domain is alredy running - if [ $( screen -list | grep \( | cut -f2 | cut -d. -f2| grep \^$f\$ | wc -l) == 0 ] + if [ $( screen -list | grep \\\.${f} | wc -w ) = 0 ] then # the domain isn't running yet so start it echo '****' starting domain: $f '****' - /srv/core/bin/$f batchstart + /srv/core/bin/domain_$f batchstart else echo '****' Domain is already running: $f '****' fi diff --git a/code/ryzom/server/patchman_cfg/admin_install/bin/run_forever b/code/ryzom/server/patchman_cfg/admin_install/bin/run_forever index c6f14b074..91a838a02 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/bin/run_forever +++ b/code/ryzom/server/patchman_cfg/admin_install/bin/run_forever @@ -3,7 +3,7 @@ while true do -if [ "$2" == "" ] +if [ "$2" = "" ] then echo echo USAGE: $0 sleep_time command_line diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/loop_patchman.sh b/code/ryzom/server/patchman_cfg/admin_install/patchman/loop_patchman.sh index 73b151c43..af057f2ae 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/loop_patchman.sh +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/loop_patchman.sh @@ -10,6 +10,7 @@ do chmod 775 bin/ps_services 2> /dev/null chmod 775 bin/run_forever 2> /dev/null chmod 775 bin/shard 2> /dev/null + chmod 775 bin/domain_* 2> /dev/null chmod 775 bin/startup 2> /dev/null chmod 775 bin/*.sh 2> /dev/null chmod 775 patchman/*_service 2> /dev/null diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/loop_patchman_once.sh b/code/ryzom/server/patchman_cfg/admin_install/patchman/loop_patchman_once.sh index 0dd697aa4..f7152cada 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/loop_patchman_once.sh +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/loop_patchman_once.sh @@ -3,8 +3,8 @@ CFGFILENAME=patchman_service.${SERVER_TYPE}.cfg echo cfg file: $CFGFILENAME -AESCFGFILENAME=admin_executor_service_default.${SERVER_TYPE}.cfg -echo aes cfg file: $AESCFGFILENAME +#AESCFGFILENAME=admin_executor_service_default.${SERVER_TYPE}.cfg +#echo aes cfg file: $AESCFGFILENAME cd /srv/core/patchman if [ -e $CFGFILENAME ] @@ -15,8 +15,8 @@ if [ -e $CFGFILENAME ] cp $CFGFILENAME patchman_service.cfg # setup the config file for the admin executor service - echo Using aes configuration file: $AESCFGFILENAME - if [ -e $AESCFGFILENAME ] ; then cp $AESCFGFILENAME admin_executor_service_default.cfg ; fi + #echo Using aes configuration file: $AESCFGFILENAME + #if [ -e $AESCFGFILENAME ] ; then cp $AESCFGFILENAME admin_executor_service_default.cfg ; fi # start the patchman service echo Launching patchman... diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/loop_special_patchman.sh b/code/ryzom/server/patchman_cfg/admin_install/patchman/loop_special_patchman.sh index af1f5b599..6aa9f2ddf 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/loop_special_patchman.sh +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/loop_special_patchman.sh @@ -1,6 +1,6 @@ #!/bin/sh -if [ "$1" == "" ] +if [ "$1" = "" ] then echo echo USAGE: $0 command_line diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/make_next_live.sh b/code/ryzom/server/patchman_cfg/admin_install/patchman/make_next_live.sh index fbaca4ac4..394fc971d 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/make_next_live.sh +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/make_next_live.sh @@ -84,7 +84,7 @@ rm -v */*.*launch_ctrl *.*launch_ctrl 2> /dev/null # initialise the state files for the new services to "xxxxx" and remove directories that are no longer of interest for D in $(ls */log.log | sed "s%/.*%%" | sort -u) do - if [ $(grep \"$D\" admin_executor_service.cfg | wc -l) == 1 ] + if [ $(grep \"$D\" admin_executor_service.cfg | wc -l) = 1 ] then printf "xxxxx" > $D/$D.state else @@ -97,7 +97,7 @@ done printf "1" > ./global.launch_ctrl # create a script for accessing the screen for this shard -SCRIPT_FILE=/srv/core/bin/${DOMAIN} +SCRIPT_FILE=/srv/core/bin/domain_${DOMAIN} echo "#!/bin/sh" > $SCRIPT_FILE echo "cd "$(pwd) >> $SCRIPT_FILE echo '/bin/sh /srv/core/bin/ryzom_domain_screen_wrapper.sh $*' >> $SCRIPT_FILE diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.default.cfg b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.default.cfg index 184fca55a..7473aa9a0 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.default.cfg +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.default.cfg @@ -28,10 +28,3 @@ StartCommands = "pam.plug spm_gw", "pam.plug bridge_gw", }; - -SpaPreCmdLineText="/bin/sh /srv/core/patchman/service_launcher.sh"; -DeploymentRootDirectory="/srv/core/patchman/"; -MakeInstalledVersionLiveCmdLine="/bin/sh /srv/core/patchman/make_next_live.sh"; -SpaLaunchAESCmdLine="/bin/sh /srv/core/patchman/loop_aes.sh"; -InstallArchiveDirectory="/srv/core/"; -InstallArchiveFileName="admin_install.tgz"; diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.mini01.cfg b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.mini01.cfg index 0bd04c5eb..f046815ce 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.mini01.cfg +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.mini01.cfg @@ -36,10 +36,3 @@ StartCommands = "pam.plug spm_gw", "pam.plug bridge_gw", }; - -SpaPreCmdLineText="/bin/sh /srv/core/patchman/service_launcher.sh"; -DeploymentRootDirectory="/srv/core/patchman/"; -MakeInstalledVersionLiveCmdLine="/bin/sh /srv/core/patchman/make_next_live.sh"; -SpaLaunchAESCmdLine="/bin/sh /srv/core/patchman/loop_aes.sh"; -InstallArchiveDirectory="/srv/core/"; -InstallArchiveFileName="admin_install.tgz"; diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.std01.cfg b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.std01.cfg index 8fc5a64c9..23175c08b 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.std01.cfg +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service.std01.cfg @@ -36,10 +36,3 @@ StartCommands = "pam.plug spm_gw", "pam.plug bridge_gw", }; - -SpaPreCmdLineText="/bin/sh /srv/core/patchman/service_launcher.sh"; -DeploymentRootDirectory="/srv/core/patchman/"; -MakeInstalledVersionLiveCmdLine="/bin/sh /srv/core/patchman/make_next_live.sh"; -SpaLaunchAESCmdLine="/bin/sh /srv/core/patchman/loop_aes.sh"; -InstallArchiveDirectory="/srv/core/"; -InstallArchiveFileName="admin_install.tgz"; diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service_base_linux.cfg b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service_base_linux.cfg index 8aea88a5f..74290a228 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service_base_linux.cfg +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/patchman_service_base_linux.cfg @@ -14,4 +14,9 @@ DontUseStdIn = 0; // 4 = nothing UseYieldMethod = 0; - +SpaPreCmdLineText="/bin/sh /srv/core/patchman/service_launcher.sh"; +DeploymentRootDirectory="/srv/core/patchman/"; +MakeInstalledVersionLiveCmdLine="/bin/sh /srv/core/patchman/make_next_live.sh"; +SpaLaunchAESCmdLine="/bin/sh /srv/core/patchman/loop_aes.sh"; +InstallArchiveDirectory="/srv/core/"; +InstallArchiveFileName="admin_install.tgz"; diff --git a/code/ryzom/server/patchman_cfg/admin_install/patchman/service_launcher.sh b/code/ryzom/server/patchman_cfg/admin_install/patchman/service_launcher.sh index 091892af7..435c44bc0 100644 --- a/code/ryzom/server/patchman_cfg/admin_install/patchman/service_launcher.sh +++ b/code/ryzom/server/patchman_cfg/admin_install/patchman/service_launcher.sh @@ -1,25 +1,26 @@ #!/bin/sh -# the object is to make a launcher script that works with a command file to determine when to launch the application that it is responsible for +# the objective is to make a launcher script that works with a command file to determine when to launch the application that it is responsible for DOMAIN=$(pwd |sed "s%/srv/core/%%" | sed "s%/.*%%") NAME_BASE=$(pwd | sed 's/\/srv\/core\///' | sed 's/^.*\///') #if [ _$DOMAIN == _pre_live ] -# then - CTRL_FILE=${NAME_BASE}.launch_ctrl - NEXT_CTRL_FILE=${NAME_BASE}.deferred_launch_ctrl +# then + CTRL_FILE=${NAME_BASE}.launch_ctrl + NEXT_CTRL_FILE=${NAME_BASE}.deferred_launch_ctrl #elif [ _$DOMAIN == _pre_pre_live ] -# then -# CTRL_FILE=${NAME_BASE}.launch_ctrl -# NEXT_CTRL_FILE=${NAME_BASE}.deferred_launch_ctrl +# then +# CTRL_FILE=${NAME_BASE}.launch_ctrl +# NEXT_CTRL_FILE=${NAME_BASE}.deferred_launch_ctrl #else -# CTRL_FILE=${NAME_BASE}_immediate.launch_ctrl -# NEXT_CTRL_FILE=${NAME_BASE}_waiting.launch_ctrl +# CTRL_FILE=${NAME_BASE}_immediate.launch_ctrl +# NEXT_CTRL_FILE=${NAME_BASE}_waiting.launch_ctrl #fi STATE_FILE=${NAME_BASE}.state START_COUNTER_FILE=${NAME_BASE}.start_count CTRL_CMDLINE=$* +CTRL_COMMAND="" echo echo --------------------------------------------------------------------------------- @@ -36,6 +37,13 @@ echo echo 0 > $START_COUNTER_FILE START_COUNTER=0 +# always give ras a first run +if [ "${NAME_BASE}" = "ras" ] +then + echo Force admin service first startup + printf LAUNCH > $CTRL_FILE +fi + echo Press ENTER to launch program while true do @@ -45,37 +53,37 @@ do then # a control file exists so read it's contents - CTRL_COMMAND=_$(cat $CTRL_FILE)_ + CTRL_COMMAND=$(cat $CTRL_FILE) # do we have a 'launch' command? - if [ $CTRL_COMMAND = _LAUNCH_ ] + if [ "$CTRL_COMMAND" = "LAUNCH" ] then - # update the start counter - START_COUNTER=$(( $START_COUNTER + 1 )) - echo $START_COUNTER > $START_COUNTER_FILE + # update the start counter + START_COUNTER=$(( $START_COUNTER + 1 )) + echo $START_COUNTER > $START_COUNTER_FILE - # big nasty hack to deal with the special cases of ryzom_naming_service and ryzom_admin_service who have badly names cfg files - for f in ryzom_*cfg - do - cp $f $(echo $f | sed "s/ryzom_//") - done + # big nasty hack to deal with the special cases of ryzom_naming_service and ryzom_admin_service who have badly names cfg files + for f in ryzom_*cfg + do + cp $f $(echo $f | sed "s/ryzom_//") + done - # we have a launch command so prepare, launch, wait for exit and do the housekeeping - echo ----------------------------------------------------------------------- - echo Launching ... - echo - printf RUNNING > $STATE_FILE + # we have a launch command so prepare, launch, wait for exit and do the housekeeping + echo ----------------------------------------------------------------------- + echo Launching ... + echo + printf RUNNING > $STATE_FILE - $CTRL_CMDLINE + $CTRL_CMDLINE - echo ----------------------------------------------------------------------- - printf STOPPED > $STATE_FILE + echo ----------------------------------------------------------------------- + printf STOPPED > $STATE_FILE - # consume (remove) the control file to allow start once - rm $CTRL_FILE + # consume (remove) the control file to allow start once + rm $CTRL_FILE - echo Press ENTER to relaunch + echo Press ENTER to relaunch fi fi @@ -87,9 +95,9 @@ do else # give the terminal user a chance to press enter to provoke a re-launch HOLD=`sh -ic '{ read a; echo "ENTER" 1>&3; kill 0; } | { sleep 2; kill 0; }' 3>&1 2>/dev/null` - if [ _${HOLD}_ != _HOLD_ ] - then - printf LAUNCH > $CTRL_FILE + if [ "${HOLD}" = "ENTER" ] + then + printf LAUNCH > $CTRL_FILE fi fi diff --git a/code/ryzom/server/patchman_cfg/default/ai_service.cfg b/code/ryzom/server/patchman_cfg/default/ai_service.cfg index 5f3882759..fdb381b38 100644 --- a/code/ryzom/server/patchman_cfg/default/ai_service.cfg +++ b/code/ryzom/server/patchman_cfg/default/ai_service.cfg @@ -6,7 +6,7 @@ SystemCmd = {}; //NegFiltersDebug += { "LNET", "HNET", "FEVIS"}; //NegFiltersInfo += { "LNET", "HNET", "VISION_DELTA", "FEIMPE", "FEVIS" }; // NegFiltersWarning += { "LNET", "FEHACK", "FERECV"}; -// NegFiltersWarning += { "positional", "faction", "pet" }; +// NegFiltersWarning += { "positional", "faction", "pet" }; ////////////////////////////////////////////////////////////////////////////// //- Basic (specific) heal profile parameters --------------------------------- @@ -49,7 +49,7 @@ DefaultNpcAggroDist = 15; DefaultEscortRange = 10; ////////////////////////////////////////////////////////////////////////////// -// Aggro // +// Aggro // ////////////////////////////////////////////////////////////////////////////// AggroReturnDistCheck = 15.0; AggroReturnDistCheckFauna = 15.0; @@ -318,7 +318,7 @@ StartCommandsWhenMirrorReadyPost = // commands for Ring continents StartCommandsWhenMirrorReadyRing = { - "loadContinent r2_desert", + "loadContinent r2_desert", "createDynamicAIInstance 10000", "loadPrimitiveFile dummy.primitive", From 80105b365c75d3412e05af96751ef2e752c1e8a5 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Fri, 7 Nov 2014 23:37:39 +0100 Subject: [PATCH 19/87] Print callstack --- code/web/public_php/login/r2_login.php | 1 + 1 file changed, 1 insertion(+) diff --git a/code/web/public_php/login/r2_login.php b/code/web/public_php/login/r2_login.php index fdce63958..b0a8a2d79 100644 --- a/code/web/public_php/login/r2_login.php +++ b/code/web/public_php/login/r2_login.php @@ -145,6 +145,7 @@ { $logFile = new CWwwLog(); $logFile->logStr("PHP ERROR/$errno $errmsg ($filename:$linenum)"); + $logFile->logStr("PHP CALLSTACK/" . print_r(debug_backtrace(), TRUE)); // Never die after an error } From 04c57350d9d769d76fb50f4fdbfc3b9809dbd1df Mon Sep 17 00:00:00 2001 From: kaetemi Date: Fri, 7 Nov 2014 23:51:42 +0100 Subject: [PATCH 20/87] Fix PHP error "Only variables should be passed by reference" --- code/web/public_php/tools/nel_message.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/web/public_php/tools/nel_message.php b/code/web/public_php/tools/nel_message.php index c970b9f2c..ee3177f8d 100644 --- a/code/web/public_php/tools/nel_message.php +++ b/code/web/public_php/tools/nel_message.php @@ -86,9 +86,10 @@ } else { - $this->serialUInt32(strlen($val)); + $valLen = strlen($val); + $this->serialUInt32($valLen); $this->Buffer .= $val; - $this->Pos += strlen($val); + $this->Pos += $valLen; debug(sprintf ("write string '%s' %d
\n", $val, $this->Pos)); } } From d76c9c5018bfad791b5d8a2c9eebeb648deee470 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sat, 8 Nov 2014 00:29:50 +0100 Subject: [PATCH 21/87] Fix PHP error "Only variables should be passed by reference" --- code/web/public_php/admin/nel/nel_message.php | 5 +++-- code/web/public_php/tools/nel_message.php | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/code/web/public_php/admin/nel/nel_message.php b/code/web/public_php/admin/nel/nel_message.php index 5e704bff1..42dd91cbe 100644 --- a/code/web/public_php/admin/nel/nel_message.php +++ b/code/web/public_php/admin/nel/nel_message.php @@ -91,9 +91,10 @@ } else { - $this->serialUInt32(strlen($val)); + $valLen = strlen($val); + $this->serialUInt32($valLen); $this->Buffer .= $val; - $this->Pos += strlen($val); + $this->Pos += $valLen; debug(sprintf ("write string '%s' %d
\n", $val, $this->Pos)); } } diff --git a/code/web/public_php/tools/nel_message.php b/code/web/public_php/tools/nel_message.php index ee3177f8d..b696bb151 100644 --- a/code/web/public_php/tools/nel_message.php +++ b/code/web/public_php/tools/nel_message.php @@ -104,7 +104,8 @@ } else { - $this->serialUInt32($val->toInt()); + $intValue = $val->toInt(); + $this->serialUInt32($intValue); debug(sprintf ("write enum '%s' %d
\n", $val->toString(), $this->Pos)); } } From 6d6926a8b879550ebfafc3a519adc7bd0660b9ac Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 10 Nov 2014 23:34:41 +0100 Subject: [PATCH 22/87] ryzomcore/v0.11.0 --- code/CMakeLists.txt | 4 ++-- code/nel/tools/3d/plugin_max/nel_export/nel_export.rc | 8 ++++---- .../plugin_max/nel_patch_converter/nel_patch_converter.rc | 8 ++++---- code/nel/tools/3d/plugin_max/nel_patch_edit/mods.rc | 8 ++++---- .../3d/plugin_max/nel_patch_paint/nel_patch_paint.rc | 8 ++++---- .../plugin_max/nel_vertex_tree_paint/vertex_tree_paint.rc | 8 ++++---- code/nel/tools/3d/plugin_max/tile_utility/tile_utility.rc | 8 ++++---- code/ryzom/common/src/game_share/ryzom_version.h | 2 +- code/web/public_php/ams/templates/layout.tpl | 2 +- 9 files changed, 28 insertions(+), 28 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 071554e06..372177889 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -2,7 +2,7 @@ # # NeL # Authors: Nevrax and the NeL Community -# Version: 0.10.0 +# Version: 0.11.0 # # Notes: # * Changing install location: add -DCMAKE_INSTALL_PREFIX:PATH=/my/new/path @@ -47,7 +47,7 @@ CHECK_OUT_OF_SOURCE() CMAKE_MINIMUM_REQUIRED(VERSION 2.6) PROJECT(RyzomCore CXX C) SET(NL_VERSION_MAJOR 0) -SET(NL_VERSION_MINOR 10) +SET(NL_VERSION_MINOR 11) SET(NL_VERSION_PATCH 0) SET(NL_VERSION "${NL_VERSION_MAJOR}.${NL_VERSION_MINOR}.${NL_VERSION_PATCH}") diff --git a/code/nel/tools/3d/plugin_max/nel_export/nel_export.rc b/code/nel/tools/3d/plugin_max/nel_export/nel_export.rc index 57edca682..d01762618 100644 --- a/code/nel/tools/3d/plugin_max/nel_export/nel_export.rc +++ b/code/nel/tools/3d/plugin_max/nel_export/nel_export.rc @@ -575,8 +575,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0, 10, 0, 0 - PRODUCTVERSION 0, 10, 0, 0 + FILEVERSION 0, 11, 0, 0 + PRODUCTVERSION 0, 11, 0, 0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -593,14 +593,14 @@ BEGIN BEGIN VALUE "Comments", "Based on Kinetix 3D Studio Max 3.0 plugin sample\0" VALUE "CompanyName", "Ryzom Core\0" - VALUE "FileVersion", "0.10.0\0" + VALUE "FileVersion", "0.11.0\0" VALUE "InternalName", "CNelExport\0" VALUE "LegalCopyright", "\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "CNelExport.dlu\0" VALUE "PrivateBuild", "\0" VALUE "ProductName", "Ryzom Core\0" - VALUE "ProductVersion", "0.10.0\0" + VALUE "ProductVersion", "0.11.0\0" VALUE "SpecialBuild", "\0" END END diff --git a/code/nel/tools/3d/plugin_max/nel_patch_converter/nel_patch_converter.rc b/code/nel/tools/3d/plugin_max/nel_patch_converter/nel_patch_converter.rc index aa8749a3e..b6eea41a6 100644 --- a/code/nel/tools/3d/plugin_max/nel_patch_converter/nel_patch_converter.rc +++ b/code/nel/tools/3d/plugin_max/nel_patch_converter/nel_patch_converter.rc @@ -85,8 +85,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0, 10, 0, 0 - PRODUCTVERSION 0, 10, 0, 0 + FILEVERSION 0, 11, 0, 0 + PRODUCTVERSION 0, 11, 0, 0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -103,12 +103,12 @@ BEGIN BEGIN VALUE "Comments", "http://www.ryzomcore.org/" VALUE "FileDescription", "PatchMesh to RykolPatchMesh" - VALUE "FileVersion", "0.10.0" + VALUE "FileVersion", "0.11.0" VALUE "InternalName", "PatchMesh to RykolPatchMesh" VALUE "LegalCopyright", "Copyright, 2000 Nevrax Ltd." VALUE "OriginalFilename", "nel_convert_patch.dlm" VALUE "ProductName", "NeL Patch Converter" - VALUE "ProductVersion", "0.10.0" + VALUE "ProductVersion", "0.11.0" END END BLOCK "VarFileInfo" diff --git a/code/nel/tools/3d/plugin_max/nel_patch_edit/mods.rc b/code/nel/tools/3d/plugin_max/nel_patch_edit/mods.rc index adc44260e..243e02da8 100644 --- a/code/nel/tools/3d/plugin_max/nel_patch_edit/mods.rc +++ b/code/nel/tools/3d/plugin_max/nel_patch_edit/mods.rc @@ -514,8 +514,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0, 10, 0, 0 - PRODUCTVERSION 0, 10, 0, 0 + FILEVERSION 0, 11, 0, 0 + PRODUCTVERSION 0, 11, 0, 0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -533,13 +533,13 @@ BEGIN VALUE "Comments", "Based on Kinetix 3D Studio Max 3.0 plugin sample\0" VALUE "CompanyName", "Ryzom Core" VALUE "FileDescription", "NeL Patch Edit" - VALUE "FileVersion", "0.10.0" + VALUE "FileVersion", "0.11.0" VALUE "InternalName", "neleditpatch" VALUE "LegalCopyright", "Copyright © 2000 Nevrax Ltd. Copyright © 1998 Autodesk Inc." VALUE "LegalTrademarks", "The following are registered trademarks of Autodesk, Inc.: 3D Studio MAX. The following are trademarks of Autodesk, Inc.: Kinetix, Kinetix(logo), BIPED, Physique, Character Studio, MAX DWG, DWG Unplugged, Heidi, FLI, FLC, DXF." VALUE "OriginalFilename", "neleditpatch.dlm" VALUE "ProductName", "Ryzom Core" - VALUE "ProductVersion", "0.10.0" + VALUE "ProductVersion", "0.11.0" END END BLOCK "VarFileInfo" diff --git a/code/nel/tools/3d/plugin_max/nel_patch_paint/nel_patch_paint.rc b/code/nel/tools/3d/plugin_max/nel_patch_paint/nel_patch_paint.rc index fadbde308..534efb2ac 100644 --- a/code/nel/tools/3d/plugin_max/nel_patch_paint/nel_patch_paint.rc +++ b/code/nel/tools/3d/plugin_max/nel_patch_paint/nel_patch_paint.rc @@ -96,8 +96,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0, 10, 0, 0 - PRODUCTVERSION 0, 10, 0, 0 + FILEVERSION 0, 11, 0, 0 + PRODUCTVERSION 0, 11, 0, 0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -116,14 +116,14 @@ BEGIN VALUE "Comments", "TECH: cyril.corvazier\0" VALUE "CompanyName", "Ryzom Core\0" VALUE "FileDescription", "NeL Patch Paint\0" - VALUE "FileVersion", "0.10.0\0" + VALUE "FileVersion", "0.11.0\0" VALUE "InternalName", "mods\0" VALUE "LegalCopyright", "Copyright © 2000 Nevrax Ltd\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "nelpatchpaint.dlm\0" VALUE "PrivateBuild", "\0" VALUE "ProductName", "Ryzom Core\0" - VALUE "ProductVersion", "0.10.0\0" + VALUE "ProductVersion", "0.11.0\0" VALUE "SpecialBuild", "\0" END END diff --git a/code/nel/tools/3d/plugin_max/nel_vertex_tree_paint/vertex_tree_paint.rc b/code/nel/tools/3d/plugin_max/nel_vertex_tree_paint/vertex_tree_paint.rc index bf5fdd549..4e70d1afc 100644 --- a/code/nel/tools/3d/plugin_max/nel_vertex_tree_paint/vertex_tree_paint.rc +++ b/code/nel/tools/3d/plugin_max/nel_vertex_tree_paint/vertex_tree_paint.rc @@ -125,8 +125,8 @@ IDC_DROPPER_CURSOR CURSOR DISCARDABLE "dropcurs.cur" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0, 10, 0, 0 - PRODUCTVERSION 0, 10, 0, 0 + FILEVERSION 0, 11, 0, 0 + PRODUCTVERSION 0, 11, 0, 0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -145,13 +145,13 @@ BEGIN VALUE "Comments", "TECH: \0" VALUE "CompanyName", "Ryzom Core\0" VALUE "FileDescription", "Vertex Tree Paint\0" - VALUE "FileVersion", "0.10.0\0" + VALUE "FileVersion", "0.11.0\0" VALUE "InternalName", "VertexTreePaint\0" VALUE "LegalCopyright", "Copyright © 2000 Nevrax Ltd. Copyright © 1998 Autodesk Inc.\0" VALUE "LegalTrademarks", "The following are registered trademarks of Autodesk, Inc.: 3D Studio MAX. The following are trademarks of Autodesk, Inc.: Kinetix, Kinetix(logo), BIPED, Physique, Character Studio, MAX DWG, DWG Unplugged, Heidi, FLI, FLC, DXF.\0" VALUE "OriginalFilename", "nel_vertex_tree_paint.dlm\0" VALUE "ProductName", "Ryzom Core\0" - VALUE "ProductVersion", "0.10.0\0" + VALUE "ProductVersion", "0.11.0\0" END END BLOCK "VarFileInfo" diff --git a/code/nel/tools/3d/plugin_max/tile_utility/tile_utility.rc b/code/nel/tools/3d/plugin_max/tile_utility/tile_utility.rc index c6118c2f8..80d1d390d 100644 --- a/code/nel/tools/3d/plugin_max/tile_utility/tile_utility.rc +++ b/code/nel/tools/3d/plugin_max/tile_utility/tile_utility.rc @@ -124,8 +124,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0, 10, 0, 0 - PRODUCTVERSION 0, 10, 0, 0 + FILEVERSION 0, 11, 0, 0 + PRODUCTVERSION 0, 11, 0, 0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -142,12 +142,12 @@ BEGIN BEGIN VALUE "Comments", "Based on Kinetix 3D Studio Max 3.0 plugin sample\0" VALUE "CompanyName", "Ryzom Core\0" - VALUE "FileVersion", "0.10.0\0" + VALUE "FileVersion", "0.11.0\0" VALUE "InternalName", "Tile_utility\0" VALUE "LegalCopyright", "\0" VALUE "OriginalFilename", "Tile_utility.dlu\0" VALUE "ProductName", "Ryzom Core\0" - VALUE "ProductVersion", "0.10.0\0" + VALUE "ProductVersion", "0.11.0\0" VALUE "FileDescription", "Create material for tiles\0" VALUE "Comments", "TECH: \0" VALUE "LegalTrademarks", "\0" diff --git a/code/ryzom/common/src/game_share/ryzom_version.h b/code/ryzom/common/src/game_share/ryzom_version.h index 1c13b7ed1..af714db4d 100644 --- a/code/ryzom/common/src/game_share/ryzom_version.h +++ b/code/ryzom/common/src/game_share/ryzom_version.h @@ -17,7 +17,7 @@ #ifndef RYZOM_VERSION_H #define RYZOM_VERSION_H -#define RYZOM_VERSION "ryzomcore/v0.10.0-dev" +#define RYZOM_VERSION "ryzomcore/v0.11.0-dev" #endif // RYZOM_VERSION_H diff --git a/code/web/public_php/ams/templates/layout.tpl b/code/web/public_php/ams/templates/layout.tpl index c949263d1..33dbf3be0 100644 --- a/code/web/public_php/ams/templates/layout.tpl +++ b/code/web/public_php/ams/templates/layout.tpl @@ -167,7 +167,7 @@
- {if $permission > 1}

AMS 0.10.0 Powered by: Charisma

{/if} + {if $permission > 1}

AMS 0.11.0 Powered by: Charisma

{/if}
{/if} From 2e94bc1d154e57e1650076a1a3ec5ec6d9770a9f Mon Sep 17 00:00:00 2001 From: kaetemi Date: Wed, 19 Nov 2014 16:30:14 +0100 Subject: [PATCH 26/87] Fix bug causing patch painter fail to open more than once --- code/nel/src/3d/driver/opengl/driver_opengl_window.cpp | 1 + 1 file changed, 1 insertion(+) 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 5bea65771..9df2a53f9 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp @@ -463,6 +463,7 @@ bool CDriverGL::unInit() { nlwarning("Can't unregister NLClass"); } + _Registered = 0; // Restaure monitor color parameters if (_NeedToRestaureGammaRamp) From 899c0c441e6be8d7616f0ebd97c26a2459f6b00f Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 24 Nov 2014 14:53:28 +0100 Subject: [PATCH 27/87] Fix #218 erratic mouse behaviour --- code/ryzom/client/src/events_listener.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/code/ryzom/client/src/events_listener.cpp b/code/ryzom/client/src/events_listener.cpp index 89963a2ab..760a5dc08 100644 --- a/code/ryzom/client/src/events_listener.cpp +++ b/code/ryzom/client/src/events_listener.cpp @@ -184,8 +184,8 @@ void CEventsListener::operator()(const CEvent& event) } // NOTE: No 0, 0 center mouse message in Windows (lower mouse message rate), but safe to assume any movement messages are requeued relative to our new position - // In case free look bugs on other platform, we may need to push in our own message on setMousePos for Windows - if (s_MouseFreeLookWaitCenter) // scX == 0 && scY == 0) + bool outsideBounds = ((abs(scX) > (drW >> 3)) || (abs(scY) > (drH >> 3))); + if (s_MouseFreeLookWaitCenter && !outsideBounds) { // Centered, set last to 0 s_MouseFreeLookLastX = 0; @@ -204,8 +204,7 @@ void CEventsListener::operator()(const CEvent& event) // updateFreeLookPos is called in updateMouseSmoothing per frame // Center cursor - bool outsideBounds = ((abs(scX) > (drW >> 3)) || (abs(scY) > (drH >> 3))); - if (outsideBounds) + if (outsideBounds && !s_MouseFreeLookWaitCenter) { s_MouseFreeLookWaitCenter = true; Driver->setMousePos(0.5f, 0.5f); From 1a5f3a2875ab4c685d2b7b6ac16ca3e1412db3f8 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 24 Nov 2014 14:57:36 +0100 Subject: [PATCH 28/87] ryzomcore/v0.11.1 --- code/CMakeLists.txt | 4 ++-- .../3d/plugin_max/nel_patch_paint/nel_patch_paint.rc | 8 ++++---- code/ryzom/common/src/game_share/ryzom_version.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 372177889..bd36abe61 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -2,7 +2,7 @@ # # NeL # Authors: Nevrax and the NeL Community -# Version: 0.11.0 +# Version: 0.11.1 # # Notes: # * Changing install location: add -DCMAKE_INSTALL_PREFIX:PATH=/my/new/path @@ -48,7 +48,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) PROJECT(RyzomCore CXX C) SET(NL_VERSION_MAJOR 0) SET(NL_VERSION_MINOR 11) -SET(NL_VERSION_PATCH 0) +SET(NL_VERSION_PATCH 1) SET(NL_VERSION "${NL_VERSION_MAJOR}.${NL_VERSION_MINOR}.${NL_VERSION_PATCH}") #----------------------------------------------------------------------------- diff --git a/code/nel/tools/3d/plugin_max/nel_patch_paint/nel_patch_paint.rc b/code/nel/tools/3d/plugin_max/nel_patch_paint/nel_patch_paint.rc index 534efb2ac..507d36ab5 100644 --- a/code/nel/tools/3d/plugin_max/nel_patch_paint/nel_patch_paint.rc +++ b/code/nel/tools/3d/plugin_max/nel_patch_paint/nel_patch_paint.rc @@ -96,8 +96,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0, 11, 0, 0 - PRODUCTVERSION 0, 11, 0, 0 + FILEVERSION 0, 11, 1, 0 + PRODUCTVERSION 0, 11, 1, 0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -116,14 +116,14 @@ BEGIN VALUE "Comments", "TECH: cyril.corvazier\0" VALUE "CompanyName", "Ryzom Core\0" VALUE "FileDescription", "NeL Patch Paint\0" - VALUE "FileVersion", "0.11.0\0" + VALUE "FileVersion", "0.11.1\0" VALUE "InternalName", "mods\0" VALUE "LegalCopyright", "Copyright © 2000 Nevrax Ltd\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "nelpatchpaint.dlm\0" VALUE "PrivateBuild", "\0" VALUE "ProductName", "Ryzom Core\0" - VALUE "ProductVersion", "0.11.0\0" + VALUE "ProductVersion", "0.11.1\0" VALUE "SpecialBuild", "\0" END END diff --git a/code/ryzom/common/src/game_share/ryzom_version.h b/code/ryzom/common/src/game_share/ryzom_version.h index af714db4d..de4524626 100644 --- a/code/ryzom/common/src/game_share/ryzom_version.h +++ b/code/ryzom/common/src/game_share/ryzom_version.h @@ -17,7 +17,7 @@ #ifndef RYZOM_VERSION_H #define RYZOM_VERSION_H -#define RYZOM_VERSION "ryzomcore/v0.11.0-dev" +#define RYZOM_VERSION "ryzomcore/v0.11.1" #endif // RYZOM_VERSION_H From ea2544902984f69bd7f872809ba1084ff9453886 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Thu, 4 Dec 2014 13:21:12 +0100 Subject: [PATCH 29/87] Fix crash with patch mesh attach --- code/nel/tools/3d/plugin_max/nel_patch_edit/np_epm_attach.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/tools/3d/plugin_max/nel_patch_edit/np_epm_attach.cpp b/code/nel/tools/3d/plugin_max/nel_patch_edit/np_epm_attach.cpp index 64a3296f0..d2843df1c 100644 --- a/code/nel/tools/3d/plugin_max/nel_patch_edit/np_epm_attach.cpp +++ b/code/nel/tools/3d/plugin_max/nel_patch_edit/np_epm_attach.cpp @@ -37,7 +37,6 @@ int EditPatchMod::DoAttach(INode *node, PatchMesh *attPatch, RPatchMesh *rattPat nodes.DisposeTemporary(); return 0; } - patchData->BeginEdit(ip->GetTime()); // If the mesh isn't yet cached, this will cause it to get cached. RPatchMesh *rpatch; @@ -49,6 +48,7 @@ int EditPatchMod::DoAttach(INode *node, PatchMesh *attPatch, RPatchMesh *rattPat } patchData->RecordTopologyTags(patch); RecordTopologyTags(); + patchData->BeginEdit(ip->GetTime()); // Transform the shape for attachment: // If reorienting, just translate to align pivots From fe5c94505f26752a10d52cdb71919da9975b9939 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 21 Dec 2014 22:55:27 +0100 Subject: [PATCH 30/87] CCtrlTextbutton checkcoords should call it's text's checkcoords method. Fix #219. --- code/nel/include/nel/gui/ctrl_text_button.h | 1 + code/nel/src/gui/ctrl_text_button.cpp | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/code/nel/include/nel/gui/ctrl_text_button.h b/code/nel/include/nel/gui/ctrl_text_button.h index d2b49ffa9..4f5251a8b 100644 --- a/code/nel/include/nel/gui/ctrl_text_button.h +++ b/code/nel/include/nel/gui/ctrl_text_button.h @@ -51,6 +51,7 @@ namespace NLGUI // Init part virtual bool parse (xmlNodePtr cur,CInterfaceGroup * parentGroup); + virtual void checkCoords(); virtual void updateCoords(); virtual uint32 getMemory() { return (uint32)(sizeof(*this)+_Id.size()); } diff --git a/code/nel/src/gui/ctrl_text_button.cpp b/code/nel/src/gui/ctrl_text_button.cpp index cdf9ea0d2..2fb19a9fc 100644 --- a/code/nel/src/gui/ctrl_text_button.cpp +++ b/code/nel/src/gui/ctrl_text_button.cpp @@ -868,6 +868,15 @@ namespace NLGUI } } + // *************************************************************************** + void CCtrlTextButton::checkCoords() + { + if( _ViewText != NULL ) + _ViewText->checkCoords(); + + CCtrlBaseButton::checkCoords(); + } + // *************************************************************************** void CCtrlTextButton::updateCoords() From c522248f2d64a9d18733ca62659959c68d8d345e Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 22 Dec 2014 14:21:01 +0100 Subject: [PATCH 31/87] ryzomcore/v0.11.2 --- code/CMakeLists.txt | 4 ++-- code/nel/tools/3d/plugin_max/nel_patch_edit/mods.rc | 8 ++++---- code/ryzom/common/src/game_share/ryzom_version.h | 5 ++++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index bd36abe61..0f9a72ac6 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -2,7 +2,7 @@ # # NeL # Authors: Nevrax and the NeL Community -# Version: 0.11.1 +# Version: 0.11.2 # # Notes: # * Changing install location: add -DCMAKE_INSTALL_PREFIX:PATH=/my/new/path @@ -48,7 +48,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) PROJECT(RyzomCore CXX C) SET(NL_VERSION_MAJOR 0) SET(NL_VERSION_MINOR 11) -SET(NL_VERSION_PATCH 1) +SET(NL_VERSION_PATCH 2) SET(NL_VERSION "${NL_VERSION_MAJOR}.${NL_VERSION_MINOR}.${NL_VERSION_PATCH}") #----------------------------------------------------------------------------- diff --git a/code/nel/tools/3d/plugin_max/nel_patch_edit/mods.rc b/code/nel/tools/3d/plugin_max/nel_patch_edit/mods.rc index 243e02da8..6de328356 100644 --- a/code/nel/tools/3d/plugin_max/nel_patch_edit/mods.rc +++ b/code/nel/tools/3d/plugin_max/nel_patch_edit/mods.rc @@ -514,8 +514,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0, 11, 0, 0 - PRODUCTVERSION 0, 11, 0, 0 + FILEVERSION 0, 11, 2, 0 + PRODUCTVERSION 0, 11, 2, 0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -533,13 +533,13 @@ BEGIN VALUE "Comments", "Based on Kinetix 3D Studio Max 3.0 plugin sample\0" VALUE "CompanyName", "Ryzom Core" VALUE "FileDescription", "NeL Patch Edit" - VALUE "FileVersion", "0.11.0" + VALUE "FileVersion", "0.11.2" VALUE "InternalName", "neleditpatch" VALUE "LegalCopyright", "Copyright © 2000 Nevrax Ltd. Copyright © 1998 Autodesk Inc." VALUE "LegalTrademarks", "The following are registered trademarks of Autodesk, Inc.: 3D Studio MAX. The following are trademarks of Autodesk, Inc.: Kinetix, Kinetix(logo), BIPED, Physique, Character Studio, MAX DWG, DWG Unplugged, Heidi, FLI, FLC, DXF." VALUE "OriginalFilename", "neleditpatch.dlm" VALUE "ProductName", "Ryzom Core" - VALUE "ProductVersion", "0.11.0" + VALUE "ProductVersion", "0.11.2" END END BLOCK "VarFileInfo" diff --git a/code/ryzom/common/src/game_share/ryzom_version.h b/code/ryzom/common/src/game_share/ryzom_version.h index de4524626..915f9ed1c 100644 --- a/code/ryzom/common/src/game_share/ryzom_version.h +++ b/code/ryzom/common/src/game_share/ryzom_version.h @@ -17,7 +17,10 @@ #ifndef RYZOM_VERSION_H #define RYZOM_VERSION_H -#define RYZOM_VERSION "ryzomcore/v0.11.1" +#define RYZOM_VERSION "ryzomcore" \ + "/" \ + "v0.11.2" \ + "" #endif // RYZOM_VERSION_H From 566a5b6e86709c5c536ca081feac89327b0611c5 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 22 Dec 2014 16:39:54 +0100 Subject: [PATCH 32/87] Fix mirror type sizes --- code/ryzom/common/src/game_share/ryzom_mirror_properties.h | 2 +- code/ryzom/server/data_shard/mirror_sheets/fe_temp.dataset | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/ryzom/common/src/game_share/ryzom_mirror_properties.h b/code/ryzom/common/src/game_share/ryzom_mirror_properties.h index 55d8b9bbb..134ebe38b 100644 --- a/code/ryzom/common/src/game_share/ryzom_mirror_properties.h +++ b/code/ryzom/common/src/game_share/ryzom_mirror_properties.h @@ -138,7 +138,7 @@ void initRyzomVisualPropertyIndices( CMirroredDataSet& dataset ); #define TYPE_BOT_TRADE_SELECTOR2 uint64 #define TYPE_EVENT_FACTION_ID uint32 -#define TYPE_PVP_MODE uint32 +#define TYPE_PVP_MODE uint16 #define TYPE_PVP_CLAN uint32 #define TYPE_FUEL bool diff --git a/code/ryzom/server/data_shard/mirror_sheets/fe_temp.dataset b/code/ryzom/server/data_shard/mirror_sheets/fe_temp.dataset index f88263c27..b891b6252 100644 --- a/code/ryzom/server/data_shard/mirror_sheets/fe_temp.dataset +++ b/code/ryzom/server/data_shard/mirror_sheets/fe_temp.dataset @@ -292,14 +292,14 @@ - + - + From 44760221f274ee0c7b925078bc5d8934dbf07139 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 1 Feb 2015 20:29:26 +0100 Subject: [PATCH 33/87] Initialize Nel3D in the Object Viewer plugin too. --- code/nel/src/3d/driver_user.cpp | 15 +------------- code/nel/src/3d/init_3d.cpp | 20 ++++++++++++++++++- .../object_viewer/object_viewer_plugin.cpp | 3 +++ 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/code/nel/src/3d/driver_user.cpp b/code/nel/src/3d/driver_user.cpp index c4dc97655..017a2b6dc 100644 --- a/code/nel/src/3d/driver_user.cpp +++ b/code/nel/src/3d/driver_user.cpp @@ -109,10 +109,6 @@ void UDriver::purgeMemory() // *************************************************************************** -// *************************************************************************** -bool CDriverUser::_StaticInit= false; - - // *************************************************************************** CDriverUser::CDriverUser (uintptr_t windowIcon, TDriver driver, emptyProc exitFunc) { @@ -122,16 +118,7 @@ CDriverUser::CDriverUser (uintptr_t windowIcon, TDriver driver, emptyProc exitFu nlassert((uint)IDriver::iconCount == (uint)UDriver::iconCount); - // Static Initialisation. - if(!_StaticInit) - { - _StaticInit= true; - // Register basic serial. - NL3D::registerSerial3d(); - - // Register basic csene. - CScene::registerBasics(); - } + NL3D::init3d(); _Driver = NULL; diff --git a/code/nel/src/3d/init_3d.cpp b/code/nel/src/3d/init_3d.cpp index bd8dffdfd..4ba439b73 100644 --- a/code/nel/src/3d/init_3d.cpp +++ b/code/nel/src/3d/init_3d.cpp @@ -19,18 +19,36 @@ #include "nel/3d/init_3d.h" #include +#include "nel/3d/scene.h" +#include "nel/3d/register_3d.h" + +namespace +{ +static bool _Initialized = false; +} namespace NL3D { void init3d () { + + if( _Initialized ) + return; + // Init for windows #ifdef NL_OS_WINDOWS // Enable FPU exceptions // Enable divid by zero and overflow exception - _control87 (_EM_INVALID|_EM_DENORMAL/*|_EM_ZERODIVIDE|_EM_OVERFLOW*/|_EM_UNDERFLOW|_EM_INEXACT, _MCW_EM); + //_control87 (_EM_INVALID|_EM_DENORMAL/*|_EM_ZERODIVIDE|_EM_OVERFLOW*/|_EM_UNDERFLOW|_EM_INEXACT, _MCW_EM); + + NL3D::registerSerial3d(); + CScene::registerBasics(); + + _Initialized = true; + + #endif // NL_OS_WINDOWS } diff --git a/code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp b/code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp index dce7ad08f..a4c948140 100644 --- a/code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp +++ b/code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp @@ -8,6 +8,7 @@ // NeL includes #include "nel/misc/debug.h" +#include "nel/3d/init_3d.h" // Qt includes #include @@ -32,6 +33,8 @@ bool ObjectViewerPlugin::initialize(ExtensionSystem::IPluginManager *pluginManag { Q_UNUSED(errorString); _plugMan = pluginManager; + + NL3D::init3d(); Modules::init(); addAutoReleasedObject(new CObjectViewerContext()); addAutoReleasedObject(new GraphicsSettingsPage()); From 8498b4aacd4c353a64e9d600a5261fe9c1de81db Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 2 Feb 2015 22:01:16 +0100 Subject: [PATCH 34/87] Fixed build of Object Viewer Widget Qt ( old, not part of Studio ). --- .../3d/object_viewer_widget/src/object_viewer_widget.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_widget/src/object_viewer_widget.cpp b/code/nel/tools/3d/object_viewer_widget/src/object_viewer_widget.cpp index af026b3df..4d0936a1a 100644 --- a/code/nel/tools/3d/object_viewer_widget/src/object_viewer_widget.cpp +++ b/code/nel/tools/3d/object_viewer_widget/src/object_viewer_widget.cpp @@ -185,7 +185,7 @@ namespace NLQT NL3D::CBloomEffect::instance().setDriver(_Driver); NL3D::CBloomEffect::instance().setScene(_Scene); - NL3D::CBloomEffect::instance().init(!_Direct3D); + NL3D::CBloomEffect::instance().init(); //NL3D::CBloomEffect::instance().setDensityBloom(Modules::config().getConfigFile().getVar("BloomDensity").asInt()); //NL3D::CBloomEffect::instance().setSquareBloom(Modules::config().getConfigFile().getVar("BloomSquare").asBool()); } @@ -366,7 +366,7 @@ namespace NLQT // Render the scene. if((NL3D::CBloomEffect::instance().getDriver() != NULL) && (_BloomEffect)) { - NL3D::CBloomEffect::instance().initBloom(); + NL3D::CBloomEffect::instance().init(); } _Driver->clearBuffers(_BackgroundColor); } @@ -378,8 +378,7 @@ namespace NLQT if((NL3D::CBloomEffect::instance().getDriver() != NULL) && (_BloomEffect)) { - NL3D::CBloomEffect::instance().endBloom(); - NL3D::CBloomEffect::instance().endInterfacesDisplayBloom(); + NL3D::CBloomEffect::instance().applyBloom(); } } From c4fa07e1a9a0817acdd8dbf8b8f498638dfdeee5 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 2 Feb 2015 22:41:29 +0100 Subject: [PATCH 35/87] Install tile editor's plugin spec to the right directory. --- .../studio/src/plugins/tile_editor/CMakeLists.txt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/CMakeLists.txt b/code/studio/src/plugins/tile_editor/CMakeLists.txt index 78cc5ef49..bfb9f3440 100644 --- a/code/studio/src/plugins/tile_editor/CMakeLists.txt +++ b/code/studio/src/plugins/tile_editor/CMakeLists.txt @@ -46,5 +46,18 @@ NL_ADD_LIB_SUFFIX(studio_plugin_tile_editor) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) -INSTALL(TARGETS studio_plugin_tile_editor LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) +IF(WIN32) + IF(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS studio_plugin_tile_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + ELSE(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS studio_plugin_tile_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + ENDIF(WITH_INSTALL_LIBRARIES) +ELSE(WIN32) + IF(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS studio_plugin_tile_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + ELSE(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS studio_plugin_tile_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + ENDIF(WITH_INSTALL_LIBRARIES) +ENDIF(WIN32) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_tile_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) From 94338a374245878afa278f1558dde529874b38fa Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 2 Feb 2015 22:51:43 +0100 Subject: [PATCH 36/87] Some CPack renames. --- code/CMakeLists.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 0f9a72ac6..500331c43 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -1,7 +1,7 @@ #----------------------------------------------------------------------------- # -# NeL -# Authors: Nevrax and the NeL Community +# Ryzom Core +# Authors: Nevrax and the Ryzom Core Community # Version: 0.11.2 # # Notes: @@ -228,30 +228,30 @@ IF(WITH_NEL_TESTS) ENDIF(WITH_NEL_TESTS) # packaging information -SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "NeL MMORPG Framework") -SET(CPACK_PACKAGE_VENDOR "NeL") +SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Ryzom Core MMORPG Framework") +SET(CPACK_PACKAGE_VENDOR "Ryzom Core") SET(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_SOURCE_DIR}/README) SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/COPYING) SET(CPACK_PACKAGE_VERSION_MAJOR "${NL_VERSION_MAJOR}") SET(CPACK_PACKAGE_VERSION_MINOR "${NL_VERSION_MINOR}") SET(CPACK_PACKAGE_VERSION_PATCH "${NL_VERSION_PATCH}") SET(CPACK_INSTALL_CMAKE_PROJECTS "${CMAKE_BINARY_DIR};NeL;ALL;/") -SET(CPACK_PACKAGE_EXECUTABLES "nel${NL_VERSION}" "nel") +SET(CPACK_PACKAGE_EXECUTABLES "ryzomcore${NL_VERSION}" "ryzomcore") # NSIS Specific Packing Setup -SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "NeL") +SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "RyzomCore") SET(CPACK_NSIS_MODIFY_PATH "ON") SET(CPACK_NSIS_MUI_ICON ${CMAKE_SOURCE_DIR}/resources/nevraxpill.ico) SET(CPACK_NSIS_MUI_UNIICON ${CMAKE_SOURCE_DIR}/resources/nevraxpill.ico) SET(CPACK_PACKAGE_ICON ${CMAKE_SOURCE_DIR}/resources\\\\nel.bmp) -SET(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} NeL") +SET(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} RyzomCore") SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\dev.ryzom.com") SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\dev.ryzom.com\\\\projects\\\\nel\\\\wiki") SET(CPACK_NSIS_CONTACT "matt.raykowski@gmail.com") ## Source Packages -SET(CPACK_PACKAGE_FILE_NAME "nel-${NL_VERSION}") -SET(CPACK_SOURCE_PACKAGE_FILE_NAME "nel-${NL_VERSION}") +SET(CPACK_PACKAGE_FILE_NAME "ryzomcore-${NL_VERSION}") +SET(CPACK_SOURCE_PACKAGE_FILE_NAME "ryzomcore-${NL_VERSION}") IF(WIN32) #SET(CPACK_GENERATOR "NSIS") SET(CPACK_GENERATOR "NSIS;ZIP") From b5e9dfbc9e336c4a47bf34be1119ee01928cd9d2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 2 Feb 2015 23:25:11 +0100 Subject: [PATCH 37/87] Use release squish if debug not found. Fixes s3tc compressor tool build. --- code/CMakeModules/FindSquish.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/CMakeModules/FindSquish.cmake b/code/CMakeModules/FindSquish.cmake index ad0f7ce80..61250fec1 100644 --- a/code/CMakeModules/FindSquish.cmake +++ b/code/CMakeModules/FindSquish.cmake @@ -55,10 +55,12 @@ FIND_LIBRARY(SQUISH_LIBRARY_DEBUG IF(SQUISH_INCLUDE_DIR) IF(SQUISH_LIBRARY_RELEASE) SET(SQUISH_FOUND "YES") - SET(SQUISH_LIBRARIES "optimized;${SQUISH_LIBRARY_RELEASE}") IF(SQUISH_LIBRARY_DEBUG) SET(SQUISH_LIBRARIES "${SQUISH_LIBRARIES};debug;${SQUISH_LIBRARY_DEBUG}") + ELSE(SQUISH_LIBRARY_DEBUG) + SET(SQUISH_LIBRARIES "${SQUISH_LIBRARIES};debug;${SQUISH_LIBRARY_RELEASE}") + MESSAGE("Debug Squish NOT found, using the release version!") ENDIF(SQUISH_LIBRARY_DEBUG) ENDIF(SQUISH_LIBRARY_RELEASE) ENDIF(SQUISH_INCLUDE_DIR) From 689a9e0883fd63d6502bbe6262186f0f74e8e723 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 5 Feb 2015 23:50:38 +0100 Subject: [PATCH 38/87] We need the LIGO config file, not directory in the first start settings dialog. --- code/studio/src/settings_dialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/studio/src/settings_dialog.cpp b/code/studio/src/settings_dialog.cpp index 78773a666..df2718b9b 100644 --- a/code/studio/src/settings_dialog.cpp +++ b/code/studio/src/settings_dialog.cpp @@ -170,7 +170,8 @@ void SettingsDialog::onPrimitivesBClicked() void SettingsDialog::onLigoBClicked() { - QString p = QFileDialog::getExistingDirectory( this, tr( "LIGO directory" ), "" ); + QString p; + p = QFileDialog::getOpenFileName( this, tr( "LIGO config file" ), "" ); ligoLE->setText( p ); } From 47f43b2a2e33b8d6a7d50aead108b0d05c703f7a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 6 Feb 2015 00:31:51 +0100 Subject: [PATCH 39/87] CPack should use the install prefix. --- code/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 500331c43..dcc9f9c93 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -237,6 +237,7 @@ SET(CPACK_PACKAGE_VERSION_MINOR "${NL_VERSION_MINOR}") SET(CPACK_PACKAGE_VERSION_PATCH "${NL_VERSION_PATCH}") SET(CPACK_INSTALL_CMAKE_PROJECTS "${CMAKE_BINARY_DIR};NeL;ALL;/") SET(CPACK_PACKAGE_EXECUTABLES "ryzomcore${NL_VERSION}" "ryzomcore") +SET(CPACK_SET_DESTDIR TRUE) # NSIS Specific Packing Setup SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "RyzomCore") From 23873f2e3a10bdcd3b03562046d199425754ede7 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 6 Feb 2015 02:29:33 +0100 Subject: [PATCH 40/87] Erm. Initialize Nel3D on other platforms too... --- code/nel/src/3d/init_3d.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/nel/src/3d/init_3d.cpp b/code/nel/src/3d/init_3d.cpp index 4ba439b73..b2bf2c05e 100644 --- a/code/nel/src/3d/init_3d.cpp +++ b/code/nel/src/3d/init_3d.cpp @@ -42,14 +42,12 @@ void init3d () // Enable divid by zero and overflow exception //_control87 (_EM_INVALID|_EM_DENORMAL/*|_EM_ZERODIVIDE|_EM_OVERFLOW*/|_EM_UNDERFLOW|_EM_INEXACT, _MCW_EM); +#endif // NL_OS_WINDOWS NL3D::registerSerial3d(); CScene::registerBasics(); _Initialized = true; - - -#endif // NL_OS_WINDOWS } } // NL3D From eaf5d26baefb85094bc8c3b0302aa020d5da16cd Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Feb 2015 00:24:29 +0100 Subject: [PATCH 41/87] Handle relative paths when loading .worldedit files in World Editor. --- code/nel/include/nel/misc/path.h | 7 +++ code/nel/src/misc/path.cpp | 51 +++++++++++++++++++ .../world_editor/world_editor_misc.cpp | 7 +++ 3 files changed, 65 insertions(+) diff --git a/code/nel/include/nel/misc/path.h b/code/nel/include/nel/misc/path.h index f3120c907..cd19c43ee 100644 --- a/code/nel/include/nel/misc/path.h +++ b/code/nel/include/nel/misc/path.h @@ -507,6 +507,13 @@ public: */ static bool makePathRelative (const char *basePath, std::string &relativePath); + /** Make path absolute + * \param relativePath - The relative path + * \param directory - the directory to which the path is relative to + * returns the absolute path, or empty if something went wrong. + */ + static std::string makePathAbsolute (const std::string &relativePath, const std::string &directory ); + /** If File in this list is added more than one in an addSearchPath, it doesn't launch a warning. */ static void addIgnoredDoubleFile(const std::string &ignoredFile); diff --git a/code/nel/src/misc/path.cpp b/code/nel/src/misc/path.cpp index d47b8ce4a..2a25276e8 100644 --- a/code/nel/src/misc/path.cpp +++ b/code/nel/src/misc/path.cpp @@ -2544,6 +2544,57 @@ bool CPath::makePathRelative (const char *basePath, std::string &relativePath) return false; } +std::string CPath::makePathAbsolute( const std::string &relativePath, const std::string &directory ) +{ + if( relativePath.empty() ) + return ""; + if( directory.empty() ) + return ""; + +#ifdef NL_OS_WINDOWS + // Windows network address. Eg.: \\someshare\path + if( ( relativePath[ 0 ] == '\\' ) && ( relativePath[ 1 ] == '\\' ) ) + return relativePath; + + // Normal Windows absolute path. Eg.: C:\something + // + if( isalpha( relativePath[ 0 ] ) && ( relativePath[ 1 ] == ':' ) && ( ( relativePath[ 2 ] == '\\' ) || ( relativePath[ 2 ] == '/' ) ) ) + return relativePath; +#else + // Unix filesystem absolute path + if( relativePath[ 0 ] == '/' ) + return relativePath; + +#endif + + // Add a slash to the directory if necessary. + // If the relative path starts with dots we need a slash. + // If the relative path starts with a slash we don't. + // If it starts with neither, we need a slash. + bool needSlash = true; + char c = relativePath[ 0 ]; + if( ( c == '\\' ) || ( c == '/' ) ) + needSlash = false; + + bool hasSlash = false; + std::string npath = directory; + c = npath[ npath.size() - 1 ]; + if( ( c == '\\' ) || ( c == '/' ) ) + hasSlash = true; + + if( needSlash && !hasSlash ) + npath += '/'; + else + if( hasSlash && !needSlash ) + npath.resize( npath.size() - 1 ); + + // Now build the new absolute path + npath += relativePath; + npath = standardizePath( npath, false ); + + return npath; +} + bool CFile::setRWAccess(const std::string &filename) { #ifdef NL_OS_WINDOWS diff --git a/code/studio/src/plugins/world_editor/world_editor_misc.cpp b/code/studio/src/plugins/world_editor/world_editor_misc.cpp index 5d6b7f94e..a2736b1c5 100644 --- a/code/studio/src/plugins/world_editor/world_editor_misc.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_misc.cpp @@ -59,6 +59,8 @@ bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList lastError = ""; + std::string p = NLMISC::CFile::getPath( fileName ); + // Load the document NLMISC::CIFile file; if (file.open(fileName)) @@ -122,6 +124,8 @@ bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList { std::string dataDir; NLMISC::CIXml::getPropertyString(dataDir, node, "VALUE"); + + dataDir = NLMISC::CPath::makePathAbsolute( dataDir, p ); worldEditList.push_back(WorldEditItem(DataDirectoryType, dataDir)); } @@ -149,6 +153,9 @@ bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList std::string filenameChild; if ( NLMISC::CIXml::getPropertyString(filenameChild, node, "FILENAME")) { + + filenameChild = NLMISC::CPath::makePathAbsolute( filenameChild, p ); + // Is it a landscape ? if (type == "landscape") { From 1c31ac6f0553d59144cf9a364e9b4b255323ea61 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Feb 2015 23:46:33 +0100 Subject: [PATCH 42/87] Install the GUI Editor widget and expression definition files to the data dir. --- code/studio/src/plugins/gui_editor/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index e1e8b38be..3813bec67 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -112,3 +112,9 @@ ELSE(WIN32) ENDIF(WIN32) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_gui_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) + +FILE(GLOB widgets "${CMAKE_CURRENT_SOURCE_DIR}/widgets/*.xml") +FILE(GLOB expressions "${CMAKE_CURRENT_SOURCE_DIR}/expressions/*.xml") + +INSTALL(FILES ${widgets} DESTINATION "${OVQT_DATA_DIR}/widgets" COMPONENT tools3d) +INSTALL(FILES ${expressions} DESTINATION "${OVQT_DATA_DIR}/expressions" COMPONENT tools3d) From 4ea7c2025df9218289fe06e3f085c1530d6fba2a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Feb 2015 01:48:39 +0100 Subject: [PATCH 43/87] Read the GUI Editor widget and expression definition XML files from the right directory. --- code/studio/CMakeLists.txt | 3 +++ code/studio/src/plugins/gui_editor/CMakeLists.txt | 2 ++ code/studio/src/plugins/gui_editor/expression_store.cpp | 3 ++- .../src/plugins/gui_editor/gui_editor_config.h.cmake | 8 ++++++++ .../src/plugins/gui_editor/widget_properties_parser.cpp | 5 +++-- 5 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 code/studio/src/plugins/gui_editor/gui_editor_config.h.cmake diff --git a/code/studio/CMakeLists.txt b/code/studio/CMakeLists.txt index bf9ee062c..c10f2ea59 100644 --- a/code/studio/CMakeLists.txt +++ b/code/studio/CMakeLists.txt @@ -10,15 +10,18 @@ IF(WIN32) SET(OVQT_PLUGIN_SPECS_DIR "plugins") SET(OVQT_PLUGIN_DIR "plugins") SET(OVQT_DATA_DIR ".") + SET(OVQT_IMP_DATA_DIR "${OVQT_DATA_DIR}") ELSEIF(APPLE) # TODO: under Mac OS X, don't install but copy files in application package SET(OVQT_PLUGIN_SPECS_DIR "plugins") SET(OVQT_PLUGIN_DIR "plugins") SET(OVQT_DATA_DIR ".") + SET(OVQT_IMP_DATA_DIR "${OVQT_DATA_DIR}") ELSE(WIN32) SET(OVQT_PLUGIN_SPECS_DIR ${NL_SHARE_PREFIX}/studio/plugins) SET(OVQT_PLUGIN_DIR ${NL_LIB_PREFIX}/studio) SET(OVQT_DATA_DIR ${NL_SHARE_PREFIX}/studio/data) + SET(OVQT_IMP_DATA_DIR "${CMAKE_INSTALL_PREFIX}/${OVQT_DATA_DIR}") CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ovqt_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/ovqt_config.h) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index 3813bec67..efa0a171c 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -4,6 +4,8 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${QT_INCLUDES} ${LUA_INCLUDE_DIR}) +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/gui_editor_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/gui_editor_config.h) + FILE(GLOB SRC *.cpp *.h) SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h diff --git a/code/studio/src/plugins/gui_editor/expression_store.cpp b/code/studio/src/plugins/gui_editor/expression_store.cpp index 9f2218b4e..0016374d3 100644 --- a/code/studio/src/plugins/gui_editor/expression_store.cpp +++ b/code/studio/src/plugins/gui_editor/expression_store.cpp @@ -21,6 +21,7 @@ #include "expression_loader.h" #include #include +#include "gui_editor_config.h" class ExpressionStorePvt { @@ -50,7 +51,7 @@ ExpressionStore::~ExpressionStore() bool ExpressionStore::load() { - QDir d( "expressions" ); + QDir d( EXPRESSIONS_DIR ); if( !d.exists() ) return false; diff --git a/code/studio/src/plugins/gui_editor/gui_editor_config.h.cmake b/code/studio/src/plugins/gui_editor/gui_editor_config.h.cmake new file mode 100644 index 000000000..0e36dcb79 --- /dev/null +++ b/code/studio/src/plugins/gui_editor/gui_editor_config.h.cmake @@ -0,0 +1,8 @@ +#ifndef GUI_EDITOR_CONFIG_H +#define GUI_EDITOR_CONFIG_H + +#define WIDGETS_DIR "${OVQT_IMP_DATA_DIR}/widgets" +#define EXPRESSIONS_DIR "${OVQT_IMP_DATA_DIR}/expressions" + +#endif + diff --git a/code/studio/src/plugins/gui_editor/widget_properties_parser.cpp b/code/studio/src/plugins/gui_editor/widget_properties_parser.cpp index e0f346fc9..fd74dcae4 100644 --- a/code/studio/src/plugins/gui_editor/widget_properties_parser.cpp +++ b/code/studio/src/plugins/gui_editor/widget_properties_parser.cpp @@ -20,6 +20,7 @@ #include #include "nel/misc/debug.h" #include "widget_info_tree.h" +#include "gui_editor_config.h" using namespace NLMISC; @@ -36,7 +37,7 @@ namespace GUIEditor void CWidgetPropParser::parseGUIWidgets() { - QDir d( "widgets" ); + QDir d( WIDGETS_DIR ); if( !d.exists() ) { nlwarning( "GUI widgets directory doesn't exist!" ); @@ -55,7 +56,7 @@ namespace GUIEditor QStringListIterator itr( files ); while( itr.hasNext() ) - parseGUIWidget( "widgets/" + itr.next() ); + parseGUIWidget( QString( WIDGETS_DIR ) + QString( "/" ) + itr.next() ); buildWidgetInfoTree(); From 05c3405e1b72bb8b273d5487ebb1353e19259aec Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Feb 2015 17:54:27 +0100 Subject: [PATCH 44/87] Renamed the studio startup settings dialog to avoid name conflict with the core plugin's settings dialog. --- code/studio/src/CMakeLists.txt | 4 +- code/studio/src/main.cpp | 4 +- .../studio/src/plugins/core/settings_dialog.h | 2 +- ...gs_dialog.cpp => startup_settings_dlg.cpp} | 42 +++++++++---------- ...ttings_dialog.h => startup_settings_dlg.h} | 12 +++--- ...ings_dialog.ui => startup_settings_dlg.ui} | 4 +- 6 files changed, 34 insertions(+), 34 deletions(-) rename code/studio/src/{settings_dialog.cpp => startup_settings_dlg.cpp} (84%) rename code/studio/src/{settings_dialog.h => startup_settings_dlg.h} (84%) rename code/studio/src/{settings_dialog.ui => startup_settings_dlg.ui} (95%) diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index 9bc071bf2..510f0f93b 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -11,7 +11,7 @@ FILE(GLOB STUDIO_SRC extension_system/*.h SET(STUDIO_HDR extension_system/iplugin_manager.h extension_system/plugin_manager.h - settings_dialog.h + startup_settings_dlg.h splash_screen.h pm_watcher.h ) @@ -22,7 +22,7 @@ SET(STUDIO_TS translations/object_viewer_qt_en.ts translations/object_viewer_qt_de.ts translations/object_viewer_qt_ru.ts) -SET(STUDIO_PLUGIN_UIS settings_dialog.ui ) +SET(STUDIO_PLUGIN_UIS startup_settings_dlg.ui ) SET(QT_USE_QTGUI TRUE) SET(QT_USE_QTOPENGL TRUE) diff --git a/code/studio/src/main.cpp b/code/studio/src/main.cpp index e758037c0..dc1e7efb6 100644 --- a/code/studio/src/main.cpp +++ b/code/studio/src/main.cpp @@ -41,7 +41,7 @@ #include #include -#include "settings_dialog.h" +#include "startup_settings_dlg.h" #include "splash_screen.h" #include "pm_watcher.h" @@ -160,7 +160,7 @@ int main(int argc, char **argv) { settings->setValue( "FirstRun", false ); - SettingsDialog sd; + StartupSettingsDlg sd; sd.setSettings( settings ); sd.load(); sd.exec(); diff --git a/code/studio/src/plugins/core/settings_dialog.h b/code/studio/src/plugins/core/settings_dialog.h index a90f88b18..9e1c86444 100644 --- a/code/studio/src/plugins/core/settings_dialog.h +++ b/code/studio/src/plugins/core/settings_dialog.h @@ -19,7 +19,7 @@ #ifndef SETTINGS_DIALOG_H #define SETTINGS_DIALOG_H -#include "../core/ui_settings_dialog.h" +#include "ui_settings_dialog.h" // Qt includes #include diff --git a/code/studio/src/settings_dialog.cpp b/code/studio/src/startup_settings_dlg.cpp similarity index 84% rename from code/studio/src/settings_dialog.cpp rename to code/studio/src/startup_settings_dlg.cpp index df2718b9b..645df7040 100644 --- a/code/studio/src/settings_dialog.cpp +++ b/code/studio/src/startup_settings_dlg.cpp @@ -15,7 +15,7 @@ // along with this program. If not, see . -#include "settings_dialog.h" +#include "startup_settings_dlg.h" #include #include #include @@ -32,7 +32,7 @@ int findListItem( QListWidget *l, const QString &s ) return -1; } -SettingsDialog::SettingsDialog( QDialog *parent ) : +StartupSettingsDlg::StartupSettingsDlg( QDialog *parent ) : QDialog( parent ) { setupUi( this ); @@ -40,11 +40,11 @@ QDialog( parent ) settings = NULL; } -SettingsDialog::~SettingsDialog() +StartupSettingsDlg::~StartupSettingsDlg() { } -void SettingsDialog::load() +void StartupSettingsDlg::load() { pluginsLE->setText( settings->value( "PluginPath" ).toString() ); @@ -82,7 +82,7 @@ void SettingsDialog::load() settings->endGroup(); } -void SettingsDialog::saveSearchPaths() +void StartupSettingsDlg::saveSearchPaths() { QStringList l; for( int i = 0; i < searchLW->count(); i++ ) @@ -93,7 +93,7 @@ void SettingsDialog::saveSearchPaths() settings->setValue( "SearchPaths", l ); } -void SettingsDialog::saveRecursivePaths() +void StartupSettingsDlg::saveRecursivePaths() { QStringList l; for( int i = 0; i < recursiveLW->count(); i++ ) @@ -104,7 +104,7 @@ void SettingsDialog::saveRecursivePaths() settings->setValue( "RecursiveSearchPathes", l ); } -void SettingsDialog::save() +void StartupSettingsDlg::save() { settings->setValue( "PluginPath", pluginsLE->text() ); @@ -123,59 +123,59 @@ void SettingsDialog::save() settings->sync(); } -void SettingsDialog::accept() +void StartupSettingsDlg::accept() { save(); QDialog::accept(); } -void SettingsDialog::reject() +void StartupSettingsDlg::reject() { QDialog::reject(); } -void SettingsDialog::onOKClicked() +void StartupSettingsDlg::onOKClicked() { accept(); } -void SettingsDialog::onCancelClicked() +void StartupSettingsDlg::onCancelClicked() { reject(); } -void SettingsDialog::onPluginBClicked() +void StartupSettingsDlg::onPluginBClicked() { QString p = QFileDialog::getExistingDirectory( this, tr( "Plugins directory" ), "" ); pluginsLE->setText( p ); } -void SettingsDialog::onSheetsBClicked() +void StartupSettingsDlg::onSheetsBClicked() { QString p = QFileDialog::getExistingDirectory( this, tr( "Sheets directory" ), "" ); sheetsLE->setText( p ); } -void SettingsDialog::onAssetsBClicked() +void StartupSettingsDlg::onAssetsBClicked() { QString p = QFileDialog::getExistingDirectory( this, tr( "Assets directory" ), "" ); assetsLE->setText( p ); } -void SettingsDialog::onPrimitivesBClicked() +void StartupSettingsDlg::onPrimitivesBClicked() { QString p = QFileDialog::getExistingDirectory( this, tr( "Primitives directory" ), "" ); primitivesLE->setText( p ); } -void SettingsDialog::onLigoBClicked() +void StartupSettingsDlg::onLigoBClicked() { QString p; p = QFileDialog::getOpenFileName( this, tr( "LIGO config file" ), "" ); ligoLE->setText( p ); } -void SettingsDialog::onPathAddClicked() +void StartupSettingsDlg::onPathAddClicked() { QString p = QFileDialog::getExistingDirectory( this, tr( "Search path" ), "" ); if( p.isEmpty() ) @@ -187,7 +187,7 @@ void SettingsDialog::onPathAddClicked() searchLW->addItem( p ); } -void SettingsDialog::onPathRemoveClicked() +void StartupSettingsDlg::onPathRemoveClicked() { QListWidgetItem *i = searchLW->currentItem(); if( i == NULL ) @@ -196,7 +196,7 @@ void SettingsDialog::onPathRemoveClicked() delete i; } -void SettingsDialog::onRecursiveAddClicked() +void StartupSettingsDlg::onRecursiveAddClicked() { QString p = QFileDialog::getExistingDirectory( this, tr( "Recursive search path" ), "" ); if( p.isEmpty() ) @@ -208,7 +208,7 @@ void SettingsDialog::onRecursiveAddClicked() recursiveLW->addItem( p ); } -void SettingsDialog::onRecursiveRemoveClicked() +void StartupSettingsDlg::onRecursiveRemoveClicked() { QListWidgetItem *i = recursiveLW->currentItem(); if( i == NULL ) @@ -218,7 +218,7 @@ void SettingsDialog::onRecursiveRemoveClicked() } -void SettingsDialog::setupConnections() +void StartupSettingsDlg::setupConnections() { connect( bb, SIGNAL( accepted() ), this, SLOT( onOKClicked() ) ); connect( bb, SIGNAL( rejected() ), this, SLOT( onCancelClicked() ) ); diff --git a/code/studio/src/settings_dialog.h b/code/studio/src/startup_settings_dlg.h similarity index 84% rename from code/studio/src/settings_dialog.h rename to code/studio/src/startup_settings_dlg.h index 173ba37d4..49dd01ef7 100644 --- a/code/studio/src/settings_dialog.h +++ b/code/studio/src/startup_settings_dlg.h @@ -14,19 +14,19 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -#ifndef SETTINGS_DIALOG_H -#define SETTINGS_DIALOG_H +#ifndef STARTUP_SETTINGS_DIALOG_H +#define STARTUP_SETTINGS_DIALOG_H -#include "ui_settings_dialog.h" +#include "ui_startup_settings_dlg.h" class QSettings; -class SettingsDialog : public QDialog, public Ui::SettingsDialog +class StartupSettingsDlg : public QDialog, public Ui::StartupSettingsDlg { Q_OBJECT public: - SettingsDialog( QDialog *parent = NULL ); - ~SettingsDialog(); + StartupSettingsDlg( QDialog *parent = NULL ); + ~StartupSettingsDlg(); void setSettings( QSettings *s ){ settings = s; } diff --git a/code/studio/src/settings_dialog.ui b/code/studio/src/startup_settings_dlg.ui similarity index 95% rename from code/studio/src/settings_dialog.ui rename to code/studio/src/startup_settings_dlg.ui index 2fb6151d3..5f125ed14 100644 --- a/code/studio/src/settings_dialog.ui +++ b/code/studio/src/startup_settings_dlg.ui @@ -1,7 +1,7 @@ - SettingsDialog - + StartupSettingsDlg + Qt::ApplicationModal From 70a83dbc455a4e25c8e7cfbedcbe5f48a3f83470 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Feb 2015 19:49:16 +0100 Subject: [PATCH 45/87] We can now set whether to use OpenGL in WE in the WE settings page. For whatever reason VMware despises the OpenGL viewport so it's a good idea to turn it off inside VMware. --- .../world_editor_settings_page.cpp | 22 +++++++ .../world_editor/world_editor_settings_page.h | 1 + .../world_editor_settings_page.ui | 63 ++++++++++++++++--- .../world_editor/world_editor_window.cpp | 1 + 4 files changed, 77 insertions(+), 10 deletions(-) diff --git a/code/studio/src/plugins/world_editor/world_editor_settings_page.cpp b/code/studio/src/plugins/world_editor/world_editor_settings_page.cpp index bb8ef2a00..d3b8bb849 100644 --- a/code/studio/src/plugins/world_editor/world_editor_settings_page.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_settings_page.cpp @@ -17,9 +17,11 @@ // Project includes #include "world_editor_settings_page.h" #include "world_editor_constants.h" +#include "../core/icore.h" // Qt includes #include +#include // NeL includes @@ -61,11 +63,31 @@ QWidget *WorldEditorSettingsPage::createPage(QWidget *parent) { m_currentPage = new QWidget(parent); m_ui.setupUi(m_currentPage); + readSettings(); + return m_currentPage; } +void WorldEditorSettingsPage::readSettings() +{ + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(Constants::WORLD_EDITOR_SECTION); + bool b = false; + + b = settings->value( Constants::WORLD_EDITOR_USE_OPENGL, true ).toBool(); + m_ui.glCB->setChecked( b ); + + settings->endGroup(); +} + void WorldEditorSettingsPage::apply() { + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(Constants::WORLD_EDITOR_SECTION); + bool b = false; + b = m_ui.glCB->isChecked(); + settings->setValue( Constants::WORLD_EDITOR_USE_OPENGL, b ); + settings->endGroup(); } } /* namespace WorldEditor */ \ No newline at end of file diff --git a/code/studio/src/plugins/world_editor/world_editor_settings_page.h b/code/studio/src/plugins/world_editor/world_editor_settings_page.h index aa7677b9f..7eeb30e1d 100644 --- a/code/studio/src/plugins/world_editor/world_editor_settings_page.h +++ b/code/studio/src/plugins/world_editor/world_editor_settings_page.h @@ -46,6 +46,7 @@ public: QIcon categoryIcon() const; virtual QWidget *createPage(QWidget *parent); + virtual void readSettings(); virtual void apply(); virtual void finish() {} diff --git a/code/studio/src/plugins/world_editor/world_editor_settings_page.ui b/code/studio/src/plugins/world_editor/world_editor_settings_page.ui index 9219da6c4..a5cb12559 100644 --- a/code/studio/src/plugins/world_editor/world_editor_settings_page.ui +++ b/code/studio/src/plugins/world_editor/world_editor_settings_page.ui @@ -3,7 +3,7 @@ WorldEditorSettingsPage - false + true @@ -25,6 +25,9 @@ + + true + Workspace @@ -37,10 +40,18 @@ - + + + false + + - + + + false + + @@ -50,15 +61,32 @@ - + + + false + + - + + + false + + - + + + true + - Use OpenGL + Use OpenGL ( requires restart ) + + + true + + + false @@ -79,7 +107,11 @@ - + + + false + + @@ -89,7 +121,11 @@ - + + + false + + @@ -101,10 +137,17 @@ - + + + false + + + + false + ... diff --git a/code/studio/src/plugins/world_editor/world_editor_window.cpp b/code/studio/src/plugins/world_editor/world_editor_window.cpp index cec3baee1..6dbd07a8a 100644 --- a/code/studio/src/plugins/world_editor/world_editor_window.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_window.cpp @@ -436,6 +436,7 @@ void WorldEditorWindow::writeSettings() settings->beginGroup(Constants::WORLD_EDITOR_SECTION); settings->setValue(Constants::WORLD_WINDOW_STATE, saveState()); settings->setValue(Constants::WORLD_WINDOW_GEOMETRY, saveGeometry()); + settings->setValue(Constants::WORLD_EDITOR_USE_OPENGL, settings->value(Constants::WORLD_EDITOR_USE_OPENGL)); settings->endGroup(); settings->sync(); } From 0f8c8f665501449549516136bc7f36a7d35af346 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Feb 2015 19:55:27 +0100 Subject: [PATCH 46/87] Change the cursor to a wait cursor when applying settings in the settings dialog. --- code/studio/src/plugins/core/settings_dialog.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/code/studio/src/plugins/core/settings_dialog.cpp b/code/studio/src/plugins/core/settings_dialog.cpp index 0b38e4e80..b1027212c 100644 --- a/code/studio/src/plugins/core/settings_dialog.cpp +++ b/code/studio/src/plugins/core/settings_dialog.cpp @@ -145,11 +145,17 @@ void SettingsDialog::pageSelected() void SettingsDialog::accept() { m_applied = true; + + setCursor( Qt::WaitCursor ); + Q_FOREACH(IOptionsPage *page, m_pages) { page->apply(); page->finish(); } + + setCursor( Qt::ArrowCursor ); + done(QDialog::Accepted); } @@ -162,8 +168,13 @@ void SettingsDialog::reject() void SettingsDialog::apply() { + setCursor( Qt::WaitCursor ); + Q_FOREACH(IOptionsPage *page, m_pages) page->apply(); + + setCursor( Qt::ArrowCursor ); + m_applied = true; } From 991a3fdf99201ba742fddda5e669afc83e143939 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Feb 2015 20:07:35 +0100 Subject: [PATCH 47/87] Include rgba.h in libwww.h. Thanks Nimetu! --- code/nel/include/nel/gui/libwww.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/nel/include/nel/gui/libwww.h b/code/nel/include/nel/gui/libwww.h index 6a744b8c0..bb6b2da86 100644 --- a/code/nel/include/nel/gui/libwww.h +++ b/code/nel/include/nel/gui/libwww.h @@ -25,6 +25,8 @@ extern "C" #include "WWWInit.h" } +#include "nel/misc/rgba.h" + namespace NLGUI { class CCtrlBaseButton; From a6ebf62e40cf542e31f25f5099af4b70a9053d3f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 11 Feb 2015 19:55:16 +0100 Subject: [PATCH 48/87] Added ryzom.ttf, it will be installed to the data directory. --- .../src/plugins/gui_editor/CMakeLists.txt | 2 ++ .../src/plugins/gui_editor/fonts/ryzom.ttf | Bin 0 -> 622280 bytes 2 files changed, 2 insertions(+) create mode 100644 code/studio/src/plugins/gui_editor/fonts/ryzom.ttf diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index efa0a171c..f2f5bfcb1 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -120,3 +120,5 @@ FILE(GLOB expressions "${CMAKE_CURRENT_SOURCE_DIR}/expressions/*.xml") INSTALL(FILES ${widgets} DESTINATION "${OVQT_DATA_DIR}/widgets" COMPONENT tools3d) INSTALL(FILES ${expressions} DESTINATION "${OVQT_DATA_DIR}/expressions" COMPONENT tools3d) + +INSTALL(DIRECTORY fonts/ DESTINATION ${OVQT_DATA_DIR} COMPONENT data) diff --git a/code/studio/src/plugins/gui_editor/fonts/ryzom.ttf b/code/studio/src/plugins/gui_editor/fonts/ryzom.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c1b19d870590a7bbf0d238e0cefdce6689d3f342 GIT binary patch literal 622280 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
geGW9*=zyyC*n=}kiVSWwCU|u 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
  • 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 literal 0 HcmV?d00001 From f76650bb21502b5f79af97e8781062f53b02fad8 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 11 Feb 2015 20:42:31 +0100 Subject: [PATCH 49/87] Add the data directory to the search path. --- code/studio/src/plugins/core/CMakeLists.txt | 4 ++++ code/studio/src/plugins/core/core_config.h.cmake | 7 +++++++ .../src/plugins/core/search_paths_settings_page.cpp | 10 +++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 code/studio/src/plugins/core/core_config.h.cmake diff --git a/code/studio/src/plugins/core/CMakeLists.txt b/code/studio/src/plugins/core/CMakeLists.txt index 2c21c9b58..db99b807c 100644 --- a/code/studio/src/plugins/core/CMakeLists.txt +++ b/code/studio/src/plugins/core/CMakeLists.txt @@ -38,6 +38,10 @@ SET(OVQT_CORE_PLUGIN_UIS settings_dialog.ui SET(OVQT_CORE_PLUGIN_RCS core.qrc) +IF(NOT WIN32) +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/core_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/core_config.h) +ENDIF(NOT WIN32) + SET(QT_USE_QTGUI TRUE) SET(QT_USE_QTOPENGL TRUE) diff --git a/code/studio/src/plugins/core/core_config.h.cmake b/code/studio/src/plugins/core/core_config.h.cmake new file mode 100644 index 000000000..1aab54c12 --- /dev/null +++ b/code/studio/src/plugins/core/core_config.h.cmake @@ -0,0 +1,7 @@ +#ifndef CORE_CONFIG_H +#define CORE_CONFIG_H + +#define STUDIO_DATA_DIR "${OVQT_IMP_DATA_DIR}" + +#endif + diff --git a/code/studio/src/plugins/core/search_paths_settings_page.cpp b/code/studio/src/plugins/core/search_paths_settings_page.cpp index e76d6c796..516d3d3f3 100644 --- a/code/studio/src/plugins/core/search_paths_settings_page.cpp +++ b/code/studio/src/plugins/core/search_paths_settings_page.cpp @@ -28,6 +28,10 @@ #include #include +#if !defined NL_OS_WINDOWS +#include "core_config.h" +#endif + namespace Core { @@ -118,6 +122,10 @@ void SearchPathsSettingsPage::applySearchPaths() for (int i = 1; i < remapExt.size(); i += 2) NLMISC::CPath::remapExtension(remapExt.at(i - 1).toUtf8().constData(), remapExt.at(i).toUtf8().constData(), true); +#if !defined NL_OS_WINDOWS + NLMISC::CPath::addSearchPath(std::string(STUDIO_DATA_DIR), false, false); +#endif + Q_FOREACH(QString path, paths) { NLMISC::CPath::addSearchPath(path.toUtf8().constData(), m_recurse, false); @@ -216,4 +224,4 @@ void SearchPathsSettingsPage::checkEnabledButton() m_ui.downToolButton->setEnabled(bEnabled); } -} /* namespace Core */ \ No newline at end of file +} /* namespace Core */ From 14046699bcab7e719f118567612b23af6df92adf Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 12:06:19 +0100 Subject: [PATCH 50/87] Fixed: Only keep Release and Debug configurations in CMake --- code/CMakeModules/nel.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/CMakeModules/nel.cmake b/code/CMakeModules/nel.cmake index 0474c7d7b..fd7004884 100644 --- a/code/CMakeModules/nel.cmake +++ b/code/CMakeModules/nel.cmake @@ -6,6 +6,9 @@ IF(NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE) ENDIF(NOT CMAKE_BUILD_TYPE) +# Declare CMAKE_CONFIGURATION_TYPES before PROJECT +SET(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE) + ### # Helper macro that generates .pc and installs it. # Argument: name - the name of the .pc package, e.g. "nel-pacs.pc" @@ -384,8 +387,6 @@ MACRO(NL_SETUP_BUILD) # Debug = NL_DEBUG # Release = NL_RELEASE - SET(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE) - IF(CMAKE_BUILD_TYPE MATCHES "Debug") SET(NL_BUILD_MODE "NL_DEBUG") ELSE(CMAKE_BUILD_TYPE MATCHES "Debug") From 1ce011be380757ef1853c616114a8403e3bd408a Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 12:41:59 +0100 Subject: [PATCH 51/87] Fixed: Compilation warnings --- code/nel/include/nel/3d/track_tcb.h | 2 +- code/nel/src/georges/form_elm.cpp | 2 +- code/ryzom/server/src/admin_modules/aes_module.cpp | 2 +- code/ryzom/server/src/ai_share/aids_messages.h | 4 ++-- .../entities_game_service/game_item_manager/game_item.cpp | 6 +++--- .../src/input_output_service/string_manager_parser.cpp | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/code/nel/include/nel/3d/track_tcb.h b/code/nel/include/nel/3d/track_tcb.h index e91cfb397..153dcbc54 100644 --- a/code/nel/include/nel/3d/track_tcb.h +++ b/code/nel/include/nel/3d/track_tcb.h @@ -218,7 +218,7 @@ protected: date*= previous->OODeltaTime; NLMISC::clamp(date, 0,1); - date = this->ease(previous, date); + date = this->ease(previous, (float)date); float hb[4]; this->computeHermiteBasis(date, hb); diff --git a/code/nel/src/georges/form_elm.cpp b/code/nel/src/georges/form_elm.cpp index 658d1d9f6..01e4010e2 100644 --- a/code/nel/src/georges/form_elm.cpp +++ b/code/nel/src/georges/form_elm.cpp @@ -231,7 +231,7 @@ bool CFormElm::isAtom () const const CType* CFormElm::getType () { warning (false, "getType", "This node is not an atom."); - return 0; + return NULL; } // *************************************************************************** diff --git a/code/ryzom/server/src/admin_modules/aes_module.cpp b/code/ryzom/server/src/admin_modules/aes_module.cpp index c4faf5c47..6a45e302d 100644 --- a/code/ryzom/server/src/admin_modules/aes_module.cpp +++ b/code/ryzom/server/src/admin_modules/aes_module.cpp @@ -573,7 +573,7 @@ namespace ADMIN time_t t = now; fprintf(fp, "AESReportDate=%s", ::ctime(&t)); - fprintf(fp, "NBService=%u\n", _ServiceStates.size()); + fprintf(fp, "NBService=%u\n", (uint)_ServiceStates.size()); // output state of each service TServiceStates::iterator first(_ServiceStates.begin()), last(_ServiceStates.end()); for (; first != last; ++first) diff --git a/code/ryzom/server/src/ai_share/aids_messages.h b/code/ryzom/server/src/ai_share/aids_messages.h index 7ef43817b..76283ec04 100644 --- a/code/ryzom/server/src/ai_share/aids_messages.h +++ b/code/ryzom/server/src/ai_share/aids_messages.h @@ -101,12 +101,12 @@ public: { } - CMsgAIFeedback(std::string message) + CMsgAIFeedback(const std::string &message) { Message=message; } - CMsgAIFeedback(char *msgStr) + CMsgAIFeedback(const char *msgStr) { Message=std::string(msgStr); } diff --git a/code/ryzom/server/src/entities_game_service/game_item_manager/game_item.cpp b/code/ryzom/server/src/entities_game_service/game_item_manager/game_item.cpp index 30ff4acae..e36a4382e 100644 --- a/code/ryzom/server/src/entities_game_service/game_item_manager/game_item.cpp +++ b/code/ryzom/server/src/entities_game_service/game_item_manager/game_item.cpp @@ -242,11 +242,11 @@ float CItemCraftParameters::getCraftParameterValue( RM_FABER_STAT_TYPE::TRMStatT case RM_FABER_STAT_TYPE::ShockWaveProtection: case RM_FABER_STAT_TYPE::PoisonProtection: case RM_FABER_STAT_TYPE::ElectricityProtection: - if (Protection1 == statType) + if (Protection1 == (PROTECTION_TYPE::TProtectionType)statType) return Protection1Factor; - else if (Protection2 == statType) + else if (Protection2 == (PROTECTION_TYPE::TProtectionType)statType) return Protection2Factor; - else if (Protection3 == statType) + else if (Protection3 == (PROTECTION_TYPE::TProtectionType)statType) return Protection3Factor; else return 0.0f; case RM_FABER_STAT_TYPE::DesertResistance: diff --git a/code/ryzom/server/src/input_output_service/string_manager_parser.cpp b/code/ryzom/server/src/input_output_service/string_manager_parser.cpp index 67ce62f10..0cbfbf595 100644 --- a/code/ryzom/server/src/input_output_service/string_manager_parser.cpp +++ b/code/ryzom/server/src/input_output_service/string_manager_parser.cpp @@ -650,7 +650,7 @@ bool CStringManager::parseBlock(const ucstring &block, CPhrase &phrase) && (first - clause.String.begin()) == (sint) clause.Replacements[repCount].InsertPlace) { // check parameter type - char *subst; + const char *subst; uint paramIndex = clause.Replacements[repCount].ParamIndex; TParamId ¶mId = phrase.Params[paramIndex]->ParamId; From 65fb1bc8c12cacc7922cea0a18eb017ae3f50a9b Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 12:43:29 +0100 Subject: [PATCH 52/87] Changed: Replaced atof by NLMISC::fromString --- .../ryzom/server/src/entities_game_service/zone_manager.cpp | 2 +- .../server/src/persistant_data_service/pds_database.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/code/ryzom/server/src/entities_game_service/zone_manager.cpp b/code/ryzom/server/src/entities_game_service/zone_manager.cpp index dd9e817b1..f55222dca 100644 --- a/code/ryzom/server/src/entities_game_service/zone_manager.cpp +++ b/code/ryzom/server/src/entities_game_service/zone_manager.cpp @@ -201,7 +201,7 @@ bool CTpSpawnZone::build(const NLLIGO::CPrimPoint * point) nlwarning(" : no z in CTpSpawnZone '%s'",_Name.c_str() ); return false; } - Point.z = ( float ) atof( value.c_str() ); + NLMISC::fromString(value, Point.z); Point.z = float( sint32 (1000.0f* Point.z) ); } else diff --git a/code/ryzom/server/src/persistant_data_service/pds_database.cpp b/code/ryzom/server/src/persistant_data_service/pds_database.cpp index 66b272d5c..84148220b 100644 --- a/code/ryzom/server/src/persistant_data_service/pds_database.cpp +++ b/code/ryzom/server/src/persistant_data_service/pds_database.cpp @@ -905,14 +905,16 @@ bool CDatabase::set(RY_PDS::TTableIndex table, RY_PDS::TRowIndex row, RY_PDS::TC case PDS_float: { - float data = (float)atof(value.c_str()); + float data; + NLMISC::fromString(value, data); return set(table, row, column, sizeof(data), &data); } break; case PDS_double: { - double data = (double)atof(value.c_str()); + double data; + NLMISC::fromString(value, data); return set(table, row, column, sizeof(data), &data); } break; From a5d69a78d73c6eee0790c15e68af44609261c81e Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 12:47:03 +0100 Subject: [PATCH 53/87] Changed: Minor changes --- code/nel/src/gui/libwww_nel_stream.cpp | 375 ++++++++++-------- .../tools/3d/panoply_maker/color_modifier.cpp | 2 - code/ryzom/client/src/session_browser_impl.h | 1 - .../ryzom/server/src/ai_share/aids_messages.h | 3 +- .../src/server_share/used_continent.cpp | 3 +- 5 files changed, 210 insertions(+), 174 deletions(-) diff --git a/code/nel/src/gui/libwww_nel_stream.cpp b/code/nel/src/gui/libwww_nel_stream.cpp index f6a45cf06..b7e218b30 100644 --- a/code/nel/src/gui/libwww_nel_stream.cpp +++ b/code/nel/src/gui/libwww_nel_stream.cpp @@ -21,7 +21,7 @@ extern "C" { - /* Library Includes */ +/* Library Includes */ #include "wwwsys.h" #include "WWWUtil.h" #include "WWWCore.h" @@ -41,8 +41,9 @@ using namespace NLMISC; extern "C" { - /* Final states have negative value */ -typedef enum _FileState { +/* Final states have negative value */ +typedef enum _FileState +{ FS_RETRY = -4, FS_ERROR = -3, FS_NO_DATA = -2, @@ -57,26 +58,29 @@ typedef enum _FileState { } FileState; /* This is the context structure for the this module */ -typedef struct _file_info { - FileState state; /* Current state of the connection */ - char * local; /* Local representation of file name */ - struct stat stat_info; /* Contains actual file chosen */ +typedef struct _file_info +{ + FileState state; /* Current state of the connection */ + char * local; /* Local representation of file name */ + struct stat stat_info; /* Contains actual file chosen */ HTNet * net; HTTimer * timer; } file_info; -struct _HTStream { +struct _HTStream +{ const HTStreamClass * isa; }; -struct _HTInputStream { +struct _HTInputStream +{ const HTInputStreamClass * isa; HTChannel * ch; HTHost * host; - char * write; /* Last byte written */ - char * read; /* Last byte read */ + char * write; /* Last byte written */ + char * read; /* Last byte read */ int b_read; - char data [INPUT_BUFFER_SIZE]; /* buffer */ + char data [INPUT_BUFFER_SIZE]; /* buffer */ }; PRIVATE int FileCleanup (HTRequest *req, int status) @@ -96,7 +100,7 @@ PRIVATE int FileCleanup (HTRequest *req, int status) } /* - ** Remove if we have registered a timer function as a callback + ** Remove if we have registered a timer function as a callback */ if (file->timer) { @@ -123,10 +127,8 @@ PUBLIC int HTLoadNeLFile (SOCKET soc, HTRequest * request) HTNet * net = HTRequest_net(request); HTParentAnchor * anchor = HTRequest_anchor(request); - HTTRACE(PROT_TRACE, "HTLoadFile.. Looking for `%s\'\n" _ - HTAnchor_physical(anchor)); - if ((file = (file_info *) HT_CALLOC(1, sizeof(file_info))) == NULL) - HT_OUTOFMEM((char*)"HTLoadFILE"); + HTTRACE(PROT_TRACE, "HTLoadFile.. Looking for `%s\'\n" _ HTAnchor_physical(anchor)); + if ((file = (file_info *) HT_CALLOC(1, sizeof(file_info))) == NULL) HT_OUTOFMEM("HTLoadFILE"); file->state = FS_BEGIN; file->net = net; HTNet_setContext(net, file); @@ -139,8 +141,8 @@ PUBLIC int HTLoadNeLFile (SOCKET soc, HTRequest * request) PRIVATE int ReturnEvent (HTTimer * timer, void * param, HTEventType /* type */) { file_info * file = (file_info *) param; - if (timer != file->timer) - HTDEBUGBREAK((char*)"File timer %p not in sync\n" _ timer); + if (timer != file->timer) HTDEBUGBREAK("File timer %p not in sync\n" _ timer); + HTTRACE(PROT_TRACE, "HTLoadFile.. Continuing %p with timer %p\n" _ file _ timer); /* @@ -163,7 +165,7 @@ PUBLIC int HTNeLFileOpen (HTNet * net, char * local, HTLocalMode /* mode */) if (!fp->open (local)) { - HTRequest_addSystemError(request, ERR_FATAL, errno, NO, (char*)"CIFile::open"); + HTRequest_addSystemError(request, ERR_FATAL, errno, NO, "CIFile::open"); return HT_ERROR; } @@ -186,7 +188,7 @@ PRIVATE int FileEvent (SOCKET /* soc */, void * pVoid, HTEventType type) { /* Interrupted */ HTRequest_addError(request, ERR_FATAL, NO, HTERR_INTERRUPTED, - NULL, 0, (char*)"HTLoadFile"); + NULL, 0, "HTLoadFile"); FileCleanup(request, HT_INTERRUPTED); return HT_OK; } @@ -202,7 +204,7 @@ PRIVATE int FileEvent (SOCKET /* soc */, void * pVoid, HTEventType type) /* We only support safe (GET, HEAD, etc) methods for the moment */ if (!HTMethod_isSafe(HTRequest_method(request))) { HTRequest_addError(request, ERR_FATAL, NO, HTERR_NOT_ALLOWED, - NULL, 0, (char*)"HTLoadFile"); + NULL, 0, "HTLoadFile"); file->state = FS_ERROR; break; } @@ -234,166 +236,188 @@ PRIVATE int FileEvent (SOCKET /* soc */, void * pVoid, HTEventType type) /* Create a new host object and link it to the net object */ { - HTHost * host = NULL; - if ((host = HTHost_new((char*)"localhost", 0)) == NULL) return HT_ERROR; - HTNet_setHost(net, host); - if (HTHost_addNet(host, net) == HT_PENDING) { - HTTRACE(PROT_TRACE, "HTLoadFile.. Pending...\n"); - /* move to the hack state */ - file->state = FS_PENDING; - return HT_OK; - } + HTHost * host = NULL; + if ((host = HTHost_new("localhost", 0)) == NULL) return HT_ERROR; + HTNet_setHost(net, host); + if (HTHost_addNet(host, net) == HT_PENDING) + { + HTTRACE(PROT_TRACE, "HTLoadFile.. Pending...\n"); + /* move to the hack state */ + file->state = FS_PENDING; + return HT_OK; + } } file->state = FS_DO_CN; break; case FS_PENDING: { - HTHost * host = NULL; - if ((host = HTHost_new((char*)"localhost", 0)) == NULL) return HT_ERROR; - HTNet_setHost(net, host); - if (HTHost_addNet(host, net) == HT_PENDING) { - HTTRACE(PROT_TRACE, "HTLoadFile.. Pending...\n"); - file->state = FS_PENDING; - return HT_OK; - } + HTHost * host = NULL; + if ((host = HTHost_new((char*)"localhost", 0)) == NULL) return HT_ERROR; + HTNet_setHost(net, host); + if (HTHost_addNet(host, net) == HT_PENDING) + { + HTTRACE(PROT_TRACE, "HTLoadFile.. Pending...\n"); + file->state = FS_PENDING; + return HT_OK; + } } file->state = FS_DO_CN; break; case FS_DO_CN: if (HTRequest_negotiation(request) && - HTMethod_isSafe(HTRequest_method(request))) { + HTMethod_isSafe(HTRequest_method(request))) + { + HTAnchor_setPhysical(anchor, file->local); + HTTRACE(PROT_TRACE, "Load File... Found `%s\'\n" _ file->local); + } + else + { + if (HT_STAT(file->local, &file->stat_info) == -1) + { + HTTRACE(PROT_TRACE, "Load File... Not found `%s\'\n" _ file->local); + HTRequest_addError(request, ERR_FATAL, NO, HTERR_NOT_FOUND, NULL, 0, "HTLoadFile"); + file->state = FS_ERROR; + break; + } + } - HTAnchor_setPhysical(anchor, file->local); - HTTRACE(PROT_TRACE, "Load File... Found `%s\'\n" _ file->local); - - } else { - if (HT_STAT(file->local, &file->stat_info) == -1) { - HTTRACE(PROT_TRACE, "Load File... Not found `%s\'\n" _ file->local); - HTRequest_addError(request, ERR_FATAL, NO, HTERR_NOT_FOUND, - NULL, 0, (char*)"HTLoadFile"); - file->state = FS_ERROR; + if (((file->stat_info.st_mode) & S_IFMT) == S_IFDIR) + { + if (HTRequest_method(request) == METHOD_GET) + { + file->state = FS_PARSE_DIR; + } + else + { + HTRequest_addError(request, ERR_INFO, NO, HTERR_NO_CONTENT, NULL, 0, "HTLoadFile"); + file->state = FS_NO_DATA; + } break; } - } - - if (((file->stat_info.st_mode) & S_IFMT) == S_IFDIR) { - if (HTRequest_method(request) == METHOD_GET) - file->state = FS_PARSE_DIR; - else { - HTRequest_addError(request, ERR_INFO, NO, HTERR_NO_CONTENT, - NULL, 0, (char*)"HTLoadFile"); - file->state = FS_NO_DATA; - } - break; - } { - BOOL editable = FALSE; - HTBind_getAnchorBindings(anchor); - if (editable) HTAnchor_appendAllow(anchor, METHOD_PUT); + BOOL editable = FALSE; + HTBind_getAnchorBindings(anchor); + if (editable) HTAnchor_appendAllow(anchor, METHOD_PUT); - /* Set the file size */ - CIFile nelFile; - if (nelFile.open (file->local)) - { - file->stat_info.st_size = nelFile.getFileSize(); - } - nelFile.close(); + /* Set the file size */ + CIFile nelFile; + if (nelFile.open (file->local)) + { + file->stat_info.st_size = nelFile.getFileSize(); + } + nelFile.close(); - if (file->stat_info.st_size) - HTAnchor_setLength(anchor, file->stat_info.st_size); + if (file->stat_info.st_size) + HTAnchor_setLength(anchor, file->stat_info.st_size); - /* Set the file last modified time stamp */ - if (file->stat_info.st_mtime > 0) - HTAnchor_setLastModified(anchor, file->stat_info.st_mtime); + /* Set the file last modified time stamp */ + if (file->stat_info.st_mtime > 0) + HTAnchor_setLastModified(anchor, file->stat_info.st_mtime); - /* Check to see if we can edit it */ - if (!editable && !file->stat_info.st_size) { - HTRequest_addError(request, ERR_INFO, NO, HTERR_NO_CONTENT, - NULL, 0, (char*)"HTLoadFile"); - file->state = FS_NO_DATA; - } else { - file->state = (HTRequest_method(request)==METHOD_GET) ? - FS_NEED_OPEN_FILE : FS_GOT_DATA; - } + /* Check to see if we can edit it */ + if (!editable && !file->stat_info.st_size) + { + HTRequest_addError(request, ERR_INFO, NO, HTERR_NO_CONTENT, NULL, 0, "HTLoadFile"); + file->state = FS_NO_DATA; + } + else + { + file->state = (HTRequest_method(request)==METHOD_GET) ? FS_NEED_OPEN_FILE : FS_GOT_DATA; + } } break; case FS_NEED_OPEN_FILE: status = HTNeLFileOpen(net, file->local, HT_FB_RDONLY); - if (status == HT_OK) { + if (status == HT_OK) { - HTStream * rstream = HTStreamStack(HTAnchor_format(anchor), - HTRequest_outputFormat(request), - HTRequest_outputStream(request), - request, YES); - HTNet_setReadStream(net, rstream); - HTRequest_setOutputConnected(request, YES); - } - - { - HTOutputStream * output = HTNet_getOutput(net, NULL, 0); - HTRequest_setInputStream(request, (HTStream *) output); - } - - if (HTRequest_isSource(request) && !HTRequest_destinationsReady(request)) - return HT_OK; - HTRequest_addError(request, ERR_INFO, NO, HTERR_OK, NULL, 0, - (char*)"HTLoadFile"); - file->state = FS_NEED_BODY; - - if (HTEvent_isCallbacksRegistered()) { - if (!HTRequest_preemptive(request)) { - if (!HTNet_preemptive(net)) { - HTTRACE(PROT_TRACE, "HTLoadFile.. Returning\n"); - HTHost_register(HTNet_host(net), net, HTEvent_READ); - } else if (!file->timer) { - HTTRACE(PROT_TRACE, "HTLoadFile.. Returning\n"); - file->timer = - HTTimer_new(NULL, ReturnEvent, file, 1, YES, NO); + { + HTStream * rstream = HTStreamStack(HTAnchor_format(anchor), + HTRequest_outputFormat(request), + HTRequest_outputStream(request), + request, YES); + HTNet_setReadStream(net, rstream); + HTRequest_setOutputConnected(request, YES); } - return HT_OK; + + { + HTOutputStream * output = HTNet_getOutput(net, NULL, 0); + HTRequest_setInputStream(request, (HTStream *) output); + } + + if (HTRequest_isSource(request) && !HTRequest_destinationsReady(request)) return HT_OK; + + HTRequest_addError(request, ERR_INFO, NO, HTERR_OK, NULL, 0, "HTLoadFile"); + file->state = FS_NEED_BODY; + + if (HTEvent_isCallbacksRegistered()) + { + if (!HTRequest_preemptive(request)) + { + if (!HTNet_preemptive(net)) + { + HTTRACE(PROT_TRACE, "HTLoadFile.. Returning\n"); + HTHost_register(HTNet_host(net), net, HTEvent_READ); + } + else if (!file->timer) + { + HTTRACE(PROT_TRACE, "HTLoadFile.. Returning\n"); + file->timer = HTTimer_new(NULL, ReturnEvent, file, 1, YES, NO); + } + return HT_OK; + } } } - } else if (status == HT_WOULD_BLOCK || status == HT_PENDING) - return HT_OK; - else { - HTRequest_addError(request, ERR_INFO, NO, HTERR_INTERNAL, - NULL, 0, (char*)"HTLoadFile"); - file->state = FS_ERROR; /* Error or interrupt */ + else if (status == HT_WOULD_BLOCK || status == HT_PENDING) + { + return HT_OK; + } + else + { + HTRequest_addError(request, ERR_INFO, NO, HTERR_INTERNAL, NULL, 0, "HTLoadFile"); + file->state = FS_ERROR; /* Error or interrupt */ } break; - case FS_NEED_BODY: + case FS_NEED_BODY: status = HTHost_read(HTNet_host(net), net); if (status == HT_WOULD_BLOCK) - return HT_OK; - else if (status == HT_LOADED || status == HT_CLOSED) { - file->state = FS_GOT_DATA; - } else { - HTRequest_addError(request, ERR_INFO, NO, HTERR_FORBIDDEN, - NULL, 0, (char*)"HTLoadFile"); - file->state = FS_ERROR; + { + return HT_OK; + } + else if (status == HT_LOADED || status == HT_CLOSED) + { + file->state = FS_GOT_DATA; + } + else + { + HTRequest_addError(request, ERR_INFO, NO, HTERR_FORBIDDEN, NULL, 0, "HTLoadFile"); + file->state = FS_ERROR; } break; case FS_TRY_FTP: { - char *url = HTAnchor_physical(anchor); - HTAnchor *anchor; - char *newname = NULL; - StrAllocCopy(newname, "ftp:"); - if (!strncmp(url, "file:", 5)) - StrAllocCat(newname, url+5); - else - StrAllocCat(newname, url); - anchor = HTAnchor_findAddress(newname); - HTRequest_setAnchor(request, anchor); - HT_FREE(newname); - FileCleanup(request, HT_IGNORE); - return HTLoad(request, YES); + char *url = HTAnchor_physical(anchor); + HTAnchor *anchor; + char *newname = NULL; + StrAllocCopy(newname, "ftp:"); + if (!strncmp(url, "file:", 5)) + { + StrAllocCat(newname, url+5); + } + else + { + StrAllocCat(newname, url); + } + anchor = HTAnchor_findAddress(newname); + HTRequest_setAnchor(request, anchor); + HT_FREE(newname); + FileCleanup(request, HT_IGNORE); + return HTLoad(request, YES); } break; @@ -461,7 +485,8 @@ PRIVATE int HTNeLReader_read (HTInputStream * me) { HTAlertCallback * cbf = HTAlert_find(HT_PROG_READ); HTNet_addBytesRead(net, me->b_read); - if (cbf) { + if (cbf) + { int tr = HTNet_bytesRead(net); (*cbf)(net->request, HT_PROG_READ, HT_MSG_NULL, NULL, &tr, NULL); } @@ -472,18 +497,28 @@ PRIVATE int HTNeLReader_read (HTInputStream * me) /* Now push the data down the stream */ if ((status = (*net->readStream->isa->put_block) - (net->readStream, me->data, me->b_read)) != HT_OK) { - if (status == HT_WOULD_BLOCK) { + (net->readStream, me->data, me->b_read)) != HT_OK) + { + if (status == HT_WOULD_BLOCK) + { HTTRACE(PROT_TRACE, "ANSI read... Target WOULD BLOCK\n"); return HT_WOULD_BLOCK; - } else if (status == HT_PAUSE) { + } + else if (status == HT_PAUSE) + { HTTRACE(PROT_TRACE, "ANSI read... Target PAUSED\n"); return HT_PAUSE; - } else if (status > 0) { /* Stream specific return code */ + } + else if (status > 0) + { + /* Stream specific return code */ HTTRACE(PROT_TRACE, "ANSI read... Target returns %d\n" _ status); me->write = me->data + me->b_read; return status; - } else { /* We have a real error */ + } + else + { + /* We have a real error */ HTTRACE(PROT_TRACE, "ANSI read... Target ERROR\n"); return status; } @@ -506,13 +541,15 @@ PRIVATE int HTNeLReader_close (HTInputStream * me) HTNet * net = HTHost_getReadNet(me->host); - if (net && net->readStream) { - if ((status = (*net->readStream->isa->_free)(net->readStream))==HT_WOULD_BLOCK) - return HT_WOULD_BLOCK; - net->readStream = NULL; + if (net && net->readStream) + { + if ((status = (*net->readStream->isa->_free)(net->readStream))==HT_WOULD_BLOCK) return HT_WOULD_BLOCK; + net->readStream = NULL; } + HTTRACE(STREAM_TRACE, "Socket read. FREEING....\n"); HT_FREE(me); + return status; } @@ -540,7 +577,8 @@ PRIVATE int HTNeLReader_free (HTInputStream * me) } HTNet * net = HTHost_getReadNet(me->host); - if (net && net->readStream) { + if (net && net->readStream) + { int status = (*net->readStream->isa->_free)(net->readStream); if (status == HT_OK) net->readStream = NULL; return status; @@ -551,7 +589,8 @@ PRIVATE int HTNeLReader_free (HTInputStream * me) PRIVATE int HTNeLReader_abort (HTInputStream * me, HTList * /* e */) { HTNet * net = HTHost_getReadNet(me->host); - if (net && net->readStream) { + if (net && net->readStream) + { int status = (*net->readStream->isa->abort)(net->readStream, NULL); if (status != HT_IGNORE) net->readStream = NULL; } @@ -560,7 +599,7 @@ PRIVATE int HTNeLReader_abort (HTInputStream * me, HTList * /* e */) PRIVATE const HTInputStreamClass HTNeLReader = { - (char*)"SocketReader", + "SocketReader", HTNeLReader_flush, HTNeLReader_free, HTNeLReader_abort, @@ -569,20 +608,20 @@ PRIVATE const HTInputStreamClass HTNeLReader = HTNeLReader_consumed }; -PUBLIC HTInputStream * HTNeLReader_new (HTHost * host, HTChannel * ch, - void * /* param */, int /* mode */) +PUBLIC HTInputStream * HTNeLReader_new (HTHost * host, HTChannel * ch, void * /* param */, int /* mode */) { - if (host && ch) { - HTInputStream * me = HTChannel_input(ch); - if (me == NULL) { - if ((me=(HTInputStream *) HT_CALLOC(1, sizeof(HTInputStream))) == NULL) - HT_OUTOFMEM((char*)"HTNeLReader_new"); - me->isa = &HTNeLReader; - me->ch = ch; - me->host = host; - HTTRACE(STREAM_TRACE, "Reader...... Created reader stream %p\n" _ me); - } - return me; + if (host && ch) + { + HTInputStream * me = HTChannel_input(ch); + if (me == NULL) + { + if ((me=(HTInputStream *) HT_CALLOC(1, sizeof(HTInputStream))) == NULL) HT_OUTOFMEM("HTNeLReader_new"); + me->isa = &HTNeLReader; + me->ch = ch; + me->host = host; + HTTRACE(STREAM_TRACE, "Reader...... Created reader stream %p\n" _ me); + } + return me; } return NULL; } diff --git a/code/nel/tools/3d/panoply_maker/color_modifier.cpp b/code/nel/tools/3d/panoply_maker/color_modifier.cpp index 3c4b1814d..a55936b7c 100644 --- a/code/nel/tools/3d/panoply_maker/color_modifier.cpp +++ b/code/nel/tools/3d/panoply_maker/color_modifier.cpp @@ -70,7 +70,6 @@ void CColorModifier::convertBitmap(NLMISC::CBitmap &destBitmap, const NLMISC::CB // blend to the destination by using the mask alpha result.blendFromui(*dest, result, mask->R); - /// keep alpha from the source dest->R = result.R; @@ -78,7 +77,6 @@ void CColorModifier::convertBitmap(NLMISC::CBitmap &destBitmap, const NLMISC::CB dest->B = result.B; dest->A = src->A; - ++ mask; ++ src; ++ dest; diff --git a/code/ryzom/client/src/session_browser_impl.h b/code/ryzom/client/src/session_browser_impl.h index 6235128b0..68f2de29d 100644 --- a/code/ryzom/client/src/session_browser_impl.h +++ b/code/ryzom/client/src/session_browser_impl.h @@ -21,7 +21,6 @@ #include "session_browser.h" #include "game_share/ring_session_manager_itf.h" #include "nel/gui/lua_helper.h" -using namespace NLGUI; #include "far_tp.h" class CSessionBrowserImpl : public CSessionBrowser, diff --git a/code/ryzom/server/src/ai_share/aids_messages.h b/code/ryzom/server/src/ai_share/aids_messages.h index 76283ec04..734acbec3 100644 --- a/code/ryzom/server/src/ai_share/aids_messages.h +++ b/code/ryzom/server/src/ai_share/aids_messages.h @@ -97,7 +97,7 @@ class CMsgAIFeedback : public NLNET::CTransportClass public: std::string Message; - CMsgAIFeedback() + CMsgAIFeedback() { } @@ -120,6 +120,5 @@ public: virtual void callback (const std::string &name, NLNET::TServiceId id); }; - #endif diff --git a/code/ryzom/server/src/server_share/used_continent.cpp b/code/ryzom/server/src/server_share/used_continent.cpp index 01ab2beda..9e9a310d9 100644 --- a/code/ryzom/server/src/server_share/used_continent.cpp +++ b/code/ryzom/server/src/server_share/used_continent.cpp @@ -17,8 +17,9 @@ #include "stdpch.h" -#include #include "used_continent.h" +#include "nel/net/service.h" + using namespace std; using namespace NLMISC; From a6cd459f330504a9ec9a3147448d09cd34882b27 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 12:47:54 +0100 Subject: [PATCH 54/87] Changed: Check getSpawn() before calling its methods --- code/ryzom/server/src/ai_service/ai_bot_npc.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/code/ryzom/server/src/ai_service/ai_bot_npc.cpp b/code/ryzom/server/src/ai_service/ai_bot_npc.cpp index cb183850e..8a7518709 100644 --- a/code/ryzom/server/src/ai_service/ai_bot_npc.cpp +++ b/code/ryzom/server/src/ai_service/ai_bot_npc.cpp @@ -714,9 +714,12 @@ void CBotNpc::sendVPA() // alternate VPA void CBotNpc::sendVisualProperties() // VisualPropertyA, B, C { - CMirrors::setVisualPropertyA( getSpawn()->dataSetRow(), _VisualPropertyA ); - CMirrors::setVisualPropertyB( getSpawn()->dataSetRow(), _VisualPropertyB ); - CMirrors::setVisualPropertyC( getSpawn()->dataSetRow(), _VisualPropertyC ); + if (getSpawn()) + { + CMirrors::setVisualPropertyA( getSpawn()->dataSetRow(), _VisualPropertyA ); + CMirrors::setVisualPropertyB( getSpawn()->dataSetRow(), _VisualPropertyB ); + CMirrors::setVisualPropertyC( getSpawn()->dataSetRow(), _VisualPropertyC ); + } } bool CBotNpc::reSpawn(bool sendMessage) From 72a50960cb08a068b67e3a526028c49d26757907 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 12:48:29 +0100 Subject: [PATCH 55/87] Changed: Used PCH for admin_modules --- code/ryzom/server/src/admin_modules/CMakeLists.txt | 4 ++++ code/ryzom/server/src/admin_modules/admin_modules_itf.cpp | 1 + code/ryzom/server/src/admin_modules/aes_client_module.cpp | 1 + code/ryzom/server/src/admin_modules/aes_module.cpp | 1 + code/ryzom/server/src/admin_modules/as_module.cpp | 1 + 5 files changed, 8 insertions(+) diff --git a/code/ryzom/server/src/admin_modules/CMakeLists.txt b/code/ryzom/server/src/admin_modules/CMakeLists.txt index ea8d8a5ff..9809b2f29 100644 --- a/code/ryzom/server/src/admin_modules/CMakeLists.txt +++ b/code/ryzom/server/src/admin_modules/CMakeLists.txt @@ -11,4 +11,8 @@ NL_ADD_LIB_SUFFIX(ryzom_adminmodules) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS}) +IF(WITH_PCH) + ADD_NATIVE_PRECOMPILED_HEADER(ryzom_adminmodules ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.h ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.cpp) +ENDIF(WITH_PCH) + INSTALL(TARGETS ryzom_adminmodules LIBRARY DESTINATION ${RYZOM_LIB_PREFIX} ARCHIVE DESTINATION ${RYZOM_LIB_PREFIX} COMPONENT libraries) diff --git a/code/ryzom/server/src/admin_modules/admin_modules_itf.cpp b/code/ryzom/server/src/admin_modules/admin_modules_itf.cpp index 258409d16..39dfc6948 100644 --- a/code/ryzom/server/src/admin_modules/admin_modules_itf.cpp +++ b/code/ryzom/server/src/admin_modules/admin_modules_itf.cpp @@ -18,6 +18,7 @@ // WARNING : this is a generated file, don't change it ! ///////////////////////////////////////////////////////////////// +#include "stdpch.h" #include "admin_modules_itf.h" namespace ADMIN diff --git a/code/ryzom/server/src/admin_modules/aes_client_module.cpp b/code/ryzom/server/src/admin_modules/aes_client_module.cpp index e2b9ca390..66dddbe1e 100644 --- a/code/ryzom/server/src/admin_modules/aes_client_module.cpp +++ b/code/ryzom/server/src/admin_modules/aes_client_module.cpp @@ -15,6 +15,7 @@ // along with this program. If not, see . +#include "stdpch.h" #include "nel/misc/singleton.h" #include "nel/net/module.h" #include "nel/net/module_builder_parts.h" diff --git a/code/ryzom/server/src/admin_modules/aes_module.cpp b/code/ryzom/server/src/admin_modules/aes_module.cpp index 6a45e302d..734dfff64 100644 --- a/code/ryzom/server/src/admin_modules/aes_module.cpp +++ b/code/ryzom/server/src/admin_modules/aes_module.cpp @@ -15,6 +15,7 @@ // along with this program. If not, see . +#include "stdpch.h" #include "nel/misc/singleton.h" #include #include "nel/misc/path.h" diff --git a/code/ryzom/server/src/admin_modules/as_module.cpp b/code/ryzom/server/src/admin_modules/as_module.cpp index cbe1b2818..9717da358 100644 --- a/code/ryzom/server/src/admin_modules/as_module.cpp +++ b/code/ryzom/server/src/admin_modules/as_module.cpp @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +#include "stdpch.h" #include "nel/misc/types_nl.h" #include #include "nel/misc/file.h" From df3cdfab70bc2a1838ee6eab7d3bbd543091e49f Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 12:52:57 +0100 Subject: [PATCH 56/87] Fixed: Unable to patch when Ryzom was located on a mounted FS --- code/ryzom/client/src/login_patch.cpp | 10 +++++----- code/ryzom/client/src/login_patch.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/code/ryzom/client/src/login_patch.cpp b/code/ryzom/client/src/login_patch.cpp index 5b9a83c83..e98cd1e32 100644 --- a/code/ryzom/client/src/login_patch.cpp +++ b/code/ryzom/client/src/login_patch.cpp @@ -1068,12 +1068,12 @@ float CPatchManager::getCurrentFileProgress() const } // **************************************************************************** -void CPatchManager::setRWAccess (const string &filename) +void CPatchManager::setRWAccess (const string &filename, bool bThrowException) { ucstring s = CI18N::get("uiSetAttrib") + " " + filename; setState(true, s); - if (!NLMISC::CFile::setRWAccess(filename)) + if (!NLMISC::CFile::setRWAccess(filename) && bThrowException) { s = CI18N::get("uiAttribErr") + " " + filename + " (" + toString(errno) + "," + strerror(errno) + ")"; setState(true, s); @@ -1351,7 +1351,7 @@ void CPatchManager::downloadFileWithCurl (const string &source, const string &de // create the local file if (NLMISC::CFile::fileExists(dest)) { - setRWAccess(dest); + setRWAccess(dest, false); NLMISC::CFile::deleteFile(dest.c_str()); } FILE *fp = fopen (dest.c_str(), "wb"); @@ -1492,7 +1492,7 @@ void CPatchManager::decompressFile (const string &filename) } string dest = filename.substr(0, filename.size ()-4); - setRWAccess(dest); + setRWAccess(dest, false); //if(isVerboseLog()) nlinfo("Calling fopen('%s','wb')", dest.c_str()); FILE *fp = fopen (dest.c_str(), "wb"); if (fp == NULL) @@ -1566,7 +1566,7 @@ void CPatchManager::applyDate (const string &sFilename, uint32 nDate) { // _utimbuf utb; // utb.actime = utb.modtime = nDate; - setRWAccess(sFilename); + setRWAccess(sFilename, false); ucstring s = CI18N::get("uiChangeDate") + " " + NLMISC::CFile::getFilename(sFilename) + " " + toString(NLMISC::CFile::getFileModificationDate (sFilename)) + " -> " + toString(nDate); setState(true,s); diff --git a/code/ryzom/client/src/login_patch.h b/code/ryzom/client/src/login_patch.h index de7351775..565de7da2 100644 --- a/code/ryzom/client/src/login_patch.h +++ b/code/ryzom/client/src/login_patch.h @@ -302,7 +302,7 @@ private: /// Read the description of the highest client version file found void readClientVersionAndDescFile(); - void setRWAccess (const std::string &filename); + void setRWAccess (const std::string &filename, bool bThrowException=true); std::string deleteFile (const std::string &filename, bool bThrowException=true, bool bWarning=true); From bb5dc2c47168010a7fb7b11d8ca6f9042f04be1d Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 12:54:17 +0100 Subject: [PATCH 57/87] Changed: Possible bug if string not found --- code/ryzom/client/src/interface_v3/chat_window.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/chat_window.cpp b/code/ryzom/client/src/interface_v3/chat_window.cpp index e74392432..1d4c0516b 100644 --- a/code/ryzom/client/src/interface_v3/chat_window.cpp +++ b/code/ryzom/client/src/interface_v3/chat_window.cpp @@ -604,7 +604,11 @@ void CChatGroupWindow::displayMessage(const ucstring &msg, NLMISC::CRGBA col, CC pos = newmsg.find(ucstring("}"));; prefix += " "; } - newmsg = newmsg.substr(0, pos + 1) + prefix + newmsg.substr(pos + 1); + + if (pos == ucstring::npos) + newmsg = prefix + newmsg; + else + newmsg = newmsg.substr(0, pos + 1) + prefix + newmsg.substr(pos + 1); // Add dynchannel number and optionally name before text if user channel CCDBNodeLeaf* node = NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_DYN_CHANNEL_NAME_IN_CHAT_CB", false); @@ -615,7 +619,11 @@ void CChatGroupWindow::displayMessage(const ucstring &msg, NLMISC::CRGBA col, CC STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId, title); prefix = title.empty() ? ucstring("") : ucstring(" ") + title; pos = newmsg.find(ucstring("] ")); - newmsg = newmsg.substr(0, pos) + prefix + newmsg.substr(pos); + + if (pos == ucstring::npos) + newmsg = prefix + newmsg; + else + newmsg = newmsg.substr(0, pos) + prefix + newmsg.substr(pos); } } break; From b6637fa6fe48e44fa66b28d3028970acf0c1794a Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 13:03:27 +0100 Subject: [PATCH 58/87] Changed: Used INVALID_AI_INSTANCE in CUsedContinent::getInstanceForContinent --- code/ryzom/server/src/ai_service/commands.cpp | 4 ++-- code/ryzom/server/src/ai_share/primitive_parser.cpp | 4 ++-- code/ryzom/server/src/entities_game_service/admin.cpp | 2 +- code/ryzom/server/src/server_share/used_continent.cpp | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code/ryzom/server/src/ai_service/commands.cpp b/code/ryzom/server/src/ai_service/commands.cpp index d257d0492..7a4ff6f0d 100644 --- a/code/ryzom/server/src/ai_service/commands.cpp +++ b/code/ryzom/server/src/ai_service/commands.cpp @@ -577,10 +577,10 @@ NLMISC_COMMAND(createStaticAIInstance, "Create a new static AIInstance for a giv CUsedContinent &uc = CUsedContinent::instance(); const uint32 in = uc.getInstanceForContinent(args[0]); - if (in == ~0) + if (in == INVALID_AI_INSTANCE) { nlwarning("The continent '%s' is unknow or not active. Can't create instance, FATAL", args[0].c_str()); - nlassert(in != ~0); + nlassert(in != INVALID_AI_INSTANCE); // nlassertex(in != ~0, ("The continent '%s' is unknow or not active. Can't create instance, FATAL", args[0].c_str())); } diff --git a/code/ryzom/server/src/ai_share/primitive_parser.cpp b/code/ryzom/server/src/ai_share/primitive_parser.cpp index 892120902..dd52b4d7a 100644 --- a/code/ryzom/server/src/ai_share/primitive_parser.cpp +++ b/code/ryzom/server/src/ai_share/primitive_parser.cpp @@ -4176,7 +4176,7 @@ NLMISC_COMMAND(loadMap,"load a complete set of primitive files","") // check that the continent is active CUsedContinent &uc = CUsedContinent::instance(); uint32 in = uc.getInstanceForContinent(continentName); - if (in == ~0) + if (in == INVALID_AI_INSTANCE) { log.displayNL("loadMap : while loading map '%s', can't load primitive '%s' coz continent '%s' is not active", args[0].c_str(), @@ -4216,7 +4216,7 @@ NLMISC_COMMAND(unloadMap,"unload a complete set of primitive files","" // check that the continent is active CUsedContinent &uc = CUsedContinent::instance(); uint32 in = uc.getInstanceForContinent(continentName); - if (in == ~0) + if (in == INVALID_AI_INSTANCE) { log.displayNL("unloadMap : while loading map '%s', can't load primitive '%s' coz continent '%s' is not active", args[0].c_str(), diff --git a/code/ryzom/server/src/entities_game_service/admin.cpp b/code/ryzom/server/src/entities_game_service/admin.cpp index 20941e77f..6e06da000 100644 --- a/code/ryzom/server/src/entities_game_service/admin.cpp +++ b/code/ryzom/server/src/entities_game_service/admin.cpp @@ -420,7 +420,7 @@ bool getAIInstanceFromGroupName(string& groupName, uint32& instanceNumber) { string continent = groupName.substr(0, groupName.find('@')); uint32 nr = CUsedContinent::instance().getInstanceForContinent(continent); - if (nr == ~0) + if (nr == INVALID_AI_INSTANCE) { return false; } diff --git a/code/ryzom/server/src/server_share/used_continent.cpp b/code/ryzom/server/src/server_share/used_continent.cpp index 9e9a310d9..9d2b48f0d 100644 --- a/code/ryzom/server/src/server_share/used_continent.cpp +++ b/code/ryzom/server/src/server_share/used_continent.cpp @@ -106,7 +106,7 @@ uint32 CUsedContinent::getInstanceForContinent(const std::string &continentName) if (it != _Continents.end()) return it->ContinentInstance; else - return ~0; + return INVALID_AI_INSTANCE; } uint32 CUsedContinent::getInstanceForContinent(CONTINENT::TContinent continentEnum) const @@ -116,7 +116,7 @@ uint32 CUsedContinent::getInstanceForContinent(CONTINENT::TContinent continentEn if (it != _Continents.end()) return it->ContinentInstance; else - return ~0; + return INVALID_AI_INSTANCE; } const std::string &CUsedContinent::getContinentForInstance(uint32 instanceNumber) const From 5b1926aeb4f28e70df91ac17972cba7470618bad Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 13:18:51 +0100 Subject: [PATCH 59/87] Changed: std::string already initialized to en empty string --- .../client/src/interface_v3/interface_manager.cpp | 2 +- code/ryzom/client/src/login_progress_post_thread.cpp | 2 +- code/ryzom/client/src/misc.cpp | 2 +- code/ryzom/client/src/net_manager.cpp | 2 +- code/ryzom/client/src/r2/displayer_visual_entity.cpp | 4 ++-- .../client/src/r2/dmc/client_edition_module.cpp | 12 ++++++------ code/ryzom/client/src/r2/dmc/com_lua_module.cpp | 8 ++++---- code/ryzom/client/src/r2/dmc/dmc.cpp | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index b89566ecd..6f4f31d14 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -2925,7 +2925,7 @@ void CInterfaceManager::initEmotes() CSkillManager *pSM = CSkillManager::getInstance(); betaTester = pSM->isTitleUnblocked(CHARACTER_TITLE::FBT); - string previousMind = ""; + string previousMind; CGroupSubMenu *pFirstMenu = 0; for (list::const_iterator it = entries.begin(); it != entries.end(); it++) diff --git a/code/ryzom/client/src/login_progress_post_thread.cpp b/code/ryzom/client/src/login_progress_post_thread.cpp index bc833fb04..76ce9c2e3 100644 --- a/code/ryzom/client/src/login_progress_post_thread.cpp +++ b/code/ryzom/client/src/login_progress_post_thread.cpp @@ -85,7 +85,7 @@ static std::string sizeToHumanStd(uint64 size) static std::string getVideoInfoDeviceName() { uint64 version; - std::string ret = ""; + std::string ret; bool ok = CSystemInfo::getVideoInfo(ret, version); if (ok) { diff --git a/code/ryzom/client/src/misc.cpp b/code/ryzom/client/src/misc.cpp index 9adf00a9a..7e018a576 100644 --- a/code/ryzom/client/src/misc.cpp +++ b/code/ryzom/client/src/misc.cpp @@ -920,7 +920,7 @@ std::string getStringCategory(const ucstring &src, ucstring &dest, bool alwaysAd std::string getStringCategoryIfAny(const ucstring &src, ucstring &dest) { - std::string colorCode = ""; + std::string colorCode; if (src.size() >= 3) { uint startPos = 0; diff --git a/code/ryzom/client/src/net_manager.cpp b/code/ryzom/client/src/net_manager.cpp index 4b37b698a..0d369fe85 100644 --- a/code/ryzom/client/src/net_manager.cpp +++ b/code/ryzom/client/src/net_manager.cpp @@ -4109,7 +4109,7 @@ void CNetManagerMulti::init( const std::string& cookie, const std::string& addr // uint32 ShardId = 0; -std::string WebServer = ""; +std::string WebServer; diff --git a/code/ryzom/client/src/r2/displayer_visual_entity.cpp b/code/ryzom/client/src/r2/displayer_visual_entity.cpp index 37632f4d4..5bc8638f0 100644 --- a/code/ryzom/client/src/r2/displayer_visual_entity.cpp +++ b/code/ryzom/client/src/r2/displayer_visual_entity.cpp @@ -564,7 +564,7 @@ void CDisplayerVisualEntity::updateWorldMapPresence() _MapDeco.setDisplayedInstance(getDisplayedInstance(), true); // retrieve icon from the displayed object (lua code) CLuaState &ls = getEditor().getLua(); - std::string texName = ""; + std::string texName; { CLuaStackChecker lsc(&ls); if (getDisplayedInstance()->getLuaProjection().callMethodByNameNoThrow("getSelectBarIcon", 0, 1)) @@ -984,7 +984,7 @@ void CDisplayerVisualEntity::updateName() break; } } - std::string firstPart = ""; + std::string firstPart; if(actNb>0) firstPart = CI18N::get("uiR2EDDefaultActTitle").toString() + " " + NLMISC::toString(actNb); 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 0a5f74cc5..93978800d 100644 --- a/code/ryzom/client/src/r2/dmc/client_edition_module.cpp +++ b/code/ryzom/client/src/r2/dmc/client_edition_module.cpp @@ -1116,12 +1116,12 @@ void CClientEditionModule::startingScenario(class NLNET::IModuleProxy * /* serve uint32 myUserId = NetMngr.getUserId(); - std::string connectionState = ""; + std::string connectionState; if (myUserId == (charId>>4) || ClientCfg.Local) { - std::string errorMsg = ""; + std::string errorMsg; CObject* hlScenario = _Scenario->getHighLevel(); hlData.setData(hlScenario); // clone before modify by translateFeatures @@ -2425,10 +2425,10 @@ bool CClientEditionModule::addToLoadList( const std::string& filename, CScenario void CClientEditionModule::loadScenarioSucceded(const std::string& filename, const std::string& body, const CScenarioValidator::TValues& values) { //H_AUTO(R2_CClientEditionModule_loadScenarioSucceded) - string initialIsland="", initialEntryPoint="", initialSeason = ""; - string creatorMD5 = "", modifiedByMD5=""; - string name = ""; - string locked = ""; + string initialIsland, initialEntryPoint, initialSeason; + string creatorMD5, modifiedByMD5; + string name; + string locked; for(uint i=0; i& pair = values[i]; diff --git a/code/ryzom/client/src/r2/dmc/com_lua_module.cpp b/code/ryzom/client/src/r2/dmc/com_lua_module.cpp index c9b6a6df2..b73813786 100644 --- a/code/ryzom/client/src/r2/dmc/com_lua_module.cpp +++ b/code/ryzom/client/src/r2/dmc/com_lua_module.cpp @@ -834,7 +834,7 @@ sint CComLuaModule::luaRequestEraseNode(lua_State* state) if (args>2) { luaL_checknumber(state, 3); } std::string instanceId(lua_tostring(state, 1)); - std::string attrName = ""; + std::string attrName; sint position = -1; if (args>1){ attrName = lua_tostring(state, 2);} if (args>2){ position = static_cast(lua_tonumber(state, 3));} @@ -1255,7 +1255,7 @@ CObject* CComLuaModule::getObjectFromLua(lua_State* state, sint idx) lua_pushnil(state); while (lua_next(state, -2) != 0) { - std::string key = ""; + std::string key; if ( lua_type(state, -2) == LUA_TSTRING) { key = lua_tostring(state, -2); @@ -1285,7 +1285,7 @@ CObject* CComLuaModule::getObjectFromLua(lua_State* state, sint idx) CObject* CComLuaModule::loadLocal(const std::string& filename, const CScenarioValidator::TValues& values) { CScenarioValidator::TValues::const_iterator first(values.begin()), last(values.end()); - std::string name = ""; + std::string name; for (; first != last; ++first) { if (first->first == "Name" ) { name = first->second; } @@ -1347,7 +1347,7 @@ bool CComLuaModule::loadUserComponent(const std::string& filename) CObject* CComLuaModule::loadFromBuffer(const std::string& data, const std::string& filename, const CScenarioValidator::TValues& values) { CScenarioValidator::TValues::const_iterator first(values.begin()), last(values.end()); - std::string name = ""; + std::string name; for (; first != last; ++first) { if (first->first == "Name" ) { name = first->second; } diff --git a/code/ryzom/client/src/r2/dmc/dmc.cpp b/code/ryzom/client/src/r2/dmc/dmc.cpp index 4642dfa10..0659f0a56 100644 --- a/code/ryzom/client/src/r2/dmc/dmc.cpp +++ b/code/ryzom/client/src/r2/dmc/dmc.cpp @@ -267,7 +267,7 @@ void CDynamicMapClient::save(const std::string& /* filename */) void CDynamicMapClient::saveRtData(const std::string& filename) { //H_AUTO(R2_CDynamicMapClient_saveRtData) - std::string name = ""; + std::string name; name += filename; //std::ostringstream out2; std::string out2; From d478bf56a356825e9026ba38f8e417bec6b26b5e Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 13:19:09 +0100 Subject: [PATCH 60/87] Fixed: Missing namespace --- code/ryzom/client/src/session_browser_impl.h | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/code/ryzom/client/src/session_browser_impl.h b/code/ryzom/client/src/session_browser_impl.h index 68f2de29d..302da2864 100644 --- a/code/ryzom/client/src/session_browser_impl.h +++ b/code/ryzom/client/src/session_browser_impl.h @@ -36,7 +36,7 @@ public: * - RingAccessPoint:onConnectionClosed() * - RingAccessPoint:onConnectionFailed() */ - void init(CLuaState *ls); + void init(NLGUI::CLuaState *ls); // from CSessionBrowser virtual void on_connectionFailed(); virtual void on_connectionClosed(); @@ -98,17 +98,17 @@ public: static const std::string &getFrontEndAddress(); private: - CLuaState::TRefPtr _Lua; - static int luaGetRingSessionList(CLuaState &ls); - static int luaGetRingCharList(CLuaState &ls); - static int luaJoinRingSession(CLuaState &ls); - static int luaCheckRingAccess(CLuaState &ls); - static int luaGetFileHeader(CLuaState &ls); - static int luaGetRingStats(CLuaState &ls); - static int luaGetScenarioScores(CLuaState &ls); - static int luaUpdateScenarioScores(CLuaState &ls); - static int luaGetSessionAverageScores(CLuaState &ls); - static int luaGetScenarioAverageScores(CLuaState &ls); + NLGUI::CLuaState::TRefPtr _Lua; + static int luaGetRingSessionList(NLGUI::CLuaState &ls); + static int luaGetRingCharList(NLGUI::CLuaState &ls); + static int luaJoinRingSession(NLGUI::CLuaState &ls); + static int luaCheckRingAccess(NLGUI::CLuaState &ls); + static int luaGetFileHeader(NLGUI::CLuaState &ls); + static int luaGetRingStats(NLGUI::CLuaState &ls); + static int luaGetScenarioScores(NLGUI::CLuaState &ls); + static int luaUpdateScenarioScores(NLGUI::CLuaState &ls); + static int luaGetSessionAverageScores(NLGUI::CLuaState &ls); + static int luaGetScenarioAverageScores(NLGUI::CLuaState &ls); // Call a method inside the 'RingAccessPoint' lua table void callRingAccessPointMethod(const char *name, int numArg, int numResult); void callRingCharTrackingMethod(const char *name, int numArg, int numResult); From 491613e7fa8e8f6572fca5e41466e1eb8f4a5b68 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 13:19:53 +0100 Subject: [PATCH 61/87] Changed: Use Ryzom user agent for CURL --- code/ryzom/client/src/interface_v3/group_html_webig.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 8ffa25878..680a26273 100644 --- a/code/ryzom/client/src/interface_v3/group_html_webig.cpp +++ b/code/ryzom/client/src/interface_v3/group_html_webig.cpp @@ -22,6 +22,7 @@ #include "../user_entity.h" #include "../entities.h" #include "interface_manager.h" +#include "user_agent.h" // used for login cookie to be sent to the web server #include "../net_manager.h" @@ -157,7 +158,7 @@ struct CWebigNotificationThread : public NLMISC::IRunnable if(!Curl) return; curl_easy_setopt(Curl, CURLOPT_COOKIEFILE, ""); curl_easy_setopt(Curl, CURLOPT_NOPROGRESS, 1); - curl_easy_setopt(Curl, CURLOPT_USERAGENT, "Ryzom"); + curl_easy_setopt(Curl, CURLOPT_USERAGENT, getUserAgent().c_str()); curl_easy_setopt(Curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(Curl, CURLOPT_WRITEFUNCTION, writeDataFromCurl); //nlinfo("ctor CWebigNotificationThread"); From eca33bfb95f08d9be4f06e91ad682958b3f8ab7c Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 13:34:45 +0100 Subject: [PATCH 62/87] Changed: Minor changes --- code/ryzom/client/src/init.cpp | 3 +-- code/ryzom/client/src/login_patch.cpp | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index 1644f7e2d..6958fe790 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -556,10 +556,9 @@ void checkDriverDepth () static std::string replaceApplicationDirToken(const std::string &dir) { - #ifdef NL_OS_MAC // if client_default.cfg is not in current directory, and it's not an absolute path, use application default directory - if (!CFile::isExists("client_default.cfg") && dir.size()>0 && dir[0]!='/') + if (!CFile::isExists("client_default.cfg") && !dir.empty() && dir[0]!='/') { return getAppBundlePath() + "/Contents/Resources/" + dir; } diff --git a/code/ryzom/client/src/login_patch.cpp b/code/ryzom/client/src/login_patch.cpp index e98cd1e32..da94f37d6 100644 --- a/code/ryzom/client/src/login_patch.cpp +++ b/code/ryzom/client/src/login_patch.cpp @@ -3398,6 +3398,7 @@ bool CPatchManager::extract(const std::string& patchPath, ok = true; } } + if (!ok) { // nothing to extract @@ -3407,15 +3408,21 @@ bool CPatchManager::extract(const std::string& patchPath, // extract uint nblab = 0; pPM->deleteFile(updateBatchFilename, false, false); + FILE *fp = fopen (updateBatchFilename.c_str(), "wt"); + if (fp == 0) { string err = toString("Can't open file '%s' for writing: code=%d %s (error code 29)", updateBatchFilename.c_str(), errno, strerror(errno)); throw Exception (err); } + +#ifdef NL_OS_WINDOWS fprintf(fp, "@echo off\n"); fprintf(fp, "ping 127.0.0.1 -n 7 -w 1000 > nul\n"); // wait - +#else + // TODO: for Linux and OS X +#endif // Unpack files with category ExtractPath non empty for (uint32 j = 0; j < sourceFilename.size(); ++j) @@ -3442,21 +3449,32 @@ bool CPatchManager::extract(const std::string& patchPath, string DstPath = CPath::standardizeDosPath(extractPath[j]); string DstName = DstPath + vFilenames[fff]; NLMISC::CFile::createDirectoryTree(extractPath[j]); - // this file must be moved + // this file must be moved +#ifdef NL_OS_WINDOWS fprintf(fp, ":loop%u\n", nblab); fprintf(fp, "attrib -r -a -s -h %s\n", DstName.c_str()); fprintf(fp, "del %s\n", DstName.c_str()); fprintf(fp, "if exist %s goto loop%u\n", DstName.c_str(), nblab); fprintf(fp, "move %s %s\n", SrcName.c_str(), DstPath.c_str()); +#else + // TODO: for Linux and OS X +#endif + nblab++; + } } } } +#ifdef NL_OS_WINDOWS fprintf(fp, "start %s %%1 %%2 %%3\n", execName.c_str()); +#else + // TODO: for Linux and OS X +#endif + fclose(fp); if (stopFun) From c569b03d0c757f11521b133e382f4b1eaf36c368 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 13:46:21 +0100 Subject: [PATCH 63/87] Changed: Replaced atoi and atof by NLMISC::fromString --- code/nel/src/misc/config_file/cf_gramatical.cpp | 4 ++-- code/nel/src/misc/config_file/cf_gramatical.ypp | 4 ++-- code/nel/src/misc/config_file/cf_lexical.cpp | 2 +- code/nel/src/misc/config_file/config_file.cpp | 6 +++++- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/code/nel/src/misc/config_file/cf_gramatical.cpp b/code/nel/src/misc/config_file/cf_gramatical.cpp index c6a50934f..bc51ef371 100644 --- a/code/nel/src/misc/config_file/cf_gramatical.cpp +++ b/code/nel/src/misc/config_file/cf_gramatical.cpp @@ -1499,7 +1499,7 @@ void cf_setVar (NLMISC::CConfigFile::CVar &Var, cf_value Val) switch (Val.Type) { case NLMISC::CConfigFile::CVar::T_REAL: Var.IntValues.push_back ((int)Val.Real); break; - case NLMISC::CConfigFile::CVar::T_STRING: Var.IntValues.push_back (atoi(Val.String)); break; + case NLMISC::CConfigFile::CVar::T_STRING: int val = 0; NLMISC::fromString(Val.String, val); Var.IntValues.push_back(val); break; default: break; } break; @@ -1507,7 +1507,7 @@ void cf_setVar (NLMISC::CConfigFile::CVar &Var, cf_value Val) switch (Val.Type) { case NLMISC::CConfigFile::CVar::T_INT: Var.RealValues.push_back ((double)Val.Int); break; - case NLMISC::CConfigFile::CVar::T_STRING: Var.RealValues.push_back (atof(Val.String)); break; + case NLMISC::CConfigFile::CVar::T_STRING: double val = 0.0; NLMISC::fromString(Val.String, val); Var.RealValues.push_back(val); break; default: break; } break; diff --git a/code/nel/src/misc/config_file/cf_gramatical.ypp b/code/nel/src/misc/config_file/cf_gramatical.ypp index 199f3df9a..0f4fd2405 100644 --- a/code/nel/src/misc/config_file/cf_gramatical.ypp +++ b/code/nel/src/misc/config_file/cf_gramatical.ypp @@ -517,7 +517,7 @@ void cf_setVar (NLMISC::CConfigFile::CVar &Var, cf_value Val) switch (Val.Type) { case NLMISC::CConfigFile::CVar::T_REAL: Var.IntValues.push_back ((int)Val.Real); break; - case NLMISC::CConfigFile::CVar::T_STRING: Var.IntValues.push_back (atoi(Val.String)); break; + case NLMISC::CConfigFile::CVar::T_STRING: int val = 0; NLMISC::fromString(Val.String, val); Var.RealValues.push_back(val); break; default: break; } break; @@ -525,7 +525,7 @@ void cf_setVar (NLMISC::CConfigFile::CVar &Var, cf_value Val) switch (Val.Type) { case NLMISC::CConfigFile::CVar::T_INT: Var.RealValues.push_back ((double)Val.Int); break; - case NLMISC::CConfigFile::CVar::T_STRING: Var.RealValues.push_back (atof(Val.String)); break; + case NLMISC::CConfigFile::CVar::T_STRING: double val = 0.0; NLMISC::fromString(Val.String, val); Var.RealValues.push_back(val); break; default: break; } break; diff --git a/code/nel/src/misc/config_file/cf_lexical.cpp b/code/nel/src/misc/config_file/cf_lexical.cpp index 80fd4fd36..8c39112a6 100644 --- a/code/nel/src/misc/config_file/cf_lexical.cpp +++ b/code/nel/src/misc/config_file/cf_lexical.cpp @@ -2337,7 +2337,7 @@ YY_RULE_SETUP if (!cf_Ignore) { cflval.Val.Type = T_REAL; - cflval.Val.Real = atof (yytext); + NLMISC::fromString(yytext, cflval.Val.Real); DEBUG_PRINTF("lex: real '%s' '%f\n", yytext, cflval.Val.Real); return REAL; } diff --git a/code/nel/src/misc/config_file/config_file.cpp b/code/nel/src/misc/config_file/config_file.cpp index 6113a7a2c..c969f614d 100644 --- a/code/nel/src/misc/config_file/config_file.cpp +++ b/code/nel/src/misc/config_file/config_file.cpp @@ -85,8 +85,12 @@ double CConfigFile::CVar::asDouble (int index) const if (index >= (int)IntValues.size () || index < 0) throw EBadSize (Name, (int)IntValues.size (), index); return (double)IntValues[index]; case T_STRING: + { if (index >= (int)StrValues.size () || index < 0) throw EBadSize (Name, (int)StrValues.size (), index); - return atof(StrValues[index].c_str()); + double val; + NLMISC::fromString(StrValues[index], val); + return val; + } default: if (index >= (int)RealValues.size () || index < 0) throw EBadSize (Name, (int)RealValues.size (), index); return RealValues[index]; From 779492b262b311e7248376e5948d79315f3ed7fc Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 13:47:37 +0100 Subject: [PATCH 64/87] Changed: Updated CMale modules --- code/CMakeModules/AndroidToolChain.cmake | 157 +++++++++++++++-------- code/CMakeModules/FindMSVC.cmake | 5 + code/CMakeModules/FindMySQL.cmake | 27 ++-- code/CMakeModules/FindWindowsSDK.cmake | 16 ++- code/CMakeModules/GetRevision.cmake | 34 +++-- 5 files changed, 154 insertions(+), 85 deletions(-) diff --git a/code/CMakeModules/AndroidToolChain.cmake b/code/CMakeModules/AndroidToolChain.cmake index 049c39adf..6690497d4 100644 --- a/code/CMakeModules/AndroidToolChain.cmake +++ b/code/CMakeModules/AndroidToolChain.cmake @@ -26,63 +26,46 @@ IF(TARGET_CPU STREQUAL "armv7") SET(LIBRARY_ARCHITECTURE "armeabi-v7a") SET(CMAKE_SYSTEM_PROCESSOR "armv7") SET(TOOLCHAIN_ARCH "arm") - SET(TOOLCHAIN_PREFIX "arm-linux-androideabi") + SET(GCC_TOOLCHAIN_PREFIX "arm-linux-androideabi") SET(TOOLCHAIN_BIN_PREFIX "arm") SET(MINIMUM_NDK_TARGET 4) ELSEIF(TARGET_CPU STREQUAL "armv5") SET(LIBRARY_ARCHITECTURE "armeabi") SET(CMAKE_SYSTEM_PROCESSOR "armv5") SET(TOOLCHAIN_ARCH "arm") - SET(TOOLCHAIN_PREFIX "arm-linux-androideabi") + SET(GCC_TOOLCHAIN_PREFIX "arm-linux-androideabi") SET(TOOLCHAIN_BIN_PREFIX "arm") SET(MINIMUM_NDK_TARGET 4) ELSEIF(TARGET_CPU STREQUAL "x86") SET(LIBRARY_ARCHITECTURE "x86") SET(CMAKE_SYSTEM_PROCESSOR "x86") SET(TOOLCHAIN_ARCH "x86") - SET(TOOLCHAIN_PREFIX "x86") + SET(GCC_TOOLCHAIN_PREFIX "x86") SET(TOOLCHAIN_BIN_PREFIX "i686") SET(MINIMUM_NDK_TARGET 9) ELSEIF(TARGET_CPU STREQUAL "mips") SET(LIBRARY_ARCHITECTURE "mips") SET(CMAKE_SYSTEM_PROCESSOR "mips") SET(TOOLCHAIN_ARCH "mips") - SET(TOOLCHAIN_PREFIX "mipsel-linux-android") + SET(GCC_TOOLCHAIN_PREFIX "mipsel-linux-android") SET(TOOLCHAIN_BIN_PREFIX "mipsel") SET(MINIMUM_NDK_TARGET 9) ENDIF(TARGET_CPU STREQUAL "armv7") +SET(ANDROID_COMPILER "GCC") + +IF(NDK_TOOLCHAIN_VERSION STREQUAL "clang") + SET(ANDROID_COMPILER "clang") + SET(CLANG_TOOLCHAIN_PREFIX "llvm") + SET(CLANG ON) +ELSE() + SET(GCC_TOOLCHAIN_VERSION ${NDK_TOOLCHAIN_VERSION}) +ENDIF() + IF(NOT NDK_TARGET) SET(NDK_TARGET ${MINIMUM_NDK_TARGET}) ENDIF(NOT NDK_TARGET) -FILE(GLOB _TOOLCHAIN_VERSIONS "${NDK_ROOT}/toolchains/${TOOLCHAIN_PREFIX}-*") -IF(_TOOLCHAIN_VERSIONS) - LIST(SORT _TOOLCHAIN_VERSIONS) - LIST(REVERSE _TOOLCHAIN_VERSIONS) - FOREACH(_TOOLCHAIN_VERSION ${_TOOLCHAIN_VERSIONS}) - STRING(REGEX REPLACE ".+${TOOLCHAIN_PREFIX}-([0-9.]+)" "\\1" _TOOLCHAIN_VERSION "${_TOOLCHAIN_VERSION}") - IF(_TOOLCHAIN_VERSION MATCHES "^([0-9.]+)$") - LIST(APPEND NDK_TOOLCHAIN_VERSIONS ${_TOOLCHAIN_VERSION}) - ENDIF(_TOOLCHAIN_VERSION MATCHES "^([0-9.]+)$") - ENDFOREACH(_TOOLCHAIN_VERSION) -ENDIF(_TOOLCHAIN_VERSIONS) - -IF(NOT NDK_TOOLCHAIN_VERSIONS) - MESSAGE(FATAL_ERROR "No Android toolchain found in default search path ${NDK_ROOT}/toolchains") -ENDIF(NOT NDK_TOOLCHAIN_VERSIONS) - -IF(NDK_TOOLCHAIN_VERSION) - LIST(FIND NDK_TOOLCHAIN_VERSIONS "${NDK_TOOLCHAIN_VERSION}" _INDEX) - IF(_INDEX EQUAL -1) - LIST(GET NDK_TOOLCHAIN_VERSIONS 0 NDK_TOOLCHAIN_VERSION) - ENDIF(_INDEX EQUAL -1) -ELSE(NDK_TOOLCHAIN_VERSION) - LIST(GET NDK_TOOLCHAIN_VERSIONS 0 NDK_TOOLCHAIN_VERSION) -ENDIF(NDK_TOOLCHAIN_VERSION) - -MESSAGE(STATUS "Target Android NDK ${NDK_TARGET} and use GCC ${NDK_TOOLCHAIN_VERSION}") - IF(CMAKE_HOST_WIN32) SET(TOOLCHAIN_HOST "windows") SET(TOOLCHAIN_BIN_SUFFIX ".exe") @@ -94,33 +77,73 @@ ELSEIF(CMAKE_HOST_UNIX) SET(TOOLCHAIN_BIN_SUFFIX "") ENDIF(CMAKE_HOST_WIN32) -SET(TOOLCHAIN_ROOT "${NDK_ROOT}/toolchains/${TOOLCHAIN_PREFIX}-${NDK_TOOLCHAIN_VERSION}/prebuilt/${TOOLCHAIN_HOST}") +MACRO(SEARCH_TOOLCHAIN _COMPILER) + SET(${_COMPILER}_TOOLCHAIN_VERSIONS) + FILE(GLOB _TOOLCHAIN_VERSIONS "${NDK_ROOT}/toolchains/${${_COMPILER}_TOOLCHAIN_PREFIX}-*") + IF(_TOOLCHAIN_VERSIONS) + LIST(SORT _TOOLCHAIN_VERSIONS) + LIST(REVERSE _TOOLCHAIN_VERSIONS) + FOREACH(_TOOLCHAIN_VERSION ${_TOOLCHAIN_VERSIONS}) + STRING(REGEX REPLACE ".+${_PREFIX}-([0-9.]+)" "\\1" _TOOLCHAIN_VERSION "${_TOOLCHAIN_VERSION}") + IF(_TOOLCHAIN_VERSION MATCHES "^([0-9.]+)$") + LIST(APPEND ${_COMPILER}_TOOLCHAIN_VERSIONS ${_TOOLCHAIN_VERSION}) + ENDIF() + ENDFOREACH() + ENDIF() + + IF(NOT ${_COMPILER}_TOOLCHAIN_VERSIONS) + MESSAGE(FATAL_ERROR "No Android ${_COMPILER} toolchain found in default search path ${NDK_ROOT}/toolchains") + ENDIF() + + IF(${_COMPILER}_TOOLCHAIN_VERSIONS) + LIST(FIND ${_COMPILER}_TOOLCHAIN_VERSIONS "${${_COMPILER}_TOOLCHAIN_VERSION}" _INDEX) + IF(_INDEX EQUAL -1) + LIST(GET ${_COMPILER}_TOOLCHAIN_VERSIONS 0 ${_COMPILER}_TOOLCHAIN_VERSION) + ENDIF() + ELSE() + LIST(GET ${_COMPILER}_TOOLCHAIN_VERSIONS 0 ${_COMPILER}_TOOLCHAIN_VERSION) + ENDIF() + + SET(${_COMPILER}_TOOLCHAIN_ROOT "${NDK_ROOT}/toolchains/${${_COMPILER}_TOOLCHAIN_PREFIX}-${${_COMPILER}_TOOLCHAIN_VERSION}/prebuilt/${TOOLCHAIN_HOST}") + + IF(NOT EXISTS "${${_COMPILER}_TOOLCHAIN_ROOT}") + FILE(GLOB _TOOLCHAIN_PREFIXES "${${_COMPILER}_TOOLCHAIN_ROOT}*") + IF(_TOOLCHAIN_PREFIXES) + LIST(GET _TOOLCHAIN_PREFIXES 0 ${_COMPILER}_TOOLCHAIN_ROOT) + ENDIF(_TOOLCHAIN_PREFIXES) + ENDIF() +ENDMACRO() + +IF(CLANG) + SEARCH_TOOLCHAIN(CLANG) + + MESSAGE(STATUS "Target Android NDK ${NDK_TARGET} and use clang ${CLANG_TOOLCHAIN_VERSION}") +ENDIF() + +SEARCH_TOOLCHAIN(GCC) + +MESSAGE(STATUS "Target Android NDK ${NDK_TARGET} and use GCC ${GCC_TOOLCHAIN_VERSION}") +MESSAGE(STATUS "Found Android LLVM toolchain in ${CLANG_TOOLCHAIN_ROOT}") +MESSAGE(STATUS "Found Android GCC toolchain in ${GCC_TOOLCHAIN_ROOT}") + SET(PLATFORM_ROOT "${NDK_ROOT}/platforms/android-${NDK_TARGET}/arch-${TOOLCHAIN_ARCH}") -IF(NOT EXISTS "${TOOLCHAIN_ROOT}") - FILE(GLOB _TOOLCHAIN_PREFIXES "${TOOLCHAIN_ROOT}*") - IF(_TOOLCHAIN_PREFIXES) - LIST(GET _TOOLCHAIN_PREFIXES 0 TOOLCHAIN_ROOT) - ENDIF(_TOOLCHAIN_PREFIXES) -ENDIF(NOT EXISTS "${TOOLCHAIN_ROOT}") - -MESSAGE(STATUS "Found Android toolchain in ${TOOLCHAIN_ROOT}") MESSAGE(STATUS "Found Android platform in ${PLATFORM_ROOT}") # include dirs SET(PLATFORM_INCLUDE_DIR "${PLATFORM_ROOT}/usr/include") SET(STL_DIR "${NDK_ROOT}/sources/cxx-stl/gnu-libstdc++") -IF(EXISTS "${STL_DIR}/${NDK_TOOLCHAIN_VERSION}") +IF(EXISTS "${STL_DIR}/${GCC_TOOLCHAIN_VERSION}") # NDK version >= 8b - SET(STL_DIR "${STL_DIR}/${NDK_TOOLCHAIN_VERSION}") -ENDIF(EXISTS "${STL_DIR}/${NDK_TOOLCHAIN_VERSION}") + SET(STL_DIR "${STL_DIR}/${GCC_TOOLCHAIN_VERSION}") +ENDIF(EXISTS "${STL_DIR}/${GCC_TOOLCHAIN_VERSION}") # Determine bin prefix for toolchain -FILE(GLOB _TOOLCHAIN_BIN_PREFIXES "${TOOLCHAIN_ROOT}/bin/${TOOLCHAIN_BIN_PREFIX}-*-gcc${TOOLCHAIN_BIN_SUFFIX}") +FILE(GLOB _TOOLCHAIN_BIN_PREFIXES "${GCC_TOOLCHAIN_ROOT}/bin/${TOOLCHAIN_BIN_PREFIX}-*-gcc${TOOLCHAIN_BIN_SUFFIX}") IF(_TOOLCHAIN_BIN_PREFIXES) LIST(GET _TOOLCHAIN_BIN_PREFIXES 0 _TOOLCHAIN_BIN_PREFIX) - STRING(REGEX REPLACE "${TOOLCHAIN_ROOT}/bin/([a-z0-9-]+)-gcc${TOOLCHAIN_BIN_SUFFIX}" "\\1" TOOLCHAIN_BIN_PREFIX "${_TOOLCHAIN_BIN_PREFIX}") + STRING(REGEX REPLACE "${GCC_TOOLCHAIN_ROOT}/bin/([a-z0-9-]+)-gcc${TOOLCHAIN_BIN_SUFFIX}" "\\1" TOOLCHAIN_BIN_PREFIX "${_TOOLCHAIN_BIN_PREFIX}") ENDIF(_TOOLCHAIN_BIN_PREFIXES) SET(STL_INCLUDE_DIR "${STL_DIR}/include") @@ -128,22 +151,48 @@ SET(STL_LIBRARY_DIR "${STL_DIR}/libs/${LIBRARY_ARCHITECTURE}") SET(STL_INCLUDE_CPU_DIR "${STL_LIBRARY_DIR}/include") SET(STL_LIBRARY "${STL_LIBRARY_DIR}/libgnustl_static.a") -SET(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_ROOT} ${PLATFORM_ROOT}/usr ${CMAKE_PREFIX_PATH} ${CMAKE_INSTALL_PREFIX} $ENV{EXTERNAL_ANDROID_PATH} CACHE string "Android find search path root") +MESSAGE(STATUS "STL include dir: ${STL_INCLUDE_DIR}") +MESSAGE(STATUS "STL library dir: ${STL_LIBRARY_DIR}") + +SET(CMAKE_FIND_ROOT_PATH ${CLANG_TOOLCHAIN_ROOT} ${GCC_TOOLCHAIN_ROOT} ${PLATFORM_ROOT}/usr ${CMAKE_PREFIX_PATH} ${CMAKE_INSTALL_PREFIX} $ENV{EXTERNAL_ANDROID_PATH} CACHE string "Android find search path root") SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -INCLUDE_DIRECTORIES(${STL_INCLUDE_DIR} ${STL_INCLUDE_CPU_DIR}) - MACRO(SET_TOOLCHAIN_BINARY _NAME _BINARY) - SET(${_NAME} ${TOOLCHAIN_ROOT}/bin/${TOOLCHAIN_BIN_PREFIX}-${_BINARY}${TOOLCHAIN_BIN_SUFFIX}) + IF("${_BINARY}" MATCHES "clang") + SET(${_NAME} ${CLANG_TOOLCHAIN_ROOT}/bin/${_BINARY}${TOOLCHAIN_BIN_SUFFIX} CACHE PATH "" FORCE ) + ELSE() + SET(${_NAME} ${GCC_TOOLCHAIN_ROOT}/bin/${TOOLCHAIN_BIN_PREFIX}-${_BINARY}${TOOLCHAIN_BIN_SUFFIX} CACHE PATH "" FORCE) + ENDIF() ENDMACRO(SET_TOOLCHAIN_BINARY) -SET_TOOLCHAIN_BINARY(CMAKE_C_COMPILER gcc) -SET_TOOLCHAIN_BINARY(CMAKE_CXX_COMPILER g++) - # Force the compilers to GCC for Android include (CMakeForceCompiler) -CMAKE_FORCE_C_COMPILER(${CMAKE_C_COMPILER} GNU) -CMAKE_FORCE_CXX_COMPILER(${CMAKE_CXX_COMPILER} GNU) + +IF(CLANG) + SET_TOOLCHAIN_BINARY(CMAKE_C_COMPILER clang) + SET_TOOLCHAIN_BINARY(CMAKE_CXX_COMPILER clang++) + + CMAKE_FORCE_C_COMPILER(${CMAKE_C_COMPILER} clang) + CMAKE_FORCE_CXX_COMPILER(${CMAKE_CXX_COMPILER} clang) + + MESSAGE(STATUS "Using clang compiler") +ELSE() + SET_TOOLCHAIN_BINARY(CMAKE_C_COMPILER gcc) + SET_TOOLCHAIN_BINARY(CMAKE_CXX_COMPILER g++) + + CMAKE_FORCE_C_COMPILER(${CMAKE_C_COMPILER} GNU) + CMAKE_FORCE_CXX_COMPILER(${CMAKE_CXX_COMPILER} GNU) + + MESSAGE(STATUS "Using GCC compiler") +ENDIF() + +SET_TOOLCHAIN_BINARY(CMAKE_STRIP strip) +SET_TOOLCHAIN_BINARY(CMAKE_AR ar) +SET_TOOLCHAIN_BINARY(CMAKE_LINKER ld) +SET_TOOLCHAIN_BINARY(CMAKE_NM nm) +SET_TOOLCHAIN_BINARY(CMAKE_OBJCOPY objcopy) +SET_TOOLCHAIN_BINARY(CMAKE_OBJDUMP objdump) +SET_TOOLCHAIN_BINARY(CMAKE_RANLIB ranlib) diff --git a/code/CMakeModules/FindMSVC.cmake b/code/CMakeModules/FindMSVC.cmake index 16455b02d..644fc57e6 100644 --- a/code/CMakeModules/FindMSVC.cmake +++ b/code/CMakeModules/FindMSVC.cmake @@ -57,6 +57,7 @@ ENDMACRO(DETECT_EXPRESS_VERSION) IF(MSVC12) DETECT_VC_VERSION("12.0") + SET(MSVC_TOOLSET "120") IF(NOT MSVC12_REDIST_DIR) # If you have VC++ 2013 Express, put x64/Microsoft.VC120.CRT/*.dll in ${EXTERNAL_PATH}/redist @@ -64,6 +65,7 @@ IF(MSVC12) ENDIF(NOT MSVC11_REDIST_DIR) ELSEIF(MSVC11) DETECT_VC_VERSION("11.0") + SET(MSVC_TOOLSET "110") IF(NOT MSVC11_REDIST_DIR) # If you have VC++ 2012 Express, put x64/Microsoft.VC110.CRT/*.dll in ${EXTERNAL_PATH}/redist @@ -71,6 +73,7 @@ ELSEIF(MSVC11) ENDIF(NOT MSVC11_REDIST_DIR) ELSEIF(MSVC10) DETECT_VC_VERSION("10.0") + SET(MSVC_TOOLSET "100") IF(NOT MSVC10_REDIST_DIR) # If you have VC++ 2010 Express, put x64/Microsoft.VC100.CRT/*.dll in ${EXTERNAL_PATH}/redist @@ -78,8 +81,10 @@ ELSEIF(MSVC10) ENDIF(NOT MSVC10_REDIST_DIR) ELSEIF(MSVC90) DETECT_VC_VERSION("9.0") + SET(MSVC_TOOLSET "90") ELSEIF(MSVC80) DETECT_VC_VERSION("8.0") + SET(MSVC_TOOLSET "80") ENDIF(MSVC12) # If you plan to use VC++ compilers with WINE, set VC_DIR environment variable diff --git a/code/CMakeModules/FindMySQL.cmake b/code/CMakeModules/FindMySQL.cmake index eb2102c8d..0e0ebfd48 100644 --- a/code/CMakeModules/FindMySQL.cmake +++ b/code/CMakeModules/FindMySQL.cmake @@ -13,7 +13,7 @@ IF(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES) SET(MYSQL_FOUND TRUE) -ELSE(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES) +ELSE() FIND_PATH(MYSQL_INCLUDE_DIR mysql.h PATH_SUFFIXES mysql @@ -33,7 +33,7 @@ ELSE(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES) PATHS $ENV{ProgramFiles}/MySQL/*/lib/opt $ENV{SystemDrive}/MySQL/*/lib/opt) - ELSE(WIN32 AND MSVC) + ELSE() FIND_LIBRARY(MYSQL_LIBRARY_RELEASE NAMES mysqlclient PATHS /usr/lib @@ -51,31 +51,30 @@ ELSE(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES) /usr/local/lib/mysql /opt/local/lib/mysql5/mysql ) - ENDIF(WIN32 AND MSVC) + ENDIF() IF(MYSQL_INCLUDE_DIR) IF(MYSQL_LIBRARY_RELEASE) - SET(MYSQL_LIBRARIES optimized ${MYSQL_LIBRARY_RELEASE}) IF(MYSQL_LIBRARY_DEBUG) - SET(MYSQL_LIBRARIES ${MYSQL_LIBRARIES} debug ${MYSQL_LIBRARY_DEBUG}) - ELSE(MYSQL_LIBRARY_DEBUG) - SET(MYSQL_LIBRARIES ${MYSQL_LIBRARIES} debug ${MYSQL_LIBRARY_RELEASE}) - ENDIF(MYSQL_LIBRARY_DEBUG) + SET(MYSQL_LIBRARIES optimized ${MYSQL_LIBRARY_RELEASE} debug ${MYSQL_LIBRARY_DEBUG}) + ELSE() + SET(MYSQL_LIBRARIES ${MYSQL_LIBRARY_RELEASE}) + ENDIF() FIND_PACKAGE(OpenSSL) IF(OPENSSL_FOUND) SET(MYSQL_LIBRARIES ${MYSQL_LIBRARIES} ${OPENSSL_LIBRARIES}) - ENDIF(OPENSSL_FOUND) - ENDIF(MYSQL_LIBRARY_RELEASE) - ENDIF(MYSQL_INCLUDE_DIR) + ENDIF() + ENDIF() + ENDIF() IF(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES) SET(MYSQL_FOUND TRUE) MESSAGE(STATUS "Found MySQL: ${MYSQL_INCLUDE_DIR}, ${MYSQL_LIBRARIES}") - ELSE(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES) + ELSE() SET(MYSQL_FOUND FALSE) MESSAGE(STATUS "MySQL not found.") - ENDIF(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES) + ENDIF() MARK_AS_ADVANCED(MYSQL_LIBRARY_RELEASE MYSQL_LIBRARY_DEBUG) -ENDIF(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES) +ENDIF() diff --git a/code/CMakeModules/FindWindowsSDK.cmake b/code/CMakeModules/FindWindowsSDK.cmake index 2e72af9e5..31288eb03 100644 --- a/code/CMakeModules/FindWindowsSDK.cmake +++ b/code/CMakeModules/FindWindowsSDK.cmake @@ -68,6 +68,10 @@ ENDIF(WINSDKCURRENT_VERSION_INCLUDE) SET(WINSDKENV_DIR $ENV{WINSDK_DIR}) +IF(NOT WINSDKENV_DIR) + SET(WINSDKENV_DIR $ENV{WindowsSDKDir}) +ENDIF(NOT WINSDKENV_DIR) + MACRO(FIND_WINSDK_VERSION_HEADERS) IF(WINSDK_DIR AND NOT WINSDK_VERSION) # Search version in headers @@ -78,7 +82,6 @@ MACRO(FIND_WINSDK_VERSION_HEADERS) ) IF(_MSI_FILE) - # Look for Windows SDK 8.0 FILE(STRINGS ${_MSI_FILE} _CONTENT REGEX "^#ifndef NTDDI_WIN8") @@ -181,7 +184,7 @@ MACRO(USE_CURRENT_WINSDK) # Look for Windows.h because there are several paths IF(EXISTS ${_INCLUDE}/Windows.h) STRING(REGEX REPLACE "/(include|INCLUDE|Include)(.*)" "" WINSDK_DIR ${_INCLUDE}) - MESSAGE(STATUS "Found Windows SDK from include environment variable in ${WINSDK_DIR}") + MESSAGE(STATUS "Found Windows SDK in INCLUDE environment variable: ${WINSDK_DIR}") BREAK() ENDIF(EXISTS ${_INCLUDE}/Windows.h) ENDFOREACH(_INCLUDE) @@ -280,6 +283,13 @@ FIND_PATH(WINSDK_SHARED_INCLUDE_DIR d3d9.h ${WINSDK_DIR}/Include ) +# directory where OpenGL headers are found +FIND_PATH(WINSDK_OPENGL_INCLUDE_DIR GL.h + HINTS + ${WINSDK_DIR}/Include/gl + ${WINSDK_DIR}/Include +) + # directory where all libraries are found FIND_PATH(WINSDK_LIBRARY_DIR ComCtl32.lib HINTS @@ -303,7 +313,7 @@ FIND_PROGRAM(WINSDK_MIDL midl IF(WINSDK_INCLUDE_DIR) SET(WINSDK_FOUND ON) - SET(WINSDK_INCLUDE_DIRS ${WINSDK_INCLUDE_DIR} ${WINSDK_SHARED_INCLUDE_DIR}) + SET(WINSDK_INCLUDE_DIRS ${WINSDK_INCLUDE_DIR} ${WINSDK_SHARED_INCLUDE_DIR} ${WINSDK_OPENGL_INCLUDE_DIR}) SET(CMAKE_LIBRARY_PATH ${WINSDK_LIBRARY_DIR} ${CMAKE_LIBRARY_PATH}) INCLUDE_DIRECTORIES(${WINSDK_INCLUDE_DIRS}) diff --git a/code/CMakeModules/GetRevision.cmake b/code/CMakeModules/GetRevision.cmake index 21b234f74..7f0a4e5f1 100644 --- a/code/CMakeModules/GetRevision.cmake +++ b/code/CMakeModules/GetRevision.cmake @@ -13,38 +13,44 @@ IF(SOURCE_DIR) IF(NOT ROOT_DIR AND SOURCE_DIR) SET(ROOT_DIR ${SOURCE_DIR}) - ENDIF(NOT ROOT_DIR AND SOURCE_DIR) + ENDIF() IF(NOT SOURCE_DIR AND ROOT_DIR) SET(SOURCE_DIR ${ROOT_DIR}) - ENDIF(NOT SOURCE_DIR AND ROOT_DIR) -ELSE(SOURCE_DIR) + ENDIF() +ELSE() SET(SOURCE_DIR ${CMAKE_SOURCE_DIR}) SET(ROOT_DIR ${CMAKE_SOURCE_DIR}) -ENDIF(SOURCE_DIR) +ENDIF() MACRO(NOW RESULT) IF (WIN32) EXECUTE_PROCESS(COMMAND "wmic" "os" "get" "localdatetime" OUTPUT_VARIABLE DATETIME) IF(NOT DATETIME MATCHES "ERROR") STRING(REGEX REPLACE ".*\n([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9]).*" "\\1-\\2-\\3 \\4:\\5:\\6" ${RESULT} "${DATETIME}") - ENDIF(NOT DATETIME MATCHES "ERROR") + ENDIF() ELSEIF(UNIX) EXECUTE_PROCESS(COMMAND "date" "+%Y-%m-%d %H:%M:%S" OUTPUT_VARIABLE DATETIME) STRING(REGEX REPLACE "([0-9: -]+).*" "\\1" ${RESULT} "${DATETIME}") - ELSE (WIN32) + ELSE() MESSAGE(SEND_ERROR "date not implemented") SET(${RESULT} "0000-00-00 00:00:00") - ENDIF (WIN32) + ENDIF() ENDMACRO(NOW) IF(EXISTS "${ROOT_DIR}/.svn/") - FIND_PACKAGE(Subversion) + FIND_PACKAGE(Subversion QUIET) IF(SUBVERSION_FOUND) Subversion_WC_INFO(${ROOT_DIR} ER) SET(REVISION ${ER_WC_REVISION}) ENDIF(SUBVERSION_FOUND) + + FIND_PACKAGE(TortoiseSVN QUIET) + + IF(TORTOISESVN_FOUND) + TORTOISESVN_GET_REVISION(${ROOT_DIR} REVISION) + ENDIF(TORTOISESVN_FOUND) ENDIF(EXISTS "${ROOT_DIR}/.svn/") IF(EXISTS "${ROOT_DIR}/.hg/") @@ -55,8 +61,8 @@ IF(EXISTS "${ROOT_DIR}/.hg/") SET(REVISION ${ER_WC_REVISION}) SET(CHANGESET ${ER_WC_CHANGESET}) SET(BRANCH ${ER_WC_BRANCH}) - ENDIF(MERCURIAL_FOUND) -ENDIF(EXISTS "${ROOT_DIR}/.hg/") + ENDIF() +ENDIF() # if processing exported sources, use "revision" file if exists IF(SOURCE_DIR AND NOT DEFINED REVISION) @@ -64,8 +70,8 @@ IF(SOURCE_DIR AND NOT DEFINED REVISION) IF(EXISTS ${REVISION_FILE}) FILE(STRINGS ${REVISION_FILE} REVISION LIMIT_COUNT 1) MESSAGE(STATUS "Read revision ${REVISION} from file") - ENDIF(EXISTS ${REVISION_FILE}) -ENDIF(SOURCE_DIR AND NOT DEFINED REVISION) + ENDIF() +ENDIF() IF(SOURCE_DIR AND DEFINED REVISION) IF(EXISTS ${SOURCE_DIR}/revision.h.in) @@ -73,5 +79,5 @@ IF(SOURCE_DIR AND DEFINED REVISION) NOW(BUILD_DATE) CONFIGURE_FILE(${SOURCE_DIR}/revision.h.in revision.h.txt) EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy revision.h.txt revision.h) # copy_if_different - ENDIF(EXISTS ${SOURCE_DIR}/revision.h.in) -ENDIF(SOURCE_DIR AND DEFINED REVISION) + ENDIF() +ENDIF() From 539f721624cf5556c689f942cbceacf86da0cbfd Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 13:57:06 +0100 Subject: [PATCH 65/87] Fixed: Compilation --- code/nel/src/misc/config_file/cf_gramatical.cpp | 4 ++-- code/nel/src/misc/config_file/cf_gramatical.ypp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/nel/src/misc/config_file/cf_gramatical.cpp b/code/nel/src/misc/config_file/cf_gramatical.cpp index bc51ef371..1d8c568b7 100644 --- a/code/nel/src/misc/config_file/cf_gramatical.cpp +++ b/code/nel/src/misc/config_file/cf_gramatical.cpp @@ -1499,7 +1499,7 @@ void cf_setVar (NLMISC::CConfigFile::CVar &Var, cf_value Val) switch (Val.Type) { case NLMISC::CConfigFile::CVar::T_REAL: Var.IntValues.push_back ((int)Val.Real); break; - case NLMISC::CConfigFile::CVar::T_STRING: int val = 0; NLMISC::fromString(Val.String, val); Var.IntValues.push_back(val); break; + case NLMISC::CConfigFile::CVar::T_STRING: { int val = 0; NLMISC::fromString(Val.String, val); Var.IntValues.push_back(val); break; } default: break; } break; @@ -1507,7 +1507,7 @@ void cf_setVar (NLMISC::CConfigFile::CVar &Var, cf_value Val) switch (Val.Type) { case NLMISC::CConfigFile::CVar::T_INT: Var.RealValues.push_back ((double)Val.Int); break; - case NLMISC::CConfigFile::CVar::T_STRING: double val = 0.0; NLMISC::fromString(Val.String, val); Var.RealValues.push_back(val); break; + case NLMISC::CConfigFile::CVar::T_STRING: { double val = 0.0; NLMISC::fromString(Val.String, val); Var.RealValues.push_back(val); break; } default: break; } break; diff --git a/code/nel/src/misc/config_file/cf_gramatical.ypp b/code/nel/src/misc/config_file/cf_gramatical.ypp index 0f4fd2405..578bf53bf 100644 --- a/code/nel/src/misc/config_file/cf_gramatical.ypp +++ b/code/nel/src/misc/config_file/cf_gramatical.ypp @@ -517,7 +517,7 @@ void cf_setVar (NLMISC::CConfigFile::CVar &Var, cf_value Val) switch (Val.Type) { case NLMISC::CConfigFile::CVar::T_REAL: Var.IntValues.push_back ((int)Val.Real); break; - case NLMISC::CConfigFile::CVar::T_STRING: int val = 0; NLMISC::fromString(Val.String, val); Var.RealValues.push_back(val); break; + case NLMISC::CConfigFile::CVar::T_STRING: { int val = 0; NLMISC::fromString(Val.String, val); Var.RealValues.push_back(val); break; } default: break; } break; @@ -525,7 +525,7 @@ void cf_setVar (NLMISC::CConfigFile::CVar &Var, cf_value Val) switch (Val.Type) { case NLMISC::CConfigFile::CVar::T_INT: Var.RealValues.push_back ((double)Val.Int); break; - case NLMISC::CConfigFile::CVar::T_STRING: double val = 0.0; NLMISC::fromString(Val.String, val); Var.RealValues.push_back(val); break; + case NLMISC::CConfigFile::CVar::T_STRING: { double val = 0.0; NLMISC::fromString(Val.String, val); Var.RealValues.push_back(val); break; } default: break; } break; From 44d0c95b692183c7c06dd2e1f1d9131cc9d79fe6 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 14:25:50 +0100 Subject: [PATCH 66/87] Fixed: Warning with multichars to int conversion --- code/nel/src/3d/vertex_program_parse.cpp | 183 ++++++++++++++++------- 1 file changed, 131 insertions(+), 52 deletions(-) diff --git a/code/nel/src/3d/vertex_program_parse.cpp b/code/nel/src/3d/vertex_program_parse.cpp index 40ac2282e..0e144d54f 100644 --- a/code/nel/src/3d/vertex_program_parse.cpp +++ b/code/nel/src/3d/vertex_program_parse.cpp @@ -17,7 +17,86 @@ #include "std3d.h" #include "nel/3d/vertex_program_parse.h" - +enum TArguments +{ +#ifdef NL_LITTLE_ENDIAN + ADD = 1094992928, + ARL = 1095912480, + BFC0 = 1111900976, + BFC1 = 1111900977, + COL0 = 1129270320, + COL1 = 1129270321, + DP3 = 1146106656, + DP4 = 1146106912, + DST = 1146311712, + END = 1162757152, + EXP = 1163415584, + EXPP = 1163415632, + FOGC = 1179600707, + HPOS = 1213222739, + LIT = 1279874080, + LOG = 1280263968, + MAD = 1296122912, + MAX = 1296128032, + MIN = 1296649760, + MOV = 1297045024, + MUL = 1297435680, + NRML = 1314016588, + OPOS = 1330663251, + PSIZ = 1347635546, + RCP = 1380143136, + RSQ = 1381191968, + SGE = 1397179680, + SLT = 1397511200, + TEX0 = 1413830704, + TEX1 = 1413830705, + TEX2 = 1413830706, + TEX3 = 1413830707, + TEX4 = 1413830708, + TEX5 = 1413830709, + TEX6 = 1413830710, + TEX7 = 1413830711, + WGHT = 1464289364, +#else + ADD = 541344833, + ARL = 541872705, + BFC0 = 809715266, + BFC1 = 826492482, + COL0 = 810307395, + COL1 = 827084611, + DP3 = 540233796, + DP4 = 540299332, + DST = 542397252, + END = 541347397, + EXP = 542136389, + EXPP = 1347442757, + FOGC = 1128746822, + HPOS = 1397706824, + LIT = 542394700, + LOG = 541544268, + MAD = 541344077, + MAX = 542654797, + MIN = 542001485, + MOV = 542527309, + MUL = 541873485, + NRML = 1280135758, + OPOS = 1397706831, + PSIZ = 1514754896, + RCP = 542131026, + RSQ = 542200658, + SGE = 541411155, + SLT = 542395475, + TEX0 = 811091284, + TEX1 = 827868500, + TEX2 = 844645716, + TEX3 = 861422932, + TEX4 = 878200148, + TEX5 = 894977364, + TEX6 = 911754580, + TEX7 = 928531796, + WGHT = 1414022999, +#endif +}; //===================================== bool CVPParser::parseWriteMask(uint &mask, std::string &errorOutput) @@ -256,23 +335,23 @@ bool CVPParser::parseInputRegister(CVPOperand &operand, std::string &errorOutput strValue |= ((uint32) *_CurrChar) << (8 * (3 - k)); ++_CurrChar; } - switch (strValue) + switch ((TArguments)strValue) { - case 'OPOS': operand.Value.InputRegisterValue = CVPOperand::IPosition; break; - case 'WGHT': operand.Value.InputRegisterValue = CVPOperand::IWeight; break; - case 'NRML': operand.Value.InputRegisterValue = CVPOperand::INormal; break; - case 'COL0': operand.Value.InputRegisterValue = CVPOperand::IPrimaryColor; break; - case 'COL1': operand.Value.InputRegisterValue = CVPOperand::ISecondaryColor; break; - case 'FOGC': operand.Value.InputRegisterValue = CVPOperand::IFogCoord; break; + case OPOS: operand.Value.InputRegisterValue = CVPOperand::IPosition; break; + case WGHT: operand.Value.InputRegisterValue = CVPOperand::IWeight; break; + case NRML: operand.Value.InputRegisterValue = CVPOperand::INormal; break; + case COL0: operand.Value.InputRegisterValue = CVPOperand::IPrimaryColor; break; + case COL1: operand.Value.InputRegisterValue = CVPOperand::ISecondaryColor; break; + case FOGC: operand.Value.InputRegisterValue = CVPOperand::IFogCoord; break; // texture argument - case 'TEX0': - case 'TEX1': - case 'TEX2': - case 'TEX3': - case 'TEX4': - case 'TEX5': - case 'TEX6': - case 'TEX7': + case TEX0: + case TEX1: + case TEX2: + case TEX3: + case TEX4: + case TEX5: + case TEX6: + case TEX7: operand.Value.InputRegisterValue = (CVPOperand::EInputRegister) (((CVPOperand::ITex0 + strValue) & 0xff) - '0'); break; default: @@ -384,23 +463,23 @@ bool CVPParser::parseOutputRegister(CVPOperand &operand, std::string &errorOutpu ++_CurrChar; } // convert to enum - switch(strValue) + switch((TArguments)strValue) { - case 'HPOS': operand.Value.OutputRegisterValue = CVPOperand::OHPosition; break; - case 'COL0': operand.Value.OutputRegisterValue = CVPOperand::OPrimaryColor; break; - case 'COL1': operand.Value.OutputRegisterValue = CVPOperand::OSecondaryColor; break; - case 'BFC0': operand.Value.OutputRegisterValue = CVPOperand::OBackFacePrimaryColor; break; - case 'BFC1': operand.Value.OutputRegisterValue = CVPOperand::OBackFaceSecondaryColor; break; - case 'FOGC': operand.Value.OutputRegisterValue = CVPOperand::OFogCoord; break; - case 'PSIZ': operand.Value.OutputRegisterValue = CVPOperand::OPointSize; break; - case 'TEX0': operand.Value.OutputRegisterValue = CVPOperand::OTex0; break; - case 'TEX1': operand.Value.OutputRegisterValue = CVPOperand::OTex1; break; - case 'TEX2': operand.Value.OutputRegisterValue = CVPOperand::OTex2; break; - case 'TEX3': operand.Value.OutputRegisterValue = CVPOperand::OTex3; break; - case 'TEX4': operand.Value.OutputRegisterValue = CVPOperand::OTex4; break; - case 'TEX5': operand.Value.OutputRegisterValue = CVPOperand::OTex5; break; - case 'TEX6': operand.Value.OutputRegisterValue = CVPOperand::OTex6; break; - case 'TEX7': operand.Value.OutputRegisterValue = CVPOperand::OTex7; break; + case HPOS: operand.Value.OutputRegisterValue = CVPOperand::OHPosition; break; + case COL0: operand.Value.OutputRegisterValue = CVPOperand::OPrimaryColor; break; + case COL1: operand.Value.OutputRegisterValue = CVPOperand::OSecondaryColor; break; + case BFC0: operand.Value.OutputRegisterValue = CVPOperand::OBackFacePrimaryColor; break; + case BFC1: operand.Value.OutputRegisterValue = CVPOperand::OBackFaceSecondaryColor; break; + case FOGC: operand.Value.OutputRegisterValue = CVPOperand::OFogCoord; break; + case PSIZ: operand.Value.OutputRegisterValue = CVPOperand::OPointSize; break; + case TEX0: operand.Value.OutputRegisterValue = CVPOperand::OTex0; break; + case TEX1: operand.Value.OutputRegisterValue = CVPOperand::OTex1; break; + case TEX2: operand.Value.OutputRegisterValue = CVPOperand::OTex2; break; + case TEX3: operand.Value.OutputRegisterValue = CVPOperand::OTex3; break; + case TEX4: operand.Value.OutputRegisterValue = CVPOperand::OTex4; break; + case TEX5: operand.Value.OutputRegisterValue = CVPOperand::OTex5; break; + case TEX6: operand.Value.OutputRegisterValue = CVPOperand::OTex6; break; + case TEX7: operand.Value.OutputRegisterValue = CVPOperand::OTex7; break; default: errorOutput = "Can't read index for output register."; return false; @@ -753,9 +832,9 @@ bool CVPParser::parseInstruction(CVPInstruction &instr, std::string &errorOutput { instrStr |= (uint32) ' '; } - switch (instrStr) + switch ((TArguments)instrStr) { - case 'ARL ': + case ARL: instr.Opcode = CVPInstruction::ARL; if (!parseOp2(instr, errorOutput)) return false; if (!instr.Src1.Swizzle.isScalar()) @@ -764,7 +843,7 @@ bool CVPParser::parseInstruction(CVPInstruction &instr, std::string &errorOutput return false; } break; - case 'RSQ ': + case RSQ: instr.Opcode = CVPInstruction::RSQ; if (!parseOp2(instr, errorOutput)) return false; if (!instr.Src1.Swizzle.isScalar()) @@ -773,8 +852,8 @@ bool CVPParser::parseInstruction(CVPInstruction &instr, std::string &errorOutput return false; } break; - case 'EXP ': - case 'EXPP': + case EXP: + case EXPP: instr.Opcode = CVPInstruction::EXPP; if (!parseOp2(instr, errorOutput)) return false; if (!instr.Src1.Swizzle.isScalar()) @@ -789,7 +868,7 @@ bool CVPParser::parseInstruction(CVPInstruction &instr, std::string &errorOutput return false; }*/ break; - case 'LOG ': + case LOG: instr.Opcode = CVPInstruction::LOG; if (!parseOp2(instr, errorOutput)) return false; if (!instr.Src1.Swizzle.isScalar()) @@ -805,7 +884,7 @@ bool CVPParser::parseInstruction(CVPInstruction &instr, std::string &errorOutput } */ break; - case 'RCP ': + case RCP: instr.Opcode = CVPInstruction::RCP; if (!parseOp2(instr, errorOutput)) return false; if (!instr.Src1.Swizzle.isScalar()) @@ -815,60 +894,60 @@ bool CVPParser::parseInstruction(CVPInstruction &instr, std::string &errorOutput } break; ///////////////// - case 'MOV ': + case MOV: instr.Opcode = CVPInstruction::MOV; if (!parseOp2(instr, errorOutput)) return false; break; - case 'LIT ': + case LIT: instr.Opcode = CVPInstruction::LIT; if (!parseOp2(instr, errorOutput)) return false; break; ///////////////// - case 'MAD ': + case MAD: instr.Opcode = CVPInstruction::MAD; if (!parseOp4(instr, errorOutput)) return false; break; ///////////////// - case 'ADD ': + case ADD: instr.Opcode = CVPInstruction::ADD; if (!parseOp3(instr, errorOutput)) return false; break; ///////////////// - case 'MUL ': + case MUL: instr.Opcode = CVPInstruction::MUL; if (!parseOp3(instr, errorOutput)) return false; break; - case 'DP3 ': + case DP3: instr.Opcode = CVPInstruction::DP3; if (!parseOp3(instr, errorOutput)) return false; break; - case 'DP4 ': + case DP4: instr.Opcode = CVPInstruction::DP4; if (!parseOp3(instr, errorOutput)) return false; break; - case 'DST ': + case DST: instr.Opcode = CVPInstruction::DST; if (!parseOp3(instr, errorOutput)) return false; break; - case 'MIN ': + case MIN: instr.Opcode = CVPInstruction::MIN; if (!parseOp3(instr, errorOutput)) return false; break; - case 'MAX ': + case MAX: instr.Opcode = CVPInstruction::MAX; if (!parseOp3(instr, errorOutput)) return false; break; - case 'SLT ': + case SLT: instr.Opcode = CVPInstruction::SLT; if (!parseOp3(instr, errorOutput)) return false; break; - case 'SGE ': + case SGE: instr.Opcode = CVPInstruction::SGE; if (!parseOp3(instr, errorOutput)) return false; break; ///////////////// - case 'END ': + case END: endEncountered = true; return true; break; From f3b38eed9b0ac115f14d12b91e9fec98ffbcf4b2 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 15:18:53 +0100 Subject: [PATCH 67/87] Changed: Improved User Agent management --- .../src/interface_v3/interface_manager.cpp | 4 ++-- code/ryzom/client/src/user_agent.cpp | 17 ++++++++++++++--- code/ryzom/client/src/user_agent.h | 2 ++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 6f4f31d14..8186d246b 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -467,8 +467,8 @@ CInterfaceManager::CInterfaceManager() CGroupHTML::options.trustedDomains = ClientCfg.WebIgTrustedDomains; CGroupHTML::options.languageCode = ClientCfg.getHtmlLanguageCode(); - CGroupHTML::options.appName = "Ryzom"; - CGroupHTML::options.appVersion = getUserAgent(); + CGroupHTML::options.appName = getUserAgentName(); + CGroupHTML::options.appVersion = getUserAgentVersion(); NLGUI::CDBManager::getInstance()->resizeBanks( NB_CDB_BANKS ); interfaceLinkUpdater = new CInterfaceLink::CInterfaceLinkUpdater(); diff --git a/code/ryzom/client/src/user_agent.cpp b/code/ryzom/client/src/user_agent.cpp index af07e8b86..1452aa584 100644 --- a/code/ryzom/client/src/user_agent.cpp +++ b/code/ryzom/client/src/user_agent.cpp @@ -21,7 +21,7 @@ #include "game_share/ryzom_version.h" -#ifdef HAVE_REVISION_H +#if defined(RYZOM_COMPATIBILITY_VERSION) && defined(HAVE_REVISION_H) #include "revision.h" #endif @@ -45,6 +45,16 @@ #endif std::string getUserAgent() +{ + return getUserAgentName() + "/" + getUserAgentVersion(); +} + +std::string getUserAgentName() +{ + return "Ryzom"; +} + +std::string getUserAgentVersion() { static std::string s_userAgent; @@ -52,8 +62,9 @@ std::string getUserAgent() { char buffer[256]; -#ifdef REVISION - sprintf(buffer, "%s.%s-%s-%s", RYZOM_VERSION, REVISION, RYZOM_SYSTEM, RYZOM_ARCH); +#if defined(REVISION) && defined(RYZOM_COMPATIBILITY_VERSION) + // we don't need RYZOM_VERSION if we already have a numeric form a.b.c, we just need to append revision to it + sprintf(buffer, "%s.%s-%s-%s", RYZOM_COMPATIBILITY_VERSION, REVISION, RYZOM_SYSTEM, RYZOM_ARCH); #else sprintf(buffer, "%s-%s-%s", RYZOM_VERSION, RYZOM_SYSTEM, RYZOM_ARCH); #endif diff --git a/code/ryzom/client/src/user_agent.h b/code/ryzom/client/src/user_agent.h index e42635871..bc508273d 100644 --- a/code/ryzom/client/src/user_agent.h +++ b/code/ryzom/client/src/user_agent.h @@ -18,6 +18,8 @@ #define CL_USER_AGENT_H std::string getUserAgent(); +std::string getUserAgentName(); +std::string getUserAgentVersion(); #endif // CL_USER_AGENT_H From b023af51cf149594ec16979f353a2c02308198bf Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 15:43:05 +0100 Subject: [PATCH 68/87] Added: PCH for admin_modules --- .../ryzom/server/src/admin_modules/stdpch.cpp | 17 +++++++ code/ryzom/server/src/admin_modules/stdpch.h | 45 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 code/ryzom/server/src/admin_modules/stdpch.cpp create mode 100644 code/ryzom/server/src/admin_modules/stdpch.h diff --git a/code/ryzom/server/src/admin_modules/stdpch.cpp b/code/ryzom/server/src/admin_modules/stdpch.cpp new file mode 100644 index 000000000..a3d45576c --- /dev/null +++ b/code/ryzom/server/src/admin_modules/stdpch.cpp @@ -0,0 +1,17 @@ +// 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" diff --git a/code/ryzom/server/src/admin_modules/stdpch.h b/code/ryzom/server/src/admin_modules/stdpch.h new file mode 100644 index 000000000..b7c667c73 --- /dev/null +++ b/code/ryzom/server/src/admin_modules/stdpch.h @@ -0,0 +1,45 @@ +// 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 AI_SHARE_STDPCH_H +#define AI_SHARE_STDPCH_H + +#include +#include + +#include "nel/misc/types_nl.h" + +#include "nel/misc/file.h" +#include "nel/misc/hierarchical_timer.h" +#include "nel/misc/mutable_container.h" +#include "nel/misc/path.h" +#include "nel/misc/singleton.h" +#include "nel/misc/sstring.h" +#include "nel/misc/string_conversion.h" +#include "nel/misc/time_nl.h" +#include "nel/net/message.h" +#include "nel/net/module.h" +#include "nel/net/module_builder_parts.h" +#include "nel/net/module_gateway.h" +#include "nel/net/module_manager.h" +#include "nel/net/module_message.h" +#include "nel/net/service.h" +#include "nel/net/unified_network.h" + +#include "game_share/callback_adaptor.h" +#include "game_share/utils.h" + +#endif From c5ee1f3d95bfd578333e7fa64e3b55e612bf1058 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 16:05:45 +0100 Subject: [PATCH 69/87] Fixed: Compilation --- code/ryzom/server/src/server_share/used_continent.h | 1 + 1 file changed, 1 insertion(+) diff --git a/code/ryzom/server/src/server_share/used_continent.h b/code/ryzom/server/src/server_share/used_continent.h index 150b6342c..40b1eb6fc 100644 --- a/code/ryzom/server/src/server_share/used_continent.h +++ b/code/ryzom/server/src/server_share/used_continent.h @@ -21,6 +21,7 @@ #include "nel/misc/types_nl.h" #include "nel/net/service.h" #include "game_share/continent.h" +#include "game_share/misc_const.h" #include From 8e343db0fab3309578e7e196b53c50e197abb9aa Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 17:47:10 +0100 Subject: [PATCH 70/87] Fixed: Warning comparing an enum to an int --- code/ryzom/client/src/interface_v3/character_3d.cpp | 2 +- code/ryzom/common/src/game_share/people_pd.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/code/ryzom/client/src/interface_v3/character_3d.cpp b/code/ryzom/client/src/interface_v3/character_3d.cpp index c76407f11..f711fb764 100644 --- a/code/ryzom/client/src/interface_v3/character_3d.cpp +++ b/code/ryzom/client/src/interface_v3/character_3d.cpp @@ -797,7 +797,7 @@ void CCharacter3D::setup (const SCharacter3DSetup &c3ds) } // Instance skin color - if (c3ds.People != -1) + if (c3ds.People != EGSPD::CPeople::Undefined) if ((c3ds.People != _CurrentSetup.People) || bInstanceRebuilt || bQualityRebuilt) { if (!_Instances[i].empty()) diff --git a/code/ryzom/common/src/game_share/people_pd.h b/code/ryzom/common/src/game_share/people_pd.h index 379a09378..ffcf8732f 100644 --- a/code/ryzom/common/src/game_share/people_pd.h +++ b/code/ryzom/common/src/game_share/people_pd.h @@ -51,6 +51,7 @@ public: enum TPeople { + Undefined = -1, Humanoid = 0, Playable = 0, Fyros = 0, From da7b88f052b0003ad61adf19c6b228d56b8e1938 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 17:47:55 +0100 Subject: [PATCH 71/87] Fixed: Warning assert always false --- code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp | 2 +- code/ryzom/common/src/game_share/brick_types.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp index 293582f52..6aa1f0e40 100644 --- a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp +++ b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp @@ -456,7 +456,7 @@ bool CCtrlSheetInfo::parseCtrlInfo(xmlNodePtr cur, CInterfaceGroup * /* parentGr else { // must not have so much brick type, else must change code! - nlassert(brickType<32); + // nlassert(brickType<32); // Ok set the bit associated _BrickTypeBitField|= 1< Date: Sat, 14 Feb 2015 17:52:15 +0100 Subject: [PATCH 72/87] Fixed: Unnamed semaphores are deprecated under OS X --- code/nel/include/nel/misc/mutex.h | 12 +++++++++--- code/nel/src/misc/mutex.cpp | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/code/nel/include/nel/misc/mutex.h b/code/nel/include/nel/misc/mutex.h index adbc7e7e5..cb7e9a188 100644 --- a/code/nel/include/nel/misc/mutex.h +++ b/code/nel/include/nel/misc/mutex.h @@ -28,7 +28,11 @@ # endif #elif defined(NL_OS_UNIX) # include // PThread -# include // PThread POSIX semaphores +# ifdef NL_OS_MAC +# include +# else +# include // PThread POSIX semaphores +# endif # include # define __forceinline # ifdef NL_OS_MAC @@ -532,8 +536,10 @@ private: #ifdef NL_OS_WINDOWS TNelRtlCriticalSection _Cs; -#elif defined NL_OS_UNIX - sem_t _Sem; +#elif defined(NL_OS_MAC) + dispatch_semaphore_t _Sem; +#elif defined(NL_OS_UNIX) + sem_t _Sem; #else # error "No fair mutex implementation for this OS" #endif diff --git a/code/nel/src/misc/mutex.cpp b/code/nel/src/misc/mutex.cpp index 3c86e2b29..28f6bae37 100644 --- a/code/nel/src/misc/mutex.cpp +++ b/code/nel/src/misc/mutex.cpp @@ -406,13 +406,21 @@ void CUnfairMutex::leave() */ CFairMutex::CFairMutex() { +#ifdef NL_OS_MAC + _Sem = dispatch_semaphore_create(1); +#else sem_init( const_cast(&_Sem), 0, 1 ); +#endif } CFairMutex::CFairMutex( const std::string &name ) { +#ifdef NL_OS_MAC + _Sem = dispatch_semaphore_create(1); +#else sem_init( const_cast(&_Sem), 0, 1 ); +#endif } @@ -421,7 +429,11 @@ CFairMutex::CFairMutex( const std::string &name ) */ CFairMutex::~CFairMutex() { +#ifdef NL_OS_MAC + dispatch_release(_Sem); +#else sem_destroy( const_cast(&_Sem) ); // needs that no thread is waiting on the semaphore +#endif } @@ -430,7 +442,11 @@ CFairMutex::~CFairMutex() */ void CFairMutex::enter() { +#ifdef NL_OS_MAC + dispatch_semaphore_wait(_Sem, DISPATCH_TIME_FOREVER); +#else sem_wait( const_cast(&_Sem) ); +#endif } @@ -439,7 +455,11 @@ void CFairMutex::enter() */ void CFairMutex::leave() { +#ifdef NL_OS_MAC + dispatch_semaphore_signal(_Sem); +#else sem_post( const_cast(&_Sem) ); +#endif } From f07c2f51b8e65e784f923d39e04c6b2d8fc31064 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 14 Feb 2015 17:54:05 +0100 Subject: [PATCH 73/87] Fixed: Warning multichars --- code/ryzom/client/src/hair_set.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/code/ryzom/client/src/hair_set.cpp b/code/ryzom/client/src/hair_set.cpp index d82733162..5d44e2857 100644 --- a/code/ryzom/client/src/hair_set.cpp +++ b/code/ryzom/client/src/hair_set.cpp @@ -45,20 +45,20 @@ void CHairSet::init (NLMISC::IProgressCallback &progress) progress.progress ((float)k/(float)numHairItem); const CItemSheet *item = SheetMngr.getItem(SLOTTYPE::HEAD_SLOT, k); - if( (item) && (!item->getShape().empty()) ) + if (item && !item->getShape().empty()) { - std::string itemName = NLMISC::toLower(item->getShape()); - if (item->getShape().find("cheveux", 0) != std::string::npos) { // get race - uint16 race = (uint16) itemName[1] | ((uint16) itemName[0] << 8); - switch(race) + std::string itemName = NLMISC::toLower(item->getShape()); + + // fortunately, first character of each race is distinct + switch(itemName[0]) { - case 'ma': _Hairs[Matis].push_back(k); break; - case 'tr': _Hairs[Tryker].push_back(k); break; - case 'zo': _Hairs[Zorai].push_back(k); break; - case 'fy': _Hairs[Fyros].push_back(k); break; + case 'm': _Hairs[Matis].push_back(k); break; + case 't': _Hairs[Tryker].push_back(k); break; + case 'z': _Hairs[Zorai].push_back(k); break; + case 'f': _Hairs[Fyros].push_back(k); break; } } } From d5b620391e164cfac5b555b5948c15bbcf145f41 Mon Sep 17 00:00:00 2001 From: kervala Date: Sun, 15 Feb 2015 09:53:56 +0100 Subject: [PATCH 74/87] Fixed: Wrong include guard for admin_modules PCH --- code/ryzom/server/src/admin_modules/stdpch.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/ryzom/server/src/admin_modules/stdpch.h b/code/ryzom/server/src/admin_modules/stdpch.h index b7c667c73..be01e5019 100644 --- a/code/ryzom/server/src/admin_modules/stdpch.h +++ b/code/ryzom/server/src/admin_modules/stdpch.h @@ -14,8 +14,8 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -#ifndef AI_SHARE_STDPCH_H -#define AI_SHARE_STDPCH_H +#ifndef ADMIN_MODULES_STDPCH_H +#define ADMIN_MODULES_STDPCH_H #include #include From cc52abcfa06b731a8fee546cb3195e703a0db650 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 17 Feb 2015 03:12:26 +0100 Subject: [PATCH 75/87] CMsgBoxDisplayer should not present a dialog now, but write the report to a file then attempt to launch the error reporter application. Which ofc doesn't exist yet in this commit. --- code/nel/src/misc/debug.cpp | 2 +- code/nel/src/misc/report.cpp | 293 ++------------------------------- code/ryzom/client/src/init.cpp | 2 + 3 files changed, 19 insertions(+), 278 deletions(-) diff --git a/code/nel/src/misc/debug.cpp b/code/nel/src/misc/debug.cpp index c7667acc2..2d09f5ef8 100644 --- a/code/nel/src/misc/debug.cpp +++ b/code/nel/src/misc/debug.cpp @@ -83,7 +83,7 @@ using namespace std; #define LOG_IN_FILE NEL_LOG_IN_FILE // If true, debug system will trap crash even if the application is in debugger -static const bool TrapCrashInDebugger = false; +static const bool TrapCrashInDebugger = true; #ifdef DEBUG_NEW #define new DEBUG_NEW diff --git a/code/nel/src/misc/report.cpp b/code/nel/src/misc/report.cpp index 20b2b1c11..39f27de5f 100644 --- a/code/nel/src/misc/report.cpp +++ b/code/nel/src/misc/report.cpp @@ -42,25 +42,14 @@ using namespace std; namespace NLMISC { -#ifdef NL_OS_WINDOWS -static HWND sendReport=NULL; -#endif - //old doesn't work on visual c++ 7.1 due to default parameter typedef bool (*TEmailFunction) (const std::string &smtpServer, const std::string &from, const std::string &to, const std::string &subject, const std::string &body, const std::string &attachedFile = "", bool onlyCheck = false); typedef bool (*TEmailFunction) (const std::string &smtpServer, const std::string &from, const std::string &to, const std::string &subject, const std::string &body, const std::string &attachedFile, bool onlyCheck); -#define DELETE_OBJECT(a) if((a)!=NULL) { DeleteObject (a); a = NULL; } - static TEmailFunction EmailFunction = NULL; void setReportEmailFunction (void *emailFunction) { EmailFunction = (TEmailFunction)emailFunction; - -#ifdef NL_OS_WINDOWS - if (sendReport) - EnableWindow(sendReport, FALSE); -#endif } #ifndef NL_OS_WINDOWS @@ -73,91 +62,26 @@ void report () #else -// Windows specific version - -static string Body; -static string Subject; -static string AttachedFile; - -static HWND checkIgnore=NULL; -static HWND debug=NULL; -static HWND ignore=NULL; -static HWND quit=NULL; -static HWND dialog=NULL; - -static bool NeedExit; -static TReportResult Result; -static bool IgnoreNextTime; -static bool CanSendMailReport= false; - -static bool DebugDefaultBehavior, QuitDefaultBehavior; - -static void sendEmail() +TReportResult report (const std::string &title, const std::string &header, const std::string &subject, const std::string &body, bool enableCheckIgnore, uint debugButton, bool ignoreButton, sint quitButton, bool sendReportButton, bool &ignoreNextTime, const string &attachedFile) { - if (CanSendMailReport && SendMessage(sendReport, BM_GETCHECK, 0, 0) != BST_CHECKED) + std::string fname; + + time_t s = time( NULL ); + fname = std::string( "log_" ) + toString( s ) + ".txt"; + + std::ofstream f; + f.open( fname.c_str() ); + if( f.good() ) { - bool res = EmailFunction ("", "", "", Subject, Body, AttachedFile, false); - if (res) - { - // EnableWindow(sendReport, FALSE); - // MessageBox (dialog, "The email was successfully sent", "email", MB_OK); -#ifndef NL_NO_DEBUG_FILES - CFile::createEmptyFile(getLogDirectory() + "report_sent"); -#endif - } - else - { -#ifndef NL_NO_DEBUG_FILES - CFile::createEmptyFile(getLogDirectory() + "report_failed"); -#endif - // MessageBox (dialog, "Failed to send the email", "email", MB_OK | MB_ICONERROR); - } + f << body; + f.close(); + + NLMISC::launchProgram( "rcerror", fname ); } - else - { -#ifndef NL_NO_DEBUG_FILES - CFile::createEmptyFile(getLogDirectory() + "report_refused"); -#endif - } -} -static LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - //MSGFILTER *pmf; + NLMISC::CFile::deleteFile( fname ); + - if (message == WM_COMMAND && HIWORD(wParam) == BN_CLICKED) - { - if ((HWND) lParam == checkIgnore) - { - IgnoreNextTime = !IgnoreNextTime; - } - else if ((HWND) lParam == debug) - { - sendEmail(); - NeedExit = true; - Result = ReportDebug; - if (DebugDefaultBehavior) - { - NLMISC_BREAKPOINT; - } - } - else if ((HWND) lParam == ignore) - { - sendEmail(); - NeedExit = true; - Result = ReportIgnore; - } - else if ((HWND) lParam == quit) - { - sendEmail(); - NeedExit = true; - Result = ReportQuit; - - if (QuitDefaultBehavior) - { - // ace: we cannot call exit() because it's call the static object dtor and can crash the application - // if the dtor call order is not good. - //exit(EXIT_SUCCESS); #ifdef NL_OS_WINDOWS #ifndef NL_COMP_MINGW // disable the Windows popup telling that the application aborted and disable the dr watson report. @@ -166,193 +90,8 @@ static LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM #endif // quit without calling atexit or static object dtors. abort(); - } - } - /*else if ((HWND) lParam == sendReport) - { - if (EmailFunction != NULL) - { - bool res = EmailFunction ("", "", "", Subject, Body, AttachedFile, false); - if (res) - { - EnableWindow(sendReport, FALSE); - MessageBox (dialog, "The email was successfully sent", "email", MB_OK); - CFile::createEmptyFile(getLogDirectory() + "report_sent"); - } - else - { - MessageBox (dialog, "Failed to send the email", "email", MB_OK | MB_ICONERROR); - } - } - }*/ - } - else if (message == WM_CHAR) - { - if (wParam == 27) - { - // ESC -> ignore - sendEmail(); - NeedExit = true; - Result = ReportIgnore; - } - } - return DefWindowProc (hWnd, message, wParam, lParam); -} - -TReportResult report (const std::string &title, const std::string &header, const std::string &subject, const std::string &body, bool enableCheckIgnore, uint debugButton, bool ignoreButton, sint quitButton, bool sendReportButton, bool &ignoreNextTime, const string &attachedFile) -{ - // register the window - static bool AlreadyRegister = false; - if(!AlreadyRegister) - { - WNDCLASSW wc; - memset (&wc,0,sizeof(wc)); - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = (WNDPROC)WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = GetModuleHandle(NULL); - wc.hIcon = NULL; - wc.hCursor = LoadCursor(NULL,IDC_ARROW); - wc.hbrBackground = (HBRUSH)COLOR_WINDOW; - wc.lpszClassName = L"NLReportWindow"; - wc.lpszMenuName = NULL; - if (!RegisterClassW(&wc)) return ReportError; - AlreadyRegister = true; - } - - ucstring formatedTitle = title.empty() ? ucstring("NeL report") : ucstring(title); - - - // create the window - dialog = CreateWindowW (L"NLReportWindow", (LPCWSTR)formatedTitle.c_str(), WS_DLGFRAME | WS_CAPTION /*| WS_THICKFRAME*/, CW_USEDEFAULT, CW_USEDEFAULT, 456, 400, NULL, NULL, GetModuleHandle(NULL), NULL); - - // create the font - HFONT font = CreateFont (-12, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial"); - - Subject = subject; - AttachedFile = attachedFile; - - // create the edit control - HWND edit = CreateWindowW (L"EDIT", NULL, WS_BORDER | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | ES_READONLY | ES_LEFT | ES_MULTILINE, 7, 70, 429, 212, dialog, (HMENU) NULL, (HINSTANCE) GetWindowLongPtr(dialog, GWLP_HINSTANCE), NULL); - SendMessage (edit, WM_SETFONT, (WPARAM) font, TRUE); - - // set the edit text limit to lot of :) - SendMessage (edit, EM_LIMITTEXT, ~0U, 0); - - Body = addSlashR (body); - - // set the message in the edit text - SendMessage (edit, WM_SETTEXT, (WPARAM)0, (LPARAM)Body.c_str()); - - if (enableCheckIgnore) - { - // create the combo box control - checkIgnore = CreateWindowW (L"BUTTON", L"Don't display this report again", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX | BS_CHECKBOX, 7, 290, 429, 18, dialog, (HMENU) NULL, (HINSTANCE) GetWindowLongPtr(dialog, GWLP_HINSTANCE), NULL); - SendMessage (checkIgnore, WM_SETFONT, (WPARAM) font, TRUE); - - if(ignoreNextTime) - { - SendMessage (checkIgnore, BM_SETCHECK, BST_CHECKED, 0); - } - } - - // create the debug button control - debug = CreateWindowW (L"BUTTON", L"Debug", WS_CHILD | WS_VISIBLE, 7, 315, 75, 25, dialog, (HMENU) NULL, (HINSTANCE) GetWindowLongPtr(dialog, GWLP_HINSTANCE), NULL); - SendMessage (debug, WM_SETFONT, (WPARAM) font, TRUE); - - if (debugButton == 0) - EnableWindow(debug, FALSE); - - // create the ignore button control - ignore = CreateWindowW (L"BUTTON", L"Ignore", WS_CHILD | WS_VISIBLE, 75+7+7, 315, 75, 25, dialog, (HMENU) NULL, (HINSTANCE) GetWindowLongPtr(dialog, GWLP_HINSTANCE), NULL); - SendMessage (ignore, WM_SETFONT, (WPARAM) font, TRUE); - - if (ignoreButton == 0) - EnableWindow(ignore, FALSE); - - // create the quit button control - quit = CreateWindowW (L"BUTTON", L"Quit", WS_CHILD | WS_VISIBLE, 75+75+7+7+7, 315, 75, 25, dialog, (HMENU) NULL, (HINSTANCE) GetWindowLongPtr(dialog, GWLP_HINSTANCE), NULL); - SendMessage (quit, WM_SETFONT, (WPARAM) font, TRUE); - - if (quitButton == 0) - EnableWindow(quit, FALSE); - - // create the debug button control - sendReport = CreateWindowW (L"BUTTON", L"Don't send the report", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, 7, 315+32, 429, 18, dialog, (HMENU) NULL, (HINSTANCE) GetWindowLongPtr(dialog, GWLP_HINSTANCE), NULL); - SendMessage (sendReport, WM_SETFONT, (WPARAM) font, TRUE); - - string formatedHeader; - if (header.empty()) - { - formatedHeader = "This application stopped to display this report."; - } - else - { - formatedHeader = header; - } - - // ace don't do that because it s slow to try to send a mail - //CanSendMailReport = sendReportButton && EmailFunction != NULL && EmailFunction("", "", "", "", "", true); - CanSendMailReport = sendReportButton && EmailFunction != NULL; - - if (CanSendMailReport) - formatedHeader += " Send report will only email the contents of the box below. Please, send it to help us (it could take few minutes to send the email, be patient)."; - else - EnableWindow(sendReport, FALSE); - - ucstring uc = ucstring::makeFromUtf8(formatedHeader); - - // create the label control - HWND label = CreateWindowW (L"STATIC", (LPCWSTR)uc.c_str(), WS_CHILD | WS_VISIBLE /*| SS_WHITERECT*/, 7, 7, 429, 51, dialog, (HMENU) NULL, (HINSTANCE) GetWindowLongPtr(dialog, GWLP_HINSTANCE), NULL); - SendMessage (label, WM_SETFONT, (WPARAM) font, TRUE); - - - DebugDefaultBehavior = debugButton==1; - QuitDefaultBehavior = quitButton==1; - - IgnoreNextTime = ignoreNextTime; - - // show until the cursor really show :) - while (ShowCursor(TRUE) < 0) - ; - - SetWindowPos (dialog, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); - - SetFocus(dialog); - SetForegroundWindow(dialog); - - NeedExit = false; - - while(!NeedExit) - { - MSG msg; - while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessageW(&msg); - } - nlSleep (1); - } - - // set the user result - ignoreNextTime = IgnoreNextTime; - - ShowWindow(dialog, SW_HIDE); - - - - DELETE_OBJECT(sendReport) - DELETE_OBJECT(quit) - DELETE_OBJECT(ignore) - DELETE_OBJECT(debug) - DELETE_OBJECT(checkIgnore) - DELETE_OBJECT(edit) - DELETE_OBJECT(label) - DELETE_OBJECT(dialog) - - return Result; + return ReportQuit; } #endif diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index 6958fe790..c7fdc97f8 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -539,6 +539,8 @@ void checkDriverVersion() void checkDriverDepth () { + nlassert( false ); + // Check desktop is in 32 bit else no window mode allowed. if (ClientCfg.Windowed) { From e962a413234dbcc1485fea9a08914d05ee223274 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 19 Feb 2015 00:20:18 +0100 Subject: [PATCH 76/87] Added the Ryzom Core Error Reporter's skeleton. --- code/nel/CMakeLists.txt | 3 ++ code/nel/rcerror/CMakeLists.txt | 37 +++++++++++++ code/nel/rcerror/rcerror.cpp | 50 ++++++++++++++++++ code/nel/rcerror/rcerror_socket.cpp | 20 +++++++ code/nel/rcerror/rcerror_socket.h | 23 ++++++++ code/nel/rcerror/rcerror_widget.cpp | 70 ++++++++++++++++++++++++ code/nel/rcerror/rcerror_widget.h | 47 +++++++++++++++++ code/nel/rcerror/rcerror_widget.ui | 82 +++++++++++++++++++++++++++++ 8 files changed, 332 insertions(+) create mode 100644 code/nel/rcerror/CMakeLists.txt create mode 100644 code/nel/rcerror/rcerror.cpp create mode 100644 code/nel/rcerror/rcerror_socket.cpp create mode 100644 code/nel/rcerror/rcerror_socket.h create mode 100644 code/nel/rcerror/rcerror_widget.cpp create mode 100644 code/nel/rcerror/rcerror_widget.h create mode 100644 code/nel/rcerror/rcerror_widget.ui diff --git a/code/nel/CMakeLists.txt b/code/nel/CMakeLists.txt index 53bf071e3..00290d097 100644 --- a/code/nel/CMakeLists.txt +++ b/code/nel/CMakeLists.txt @@ -84,3 +84,6 @@ IF(WITH_NEL_TOOLS OR WITH_NEL_MAXPLUGIN) ADD_SUBDIRECTORY(tools) ENDIF(WITH_NEL_TOOLS OR WITH_NEL_MAXPLUGIN) +IF(WITH_QT) + ADD_SUBDIRECTORY(rcerror) +ENDIF(WITH_QT) diff --git a/code/nel/rcerror/CMakeLists.txt b/code/nel/rcerror/CMakeLists.txt new file mode 100644 index 000000000..412da9b6c --- /dev/null +++ b/code/nel/rcerror/CMakeLists.txt @@ -0,0 +1,37 @@ +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SRC_DIR} ${QT_INCLUDES}) +FILE(GLOB RCERROR_SRC *.cpp) +FILE(GLOB RCERROR_HDR *h) + +SET(RCERROR_MOC_HDR +rcerror_socket.h +rcerror_widget.h +) + +SET(RCERROR_UI +rcerror_widget.ui +) + +SET(QT_USE_QTGUI TRUE) +SET(QT_USE_QTNETWORK TRUE) +SET(QT_USE_QTMAIN TRUE) +SET(QT_USE_QTOPENGL FALSE) +SET(QT_USE_QTXML FALSE) + +INCLUDE(${QT_USE_FILE}) +ADD_DEFINITIONS(${QT_DEFINITIONS}) + +QT4_WRAP_CPP(RCERROR_MOC_SRC ${RCERROR_MOC_HDR}) +QT4_WRAP_UI(RCERROR_UI_HDR ${RCERROR_UI}) + +SOURCE_GROUP(QtResources FILES ${RCERROR_UI}) +SOURCE_GROUP(QtGeneratedUiHdr FILES ${RCERROR_UI_HDR}) +SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${RCERROR_MOC_SRC}) +SOURCE_GROUP("source files" FILES ${RCERROR_SRC}) +SOURCE_GROUP("header files" FILES ${RCERROR_HDR}) + +ADD_EXECUTABLE(rcerror WIN32 MACOSX_BUNDLE ${RCERROR_SRC} ${RCERROR_MOC_HDR} ${RCERROR_MOC_SRC} ${RCERROR_UI_HDR}) +TARGET_LINK_LIBRARIES(rcerror ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY}) + +NL_DEFAULT_PROPS(rcerror "Ryzom Core Error Reporter") +NL_ADD_RUNTIME_FLAGS(rcerror) + diff --git a/code/nel/rcerror/rcerror.cpp b/code/nel/rcerror/rcerror.cpp new file mode 100644 index 000000000..6fa876e81 --- /dev/null +++ b/code/nel/rcerror/rcerror.cpp @@ -0,0 +1,50 @@ +// Ryzom Core MMORPG framework - Error Reporter +// +// Copyright (C) 2015 Laszlo Kis-Adam +// Copyright (C) 2010 Ryzom Core +// +// 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 "rcerror_widget.h" +#include +#include + +int main( int argc, char **argv ) +{ + QApplication app( argc, argv ); + +#if 0 + + if( argc < 2 ) + { + QMessageBox::information( NULL, + QObject::tr( "Error" ), + QObject::tr( "Need to specify a path to the error report." ) ); + return 1; + } +#endif + + RCErrorWidget w; + +#if 0 + w.setFileName( argv[ 1 ] ); +#else + w.setFileName( "log.log" ); +#endif + + w.show(); + + return app.exec(); +} \ No newline at end of file diff --git a/code/nel/rcerror/rcerror_socket.cpp b/code/nel/rcerror/rcerror_socket.cpp new file mode 100644 index 000000000..f39946423 --- /dev/null +++ b/code/nel/rcerror/rcerror_socket.cpp @@ -0,0 +1,20 @@ +// Ryzom Core MMORPG framework - Error Reporter +// +// Copyright (C) 2015 Laszlo Kis-Adam +// Copyright (C) 2010 Ryzom Core +// +// 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 "rcerror_socket.h" + diff --git a/code/nel/rcerror/rcerror_socket.h b/code/nel/rcerror/rcerror_socket.h new file mode 100644 index 000000000..8cd9f54ad --- /dev/null +++ b/code/nel/rcerror/rcerror_socket.h @@ -0,0 +1,23 @@ +// Ryzom Core MMORPG framework - Error Reporter +// +// Copyright (C) 2015 Laszlo Kis-Adam +// Copyright (C) 2010 Ryzom Core +// +// 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 RCERROR_SOCKET +#define RCERROR_SOCKET +#endif + diff --git a/code/nel/rcerror/rcerror_widget.cpp b/code/nel/rcerror/rcerror_widget.cpp new file mode 100644 index 000000000..a50b273d3 --- /dev/null +++ b/code/nel/rcerror/rcerror_widget.cpp @@ -0,0 +1,70 @@ +// Ryzom Core MMORPG framework - Error Reporter +// +// Copyright (C) 2015 Laszlo Kis-Adam +// Copyright (C) 2010 Ryzom Core +// +// 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 "rcerror_widget.h" +#include +#include +#include + +RCErrorWidget::RCErrorWidget( QWidget *parent ) : +QWidget( parent ) +{ + m_ui.setupUi( this ); + QTimer::singleShot( 1, this, SLOT( onLoad() ) ); + + connect( m_ui.sendButton, SIGNAL( clicked( bool ) ), this, SLOT( onSendClicked() ) ); + connect( m_ui.canceButton, SIGNAL( clicked( bool ) ), this, SLOT( onCancelClicked() ) ); + connect( m_ui.emailCB, SIGNAL( stateChanged( int ) ), this, SLOT( onCBClicked() ) ); +} + +RCErrorWidget::~RCErrorWidget() +{ +} + +void RCErrorWidget::onLoad() +{ + QFile f( m_fileName ); + bool b = f.open( QFile::ReadOnly | QFile::Text ); + if( !b ) + { + return; + } + + QTextStream ss( &f ); + m_ui.reportEdit->setPlainText( ss.readAll() ); + f.close(); +} + +void RCErrorWidget::onSendClicked() +{ + close(); +} + +void RCErrorWidget::onCancelClicked() +{ + close(); +} + +void RCErrorWidget::onCBClicked() +{ + m_ui.emailEdit->setEnabled( m_ui.emailCB->isChecked() ); +} + + + diff --git a/code/nel/rcerror/rcerror_widget.h b/code/nel/rcerror/rcerror_widget.h new file mode 100644 index 000000000..ae5629e55 --- /dev/null +++ b/code/nel/rcerror/rcerror_widget.h @@ -0,0 +1,47 @@ +// Ryzom Core MMORPG framework - Error Reporter +// +// Copyright (C) 2015 Laszlo Kis-Adam +// Copyright (C) 2010 Ryzom Core +// +// 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 RCERROR_WIDGET +#define RCERROR_SOCKET + + +#include "ui_rcerror_widget.h" + +class RCErrorWidget : public QWidget +{ + Q_OBJECT +public: + RCErrorWidget( QWidget *parent = NULL ); + ~RCErrorWidget(); + + void setFileName( const char *fn ){ m_fileName = fn; } + +private Q_SLOTS: + void onLoad(); + void onSendClicked(); + void onCancelClicked(); + void onCBClicked(); + +private: + Ui::RCErrorWidget m_ui; + QString m_fileName; +}; + +#endif + diff --git a/code/nel/rcerror/rcerror_widget.ui b/code/nel/rcerror/rcerror_widget.ui new file mode 100644 index 000000000..72e5f92f5 --- /dev/null +++ b/code/nel/rcerror/rcerror_widget.ui @@ -0,0 +1,82 @@ + + + RCErrorWidget + + + Qt::ApplicationModal + + + + 0 + 0 + 400 + 407 + + + + Ryzom Core error report + + + + + + What were you doing when the crash occured? + + + + + + + + + + Contents of the report ( automatically generated ) + + + + + + + true + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Email me if you have further questions, or updates on this issue + + + + + + + false + + + Enter your email address here + + + + + + + Send + + + + + + + Cancel + + + + + + + + From aca8314fdb4aeff0065f57b2f038f5398f6cf951 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Feb 2015 01:59:04 +0100 Subject: [PATCH 77/87] Implemented the bug report Qt app and an example web app that takes the report. --- code/nel/rcerror/rcerror_data.h | 33 ++++++++ code/nel/rcerror/rcerror_socket.cpp | 46 +++++++++++ code/nel/rcerror/rcerror_socket.h | 26 ++++++ code/nel/rcerror/rcerror_widget.cpp | 25 +++++- code/nel/rcerror/rcerror_widget.h | 7 +- code/web/rcerror_web/config.inc.php | 30 +++++++ code/web/rcerror_web/log.inc.php | 45 +++++++++++ code/web/rcerror_web/rcerror.php | 112 ++++++++++++++++++++++++++ code/web/rcerror_web/rcerror_test.htm | 19 +++++ 9 files changed, 341 insertions(+), 2 deletions(-) create mode 100644 code/nel/rcerror/rcerror_data.h create mode 100644 code/web/rcerror_web/config.inc.php create mode 100644 code/web/rcerror_web/log.inc.php create mode 100644 code/web/rcerror_web/rcerror.php create mode 100644 code/web/rcerror_web/rcerror_test.htm diff --git a/code/nel/rcerror/rcerror_data.h b/code/nel/rcerror/rcerror_data.h new file mode 100644 index 000000000..146102038 --- /dev/null +++ b/code/nel/rcerror/rcerror_data.h @@ -0,0 +1,33 @@ +// Ryzom Core MMORPG framework - Error Reporter +// +// Copyright (C) 2015 Laszlo Kis-Adam +// Copyright (C) 2010 Ryzom Core +// +// 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 RCERROR_DATA +#define RCERROR_DATA + +#include + + +struct RCErrorData +{ + QString description; + QString report; + QString email; +}; + +#endif diff --git a/code/nel/rcerror/rcerror_socket.cpp b/code/nel/rcerror/rcerror_socket.cpp index f39946423..d84f69ec8 100644 --- a/code/nel/rcerror/rcerror_socket.cpp +++ b/code/nel/rcerror/rcerror_socket.cpp @@ -17,4 +17,50 @@ // along with this program. If not, see . #include "rcerror_socket.h" +#include +#include +#include + +namespace +{ + static const char *BUG_URL = "http://192.168.2.67/dfighter/r.php"; +} + +class RCErrorSocketPvt +{ +public: + QNetworkAccessManager mgr; +}; + +RCErrorSocket::RCErrorSocket( QObject *parent ) : +QObject( parent ) +{ + m_pvt = new RCErrorSocketPvt(); + + connect( &m_pvt->mgr, SIGNAL( finished( QNetworkReply* ) ), this, SLOT( onFinished() ) ); +} + +RCErrorSocket::~RCErrorSocket() +{ + delete m_pvt; +} + +void RCErrorSocket::sendReport( const RCErrorData &data ) +{ + QUrl params; + params.addQueryItem( "report", data.report ); + params.addQueryItem( "descr", data.description ); + params.addQueryItem( "email", data.email ); + + QUrl url( BUG_URL ); + QNetworkRequest request( url ); + request.setRawHeader( "Connection", "close" ); + + m_pvt->mgr.post( request, params.encodedQuery() ); +} + +void RCErrorSocket::onFinished() +{ + Q_EMIT reportSent(); +} diff --git a/code/nel/rcerror/rcerror_socket.h b/code/nel/rcerror/rcerror_socket.h index 8cd9f54ad..ee0f510b1 100644 --- a/code/nel/rcerror/rcerror_socket.h +++ b/code/nel/rcerror/rcerror_socket.h @@ -19,5 +19,31 @@ #ifndef RCERROR_SOCKET #define RCERROR_SOCKET + +#include +#include "rcerror_data.h" + +class RCErrorSocketPvt; + +class RCErrorSocket : public QObject +{ + Q_OBJECT + +public: + RCErrorSocket( QObject *parent ); + ~RCErrorSocket(); + + void sendReport( const RCErrorData &data ); + +Q_SIGNALS: + void reportSent(); + +private Q_SLOTS: + void onFinished(); + +private: + RCErrorSocketPvt *m_pvt; +}; + #endif diff --git a/code/nel/rcerror/rcerror_widget.cpp b/code/nel/rcerror/rcerror_widget.cpp index a50b273d3..faded0afa 100644 --- a/code/nel/rcerror/rcerror_widget.cpp +++ b/code/nel/rcerror/rcerror_widget.cpp @@ -18,23 +18,32 @@ #include "rcerror_widget.h" +#include "rcerror_socket.h" +#include "rcerror_data.h" #include #include #include +#include RCErrorWidget::RCErrorWidget( QWidget *parent ) : QWidget( parent ) { m_ui.setupUi( this ); + + m_socket = new RCErrorSocket( this ); + QTimer::singleShot( 1, this, SLOT( onLoad() ) ); connect( m_ui.sendButton, SIGNAL( clicked( bool ) ), this, SLOT( onSendClicked() ) ); connect( m_ui.canceButton, SIGNAL( clicked( bool ) ), this, SLOT( onCancelClicked() ) ); connect( m_ui.emailCB, SIGNAL( stateChanged( int ) ), this, SLOT( onCBClicked() ) ); + + connect( m_socket, SIGNAL( reportSent() ), this, SLOT( onReportSent() ) ); } RCErrorWidget::~RCErrorWidget() { + m_socket = NULL; } void RCErrorWidget::onLoad() @@ -53,7 +62,14 @@ void RCErrorWidget::onLoad() void RCErrorWidget::onSendClicked() { - close(); + m_ui.sendButton->setEnabled( false ); + + RCErrorData data; + data.description = m_ui.descriptionEdit->toPlainText(); + data.report = m_ui.reportEdit->toPlainText(); + data.email = m_ui.emailEdit->text(); + + m_socket->sendReport( data ); } void RCErrorWidget::onCancelClicked() @@ -66,5 +82,12 @@ void RCErrorWidget::onCBClicked() m_ui.emailEdit->setEnabled( m_ui.emailCB->isChecked() ); } +void RCErrorWidget::onReportSent() +{ + QMessageBox::information( this, + tr( "Report sent" ), + tr( "The report has been sent." ) ); + close(); +} diff --git a/code/nel/rcerror/rcerror_widget.h b/code/nel/rcerror/rcerror_widget.h index ae5629e55..869838e41 100644 --- a/code/nel/rcerror/rcerror_widget.h +++ b/code/nel/rcerror/rcerror_widget.h @@ -18,11 +18,13 @@ #ifndef RCERROR_WIDGET -#define RCERROR_SOCKET +#define RCERROR_WIDGET #include "ui_rcerror_widget.h" +class RCErrorSocket; + class RCErrorWidget : public QWidget { Q_OBJECT @@ -37,10 +39,13 @@ private Q_SLOTS: void onSendClicked(); void onCancelClicked(); void onCBClicked(); + + void onReportSent(); private: Ui::RCErrorWidget m_ui; QString m_fileName; + RCErrorSocket *m_socket; }; #endif diff --git a/code/web/rcerror_web/config.inc.php b/code/web/rcerror_web/config.inc.php new file mode 100644 index 000000000..fe4b3e928 --- /dev/null +++ b/code/web/rcerror_web/config.inc.php @@ -0,0 +1,30 @@ + +// +// 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 . + +class BugReportConfig +{ + static public $dbhost = "localhost"; + static public $dbport = "3306"; + static public $dbdb = "bugs"; + static public $dbuser = "bugs"; + static public $dbpw = "bugs"; +} + +?> diff --git a/code/web/rcerror_web/log.inc.php b/code/web/rcerror_web/log.inc.php new file mode 100644 index 000000000..71deee24f --- /dev/null +++ b/code/web/rcerror_web/log.inc.php @@ -0,0 +1,45 @@ + +// +// 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 . + +/// Simple file logger class +class Logger +{ + private $lf = NULL; + + function __construct() + { + $this->lf = fopen( 'log.txt', 'a' ); + if( $this->lf === FALSE ) + exit( 1 ); + } + + function __destruct() + { + fclose( $this->lf ); + } + + public function log( $msg ) + { + $date = date( "[M d, Y H:i:s] " ); + fwrite( $this->lf, $date . $msg . "\n" ); + } +} + +?> diff --git a/code/web/rcerror_web/rcerror.php b/code/web/rcerror_web/rcerror.php new file mode 100644 index 000000000..d20214d11 --- /dev/null +++ b/code/web/rcerror_web/rcerror.php @@ -0,0 +1,112 @@ + +// +// 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 . + +require_once( 'config.inc.php' ); +require_once( 'log.inc.php' ); + +/// Example web application that takes bug reports from the bug reporter Qt app +class BugReportGatherApp +{ + private $db = NULL; + private $logger = NULL; + + function __construct() + { + $this->logger = new Logger(); + } + + private function logPOSTVars() + { + $report = ""; + $descr = ""; + $email = ""; + + if( isset( $_POST[ 'report' ] ) ) + $report = $_POST[ 'report' ]; + + if( isset( $_POST[ 'descr' ] ) ) + $descr = $_POST[ 'descr' ]; + + if( isset( $_POST[ 'email' ] ) ) + $email = $_POST[ 'email' ]; + + $this->logger->log( 'report: ' . "\n" . $report ); + $this->logger->log( 'description: ' . "\n" . $descr ); + $this->logger->log( 'email: ' . "\n" . $email ); + } + + private function buildQuery() + { + $report = ""; + $descr = ""; + $email = ""; + + if( isset( $_POST[ 'report' ] ) ) + $report = $_POST[ 'report' ]; + + if( isset( $_POST[ 'descr' ] ) ) + $descr = $_POST[ 'descr' ]; + + if( isset( $_POST[ 'email' ] ) ) + $email = $_POST[ 'email' ]; + + $report = $this->db->real_escape_string( $report ); + $descr = $this->db->real_escape_string( $descr ); + $email = $this->db->real_escape_string( $email ); + + + $q = "INSERT INTO `bugs` (`report`,`description`,`email`) VALUES ("; + $q .= "'$report',"; + $q .= "'$descr',"; + $q .= "'$email')"; + + return $q; + } + + public function exec() + { + //$this->logPOSTVars(); + + $this->db = new mysqli( BugReportConfig::$dbhost, BugReportConfig::$dbuser, BugReportConfig::$dbpw, BugReportConfig::$dbdb, BugReportConfig::$dbport ); + if( mysqli_connect_error() ) + { + $this->logger->log( "Connection error :(" ); + $this->logger->log( mysqli_connect_error() ); + return; + } + + $q = $this->buildQuery(); + $result = $this->db->query( $q ); + if( $result !== TRUE ) + { + $this->logger->log( "Query failed :(" ); + $this->logger->log( 'Query: ' . $q ); + $this->logPOSTVars(); + } + + $this->db->close(); + } +} + + +$app = new BugReportGatherApp(); +$app->exec(); + +?> diff --git a/code/web/rcerror_web/rcerror_test.htm b/code/web/rcerror_web/rcerror_test.htm new file mode 100644 index 000000000..eb314d3f7 --- /dev/null +++ b/code/web/rcerror_web/rcerror_test.htm @@ -0,0 +1,19 @@ + +Ryzom Core Error Report Web application test harness + +
    + + + + + + + + + +
    Description
    Report
    Email
    + +
    +
    + + From a92f816f557b249bb21f0230afcb228ff1fcc793 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Feb 2015 02:03:33 +0100 Subject: [PATCH 78/87] Probably a good idea to look for rcerror as rcerror.exe on Windows. --- code/nel/src/misc/report.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/nel/src/misc/report.cpp b/code/nel/src/misc/report.cpp index 39f27de5f..1a94e17a6 100644 --- a/code/nel/src/misc/report.cpp +++ b/code/nel/src/misc/report.cpp @@ -76,7 +76,11 @@ TReportResult report (const std::string &title, const std::string &header, const f << body; f.close(); +#ifdef NL_OS_WINDOWS + NLMISC::launchProgram( "rcerror.exe", fname ); +#else NLMISC::launchProgram( "rcerror", fname ); +#endif } NLMISC::CFile::deleteFile( fname ); From 04480a32909fd8ca260093e8ee09da940e6f9d0b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Feb 2015 02:35:11 +0100 Subject: [PATCH 79/87] Unfortunately on Windows argc and argv parameters are unreliable inside a Qt application, so I had to hardcode the report file name. :( --- code/nel/rcerror/rcerror.cpp | 19 +------------------ code/nel/rcerror/rcerror_widget.cpp | 5 ++++- code/nel/src/misc/report.cpp | 8 +------- 3 files changed, 6 insertions(+), 26 deletions(-) diff --git a/code/nel/rcerror/rcerror.cpp b/code/nel/rcerror/rcerror.cpp index 6fa876e81..0d5088167 100644 --- a/code/nel/rcerror/rcerror.cpp +++ b/code/nel/rcerror/rcerror.cpp @@ -25,25 +25,8 @@ int main( int argc, char **argv ) { QApplication app( argc, argv ); -#if 0 - - if( argc < 2 ) - { - QMessageBox::information( NULL, - QObject::tr( "Error" ), - QObject::tr( "Need to specify a path to the error report." ) ); - return 1; - } -#endif - RCErrorWidget w; - -#if 0 - w.setFileName( argv[ 1 ] ); -#else - w.setFileName( "log.log" ); -#endif - + w.setFileName( "rcerrorlog.txt" ); w.show(); return app.exec(); diff --git a/code/nel/rcerror/rcerror_widget.cpp b/code/nel/rcerror/rcerror_widget.cpp index faded0afa..6c31533ad 100644 --- a/code/nel/rcerror/rcerror_widget.cpp +++ b/code/nel/rcerror/rcerror_widget.cpp @@ -52,7 +52,10 @@ void RCErrorWidget::onLoad() bool b = f.open( QFile::ReadOnly | QFile::Text ); if( !b ) { - return; + QMessageBox::information( this, + tr( "No log file found" ), + tr( "There was no log file found, therefore nothing to report. Exiting..." ) ); + close(); } QTextStream ss( &f ); diff --git a/code/nel/src/misc/report.cpp b/code/nel/src/misc/report.cpp index 1a94e17a6..88c707aaa 100644 --- a/code/nel/src/misc/report.cpp +++ b/code/nel/src/misc/report.cpp @@ -64,10 +64,7 @@ void report () TReportResult report (const std::string &title, const std::string &header, const std::string &subject, const std::string &body, bool enableCheckIgnore, uint debugButton, bool ignoreButton, sint quitButton, bool sendReportButton, bool &ignoreNextTime, const string &attachedFile) { - std::string fname; - - time_t s = time( NULL ); - fname = std::string( "log_" ) + toString( s ) + ".txt"; + std::string fname = "rcerrorlog.txt"; std::ofstream f; f.open( fname.c_str() ); @@ -83,9 +80,6 @@ TReportResult report (const std::string &title, const std::string &header, const #endif } - NLMISC::CFile::deleteFile( fname ); - - #ifdef NL_OS_WINDOWS #ifndef NL_COMP_MINGW // disable the Windows popup telling that the application aborted and disable the dr watson report. From 52bb68f547a9ae862b346dc4aa841c6133a4decc Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Feb 2015 02:44:22 +0100 Subject: [PATCH 80/87] Override the cursor while sending the report. --- code/nel/rcerror/rcerror_socket.cpp | 2 +- code/nel/rcerror/rcerror_widget.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/code/nel/rcerror/rcerror_socket.cpp b/code/nel/rcerror/rcerror_socket.cpp index d84f69ec8..6b1fd932d 100644 --- a/code/nel/rcerror/rcerror_socket.cpp +++ b/code/nel/rcerror/rcerror_socket.cpp @@ -23,7 +23,7 @@ namespace { - static const char *BUG_URL = "http://192.168.2.67/dfighter/r.php"; + static const char *BUG_URL = "http://192.168.2.66/dfighter/r.php"; } class RCErrorSocketPvt diff --git a/code/nel/rcerror/rcerror_widget.cpp b/code/nel/rcerror/rcerror_widget.cpp index 6c31533ad..e02090e0d 100644 --- a/code/nel/rcerror/rcerror_widget.cpp +++ b/code/nel/rcerror/rcerror_widget.cpp @@ -66,6 +66,7 @@ void RCErrorWidget::onLoad() void RCErrorWidget::onSendClicked() { m_ui.sendButton->setEnabled( false ); + QApplication::setOverrideCursor( Qt::WaitCursor ); RCErrorData data; data.description = m_ui.descriptionEdit->toPlainText(); @@ -87,6 +88,8 @@ void RCErrorWidget::onCBClicked() void RCErrorWidget::onReportSent() { + QApplication::setOverrideCursor( Qt::ArrowCursor ); + QMessageBox::information( this, tr( "Report sent" ), tr( "The report has been sent." ) ); From 31907ca35f805ae5783b50e0869154772b68862e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Feb 2015 02:54:05 +0100 Subject: [PATCH 81/87] Tell the user if the report couldn't be sent. --- code/nel/rcerror/rcerror_socket.cpp | 10 +++++++--- code/nel/rcerror/rcerror_socket.h | 4 +++- code/nel/rcerror/rcerror_widget.cpp | 11 +++++++++++ code/nel/rcerror/rcerror_widget.h | 1 + 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/code/nel/rcerror/rcerror_socket.cpp b/code/nel/rcerror/rcerror_socket.cpp index 6b1fd932d..8a011c046 100644 --- a/code/nel/rcerror/rcerror_socket.cpp +++ b/code/nel/rcerror/rcerror_socket.cpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace { @@ -37,7 +38,7 @@ QObject( parent ) { m_pvt = new RCErrorSocketPvt(); - connect( &m_pvt->mgr, SIGNAL( finished( QNetworkReply* ) ), this, SLOT( onFinished() ) ); + connect( &m_pvt->mgr, SIGNAL( finished( QNetworkReply* ) ), this, SLOT( onFinished( QNetworkReply* ) ) ); } RCErrorSocket::~RCErrorSocket() @@ -59,8 +60,11 @@ void RCErrorSocket::sendReport( const RCErrorData &data ) m_pvt->mgr.post( request, params.encodedQuery() ); } -void RCErrorSocket::onFinished() +void RCErrorSocket::onFinished( QNetworkReply *reply ) { - Q_EMIT reportSent(); + if( reply->error() != QNetworkReply::NoError ) + Q_EMIT reportFailed(); + else + Q_EMIT reportSent(); } diff --git a/code/nel/rcerror/rcerror_socket.h b/code/nel/rcerror/rcerror_socket.h index ee0f510b1..a37fa32d0 100644 --- a/code/nel/rcerror/rcerror_socket.h +++ b/code/nel/rcerror/rcerror_socket.h @@ -24,6 +24,7 @@ #include "rcerror_data.h" class RCErrorSocketPvt; +class QNetworkReply; class RCErrorSocket : public QObject { @@ -37,9 +38,10 @@ public: Q_SIGNALS: void reportSent(); + void reportFailed(); private Q_SLOTS: - void onFinished(); + void onFinished( QNetworkReply *reply ); private: RCErrorSocketPvt *m_pvt; diff --git a/code/nel/rcerror/rcerror_widget.cpp b/code/nel/rcerror/rcerror_widget.cpp index e02090e0d..a28afbca6 100644 --- a/code/nel/rcerror/rcerror_widget.cpp +++ b/code/nel/rcerror/rcerror_widget.cpp @@ -39,6 +39,7 @@ QWidget( parent ) connect( m_ui.emailCB, SIGNAL( stateChanged( int ) ), this, SLOT( onCBClicked() ) ); connect( m_socket, SIGNAL( reportSent() ), this, SLOT( onReportSent() ) ); + connect( m_socket, SIGNAL( reportFailed() ), this, SLOT( onReportFailed() ) ); } RCErrorWidget::~RCErrorWidget() @@ -97,3 +98,13 @@ void RCErrorWidget::onReportSent() close(); } +void RCErrorWidget::onReportFailed() +{ + QApplication::setOverrideCursor( Qt::ArrowCursor ); + + QMessageBox::information( this, + tr( "Report failed" ), + tr( "Failed to send the report..." ) ); + + close(); +} \ No newline at end of file diff --git a/code/nel/rcerror/rcerror_widget.h b/code/nel/rcerror/rcerror_widget.h index 869838e41..1dd51c2af 100644 --- a/code/nel/rcerror/rcerror_widget.h +++ b/code/nel/rcerror/rcerror_widget.h @@ -41,6 +41,7 @@ private Q_SLOTS: void onCBClicked(); void onReportSent(); + void onReportFailed(); private: Ui::RCErrorWidget m_ui; From 7e2e2ae56b75edc79e7de563f8d08d7c4a9351f6 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Feb 2015 02:56:22 +0100 Subject: [PATCH 82/87] Oups --- code/ryzom/client/src/init.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index c7fdc97f8..6958fe790 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -539,8 +539,6 @@ void checkDriverVersion() void checkDriverDepth () { - nlassert( false ); - // Check desktop is in 32 bit else no window mode allowed. if (ClientCfg.Windowed) { From 0eb8913a20f288e6aae6f1d103549d233fe74361 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Feb 2015 03:22:02 +0100 Subject: [PATCH 83/87] Typo... --- code/nel/rcerror/rcerror_data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/rcerror/rcerror_data.h b/code/nel/rcerror/rcerror_data.h index 146102038..9f12b12fd 100644 --- a/code/nel/rcerror/rcerror_data.h +++ b/code/nel/rcerror/rcerror_data.h @@ -20,7 +20,7 @@ #ifndef RCERROR_DATA #define RCERROR_DATA -#include +#include struct RCErrorData From d33da5fe44abdc8fcfd29492c44b6d41667dd618 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 21 Feb 2015 20:01:44 +0100 Subject: [PATCH 84/87] Install rcerror --- code/nel/rcerror/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/nel/rcerror/CMakeLists.txt b/code/nel/rcerror/CMakeLists.txt index 412da9b6c..51522cf0c 100644 --- a/code/nel/rcerror/CMakeLists.txt +++ b/code/nel/rcerror/CMakeLists.txt @@ -35,3 +35,5 @@ TARGET_LINK_LIBRARIES(rcerror ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY}) NL_DEFAULT_PROPS(rcerror "Ryzom Core Error Reporter") NL_ADD_RUNTIME_FLAGS(rcerror) +INSTALL(TARGETS rcerror RUNTIME DESTINATION ${NL_BIN_PREFIX}) + From 566d21f64e67e230edfee57647bcc5b0f3e01b9b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 21 Feb 2015 21:28:56 +0100 Subject: [PATCH 85/87] Use CMsgBoxDisplayer on platforms other than Windows as well. --- code/nel/src/misc/debug.cpp | 8 +------- code/nel/src/misc/displayer.cpp | 2 -- code/nel/src/misc/report.cpp | 12 ------------ 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/code/nel/src/misc/debug.cpp b/code/nel/src/misc/debug.cpp index 2d09f5ef8..aaa551f1f 100644 --- a/code/nel/src/misc/debug.cpp +++ b/code/nel/src/misc/debug.cpp @@ -1193,13 +1193,7 @@ void createDebug (const char *logPath, bool logInFile, bool eraseLastLog) INelContext::getInstance().setAssertLog(new CLog (CLog::LOG_ASSERT)); sd = new CStdDisplayer ("DEFAULT_SD"); - -#ifdef NL_OS_WINDOWS - if (TrapCrashInDebugger || !IsDebuggerPresent ()) - { - DefaultMsgBoxDisplayer = new CMsgBoxDisplayer ("DEFAULT_MBD"); - } -#endif + DefaultMsgBoxDisplayer = new CMsgBoxDisplayer ("DEFAULT_MBD"); #if LOG_IN_FILE if (logInFile) diff --git a/code/nel/src/misc/displayer.cpp b/code/nel/src/misc/displayer.cpp index d48c44d02..35ae27964 100644 --- a/code/nel/src/misc/displayer.cpp +++ b/code/nel/src/misc/displayer.cpp @@ -529,7 +529,6 @@ void CFileDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *mes // in release "" void CMsgBoxDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *message) { -#ifdef NL_OS_WINDOWS bool needSpace = false; // stringstream ss; @@ -720,7 +719,6 @@ void CMsgBoxDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *m } */ } -#endif } diff --git a/code/nel/src/misc/report.cpp b/code/nel/src/misc/report.cpp index 88c707aaa..b165e29f5 100644 --- a/code/nel/src/misc/report.cpp +++ b/code/nel/src/misc/report.cpp @@ -52,16 +52,6 @@ void setReportEmailFunction (void *emailFunction) EmailFunction = (TEmailFunction)emailFunction; } -#ifndef NL_OS_WINDOWS - -// GNU/Linux, do nothing - -void report () -{ -} - -#else - TReportResult report (const std::string &title, const std::string &header, const std::string &subject, const std::string &body, bool enableCheckIgnore, uint debugButton, bool ignoreButton, sint quitButton, bool sendReportButton, bool &ignoreNextTime, const string &attachedFile) { std::string fname = "rcerrorlog.txt"; @@ -92,7 +82,5 @@ TReportResult report (const std::string &title, const std::string &header, const return ReportQuit; } -#endif - } // NLMISC From 8a571b8689561cd772987fafc5a52f2d4f81af71 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 21 Feb 2015 22:32:11 +0100 Subject: [PATCH 86/87] A little cleanup of CMsgBoxDisplayer. --- code/nel/include/nel/misc/report.h | 17 +-- code/nel/src/misc/debug.cpp | 2 +- code/nel/src/misc/displayer.cpp | 174 +---------------------------- code/nel/src/misc/report.cpp | 19 +--- 4 files changed, 7 insertions(+), 205 deletions(-) diff --git a/code/nel/include/nel/misc/report.h b/code/nel/include/nel/misc/report.h index 11745b6e3..6bf3df959 100644 --- a/code/nel/include/nel/misc/report.h +++ b/code/nel/include/nel/misc/report.h @@ -21,21 +21,8 @@ namespace NLMISC { -/** Display a custom message box. - * - * \param title set the title of the report. If empty, it'll display "NeL report". - * \param header message displayed before the edit text box. If empty, it displays the default message. - * \param body message displayed in the edit text box. This string will be sent by email. - * \param debugButton 0 for disabling it, 1 for enable with default behaviors (generate a breakpoint), 2 for enable with no behavior - * - * - * - * \return the button clicked or error - */ - -enum TReportResult { ReportDebug, ReportIgnore, ReportQuit, ReportError }; - -TReportResult report (const std::string &title, const std::string &header, const std::string &subject, const std::string &body, bool enableCheckIgnore, uint debugButton, bool ignoreButton, sint quitButton, bool sendReportButton, bool &ignoreNextTime, const std::string &attachedFile = ""); +/// Prepares the error report, writes it to disk and launches the error reporter +void report ( const std::string &body ); /** call this in the main of your appli to enable email: setReportEmailFunction (sendEmail); */ diff --git a/code/nel/src/misc/debug.cpp b/code/nel/src/misc/debug.cpp index aaa551f1f..67c8cb0f3 100644 --- a/code/nel/src/misc/debug.cpp +++ b/code/nel/src/misc/debug.cpp @@ -553,7 +553,7 @@ public: // yoyo: allow only to send the crash report once. Because users usually click ignore, // which create noise into list of bugs (once a player crash, it will surely continues to do it). bool i = false; - report (progname+shortExc, "", subject, _Reason, true, 1, true, 1, !isCrashAlreadyReported(), i, NL_CRASH_DUMP_FILE); + report ( _Reason ); // no more sent mail for crash setCrashAlreadyReported(true); diff --git a/code/nel/src/misc/displayer.cpp b/code/nel/src/misc/displayer.cpp index 35ae27964..8296d1c0b 100644 --- a/code/nel/src/misc/displayer.cpp +++ b/code/nel/src/misc/displayer.cpp @@ -529,114 +529,7 @@ void CFileDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *mes // in release "" void CMsgBoxDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *message) { - - bool needSpace = false; -// stringstream ss; - string str; - - // create the string for the clipboard - - if (args.Date != 0) - { - str += dateToHumanString(args.Date); - needSpace = true; - } - - if (args.LogType != CLog::LOG_NO) - { - //if (needSpace) { ss << " "; needSpace = false; } - if (needSpace) { str += " "; needSpace = false; } - str += logTypeToString(args.LogType); - needSpace = true; - } - - if (!args.ProcessName.empty()) - { - //if (needSpace) { ss << " "; needSpace = false; } - if (needSpace) { str += " "; needSpace = false; } - str += args.ProcessName; - needSpace = true; - } - - if (args.FileName != NULL) - { - //if (needSpace) { ss << " "; needSpace = false; } - if (needSpace) { str += " "; needSpace = false; } - str += CFile::getFilename(args.FileName); - needSpace = true; - } - - if (args.Line != -1) - { - //if (needSpace) { ss << " "; needSpace = false; } - if (needSpace) { str += " "; needSpace = false; } - str += NLMISC::toString(args.Line); - needSpace = true; - } - - if (args.FuncName != NULL) - { - //if (needSpace) { ss << " "; needSpace = false; } - if (needSpace) { str += " "; needSpace = false; } - str += args.FuncName; - needSpace = true; - } - - if (needSpace) { str += ": "; needSpace = false; } - - str += message; - - CSystemUtils::copyTextToClipboard(str); - - // create the string on the screen - needSpace = false; -// stringstream ss2; - string str2; - -#ifdef NL_DEBUG - if (!args.ProcessName.empty()) - { - if (needSpace) { str2 += " "; needSpace = false; } - str2 += args.ProcessName; - needSpace = true; - } - - if (args.FileName != NULL) - { - if (needSpace) { str2 += " "; needSpace = false; } - str2 += CFile::getFilename(args.FileName); - needSpace = true; - } - - if (args.Line != -1) - { - if (needSpace) { str2 += " "; needSpace = false; } - str2 += NLMISC::toString(args.Line); - needSpace = true; - } - - if (args.FuncName != NULL) - { - if (needSpace) { str2 += " "; needSpace = false; } - str2 += args.FuncName; - needSpace = true; - } - - if (needSpace) { str2 += ": "; needSpace = false; } - -#endif // NL_DEBUG - - str2 += message; - str2 += "\n\n(this message was copied in the clipboard)"; - -/* if (IsDebuggerPresent ()) - { - // Must break in assert call - DebugNeedAssert = true; - } - else -*/ { - + // Display the report string body; @@ -656,69 +549,8 @@ void CMsgBoxDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *m body += "Reason: " + toString(message); body += args.CallstackAndLog; - - string subject; - - // procname is host/service_name-sid we only want the service_name to avoid redondant mail - string procname; - string::size_type pos = args.ProcessName.find ("/"); - if (pos == string::npos) - { - procname = args.ProcessName; - } - else - { - string::size_type pos2 = args.ProcessName.find ("-", pos+1); - if (pos2 == string::npos) - { - procname = args.ProcessName.substr (pos+1); - } - else - { - procname = args.ProcessName.substr (pos+1, pos2-pos-1); - } - } - - subject += procname + " NeL " + toString(LogTypeToString[0][args.LogType]) + " " + (args.FileName?string(args.FileName):"") + " " + toString(args.Line) + " " + (args.FuncName?string(args.FuncName):""); - - // Check the envvar NEL_IGNORE_ASSERT - if (getenv ("NEL_IGNORE_ASSERT") == NULL) - { - // yoyo: allow only to send the crash report once. Because users usually click ignore, - // which create noise into list of bugs (once a player crash, it will surely continues to do it). - std::string filename = getLogDirectory() + NL_CRASH_DUMP_FILE; - - if (ReportDebug == report (args.ProcessName + " NeL " + toString(logTypeToString(args.LogType, true)), "", subject, body, true, 2, true, 1, !isCrashAlreadyReported(), IgnoreNextTime, filename.c_str())) - { - INelContext::getInstance().setDebugNeedAssert(true); - } - - // no more sent mail for crash - setCrashAlreadyReported(true); - } - -/* // Check the envvar NEL_IGNORE_ASSERT - if (getenv ("NEL_IGNORE_ASSERT") == NULL) - { - // Ask the user to continue, debug or ignore - int result = MessageBox (NULL, ss2.str().c_str (), logTypeToString(args.LogType, true), MB_ABORTRETRYIGNORE | MB_ICONSTOP); - if (result == IDABORT) - { - // Exit the program now - exit (EXIT_FAILURE); - } - else if (result == IDRETRY) - { - // Give the debugger a try - DebugNeedAssert = true; - } - else if (result == IDIGNORE) - { - // Continue, do nothing - } - } -*/ } - + + report( body ); } diff --git a/code/nel/src/misc/report.cpp b/code/nel/src/misc/report.cpp index b165e29f5..54c456ade 100644 --- a/code/nel/src/misc/report.cpp +++ b/code/nel/src/misc/report.cpp @@ -22,23 +22,8 @@ #include "nel/misc/report.h" #include "nel/misc/path.h" -#ifdef NL_OS_WINDOWS -# ifndef NL_COMP_MINGW -# define NOMINMAX -# endif -# include -# include -# include -#endif // NL_OS_WINDOWS - -#define NL_NO_DEBUG_FILES 1 - using namespace std; -#ifdef DEBUG_NEW - #define new DEBUG_NEW -#endif - namespace NLMISC { @@ -52,7 +37,7 @@ void setReportEmailFunction (void *emailFunction) EmailFunction = (TEmailFunction)emailFunction; } -TReportResult report (const std::string &title, const std::string &header, const std::string &subject, const std::string &body, bool enableCheckIgnore, uint debugButton, bool ignoreButton, sint quitButton, bool sendReportButton, bool &ignoreNextTime, const string &attachedFile) +void report ( const std::string &body ) { std::string fname = "rcerrorlog.txt"; @@ -78,8 +63,6 @@ TReportResult report (const std::string &title, const std::string &header, const #endif // quit without calling atexit or static object dtors. abort(); - - return ReportQuit; } From 98cc1f03f8f3d54e411546ff3bf9e0290cda2a6d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 21 Feb 2015 22:34:02 +0100 Subject: [PATCH 87/87] Removed unused references to CMsgBoxDisplayer. --- code/ryzom/client/src/connection.cpp | 1 - code/ryzom/client/src/init.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/code/ryzom/client/src/connection.cpp b/code/ryzom/client/src/connection.cpp index 8b07cc7f2..22354e436 100644 --- a/code/ryzom/client/src/connection.cpp +++ b/code/ryzom/client/src/connection.cpp @@ -103,7 +103,6 @@ extern uint32 Version; // Client Version. extern UDriver *Driver; extern UTextContext *TextContext; extern bool game_exit; -extern CMsgBoxDisplayer MsgBoxError; extern CSoundManager *SoundMngr; diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index 6958fe790..f0fd40dae 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -142,7 +142,6 @@ using namespace std; // Ligo primitive class CLigoConfig LigoConfig; -CMsgBoxDisplayer MsgBoxError; CClientChatManager ChatMngr; bool LastScreenSaverEnabled = false;