Merge branch 'develop' into feature/opengl3

feature/opengl3
kaetemi 4 years ago
commit 440e062fb0

@ -54,8 +54,8 @@ ENDIF()
CMAKE_MINIMUM_REQUIRED(VERSION 2.6) CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(RyzomCore CXX C) PROJECT(RyzomCore CXX C)
SET(NL_VERSION_MAJOR 1) SET(NL_VERSION_MAJOR 1)
SET(NL_VERSION_MINOR 0) SET(NL_VERSION_MINOR 1)
SET(NL_VERSION_PATCH 2) SET(NL_VERSION_PATCH 0 CACHE STRING "Patch version")
SET(YEAR "2001-${CURRENT_YEAR}") SET(YEAR "2001-${CURRENT_YEAR}")
SET(AUTHOR "Winch Gate and The Ryzom Core Community") SET(AUTHOR "Winch Gate and The Ryzom Core Community")

@ -379,6 +379,10 @@ namespace NLGUI
TSmallScriptCache _SmallScriptCache; TSmallScriptCache _SmallScriptCache;
static const char * _NELSmallScriptTableName; static const char * _NELSmallScriptTableName;
#ifdef _WIN32
HMODULE m_LuaSocket;
#endif
private: private:
// this object isn't intended to be copied // this object isn't intended to be copied
CLuaState(const CLuaState &/* other */):NLMISC::CRefCount() { nlassert(0); } CLuaState(const CLuaState &/* other */):NLMISC::CRefCount() { nlassert(0); }

@ -263,8 +263,8 @@ inline lua_Integer CLuaState::toInteger(int index)
if (!isnum) if (!isnum)
{ {
lua_Number d = lua_tonumber(_State, index); lua_Number d = lua_tonumber(_State, index);
nlwarning("Lua: Unable to convert Lua number %lf to integer", d);
res = (lua_Integer)d; res = (lua_Integer)d;
nlwarning("Lua: Converting lua_Number %lf to lua_Integer %i", d, (int)res);
} }
return res; return res;
#else #else

@ -89,6 +89,9 @@ void createDebug (const char *logPath = NULL, bool logInFile = true, bool eraseL
/// Do not call this, unless you know what you're trying to do (it kills debug)! /// Do not call this, unless you know what you're trying to do (it kills debug)!
void destroyDebug(); void destroyDebug();
/// Attach exception handler, for new threads and fibers
void attachExceptionHandler();
// call this if you want to change the dir of the log.log file // call this if you want to change the dir of the log.log file
void changeLogDirectory(const std::string &dir); void changeLogDirectory(const std::string &dir);
@ -352,7 +355,7 @@ void setCrashAlreadyReported(bool state);
* Same as nlassertex(false,exp); * Same as nlassertex(false,exp);
*/ */
// removed because we always check assert (even in release mode) #if defined (NL_OS_WINDOWS) && defined (NL_DEBUG) #if defined(NL_DEBUG) /* Debug break is only useful in debug builds */
#if defined(NL_OS_WINDOWS) #if defined(NL_OS_WINDOWS)
#define NLMISC_BREAKPOINT __debugbreak() #define NLMISC_BREAKPOINT __debugbreak()
#elif defined(NL_OS_UNIX) && defined(NL_COMP_GCC) #elif defined(NL_OS_UNIX) && defined(NL_COMP_GCC)
@ -360,6 +363,9 @@ void setCrashAlreadyReported(bool state);
#else #else
#define NLMISC_BREAKPOINT abort() #define NLMISC_BREAKPOINT abort()
#endif #endif
#else
#define NLMISC_BREAKPOINT do { } while (0)
#endif
// Internal, don't use it (make smaller assert code) // Internal, don't use it (make smaller assert code)
extern bool _assert_stop(bool &ignoreNextTime, sint line, const char *file, const char *funcName, const char *exp); extern bool _assert_stop(bool &ignoreNextTime, sint line, const char *file, const char *funcName, const char *exp);

@ -662,6 +662,7 @@ private:
std::vector<TCallbackArgItem> _UpUniCallback; std::vector<TCallbackArgItem> _UpUniCallback;
TNameMappedCallback _DownCallbacks; TNameMappedCallback _DownCallbacks;
std::vector<TCallbackArgItem> _DownUniCallback; std::vector<TCallbackArgItem> _DownUniCallback;
std::set<std::pair<std::string, TServiceId>> _NotifiedUpCallbacks;
/// Recording state /// Recording state
CCallbackNetBase::TRecordingState _RecordingState; CCallbackNetBase::TRecordingState _RecordingState;

@ -191,7 +191,7 @@ public:
/// Create a native music channel, only supported by the FMod driver. /// Create a native music channel, only supported by the FMod driver.
virtual IMusicChannel *createMusicChannel() { return NULL; } virtual IMusicChannel *createMusicChannel() { return NULL; }
/** Get music info. Returns false if the song is not found or the function is not implemented. /** Get music info. Returns false if the song is not found or the function is not implemented.
* \param filepath path to file, CPath::lookup done by driver * \param filepath full path to file
* \param artist returns the song artist (empty if not available) * \param artist returns the song artist (empty if not available)
* \param title returns the title (empty if not available) * \param title returns the title (empty if not available)
*/ */

@ -108,7 +108,7 @@ public:
bool play(const std::string &filepath, uint xFadeTime = 0, bool async = true, bool loop = true); bool play(const std::string &filepath, uint xFadeTime = 0, bool async = true, bool loop = true);
/// Stop the music previously loaded and played (the Memory is also freed) /// Stop the music previously loaded and played (the Memory is also freed)
void stop(uint xFadeTime = 0); bool stop(uint xFadeTime = 0);
/// Pause the music previously loaded and played (the Memory is not freed) /// Pause the music previously loaded and played (the Memory is not freed)
void pause(); void pause();

@ -96,6 +96,8 @@ private:
IAudioDecoder *m_AudioDecoder; IAudioDecoder *m_AudioDecoder;
std::string m_LookupPath;
bool m_Paused; bool m_Paused;
bool m_DecodingEnded; bool m_DecodingEnded;

@ -34,7 +34,7 @@ class CCurlHttpClient
public: public:
/// Constructor /// Constructor
CCurlHttpClient() {} CCurlHttpClient() : _CurlStruct(NULL) {}
/// Connect to an http server (string by val is intended). If you specify a whole URL, an attempt will be made to determine the server. /// Connect to an http server (string by val is intended). If you specify a whole URL, an attempt will be made to determine the server.
bool connect(const std::string &server); bool connect(const std::string &server);

@ -3830,9 +3830,15 @@ void CDriverD3D::CLightState::apply(CDriverD3D *driver)
void CDriverD3D::CRenderTargetState::apply(CDriverD3D *driver) void CDriverD3D::CRenderTargetState::apply(CDriverD3D *driver)
{ {
H_AUTO_D3D(CDriverD3D_CRenderTargetState); H_AUTO_D3D(CDriverD3D_CRenderTargetState);
driver->_DeviceInterface->SetRenderTarget (0, Target); nlassert(TargetOwned); // Can only apply once!
driver->_DeviceInterface->SetRenderTarget(0, Target);
driver->setupViewport(driver->_Viewport); driver->setupViewport(driver->_Viewport);
driver->setupScissor(driver->_Scissor); driver->setupScissor(driver->_Scissor);
if (TargetOwned)
{
Target->Release();
TargetOwned = false;
}
} }
// *************************************************************************** // ***************************************************************************

@ -1546,11 +1546,13 @@ public:
Texture = NULL; Texture = NULL;
Level = 0; Level = 0;
CubeFace = 0; CubeFace = 0;
TargetOwned = false;
} }
IDirect3DSurface9 *Target; IDirect3DSurface9 *Target;
ITexture *Texture; ITexture *Texture;
uint8 Level; uint8 Level;
uint8 CubeFace; uint8 CubeFace;
bool TargetOwned;
virtual void apply(CDriverD3D *driver); virtual void apply(CDriverD3D *driver);
}; };
@ -2076,10 +2078,17 @@ public:
NL_D3D_CACHE_TEST(CacheTest_RenderTarget, _RenderTarget.Target != target) NL_D3D_CACHE_TEST(CacheTest_RenderTarget, _RenderTarget.Target != target)
#endif // NL_D3D_USE_RENDER_STATE_CACHE #endif // NL_D3D_USE_RENDER_STATE_CACHE
{ {
if (_RenderTarget.TargetOwned)
{
nlassert(_RenderTarget.Target);
_RenderTarget.Target->Release();
}
_RenderTarget.Target = target; _RenderTarget.Target = target;
_RenderTarget.Texture = texture; _RenderTarget.Texture = texture;
_RenderTarget.Level = level; _RenderTarget.Level = level;
_RenderTarget.CubeFace = cubeFace; _RenderTarget.CubeFace = cubeFace;
_RenderTarget.TargetOwned = target;
target->AddRef();
touchRenderVariable (&_RenderTarget); touchRenderVariable (&_RenderTarget);

@ -706,9 +706,13 @@ bool CDriverD3D::setupMaterial(CMaterial &mat)
// Set the texture states // Set the texture states
if (text || (stage == 0)) if (text || (stage == 0))
{ {
// Doesn't use a pixel shader ? Set the textures stages if (matShader == CMaterial::Program)
if (pShader->PixelShader == NULL)
{ {
// Do nothing for user pixel shader
}
else if (!pShader->PixelShader)
{
// Doesn't use a pixel shader ? Set the textures stages
if (pShader->RGBPipe[stage]) if (pShader->RGBPipe[stage])
{ {
setTextureState (stage, D3DTSS_COLOROP, pShader->ColorOp[stage]); setTextureState (stage, D3DTSS_COLOROP, pShader->ColorOp[stage]);
@ -1145,7 +1149,7 @@ bool CDriverD3D::setupMaterial(CMaterial &mat)
} }
break; break;
case CMaterial::Cloud: case CMaterial::Cloud:
{ {
H_AUTO_D3D(CDriverD3D_setupMaterial_setupCloudShader) H_AUTO_D3D(CDriverD3D_setupMaterial_setupCloudShader)
activeShader (&_ShaderCloud); activeShader (&_ShaderCloud);
@ -1167,7 +1171,7 @@ bool CDriverD3D::setupMaterial(CMaterial &mat)
return false; return false;
} }
break; break;
case CMaterial::Water: case CMaterial::Water:
{ {
H_AUTO_D3D(CDriverD3D_setupMaterial_setupWaterShader) H_AUTO_D3D(CDriverD3D_setupMaterial_setupWaterShader)
activeShader(mat.getTexture(3) ? &_ShaderWaterDiffuse : &_ShaderWaterNoDiffuse); activeShader(mat.getTexture(3) ? &_ShaderWaterDiffuse : &_ShaderWaterNoDiffuse);
@ -1296,7 +1300,14 @@ bool CDriverD3D::setupMaterial(CMaterial &mat)
} }
} }
} }
// CMaterial::Water break; // CMaterial::Water
case CMaterial::Program:
{
H_AUTO_D3D(CDriverD3D_setupMaterial_setupProgramshader)
// No material shader
activeShader(NULL);
}
break;
} }
// New material setuped // New material setuped

@ -1084,6 +1084,7 @@ void CDriverD3D::swapTextureHandle(ITexture &tex0, ITexture &tex1)
swap(t0->Height, t1->Height); swap(t0->Height, t1->Height);
swap(t0->SrcCompressed, t1->SrcCompressed); swap(t0->SrcCompressed, t1->SrcCompressed);
swap(t0->IsCube, t1->IsCube); swap(t0->IsCube, t1->IsCube);
swap(t0->RenderTarget, t1->RenderTarget);
swap(t0->Levels, t1->Levels); swap(t0->Levels, t1->Levels);
swap(t0->FirstMipMap, t1->FirstMipMap); swap(t0->FirstMipMap, t1->FirstMipMap);
swap(t0->TextureMemory, t1->TextureMemory); swap(t0->TextureMemory, t1->TextureMemory);

@ -1584,6 +1584,14 @@ void registerGlExtensions(CGlExtensions &ext)
{ {
H_AUTO_OGL(registerGlExtensions); H_AUTO_OGL(registerGlExtensions);
#ifdef NL_OS_MAC
CGLContextObj ctx = CGLGetCurrentContext();
if (ctx == NULL)
{
nlerror("No OpenGL context set");
}
#endif
// OpenGL 1.2 ?? // OpenGL 1.2 ??
const char *nglVersion = (const char *)glGetString (GL_VERSION); const char *nglVersion = (const char *)glGetString (GL_VERSION);

@ -1072,6 +1072,9 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re
[_ctx flushBuffer]; [_ctx flushBuffer];
[_glView display]; [_glView display];
// Set context as thread context
CGLSetCurrentContext((CGLContextObj)[_ctx CGLContextObj]);
_EventEmitter.init(this, _glView, _DestroyWindow); _EventEmitter.init(this, _glView, _DestroyWindow);
#elif defined(NL_OS_UNIX) #elif defined(NL_OS_UNIX)

@ -246,6 +246,7 @@ void CFXAA::applyEffect()
// create render target // create render target
CTextureUser *otherRenderTarget = m_Driver->getRenderTargetManager().getRenderTarget(width, height, mode2D); CTextureUser *otherRenderTarget = m_Driver->getRenderTargetManager().getRenderTarget(width, height, mode2D);
nlassert(otherRenderTarget);
// swap render target // swap render target
CTextureUser texNull; CTextureUser texNull;

@ -979,6 +979,9 @@ void CLodCharacterManager::addTextureCompute(CLodCharacterInstance &instance,
// get lookup ptr. // get lookup ptr.
nlassert(lodTexture.Texture.size()==NL3D_CLOD_TEXT_SIZE); nlassert(lodTexture.Texture.size()==NL3D_CLOD_TEXT_SIZE);
if (lodTexture.Texture.size() < NL3D_CLOD_TEXT_SIZE)
return;
const CLodCharacterTexture::CTUVQ *lookUpPtr= &lodTexture.Texture[0]; const CLodCharacterTexture::CTUVQ *lookUpPtr= &lodTexture.Texture[0];
// apply the lodTexture, taking only better quality (ie nearer 0) // apply the lodTexture, taking only better quality (ie nearer 0)

@ -216,16 +216,55 @@ namespace NLGUI
// *** Load base libs // *** Load base libs
{ {
CLuaStackChecker lsc(this); CLuaStackChecker lsc(this);
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501
luaL_openlibs(_State); luaL_openlibs(_State);
#else #else
luaopen_base (_State); luaopen_base (_State);
luaopen_table (_State); luaopen_table (_State);
luaopen_io (_State); luaopen_io (_State);
luaopen_string (_State); luaopen_string (_State);
luaopen_math (_State); luaopen_math (_State);
luaopen_debug (_State); luaopen_debug (_State);
#endif #endif
#ifdef _WIN32
// Lua socket library for MobDebug, optional
if (NLMISC::CFile::fileExists("socket\\core.dll"))
{
// Load socket\core.dll dynamically
m_LuaSocket = LoadLibraryW(L"socket\\core.dll");
if (!m_LuaSocket)
{
nlwarning("Lua socket library found, but failed to load");
}
else
{
void *luaopen_socket_core = (void *)GetProcAddress(m_LuaSocket, "luaopen_socket_core");
if (!luaopen_socket_core)
{
nlwarning("Lua socket library loaded, but `luaopen_socket_core` not found");
FreeLibrary(m_LuaSocket);
m_LuaSocket = NULL;
}
else
{
// preload['socket.core'] = luaopen_socket_core
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501
lua_getglobal(_State, "package");
lua_getfield(_State, -1, "preload");
lua_pushcfunction(_State, (lua_CFunction)luaopen_socket_core);
lua_setfield(_State, -2, "socket.core");
lua_pop(_State, 2);
nlinfo("Lua socket library preloaded");
#endif
}
}
}
else
{
m_LuaSocket = NULL;
}
#endif
// open are buggy???? // open are buggy????
clear(); clear();
@ -313,6 +352,14 @@ namespace NLGUI
// Clear Small Script Cache // Clear Small Script Cache
_SmallScriptPool= 0; _SmallScriptPool= 0;
_SmallScriptCache.clear(); _SmallScriptCache.clear();
#ifdef _WIN32
if (m_LuaSocket)
{
FreeLibrary(m_LuaSocket);
m_LuaSocket = NULL;
}
#endif
} }
// *************************************************************************** // ***************************************************************************
@ -464,7 +511,23 @@ namespace NLGUI
// execute the script text, with dbgSrc==filename (use @ for lua internal purpose) // execute the script text, with dbgSrc==filename (use @ for lua internal purpose)
executeScriptInternal(script, string("@") + CFile::getFilename(pathName)); #ifdef _WIN32
// Paths need to be correct for debugging to work
std::string pathNameStandardized = pathName;
if (pathNameStandardized.size() > 1)
{
if (pathNameStandardized[1] == ':' && pathNameStandardized[0] >= 'a' && pathNameStandardized[0] <= 'z')
pathNameStandardized[0] -= 'a' - 'A';
for (ptrdiff_t i = 0; i < (ptrdiff_t)pathNameStandardized.size(); ++i)
{
if (pathNameStandardized[i] == '/')
pathNameStandardized[i] = '\\';
}
}
#else
const std::string &pathNameStandardized = pathName;
#endif
executeScriptInternal(script, string("@") + pathNameStandardized);
return true; return true;
} }

@ -143,6 +143,9 @@ namespace NLMISC
NL_CT_DEBUG("CoTask : task %p start func called", task); NL_CT_DEBUG("CoTask : task %p start func called", task);
// Attach exception handler
attachExceptionHandler();
try try
{ {
// run the task // run the task
@ -151,6 +154,7 @@ namespace NLMISC
catch(...) catch(...)
{ {
nlwarning("CCoTask::startFunc : the task has generated an unhandled exeption and will terminate"); nlwarning("CCoTask::startFunc : the task has generated an unhandled exeption and will terminate");
NLMISC_BREAKPOINT;
} }
task->_Finished = true; task->_Finished = true;

@ -1157,6 +1157,15 @@ void destroyDebug()
} }
} }
void attachExceptionHandler()
{
#ifndef NL_COMP_MINGW
# ifdef NL_OS_WINDOWS
_set_se_translator(exceptionTranslator);
# endif // NL_OS_WINDOWS
#endif //!NL_COMP_MINGW
}
void createDebug (const char *logPath, bool logInFile, bool eraseLastLog) void createDebug (const char *logPath, bool logInFile, bool eraseLastLog)
{ {
// Do some basic compiler time check on type size // Do some basic compiler time check on type size

@ -179,7 +179,6 @@
#else #else
# include <sys/types.h> # include <sys/types.h>
# include <sys/stat.h> # include <sys/stat.h>
# include <sys/sysctl.h>
# include <fcntl.h> # include <fcntl.h>
# include <unistd.h> # include <unistd.h>
# include <cerrno> # include <cerrno>

@ -67,6 +67,9 @@ static unsigned long __stdcall ProxyFunc (void *arg)
// Set the thread pointer in TLS memory // Set the thread pointer in TLS memory
nlverify (TlsSetValue (TLSThreadPointer, (void*)parent) != 0); nlverify (TlsSetValue (TLSThreadPointer, (void*)parent) != 0);
// Attach exception handler
attachExceptionHandler();
// Run the thread // Run the thread
parent->Runnable->run(); parent->Runnable->run();

@ -2090,6 +2090,14 @@ void CUnifiedNetwork::addNetworkAssociation (const string &networkName, uint8 ni
void CUnifiedNetwork::callServiceUpCallback (const std::string &serviceName, TServiceId sid, bool callGlobalCallback) void CUnifiedNetwork::callServiceUpCallback (const std::string &serviceName, TServiceId sid, bool callGlobalCallback)
{ {
std::pair<std::string, TServiceId> pss = std::make_pair(serviceName, sid);
if (_NotifiedUpCallbacks.find(pss) != _NotifiedUpCallbacks.end())
{
nlwarning("HNETL5: Attempt to call service UP callback twice for '%s', ignored!", serviceName.c_str());
return;
}
_NotifiedUpCallbacks.insert(pss);
// now we warn the user // now we warn the user
CUnifiedNetwork::TNameMappedCallback::iterator it = _UpCallbacks.find(serviceName); CUnifiedNetwork::TNameMappedCallback::iterator it = _UpCallbacks.find(serviceName);
if (it != _UpCallbacks.end()) if (it != _UpCallbacks.end())
@ -2119,6 +2127,14 @@ void CUnifiedNetwork::callServiceUpCallback (const std::string &serviceName, TSe
void CUnifiedNetwork::callServiceDownCallback (const std::string &serviceName, TServiceId sid, bool callGlobalCallback) void CUnifiedNetwork::callServiceDownCallback (const std::string &serviceName, TServiceId sid, bool callGlobalCallback)
{ {
std::pair<std::string, TServiceId> pss = std::make_pair(serviceName, sid);
if (_NotifiedUpCallbacks.find(pss) == _NotifiedUpCallbacks.end())
{
nlwarning("HNETL5: Attempt to call service DOWN callback twice for '%s', ignored!", serviceName.c_str());
return;
}
_NotifiedUpCallbacks.erase(pss);
// now we warn the user // now we warn the user
CUnifiedNetwork::TNameMappedCallback::iterator it = _DownCallbacks.find(serviceName); CUnifiedNetwork::TNameMappedCallback::iterator it = _DownCallbacks.find(serviceName);
if (it != _DownCallbacks.end()) if (it != _DownCallbacks.end())

@ -418,13 +418,13 @@ void CMoveContainer::updateCells (CMovePrimitive *primitive, uint8 worldImage)
/* // Check BB width not too large /* // Check BB width not too large
if (wI->getBBXMax() - wI->getBBXMin() > _CellWidth) if (wI->getBBXMax() - wI->getBBXMin() > _CellWidth)
{ {
nlwarning ("Primitives have moved more than a cell."); nlwarning ("Primitives have moved more than a cell, width: %f.", (float)(wI->getBBXMax() - wI->getBBXMin()));
} }
// Check BB height not too large // Check BB height not too large
if (wI->getBBYMax() - wI->getBBYMin() > _CellHeight) if (wI->getBBYMax() - wI->getBBYMin() > _CellHeight)
{ {
nlwarning ("Primitives have moved more than a cell."); nlwarning ("Primitives have moved more than a cell, height: %f.", (float)(wI->getBBYMax() - wI->getBBYMin()));
} }
*/ */
#endif #endif

@ -56,18 +56,12 @@ IAudioDecoder::~IAudioDecoder()
IAudioDecoder *IAudioDecoder::createAudioDecoder(const std::string &filepath, bool async, bool loop) IAudioDecoder *IAudioDecoder::createAudioDecoder(const std::string &filepath, bool async, bool loop)
{ {
std::string lookup = CPath::lookup(filepath, false);
if (lookup.empty())
{
nlwarning("Music file %s does not exist!", filepath.c_str());
return NULL;
}
std::string type = CFile::getExtension(filepath); std::string type = CFile::getExtension(filepath);
CIFile *ifile = new CIFile(); CIFile *ifile = new CIFile();
ifile->setCacheFileOnOpen(!async); ifile->setCacheFileOnOpen(!async);
ifile->allowBNPCacheFileOnOpen(!async); ifile->allowBNPCacheFileOnOpen(!async);
ifile->open(lookup); ifile->open(filepath);
IAudioDecoder *mb = createAudioDecoder(type, ifile, loop); IAudioDecoder *mb = createAudioDecoder(type, ifile, loop);
@ -116,10 +110,9 @@ IAudioDecoder *IAudioDecoder::createAudioDecoder(const std::string &type, NLMISC
bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, std::string &title, float &length) bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, std::string &title, float &length)
{ {
std::string lookup = CPath::lookup(filepath, false); if (filepath.empty() || !CFile::fileExists(filepath))
if (lookup.empty())
{ {
nlwarning("Music file %s does not exist!", filepath.c_str()); nlwarning("Music file '%s' does not exist!", filepath.c_str());
return false; return false;
} }
@ -127,7 +120,7 @@ bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, st
CIFile ifile; CIFile ifile;
ifile.setCacheFileOnOpen(false); ifile.setCacheFileOnOpen(false);
ifile.allowBNPCacheFileOnOpen(false); ifile.allowBNPCacheFileOnOpen(false);
if (ifile.open(lookup)) if (ifile.open(filepath))
return CAudioDecoderFfmpeg::getInfo(&ifile, artist, title, length); return CAudioDecoderFfmpeg::getInfo(&ifile, artist, title, length);
#else #else
std::string type = CFile::getExtension(filepath); std::string type = CFile::getExtension(filepath);
@ -138,7 +131,7 @@ bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, st
CIFile ifile; CIFile ifile;
ifile.setCacheFileOnOpen(false); ifile.setCacheFileOnOpen(false);
ifile.allowBNPCacheFileOnOpen(false); ifile.allowBNPCacheFileOnOpen(false);
if (ifile.open(lookup)) if (ifile.open(filepath))
return CAudioDecoderVorbis::getInfo(&ifile, artist, title, length); return CAudioDecoderVorbis::getInfo(&ifile, artist, title, length);
nlwarning("Unable to open: '%s'", filepath.c_str()); nlwarning("Unable to open: '%s'", filepath.c_str());
@ -149,7 +142,7 @@ bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, st
CIFile ifile; CIFile ifile;
ifile.setCacheFileOnOpen(false); ifile.setCacheFileOnOpen(false);
ifile.allowBNPCacheFileOnOpen(false); ifile.allowBNPCacheFileOnOpen(false);
if (ifile.open(lookup)) if (ifile.open(filepath))
return CAudioDecoderMP3::getInfo(&ifile, artist, title, length); return CAudioDecoderMP3::getInfo(&ifile, artist, title, length);
nlwarning("Unable to open: '%s'", filepath.c_str()); nlwarning("Unable to open: '%s'", filepath.c_str());

@ -496,36 +496,20 @@ bool getTag (std::string &result, const char *tag, FSOUND_STREAM *stream)
} }
/** Get music info. Returns false if the song is not found or the function is not implemented. /** Get music info. Returns false if the song is not found or the function is not implemented.
* \param filepath path to file, CPath::lookup done by driver * \param filepath full path to file
* \param artist returns the song artist (empty if not available) * \param artist returns the song artist (empty if not available)
* \param title returns the title (empty if not available) * \param title returns the title (empty if not available)
*/ */
bool CSoundDriverFMod::getMusicInfo(const std::string &filepath, std::string &artist, std::string &title, float &length) bool CSoundDriverFMod::getMusicInfo(const std::string &filepath, std::string &artist, std::string &title, float &length)
{ {
/* Open a stream, get the tag if it exists, close the stream */ if (filepath.empty() || !CFile::fileExists(filepath))
string pathName = CPath::lookup(filepath, false);
uint32 fileOffset = 0, fileSize = 0;
if (pathName.empty())
{ {
nlwarning("NLSOUND FMod Driver: Music file %s not found!", filepath.c_str()); nlwarning("NLSOUND FMod Driver: Music file %s not found!", filepath.c_str());
return false; return false;
} }
// if the file is in a bnp
if (pathName.find('@') != string::npos)
{
if (CBigFile::getInstance().getFileInfo(pathName, fileSize, fileOffset))
{
// set pathname to bnp
pathName = pathName.substr(0, pathName.find('@'));
}
else
{
nlwarning("NLSOUND FMod Driver: BNP BROKEN");
return false;
}
}
FSOUND_STREAM *stream = FSOUND_Stream_Open((const char *)CPath::lookup(filepath, false).c_str(), FSOUND_2D, (sint)fileOffset, (sint)fileSize); uint32 fileOffset = 0, fileSize = 0;
FSOUND_STREAM *stream = FSOUND_Stream_Open(filepath.c_str(), FSOUND_2D, (sint)fileOffset, (sint)fileSize);
if (stream) if (stream)
{ {
getTag(artist, "ARTIST", stream); getTag(artist, "ARTIST", stream);

@ -112,7 +112,7 @@ public:
virtual IMusicChannel *createMusicChannel(); virtual IMusicChannel *createMusicChannel();
/** Get music info. Returns false if the song is not found or the function is not implemented. /** Get music info. Returns false if the song is not found or the function is not implemented.
* \param filepath path to file, CPath::lookup done by driver * \param filepath full path to file
* \param artist returns the song artist (empty if not available) * \param artist returns the song artist (empty if not available)
* \param title returns the title (empty if not available) * \param title returns the title (empty if not available)
*/ */

@ -480,7 +480,7 @@ void CSourceXAudio2::setLooping(bool l)
_SourceVoice->GetState(&voice_state); _SourceVoice->GetState(&voice_state);
if (voice_state.BuffersQueued) if (voice_state.BuffersQueued)
{ {
nlwarning(NLSOUND_XAUDIO2_PREFIX "Not playing but buffer already queued while switching loop mode!?! Flush and requeue"); // nlwarning(NLSOUND_XAUDIO2_PREFIX "Not playing but buffer already queued while switching loop mode!?! Flush and requeue");
if (FAILED(_SourceVoice->FlushSourceBuffers())) if (FAILED(_SourceVoice->FlushSourceBuffers()))
nlwarning(NLSOUND_XAUDIO2_PREFIX "FAILED FlushSourceBuffers"); nlwarning(NLSOUND_XAUDIO2_PREFIX "FAILED FlushSourceBuffers");
// queue buffer with correct looping parameters // queue buffer with correct looping parameters

@ -147,7 +147,7 @@ void CMusicChannelFader::updateVolume()
*/ */
bool CMusicChannelFader::play(const std::string &filepath, uint xFadeTime, bool async, bool loop) bool CMusicChannelFader::play(const std::string &filepath, uint xFadeTime, bool async, bool loop)
{ {
stop(xFadeTime); bool stopped = stop(xFadeTime);
// Find the next best free music channel // Find the next best free music channel
uint nextFader = _MaxMusicFader; uint nextFader = _MaxMusicFader;
@ -164,7 +164,7 @@ bool CMusicChannelFader::play(const std::string &filepath, uint xFadeTime, bool
// Play a song in it :) // Play a song in it :)
_CMusicFader &fader = _MusicFader[_ActiveMusicFader]; _CMusicFader &fader = _MusicFader[_ActiveMusicFader];
if (xFadeTime) fader.fadeIn(xFadeTime); if (xFadeTime && !stopped) fader.fadeIn(xFadeTime); // only fade in when fading out
else fader.XFadeVolume = 1.0f; else fader.XFadeVolume = 1.0f;
fader.Playing = true; fader.Playing = true;
updateVolume(); // make sure at ok volume to start :) updateVolume(); // make sure at ok volume to start :)
@ -173,12 +173,17 @@ bool CMusicChannelFader::play(const std::string &filepath, uint xFadeTime, bool
} }
/// Stop the music previously loaded and played (the Memory is also freed) /// Stop the music previously loaded and played (the Memory is also freed)
void CMusicChannelFader::stop(uint xFadeTime) bool CMusicChannelFader::stop(uint xFadeTime)
{ {
if (xFadeTime) if (xFadeTime)
{ {
bool stopped = true;
for (uint i = 0; i < _MaxMusicFader; ++i) if (_MusicFader[i].Playing) for (uint i = 0; i < _MaxMusicFader; ++i) if (_MusicFader[i].Playing)
{
_MusicFader[i].fadeOut(xFadeTime); _MusicFader[i].fadeOut(xFadeTime);
stopped = false; // fading
}
return stopped;
} }
else else
{ {
@ -188,6 +193,7 @@ void CMusicChannelFader::stop(uint xFadeTime)
_MusicFader[i].Fade = false; _MusicFader[i].Fade = false;
_MusicFader[i].Playing = false; _MusicFader[i].Playing = false;
} }
return true;
} }
} }

@ -108,6 +108,13 @@ void CStreamFileSource::play()
//{ //{
// nlwarning("Already waiting for play"); // nlwarning("Already waiting for play");
//} //}
std::string filepath = getStreamFileSound()->getFilePath();
m_LookupPath = NLMISC::CPath::lookup(filepath, false, false);
if (m_LookupPath.empty())
{
nlwarning("Music file %s does not exist!", filepath.c_str());
return;
}
if (!getStreamFileSound()->getAsync()) if (!getStreamFileSound()->getAsync())
{ {
if (!prepareDecoder()) if (!prepareDecoder())
@ -272,7 +279,8 @@ bool CStreamFileSource::prepareDecoder()
if (!m_AudioDecoder) if (!m_AudioDecoder)
{ {
// load the file // load the file
m_AudioDecoder = IAudioDecoder::createAudioDecoder(getStreamFileSound()->getFilePath(), getStreamFileSound()->getAsync(), getStreamFileSound()->getLooping()); nlassert(!m_LookupPath.empty());
m_AudioDecoder = IAudioDecoder::createAudioDecoder(m_LookupPath, getStreamFileSound()->getAsync(), getStreamFileSound()->getLooping());
if (!m_AudioDecoder) if (!m_AudioDecoder)
{ {
nlwarning("Failed to create IAudioDecoder, likely invalid format"); nlwarning("Failed to create IAudioDecoder, likely invalid format");

@ -191,7 +191,11 @@ bool CCurlHttpClient::receive(string &res, bool verbose)
// *************************************************************************** // ***************************************************************************
void CCurlHttpClient::disconnect() void CCurlHttpClient::disconnect()
{ {
curl_easy_cleanup(_Curl); if (_CurlStruct)
{
curl_easy_cleanup(_Curl);
_CurlStruct = NULL;
}
curl_global_cleanup(); curl_global_cleanup();
} }

@ -135,6 +135,9 @@ bool CLodTextureBuilder::computeTexture(const CMeshMRM &meshMRM, NL3D::CLodCha
const uint8 *srcPos= (const uint8*)vba.getVertexCoordPointer(); const uint8 *srcPos= (const uint8*)vba.getVertexCoordPointer();
const uint8 *srcNormal= (const uint8*)vba.getNormalCoordPointer(); const uint8 *srcNormal= (const uint8*)vba.getNormalCoordPointer();
const uint8 *srcUV= (const uint8*)vba.getTexCoordPointer(); const uint8 *srcUV= (const uint8*)vba.getTexCoordPointer();
nlassert(srcPos);
nlassert(srcNormal);
nlassert(srcUV);
uint vertexSize = VB.getVertexSize(); uint vertexSize = VB.getVertexSize();
// For the more precise lod // For the more precise lod
uint lodId= meshMRM.getNbLod()-1; uint lodId= meshMRM.getNbLod()-1;

@ -49,6 +49,9 @@ printLog(log, "-------")
printLog(log, time.strftime("%Y-%m-%d %H:%MGMT", time.gmtime(time.time()))) printLog(log, time.strftime("%Y-%m-%d %H:%MGMT", time.gmtime(time.time())))
printLog(log, "") printLog(log, "")
# Find tools
SevenZip = findTool(log, ToolDirectories, SevenZipTool, ToolSuffix)
# List the directories that will be used # List the directories that will be used
archiveDirectories = [ ] archiveDirectories = [ ]
for dir in InstallShardDataDirectories: for dir in InstallShardDataDirectories:
@ -89,23 +92,29 @@ else:
printLog(log, "") printLog(log, "")
if not args.admininstall: if not args.admininstall:
printLog(log, ">>> Create new version <<<") if SevenZip == "":
newVersion = 1 toolLogFail(log, SevenZipTool, ToolSuffix)
vstr = str(newVersion).zfill(6) else:
vpath = PatchmanBridgeServerDirectory + "/" + vstr printLog(log, ">>> Create new version <<<")
while os.path.exists(vpath): newVersion = 1
newVersion = newVersion + 1
vstr = str(newVersion).zfill(6) vstr = str(newVersion).zfill(6)
vpath = PatchmanBridgeServerDirectory + "/" + vstr vpath = PatchmanBridgeServerDirectory + "/" + vstr
mkPath(log, vpath) while os.path.exists(vpath):
for dir in archiveDirectories: newVersion = newVersion + 1
mkPath(log, ShardInstallDirectory + "/" + dir) vstr = str(newVersion).zfill(6)
tgzPath = vpath + "/" + dir + ".tgz" vpath = PatchmanBridgeServerDirectory + "/" + vstr
printLog(log, "WRITE " + tgzPath) mkPath(log, vpath)
tar = tarfile.open(tgzPath, "w:gz") for dir in archiveDirectories:
tar.add(ShardInstallDirectory + "/" + dir, arcname = dir) mkPath(log, ShardInstallDirectory + "/" + dir)
tar.close() # tgzPath = vpath + "/" + dir + ".tgz"
printLog(log, "") # printLog(log, "WRITE " + tgzPath)
# tar = tarfile.open(tgzPath, "w:gz")
# tar.add(ShardInstallDirectory + "/" + dir, arcname = dir)
# tar.close()
sevenZipPath = vpath + "/" + dir + ".7z"
printLog(log, "WRITE " + sevenZipPath)
subprocess.call([ SevenZip, "a", sevenZipPath, ShardInstallDirectory + "/" + dir ])
printLog(log, "")
log.close() log.close()
if os.path.isfile("c1_shard_patch.log"): if os.path.isfile("c1_shard_patch.log"):

@ -98,3 +98,4 @@ PatchGenTool = "patch_gen"
TranslationToolsTool = "translation_tools" TranslationToolsTool = "translation_tools"
BuildWorldPackedColTool = "build_world_packed_col" BuildWorldPackedColTool = "build_world_packed_col"
R2IslandsTexturesTool = "r2_islands_textures" R2IslandsTexturesTool = "r2_islands_textures"
SevenZipTool = "7za"

@ -123,7 +123,9 @@ else:
printLog(log, "") printLog(log, "")
printLog(log, ">>> Make bnp <<<") printLog(log, ">>> Make bnp <<<")
targetPath = ClientPatchDirectory + "/bnp" targetPath = ClientPatchDirectory + "/bnp"
tagPath = ClientPatchDirectory + "/bnp_tag"
mkPath(log, targetPath) mkPath(log, targetPath)
mkPath(log, tagPath)
for category in InstallClientData: for category in InstallClientData:
packExt = ".bnp" packExt = ".bnp"
if (category["StreamedPackages"]): if (category["StreamedPackages"]):
@ -133,25 +135,32 @@ else:
sourcePath = InstallDirectory + "/" + package[0] sourcePath = InstallDirectory + "/" + package[0]
mkPath(log, sourcePath) mkPath(log, sourcePath)
targetBnp = targetPath + "/" + package[0] + packExt targetBnp = targetPath + "/" + package[0] + packExt
tagBnp = tagPath + "/" + package[0] + packExt + ".tag"
if (len(package[1]) > 0): if (len(package[1]) > 0):
targetBnp = targetPath + "/" + package[1][0] targetBnp = targetPath + "/" + package[1][0]
tagBnp = tagPath + "/" + package[1][0] + ".tag"
printLog(log, "TARGET " + package[1][0]) printLog(log, "TARGET " + package[1][0])
needUpdateBnp = 1 needUpdateBnp = 1
if (len(package) > 2): if (len(package) > 2):
needUpdateBnp = needUpdate(log, sourcePath + "/" + package[2], targetBnp) needUpdateBnp = needUpdate(log, sourcePath + "/" + package[2], tagBnp)
else: else:
needUpdateBnp = needUpdateDirNoSubdirFile(log, sourcePath, targetBnp) needUpdateBnp = needUpdateDirNoSubdirFile(log, sourcePath, tagBnp)
if (needUpdateBnp): if (needUpdateBnp):
subRet = 0
open(tagBnp, 'a').close()
os.utime(tagBnp, None)
if (category["StreamedPackages"]): if (category["StreamedPackages"]):
printLog(log, "SNP " + targetBnp) printLog(log, "SNP " + targetBnp)
# cwDir = os.getcwd().replace("\\", "/") # cwDir = os.getcwd().replace("\\", "/")
# toolDir = os.path.dirname(Lzma).replace("\\", "/") # toolDir = os.path.dirname(Lzma).replace("\\", "/")
# os.chdir(toolDir) # os.chdir(toolDir)
subprocess.call([ SnpMake, "-p", sourcePath, targetBnp, ClientPatchDirectory + "/stream" ] + package[1][1:]) subRet = subprocess.call([ SnpMake, "-p", sourcePath, targetBnp, ClientPatchDirectory + "/stream" ] + package[1][1:])
# os.chdir(cwDir) # os.chdir(cwDir)
else: else:
printLog(log, "BNP " + targetBnp) printLog(log, "BNP " + targetBnp)
subprocess.call([ BnpMake, "-p", sourcePath, "-o", targetBnp ] + package[1][1:]) subRet = subprocess.call([ BnpMake, "-p", sourcePath, "-o", targetBnp ] + package[1][1:])
if (subRet != 0):
os.remove(tagBnp)
else: else:
printLog(log, "SKIP " + targetBnp) printLog(log, "SKIP " + targetBnp)
printLog(log, "") printLog(log, "")

@ -74,6 +74,13 @@ else:
printLog(log, ">>> Copy Shape <<<") printLog(log, ">>> Copy Shape <<<")
copyFilesExtNoTreeIfNeeded(log, shapeDirectory, ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory, ".shape") copyFilesExtNoTreeIfNeeded(log, shapeDirectory, ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory, ".shape")
printLog(log, ">>> Copy non-ShadowSkin non-CLodTex Shape <<<")
shapeDirectory = ExportBuildDirectory + "/" + ShapeNotOptimizedExportDirectory
mkPath(log, shapeDirectory)
mkPath(log, ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory)
copyFilesExtNoTreeIfNeeded(log, shapeDirectory, ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory, ".shape")
shapeDirectory = ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory
# copy lightmap_not_optimized to lightmap # copy lightmap_not_optimized to lightmap
printLog(log, ">>> Optimize lightmaps <<<") printLog(log, ">>> Optimize lightmaps <<<")
loPathLightmapsOriginal = ExportBuildDirectory + "/" + ShapeLightmapNotOptimizedExportDirectory loPathLightmapsOriginal = ExportBuildDirectory + "/" + ShapeLightmapNotOptimizedExportDirectory

@ -338,6 +338,9 @@ R2EDMaxMapScale = 8.0;
WindowSnapInvert = 0; WindowSnapInvert = 0;
WindowSnapDistance = 10; WindowSnapDistance = 10;
WindowSnapDistance_min = 0;
WindowSnapDistance_max = 50;
WindowSnapDistance_step = 1;
////////////////// //////////////////
// SOUND CONFIG // // SOUND CONFIG //

@ -1120,7 +1120,7 @@ void CCharacterCL::computeAnimSet()
// Use the generic method to compute the animation set. // Use the generic method to compute the animation set.
if(!::computeAnimSet(_CurrentAnimSet[MOVE], _Mode, _Sheet->getAnimSetBaseName(), _Items[SLOTTYPE::LEFT_HAND_SLOT].Sheet, _Items[SLOTTYPE::RIGHT_HAND_SLOT].Sheet, !modeWithHiddenItems())) if(!::computeAnimSet(_CurrentAnimSet[MOVE], _Mode, _Sheet->getAnimSetBaseName(), _Items[SLOTTYPE::LEFT_HAND_SLOT].Sheet, _Items[SLOTTYPE::RIGHT_HAND_SLOT].Sheet, !modeWithHiddenItems()))
{ {
//nlwarning("CH:computeAnimSet:%d: pb when trying to compute the animset. Sheet Id '%u(%s)'.", _Slot, _SheetId.asInt(), _SheetId.toString().c_str()); nlwarning("CH:computeAnimSet:%d: pb when trying to compute the animset. Sheet Id '%u(%s)'.", _Slot, _SheetId.asInt(), _SheetId.toString().c_str());
} }
}// computeAnimSet // }// computeAnimSet //
@ -3360,7 +3360,7 @@ void CCharacterCL::showOrHideBodyParts( bool objectsVisible )
lHandInstIdx = SLOTTYPE::LEFT_HAND_SLOT; lHandInstIdx = SLOTTYPE::LEFT_HAND_SLOT;
// hide gloves(armor) if player has magician amplifier // hide gloves(armor) if player has magician amplifier
if( _Items[rHandInstIdx].Sheet && (_Items[rHandInstIdx].Sheet->ItemType == ITEM_TYPE::MAGICIAN_STAFF) ) if( _Items[SLOTTYPE::RIGHT_HAND_SLOT].Sheet && (_Items[SLOTTYPE::RIGHT_HAND_SLOT].Sheet->ItemType == ITEM_TYPE::MAGICIAN_STAFF) )
{ {
if( !_Instances[SLOTTYPE::HANDS_SLOT].Current.empty() ) if( !_Instances[SLOTTYPE::HANDS_SLOT].Current.empty() )
_Instances[SLOTTYPE::HANDS_SLOT].Current.hide(); _Instances[SLOTTYPE::HANDS_SLOT].Current.hide();
@ -3378,8 +3378,9 @@ void CCharacterCL::showOrHideBodyParts( bool objectsVisible )
if( !objectsVisible ) if( !objectsVisible )
{ {
// Right Hand // Right Hand
nlassert(SLOTTYPE::RIGHT_HAND_SLOT < _Items.size() && SLOTTYPE::LEFT_HAND_SLOT < _Items.size());
if(rHandInstIdx<_Instances.size()) if(rHandInstIdx<_Instances.size())
if( !(_Items[rHandInstIdx].Sheet && _Items[rHandInstIdx].Sheet->NeverHideWhenEquipped ) ) if( !(_Items[SLOTTYPE::RIGHT_HAND_SLOT].Sheet && _Items[SLOTTYPE::RIGHT_HAND_SLOT].Sheet->NeverHideWhenEquipped ) )
if(!_Instances[rHandInstIdx].Current.empty()) if(!_Instances[rHandInstIdx].Current.empty())
{ {
_Instances[rHandInstIdx].Current.hide(); _Instances[rHandInstIdx].Current.hide();
@ -3387,7 +3388,7 @@ void CCharacterCL::showOrHideBodyParts( bool objectsVisible )
} }
// Left Hand // Left Hand
if(lHandInstIdx <_Instances.size()) if(lHandInstIdx <_Instances.size())
if( !(_Items[lHandInstIdx].Sheet && _Items[lHandInstIdx].Sheet->NeverHideWhenEquipped ) ) if( !(_Items[SLOTTYPE::LEFT_HAND_SLOT].Sheet && _Items[SLOTTYPE::LEFT_HAND_SLOT].Sheet->NeverHideWhenEquipped ) )
if(!_Instances[lHandInstIdx].Current.empty()) if(!_Instances[lHandInstIdx].Current.empty())
{ {
_Instances[lHandInstIdx].Current.hide(); _Instances[lHandInstIdx].Current.hide();
@ -9293,14 +9294,14 @@ const char *CCharacterCL::getBoneNameFromBodyPart(BODY::TBodyPart part, BODY::TS
const CItemSheet *CCharacterCL::getRightHandItemSheet() const const CItemSheet *CCharacterCL::getRightHandItemSheet() const
{ {
if (_RHandInstIdx == CEntityCL::BadIndex) return NULL; if (_RHandInstIdx == CEntityCL::BadIndex) return NULL;
return _Items[_RHandInstIdx].Sheet; return _Items[SLOTTYPE::RIGHT_HAND_SLOT].Sheet;
} }
// ********************************************************************************************* // *********************************************************************************************
const CItemSheet *CCharacterCL::getLeftHandItemSheet() const const CItemSheet *CCharacterCL::getLeftHandItemSheet() const
{ {
if (_LHandInstIdx == CEntityCL::BadIndex) return NULL; if (_LHandInstIdx == CEntityCL::BadIndex) return NULL;
return _Items[_LHandInstIdx].Sheet; return _Items[SLOTTYPE::LEFT_HAND_SLOT].Sheet;
} }
// *************************************************************************** // ***************************************************************************

@ -465,7 +465,13 @@ CClientConfig::CClientConfig()
SoundOn = true; // Default is with sound. SoundOn = true; // Default is with sound.
DriverSound = SoundDrvAuto; DriverSound = SoundDrvAuto;
SoundForceSoftwareBuffer = true; SoundForceSoftwareBuffer = true;
SoundOutGameMusic = "main menu loop.ogg"; StartMusic = "main theme air.ogg"; // Use at game startup (originally no music)
EmptySlotMusic = "loading music loop.ogg"; // Use in character selection for empty slots
LoadingMusic = "main menu loop.ogg"; // Main loading used after leaving character selection, and when going back to character selection
KamiTeleportMusic = "kami teleport.ogg"; // Kami teleport
KaravanTeleportMusic = "karavan teleport.ogg"; // Karavan teleport
TeleportLoadingMusic = "loading music loop.ogg"; // Use for generic teleportations
DeathMusic = "death.ogg"; // Player death
SoundSFXVolume = 1.f; SoundSFXVolume = 1.f;
SoundGameMusicVolume = 1.f; SoundGameMusicVolume = 1.f;
SoundTPFade = 500; SoundTPFade = 500;
@ -476,7 +482,7 @@ CClientConfig::CClientConfig()
UserEntitySoundLevel = 0.5f; // Default volume for sound in 1st person UserEntitySoundLevel = 0.5f; // Default volume for sound in 1st person
UseEax = true; // Default to use EAX; UseEax = true; // Default to use EAX;
UseADPCM = false; // Defualt to PCM sample, NO ADPCM UseADPCM = false; // Defualt to PCM sample, NO ADPCM
MaxTrack = 32; // DEfault to 32 track MaxTrack = 32; // Default to 32 track
ColorShout = CRGBA(150,0,0,255); // Default Shout color. ColorShout = CRGBA(150,0,0,255); // Default Shout color.
ColorTalk = CRGBA(255,255,255,255); // Default Talk color. ColorTalk = CRGBA(255,255,255,255); // Default Talk color.
@ -1248,7 +1254,13 @@ void CClientConfig::setValues()
// SoundForceSoftwareBuffer // SoundForceSoftwareBuffer
READ_BOOL_FV(SoundForceSoftwareBuffer); READ_BOOL_FV(SoundForceSoftwareBuffer);
// SoundOutGameMusic // SoundOutGameMusic
READ_STRING_DEV(SoundOutGameMusic) READ_STRING_DEV(StartMusic)
READ_STRING_DEV(EmptySlotMusic)
READ_STRING_DEV(LoadingMusic)
READ_STRING_DEV(KamiTeleportMusic)
READ_STRING_DEV(KaravanTeleportMusic)
READ_STRING_DEV(TeleportLoadingMusic)
READ_STRING_DEV(DeathMusic)
// SoundSFXVolume // SoundSFXVolume
READ_FLOAT_FV(SoundSFXVolume); READ_FLOAT_FV(SoundSFXVolume);
// SoundGameMusicVolume // SoundGameMusicVolume

@ -348,8 +348,14 @@ struct CClientConfig
/// SoundForceSoftwareBuffer /// SoundForceSoftwareBuffer
bool SoundForceSoftwareBuffer; bool SoundForceSoftwareBuffer;
/// The outgame music file /// Music files
string SoundOutGameMusic; string StartMusic;
string EmptySlotMusic;
string LoadingMusic;
string KamiTeleportMusic;
string KaravanTeleportMusic;
string TeleportLoadingMusic;
string DeathMusic;
/// The Sound SFX Volume (0-1) (ie all but music) /// The Sound SFX Volume (0-1) (ie all but music)
float SoundSFXVolume; float SoundSFXVolume;

@ -213,6 +213,21 @@ void CCharacterSheet::build(const NLGEORGES::UFormElm &item)
// IN LEFT HAND // IN LEFT HAND
readEquipment(item, "Basics.Equipment.HandL", ObjectInLeftHand); readEquipment(item, "Basics.Equipment.HandL", ObjectInLeftHand);
if (!ObjectInRightHand.IdItem)
{
std::string right;
item.getValueByName(right, "item_right");
if (!right.empty())
ObjectInRightHand.IdItem = ClientSheetsStrings.add(NLMISC::toLower(right));
}
if (!ObjectInLeftHand.IdItem)
{
std::string left;
item.getValueByName(left, "item_left");
if (!left.empty())
ObjectInLeftHand.IdItem = ClientSheetsStrings.add(NLMISC::toLower(left));
}
// Get the animation set Base Name. // Get the animation set Base Name.
string AnimSetBaseName; string AnimSetBaseName;

@ -273,6 +273,73 @@ void setOutGameFullScreen()
CViewRenderer::getInstance()->setInterfaceScale(1.0f, 1024, 768); CViewRenderer::getInstance()->setInterfaceScale(1.0f, 1024, 768);
} }
// ------------------------------------------------------------------------------------------------
class CSoundGlobalMenu
{
public:
CSoundGlobalMenu()
{
_MusicWantedAsync= false;
_NbFrameBeforeChange= NbFrameBeforeChangeMax;
}
void reset();
void setMusic(const string &music, bool async);
void updateSound();
private:
string _MusicPlayed;
string _MusicWanted;
bool _MusicWantedAsync;
sint _NbFrameBeforeChange;
enum {NbFrameBeforeChangeMax= 10};
};
void CSoundGlobalMenu::reset()
{
_MusicPlayed.clear();
_MusicWanted.clear();
}
void CSoundGlobalMenu::updateSound()
{
// **** update the music played
// The first music played is the music played at loading, before select char
if (_MusicPlayed.empty())
_MusicPlayed = toLower(LoadingMusic.empty() ? ClientCfg.StartMusic : LoadingMusic);
if (_MusicWanted.empty())
_MusicWanted = toLower(LoadingMusic.empty() ? ClientCfg.StartMusic : LoadingMusic);
// because music is changed when the player select other race for instance,
// wait the 3D to load (stall some secs)
// if the wanted music is the same as the one currently playing, just continue playing
if(_MusicPlayed!=_MusicWanted)
{
// wait nbFrameBeforeChangeMax before actually changing the music
_NbFrameBeforeChange--;
if(_NbFrameBeforeChange<=0)
{
_MusicPlayed= _MusicWanted;
// play the music
if (SoundMngr != NULL)
SoundMngr->playMusic(_MusicPlayed, 500, _MusicWantedAsync, true, true);
}
}
// **** update mngr
if (SoundMngr != NULL)
SoundMngr->update();
}
void CSoundGlobalMenu::setMusic(const string &music, bool async)
{
_MusicWanted= toLower(music);
_MusicWantedAsync= async;
// reset the counter
_NbFrameBeforeChange= NbFrameBeforeChangeMax;
}
static CSoundGlobalMenu SoundGlobalMenu;
// New version of the menu after the server connection // New version of the menu after the server connection
// //
@ -405,6 +472,8 @@ bool connection (const string &cookie, const string &fsaddr)
InterfaceState = GLOBAL_MENU; InterfaceState = GLOBAL_MENU;
} }
// No loading music here, this is right before character selection, using the existing music
// Create the loading texture. We can't do that before because we need to add search path first. // Create the loading texture. We can't do that before because we need to add search path first.
beginLoading (LoadBackground); beginLoading (LoadBackground);
UseEscapeDuringLoading = USE_ESCAPE_DURING_LOADING; UseEscapeDuringLoading = USE_ESCAPE_DURING_LOADING;
@ -507,6 +576,7 @@ bool reconnection()
ProgressBar.setFontFactor(1.0f); ProgressBar.setFontFactor(1.0f);
// Init out game // Init out game
SoundGlobalMenu.reset();
pIM->initOutGame(); pIM->initOutGame();
// Hide cursor for interface // Hide cursor for interface
@ -522,6 +592,9 @@ bool reconnection()
FarTP.setOutgame(); FarTP.setOutgame();
if (SoundMngr)
SoundMngr->setupFadeSound(1.0f, 1.0f);
// these two globals sequence GlobalMenu to display the character select dialog // these two globals sequence GlobalMenu to display the character select dialog
WaitServerAnswer = true; WaitServerAnswer = true;
userChar = true; userChar = true;
@ -556,6 +629,8 @@ bool reconnection()
// this also kicks the state machine to sendReady() so we stop spinning in farTPmainLoop // this also kicks the state machine to sendReady() so we stop spinning in farTPmainLoop
FarTP.setIngame(); FarTP.setIngame();
// Not loading music here, this is before character selection, keep existing music
// Create the loading texture. We can't do that before because we need to add search path first. // Create the loading texture. We can't do that before because we need to add search path first.
beginLoading (LoadBackground); beginLoading (LoadBackground);
UseEscapeDuringLoading = USE_ESCAPE_DURING_LOADING; UseEscapeDuringLoading = USE_ESCAPE_DURING_LOADING;
@ -731,66 +806,6 @@ std::string buildPlayerNameForSaveFile(const ucstring &playerNameIn)
return ret; return ret;
} }
// ------------------------------------------------------------------------------------------------
class CSoundGlobalMenu
{
public:
CSoundGlobalMenu()
{
_MusicWantedAsync= false;
_NbFrameBeforeChange= NbFrameBeforeChangeMax;
}
void setMusic(const string &music, bool async);
void updateSound();
private:
string _MusicPlayed;
string _MusicWanted;
bool _MusicWantedAsync;
sint _NbFrameBeforeChange;
enum {NbFrameBeforeChangeMax= 10};
};
void CSoundGlobalMenu::updateSound()
{
// **** update the music played
// The first music played is the music played at loading, before select char
if(_MusicPlayed.empty())
_MusicPlayed= toLower(ClientCfg.SoundOutGameMusic);
if(_MusicWanted.empty())
_MusicWanted= toLower(ClientCfg.SoundOutGameMusic);
// because music is changed when the player select other race for instance,
// wait the 3D to load (stall some secs)
// if the wanted music is the same as the one currently playing, just continue playing
if(_MusicPlayed!=_MusicWanted)
{
// wait nbFrameBeforeChangeMax before actually changing the music
_NbFrameBeforeChange--;
if(_NbFrameBeforeChange<=0)
{
_MusicPlayed= _MusicWanted;
// play the music
if (SoundMngr != NULL)
SoundMngr->playMusic(_MusicPlayed, 500, _MusicWantedAsync, true, true);
}
}
// **** update mngr
if (SoundMngr != NULL)
SoundMngr->update();
}
void CSoundGlobalMenu::setMusic(const string &music, bool async)
{
_MusicWanted= toLower(music);
_MusicWantedAsync= async;
// reset the counter
_NbFrameBeforeChange= NbFrameBeforeChangeMax;
}
static CSoundGlobalMenu SoundGlobalMenu;
static bool LuaBGDSuccessFlag = true; // tmp, for debug static bool LuaBGDSuccessFlag = true; // tmp, for debug
@ -2041,8 +2056,8 @@ public:
fromString(getParam(Params, "async"), async); fromString(getParam(Params, "async"), async);
// if empty name, return to default mode // if empty name, return to default mode
if(sName.empty()) if (sName.empty())
sName= ClientCfg.SoundOutGameMusic; sName = ClientCfg.EmptySlotMusic;
// change the music // change the music
SoundGlobalMenu.setMusic(sName, async); SoundGlobalMenu.setMusic(sName, async);

@ -162,7 +162,9 @@ CDecal::CDecal()
{ {
DecalAttenuationVertexProgram = new CVertexProgramDecalAttenuation(); DecalAttenuationVertexProgram = new CVertexProgramDecalAttenuation();
} }
_ShadowMap = new CShadowMap(&(((CSceneUser *) Scene)->getScene().getRenderTrav().getShadowMapManager()));
// initialized in render() as depends on scene
_ShadowMap = NULL;
_Material.initUnlit(); _Material.initUnlit();
_Diffuse = CRGBA::White; _Diffuse = CRGBA::White;
_Emissive = CRGBA::Black; _Emissive = CRGBA::Black;
@ -251,7 +253,11 @@ CRGBA CDecal::getDiffuse() const
// **************************************************************************** // ****************************************************************************
CDecal::~CDecal() CDecal::~CDecal()
{ {
delete _ShadowMap; if (_ShadowMap)
{
delete _ShadowMap;
_ShadowMap = NULL;
}
} }
// **************************************************************************** // ****************************************************************************
@ -527,7 +533,12 @@ void CDecal::render(NL3D::UDriver &/* drv */,
// //
float tileNear = Landscape->getTileNear(); float tileNear = Landscape->getTileNear();
// //
nlassert(_ShadowMap); if (!_ShadowMap)
{
_ShadowMap = new CShadowMap(&(((CSceneUser *) Scene)->getScene().getRenderTrav().getShadowMapManager()));
nlassert(_ShadowMap);
}
_ShadowMap->LocalClipPlanes.resize(4); _ShadowMap->LocalClipPlanes.resize(4);
CVector corners[4] = CVector corners[4] =
{ {

@ -378,6 +378,8 @@ void CEntityCL::SInstanceCL::updateCurrentFromLoading(NL3D::USkeleton Skeleton)
sint stickID = Skeleton.getBoneIdByName(StickPoint); sint stickID = Skeleton.getBoneIdByName(StickPoint);
if(stickID != -1) if(stickID != -1)
Skeleton.stickObject(Current, stickID); Skeleton.stickObject(Current, stickID);
else
nlwarning("Skeleton '%s' is missing bone '%s' for object attachment.", Skeleton.getShapeName().c_str(), StickPoint.c_str());
} }
} }

@ -1112,15 +1112,6 @@ void CFarTP::disconnectFromPreviousShard()
beginLoading (StartBackground); beginLoading (StartBackground);
UseEscapeDuringLoading = false; UseEscapeDuringLoading = false;
// Play music and fade out the Game Sound
if (SoundMngr)
{
// Loading Music Loop.ogg
LoadingMusic = ClientCfg.SoundOutGameMusic;
SoundMngr->playEventMusic(LoadingMusic, CSoundManager::LoadingMusicXFade, true);
SoundMngr->fadeOutGameSound(ClientCfg.SoundTPFade);
}
// Change the tips // Change the tips
selectTipsOfTheDay (rand()); selectTipsOfTheDay (rand());
@ -1129,6 +1120,21 @@ void CFarTP::disconnectFromPreviousShard()
ucstring nmsg("Loading..."); ucstring nmsg("Loading...");
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) ); ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
ProgressBar.progress(0); ProgressBar.progress(0);
// Play music and fade out the Game Sound
if (SoundMngr)
{
SoundMngr->fadeOutGameSound(ClientCfg.SoundTPFade);
// Stop and enable music
SoundMngr->stopMusic(0);
SoundMngr->setupFadeSound(0.0f, 1.0f);
// Loading Music Loop.ogg
LoadingMusic = ClientCfg.LoadingMusic;
// SoundMngr->playEventMusic(LoadingMusic, CSoundManager::LoadingMusicXFade, true);
SoundMngr->playMusic(LoadingMusic, 0, false, true, true);
}
} }
// Disconnect from the FS // Disconnect from the FS

@ -1413,6 +1413,42 @@ void prelogInit()
StereoDisplay->setDriver(Driver); // VR_DRIVER StereoDisplay->setDriver(Driver); // VR_DRIVER
} }
{
H_AUTO(InitRZSound)
// Init the sound manager
nmsg = "Initializing sound manager...";
ProgressBar.newMessage(ClientCfg.buildLoadingString(nmsg));
if (ClientCfg.SoundOn)
{
nlassert(!SoundMngr);
SoundMngr = new CSoundManager(&ProgressBar);
try
{
SoundMngr->init(&ProgressBar);
}
catch(const Exception &e)
{
nlwarning("init : Error when creating 'SoundMngr' : %s", e.what());
delete SoundMngr;
SoundMngr = NULL;
}
// Play Music just after the SoundMngr is inited
if (SoundMngr)
{
// init the SoundMngr with backuped volume
SoundMngr->setSFXVolume(ClientCfg.SoundSFXVolume);
SoundMngr->setGameMusicVolume(ClientCfg.SoundGameMusicVolume);
// Play the login screen music
SoundMngr->playMusic(ClientCfg.StartMusic, 0, true, true, true);
}
}
CPath::memoryCompress(); // Because sound calls addSearchPath
}
nlinfo ("PROFILE: %d seconds for prelogInit", (uint32)(ryzomGetLocalTime ()-initStart)/1000); nlinfo ("PROFILE: %d seconds for prelogInit", (uint32)(ryzomGetLocalTime ()-initStart)/1000);
FPU_CHECKER_ONCE FPU_CHECKER_ONCE
@ -1555,55 +1591,6 @@ void postlogInit()
// set the primitive context // set the primitive context
CPrimitiveContext::instance().CurrentLigoConfig = &LigoConfig; CPrimitiveContext::instance().CurrentLigoConfig = &LigoConfig;
{
H_AUTO(InitRZSound)
// Init the sound manager
nmsg = "Initializing sound manager...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
if(ClientCfg.SoundOn)
{
SoundMngr = new CSoundManager(&ProgressBar);
try
{
SoundMngr->init(&ProgressBar);
}
catch(const Exception &e)
{
nlwarning("init : Error when creating 'SoundMngr' : %s", e.what());
delete SoundMngr;
SoundMngr = NULL;
}
// Play Music just after the SoundMngr is inited
if(SoundMngr)
{
// init the SoundMngr with backuped volume
SoundMngr->setSFXVolume(ClientCfg.SoundSFXVolume);
SoundMngr->setGameMusicVolume(ClientCfg.SoundGameMusicVolume);
// no fadein, and not async because don't work well because of loading in the main thread
// Force use GameMusic volume
const uint fadeInTime= 500;
SoundMngr->playMusic(ClientCfg.SoundOutGameMusic, fadeInTime, false, true, true);
// Because of blocking loading, force the fadeIn
TTime t0= ryzomGetLocalTime();
TTime t1;
while((t1=ryzomGetLocalTime())<t0+fadeInTime)
{
//ProgressBar.progress(1.f);
SoundMngr->updateAudioMixerOnly();
}
}
}
CPath::memoryCompress(); // Because sound call addSearchPath
initLast = initCurrent;
initCurrent = ryzomGetLocalTime();
//nlinfo ("PROFILE: %d seconds (%d total) for Initializing sound manager", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
}
{ {
H_AUTO(InitRZShIdI) H_AUTO(InitRZShIdI)

@ -473,6 +473,27 @@ void initMainLoop()
FPU_CHECKER_ONCE FPU_CHECKER_ONCE
if (SoundMngr)
{
// Loading Music
LoadingMusic = ClientCfg.LoadingMusic;
// SoundMngr->playEventMusic(LoadingMusic, CSoundManager::LoadingMusicXFade, true);
// no fadein, and not async because don't work well because of loading in the main thread
// Force use GameMusic volume
const uint fadeInTime = 500;
SoundMngr->playMusic(LoadingMusic, fadeInTime, false, true, true);
// Because of blocking loading, force the fadeIn
TTime t0 = ryzomGetLocalTime();
TTime t1;
do
{
ProgressBar.progress(0);
SoundMngr->updateAudioMixerOnly();
nlSleep(10);
} while ((t1 = ryzomGetLocalTime()) < t0 + fadeInTime);
}
// Get the interface manager // Get the interface manager
CInterfaceManager *pIM = CInterfaceManager::getInstance(); CInterfaceManager *pIM = CInterfaceManager::getInstance();

@ -2822,24 +2822,6 @@ public:
virtual void execute (CCtrlBase * /* pCaller */, const string &Params) virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
{ {
/* // Previous version (multiple pressed on a desktop change a central window
uint desktop;
fromString(Params, desktop);
if (desktop <MAX_NUM_MODES)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
const string procNames[MAX_NUM_MODES] = { "tb_setexp", "tb_setinfo", "tb_setlab", "tb_setkeys" };
const string dbNames[MAX_NUM_MODES] = { "", "UI:SAVE:CURRENT_INFO_MODE", "UI:SAVE:CURRENT_LAB_MODE", "UI:SAVE:CURRENT_KEY_MODE" };
string sValue;
CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp(dbNames[desktop], false);
if (pNL != NULL)
sValue = NLMISC::toString((sint32)pNL->getValue64());
vector<string> vecStr;
vecStr.push_back(procNames[desktop]);
vecStr.push_back(sValue);
CWidgetManager::getInstance()->runProcedure(procNames[desktop], NULL, vecStr);
}*/
CInterfaceManager *pIM = CInterfaceManager::getInstance(); CInterfaceManager *pIM = CInterfaceManager::getInstance();
CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:gestion_windows")); CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:gestion_windows"));
if (pGC == NULL) if (pGC == NULL)
@ -2850,11 +2832,14 @@ public:
CInterfaceElement *pIE = CWidgetManager::getInstance()->getElementFromId("ui:interface:gestion_windows:close"); CInterfaceElement *pIE = CWidgetManager::getInstance()->getElementFromId("ui:interface:gestion_windows:close");
if (pIE != NULL) pIE->setActive(false); if (pIE != NULL) pIE->setActive(false);
bool switchDesktop = false;
CActionsManager *pAM = &Actions; CActionsManager *pAM = &Actions;
if (!pAM->valide(CAction::CName("set_desktop",Params.c_str()))) if (!pAM->valide(CAction::CName("set_desktop",Params.c_str())))
{ {
pGC->setActive(false); pGC->setActive(false);
_FirstTime = true; _FirstTime = true;
switchDesktop = true;
} }
else // Key is down else // Key is down
{ {
@ -2862,11 +2847,7 @@ public:
if (_FirstTime) if (_FirstTime)
{ {
_FirstTime = false; _FirstTime = false;
switchDesktop = true;
vector<string> vecStr;
vecStr.push_back("tb_setdesktop");
vecStr.push_back(Params);
CWidgetManager::getInstance()->runProcedure("tb_setdesktop", NULL, vecStr);
} }
else // Not the first time else // Not the first time
{ {
@ -2876,6 +2857,13 @@ public:
CWidgetManager::getInstance()->setTopWindow(pGC); CWidgetManager::getInstance()->setTopWindow(pGC);
} }
} }
if (switchDesktop)
{
vector<string> vecStr;
vecStr.push_back("tb_setdesktop");
vecStr.push_back(Params);
CWidgetManager::getInstance()->runProcedure("tb_setdesktop", NULL, vecStr);
}
} }
private: private:
bool _FirstTime; bool _FirstTime;

@ -540,6 +540,9 @@ CCtrlDraggable(param)
_SapBuffIcon = "ico_sap.tga"; _SapBuffIcon = "ico_sap.tga";
_StaBuffIcon = "ico_stamina.tga"; _StaBuffIcon = "ico_stamina.tga";
_FocusBuffIcon = "ico_focus.tga"; _FocusBuffIcon = "ico_focus.tga";
_RegenText = NULL;
_RegenTextValue = 0;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -564,6 +567,11 @@ CDBCtrlSheet::~CDBCtrlSheet()
Driver->deleteTextureFile(_GuildSymb); Driver->deleteTextureFile(_GuildSymb);
_GuildSymb = NULL; _GuildSymb = NULL;
} }
if (_RegenText)
{
delete _RegenText;
_RegenText = NULL;
}
// ensure erase static // ensure erase static
if(this==_CurrMenuSheet) _CurrMenuSheet = NULL; if(this==_CurrMenuSheet) _CurrMenuSheet = NULL;
@ -2045,6 +2053,12 @@ void CDBCtrlSheet::draw()
if (!_LastSheetId) if (!_LastSheetId)
{ {
_RegenTickRange = CTickRange(); _RegenTickRange = CTickRange();
if (_RegenText)
{
delete _RegenText;
_RegenText = NULL;
_RegenTextValue = 0;
}
} }
else else
{ {
@ -2071,6 +2085,36 @@ void CDBCtrlSheet::draw()
{ {
rVR.drawQuad(_RenderLayer + 1, regenTris[tri], backTex, CRGBA::White, false); rVR.drawQuad(_RenderLayer + 1, regenTris[tri], backTex, CRGBA::White, false);
} }
if (!_RegenText) {
_RegenText = new CViewText(CViewBase::TCtorParam());
_RegenText->setId(getId() + ":regen");
_RegenText->setParent(_Parent);
_RegenText->setOverflowText(ucstring(""));
_RegenText->setModulateGlobalColor(false);
_RegenText->setMultiLine(false);
_RegenText->setTextMode(CViewText::ClipWord);
_RegenText->setFontSizing("0", "0");
// TODO: font size / color hardcoded.
_RegenText->setFontSize(8);
_RegenText->setColor(CRGBA::White);
_RegenText->setShadow(true);
_RegenText->setActive(true);
_RegenText->updateTextContext();
}
// TODO: ticks in second hardcoded
uint32 nextValue = _RegenTickRange.EndTick > LastGameCycle ? (_RegenTickRange.EndTick - LastGameCycle) / 10 : 0;
if (_RegenTextValue != nextValue)
{
_RegenTextValue = nextValue;
_RegenText->setText(toString("%d", _RegenTextValue));
_RegenText->updateTextContext();
}
_RegenText->setXReal(_XReal+1);
_RegenText->setYReal(_YReal+2);
_RegenText->setRenderLayer(_RenderLayer+2);
_RegenText->draw();
} }
} }

@ -56,6 +56,7 @@ class COutpostBuildingSheet;
namespace NLGUI namespace NLGUI
{ {
class CViewRenderer; class CViewRenderer;
class CViewText;
} }
class CDBCtrlSheet; class CDBCtrlSheet;
@ -736,6 +737,8 @@ protected:
sint8 _ArmourColorIndex; sint8 _ArmourColorIndex;
CTickRange _RegenTickRange; CTickRange _RegenTickRange;
NLGUI::CViewText *_RegenText;
uint32 _RegenTextValue;
/// D'n'd /// D'n'd
sint32 _DragX, _DragY; sint32 _DragX, _DragY;

@ -1333,15 +1333,18 @@ void CGroupMap::checkCoords()
{ {
if( _AnimalLM[i] ) if( _AnimalLM[i] )
{ {
// update pos
sint32 px, py;
_AnimalPosStates[i]->getPos(px, py);
updateLMPosFromDBPos(_AnimalLM[i], px, py);
if (_IsIsland) if (_IsIsland)
{ {
_AnimalLM[i]->setActive(false); _AnimalLM[i]->setActive(false);
} }
else else if (_AnimalLM[i]->getActive())
{ {
_AnimalLM[i]->setActive(true);
// update texture from animal status // update texture from animal status
CInterfaceManager *pIM= CInterfaceManager::getInstance();
CCDBNodeLeaf *statusNode = NLGUI::CDBManager::getInstance()->getDbProp(toString("SERVER:PACK_ANIMAL:BEAST%d", i) + ":STATUS", false); CCDBNodeLeaf *statusNode = NLGUI::CDBManager::getInstance()->getDbProp(toString("SERVER:PACK_ANIMAL:BEAST%d", i) + ":STATUS", false);
if (statusNode && ANIMAL_STATUS::isInStable((ANIMAL_STATUS::EAnimalStatus)statusNode->getValue32()) ) if (statusNode && ANIMAL_STATUS::isInStable((ANIMAL_STATUS::EAnimalStatus)statusNode->getValue32()) )
{ {
@ -1372,11 +1375,6 @@ void CGroupMap::checkCoords()
case ANIMAL_TYPE::Demon: sPrefix = "uiPATitleDemon"; break; case ANIMAL_TYPE::Demon: sPrefix = "uiPATitleDemon"; break;
} }
_AnimalLM[i]->setDefaultContextHelp(NLMISC::CI18N::get(sPrefix+toString(i+1))); _AnimalLM[i]->setDefaultContextHelp(NLMISC::CI18N::get(sPrefix+toString(i+1)));
// update pos
sint32 px, py;
_AnimalPosStates[i]->getPos(px, py);
updateLMPosFromDBPos(_AnimalLM[i], px, py);
} }
} }
} }
@ -2473,7 +2471,8 @@ void CGroupMap::updateMatchedLandmarks()
std::vector<std::pair<string,string> > params; std::vector<std::pair<string,string> > params;
params.clear(); params.clear();
params.push_back(std::pair<string,string>("id", toString("lm%d", k))); params.push_back(std::pair<string,string>("id", toString("lm%d", k)));
params.push_back(std::pair<string,string>("tooltip", _MatchedLandmarks[k].Title.toUtf8())); // ctrl base expects utf8 string to start with "u:"
params.push_back(std::pair<string,string>("tooltip", "u:" + _MatchedLandmarks[k].Title.toUtf8()));
params.push_back(std::pair<string,string>("index", toString(k))); params.push_back(std::pair<string,string>("index", toString(k)));
CInterfaceGroup *g = CWidgetManager::getInstance()->getParser()->createGroupInstance("lm_search_result", pL->getId(), params); CInterfaceGroup *g = CWidgetManager::getInstance()->getParser()->createGroupInstance("lm_search_result", pL->getId(), params);
@ -2677,7 +2676,7 @@ void CGroupMap::setLandmarkFilter(const std::string &s)
if (!s.empty()) { if (!s.empty()) {
ucstring ucs; ucstring ucs;
ucs.fromUtf8(s); ucs.fromUtf8(s);
splitUCString(toLower(s), ucstring(" "), _LandmarkFilter); splitUCString(toLower(ucs), ucstring(" "), _LandmarkFilter);
} }
// recreate landmarks // recreate landmarks

@ -271,16 +271,16 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event)
{ {
CViewPointer &rIP = *static_cast< CViewPointer* >( CWidgetManager::getInstance()->getPointer() ); CViewPointer &rIP = *static_cast<CViewPointer *>(CWidgetManager::getInstance()->getPointer());
NLGUI::CEventDescriptorMouse eventDesc; NLGUI::CEventDescriptorMouse eventDesc;
sint32 x,y; sint32 x, y;
rIP.getPointerDispPos (x, y); rIP.getPointerDispPos(x, y);
eventDesc.setX (x); eventDesc.setX(x);
eventDesc.setY (y); eventDesc.setY(y);
bool handled= false; bool handled = false;
// button down ? // button down ?
static volatile bool doTest = false; static volatile bool doTest = false;
@ -291,7 +291,7 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event)
{ {
if (_RecoverFocusLost) if (_RecoverFocusLost)
{ {
handled |= updateMousePos((CEventMouse&)event, eventDesc); // must update mouse pos here, handled |= updateMousePos((CEventMouse&)event); // must update mouse pos here,
// because when app window focus is gained by a mouse click, this is // because when app window focus is gained by a mouse click, this is
// the only place where we can retrieve mouse pos before a mouse move // the only place where we can retrieve mouse pos before a mouse move
_RecoverFocusLost = false; _RecoverFocusLost = false;
@ -299,10 +299,19 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event)
if (!handled) if (!handled)
{ {
if (R2::getEditor().isInitialized() if (R2::getEditor().isInitialized()
&& (R2::isEditionCurrent() || R2::getEditor().getCurrentTool()) && (R2::isEditionCurrent() || R2::getEditor().getCurrentTool()))
)
{ {
handled |= R2::getEditor().handleEvent(eventDesc); const NLMISC::CEventMouseDown *mouseDownEvent = static_cast<const NLMISC::CEventMouseDown *>(&event);
if (mouseDownEvent->Button & NLMISC::leftButton)
{
eventDesc.setEventTypeExtended(CEventDescriptorMouse::mouseleftdown);
handled |= R2::getEditor().handleEvent(eventDesc);
}
if (mouseDownEvent->Button & NLMISC::rightButton)
{
eventDesc.setEventTypeExtended(CEventDescriptorMouse::mouserightdown);
handled |= R2::getEditor().handleEvent(eventDesc);
}
} }
} }
handled |= inputHandler.handleMouseButtonDownEvent( event ); handled |= inputHandler.handleMouseButtonDownEvent( event );
@ -321,7 +330,7 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event)
// mouse move? // mouse move?
else if(event == EventMouseMoveId) else if(event == EventMouseMoveId)
{ {
handled |= updateMousePos((CEventMouse&)event, eventDesc); handled |= updateMousePos((CEventMouse&)event);
} }
else if (event == EventMouseWheelId) else if (event == EventMouseWheelId)
{ {
@ -330,19 +339,77 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event)
} }
// if Event not handled, post to Action Manager // if Event not handled, post to Action Manager
if( !handled ) if (!handled)
{ {
bool handled = false;
if (R2::getEditor().isInitialized() if (R2::getEditor().isInitialized()
&& (R2::isEditionCurrent() || R2::getEditor().getCurrentTool()) && (R2::isEditionCurrent() || R2::getEditor().getCurrentTool()))
)
{ {
handled = R2::getEditor().handleEvent(eventDesc); if (event == EventMouseDownId)
{
const NLMISC::CEventMouseDown *mouseDownEvent = static_cast<const NLMISC::CEventMouseDown *>(&event);
if (mouseDownEvent->Button & NLMISC::leftButton)
{
eventDesc.setEventTypeExtended(CEventDescriptorMouse::mouseleftdown);
handled |= R2::getEditor().handleEvent(eventDesc);
}
if (mouseDownEvent->Button & NLMISC::rightButton)
{
eventDesc.setEventTypeExtended(CEventDescriptorMouse::mouserightdown);
handled |= R2::getEditor().handleEvent(eventDesc);
}
}
else if (event == EventMouseUpId)
{
const NLMISC::CEventMouseUp *mouseUpEvent = static_cast<const NLMISC::CEventMouseUp *>(&event);
if (mouseUpEvent->Button & NLMISC::leftButton)
{
eventDesc.setEventTypeExtended(CEventDescriptorMouse::mouseleftup);
handled |= R2::getEditor().handleEvent(eventDesc);
}
if (mouseUpEvent->Button & NLMISC::rightButton)
{
eventDesc.setEventTypeExtended(CEventDescriptorMouse::mouserightup);
handled |= R2::getEditor().handleEvent(eventDesc);
}
}
else if (event == EventMouseDblClkId)
{
const NLMISC::CEventMouseDblClk *mouseDblClkEvent = static_cast<const NLMISC::CEventMouseDblClk *>(&event);
if (mouseDblClkEvent->Button & NLMISC::leftButton)
{
eventDesc.setEventTypeExtended(CEventDescriptorMouse::mouseleftdblclk);
handled |= R2::getEditor().handleEvent(eventDesc);
}
if (mouseDblClkEvent->Button & NLMISC::rightButton)
{
eventDesc.setEventTypeExtended(CEventDescriptorMouse::mouserightdblclk);
handled |= R2::getEditor().handleEvent(eventDesc);
}
}
else
{
if (event == EventMouseWheelId)
{
const NLMISC::CEventMouseWheel *wheelEvent = static_cast<const NLMISC::CEventMouseWheel *>(&event);
eventDesc.setEventTypeExtended(CEventDescriptorMouse::mousewheel);
eventDesc.setWheel(wheelEvent->Direction ? 1 : -1);
handled = R2::getEditor().handleEvent(eventDesc);
}
else if (event == EventMouseMoveId)
{
eventDesc.setEventTypeExtended(CEventDescriptorMouse::mousemove);
handled = R2::getEditor().handleEvent(eventDesc);
}
else
{
nlwarning("R2 unknown mouse event '%s'", event.toString().c_str());
}
}
} }
if (!handled) if (!handled)
{ {
// post to Action Manager // post to Action Manager
FilteredEventServer.postEvent( event.clone() ); FilteredEventServer.postEvent(event.clone());
} }
} }
} }
@ -355,7 +422,7 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event)
// *************************************************************************** // ***************************************************************************
bool CInputHandlerManager::updateMousePos(NLMISC::CEventMouse &event, NLGUI::CEventDescriptorMouse &eventDesc) bool CInputHandlerManager::updateMousePos(NLMISC::CEventMouse &event)
{ {
if (!IsMouseFreeLook()) if (!IsMouseFreeLook())
return inputHandler.handleMouseMoveEvent( event ); return inputHandler.handleMouseMoveEvent( event );

@ -181,7 +181,7 @@ private:
void parseKey(xmlNodePtr cur, std::vector<CComboKey> &out); void parseKey(xmlNodePtr cur, std::vector<CComboKey> &out);
// return true if handled // return true if handled
bool updateMousePos(NLMISC::CEventMouse &event, NLGUI::CEventDescriptorMouse &eventDesc); bool updateMousePos(NLMISC::CEventMouse &event);
NLGUI::CInputHandler inputHandler; NLGUI::CInputHandler inputHandler;

@ -1044,6 +1044,10 @@ void CInterfaceManager::initInGame()
gc->setTarget(gc->getSavedTarget()); gc->setTarget(gc->getSavedTarget());
} }
// rebuild mp3 player playlist if user reselected a char (songs are already scanned)
CAHManager::getInstance()->runActionHandler("music_player", NULL, "update_playlist");
CAHManager::getInstance()->runActionHandler("music_player", NULL, "stop");
CCDBNodeLeaf *node = NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CHATLOG_STATE", false); CCDBNodeLeaf *node = NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CHATLOG_STATE", false);
if (node) if (node)
{ {

@ -3648,15 +3648,23 @@ void CInventoryManager::onTradeChangeSession()
// *************************************************************************** // ***************************************************************************
void CInventoryManager::updateItemInfoQueue() void CInventoryManager::updateItemInfoQueue()
{ {
if (!ConnectionReadySent) // CONNECTION:READY not yet sent, so we cannot send requests yet!
{
// Caused by CNetworkConnection::reinit, and NLMISC::CCDBNodeBranch::resetData
// TODO: Item sheets are effectively being set to 0, any way to detect this in particular?
// Slots with sheet 0 won't have any info to request anyway!
// Remove this check in favour of the assert lower down when properly implemented.
nlwarning("Update item info queue (%i), but connection not ready", (int)_ItemInfoWaiters.size());
return;
}
// CONNECTION:READY not yet sent, so we cannot send requests yet!
nlassert(ConnectionReadySent || !_ItemInfoWaiters.size());
// For All waiters, look if one need update. // For All waiters, look if one need update.
TItemInfoWaiters::iterator it; TItemInfoWaiters::iterator it;
for(it= _ItemInfoWaiters.begin();it!=_ItemInfoWaiters.end();it++) for(it= _ItemInfoWaiters.begin();it!=_ItemInfoWaiters.end();it++)
{ {
/* \todo yoyo remove: temp patch to be sure that the client does not send messages before the
CONNECTION:READY is sent
*/
nlassert(ConnectionReadySent);
IItemInfoWaiter *waiter=*it; IItemInfoWaiter *waiter=*it;
uint itemSlotId= waiter->ItemSlotId; uint itemSlotId= waiter->ItemSlotId;
TItemInfoMap::iterator it= _ItemInfoMap.find(itemSlotId); TItemInfoMap::iterator it= _ItemInfoMap.find(itemSlotId);

@ -28,6 +28,9 @@
#include "interface_manager.h" #include "interface_manager.h"
#include "../client_cfg.h" #include "../client_cfg.h"
#include "nel/misc/thread.h"
#include "nel/misc/mutex.h"
using namespace std; using namespace std;
using namespace NLMISC; using namespace NLMISC;
using namespace NL3D; using namespace NL3D;
@ -48,6 +51,88 @@ extern UDriver *Driver;
#define MP3_SAVE_REPEAT "UI:SAVE:MP3_REPEAT" #define MP3_SAVE_REPEAT "UI:SAVE:MP3_REPEAT"
CMusicPlayer MusicPlayer; CMusicPlayer MusicPlayer;
static NLMISC::CUnfairMutex MusicPlayerMutex;
// ***************************************************************************
class CMusicPlayerWorker : public NLMISC::IRunnable
{
private:
bool _Running;
IThread *_Thread;
std::vector<std::string> _Files;
public:
CMusicPlayerWorker(): _Running(false), _Thread(NULL)
{
}
~CMusicPlayerWorker()
{
_Running = false;
if (_Thread)
{
_Thread->terminate();
delete _Thread;
_Thread = NULL;
}
}
bool isRunning() const { return _Running; }
void run()
{
_Running = true;
uint i = 0;
while(_Running && SoundMngr && i < _Files.size())
{
// get copy incase _Files changes
std::string filename(_Files[i]);
std::string title;
float length;
if (SoundMngr->getMixer()->getSongTitle(filename, title, length))
{
MusicPlayer.updateSong(filename, title, length);
}
++i;
}
_Running = false;
_Files.clear();
}
// called from GUI
void getSongsInfo(const std::vector<std::string> &filenames)
{
if (_Thread)
{
stopThread();
}
_Files = filenames;
_Thread = IThread::create(this);
nlassert(_Thread != NULL);
_Thread->start();
}
void stopThread()
{
_Running = false;
if (_Thread)
{
_Thread->wait();
delete _Thread;
_Thread = NULL;
}
}
};
static CMusicPlayerWorker MusicPlayerWorker;
// *************************************************************************** // ***************************************************************************
@ -69,11 +154,14 @@ bool CMusicPlayer::isShuffleEnabled() const
return (NLGUI::CDBManager::getInstance()->getDbProp(MP3_SAVE_SHUFFLE)->getValue32() == 1); return (NLGUI::CDBManager::getInstance()->getDbProp(MP3_SAVE_SHUFFLE)->getValue32() == 1);
} }
// *************************************************************************** // ***************************************************************************
void CMusicPlayer::playSongs (const std::vector<CSongs> &songs) void CMusicPlayer::playSongs (const std::vector<std::string> &filenames)
{ {
_Songs = songs; _Songs.clear();
for (uint i=0; i<filenames.size(); i++)
{
_Songs.push_back(CSongs(filenames[i], CFile::getFilename(filenames[i]), 0.f));
}
// reset song index if out of bounds // reset song index if out of bounds
if (_CurrentSongIndex > _Songs.size()) if (_CurrentSongIndex > _Songs.size())
@ -85,26 +173,113 @@ void CMusicPlayer::playSongs (const std::vector<CSongs> &songs)
rebuildPlaylist(); rebuildPlaylist();
// If pause, stop, else play will resume // If pause, stop, else play will resume
if (_State == Paused) if (_State == Paused || _Songs.empty())
_State = Stopped; stop();
// get song title/duration using worker thread
MusicPlayerWorker.getSongsInfo(filenames);
} }
// *************************************************************************** // ***************************************************************************
void CMusicPlayer::updatePlaylist(sint prevIndex) void CMusicPlayer::updatePlaylist(uint index, bool state)
{ {
CInterfaceElement *pIE; if (index >= _Songs.size()) return;
std::string rowId;
std::string rowId = toString("%s:s%d:bg", MP3_PLAYER_PLAYLIST_LIST, index);
CInterfaceElement *pIE = dynamic_cast<CInterfaceElement*>(CWidgetManager::getInstance()->getElementFromId(rowId));
if (pIE) pIE->setActive(state);
}
void CMusicPlayer::updatePlaylist(sint prevIndex)
{
if (prevIndex >= 0 && prevIndex < _Songs.size()) if (prevIndex >= 0 && prevIndex < _Songs.size())
{ {
rowId = toString("%s:s%d:bg", MP3_PLAYER_PLAYLIST_LIST, prevIndex); updatePlaylist(prevIndex, false);
pIE = dynamic_cast<CInterfaceElement*>(CWidgetManager::getInstance()->getElementFromId(rowId)); }
if (pIE) pIE->setActive(false);
updatePlaylist(_CurrentSongIndex, true);
}
// ***************************************************************************
// called from worker thread
void CMusicPlayer::updateSong(const std::string filename, const std::string title, float length)
{
CAutoMutex<CUnfairMutex> mutex(MusicPlayerMutex);
_SongUpdateQueue.push_back(CSongs(filename, title, length));
}
// ***************************************************************************
// called from GUI
void CMusicPlayer::updateSongs()
{
CAutoMutex<CUnfairMutex> mutex(MusicPlayerMutex);
if (!_SongUpdateQueue.empty())
{
for(uint i = 0; i < _SongUpdateQueue.size(); ++i)
{
updateSong(_SongUpdateQueue[i]);
}
_SongUpdateQueue.clear();
}
}
// ***************************************************************************
void CMusicPlayer::updateSong(const CSongs &song)
{
uint index = 0;
while(index < _Songs.size())
{
if (_Songs[index].Filename == song.Filename)
{
_Songs[index].Title = song.Title;
_Songs[index].Length = song.Length;
break;
}
++index;
}
if (index == _Songs.size())
{
nlwarning("Unknown song file '%s'", song.Filename.c_str());
return;
}
std::string rowId(toString("%s:s%d", MP3_PLAYER_PLAYLIST_LIST, index));
CInterfaceGroup *pIG = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(rowId));
if (!pIG)
{
nlwarning("Playlist row '%s' not found", rowId.c_str());
return;
} }
rowId = toString("%s:s%d:bg", MP3_PLAYER_PLAYLIST_LIST, _CurrentSongIndex); CViewText *pVT;
pIE = dynamic_cast<CInterfaceElement*>(CWidgetManager::getInstance()->getElementFromId(rowId)); pVT = dynamic_cast<CViewText *>(pIG->getView(TEMPLATE_PLAYLIST_SONG_TITLE));
if (pIE) pIE->setActive(true); if (pVT)
{
pVT->setHardText(song.Title);
}
else
{
nlwarning("title element '%s' not found", TEMPLATE_PLAYLIST_SONG_TITLE);
}
pVT = dynamic_cast<CViewText *>(pIG->getView(TEMPLATE_PLAYLIST_SONG_DURATION));
if (pVT)
{
uint min = (sint32)(song.Length / 60) % 60;
uint sec = (sint32)(song.Length) % 60;
uint hour = song.Length / 3600;
std::string duration(toString("%02d:%02d", min, sec));
if (hour > 0)
duration = toString("%02d:", hour) + duration;
pVT->setHardText(duration);
}
else
{
nlwarning("duration element '%s' not found", TEMPLATE_PLAYLIST_SONG_DURATION);
}
} }
// *************************************************************************** // ***************************************************************************
@ -131,12 +306,16 @@ void CMusicPlayer::rebuildPlaylist()
_CurrentSongIndex = i; _CurrentSongIndex = i;
} }
uint min = (sint32)(_Songs[i].Length / 60) % 60; std::string duration("--:--");
uint sec = (sint32)(_Songs[i].Length) % 60; if (_Songs[i].Length > 0)
uint hour = _Songs[i].Length / 3600; {
std::string duration(toString("%02d:%02d", min, sec)); uint min = (sint32)(_Songs[i].Length / 60) % 60;
if (hour > 0) uint sec = (sint32)(_Songs[i].Length) % 60;
duration = toString("%02d:", hour) + duration; uint hour = _Songs[i].Length / 3600;
duration = toString("%02d:%02d", min, sec);
if (hour > 0)
duration = toString("%02d:", hour) + duration;
}
vector< pair<string, string> > vParams; vector< pair<string, string> > vParams;
vParams.push_back(pair<string, string>("id", "s" + toString(i))); vParams.push_back(pair<string, string>("id", "s" + toString(i)));
@ -176,6 +355,17 @@ void CMusicPlayer::play (sint index)
if(!SoundMngr) if(!SoundMngr)
return; return;
if (_Songs.empty())
{
index = 0;
createPlaylistFromMusic();
}
if (_Songs.empty())
{
stop();
return;
}
sint prevSongIndex = _CurrentSongIndex; sint prevSongIndex = _CurrentSongIndex;
@ -244,11 +434,15 @@ void CMusicPlayer::stop ()
return; return;
// stop the music only if we are really playing (else risk to stop a background music!) // stop the music only if we are really playing (else risk to stop a background music!)
SoundMngr->stopMusic(0); if (_State != Stopped)
SoundMngr->stopMusic(0);
_State = Stopped; _State = Stopped;
_PlayStart = 0; _PlayStart = 0;
_PauseTime = 0; _PauseTime = 0;
clearPlayingInfo();
NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:MP3_PLAYING")->setValueBool(false); NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:MP3_PLAYING")->setValueBool(false);
} }
@ -284,15 +478,48 @@ void CMusicPlayer::next ()
} }
// *************************************************************************** // ***************************************************************************
void CMusicPlayer::updatePlayingInfo(const std::string info)
{
CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:mp3_player:screen:text"));
if (pVT)
{
pVT->setText(ucstring::makeFromUtf8(info));
}
}
// ***************************************************************************
void CMusicPlayer::clearPlayingInfo()
{
if (_Songs.empty())
{
updatePlayingInfo(CI18N::get("uiNoFiles").toUtf8());
}
else
{
updatePlayingInfo("");
}
}
// ***************************************************************************
void CMusicPlayer::update () void CMusicPlayer::update ()
{ {
if(!SoundMngr) if(!SoundMngr)
{
if (_State != Stopped)
{
_State = Stopped;
clearPlayingInfo();
}
return; return;
}
if (MusicPlayerWorker.isRunning() || !_SongUpdateQueue.empty())
{
updateSongs();
}
if (_State == Playing) if (_State == Playing)
{ {
CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:mp3_player:screen:text"));
if (pVT)
{ {
TTime dur = (CTime::getLocalTime() - _PlayStart) / 1000; TTime dur = (CTime::getLocalTime() - _PlayStart) / 1000;
uint min = (dur / 60) % 60; uint min = (dur / 60) % 60;
@ -302,7 +529,7 @@ void CMusicPlayer::update ()
std::string title(toString("%02d:%02d", min, sec)); std::string title(toString("%02d:%02d", min, sec));
if (hour > 0) title = toString("%02d:", hour) + title; if (hour > 0) title = toString("%02d:", hour) + title;
title += " " + _CurrentSong.Title; title += " " + _CurrentSong.Title;
pVT->setText(ucstring::makeFromUtf8(title)); updatePlayingInfo(title);
} }
if (SoundMngr->isMusicEnded ()) if (SoundMngr->isMusicEnded ())
@ -323,15 +550,20 @@ void CMusicPlayer::update ()
} }
else else
{ {
SoundMngr->stopMusic(0); // remove active highlight from playlist
_State = Stopped; updatePlaylist(_CurrentSongIndex, false);
stop();
// restart from top on next 'play'
_CurrentSongIndex = 0;
} }
} }
} }
} }
// *************************************************************************** // ***************************************************************************
static void addFromPlaylist(const std::string &playlist, std::vector<std::string> &filenames) static void addFromPlaylist(const std::string &playlist, const std::vector<std::string> &extensions, std::vector<std::string> &filenames)
{ {
static uint8 utf8Header[] = { 0xefu, 0xbbu, 0xbfu }; static uint8 utf8Header[] = { 0xefu, 0xbbu, 0xbfu };
@ -362,15 +594,82 @@ static void addFromPlaylist(const std::string &playlist, std::vector<std::string
// Not a comment line // Not a comment line
if (lineStr[0] != '#') if (lineStr[0] != '#')
{ {
std::string filepath = CFile::getPath(lineStr); std::string filename = CPath::makePathAbsolute(CFile::getPath(lineStr), basePlaylist) + CFile::getFilename(lineStr);
std::string filename = CFile::getFilename(lineStr); std::string ext = toLower(CFile::getExtension(filename));
filenames.push_back (CPath::makePathAbsolute(filepath, basePlaylist)+filename); if (std::find(extensions.begin(), extensions.end(), ext) != extensions.end())
{
if (CFile::fileExists(filename))
filenames.push_back(filename);
else
nlwarning("Ignore non-existing file '%s'", filename.c_str());
}
else
{
nlwarning("Ingnore invalid extension '%s'", filename.c_str());
}
} }
} }
fclose (file); fclose (file);
} }
} }
void CMusicPlayer::createPlaylistFromMusic()
{
std::vector<std::string> extensions;
SoundMngr->getMixer()->getMusicExtensions(extensions);
// no format supported
if (extensions.empty())
{
// in the very unlikely scenario
const ucstring message("Sound driver has no support for music.");
CInterfaceManager::getInstance()->displaySystemInfo(message, "SYS");
nlinfo("%s", message.toUtf8().c_str());
return;
}
std::string newPath = CPath::makePathAbsolute(CPath::standardizePath(ClientCfg.MediaPlayerDirectory), CPath::getCurrentPath(), true);
std::string extlist;
join(extensions, ", ", extlist);
extlist += ", m3u, m3u8";
std::string msg(CI18N::get("uiMk_system6").toUtf8());
msg += ": " + newPath + " (" + extlist + ")";
CInterfaceManager::getInstance()->displaySystemInfo(ucstring::makeFromUtf8(msg), "SYS");
nlinfo("%s", msg.c_str());
// Recursive scan for files from media directory
vector<string> filesToProcess;
CPath::getPathContent (newPath, true, false, true, filesToProcess);
uint i;
std::vector<std::string> filenames;
std::vector<std::string> playlists;
for (i = 0; i < filesToProcess.size(); ++i)
{
std::string ext = toLower(CFile::getExtension(filesToProcess[i]));
if (std::find(extensions.begin(), extensions.end(), ext) != extensions.end())
{
filenames.push_back(filesToProcess[i]);
}
else if (ext == "m3u" || ext == "m3u8")
{
playlists.push_back(filesToProcess[i]);
}
}
// Add songs from playlists
for (i = 0; i < playlists.size(); ++i)
{
addFromPlaylist(playlists[i], extensions, filenames);
}
// Sort songs by filename
sort(filenames.begin(), filenames.end());
playSongs(filenames);
}
// *************************************************************************** // ***************************************************************************
class CMusicPlayerPlaySongs: public IActionHandler class CMusicPlayerPlaySongs: public IActionHandler
{ {
@ -379,82 +678,16 @@ public:
{ {
if(!SoundMngr) if(!SoundMngr)
{ {
CInterfaceManager::getInstance()->messageBox (CI18N::get ("uiSoundDisabled")); // Do not show warning on volume change as its restored at startup
if (Params.find("volume") == std::string::npos)
CInterfaceManager::getInstance()->messageBox (CI18N::get ("uiMP3SoundDisabled"));
return; return;
} }
if (Params == "play_songs") if (Params == "play_songs")
{ {
std::vector<std::string> extensions; MusicPlayer.createPlaylistFromMusic();
SoundMngr->getMixer()->getMusicExtensions(extensions);
// no format supported
if (extensions.empty())
{
// in the very unlikely scenario
const ucstring message("Sound driver has no support for music.");
CInterfaceManager::getInstance()->displaySystemInfo(message, "SYS");
nlinfo("%s", message.toUtf8().c_str());
return;
}
std::string newPath = CPath::makePathAbsolute(CPath::standardizePath(ClientCfg.MediaPlayerDirectory), CPath::getCurrentPath(), true);
std::string extlist;
join(extensions, ", ", extlist);
extlist += ", m3u, m3u8";
std::string msg(CI18N::get("uiMk_system6").toUtf8());
msg += ": " + newPath + " (" + extlist + ")";
CInterfaceManager::getInstance()->displaySystemInfo(ucstring::makeFromUtf8(msg), "SYS");
nlinfo("%s", msg.c_str());
// Recursive scan for files from media directory
vector<string> filesToProcess;
CPath::getPathContent (newPath, true, false, true, filesToProcess);
uint i;
std::vector<std::string> filenames;
std::vector<std::string> playlists;
for (i = 0; i < filesToProcess.size(); ++i)
{
std::string ext = toLower(CFile::getExtension(filesToProcess[i]));
if (std::find(extensions.begin(), extensions.end(), ext) != extensions.end())
{
filenames.push_back(filesToProcess[i]);
}
else if (ext == "m3u" || ext == "m3u8")
{
playlists.push_back(filesToProcess[i]);
}
}
// Sort songs by filename
sort (filenames.begin(), filenames.end());
// Add songs from playlists
for (i = 0; i < playlists.size(); ++i)
{
addFromPlaylist(playlists[i], filenames);
}
// Build the songs array
std::vector<CMusicPlayer::CSongs> songs;
for (i=0; i<filenames.size(); i++)
{
if (!CFile::fileExists(filenames[i])) {
nlwarning("Ignore non-existing file '%s'", filenames[i].c_str());
continue;
}
CMusicPlayer::CSongs song;
song.Filename = filenames[i];
// TODO: cache the result for next refresh
SoundMngr->getMixer()->getSongTitle(filenames[i], song.Title, song.Length);
if (song.Length > 0)
songs.push_back (song);
}
MusicPlayer.playSongs(songs);
} }
else if (Params == "update_playlist") else if (Params == "update_playlist")
{ {

@ -42,12 +42,16 @@ public:
class CSongs class CSongs
{ {
public: public:
CSongs(std::string file = std::string(), std::string title = std::string(), float length = 0.f)
: Filename(file), Title(title), Length(length)
{ }
std::string Filename; std::string Filename;
std::string Title; std::string Title;
float Length; float Length;
}; };
void playSongs (const std::vector<CSongs> &songs); void playSongs (const std::vector<std::string> &filenames);
void play (sint index = -1); // Play the song at current position, if playing, restart. If paused, resume. void play (sint index = -1); // Play the song at current position, if playing, restart. If paused, resume.
void pause (); void pause ();
void stop (); void stop ();
@ -58,6 +62,10 @@ public:
void update (); void update ();
// update currently playing song info/duration on main gui
void updatePlayingInfo(const std::string info);
void clearPlayingInfo();
bool isRepeatEnabled() const; bool isRepeatEnabled() const;
bool isShuffleEnabled() const; bool isShuffleEnabled() const;
@ -67,6 +75,20 @@ public:
void shuffleAndRebuildPlaylist(); void shuffleAndRebuildPlaylist();
// Update playlist active row // Update playlist active row
void updatePlaylist(sint prevIndex = -1); void updatePlaylist(sint prevIndex = -1);
// set/remove playlist highlight
void updatePlaylist(uint index, bool state);
// Update single song title/duration on _Songs and on playlist
void updateSong(const CSongs &song);
// Update _Songs and playlist from _SongUpdateQueue
void updateSongs();
// update song from worker thread
void updateSong(const std::string filename, const std::string title, float length);
// scan music folder and rebuild playlist
void createPlaylistFromMusic();
private: private:
@ -74,6 +96,8 @@ private:
CSongs _CurrentSong; CSongs _CurrentSong;
uint _CurrentSongIndex; // If (!_Songs.empty()) must always be <_Songs.size() uint _CurrentSongIndex; // If (!_Songs.empty()) must always be <_Songs.size()
std::vector<CSongs> _Songs; std::vector<CSongs> _Songs;
// updated info from worker thread
std::vector<CSongs> _SongUpdateQueue;
// State // State
enum TState { Stopped, Playing, Paused } _State; enum TState { Stopped, Playing, Paused } _State;

@ -3279,6 +3279,7 @@ bool loginIntroSkip;
void loginIntro() void loginIntro()
{ {
// Display of nevrax logo is done at init time (see init.cpp) just before addSearchPath (second one) // Display of nevrax logo is done at init time (see init.cpp) just before addSearchPath (second one)
#if 0
for (uint i = 0; i < 1; i++) // previously display nevrax then nvidia for (uint i = 0; i < 1; i++) // previously display nevrax then nvidia
{ {
if (i != 0) if (i != 0)
@ -3316,6 +3317,7 @@ void loginIntro()
NLGUI::CDBManager::getInstance()->flushObserverCalls(); NLGUI::CDBManager::getInstance()->flushObserverCalls();
} }
} }
#endif
beginLoading(StartBackground); beginLoading(StartBackground);
ProgressBar.finish(); ProgressBar.finish();
} }

@ -556,11 +556,11 @@ void clearBuffers()
} }
// Sky is used to clear the frame buffer now, but if in line or point polygon mode, we should draw it // Sky is used to clear the frame buffer now, but if in line or point polygon mode, we should draw it
if (Driver->getPolygonMode() != UDriver::Filled) if (Driver->getPolygonMode() != UDriver::Filled || !Filter3D[FilterSky])
{ {
if (!Driver->isLost()) if (!Driver->isLost())
{ {
Driver->clearBuffers (CRGBA(127, 127, 127)); Driver->clearBuffers (ClientCfg.BGColor);
} }
} }
} }
@ -2240,19 +2240,21 @@ bool mainLoop()
{ {
StartPlayTime = NLMISC::CTime::getLocalTime(); StartPlayTime = NLMISC::CTime::getLocalTime();
} }
// Start background sound play now ! (nb: restarted if load just ended, or if sound re-enabled) // Start background sound play now ! (nb: restarted if load just ended, or if sound re-enabled)
if (SoundMngr) if (SoundMngr)
{ {
H_AUTO_USE ( RZ_Client_Main_Loop_Sound ) H_AUTO_USE ( RZ_Client_Main_Loop_Sound )
SoundMngr->playBackgroundSound();
}
// Fade in Game Sound now (before endLoading)
if(SoundMngr)
{
// fade out loading music // fade out loading music
if(LoadingMusic==SoundMngr->getEventMusicPlayed()) if (SoundMngr->getEventMusicPlayed() == LoadingMusic)
{
SoundMngr->stopEventMusic(LoadingMusic, CSoundManager::LoadingMusicXFade); SoundMngr->stopEventMusic(LoadingMusic, CSoundManager::LoadingMusicXFade);
}
SoundMngr->playBackgroundSound();
// Fade in Game Sound now (before endLoading)
// fade in game sound // fade in game sound
SoundMngr->fadeInGameSound(ClientCfg.SoundTPFade); SoundMngr->fadeInGameSound(ClientCfg.SoundTPFade);
} }
@ -2515,9 +2517,6 @@ bool mainLoop()
Actions.enable(true); Actions.enable(true);
EditActions.enable(true); EditActions.enable(true);
// For stoping the outgame music, start after 30 frames, and duration of 3 seconds
// CMusicFader outgameFader(60, 3);
// check for banned player // check for banned player
if (testPermanentBanMarkers()) if (testPermanentBanMarkers())
{ {
@ -2527,6 +2526,9 @@ bool mainLoop()
} }
} }
// For stoping the outgame music, start after 30 frames, and duration of 3 seconds
outgameFader = CMusicFader(60, 3);
// Short reinit of the main loop after farTP or character reselection // Short reinit of the main loop after farTP or character reselection
Ping.init(); Ping.init();
updateLightDesc(); updateLightDesc();

@ -110,6 +110,9 @@ void updateFromClientCfg()
if (ClientCfg.BilinearUI != LastClientCfg.BilinearUI) if (ClientCfg.BilinearUI != LastClientCfg.BilinearUI)
CViewRenderer::getInstance()->setBilinearFiltering(ClientCfg.BilinearUI); CViewRenderer::getInstance()->setBilinearFiltering(ClientCfg.BilinearUI);
CWidgetManager::getInstance()->setWindowSnapInvert(ClientCfg.WindowSnapInvert);
CWidgetManager::getInstance()->setWindowSnapDistance(ClientCfg.WindowSnapDistance);
//--------------------------------------------------- //---------------------------------------------------
if (ClientCfg.WaitVBL != LastClientCfg.WaitVBL) if (ClientCfg.WaitVBL != LastClientCfg.WaitVBL)
{ {

@ -1483,32 +1483,33 @@ void impulseTPCommon(NLMISC::CBitMemStream &impulse, bool hasSeason)
void impulseTPCommon2(NLMISC::CBitMemStream &impulse, bool hasSeason) void impulseTPCommon2(NLMISC::CBitMemStream &impulse, bool hasSeason)
{ {
// choose a default screen if not setuped // choose a default screen if not setuped
if( LoadingBackground!=ResurectKamiBackground && LoadingBackground!=ResurectKaravanBackground && if (LoadingBackground != ResurectKamiBackground && LoadingBackground != ResurectKaravanBackground
LoadingBackground!=TeleportKamiBackground && LoadingBackground!=TeleportKaravanBackground) && LoadingBackground != TeleportKamiBackground && LoadingBackground != TeleportKaravanBackground)
LoadingBackground= TeleportKaravanBackground; LoadingBackground = ElevatorBackground;
// if resurect but user not dead, choose default. NB: this is a bug, the tp impulse should tell // if resurect but user not dead, choose default. NB: this is a bug, the tp impulse should tell
// which background to choose. \todo yoyo: this is a temp fix // which background to choose. \todo yoyo: this is a temp fix
if( UserEntity && !UserEntity->isDead() && if (UserEntity && !UserEntity->isDead() && (LoadingBackground == ResurectKamiBackground || LoadingBackground == ResurectKaravanBackground))
(LoadingBackground==ResurectKamiBackground || LoadingBackground==ResurectKaravanBackground) ) LoadingBackground = ElevatorBackground;
LoadingBackground= TeleportKaravanBackground;
// Play music according to the background // Play music according to the background
if(SoundMngr) if (SoundMngr)
{ {
LoadingMusic.clear(); LoadingMusic.clear();
if(LoadingBackground==TeleportKamiBackground) switch (LoadingBackground)
LoadingMusic= "Kami Teleport.ogg";
else if(LoadingBackground==TeleportKaravanBackground)
LoadingMusic= "Karavan Teleport.ogg";
// if resurection, continue to play death music
else if(LoadingBackground==ResurectKamiBackground || LoadingBackground==ResurectKaravanBackground)
{
// noop
}
// default: loading music
else
{ {
LoadingMusic= "Loading Music Loop.ogg"; case TeleportKamiBackground:
LoadingMusic = ClientCfg.KamiTeleportMusic;
break;
case TeleportKaravanBackground:
LoadingMusic = ClientCfg.KaravanTeleportMusic;
break;
case ResurectKamiBackground:
case ResurectKaravanBackground:
// TODO: Resurrect music
break;
default:
LoadingMusic = ClientCfg.TeleportLoadingMusic;
break;
} }
// start to play // start to play

@ -5785,7 +5785,7 @@ void CEditor::scenarioUpdated(CObject* highLevel, bool willTP, uint32 initialAct
} }
// //
projectInLua(_Scenario); // push on the lua stack projectInLua(_Scenario); // push on the lua stack
getLua().push(float(initialActIndex)); // example reconnect after test in act4 getLua().push(initialActIndex); // example reconnect after test in act4
// update value in the framework // update value in the framework
callEnvFunc("onScenarioUpdated", 2); callEnvFunc("onScenarioUpdated", 2);
//nlwarning("Instance list now is :"); //nlwarning("Instance list now is :");

@ -240,8 +240,8 @@ void releaseMainLoopReselect()
// alredy called from farTPMainLoop() // alredy called from farTPMainLoop()
// --R2::getEditor().autoConfigRelease(IsInRingSession); // --R2::getEditor().autoConfigRelease(IsInRingSession);
// Pause any user played music // stop any user played music
MusicPlayer.pause(); MusicPlayer.stop();
// only really needed at exit // only really needed at exit
// --STRING_MANAGER::CStringManagerClient::instance()->flushStringCache(); // --STRING_MANAGER::CStringManagerClient::instance()->flushStringCache();
@ -390,8 +390,8 @@ void releaseMainLoop(bool closeConnection)
// Release R2 editor if applicable // Release R2 editor if applicable
R2::getEditor().autoConfigRelease(IsInRingSession); R2::getEditor().autoConfigRelease(IsInRingSession);
// Pause any user played music // stop any user played music
MusicPlayer.pause(); MusicPlayer.stop();
// flush the server string cache // flush the server string cache
STRING_MANAGER::CStringManagerClient::instance()->flushStringCache(); STRING_MANAGER::CStringManagerClient::instance()->flushStringCache();

@ -4309,20 +4309,19 @@ void CUserEntity::updatePreCollision(const NLMISC::TTime &time, CEntityCL *targe
// test each frame if the mode has changed // test each frame if the mode has changed
if(SoundMngr) if(SoundMngr)
{ {
string deadMusic= "death.ogg";
// Play/stop music if comes from or goes to dead // Play/stop music if comes from or goes to dead
bool isDead= _Mode==MBEHAV::DEATH || _Mode==MBEHAV::SWIM_DEATH; bool isDead = _Mode == MBEHAV::DEATH || _Mode == MBEHAV::SWIM_DEATH;
// must start music? // must start music?
if( isDead && SoundMngr->getEventMusicPlayed()!=deadMusic ) if (isDead && SoundMngr->getEventMusicPlayed() != ClientCfg.DeathMusic)
{ {
SoundMngr->playEventMusic(deadMusic, 0, true); SoundMngr->playEventMusic(ClientCfg.DeathMusic, 0, true);
} }
// must end music? // must end music?
if( !isDead && SoundMngr->getEventMusicPlayed()==deadMusic ) if (!isDead && SoundMngr->getEventMusicPlayed() == ClientCfg.DeathMusic)
{ {
SoundMngr->stopEventMusic(deadMusic, CSoundManager::LoadingMusicXFade); SoundMngr->stopEventMusic(ClientCfg.DeathMusic, CSoundManager::LoadingMusicXFade);
} }
} }
} }

@ -187,7 +187,7 @@ BOOL CFileTreeCtrl::OnNotify ( WPARAM wParam, LPARAM lParam, LRESULT* pResult )
{ {
LPNMHDR pnmh = (LPNMHDR) lParam; LPNMHDR pnmh = (LPNMHDR) lParam;
// Tree ? // Tree ?
if (wParam == 0) // if (wParam == 0)
{ {
switch (pnmh->code) switch (pnmh->code)
{ {

@ -720,6 +720,8 @@ void CFormDialog::onLastFocus ()
int CFormDialog::getWidget (uint dialogId) const int CFormDialog::getWidget (uint dialogId) const
{ {
if (dialogId == 0xFFFE)
dialogId = 0;
for (uint i=0; i<Widgets.size(); i++) for (uint i=0; i<Widgets.size(); i++)
{ {
if (Widgets[i]->isDialog (dialogId)) if (Widgets[i]->isDialog (dialogId))
@ -1198,6 +1200,11 @@ void CFormDialog::onGetSubFocus (uint id)
{ {
// Get the widget // Get the widget
int widget = getWidget (id); int widget = getWidget (id);
if (widget < 0)
{
nldebug("Invalid widget id %d", (int)id);
return;
}
WidgetFocused = widget; WidgetFocused = widget;
// Window view // Window view
@ -1584,7 +1591,7 @@ void CFormMemCombo::create (DWORD wStyle, RECT &currentPos, CFormDialog *parent,
{ {
// Create the mem combobox // Create the mem combobox
parent->setComboSpinSize (currentPos); parent->setComboSpinSize (currentPos);
Combo.create (WS_CHILD|WS_TABSTOP, currentPos, parent, dialog_index, reg, theApp.RememberListSize); Combo.create (WS_CHILD|WS_TABSTOP, currentPos, parent, dialog_index ? dialog_index : 0xFFFE, reg, theApp.RememberListSize);
parent->initWidget (Combo); parent->initWidget (Combo);
// Create the spin // Create the spin
@ -1599,7 +1606,7 @@ void CFormMemCombo::create (DWORD wStyle, RECT &currentPos, CFormDialog *parent,
{ {
// Create the mem combobox // Create the mem combobox
parent->setComboBrowseSize (currentPos); parent->setComboBrowseSize (currentPos);
Combo.create (WS_CHILD|WS_TABSTOP, currentPos, parent, dialog_index, reg, theApp.RememberListSize); Combo.create (WS_CHILD|WS_TABSTOP, currentPos, parent, dialog_index ? dialog_index : 0xFFFE, reg, theApp.RememberListSize);
parent->initWidget (Combo); parent->initWidget (Combo);
// Create the spin // Create the spin
@ -1621,7 +1628,7 @@ void CFormMemCombo::create (DWORD wStyle, RECT &currentPos, CFormDialog *parent,
{ {
// Create the mem combobox // Create the mem combobox
parent->setComboSize (currentPos, parent->SmallWidget); parent->setComboSize (currentPos, parent->SmallWidget);
Combo.create (WS_CHILD|WS_TABSTOP, currentPos, parent, dialog_index, reg, theApp.RememberListSize); Combo.create (WS_CHILD|WS_TABSTOP, currentPos, parent, dialog_index ? dialog_index : 0xFFFE, reg, theApp.RememberListSize);
parent->initWidget (Combo); parent->initWidget (Combo);
parent->getNextPos (currentPos); parent->getNextPos (currentPos);
} }
@ -1914,7 +1921,7 @@ void CFormCombo::create (DWORD wStyle, RECT &currentPos, CFormDialog *parent, ui
parent->setComboSize (currentPos, parent->SmallWidget); parent->setComboSize (currentPos, parent->SmallWidget);
RECT comboPos = currentPos; RECT comboPos = currentPos;
parent->adjusteComboSize (comboPos); parent->adjusteComboSize (comboPos);
Combo.Create (WS_CHILD|WS_VSCROLL|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS|WS_CHILD|WS_TABSTOP, comboPos, parent, dialog_index); Combo.Create (WS_CHILD|WS_VSCROLL|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS|WS_CHILD|WS_TABSTOP, comboPos, parent, dialog_index ? dialog_index : 0xFFFE);
parent->initWidget (Combo); parent->initWidget (Combo);
parent->getNextPos (currentPos); parent->getNextPos (currentPos);
@ -2097,7 +2104,7 @@ void CFormBigEdit::create (DWORD wStyle, RECT &currentPos, CFormDialog *parent,
// Create the mem combobox // Create the mem combobox
parent->setBigEditSize (currentPos, parent->SmallWidget); parent->setBigEditSize (currentPos, parent->SmallWidget);
Edit.CreateEx (WS_EX_CLIENTEDGE, _T("EDIT"), _T(""), WS_VSCROLL|ES_OEMCONVERT|ES_MULTILINE|ES_WANTRETURN|WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL|ES_AUTOVSCROLL, currentPos, parent, dialog_index); Edit.CreateEx (WS_EX_CLIENTEDGE, _T("EDIT"), _T(""), WS_VSCROLL|ES_OEMCONVERT|ES_MULTILINE|ES_WANTRETURN|WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL|ES_AUTOVSCROLL, currentPos, parent, dialog_index ? dialog_index : 0xFFFE);
parent->initWidget (Edit); parent->initWidget (Edit);
parent->getNextPos (currentPos); parent->getNextPos (currentPos);
@ -2271,7 +2278,7 @@ void CColorEdit::create (DWORD wStyle, RECT &currentPos, CFormDialog *parent, ui
// Create the mem combobox // Create the mem combobox
parent->setColorSize (currentPos, parent->SmallWidget); parent->setColorSize (currentPos, parent->SmallWidget);
Color.create (WS_CHILD|WS_VISIBLE|WS_TABSTOP, currentPos, parent, dialog_index); Color.create (WS_CHILD|WS_VISIBLE|WS_TABSTOP, currentPos, parent, dialog_index ? dialog_index : 0xFFFE);
parent->initWidget (Color); parent->initWidget (Color);
// Create the reset button // Create the reset button
@ -2501,7 +2508,7 @@ void CListWidget::create (DWORD wStyle, RECT &currentPos, CFormDialog *parent, u
// Create the mem combobox // Create the mem combobox
parent->setListSize (currentPos, parent->SmallWidget); parent->setListSize (currentPos, parent->SmallWidget);
ListCtrl.create (WS_CHILD|WS_VISIBLE|WS_TABSTOP, currentPos, parent, dialog_index); ListCtrl.create (WS_CHILD|WS_VISIBLE|WS_TABSTOP, currentPos, parent, dialog_index ? dialog_index : 0xFFFE);
parent->initWidget (ListCtrl); parent->initWidget (ListCtrl);
parent->getNextPos (currentPos); parent->getNextPos (currentPos);
@ -2759,7 +2766,7 @@ void CIconWidget::create (DWORD wStyle, RECT &currentPos, CFormDialog *parent, u
// Create the mem combobox // Create the mem combobox
parent->setEditSize (currentPos, parent->IconHeight, parent->IconHeight); parent->setEditSize (currentPos, parent->IconHeight, parent->IconHeight);
Icon.create (WS_CHILD|WS_VISIBLE|WS_TABSTOP, currentPos, parent, dialog_index); Icon.create (WS_CHILD|WS_VISIBLE|WS_TABSTOP, currentPos, parent, dialog_index ? dialog_index : 0xFFFE);
parent->initWidget (Icon); parent->initWidget (Icon);
parent->getNextPos (currentPos); parent->getNextPos (currentPos);

Loading…
Cancel
Save