This commit is contained in:
rti 2010-10-30 23:48:55 +02:00
commit 5735dc26b1
573 changed files with 45305 additions and 2851 deletions

View file

@ -10,9 +10,9 @@ IF(WIN32)
FIND_PACKAGE(DirectXSDK REQUIRED)
# On Win32 we can also build the MAX plugins.
IF(WITH_MAXPLUGIN)
IF(WITH_NEL_MAXPLUGIN)
FIND_PACKAGE(3dsMaxSDK)
ENDIF(WITH_MAXPLUGIN)
ENDIF(WITH_NEL_MAXPLUGIN)
ENDIF(WIN32)
IF(WITH_3D)

View file

@ -174,7 +174,9 @@ public:
_Mutex.enter();
if(NL3D_BlockMemoryAssertOnPurge)
{
nlassert(_NAllocatedElts==0);
}
while(_Blocks.begin()!=_Blocks.end())
{

View file

@ -124,7 +124,7 @@ public:
{
public:
CVar () : Type(T_UNKNOWN), Root(false), FromLocalFile(true), SaveWrap(6) {}
CVar () : Type(T_UNKNOWN), Root(false), Comp(false), FromLocalFile(true), SaveWrap(6) {}
/// \name Access to the variable content.
//@{

View file

@ -20,6 +20,7 @@
#include <string>
#include <vector>
#include <map>
#include <limits>
#include "types_nl.h"
#include "entity_id.h"

View file

@ -283,11 +283,11 @@ typedef uint64_t uint64;
typedef int sint; // at least 32bits (depend of processor)
typedef unsigned int uint; // at least 32bits (depend of processor)
#if __SIZEOF_LONG__ == 8
#ifdef _LP64
# define NL_I64 "l"
#else
# define NL_I64 "ll"
#endif // __SIZEOF_LONG__ == 8
#endif // _LP64
#endif // NL_OS_UNIX
@ -307,6 +307,8 @@ typedef unsigned int uint; // at least 32bits (depend of processor)
# define CHashSet std::tr1::unordered_set
# define CHashMultiMap std::tr1::unordered_multimap
#elif defined(NL_COMP_VC7) || defined(NL_COMP_VC71) || defined(NL_COMP_VC8) || defined(NL_COMP_VC9) // VC7 through 9
# include <hash_map>
# include <hash_set>
# define CHashMap stdext::hash_map
# define CHashSet stdext::hash_set
# define CHashMultiMap stdext::hash_multimap

View file

@ -38,6 +38,7 @@
#include <exception>
#include <utility>
#include <deque>
#include <limits>
#ifdef NL_DEBUG

View file

@ -180,8 +180,6 @@ CDriverGL::CDriverGL()
_PBuffer = NULL;
_hRC = NULL;
_hDC = NULL;
_NeedToRestaureGammaRamp = false;
_Interval = 1;
#elif defined(NL_OS_MAC)
@ -192,7 +190,7 @@ CDriverGL::CDriverGL()
// autorelease pool for memory management
_autoreleasePool = [[NSAutoreleasePool alloc] init];
// init the application object
[NSApplication sharedApplication];
@ -201,7 +199,7 @@ CDriverGL::CDriverGL()
// finish the application launching
[NSApp finishLaunching];
#elif defined (NL_OS_UNIX)
_cursor = None;
@ -215,6 +213,9 @@ CDriverGL::CDriverGL()
#endif // NL_OS_UNIX
_NeedToRestaureGammaRamp = false;
_Interval = 1;
_win = EmptyWindow;
_DestroyWindow = false;
@ -312,7 +313,6 @@ CDriverGL::CDriverGL()
_VBHardProfiling= false;
_CurVBHardLockCount= 0;
_NumVBHardProfileFrame= 0;
_Interval = 1;
_TexEnvReplace.setDefault();
_TexEnvReplace.Env.OpAlpha = CMaterial::Previous;
@ -354,14 +354,17 @@ bool CDriverGL::setupDisplay()
// Driver caps.
//=============
// Retrieve the extensions for the current context.
NL3D::registerGlExtensions (_Extensions);
registerGlExtensions (_Extensions);
vector<string> lines;
explode(_Extensions.toString(), string("\n"), lines);
for(uint i = 0; i < lines.size(); i++)
nlinfo("3D: %s", lines[i].c_str());
#ifdef NL_OS_WINDOWS
NL3D::registerWGlExtensions(_Extensions, _hDC);
registerWGlExtensions(_Extensions, _hDC);
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
registerGlXExtensions(_Extensions, _dpy, DefaultScreen(_dpy));
#endif // NL_OS_WINDOWS
// Check required extensions!!
@ -615,10 +618,8 @@ bool CDriverGL::setupDisplay()
}
}
#ifdef NL_OS_WINDOWS
// Reset the vbl interval
setSwapVBLInterval(_Interval);
#endif
return true;
}
@ -876,7 +877,7 @@ bool CDriverGL::swapBuffers()
[_autoreleasePool release];
_autoreleasePool = [[NSAutoreleasePool alloc] init];
}
[_ctx flushBuffer];
[containerView() display];
@ -1673,12 +1674,12 @@ ATTRIB bump0TexCoord = fragment.texcoord[0]; \n\
ATTRIB bump1TexCoord = fragment.texcoord[1]; \n\
ATTRIB envMapTexCoord = fragment.texcoord[2]; \n\
OUTPUT oCol = result.color; \n\
TEMP bmValue; \n\
TEMP bmValue; \n\
#read bump map 0 \n\
TEX bmValue, bump0TexCoord, texture[0], 2D; \n\
#bias result (include scaling) \n\
MAD bmValue, bmValue, bump0ScaleBias.xxxx, bump0ScaleBias.yyzz; \n\
ADD bmValue, bmValue, bump1TexCoord; \n\
ADD bmValue, bmValue, bump1TexCoord; \n\
#read bump map 1 \n\
TEX bmValue, bmValue, texture[1], 2D; \n\
#bias result (include scaling) \n\
@ -1701,14 +1702,14 @@ ATTRIB bump1TexCoord = fragment.texcoord[1]; \n\
ATTRIB envMapTexCoord = fragment.texcoord[2]; \n\
ATTRIB fogValue = fragment.fogcoord; \n\
OUTPUT oCol = result.color; \n\
TEMP bmValue; \n\
TEMP bmValue; \n\
TEMP envMap; \n\
TEMP tmpFog; \n\
#read bump map 0 \n\
TEX bmValue, bump0TexCoord, texture[0], 2D; \n\
#bias result (include scaling) \n\
MAD bmValue, bmValue, bump0ScaleBias.xxxx, bump0ScaleBias.yyzz; \n\
ADD bmValue, bmValue, bump1TexCoord; \n\
ADD bmValue, bmValue, bump1TexCoord; \n\
#read bump map 1 \n\
TEX bmValue, bmValue, texture[1], 2D; \n\
#bias result (include scaling) \n\
@ -1735,14 +1736,14 @@ ATTRIB bump1TexCoord = fragment.texcoord[1]; \n\
ATTRIB envMapTexCoord = fragment.texcoord[2]; \n\
ATTRIB diffuseTexCoord = fragment.texcoord[3]; \n\
OUTPUT oCol = result.color; \n\
TEMP bmValue; \n\
TEMP bmValue; \n\
TEMP diffuse; \n\
TEMP envMap; \n\
#read bump map 0 \n\
TEX bmValue, bump0TexCoord, texture[0], 2D; \n\
#bias result (include scaling) \n\
MAD bmValue, bmValue, bump0ScaleBias.xxxx, bump0ScaleBias.yyzz; \n\
ADD bmValue, bmValue, bump1TexCoord; \n\
ADD bmValue, bmValue, bump1TexCoord; \n\
#read bump map 1 \n\
TEX bmValue, bmValue, texture[1], 2D; \n\
#bias result (include scaling) \n\
@ -1770,7 +1771,7 @@ ATTRIB envMapTexCoord = fragment.texcoord[2]; \n\
ATTRIB diffuseTexCoord = fragment.texcoord[3]; \n\
ATTRIB fogValue = fragment.fogcoord; \n\
OUTPUT oCol = result.color; \n\
TEMP bmValue; \n\
TEMP bmValue; \n\
TEMP diffuse; \n\
TEMP envMap; \n\
TEMP tmpFog; \n\
@ -1778,7 +1779,7 @@ TEMP tmpFog; \n\
TEX bmValue, bump0TexCoord, texture[0], 2D; \n\
#bias result (include scaling) \n\
MAD bmValue, bmValue, bump0ScaleBias.xxxx, bump0ScaleBias.yyzz; \n\
ADD bmValue, bmValue, bump1TexCoord; \n\
ADD bmValue, bmValue, bump1TexCoord; \n\
#read bump map 1 \n\
TEX bmValue, bmValue, texture[1], 2D; \n\
#bias result (include scaling) \n\
@ -2038,29 +2039,70 @@ void CDriverGL::flush()
void CDriverGL::setSwapVBLInterval(uint interval)
{
H_AUTO_OGL(CDriverGL_setSwapVBLInterval)
if (!_Initialized)
return;
bool res = true;
#ifdef NL_OS_WINDOWS
_Interval = interval;
if(_Extensions.WGLEXTSwapControl && _Initialized)
if(_Extensions.WGLEXTSwapControl)
{
nwglSwapIntervalEXT(_Interval);
res = nwglSwapIntervalEXT(_Interval) == TRUE;
}
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
if (_win && _Extensions.GLXEXTSwapControl)
{
res = nglXSwapIntervalEXT(_dpy, _win, interval) == 0;
}
else if (_Extensions.GLXSGISwapControl)
{
res = nglXSwapIntervalSGI(interval) == 0;
}
else if (_Extensions.GLXMESASwapControl)
{
res = nglXSwapIntervalMESA(interval) == 0;
}
#endif
if (res)
{
_Interval = interval;
}
else
{
nlwarning("Could not set swap interval");
}
}
// ***************************************************************************
uint CDriverGL::getSwapVBLInterval()
{
H_AUTO_OGL(CDriverGL_getSwapVBLInterval)
#ifdef NL_OS_WINDOWS
if(_Extensions.WGLEXTSwapControl)
{
return _Interval;
return nwglGetSwapIntervalEXT();
}
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
if (_win && _Extensions.GLXEXTSwapControl)
{
uint swap, maxSwap;
glXQueryDrawable(_dpy, _win, GLX_SWAP_INTERVAL_EXT, &swap);
glXQueryDrawable(_dpy, _win, GLX_MAX_SWAP_INTERVAL_EXT, &maxSwap);
nlwarning("The swap interval is %u and the max swap interval is %u", swap, maxSwap);
return swap;
}
else if (_Extensions.GLXMESASwapControl)
{
return nglXGetSwapIntervalMESA();
}
else
return 1;
#else
return 1;
#endif
return _Interval;
}
// ***************************************************************************
@ -2419,10 +2461,10 @@ void CDriverGL::displayBench (class NLMISC::CLog *log)
}
#ifdef NL_DEBUG
void CDriverGL::dumpMappedBuffers()
{
_AGPVertexArrayRange->dumpMappedBuffers();
}
void CDriverGL::dumpMappedBuffers()
{
_AGPVertexArrayRange->dumpMappedBuffers();
}
#endif
// ***************************************************************************

View file

@ -440,6 +440,18 @@ PFNWGLGETSWAPINTERVALEXTPROC nwglGetSwapIntervalEXT;
// WGL_ARB_extensions_string
PFNWGLGETEXTENSIONSSTRINGARBPROC nwglGetExtensionsStringARB;
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
// Swap control extensions
PFNGLXSWAPINTERVALEXTPROC nglXSwapIntervalEXT;
PFNGLXSWAPINTERVALSGIPROC nglXSwapIntervalSGI;
PFNGLXSWAPINTERVALMESAPROC nglXSwapIntervalMESA;
PFNGLXGETSWAPINTERVALMESAPROC nglXGetSwapIntervalMESA;
#endif
// ***************************************************************************
@ -1410,6 +1422,46 @@ static bool setupWGLEXTSwapControl(const char *glext)
return true;
}
// *********************************
static bool setupGLXEXTSwapControl(const char *glext)
{
H_AUTO_OGL(setupGLXEXTSwapControl);
CHECK_EXT("GLX_EXT_swap_control");
#ifdef NL_OS_UNIX
CHECK_ADDRESS(PFNGLXSWAPINTERVALEXTPROC, glXSwapIntervalEXT);
#endif
return true;
}
// *********************************
static bool setupGLXSGISwapControl(const char *glext)
{
H_AUTO_OGL(setupGLXSGISwapControl);
CHECK_EXT("GLX_SGI_swap_control");
#ifdef NL_OS_UNIX
CHECK_ADDRESS(PFNGLXSWAPINTERVALSGIPROC, glXSwapIntervalSGI);
#endif
return true;
}
// *********************************
static bool setupGLXMESASwapControl(const char *glext)
{
H_AUTO_OGL(setupGLXMESASwapControl);
CHECK_EXT("GLX_MESA_swap_control");
#ifdef NL_OS_UNIX
CHECK_ADDRESS(PFNGLXSWAPINTERVALMESAPROC, glXSwapIntervalMESA);
CHECK_ADDRESS(PFNGLXGETSWAPINTERVALMESAPROC, glXGetSwapIntervalMESA);
#endif
return true;
}
#ifdef NL_OS_WINDOWS
// ***************************************************************************
bool registerWGlExtensions(CGlExtensions &ext, HDC hDC)
@ -1452,6 +1504,49 @@ bool registerWGlExtensions(CGlExtensions &ext, HDC hDC)
return true;
}
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
// ***************************************************************************
bool registerGlXExtensions(CGlExtensions &ext, Display *dpy, sint screen)
{
H_AUTO_OGL(registerGlXExtensions);
// Get extension string
const char *glext = glXQueryExtensionsString(dpy, screen);
if (glext == NULL)
{
nlwarning ("glXQueryExtensionsString failed");
return false;
}
nldebug("3D: Available GLX Extensions:");
if (DebugLog)
{
vector<string> exts;
explode(string(glext), string(" "), exts);
for(uint i = 0; i < exts.size(); i++)
{
if(i%5==0) DebugLog->displayRaw("3D: ");
DebugLog->displayRaw(string(exts[i]+" ").c_str());
if(i%5==4) DebugLog->displayRaw("\n");
}
DebugLog->displayRaw("\n");
}
// Check for pbuffer
// ext.WGLARBPBuffer= setupWGLARBPBuffer(glext);
// Check for pixel format
// ext.WGLARBPixelFormat= setupWGLARBPixelFormat(glext);
// Check for swap control
ext.GLXEXTSwapControl= setupGLXEXTSwapControl(glext);
ext.GLXSGISwapControl= setupGLXSGISwapControl(glext);
ext.GLXMESASwapControl= setupGLXMESASwapControl(glext);
return true;
}
#endif // NL_OS_WINDOWS
}

View file

@ -35,6 +35,7 @@
# include <GL/gl.h>
# include <GL/glext.h> // Please download it from http://www.opengl.org/registry/
# include <GL/glx.h>
# include <GL/glxext.h>
#endif // NL_OS_UNIX
#ifndef GL_GLEXT_VERSION
@ -94,6 +95,11 @@ struct CGlExtensions
bool WGLARBPixelFormat;
bool WGLEXTSwapControl;
// GLX extensions, true if supported
bool GLXEXTSwapControl;
bool GLXSGISwapControl;
bool GLXMESASwapControl;
// ATI Extensions.
bool ATIVertexArrayObject;
bool ATIMapObjectBuffer;
@ -148,6 +154,9 @@ public:
WGLARBPBuffer= false;
WGLARBPixelFormat= false;
WGLEXTSwapControl= false;
GLXEXTSwapControl= false;
GLXSGISwapControl= false;
GLXMESASwapControl= false;
EXTBlendColor= false;
ATIVertexArrayObject= false;
ATIEnvMapBumpMap = false;
@ -226,6 +235,11 @@ public:
result += WGLARBPBuffer ? "WGLARBPBuffer " : "";
result += WGLARBPixelFormat ? "WGLARBPixelFormat " : "";
result += WGLEXTSwapControl ? "WGLEXTSwapControl " : "";
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
result += GLXEXTSwapControl ? "GLXEXTSwapControl " : "";
result += GLXSGISwapControl ? "GLXSGISwapControl " : "";
result += GLXMESASwapControl ? "GLXMESASwapControl " : "";
#endif
result += "\n Array/VBO: ";
@ -250,6 +264,10 @@ public:
#ifdef NL_OS_WINDOWS
/// This function will test and register WGL functions before than the gl context is created
bool registerWGlExtensions(CGlExtensions &ext, HDC hDC);
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
/// This function will test and register GLX functions before than the gl context is created
bool registerGlXExtensions(CGlExtensions &ext, Display *dpy, sint screen);
#endif // NL_OS_WINDOWS
/// This function test and register the extensions for the current GL context.
@ -675,6 +693,18 @@ extern PFNWGLGETSWAPINTERVALEXTPROC nwglGetSwapIntervalEXT;
// WGL_ARB_extensions_string
extern PFNWGLGETEXTENSIONSSTRINGARBPROC nwglGetExtensionsStringARB;
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
// Swap control extensions
//===========================
extern PFNGLXSWAPINTERVALEXTPROC nglXSwapIntervalEXT;
extern PFNGLXSWAPINTERVALSGIPROC nglXSwapIntervalSGI;
extern PFNGLXSWAPINTERVALMESAPROC nglXSwapIntervalMESA;
extern PFNGLXGETSWAPINTERVALMESAPROC nglXGetSwapIntervalMESA;
#endif
// GL_EXT_framebuffer_object

View file

@ -22,8 +22,7 @@
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/Xutil.h>
#include "nel/misc/debug.h"
@ -568,7 +567,7 @@ bool CUnixEventEmitter::processMessage (XEvent &event, CEventServer *server)
ucstring ucstr;
ucstr.fromUtf8(Text);
CEventChar *charEvent = new CEventChar (ucstr[0], noKeyButton, this);
CEventChar *charEvent = new CEventChar (ucstr[0], getKeyButton(event.xbutton.state), this);
// raw if not processed by IME
charEvent->setRaw(keyCode != 0);
@ -577,7 +576,7 @@ bool CUnixEventEmitter::processMessage (XEvent &event, CEventServer *server)
#else
for (int i = 0; i < c; i++)
{
CEventChar *charEvent = new CEventChar ((ucchar)(unsigned char)Text[i], noKeyButton, this);
CEventChar *charEvent = new CEventChar ((ucchar)(unsigned char)Text[i], getKeyButton(event.xbutton.state), this);
// raw if not processed by IME
charEvent->setRaw(keyCode != 0);

View file

@ -24,8 +24,7 @@
#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/Xlib.h>
namespace NLMISC {

View file

@ -1147,11 +1147,9 @@ void destroyDebug()
void createDebug (const char *logPath, bool logInFile, bool eraseLastLog)
{
// Do some basic compiler time check on type size
nlctassert(sizeof(char) == 1);
// static bool alreadyCreateSharedAmongThreads = false;
// if ( !alreadyCreateSharedAmongThreads )
if (!INelContext::getInstance().getAlreadyCreateSharedAmongThreads())

View file

@ -1727,16 +1727,22 @@ std::string CFileContainer::getTemporaryDirectory()
static std::string path;
if (path.empty())
{
char *tempDir = getenv("TEMP");
const char *temp = getenv("TEMP");
const char *tmp = getenv("TMP");
if (tempDir == NULL)
tempDir = getenv("TMP");
std::string tempDir;
if (temp)
tempDir = temp;
if (tempDir.empty() && tmp)
tempDir = tmp;
#ifdef NL_OS_UNIX
if (tempDir == NULL)
if (tempDir.empty())
tempDir = "/tmp";
#else
if (tempDir == NULL)
if (tempDir.empty())
tempDir = ".";
#endif

View file

@ -1,19 +1,19 @@
FILE(GLOB SRC *.cpp *.h)
FILE(GLOB SRC *.cpp *.h *.def)
NL_TARGET_DRIVER(nel_drv_dsound ${SRC})
NL_TARGET_DRIVER(nel_drv_dsound_win ${SRC})
INCLUDE_DIRECTORIES(${DXSDK_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(nel_drv_dsound nelmisc nelsnd_lowlevel ${DXSDK_DSOUND_LIBRARY} ${DXSDK_GUID_LIBRARY})
TARGET_LINK_LIBRARIES(nel_drv_dsound_win nelmisc nelsnd_lowlevel ${DXSDK_DSOUND_LIBRARY} ${DXSDK_GUID_LIBRARY})
NL_DEFAULT_PROPS(nel_drv_dsound "NeL, Driver, Sound: DirectSound")
NL_ADD_RUNTIME_FLAGS(nel_drv_dsound)
NL_ADD_LIB_SUFFIX(nel_drv_dsound)
NL_DEFAULT_PROPS(nel_drv_dsound_win "NeL, Driver, Sound: DirectSound")
NL_ADD_RUNTIME_FLAGS(nel_drv_dsound_win)
NL_ADD_LIB_SUFFIX(nel_drv_dsound_win)
IF(WITH_PCH)
ADD_NATIVE_PRECOMPILED_HEADER(nel_drv_dsound ${CMAKE_CURRENT_SOURCE_DIR}/stddsound.h ${CMAKE_CURRENT_SOURCE_DIR}/stddsound.cpp)
ADD_NATIVE_PRECOMPILED_HEADER(nel_drv_dsound_win ${CMAKE_CURRENT_SOURCE_DIR}/stddsound.h ${CMAKE_CURRENT_SOURCE_DIR}/stddsound.cpp)
ENDIF(WITH_PCH)
INSTALL(TARGETS nel_drv_dsound RUNTIME DESTINATION bin LIBRARY DESTINATION ${NL_DRIVER_PREFIX} ARCHIVE DESTINATION lib COMPONENT driverssound)
INSTALL(TARGETS nel_drv_dsound_win RUNTIME DESTINATION bin LIBRARY DESTINATION ${NL_DRIVER_PREFIX} ARCHIVE DESTINATION lib COMPONENT driverssound)
IF(WITH_MAXPLUGIN)
INSTALL(TARGETS nel_drv_dsound RUNTIME DESTINATION maxplugin COMPONENT driverssound)
INSTALL(TARGETS nel_drv_dsound_win RUNTIME DESTINATION maxplugin COMPONENT driverssound)
ENDIF(WITH_MAXPLUGIN)

View file

@ -1,19 +1,19 @@
FILE(GLOB SRC *.cpp *.h)
FILE(GLOB SRC *.cpp *.h *.def)
NL_TARGET_DRIVER(nel_drv_fmod ${SRC})
NL_TARGET_DRIVER(nel_drv_fmod_win ${SRC})
INCLUDE_DIRECTORIES(${FMOD_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(nel_drv_fmod ${FMOD_LIBRARY} nelmisc nelsnd_lowlevel)
TARGET_LINK_LIBRARIES(nel_drv_fmod_win ${FMOD_LIBRARY} nelmisc nelsnd_lowlevel)
NL_DEFAULT_PROPS(nel_drv_fmod "NeL, Driver, Sound: FMOD")
NL_ADD_RUNTIME_FLAGS(nel_drv_fmod)
NL_ADD_LIB_SUFFIX(nel_drv_fmod)
NL_DEFAULT_PROPS(nel_drv_fmod_win "NeL, Driver, Sound: FMOD")
NL_ADD_RUNTIME_FLAGS(nel_drv_fmod_win)
NL_ADD_LIB_SUFFIX(nel_drv_fmod_win)
IF(WITH_PCH)
ADD_NATIVE_PRECOMPILED_HEADER(nel_drv_fmod ${CMAKE_CURRENT_SOURCE_DIR}/stdfmod.h ${CMAKE_CURRENT_SOURCE_DIR}/stdfmod.cpp)
ADD_NATIVE_PRECOMPILED_HEADER(nel_drv_fmod_win ${CMAKE_CURRENT_SOURCE_DIR}/stdfmod.h ${CMAKE_CURRENT_SOURCE_DIR}/stdfmod.cpp)
ENDIF(WITH_PCH)
INSTALL(TARGETS nel_drv_fmod RUNTIME DESTINATION bin LIBRARY DESTINATION ${NL_DRIVER_PREFIX} ARCHIVE DESTINATION lib COMPONENT driverssound)
INSTALL(TARGETS nel_drv_fmod_win RUNTIME DESTINATION bin LIBRARY DESTINATION ${NL_DRIVER_PREFIX} ARCHIVE DESTINATION lib COMPONENT driverssound)
IF(WITH_MAXPLUGIN)
INSTALL(TARGETS nel_drv_fmod RUNTIME DESTINATION maxplugin COMPONENT driverssound)
INSTALL(TARGETS nel_drv_fmod_win RUNTIME DESTINATION maxplugin COMPONENT driverssound)
ENDIF(WITH_MAXPLUGIN)

View file

@ -1,4 +1,10 @@
FILE(GLOB SRC *.cpp *.h)
FILE(GLOB SRC *.cpp *.h *.def)
IF(WIN32)
SET(NLDRV_AL_LIB "nel_drv_openal_win")
ELSE(WIN32)
SET(NLDRV_AL_LIB "nel_drv_openal")
ENDIF(WIN32)
SOURCE_GROUP(efx FILES
effect_al.cpp
@ -18,31 +24,31 @@ SOURCE_GROUP(util FILES
ext_al.cpp
ext_al.h)
NL_TARGET_DRIVER(nel_drv_openal ${SRC})
NL_TARGET_DRIVER(${NLDRV_AL_LIB} ${SRC})
INCLUDE_DIRECTORIES(${OPENAL_INCLUDE_DIR})
IF(WITH_STLPORT)
TARGET_LINK_LIBRARIES(nel_drv_openal ${CMAKE_THREAD_LIBS_INIT})
TARGET_LINK_LIBRARIES(${NLDRV_AL_LIB} ${CMAKE_THREAD_LIBS_INIT})
ENDIF(WITH_STLPORT)
TARGET_LINK_LIBRARIES(nel_drv_openal ${OPENAL_LIBRARY} nelmisc nelsnd_lowlevel)
NL_DEFAULT_PROPS(nel_drv_openal "NeL, Driver, Sound: OpenAL")
NL_ADD_RUNTIME_FLAGS(nel_drv_openal)
NL_ADD_LIB_SUFFIX(nel_drv_openal)
TARGET_LINK_LIBRARIES(${NLDRV_AL_LIB} ${OPENAL_LIBRARY} nelmisc nelsnd_lowlevel)
NL_DEFAULT_PROPS(${NLDRV_AL_LIB} "NeL, Driver, Sound: OpenAL")
NL_ADD_RUNTIME_FLAGS(${NLDRV_AL_LIB})
NL_ADD_LIB_SUFFIX(${NLDRV_AL_LIB})
IF(WIN32)
# Find and include EFX-Util on Windows.
FIND_PACKAGE(EFXUtil)
INCLUDE_DIRECTORIES(${EFXUTIL_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(nel_drv_openal ${EFXUTIL_LIBRARY})
TARGET_LINK_LIBRARIES(${NLDRV_AL_LIB} ${EFXUTIL_LIBRARY})
ENDIF(WIN32)
IF(WITH_PCH)
ADD_NATIVE_PRECOMPILED_HEADER(nel_drv_openal ${CMAKE_CURRENT_SOURCE_DIR}/stdopenal.h ${CMAKE_CURRENT_SOURCE_DIR}/stdopenal.cpp)
ADD_NATIVE_PRECOMPILED_HEADER(${NLDRV_AL_LIB} ${CMAKE_CURRENT_SOURCE_DIR}/stdopenal.h ${CMAKE_CURRENT_SOURCE_DIR}/stdopenal.cpp)
ENDIF(WITH_PCH)
INSTALL(TARGETS nel_drv_openal RUNTIME DESTINATION bin LIBRARY DESTINATION ${NL_DRIVER_PREFIX} ARCHIVE DESTINATION lib COMPONENT driverssound)
INSTALL(TARGETS ${NLDRV_AL_LIB} RUNTIME DESTINATION bin LIBRARY DESTINATION ${NL_DRIVER_PREFIX} ARCHIVE DESTINATION lib COMPONENT driverssound)
IF(WITH_MAXPLUGIN)
INSTALL(TARGETS nel_drv_openal RUNTIME DESTINATION maxplugin COMPONENT driverssound)
INSTALL(TARGETS ${NLDRV_AL_LIB} RUNTIME DESTINATION maxplugin COMPONENT driverssound)
ENDIF(WITH_MAXPLUGIN)

View file

@ -1,4 +1,4 @@
FILE(GLOB SRC *.cpp *.h)
FILE(GLOB SRC *.cpp *.h *.def)
SOURCE_GROUP(sfx FILES
buffer_xaudio2.cpp
@ -26,21 +26,21 @@ SOURCE_GROUP(efx FILES
effect_xaudio2.cpp
effect_xaudio2.h)
NL_TARGET_DRIVER(nel_drv_xaudio2 ${SRC})
NL_TARGET_DRIVER(nel_drv_xaudio2_win ${SRC})
INCLUDE_DIRECTORIES(${DXSDK_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(nel_drv_xaudio2 nelmisc nelsnd_lowlevel ${DXSDK_XAUDIO_LIBRARY} ${DXSDK_GUID_LIBRARY})
TARGET_LINK_LIBRARIES(nel_drv_xaudio2_win nelmisc nelsnd_lowlevel ${DXSDK_XAUDIO_LIBRARY} ${DXSDK_GUID_LIBRARY})
NL_DEFAULT_PROPS(nel_drv_xaudio2 "NeL, Driver, Sound: XAudio2")
NL_ADD_RUNTIME_FLAGS(nel_drv_xaudio2)
NL_ADD_LIB_SUFFIX(nel_drv_xaudio2)
NL_DEFAULT_PROPS(nel_drv_xaudio2_win "NeL, Driver, Sound: XAudio2")
NL_ADD_RUNTIME_FLAGS(nel_drv_xaudio2_win)
NL_ADD_LIB_SUFFIX(nel_drv_xaudio2_win)
IF(WITH_PCH)
ADD_NATIVE_PRECOMPILED_HEADER(nel_drv_xaudio2 ${CMAKE_CURRENT_SOURCE_DIR}/stdxaudio2.h ${CMAKE_CURRENT_SOURCE_DIR}/stdxaudio2.cpp)
ADD_NATIVE_PRECOMPILED_HEADER(nel_drv_xaudio2_win ${CMAKE_CURRENT_SOURCE_DIR}/stdxaudio2.h ${CMAKE_CURRENT_SOURCE_DIR}/stdxaudio2.cpp)
ENDIF(WITH_PCH)
INSTALL(TARGETS nel_drv_xaudio2 RUNTIME DESTINATION bin LIBRARY DESTINATION ${NL_DRIVER_PREFIX} ARCHIVE DESTINATION lib COMPONENT driverssound)
INSTALL(TARGETS nel_drv_xaudio2_win RUNTIME DESTINATION bin LIBRARY DESTINATION ${NL_DRIVER_PREFIX} ARCHIVE DESTINATION lib COMPONENT driverssound)
IF(WITH_MAXPLUGIN)
INSTALL(TARGETS nel_drv_xaudio2 RUNTIME DESTINATION maxplugin COMPONENT driverssound)
INSTALL(TARGETS nel_drv_xaudio2_win RUNTIME DESTINATION maxplugin COMPONENT driverssound)
ENDIF(WITH_MAXPLUGIN)

View file

@ -35,17 +35,18 @@ IF(WIN32)
ADD_SUBDIRECTORY(tile_edit)
ENDIF(MFC_FOUND)
IF(WITH_MAXPLUGIN)
IF(WITH_NEL_MAXPLUGIN)
IF(MAXSDK_FOUND)
ADD_SUBDIRECTORY(plugin_max)
ADD_SUBDIRECTORY(ligo)
ENDIF(MAXSDK_FOUND)
ENDIF(WITH_MAXPLUGIN)
ENDIF(WITH_NEL_MAXPLUGIN)
ENDIF(WIN32)
IF(WITH_QT)
ADD_SUBDIRECTORY(tile_edit_qt)
ADD_SUBDIRECTORY(object_viewer_qt)
ENDIF(WITH_QT)
IF(SQUISH_FOUND)

View file

@ -161,7 +161,7 @@ bool putIn (NLMISC::CBitmap *pSrc, NLMISC::CBitmap *pDst, sint32 x, sint32 y, bo
// ***************************************************************************
string getBaseName (const string &fullname)
{
string sTmp2 = "";
string sTmp2;
string::size_type pos = fullname.rfind('_');
if (pos != string::npos)
sTmp2 = fullname.substr(0, pos+1);

View file

@ -346,7 +346,7 @@ int main(int argc, char **argv)
TextContext.setColor (CRGBA(255,255,255,255));
string sAllClusters = "";
string sAllClusters;
for( uint32 j = 0; j < vCluster.size(); ++j)
{
sAllClusters += vCluster[j]->Name;

View file

@ -171,7 +171,7 @@ bool putIn (NLMISC::CBitmap *pSrc, NLMISC::CBitmap *pDst, sint32 x, sint32 y)
// ---------------------------------------------------------------------------
string getBaseName (const string &fullname)
{
string sTmp2 = "";
string sTmp2;
string::size_type pos = fullname.rfind('_');
if (pos != string::npos)
sTmp2 = fullname.substr(0, pos+1);

View file

@ -0,0 +1,19 @@
#-----------------------------------------------------------------------------
#
# Object Viewer Qt
# Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
#
#-----------------------------------------------------------------------------
# This tells the application(s) where to fidn the installed data.
ADD_DEFINITIONS(-DDATA_DIR="\\"${NL_SHARE_PREFIX}/object_viewer_qt/\\"")
ADD_SUBDIRECTORY(src)
INSTALL(DIRECTORY data/
DESTINATION share/object_viewer_qt/data
COMPONENT data
PATTERN "CVS" EXCLUDE
PATTERN ".svn" EXCLUDE
PATTERN "Makefile*" EXCLUDE)

View file

@ -0,0 +1 @@
Put your license here!

View file

@ -0,0 +1 @@
Talk about how to use Hello World or who wrote it, that sort of stuff.

Binary file not shown.

View file

@ -0,0 +1,29 @@
RootConfigFilename = "object_viewer_default.cfg";
SearchPaths = {
"/mnt/disk_d/NEL3D/texture", "/mnt/disk_d/NEL3D/SFX/maps", "/mnt/disk_d/NEL3D/Database_proto/Stuff/fyros/agent/actors/_textures"
};
GraphicsEnabled = 1;
SoundEnabled = 1;
GraphicsDriver = "OpenGL";
SoundDriver = "OpenAL";
SoundDevice = "";
LanguageCode = "en";
QtStyle = "";
FontName = "andbasr.ttf";
FontShadow = 1;
BackgroundColor = {
98, 98, 98
};
FogStart = 0.0000000000;
FogEnd = 10.0000000000;
FogColor = {
88, 88, 88
};
SoundAutoLoadSample = 1;
SoundMaxTrack = 48;
SoundEnableOccludeObstruct = 1;
SoundEnableReverb = 1;
SoundManualRolloff = 1;
SoundUseADPCM = 0;
SoundForceSoftware = 0;
CameraFocal = 75.0000000000;

View file

@ -0,0 +1,156 @@
//////////////////////////////////////////////////////////////////////////////
// Config file for Object Viewer Qt ////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// This file is used to setup the Object Viewer tool.
//
//////////////////////////////////////////////////////////////////////////////
// NeL Qt ////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Root directory where we can find the client datas (zones, tiles, maps, ...)
// You must uncomment this line on GNU/Linux and comment the next one
//SearchPaths = { "/usr/local/share/games/nel_qt/" };
SearchPaths = { "data" };
// Which extensions to remap to what if needed (pairs of 2)
RemapExtensions = { "png", "tga", "dds", "tga"};
// The language code of the client
LanguageCode = "en";
// If changes to the config should be saved on exit
SaveConfig = 1;
//////////////////////////////////////////////////////////////////////////////
// Qt ////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
QtStyle = "Cleanlooks";
QtPalette = 0;
QtWindowState = "";
QtWindowGeometry = "";
//////////////////////////////////////////////////////////////////////////////
// Graphics //////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Use OpenGL or Direct3D (Windows)
GraphicsEnabled = 1;
GraphicsDrivers = { "OpenGL", "Direct3D" };
GraphicsDriver = "OpenGL";
// Resolution of the screen
// ScreenWidth = 1360;
// ScreenHeight = 768;
// ScreenDepth = 32;
// If 1, run in fullscreen mode, 0 for windowed
// Fullscreen = 0;
// Font name used for all text in the client (it can be a .ttf, .fon, .pfb)
FontName = "andbasr.ttf";
FontShadow = 1;
// Background color
BackgroundColor = { 151, 156, 182 };
// Bloom effect
BloomEffect = 1;
BloomSquare = 1;
BloomDensity = 120;
// Path where screenshots are saved
ScreenshotName = "nel_qt";
ScreenshotJPG = 1;
ScreenshotPNG = 1;
ScreenshotTGA = 0;
ScreenshotPath = "screenshots";
//////////////////////////////////////////////////////////////////////////////
// Environment ///////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
CameraFocal = 75.0;
SunDirection = { -2.935, +0.107, -1.22 };
SunAmbient = { 190, 170, 150 };
SunDiffuse = { 255, 248, 255 };
SunSpecular = { 255, 255, 255};
// 1 if you want to see the fog
FogEnable = 1;
FogStart = 100.0; // in meter
FogEnd = 250.0; // in meter
FogColor = { 129, 136, 205 }; // { 147, 125, 114 };
/////////////////////////////////////////////////////////////
//// Vegetable Landscape Setup (for vegetable edition) //////
/////////////////////////////////////////////////////////////
VegetTileBank = ""; // this is optional, but obligatory for Vegetable Edit to work properly
VegetTileFarBank = ""; // this is optional, but obligatory for Vegetable Edit to work properly
VegetLandscapeZones = // this is optional, but obligatory for Vegetable Edit to work properly
{
"WARNING: Delete this string" // NOT DELETE
};
VegetLandscapeThreshold = 0.01; // this is optional
VegetLandscapeTileNear = 50.0; // this is optional
VegetLandscapeAmbient = {17, 54, 100, 255} ; // this is optional
VegetLandscapeDiffuse = {241, 226, 244, 255} ; // this is optional
VegetLandscapeSnapHeight = 1.70; // this is optional
VegetLandscapeMultiply = 1.5;
// veget setup
VegetTexture = ""; // this is optional, but important for Vegetable Edit to behave properly
VegetAmbient = {80, 80, 80}; // this is optional
VegetDiffuse = {255, 255, 255}; // this is optional. NB: works like veget_landscape_diffuse (ie maxLightFactor possible)
VegetLightDir = {0.0, 1.0, -1.0}; // this is optional
VegetWindDir = {1.0, 1.0, 0.0}; // this is optional
VegetWindFreq = 0.5; // this is optional
VegetWindPower = 5.0; // this is optional
VegetWindBendMin = 0.5; // this is optional
//////////////////////////////////////////////////////////////////////////////
// Time //////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
FpsSmoothing = 64;
//////////////////////////////////////////////////////////////////////////////
// Sound /////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// The sound driver, choose between "Auto", "FMod", "DSound" and "OpenAl"
SoundEnabled = 1;
SoundDrivers = { "Auto", "OpenAL", "XAudio2", "FMod", "DSound" };
SoundDriver = "OpenAL";
SoundDevice = "";
SoundMaxTrack = 48;
SoundEnableOccludeObstruct = 1;
SoundEnableReverb = 1;
SoundManualRolloff = 1;
SoundUseADPCM = 0;
SoundForceSoftware = 0;
SoundAutoLoadSample = 1;
SoundPackedSheetPath = "/home/timon/sound";
SoundSamplePath = "/home/timon/sound";
//////////////////////////////////////////////////////////////////////////////
// Interface /////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Debug HUD /////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// end of file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

View file

@ -0,0 +1,11 @@
@echo off
del html\ovqt\*.* /Q
set WORKDIR=%CD%
cd ..
set CURDIR=%CD%
cd %WORKDIR%
doxygen ovqt.dox -DCURDIR
pause

View file

@ -0,0 +1,9 @@
#!/bin/sh
rm -rf html/ovqt
WORKDIR=$(pwd)
cd ..
export CURDIR=$(pwd)
cd $WORKDIR
doxygen ovqt.dox -DCURDIR

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,63 @@
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${LIBXML2_INCLUDE_DIR} ${NEL_INCLUDE_DIR} ${QT_INCLUDES})
INCLUDE( ${QT_USE_FILE} )
FILE(GLOB OBJECT_VIEWER_SRC configuration.h entity.h object_viewer.h particle_editor.h modules.h sound_system.h
particle_node.h ps_initial_pos.h dup_ps.h vegetable_editor.h vegetable_node.h *.cpp)
SET(OBJECT_VIEWER_HDR main_window.h graphics_viewport.h animation_dialog.h
animation_set_dialog.h settings_dialog.h setup_fog_dialog.h
slot_manager_dialog.h particle_control_dialog.h particle_workspace_dialog.h
particle_tree_model.h particle_system_page.h particle_workspace_page.h edit_range_widget.h
emitter_page.h attrib_widget.h located_bindable_page.h located_page.h
particle_force_page.h particle_light_page.h particle_zone_page.h particle_sound_page.h
basic_edit_widget.h direction_widget.h color_edit_widget.h particle_property_dialog.h
ps_mover_page.h graphics_info_widget.h value_blender_dialog.h value_gradient_dialog.h
value_from_emitter_dialog.h curve_dialog.h bin_op_dialog.h hoverpoints.h
mesh_widget.h morph_mesh_dialog.h constraint_mesh_widget.h tail_particle_widget.h
auto_lod_dialog.h particle_texture_widget.h particle_texture_anim_widget.h
multi_tex_dialog.h spinner_dialog.h follow_path_dialog.h water_pool_dialog.h
skeleton_scale_dialog.h skeleton_tree_model.h particle_link_skeleton_dialog.h
vegetable_dialog.h global_wind_dialog.h day_night_dialog.h sun_color_dialog.h
vegetable_noise_value_widget.h vegetable_density_page.h vegetable_landscape_page.h
vegetable_scale_page.h vegetable_appearance_page.h vegetable_rotate_page.h)
SET(OBJECT_VIEWER_UIS animation_form.ui animation_set_form.ui settings_form.ui
setup_fog_form.ui slot_form.ui particle_control_form.ui particle_workspace_form.ui
edit_range_float_form.ui edit_range_uint_form.ui particle_system_form.ui workspace_form.ui
attrib_form.ui emitter_form.ui located_bindable_form.ui located_form.ui
particle_force_form.ui particle_light_form.ui particle_zone_form.ui particle_sound_form.ui
basic_edit_form.ui direction_form.ui color_edit_form.ui ps_mover_form.ui curve_form.ui
mesh_form.ui morph_mesh_form.ui constraint_mesh_form.ui tail_form.ui auto_lod_form.ui
particle_texture_form.ui particle_texture_anim_form.ui multi_tex_form.ui skeleton_scale_form.ui
particle_link_skeleton_form.ui water_pool_form.ui vegetable_dialog_form.ui
vegetable_noise_value_form.ui global_wind_form.ui sun_color_form.ui day_night_form.ui
vegetable_density_form.ui vegetable_apperance_form.ui vegetable_landscape_form.ui
vegetable_rotate_form.ui vegetable_scale_form.ui)
SET(OBJECT_VIEWER_RCS object_viewer_qt.qrc)
SET(QT_USE_QTGUI TRUE)
SET(QT_USE_QTOPENGL TRUE)
QT4_ADD_RESOURCES( OBJECT_VIEWER_RC_SRCS ${OBJECT_VIEWER_RCS} )
QT4_WRAP_CPP( OBJECT_VIEWER_MOC_SRCS ${OBJECT_VIEWER_HDR} )
QT4_WRAP_UI( OBJECT_VIEWER_UI_HDRS ${OBJECT_VIEWER_UIS} )
ADD_EXECUTABLE(object_viewer_qt WIN32 ${OBJECT_VIEWER_SRC} ${OBJECT_VIEWER_MOC_SRCS} ${OBJECT_VIEWER_RC_SRCS} ${OBJECT_VIEWER_UI_HDRS})
TARGET_LINK_LIBRARIES(object_viewer_qt
nelmisc
nel3d
nelsound
nelligo
nelgeorges
${QT_LIBRARIES}
${QT_QTOPENGL_LIBRARY}
${QT_QTMAIN_LIBRARY})
ADD_DEFINITIONS(-DQT_NO_KEYWORDS ${LIBXML2_DEFINITIONS} ${QT_DEFINITIONS})
NL_DEFAULT_PROPS(object_viewer_qt "NeL, Tools, 3D: Object Viewer Qt")
NL_ADD_RUNTIME_FLAGS(object_viewer_qt)
IF(WITH_PCH)
ADD_NATIVE_PRECOMPILED_HEADER(object_viewer_qt ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.h ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.cpp)
ENDIF(WITH_PCH)
INSTALL(TARGETS object_viewer_qt RUNTIME DESTINATION bin COMPONENT runtime)

View file

@ -0,0 +1,190 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "animation_dialog.h"
// Qt includes
// NeL includes
// Project includes
#include "modules.h"
using namespace NLMISC;
namespace NLQT {
CAnimationDialog::CAnimationDialog(QWidget *parent)
: QDockWidget(parent)
{
_ui.setupUi(this);
//setFixedHeight(sizeHint().height());
connect(_ui.startPushButton, SIGNAL(clicked()), this, SLOT(start()));
connect(_ui.playPushButton, SIGNAL(clicked()), this, SLOT(play()));
connect(_ui.stopPushButton, SIGNAL(clicked()), this, SLOT(stop()));
connect(_ui.endPushButton, SIGNAL(clicked()), this, SLOT(end()));
connect(_ui.horizontalSlider, SIGNAL(sliderMoved(int)), this, SLOT(changeFrame(int)));
connect(_ui.startSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeStartAnim(int)));
connect(_ui.endSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeEndAnim(int)));
// init QTimeLine
_timeLine = new QTimeLine(_ui.endSpinBox->value() * _frameRate, this);
_timeLine->setCurveShape(QTimeLine::LinearCurve);
_timeLine->setUpdateInterval(25);
_timeLine->setFrameRange(_ui.startSpinBox->value(), _ui.endSpinBox->value());
connect(_timeLine, SIGNAL(frameChanged(int)), this, SLOT(updateAnim(int)));
connect(_timeLine, SIGNAL(finished()), this, SLOT(finish()));
connect(_ui.incPosCheckBox, SIGNAL(toggled(bool)), this, SLOT(setIncPos(bool)));
connect(_ui.inPlaceCheckBox, SIGNAL(toggled(bool)), this, SLOT(setInPlace(bool)));
// sync horizontalSlider with a timeLine
_ui.endSpinBox->setValue(99);
}
CAnimationDialog::~CAnimationDialog()
{
}
NL3D::TAnimationTime CAnimationDialog::getTime ()
{
return float(_timeLine->currentFrame()) / _frameRate;
}
void CAnimationDialog::changeAnimLength()
{
std::string curObj = Modules::objView().getCurrentObject();
if (curObj.empty())
return;
CEntity &entity = Modules::objView().getEntity(curObj);
float animLength = entity.getPlayListLength();
_ui.startSpinBox->setValue(0);
_ui.endSpinBox->setValue(int(animLength * _frameRate));
}
void CAnimationDialog::setCurrentShape(const QString &name)
{
if (name.isEmpty())
return;
CEntity &entity = Modules::objView().getEntity(name.toStdString());
_ui.inPlaceCheckBox->setChecked(entity.getInPlace());
_ui.incPosCheckBox->setChecked(entity.getIncPos());
}
void CAnimationDialog::start()
{
_timeLine->setCurrentTime((float(_ui.startSpinBox->value()) / _frameRate) * 1000);
}
void CAnimationDialog::play()
{
std::string curObj = Modules::objView().getCurrentObject();
if (curObj.empty())
{
_ui.playPushButton->setChecked(false);
return;
}
CEntity &entity = Modules::objView().getEntity(curObj);
entity.playbackAnim(true);
if (_timeLine->state() == QTimeLine::Running)
_timeLine->setPaused(true);
else if (_timeLine->currentFrame() == _timeLine->endFrame()) _timeLine->start();
else
_timeLine->resume();
}
void CAnimationDialog::stop()
{
_timeLine->stop();
_timeLine->setCurrentTime(0);
_ui.playPushButton->setChecked(false);
std::string curObj = Modules::objView().getCurrentObject();
if (curObj.empty())
return;
CEntity &entity = Modules::objView().getEntity(curObj);
entity.playbackAnim(false);
}
void CAnimationDialog::end()
{
_timeLine->setCurrentTime((float(_ui.endSpinBox->value()) / _frameRate) * 1000);
}
void CAnimationDialog::changeFrame(int frame)
{
if (_timeLine->state() == QTimeLine::Running)
{
_timeLine->setPaused(true);
_timeLine->setCurrentTime((float(frame) / _frameRate) * 1000);
_timeLine->resume();
}
else _timeLine->setCurrentTime((float(frame) / _frameRate) * 1000);
}
void CAnimationDialog::changeStartAnim(int start)
{
_timeLine->setDuration((float(start - _ui.startSpinBox->value()) / _frameRate) * 1000);
_timeLine->setFrameRange(start, _ui.endSpinBox->value());
}
void CAnimationDialog::changeEndAnim(int end)
{
_ui.horizontalSlider->setMaximum(end);
_timeLine->setDuration((float(end - _ui.startSpinBox->value()) / _frameRate) * 1000);
_timeLine->setFrameRange(_ui.startSpinBox->value(), end);
}
void CAnimationDialog::updateAnim(int frame)
{
_ui.horizontalSlider->setSliderPosition(frame);
}
void CAnimationDialog::setInPlace(bool state)
{
std::string curObj = Modules::objView().getCurrentObject();
if (curObj.empty())
return;
CEntity &entity = Modules::objView().getEntity(curObj);
entity.setInPlace(state);
}
void CAnimationDialog::setIncPos(bool state)
{
std::string curObj = Modules::objView().getCurrentObject();
if (curObj.empty())
return;
CEntity &entity = Modules::objView().getEntity(curObj);
entity.setIncPos(state);
}
void CAnimationDialog::finish()
{
if (_ui.loopCheckBox->checkState() == Qt::Checked) play();
else _ui.playPushButton->setChecked(false);
}
} /* namespace NLQT */

View file

@ -0,0 +1,91 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANIMATION_DIALOG_H
#define ANIMATION_DIALOG_H
#include <nel/misc/types_nl.h>
#include "ui_animation_form.h"
// Qt includes
#include <QtCore/QTimeLine>
// STL includes
// NeL includes
#include "nel/3d/animation_time.h"
// Project includes
namespace NLQT {
/**
@class CAnimationDialog
@brief Animation model control dialog.
@details The dialogue doesn't affect on the model itself, but only calculates the current time of animations
that can be obtained through a class method getTime().
The user can influence on the duration of the animation, but he doesn't know the total time for all the animations in the playlist.
Therefore, the class provides a slot that requires a total duration of the animated object animations and set it.
*/
class CAnimationDialog: public QDockWidget
{
Q_OBJECT
public:
/// Constructor, sets the default length of time from 0 to 99
CAnimationDialog(QWidget *parent = 0);
~CAnimationDialog();
/// Get the current time animations
/// @return Returns the current time animations, which can then be use in class CObjectViewer
NL3D::TAnimationTime getTime ();
public Q_SLOTS:
/// Find the total time of the playlist and sets its
void changeAnimLength();
/// Updates animation status for the selected current object
/// @param name - the name of the selected object
void setCurrentShape(const QString &name);
private Q_SLOTS:
void start();
void play();
void stop();
void end();
void changeFrame(int frame);
void changeStartAnim(int start);
void changeEndAnim(int end);
void updateAnim(int frame);
void setInPlace(bool state);
void setIncPos(bool state);
void finish();
private:
static const int _frameRate = 50;
QTimeLine *_timeLine;
Ui::CAnimationDialog _ui;
friend class CMainWindow;
}; /* CAnimationDialog */
} /* namespace NLQT */
#endif // ANIMATION_DIALOG_H

View file

@ -0,0 +1,392 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CAnimationDialog</class>
<widget class="QDockWidget" name="CAnimationDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>519</width>
<height>98</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>519</width>
<height>98</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>524287</width>
<height>524287</height>
</size>
</property>
<property name="floating">
<bool>false</bool>
</property>
<property name="features">
<set>QDockWidget::AllDockWidgetFeatures</set>
</property>
<property name="allowedAreas">
<set>Qt::AllDockWidgetAreas</set>
</property>
<property name="windowTitle">
<string>Animation </string>
</property>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="7">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QSlider" name="horizontalSlider">
<property name="maximum">
<number>99</number>
</property>
<property name="pageStep">
<number>10</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
<property name="invertedControls">
<bool>false</bool>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>10</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="currentSpinBox">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="maximum">
<number>999999</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<item>
<widget class="QSpinBox" name="startSpinBox">
<property name="buttonSymbols">
<enum>QAbstractSpinBox::UpDownArrows</enum>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="maximum">
<number>999999</number>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="loopCheckBox">
<property name="text">
<string>Loop</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="inPlaceCheckBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>In place</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="incPosCheckBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Increment pos</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="endSpinBox">
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="maximum">
<number>999999</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="startPushButton">
<property name="minimumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="object_viewer_qt.qrc">
<normaloff>:/images/skip-backward.png</normaloff>:/images/skip-backward.png</iconset>
</property>
<property name="iconSize">
<size>
<width>28</width>
<height>28</height>
</size>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="backwardPushButton">
<property name="minimumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="object_viewer_qt.qrc">
<normaloff>:/images/seek-backward.png</normaloff>:/images/seek-backward.png</iconset>
</property>
<property name="iconSize">
<size>
<width>28</width>
<height>28</height>
</size>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QToolButton" name="playPushButton">
<property name="minimumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="object_viewer_qt.qrc">
<normaloff>:/images/play.png</normaloff>
<normalon>:/images/pause.png</normalon>:/images/play.png</iconset>
</property>
<property name="iconSize">
<size>
<width>28</width>
<height>28</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QToolButton" name="stopPushButton">
<property name="minimumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="object_viewer_qt.qrc">
<normaloff>:/images/stop.png</normaloff>:/images/stop.png</iconset>
</property>
<property name="iconSize">
<size>
<width>28</width>
<height>28</height>
</size>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QToolButton" name="forwardPushButton">
<property name="minimumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="object_viewer_qt.qrc">
<normaloff>:/images/seek-forward.png</normaloff>:/images/seek-forward.png</iconset>
</property>
<property name="iconSize">
<size>
<width>28</width>
<height>28</height>
</size>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="QToolButton" name="endPushButton">
<property name="minimumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="object_viewer_qt.qrc">
<normaloff>:/images/skip-forward.png</normaloff>:/images/skip-forward.png</iconset>
</property>
<property name="iconSize">
<size>
<width>28</width>
<height>28</height>
</size>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources>
<include location="object_viewer_qt.qrc"/>
</resources>
<connections>
<connection>
<sender>currentSpinBox</sender>
<signal>valueChanged(int)</signal>
<receiver>horizontalSlider</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>151</x>
<y>55</y>
</hint>
<hint type="destinationlabel">
<x>163</x>
<y>77</y>
</hint>
</hints>
</connection>
<connection>
<sender>horizontalSlider</sender>
<signal>valueChanged(int)</signal>
<receiver>currentSpinBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>224</x>
<y>85</y>
</hint>
<hint type="destinationlabel">
<x>141</x>
<y>55</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -0,0 +1,293 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "animation_set_dialog.h"
// Qt includes
#include <QtGui/QFileDialog>
// NeL includes
// Project includes
#include "modules.h"
#include "entity.h"
namespace NLQT {
CAnimationSetDialog::CAnimationSetDialog(QWidget *parent)
: QDockWidget(parent)
{
ui.setupUi(this);
connect(ui.addToolButton, SIGNAL(clicked()), this, SLOT(addAnim()));
connect(ui.removeToolButton, SIGNAL(clicked()), this, SLOT(removeAnim()));
connect(ui.upToolButton, SIGNAL(clicked()), this, SLOT(upAnim()));
connect(ui.downToolButton, SIGNAL(clicked()), this, SLOT(downAnim()));
connect(ui.addAnimPushButton, SIGNAL(clicked()), this, SLOT(loadAnim()));
connect(ui.addSwtPushButton, SIGNAL(clicked()), this, SLOT(loadSwt()));
connect(ui.resetPushButton, SIGNAL(clicked()), this, SLOT(resetAnim()));
connect(ui.listRadioButton, SIGNAL(clicked(bool)), this, SLOT(setModeAnim()));
connect(ui.mixerRadioButton, SIGNAL(clicked(bool)), this, SLOT(setModeAnim()));
connect(ui.objectsComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(setCurrentShape(QString)));
}
CAnimationSetDialog::~CAnimationSetDialog()
{
}
void CAnimationSetDialog::setCurrentShape(const QString &name)
{
if (name.isEmpty())
return;
Modules::objView().setCurrentObject(name.toStdString());
updateListAnim();
Q_EMIT changeCurrentShape(name);
}
void CAnimationSetDialog::setModeAnim()
{
std::string curObj = Modules::objView().getCurrentObject();
if (curObj.empty())
return;
CEntity &entity = Modules::objView().getEntity(curObj);
if (ui.mixerRadioButton->isChecked())
entity.setMode(CEntity::Mode::Mixer);
else
entity.setMode(CEntity::Mode::PlayList);
}
void CAnimationSetDialog::updateListObject()
{
ui.objectsComboBox->clear();
std::vector<std::string> listObjects;
Modules::objView().getListObjects(listObjects);
for (size_t i = 0; i < listObjects.size(); i++)
ui.objectsComboBox->addItem(QString(listObjects[i].c_str()));
if (listObjects.empty())
{
ui.addAnimPushButton->setEnabled(false);
ui.addSwtPushButton->setEnabled(false);
ui.resetPushButton->setEnabled(false);
ui.setLengthPushButton->setEnabled(false);
}
else
{
ui.addAnimPushButton->setEnabled(true);
ui.addSwtPushButton->setEnabled(true);
ui.resetPushButton->setEnabled(true);
ui.setLengthPushButton->setEnabled(true);
}
}
void CAnimationSetDialog::updateListAnim()
{
ui.animTreeWidget->clear();
ui.animPlaylistWidget->clear();
ui.skeletonTreeWidget->clear();
std::string curObj = Modules::objView().getCurrentObject();
if (curObj.empty())
return;
CEntity &entity = Modules::objView().getEntity(curObj);
std::vector<std::string>& animationList = entity.getAnimationList();
std::vector<std::string>& swtList = entity.getSWTList();
std::vector<std::string>& playListAnimation = entity.getPlayListAnimation();
// update animation list widget
for(size_t i = 0; i < animationList.size(); ++i)
{
QTreeWidgetItem *item = new QTreeWidgetItem(ui.animTreeWidget);
item->setText(0,QString(animationList[i].c_str()));
}
// update skeleton weight template list widget
for(size_t i = 0; i < swtList.size(); ++i)
{
QTreeWidgetItem *item = new QTreeWidgetItem(ui.skeletonTreeWidget);
item->setText(0,QString(swtList[i].c_str()));
}
// update PlayList animation widget
for(size_t i = 0; i < playListAnimation.size(); ++i)
{
QListWidgetItem *item = new QListWidgetItem(ui.animPlaylistWidget);
item->setText(QString(playListAnimation[i].c_str()));
}
if (animationList.empty())
{
// lock buttons
ui.addToolButton->setEnabled(false);
ui.removeToolButton->setEnabled(false);
ui.upToolButton->setEnabled(false);
ui.downToolButton->setEnabled(false);
}
else
{
// unlock buttons
ui.addToolButton->setEnabled(true);
ui.removeToolButton->setEnabled(true);
ui.upToolButton->setEnabled(true);
ui.downToolButton->setEnabled(true);
}
}
void CAnimationSetDialog::loadAnim()
{
CEntity &entity = Modules::objView().getEntity(Modules::objView().getCurrentObject());
QStringList fileNames = QFileDialog::getOpenFileNames(this,
tr("Open NeL anim file"), ".",
tr("NeL anim files (*.anim);;"));
setCursor(Qt::WaitCursor);
if (!fileNames.isEmpty())
{
QStringList list = fileNames;
QStringList::Iterator it = list.begin();
while(it != list.end())
{
std::string animName = it->toStdString();
entity.loadAnimation(animName);
++it;
}
updateListAnim();
}
setCursor(Qt::ArrowCursor);
}
void CAnimationSetDialog::loadSwt()
{
CEntity &entity = Modules::objView().getEntity(Modules::objView().getCurrentObject());
QStringList fileNames = QFileDialog::getOpenFileNames(this,
tr("Open NeL anim file"), ".",
tr("NeL Skeleton Weight Template files (*.swt);;"));
setCursor(Qt::WaitCursor);
if (!fileNames.isEmpty())
{
QStringList list = fileNames;
QStringList::Iterator it = list.begin();
while(it != list.end())
{
std::string swtName = it->toStdString();
entity.loadSWT(swtName);
++it;
}
updateListAnim();
}
setCursor(Qt::ArrowCursor);
}
void CAnimationSetDialog::resetAnim()
{
CEntity &entity = Modules::objView().getEntity(Modules::objView().getCurrentObject());
entity.reset();
updateListAnim();
}
void CAnimationSetDialog::addAnim()
{
CEntity &entity = Modules::objView().getEntity(Modules::objView().getCurrentObject());
QList<QTreeWidgetItem*> list = ui.animTreeWidget->selectedItems();
Q_FOREACH(QTreeWidgetItem* item, list)
{
std::string animName = item->text(0).toStdString();
entity.addAnimToPlayList(animName);
ui.animPlaylistWidget->addItem(item->text(0));
}
}
void CAnimationSetDialog::removeAnim()
{
CEntity &entity = Modules::objView().getEntity(Modules::objView().getCurrentObject());
QList<QListWidgetItem*> list = ui.animPlaylistWidget->selectedItems();
Q_FOREACH(QListWidgetItem* item, list)
{
int row = ui.animPlaylistWidget->row(item);
QListWidgetItem *removeItem = ui.animPlaylistWidget->takeItem(row);
if (!removeItem)
delete removeItem;
entity.removeAnimToPlayList(row);
}
}
void CAnimationSetDialog::upAnim()
{
CEntity &entity = Modules::objView().getEntity(Modules::objView().getCurrentObject());
QList<QListWidgetItem*> list = ui.animPlaylistWidget->selectedItems();
if (list.empty())
return;
int frontRow = ui.animPlaylistWidget->row(list.front());
int backRow = ui.animPlaylistWidget->row(list.back());
if (frontRow == 0)
return;
QListWidgetItem *item = ui.animPlaylistWidget->takeItem(frontRow - 1);
ui.animPlaylistWidget->insertItem(backRow, item);
for (int i = frontRow; i <= backRow; ++i)
entity.swapAnimToPlayList(i - 1, i);
}
void CAnimationSetDialog::downAnim()
{
CEntity &entity = Modules::objView().getEntity(Modules::objView().getCurrentObject());
QList<QListWidgetItem*> list = ui.animPlaylistWidget->selectedItems();
if (list.empty())
return;
int frontRow = ui.animPlaylistWidget->row(list.front());
int backRow = ui.animPlaylistWidget->row(list.back());
if (backRow == (ui.animPlaylistWidget->count() - 1))
return;
QListWidgetItem *item = ui.animPlaylistWidget->takeItem(backRow + 1);
ui.animPlaylistWidget->insertItem(frontRow, item);
for (int i = backRow; i >= frontRow; --i)
entity.swapAnimToPlayList(i, i + 1);
}
} /* namespace NLQT */

View file

@ -0,0 +1,86 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANIMATION_SET_DIALOG_H
#define ANIMATION_SET_DIALOG_H
#include "ui_animation_set_form.h"
// STL includes
// NeL includes
// Project includes
namespace NLQT {
/**
@class CAnimationSetDialog
@brief Dialog - Animations control, loading animation, weight for skeleton and playlist composition.
@details Dialog loads animations files and weight for skeleton animation. Files can also be unloaded.
For loading / unloading and animation control dialog uses the functionality of CEntity class.
But the main opportunity for dialogue is to generating animations playlists.
Also, the dialogue has a control element to select the current shape (emit a signal changeCurrentShape())
and switch of playlist/mixer (this functionality will soon be transferred to another specialized dialogue).
As each shape has its own list of loaded animations and playlist,when you switch your current shape,
the dialogue should be notified through the slot setCurrentShape ().
*/
class CAnimationSetDialog: public QDockWidget
{
Q_OBJECT
public:
CAnimationSetDialog(QWidget *parent = 0);
~CAnimationSetDialog();
/// Update the objects list (this function should be moved to another dialogue)
void updateListObject();
/// Update the list of loaded animation files
void updateListAnim();
Q_SIGNALS:
/// Signal emitted when changing the current animation object.
void changeCurrentShape(const QString &name);
public Q_SLOTS:
/// Updates and displays the list of loaded animations and playlist for the selected current object
/// @param name - the name of the selected object
void setCurrentShape(const QString &name);
private Q_SLOTS:
void setModeAnim();
void loadAnim();
void loadSwt();
void resetAnim();
void addAnim();
void removeAnim();
void upAnim();
void downAnim();
private:
Ui::CAnimationSetDialog ui;
friend class CMainWindow;
}; /* CAnimationDialog */
} /* namespace NLQT */
#endif // ANIMATION_SET_DIALOG_H

View file

@ -0,0 +1,480 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CAnimationSetDialog</class>
<widget class="QDockWidget" name="CAnimationSetDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>300</width>
<height>562</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>390</height>
</size>
</property>
<property name="windowIcon">
<iconset resource="object_viewer_qt.qrc">
<normaloff>:/images/animset.png</normaloff>:/images/animset.png</iconset>
</property>
<property name="windowTitle">
<string>Animation set manager</string>
</property>
<widget class="QWidget" name="dockWidgetContents">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Edited object:</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="objectsComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QSplitter" name="splitter_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Animations:</string>
</property>
</widget>
</item>
<item>
<widget class="QTreeWidget" name="animTreeWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="dragEnabled">
<bool>false</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::NoDragDrop</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="columnCount">
<number>1</number>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Skeleton weight template:</string>
</property>
</widget>
</item>
<item>
<widget class="QTreeWidget" name="skeletonTreeWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>5646546</height>
</size>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="layoutWidget">
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0" colspan="4">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Animations playlist:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="5">
<widget class="QListWidget" name="animPlaylistWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="dragEnabled">
<bool>false</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::NoDragDrop</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::IgnoreAction</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ContiguousSelection</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QToolButton" name="addToolButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="object_viewer_qt.qrc">
<normaloff>:/images/list-add.png</normaloff>:/images/list-add.png</iconset>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QToolButton" name="removeToolButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="object_viewer_qt.qrc">
<normaloff>:/images/list-remove.png</normaloff>:/images/list-remove.png</iconset>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QToolButton" name="upToolButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="object_viewer_qt.qrc">
<normaloff>:/images/go-up.png</normaloff>:/images/go-up.png</iconset>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QToolButton" name="downToolButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="object_viewer_qt.qrc">
<normaloff>:/images/go-down.png</normaloff>:/images/go-down.png</iconset>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</widget>
</item>
<item row="2" column="4">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item row="2" column="0">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QPushButton" name="addAnimPushButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Add anim</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="addSwtPushButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Add swt</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="resetPushButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Reset</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="setLengthPushButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Set anim length</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QRadioButton" name="listRadioButton">
<property name="text">
<string>Use the list</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="mixerRadioButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Use the mixer</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<resources>
<include location="object_viewer_qt.qrc"/>
</resources>
<connections/>
</ui>

View file

@ -0,0 +1,291 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CAttribWidget</class>
<widget class="QGroupBox" name="CAttribWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>276</width>
<height>273</height>
</rect>
</property>
<property name="windowTitle">
<string>GroupBox</string>
</property>
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QComboBox" name="comboBox">
<item>
<property name="text">
<string>Constant</string>
</property>
</item>
<item>
<property name="text">
<string>Scheme</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0" colspan="3">
<widget class="NLQT::CBasicEditWidget" name="constAttribPlaneWidget" native="true">
<zorder>schemeWidget</zorder>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="NLQT::CColorEditWidget" name="constRGBAWidget" native="true"/>
</item>
<item row="4" column="0" colspan="3">
<widget class="NLQT::CEditRangeIntWidget" name="constRangeIntWidget" native="true"/>
</item>
<item row="5" column="0" colspan="3">
<widget class="NLQT::CEditRangeFloatWidget" name="constRangeFloatWidget" native="true"/>
</item>
<item row="6" column="0" colspan="3">
<widget class="NLQT::CEditRangeUIntWidget" name="constRangeUIntWidget" native="true"/>
</item>
<item row="7" column="0" rowspan="2" colspan="3">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="inputLabel">
<property name="text">
<string>Input mutliplier:</string>
</property>
</widget>
</item>
<item row="8" column="1" rowspan="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>108</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="8" column="2" rowspan="2">
<widget class="QCheckBox" name="clampCheckBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Clamp</string>
</property>
</widget>
</item>
<item row="10" column="0" colspan="3">
<widget class="NLQT::CEditRangeFloatWidget" name="inMultiplierWidget" native="true">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="11" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="3">
<widget class="QWidget" name="schemeWidget" native="true">
<property name="enabled">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QComboBox" name="schemeComboBox"/>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="editPushButton">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>E</string>
</property>
</widget>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="srcLabel">
<property name="text">
<string>Src:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="srcComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Date</string>
</property>
</item>
<item>
<property name="text">
<string>Position</string>
</property>
</item>
<item>
<property name="text">
<string>Inverse Mass</string>
</property>
</item>
<item>
<property name="text">
<string>Speed</string>
</property>
</item>
<item>
<property name="text">
<string>Random</string>
</property>
</item>
<item>
<property name="text">
<string>User param</string>
</property>
</item>
<item>
<property name="text">
<string>LOD</string>
</property>
</item>
<item>
<property name="text">
<string>Square LOD</string>
</property>
</item>
<item>
<property name="text">
<string>Clamped LOD</string>
</property>
</item>
<item>
<property name="text">
<string>Camped square LOD</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="userParamPushButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>U</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="putPushButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>P</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="getPushButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>G</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>NLQT::CEditRangeUIntWidget</class>
<extends>QWidget</extends>
<header>edit_range_widget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>NLQT::CEditRangeFloatWidget</class>
<extends>QWidget</extends>
<header>edit_range_widget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>NLQT::CBasicEditWidget</class>
<extends>QWidget</extends>
<header>basic_edit_widget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>NLQT::CColorEditWidget</class>
<extends>QWidget</extends>
<header>color_edit_widget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>NLQT::CEditRangeIntWidget</class>
<extends>QWidget</extends>
<header>edit_range_widget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,972 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "attrib_widget.h"
// Qt includes
#include <QtGui/QInputDialog>
// NeL includes
#include <nel/3d/ps_attrib_maker.h>
#include <nel/3d/ps_float.h>
#include <nel/3d/ps_int.h>
#include <nel/3d/ps_color.h>
#include <nel/3d/ps_plane_basis.h>
#include <nel/3d/ps_plane_basis_maker.h>
// Projects includes
#include "value_blender_dialog.h"
#include "value_gradient_dialog.h"
#include "bin_op_dialog.h"
#include "curve_dialog.h"
#include "value_from_emitter_dialog.h"
#include "spinner_dialog.h"
#include "follow_path_dialog.h"
namespace NLQT {
CAttribWidget::CAttribWidget(QWidget *parent)
: QGroupBox(parent),
_SrcInputEnabled(true),
_EnableConstantValue(true),
_DisableMemoryScheme(false),
_NbCycleEnabled(true),
_Node(NULL), _SchemeWidget(NULL)
{
_ui.setupUi(this);
_ui.constRangeUIntWidget->hide();
_ui.constRangeFloatWidget->hide();
_ui.constAttribPlaneWidget->hide();
_ui.constRangeIntWidget->hide();
_ui.constRGBAWidget->hide();
_ui.schemeWidget->hide();
_ui.inMultiplierWidget->setRange(0.1f, 10.1f);
_ui.inMultiplierWidget->enableLowerBound(0, true);;
_ui.inMultiplierWidget->setWrapper(&_NbCyclesWrapper);
_NbCyclesWrapper.widget = this;
}
CAttribWidget::~CAttribWidget()
{
}
void CAttribWidget::setEnabledConstantValue(bool enableConstantValue)
{
_EnableConstantValue = enableConstantValue;
}
void CAttribWidget::init()
{
connect(_ui.editPushButton, SIGNAL(clicked()), this, SLOT(clickedEdit()));
connect(_ui.clampCheckBox, SIGNAL(toggled(bool)), this, SLOT(setClamp(bool)));
connect(_ui.schemeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(changeCurrentScheme(int)));
connect(_ui.srcComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setCurrentSrc(int)));
connect(_ui.userParamPushButton, SIGNAL(clicked()), this, SLOT(setUserIndex()));
connect(_ui.comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(changeUseScheme(int)));
}
void CAttribWidget::updateUi()
{
if (!_EnableConstantValue)
_ui.comboBox->hide();
else
_ui.comboBox->show();
if (useScheme())
{
if (_ui.comboBox->currentIndex() == 1)
schemeValueUpdate();
else
_ui.comboBox->setCurrentIndex(1);
}
else
{
nlassert(_EnableConstantValue);
if (_ui.comboBox->currentIndex() == 0)
cstValueUpdate();
else
_ui.comboBox->setCurrentIndex(0);
}
}
void CAttribWidget::clickedEdit()
{
QDialog *dialog = editScheme();
if (dialog != NULL)
{
dialog->setModal(true);
dialog->show();
dialog->exec();
delete dialog;
}
}
void CAttribWidget::setClamp(bool state)
{
// avoid performance warning
if (state != isSchemeClamped())
clampScheme(state);
}
void CAttribWidget::changeCurrentScheme(int index)
{
if (getCurrentScheme() != index)
setCurrentScheme(uint(index));
schemeValueUpdate();
}
void CAttribWidget::setCurrentSrc(int index)
{
NL3D::CPSInputType it;
it.InputType = (NL3D::CPSInputType::TInputType) index;
if (it.InputType != getSchemeInput().InputType)
{
if (it.InputType == NL3D::CPSInputType::attrUserParam)
{
it.UserParamNum = 0;
}
setSchemeInput(it);
}
inputValueUpdate();
}
void CAttribWidget::setUserIndex()
{
bool ok;
int i = QInputDialog::getInt(this, tr("Set user param"), tr(""), getSchemeInput().UserParamNum + 1, 1, 4, 1, &ok);
if (ok)
{
NL3D::CPSInputType it = getSchemeInput();
it.UserParamNum = i - 1;
setSchemeInput(it);
}
inputValueUpdate();
}
void CAttribWidget::changeUseScheme(int index)
{
if (index == 0)
{
if (!useScheme())
resetCstValue(); // change constant
cstValueUpdate(); // update ui
}
else
{
if (useScheme())
changeCurrentScheme(getCurrentScheme()); // update ui
else
changeCurrentScheme(0); // change scheme
}
}
void CAttribWidget::inputValueUpdate(void)
{
if (useScheme() && getSchemeInput().InputType == NL3D::CPSInputType::attrUserParam)
{
//_ui.userParamPushButton->setText(tr("User param: %1").arg(getSchemeInput().UserParamNum + 1));
_ui.userParamPushButton->setEnabled(true);
}
else
{
//_ui.userParamPushButton->setText(tr("User param:"));
_ui.userParamPushButton->setEnabled(false);
}
}
void CAttribWidget::schemeValueUpdate()
{
if (!useScheme()) return;
_ui.constRangeUIntWidget->hide();
_ui.constRangeFloatWidget->hide();
_ui.constAttribPlaneWidget->hide();
_ui.constRangeIntWidget->hide();
_ui.constRGBAWidget->hide();
_ui.schemeWidget->show();
sint k = getCurrentScheme();
if (k == -1) // unknow scheme ...
{
_ui.schemeComboBox->setCurrentIndex(k);
k = 0;
}
if (k != _ui.schemeComboBox->currentIndex())
_ui.schemeComboBox->setCurrentIndex(k);
if (hasSchemeCustomInput() && _SrcInputEnabled)
{
_ui.srcLabel->setEnabled(true);
_ui.srcComboBox->setEnabled(true);
_ui.srcComboBox->setCurrentIndex(int(getSchemeInput().InputType));
_ui.clampCheckBox->setEnabled(isClampingSupported());
_ui.inMultiplierWidget->setEnabled(isClampingSupported());
_ui.inputLabel->setEnabled(isClampingSupported());
}
else
{
_ui.srcLabel->setEnabled(false);
_ui.srcComboBox->setEnabled(false);
inputValueUpdate();
_ui.clampCheckBox->setEnabled(false);
_ui.inMultiplierWidget->setEnabled(false);
_ui.inputLabel->setEnabled(false);
}
if (_NbCycleEnabled)
{
_ui.inMultiplierWidget->updateUi();
_ui.inMultiplierWidget->show();
_ui.inputLabel->show();
_ui.inMultiplierWidget->setEnabled(true);
_ui.clampCheckBox->show();
}
else
{
_ui.inputLabel->hide();
_ui.inMultiplierWidget->hide();
_ui.clampCheckBox->hide();
}
if (isClampingSupported())
_ui.clampCheckBox->setChecked(isSchemeClamped());
}
void CAttribWidget::enableMemoryScheme(bool enabled)
{
_DisableMemoryScheme = !enabled;
if (!enabled)
{
_ui.schemeComboBox->removeItem(_ui.schemeComboBox->count() - 1);
_ui.schemeComboBox->removeItem(_ui.schemeComboBox->count() - 1);
}
}
CAttribFloatWidget::CAttribFloatWidget(QWidget *parent)
: CAttribWidgetT<float>(parent)
{
_ui.schemeComboBox->addItem(tr("value blender"));
_ui.schemeComboBox->addItem(tr("values gradient"));
_ui.schemeComboBox->addItem(tr("curve"));
_ui.schemeComboBox->addItem(tr("value computed from emitter"));
_ui.schemeComboBox->addItem(tr("binary operator"));
}
CAttribFloatWidget::~CAttribFloatWidget()
{
}
void CAttribFloatWidget::setRange(float minValue, float maxValue)
{
_MinRange = minValue;
_MaxRange = maxValue;
_ui.constRangeFloatWidget->setRange(_MinRange, _MaxRange);
}
void CAttribFloatWidget::setWrapper(IPSWrapper<float> *wrapper)
{
nlassert(wrapper);
_Wrapper = wrapper;
_ui.constRangeFloatWidget->setWrapper(_Wrapper);
}
QDialog *CAttribFloatWidget::editScheme(void)
{
NL3D::CPSAttribMaker<float> *scheme = _SchemeWrapper->getScheme();
if (dynamic_cast<NL3D::CPSFloatBlender *>(scheme))
{
CFloatBlenderDialogClient *myInterface = new CFloatBlenderDialogClient();
myInterface->MinRange = _MinRange;
myInterface->MaxRange = _MaxRange;
myInterface->SchemeFunc = & ((NL3D::CPSValueBlenderSample<float, 64> *) scheme)->_F;
CValueBlenderDialog *vb = new CValueBlenderDialog(myInterface, _Node, true, this);
return vb;
}
if (dynamic_cast<NL3D::CPSFloatGradient *>(scheme))
{
CFloatGradientWrapper *wrapper = new CFloatGradientWrapper;
wrapper->MinRange = _MinRange;
wrapper->MaxRange = _MaxRange;
wrapper->Scheme = &(((NL3D::CPSFloatGradient *) (_SchemeWrapper->getScheme()) )->_F);
CGradientDialog *gd = new CGradientDialog(_Node, wrapper, true, true, 2, this);
wrapper->DefaultValue = 0.f;
return gd;
}
if (dynamic_cast<NL3D::CPSFloatMemory *>(scheme))
{
CAttribFloatWidget *adf = new CAttribFloatWidget();
adf->setRange(_MinRange, _MaxRange);
CValueFromEmitterDialogT<float> *vfe = new CValueFromEmitterDialogT<float>( (NL3D::CPSFloatMemory *)(scheme),
adf,
this);
vfe->init();
adf->setWorkspaceNode(_Node);
adf->updateUi();
return vfe;
}
if (dynamic_cast<NL3D::CPSFloatBinOp *>(scheme))
{
CAttribFloatWidget *ad[2] = { NULL, NULL};
for (uint k = 0; k <2; ++k)
{
ad[k] = new CAttribFloatWidget();
ad[k]->setRange(_MinRange, _MaxRange);
}
CBinOpDialogT<float> *bod = new CBinOpDialogT<float>( (NL3D::CPSFloatBinOp *)(scheme),
(CAttribWidgetT<float> **) ad,
this);
bod->init();
for (uint k = 0; k <2; ++k)
{
ad[k]->setWorkspaceNode(_Node);
ad[k]->updateUi();
}
return bod;
}
if (dynamic_cast<NL3D::CPSFloatCurve *>(scheme))
{
CurveEditDialog *curve = new CurveEditDialog(&(dynamic_cast<NL3D::CPSFloatCurve *>(scheme)->_F), _Node, this);
return curve;
}
return NULL;
}
void CAttribFloatWidget::setCurrentScheme(uint index)
{
nlassert(index < 5);
NL3D::CPSAttribMaker<float> *scheme = NULL;
switch (index)
{
case 0:
scheme = new NL3D::CPSFloatBlender(_MinRange, _MaxRange);
break;
case 1:
{
static const float values[2] = { 0.1f, 1.f };
scheme = new NL3D::CPSFloatGradient(values, 2, 16, 1.f);
}
break;
case 2:
{
NL3D::CPSFloatCurve *curve = new NL3D::CPSFloatCurve;
curve->_F.setNumSamples(128);
curve->_F.addControlPoint(NL3D::CPSFloatCurveFunctor::CCtrlPoint(0, 0.5f));
curve->_F.addControlPoint(NL3D::CPSFloatCurveFunctor::CCtrlPoint(1, 0.5f));
scheme = curve;
}
break;
case 3:
scheme = new NL3D::CPSFloatMemory;
((NL3D::CPSAttribMakerMemory<float> *) scheme)->setScheme(new NL3D::CPSFloatBlender(_MinRange, _MaxRange));
break;
case 4 :
scheme = new NL3D::CPSFloatBinOp;
((NL3D::CPSFloatBinOp *) scheme)->setArg(0, new NL3D::CPSFloatBlender);
((NL3D::CPSFloatBinOp *) scheme)->setArg(1, new NL3D::CPSFloatBlender);
break;
default:
break;
}
if (scheme)
{
_SchemeWrapper->setSchemeAndUpdateModifiedFlag(scheme);
}
}
sint CAttribFloatWidget::getCurrentScheme(void) const
{
const NL3D::CPSAttribMaker<float> *scheme = _SchemeWrapper->getScheme();
if (dynamic_cast<const NL3D::CPSFloatBlender *>(scheme))
return 0;
if (dynamic_cast<const NL3D::CPSFloatGradient *>(scheme))
return 1;
if (dynamic_cast<const NL3D::CPSFloatCurve *>(scheme))
return 2;
if (dynamic_cast<const NL3D::CPSFloatMemory *>(scheme))
return 3;
if (dynamic_cast<const NL3D::CPSFloatBinOp *>(scheme))
return 4;
return -1;
}
void CAttribFloatWidget::cstValueUpdate()
{
_ui.schemeWidget->hide();
_ui.inMultiplierWidget->setEnabled(false);
_ui.clampCheckBox->setEnabled(false);
_ui.inputLabel->setEnabled(false);
_ui.constRangeFloatWidget->show();
_ui.constRangeFloatWidget->updateUi();
}
CAttribUIntWidget::CAttribUIntWidget(QWidget *parent)
: CAttribWidgetT<uint32>(parent)
{
_ui.schemeComboBox->addItem(tr("value blender"));
_ui.schemeComboBox->addItem(tr("values gradient"));
_ui.schemeComboBox->addItem(tr("value computed from emitter"));
_ui.schemeComboBox->addItem(tr("binary operator"));
}
CAttribUIntWidget::~CAttribUIntWidget()
{
}
void CAttribUIntWidget::setRange(uint32 minValue, uint32 maxValue)
{
_MinRange = minValue;
_MaxRange = maxValue;
_ui.constRangeUIntWidget->setRange(_MinRange, _MaxRange);
}
void CAttribUIntWidget::setWrapper(IPSWrapper<uint32> *wrapper)
{
nlassert(wrapper);
_Wrapper = wrapper;
_ui.constRangeUIntWidget->setWrapper(_Wrapper);
}
QDialog *CAttribUIntWidget::editScheme(void)
{
const NL3D::CPSAttribMaker<uint32> *scheme = _SchemeWrapper->getScheme();
if (dynamic_cast<const NL3D::CPSUIntBlender *>(scheme))
{
CUIntBlenderDialogClient *myInterface = new CUIntBlenderDialogClient();
myInterface->MinRange = _MinRange;
myInterface->MaxRange = _MaxRange;
myInterface->SchemeFunc = & ((NL3D::CPSValueBlenderSample<uint32, 64> *) scheme)->_F;
CValueBlenderDialog *vb = new CValueBlenderDialog(myInterface, _Node, true, this);
return vb;
}
if (dynamic_cast<const NL3D::CPSUIntGradient *>(scheme))
{
CUIntGradientWrapper *wrapper = new CUIntGradientWrapper;
wrapper->MinRange = _MinRange;
wrapper->MaxRange = _MaxRange;
wrapper->Scheme = &(((NL3D::CPSUIntGradient *) (_SchemeWrapper->getScheme()) )->_F);
CGradientDialog *gd = new CGradientDialog(_Node, wrapper, true, true, 2, this);
wrapper->DefaultValue = 0;
return gd;
}
if (dynamic_cast<const NL3D::CPSUIntMemory *>(scheme))
{
CAttribUIntWidget *adu = new CAttribUIntWidget();
adu->setRange(_MinRange, _MaxRange);
CValueFromEmitterDialogT<uint32> *vfe = new CValueFromEmitterDialogT<uint32>( (NL3D::CPSUIntMemory *)(scheme),
adu,
this);
vfe->init();
adu->setWorkspaceNode(_Node);
adu->updateUi();
return vfe;
}
if (dynamic_cast<const NL3D::CPSUIntBinOp *>(scheme))
{
CAttribUIntWidget *ad[2] = { NULL, NULL};
for (uint k = 0; k <2; ++k)
{
ad[k] = new CAttribUIntWidget();
ad[k]->setRange(_MinRange, _MaxRange);
}
CBinOpDialogT<uint32> *bod = new CBinOpDialogT<uint32>( (NL3D::CPSUIntBinOp *)(scheme),
(CAttribWidgetT<uint32> **) ad,
this);
bod->init();
for (uint k = 0; k <2; ++k)
{
ad[k]->setWorkspaceNode(_Node);
ad[k]->updateUi();
}
return bod;
}
return NULL;
}
void CAttribUIntWidget::setCurrentScheme(uint index)
{
nlassert(index < 4);
NL3D::CPSAttribMaker<uint32> *scheme = NULL;
switch (index)
{
case 0 :
scheme = new NL3D::CPSUIntBlender(_MinRange, _MaxRange);
break;
case 1 :
scheme = new NL3D::CPSUIntGradient;
break;
case 2 :
scheme = new NL3D::CPSUIntMemory;
((NL3D::CPSAttribMakerMemory<uint32> *) scheme)->setScheme(new NL3D::CPSUIntBlender(_MinRange, _MaxRange) );
break;
case 3 :
scheme = new NL3D::CPSUIntBinOp;
((NL3D::CPSUIntBinOp *) scheme)->setArg(0, new NL3D::CPSUIntBlender);
((NL3D::CPSUIntBinOp *) scheme)->setArg(1, new NL3D::CPSUIntBlender);
break;
default:
break;
}
if (scheme)
{
_SchemeWrapper->setSchemeAndUpdateModifiedFlag(scheme);
}
}
sint CAttribUIntWidget::getCurrentScheme(void) const
{
const NL3D::CPSAttribMaker<uint32> *scheme = _SchemeWrapper->getScheme();
if (dynamic_cast<const NL3D::CPSUIntBlender *>(scheme)) return 0;
if (dynamic_cast<const NL3D::CPSUIntGradient *>(scheme)) return 1;
if (dynamic_cast<const NL3D::CPSUIntMemory *>(scheme)) return 2;
if (dynamic_cast<const NL3D::CPSUIntBinOp *>(scheme)) return 3;
return -1;
}
void CAttribUIntWidget::cstValueUpdate()
{
_ui.schemeWidget->hide();
_ui.inMultiplierWidget->setEnabled(false);
_ui.clampCheckBox->setEnabled(false);
_ui.inputLabel->setEnabled(false);
_ui.constRangeUIntWidget->show();
_ui.constRangeUIntWidget->updateUi();
}
CAttribIntWidget::CAttribIntWidget(QWidget *parent)
: CAttribWidgetT<sint32>(parent)
{
_ui.schemeComboBox->addItem(tr("value exact blender"));
_ui.schemeComboBox->addItem(tr("values gradient"));
_ui.schemeComboBox->addItem(tr("value computed from emitter"));
_ui.schemeComboBox->addItem(tr("binary operator"));
}
CAttribIntWidget::~CAttribIntWidget()
{
}
void CAttribIntWidget::setRange(sint32 minValue, sint32 maxValue)
{
_MinRange = minValue;
_MaxRange = maxValue;
_ui.constRangeIntWidget->setRange(_MinRange, _MaxRange);
}
void CAttribIntWidget::setWrapper(IPSWrapper<sint32> *wrapper)
{
nlassert(wrapper);
_Wrapper = wrapper;
_ui.constRangeIntWidget->setWrapper(_Wrapper);
}
QDialog *CAttribIntWidget::editScheme(void)
{
const NL3D::CPSAttribMaker<sint32> *scheme = _SchemeWrapper->getScheme();
if (dynamic_cast<const NL3D::CPSIntBlender *>(scheme))
{
CIntBlenderDialogClient *myInterface = new CIntBlenderDialogClient();
myInterface->MinRange = _MinRange;
myInterface->MaxRange = _MaxRange;
myInterface->SchemeFunc = & ((NL3D::CPSValueBlenderSample<sint32, 64> *) scheme)->_F;
CValueBlenderDialog *vb = new CValueBlenderDialog(myInterface, _Node, true, this);
return vb;
}
if (dynamic_cast<const NL3D::CPSIntGradient *>(scheme))
{
CIntGradientWrapper *wrapper = new CIntGradientWrapper;
wrapper->MinRange = _MinRange;
wrapper->MaxRange = _MaxRange;
wrapper->Scheme = &(((NL3D::CPSIntGradient *) (_SchemeWrapper->getScheme()) )->_F);
CGradientDialog *gd = new CGradientDialog(_Node, wrapper, true, true, 2, this);
wrapper->DefaultValue = 0;
return gd;
}
if (dynamic_cast<const NL3D::CPSIntMemory *>(scheme))
{
CAttribIntWidget *adi = new CAttribIntWidget();
adi->setRange(_MinRange, _MaxRange);
CValueFromEmitterDialogT<sint32> *vfe = new CValueFromEmitterDialogT<sint32>((NL3D::CPSIntMemory *) _SchemeWrapper->getScheme(),
adi, this);
vfe->init();
adi->setWorkspaceNode(_Node);
adi->updateUi();
return vfe;
}
if (dynamic_cast<const NL3D::CPSIntBinOp *>(scheme))
{
CAttribIntWidget *ad[2] = { NULL, NULL};
for (uint k = 0; k <2; ++k)
{
ad[k] = new CAttribIntWidget();
ad[k]->setRange(_MinRange, _MaxRange);
}
CBinOpDialogT<sint32> *bod = new CBinOpDialogT<sint32>( (NL3D::CPSIntBinOp *)(scheme),
(CAttribWidgetT<sint32> **) ad,
this);
bod->init();
for (uint k = 0; k <2; ++k)
{
ad[k]->setWorkspaceNode(_Node);
ad[k]->updateUi();
}
return bod;
}
return NULL;
}
void CAttribIntWidget::setCurrentScheme(uint index)
{
nlassert(index < 4);
NL3D::CPSAttribMaker<sint32> *scheme = NULL;
switch (index)
{
case 0 :
scheme = new NL3D::CPSIntBlender;
break;
case 1 :
scheme = new NL3D::CPSIntGradient;
break;
case 2 :
scheme = new NL3D::CPSIntMemory;
((NL3D::CPSAttribMakerMemory<sint32> *) scheme)->setScheme(new NL3D::CPSIntBlender(_MinRange, _MaxRange));
break;
case 3 :
scheme = new NL3D::CPSIntBinOp;
((NL3D::CPSIntBinOp *) scheme)->setArg(0, new NL3D::CPSIntBlender);
((NL3D::CPSIntBinOp *) scheme)->setArg(1, new NL3D::CPSIntBlender);
break;
default:
break;
}
if (scheme)
{
_SchemeWrapper->setSchemeAndUpdateModifiedFlag(scheme);
}
}
sint CAttribIntWidget::getCurrentScheme(void) const
{
const NL3D::CPSAttribMaker<sint32> *scheme = _SchemeWrapper->getScheme();
if (dynamic_cast<const NL3D::CPSIntBlender *>(scheme)) return 0;
if (dynamic_cast<const NL3D::CPSIntGradient *>(scheme)) return 1;
if (dynamic_cast<const NL3D::CPSIntMemory *>(scheme)) return 2;
if (dynamic_cast<const NL3D::CPSIntBinOp *>(scheme)) return 3;
return -1;
}
void CAttribIntWidget::cstValueUpdate()
{
_ui.schemeWidget->hide();
_ui.inMultiplierWidget->setEnabled(false);
_ui.clampCheckBox->setEnabled(false);
_ui.inputLabel->setEnabled(false);
_ui.constRangeIntWidget->show();
//_ui.constRangeIntWidget->updateUi();
}
CAttribRGBAWidget::CAttribRGBAWidget(QWidget *parent)
: CAttribWidgetT<NLMISC::CRGBA>(parent)
{
_ui.schemeComboBox->addItem(tr("color sampled blender"));
_ui.schemeComboBox->addItem(tr("color gradient"));
_ui.schemeComboBox->addItem(tr("color exact blender"));
_ui.schemeComboBox->addItem(tr("values computed from emitter"));
_ui.schemeComboBox->addItem(tr("binary operator"));
}
CAttribRGBAWidget::~CAttribRGBAWidget()
{
}
void CAttribRGBAWidget::setWrapper(IPSWrapper<NLMISC::CRGBA> *wrapper)
{
nlassert(wrapper);
_Wrapper = wrapper;
_ui.constRGBAWidget->setWrapper(_Wrapper);
}
QDialog *CAttribRGBAWidget::editScheme(void)
{
const NL3D::CPSAttribMaker<NLMISC::CRGBA> *scheme = _SchemeWrapper->getScheme();
if (dynamic_cast<const NL3D::CPSColorBlender *>(scheme))
{
CRGBABlenderDialogClient *myInterface = new CRGBABlenderDialogClient();
myInterface->SchemeFunc = & ((NL3D::CPSValueBlenderSample<NLMISC::CRGBA, 64> *) scheme)->_F;
CValueBlenderDialog *vb = new CValueBlenderDialog(myInterface, _Node, true, this);
return vb;
}
if (dynamic_cast<const NL3D::CPSColorGradient *>(scheme))
{
CColorGradientWrapper *wrapper = new CColorGradientWrapper;
wrapper->Scheme = &(((NL3D::CPSColorGradient *) (_SchemeWrapper->getScheme()) )->_F);
CGradientDialog *gd = new CGradientDialog(_Node, wrapper, true, true, 2, this);
wrapper->DefaultValue = NLMISC::CRGBA::White;
return gd;
}
if (dynamic_cast<const NL3D::CPSColorBlenderExact *>(scheme))
{
return NULL;
}
if (dynamic_cast<const NL3D::CPSColorMemory *>(scheme))
{
CAttribRGBAWidget *ad = new CAttribRGBAWidget();
CValueFromEmitterDialogT<NLMISC::CRGBA> *vfe = new CValueFromEmitterDialogT<NLMISC::CRGBA>( (NL3D::CPSColorMemory *)(scheme),
ad,
this);
vfe->init();
ad->setWorkspaceNode(_Node);
ad->updateUi();
return vfe;
}
if (dynamic_cast<const NL3D::CPSColorBinOp *>(scheme))
{
CAttribRGBAWidget *ad[2] = { NULL, NULL};
for (uint k = 0; k <2; ++k)
{
ad[k] = new CAttribRGBAWidget();
}
CBinOpDialogT<NLMISC::CRGBA> *bod = new CBinOpDialogT<NLMISC::CRGBA>( (NL3D::CPSColorBinOp *)(scheme),
(CAttribWidgetT<NLMISC::CRGBA> **) ad,
this);
bod->init();
for (uint k = 0; k <2; ++k)
{
ad[k]->setWorkspaceNode(_Node);
ad[k]->updateUi();
}
return bod;
}
return NULL;
}
void CAttribRGBAWidget::setCurrentScheme(uint index)
{
nlassert(index < 5);
NL3D::CPSAttribMaker<NLMISC::CRGBA> *scheme = NULL;
switch (index)
{
case 0 :
scheme = new NL3D::CPSColorBlender;
break;
case 1 :
scheme = new NL3D::CPSColorGradient(NL3D::CPSColorGradient::_DefaultGradient, 2, 16, 1.f);
break;
case 2 :
scheme = new NL3D::CPSColorBlenderExact;
break;
case 3 :
scheme = new NL3D::CPSColorMemory;
((NL3D::CPSAttribMakerMemory<NLMISC::CRGBA> *) scheme)->setScheme(new NL3D::CPSColorBlender);
break;
case 4 :
scheme = new NL3D::CPSColorBinOp;
((NL3D::CPSColorBinOp *) scheme)->setArg(0, new NL3D::CPSColorBlender);
((NL3D::CPSColorBinOp *) scheme)->setArg(1, new NL3D::CPSColorBlender);
break;
default:
break;
}
if (scheme)
{
_SchemeWrapper->setSchemeAndUpdateModifiedFlag(scheme);
}
}
sint CAttribRGBAWidget::getCurrentScheme(void) const
{
const NL3D::CPSAttribMaker<NLMISC::CRGBA> *scheme = _SchemeWrapper->getScheme();
if (dynamic_cast<const NL3D::CPSColorBlender *>(scheme)) return 0;
if (dynamic_cast<const NL3D::CPSColorGradient *>(scheme)) return 1;
if (dynamic_cast<const NL3D::CPSColorBlenderExact *>(scheme)) return 2;
if (dynamic_cast<const NL3D::CPSColorMemory *>(scheme)) return 3;
if (dynamic_cast<const NL3D::CPSColorBinOp *>(scheme)) return 4;
return -1;
}
void CAttribRGBAWidget::cstValueUpdate()
{
_ui.schemeWidget->hide();
_ui.inMultiplierWidget->setEnabled(false);
_ui.clampCheckBox->setEnabled(false);
_ui.inputLabel->setEnabled(false);
_ui.constRGBAWidget->show();
_ui.constRGBAWidget->updateUi();
}
CAttribPlaneBasisWidget::CAttribPlaneBasisWidget(QWidget *parent)
: CAttribWidgetT<NL3D::CPlaneBasis>(parent)
{
_ui.schemeComboBox->addItem(tr("basis gradient"));
_ui.schemeComboBox->addItem(tr("follow path"));
_ui.schemeComboBox->addItem(tr("spinner"));
_ui.schemeComboBox->addItem(tr("values computed from emitter"));
_ui.schemeComboBox->addItem(tr("binary operator"));
}
CAttribPlaneBasisWidget::~CAttribPlaneBasisWidget()
{
}
void CAttribPlaneBasisWidget::setWrapper(IPSWrapper<NL3D::CPlaneBasis> *wrapper)
{
nlassert(wrapper);
_Wrapper = wrapper;
_ui.constAttribPlaneWidget->setWrapper(_Wrapper);
}
QDialog *CAttribPlaneBasisWidget::editScheme(void)
{
NL3D::CPSAttribMaker<NL3D::CPlaneBasis> *scheme = _SchemeWrapper->getScheme();
if (dynamic_cast<NL3D::CPSPlaneBasisGradient *>(scheme))
{
CPlaneBasisGradientWrapper *wrapper = new CPlaneBasisGradientWrapper;
wrapper->Scheme = &(((NL3D::CPSPlaneBasisGradient *) (_SchemeWrapper->getScheme()) )->_F);
CGradientDialog *gd = new CGradientDialog(_Node, wrapper, true, true, 2, this);
wrapper->DefaultValue = NL3D::CPlaneBasis(NLMISC::CVector::K);
return gd;
}
if (dynamic_cast<NL3D::CPSPlaneBasisFollowSpeed *>(scheme))
{
CFollowPathDialog *dialog = new CFollowPathDialog(dynamic_cast<NL3D::CPSPlaneBasisFollowSpeed *>(scheme), _Node, this);
return dialog;
}
if (dynamic_cast<NL3D::CPSPlaneBasisMemory *>(scheme))
{
CAttribPlaneBasisWidget *ad = new CAttribPlaneBasisWidget();
CValueFromEmitterDialogT<NL3D::CPlaneBasis> *vfe = new CValueFromEmitterDialogT<NL3D::CPlaneBasis>
( (NL3D::CPSPlaneBasisMemory *)(scheme),
ad, this);
vfe->init();
ad->setWorkspaceNode(_Node);
ad->updateUi();
return vfe;
}
if (dynamic_cast<NL3D::CPSPlaneBasisBinOp *>(scheme))
{
CAttribPlaneBasisWidget *ad[2] = { NULL, NULL};
for (uint k = 0; k <2; ++k)
{
ad[k] = new CAttribPlaneBasisWidget();
}
CBinOpDialogT<NL3D::CPlaneBasis> *bod = new CBinOpDialogT<NL3D::CPlaneBasis>( (NL3D::CPSPlaneBasisBinOp *)(scheme),
(CAttribWidgetT<NL3D::CPlaneBasis> **) ad,
this);
bod->init();
for (uint k = 0; k <2; ++k)
{
ad[k]->setWorkspaceNode(_Node);
ad[k]->updateUi();
}
return bod;
}
if (dynamic_cast<NL3D::CPSBasisSpinner *>(scheme))
{
CSpinnerDialog *dialog = new CSpinnerDialog(dynamic_cast<NL3D::CPSBasisSpinner *>(scheme), _Node, this);
return dialog;
}
return NULL;
}
void CAttribPlaneBasisWidget::setCurrentScheme(uint index)
{
nlassert(index < 5);
NL3D::CPSAttribMaker<NL3D::CPlaneBasis> *scheme = NULL;
switch (index)
{
case 0:
scheme = new NL3D::CPSPlaneBasisGradient;
break;
case 1:
scheme = new NL3D::CPSPlaneBasisFollowSpeed;
break;
case 2:
scheme = new NL3D::CPSBasisSpinner;
static_cast<NL3D::CPSBasisSpinner *>(scheme)->_F.setNumSamples(16);
break;
case 3:
scheme = new NL3D::CPSPlaneBasisMemory;
((NL3D::CPSAttribMakerMemory<NL3D::CPlaneBasis> *) scheme)->setScheme(new NL3D::CPSPlaneBasisFollowSpeed);
if (_Node)
{
_Node->setModified(true);
}
break;
case 4 :
scheme = new NL3D::CPSPlaneBasisBinOp;
((NL3D::CPSPlaneBasisBinOp *) scheme)->setArg(0, new NL3D::CPSPlaneBasisFollowSpeed);
((NL3D::CPSPlaneBasisBinOp *) scheme)->setArg(1, new NL3D::CPSPlaneBasisFollowSpeed);
break;
default:
break;
}
if (scheme)
{
_SchemeWrapper->setSchemeAndUpdateModifiedFlag(scheme);
}
}
sint CAttribPlaneBasisWidget::getCurrentScheme(void) const
{
const NL3D::CPSAttribMaker<NL3D::CPlaneBasis> *scheme = _SchemeWrapper->getScheme();
if (dynamic_cast<const NL3D::CPSPlaneBasisGradient *>(scheme)) return 0;
if (dynamic_cast<const NL3D::CPSPlaneBasisFollowSpeed *>(scheme)) return 1;
if (dynamic_cast<const NL3D::CPSBasisSpinner *>(scheme)) return 2;
if (dynamic_cast<const NL3D::CPSPlaneBasisMemory *>(scheme)) return 3;
if (dynamic_cast<const NL3D::CPSPlaneBasisBinOp *>(scheme)) return 4;
return -1;
}
void CAttribPlaneBasisWidget::cstValueUpdate()
{
_ui.schemeWidget->hide();
_ui.inMultiplierWidget->setEnabled(false);
_ui.clampCheckBox->setEnabled(false);
_ui.inputLabel->setEnabled(false);
_ui.constAttribPlaneWidget->show();
_ui.constAttribPlaneWidget->updateUi();
}
} /* namespace NLQT */

View file

@ -0,0 +1,362 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ATTRIB_WIDGET_H
#define ATTRIB_WIDGET_H
#include <nel/misc/types_nl.h>
#include "ui_attrib_form.h"
// Qt includes
#include <QtGui/QDialog>
// STL includes
// NeL includes
#include <nel/misc/config_file.h>
#include <nel/misc/rgba.h>
#include <nel/3d/ps_plane_basis.h>
#include <nel/3d/ps_attrib_maker.h>
// Project includes
#include "ps_wrapper.h"
#include "particle_node.h"
namespace NLQT {
/**
@class CAttribWidget
@brief Base attrib maker edition dialog.
*/
class CAttribWidget: public QGroupBox
{
Q_OBJECT
public:
CAttribWidget(QWidget *parent = 0);
~CAttribWidget();
/// @param enableConstantValue - when false, only a scheme is available
void setEnabledConstantValue(bool enableConstantValue = true);
/// Force to update dialog content
void updateUi();
/// Сonnects all the slots with signals
void init();
/// Sets the pointer CWorkspaceNode* in the wrappers.
virtual void setWorkspaceNode(CWorkspaceNode *node) = 0;
/// Private usage (not private because accessed by a static function) : return the nbCycles parameter of the scheme (e.g the input multiplier).
virtual float getSchemeNbCycles(void) const = 0;
/// Private usage (not private because accessed by a static function) : set the nbCycles parameter of the scheme (e.g the input multiplier)
virtual void setSchemeNbCycles(float nbCycles) = 0;
/// Enable the srcInput
void enableSrcInput(bool enable = true) { _SrcInputEnabled = enable; }
bool isSrcInputEnabled() const { return _SrcInputEnabled; }
/// Disable the possibility to choose a scheme that has memory. (for example, a scheme for lifetime of a located has no sense
/// because located have already some memory to store it)
void enableMemoryScheme(bool enabled = true);
/// Tells wether memory schemes are enables
/// @see enableMemoryScheme()
bool isMemorySchemeEnabled() const { return !_DisableMemoryScheme; }
/// Enable Nb Cycle tuning
void enableNbCycles(bool enabled) { _NbCycleEnabled = enabled; }
bool isNbCycleEnabled() const { return _NbCycleEnabled; }
private Q_SLOTS:
virtual void clickedEdit();
virtual void setClamp(bool state);
virtual void changeCurrentScheme(int index);
virtual void setCurrentSrc(int index);
virtual void setUserIndex();
virtual void changeUseScheme(int index);
protected:
/// change the dialog for constant values
virtual void cstValueUpdate() = 0;
/// enable / disable the 'edit input' button, when input can be edited
void inputValueUpdate(void);
/// toggle back from scheme to cst value
virtual void resetCstValue(void) = 0;
/// change the dialog for scheme usage
void schemeValueUpdate();
/// return true if a scheme is used
virtual bool useScheme(void) const = 0;
/// edit the current scheme. And return a window on it
virtual QDialog *editScheme(void) = 0;
/// set the current scheme
virtual void setCurrentScheme(uint index) = 0;
/// set the current scheme ptr
virtual void setCurrentSchemePtr(NL3D::CPSAttribMakerBase *) = 0;
/// get the current scheme, -1 if the scheme is unknow (created outside the editor ?)
virtual sint getCurrentScheme(void) const = 0;
/// get a pointer on the current scheme base class
virtual NL3D::CPSAttribMakerBase *getCurrentSchemePtr(void) const = 0;
/// tells wether the scheme supports custom input
virtual bool hasSchemeCustomInput(void) const = 0;
/// retrieve the scheme input id
virtual NL3D::CPSInputType getSchemeInput(void) const = 0;
/// set the scheme input id
virtual void setSchemeInput(const NL3D::CPSInputType &input) = 0;
/// tells wether the scheme input value is clamped or not
virtual bool isSchemeClamped(void) const = 0;
/// clamp / unclamp the scheme
virtual void clampScheme(bool clamped = true) = 0;
/// return true if clamping is supported
virtual bool isClampingSupported(void) const = 0;
/// bool : true is src input are allowed
bool _SrcInputEnabled;
/// true if constant values are allowed
bool _EnableConstantValue;
/// this is equal to true when memory schemes are not permitted
bool _DisableMemoryScheme;
/// true to enable 'nb cycles' control
bool _NbCycleEnabled;
/// wrapper to tune the number of cycles
struct CNbCyclesWrapper : public IPSWrapperFloat
{
CAttribWidget *widget;
float get(void) const { return widget->getSchemeNbCycles(); }
void set(const float &v) { widget->setSchemeNbCycles(v); }
} _NbCyclesWrapper;
CWorkspaceNode *_Node;
QDialog *_SchemeWidget;
Ui::CAttribWidget _ui;
}; /* class CAttribWidget */
/**
@class CAttribWidgetT
@brief A template class that helps to specialize the attrib maker edition dialog with various types.
*/
template <typename T> class CAttribWidgetT : public CAttribWidget
{
public:
CAttribWidgetT(QWidget *parent = 0): CAttribWidget(parent),
_Wrapper(NULL),
_SchemeWrapper(NULL)
{
}
virtual void setWrapper(IPSWrapper<T> *wrapper) = 0;
void setSchemeWrapper(IPSSchemeWrapper<T> *schemeWrapper) { nlassert(schemeWrapper); _SchemeWrapper = schemeWrapper; }
// Inherited from CAttribWidget
virtual QDialog *editScheme(void) = 0;
virtual void setCurrentScheme(uint index) = 0;
virtual sint getCurrentScheme(void) const = 0;
virtual void resetCstValue(void)
{
_Wrapper->setAndUpdateModifiedFlag(_Wrapper->get()); // reuse current color
}
virtual bool hasSchemeCustomInput(void) const { return _SchemeWrapper->getScheme()->hasCustomInput(); }
virtual NL3D::CPSInputType getSchemeInput(void) const { return _SchemeWrapper->getScheme()->getInput(); }
virtual void setSchemeInput(const NL3D::CPSInputType &input) { _SchemeWrapper->getScheme()->setInput(input); }
virtual void setWorkspaceNode(CWorkspaceNode *node)
{
_Node = node; if (_Wrapper != NULL) _Wrapper->OwnerNode = _Node; if (_SchemeWrapper != NULL) _SchemeWrapper->OwnerNode = _Node;
};
virtual float getSchemeNbCycles(void) const { return _SchemeWrapper->getScheme()->getNbCycles(); }
virtual void setSchemeNbCycles(float nbCycles) { _SchemeWrapper->getScheme()->setNbCycles(nbCycles); }
virtual bool isSchemeClamped(void) const { return _SchemeWrapper->getScheme()->getClamping(); }
virtual void clampScheme(bool clamped = true) { _SchemeWrapper->getScheme()->setClamping(clamped); }
virtual bool isClampingSupported(void) const { return _SchemeWrapper->getScheme()->isClampingSupported(); };
virtual NL3D::CPSAttribMakerBase *getCurrentSchemePtr(void) const { return _SchemeWrapper->getScheme(); }
virtual void setCurrentSchemePtr(NL3D::CPSAttribMakerBase *s)
{
_SchemeWrapper->setSchemeAndUpdateModifiedFlag(NLMISC::safe_cast<NL3D::CPSAttribMaker<T> *>(s));
}
virtual void cstValueUpdate() = 0;
protected:
virtual bool useScheme(void) const
{
nlassert(_SchemeWrapper);
return(_SchemeWrapper->getScheme() != NULL);
}
public:
/// Wrapper to set/get a constant float
IPSWrapper<T> *_Wrapper;
/// Wrapper to set/get a scheme
IPSSchemeWrapper<T> *_SchemeWrapper;
};
/**
@class CAttribFloatWidget
@brief An attribute editor specialized for float values
*/
class CAttribFloatWidget: public CAttribWidgetT<float>
{
Q_OBJECT
public:
CAttribFloatWidget(QWidget *parent = 0);
~CAttribFloatWidget();
void setRange(float minValue = 0, float maxValue = 10);
void setWrapper(IPSWrapper<float> *wrapper);
// inherited from CAttribWidget
virtual QDialog *editScheme(void);
virtual void setCurrentScheme(uint index);
virtual sint getCurrentScheme(void) const;
virtual void cstValueUpdate();
private:
float _MinRange, _MaxRange;
}; /* class CAttribFloatWidget */
/**
@class CAttribUIntWidget
@brief An attribute editor specialized for unsigned int values
*/
class CAttribUIntWidget: public CAttribWidgetT<uint32>
{
Q_OBJECT
public:
CAttribUIntWidget(QWidget *parent = 0);
~CAttribUIntWidget();
void setRange(uint32 minValue = 0, uint32 maxValue = 10);
void setWrapper(IPSWrapper<uint32> *wrapper);
// inherited from CAttribWidget
virtual QDialog *editScheme(void);
virtual void setCurrentScheme(uint index);
virtual sint getCurrentScheme(void) const;
virtual void cstValueUpdate();
private:
uint32 _MinRange, _MaxRange;
}; /* class CAttribUIntWidget */
/**
@class CAttribIntWidget
@brief An attribute editor specialized for signed int values
*/
class CAttribIntWidget: public CAttribWidgetT<sint32>
{
Q_OBJECT
public:
CAttribIntWidget(QWidget *parent = 0);
~CAttribIntWidget();
void setRange(sint32 minValue = 0, sint32 maxValue = 10);
void setWrapper(IPSWrapper<sint32> *wrapper);
// inherited from CAttribWidget
virtual QDialog *editScheme(void);
virtual void setCurrentScheme(uint index);
virtual sint getCurrentScheme(void) const;
virtual void cstValueUpdate();
private:
sint32 _MinRange, _MaxRange;
}; /* class CAttribIntWidget */
/**
@class CAttribRGBAWidget
@brief An attribute editor specialized for RGB values
*/
class CAttribRGBAWidget: public CAttribWidgetT<NLMISC::CRGBA>
{
Q_OBJECT
public:
CAttribRGBAWidget(QWidget *parent = 0);
~CAttribRGBAWidget();
void setWrapper(IPSWrapper<NLMISC::CRGBA> *wrapper);
// inherited from CAttribWidget
virtual QDialog *editScheme(void);
virtual void setCurrentScheme(uint index);
virtual sint getCurrentScheme(void) const;
virtual void cstValueUpdate();
private:
}; /* class CAttribRGBAWidget */
/**
@class CAttribPlaneBasisWidget
@brief An attribute editor specialized for plane basis values
*/
class CAttribPlaneBasisWidget: public CAttribWidgetT<NL3D::CPlaneBasis>
{
Q_OBJECT
public:
CAttribPlaneBasisWidget(QWidget *parent = 0);
~CAttribPlaneBasisWidget();
void setWrapper(IPSWrapper<NL3D::CPlaneBasis> *wrapper);
// inherited from CAttribWidget
virtual QDialog *editScheme(void);
virtual void setCurrentScheme(uint index);
virtual sint getCurrentScheme(void) const;
virtual void cstValueUpdate();
private:
}; /* class CAttribPlaneBasisWidget */
} /* namespace NLQT */
#endif // ATTRIB_WIDGET_H

View file

@ -0,0 +1,88 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "auto_lod_dialog.h"
// STL includes
// Qt includes
// NeL includes
// Project includes
namespace NLQT {
CAutoLODDialog::CAutoLODDialog(CWorkspaceNode *ownerNode, NL3D::CParticleSystem *ps, QWidget *parent)
: QDialog(parent), _Node(ownerNode), _PS(ps)
{
_ui.setupUi(this);
setFixedHeight(sizeHint().height());
_DistRatioWrapper.PS = _PS;
_MaxDistLODBiasWrapper.PS = _PS;
_DistRatioWrapper.OwnerNode = _Node;
_MaxDistLODBiasWrapper.OwnerNode = _Node;
// Edit the distance at which LOD starts
_ui.startPercentDistWidget->setRange(0.f, 0.99f);
_ui.startPercentDistWidget->enableUpperBound(1.f, true);
_ui.startPercentDistWidget->enableLowerBound(0.f, false);
_ui.startPercentDistWidget->setWrapper(&_DistRatioWrapper);
_ui.startPercentDistWidget->updateUi();
// For non-shared systems only : Set the LOD bias at the max distance, so that some particles are still displayed
_ui.maxDistBiasWidget->setRange(0.f, 1.0f);
_ui.maxDistBiasWidget->enableUpperBound(1.f, false);
_ui.maxDistBiasWidget->enableLowerBound(0.f, false);
_ui.maxDistBiasWidget->setWrapper(&_MaxDistLODBiasWrapper);
_ui.maxDistBiasWidget->updateUi();
if (_PS->isSharingEnabled())
{
_ui.maxDistBiasWidget->setEnabled(false);
_ui.maxDistBiasLabel->setEnabled(false);
}
else
_ui.skipParticlesCheckBox->setEnabled(false);
_ui.degrdExponentSpinBox->setValue(int(_PS->getAutoLODDegradationExponent()) - 1);
_ui.skipParticlesCheckBox->setChecked(_PS->getAutoLODMode());
connect(_ui.degrdExponentSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setDegradationExponent(int)));
connect(_ui.skipParticlesCheckBox, SIGNAL(toggled(bool)), this, SLOT(setSkipParticles(bool)));
}
CAutoLODDialog::~CAutoLODDialog()
{
}
void CAutoLODDialog::setDegradationExponent(int value)
{
_PS->setupAutoLOD(_PS->getAutoLODStartDistPercent(),value + 1);
}
void CAutoLODDialog::setSkipParticles(bool state)
{
_PS->setAutoLODMode(state);
}
} /* namespace NLQT */

View file

@ -0,0 +1,73 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AUTO_LOD_DIALOG_H
#define AUTO_LOD_DIALOG_H
#include "ui_auto_lod_form.h"
// STL includes
// Qt includes
// NeL includes
#include "nel/3d/particle_system.h"
// Project includes
#include "ps_wrapper.h"
namespace NLQT {
class CAutoLODDialog: public QDialog
{
Q_OBJECT
public:
CAutoLODDialog(CWorkspaceNode *ownerNode, NL3D::CParticleSystem *ps, QWidget *parent = 0);
~CAutoLODDialog();
private Q_SLOTS:
void setDegradationExponent(int value);
void setSkipParticles(bool state);
private:
CWorkspaceNode *_Node;
NL3D::CParticleSystem *_PS;
struct CDistRatioWrapper : IPSWrapperFloat
{
NL3D::CParticleSystem *PS;
virtual float get() const { return PS->getAutoLODStartDistPercent(); }
virtual void set(const float &v) { PS->setupAutoLOD(v, PS->getAutoLODDegradationExponent()); }
} _DistRatioWrapper;
struct CMaxDistLODBiasWrapper : IPSWrapperFloat
{
NL3D::CParticleSystem *PS;
virtual float get() const { return PS->getMaxDistLODBias(); }
virtual void set(const float &v) { PS->setMaxDistLODBias(v); }
} _MaxDistLODBiasWrapper;
Ui::CAutoLODDialog _ui;
}; /* class CAutoLODDialog */
} /* namespace NLQT */
#endif // AUTO_LOD_DIALOG_H

View file

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CAutoLODDialog</class>
<widget class="QDialog" name="CAutoLODDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>543</width>
<height>137</height>
</rect>
</property>
<property name="windowTitle">
<string>Auto LOD</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Start percent DIST:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="NLQT::CEditRangeFloatWidget" name="startPercentDistWidget" native="true"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="maxDistBiasLabel">
<property name="text">
<string>Max dist BIAS:</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="4">
<widget class="NLQT::CEditRangeFloatWidget" name="maxDistBiasWidget" native="true"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Degradation exponent:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="degrdExponentSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>4</number>
</property>
</widget>
</item>
<item row="4" column="2" colspan="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>331</width>
<height>21</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="skipParticlesCheckBox">
<property name="text">
<string>Skip particles</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>139</width>
<height>22</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>NLQT::CEditRangeFloatWidget</class>
<extends>QWidget</extends>
<header>edit_range_widget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>CAutoLODDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>CAutoLODDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -0,0 +1,214 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CBasicEditWidget</class>
<widget class="QWidget" name="CBasicEditWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>283</width>
<height>99</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Psi</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSlider" name="psiHorizontalSlider">
<property name="maximum">
<number>359</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QSpinBox" name="psiSpinBox">
<property name="maximum">
<number>359</number>
</property>
</widget>
</item>
<item row="0" column="3" rowspan="3">
<widget class="NLQT::CGraphicsInfoWidget" name="graphicsWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>75</width>
<height>75</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Theta</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSlider" name="thetaHorizontalSlider">
<property name="maximum">
<number>360</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="thetaSpinBox">
<property name="maximum">
<number>359</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Phi</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSlider" name="phiHorizontalSlider">
<property name="maximum">
<number>360</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="phiSpinBox">
<property name="maximum">
<number>359</number>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>NLQT::CGraphicsInfoWidget</class>
<extends>QWidget</extends>
<header>graphics_info_widget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>psiHorizontalSlider</sender>
<signal>valueChanged(int)</signal>
<receiver>psiSpinBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>126</x>
<y>22</y>
</hint>
<hint type="destinationlabel">
<x>173</x>
<y>22</y>
</hint>
</hints>
</connection>
<connection>
<sender>thetaHorizontalSlider</sender>
<signal>valueChanged(int)</signal>
<receiver>thetaSpinBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>135</x>
<y>41</y>
</hint>
<hint type="destinationlabel">
<x>192</x>
<y>41</y>
</hint>
</hints>
</connection>
<connection>
<sender>phiHorizontalSlider</sender>
<signal>valueChanged(int)</signal>
<receiver>phiSpinBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>134</x>
<y>65</y>
</hint>
<hint type="destinationlabel">
<x>170</x>
<y>65</y>
</hint>
</hints>
</connection>
<connection>
<sender>phiSpinBox</sender>
<signal>valueChanged(int)</signal>
<receiver>phiHorizontalSlider</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>184</x>
<y>77</y>
</hint>
<hint type="destinationlabel">
<x>138</x>
<y>79</y>
</hint>
</hints>
</connection>
<connection>
<sender>thetaSpinBox</sender>
<signal>valueChanged(int)</signal>
<receiver>thetaHorizontalSlider</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>179</x>
<y>50</y>
</hint>
<hint type="destinationlabel">
<x>154</x>
<y>50</y>
</hint>
</hints>
</connection>
<connection>
<sender>psiSpinBox</sender>
<signal>valueChanged(int)</signal>
<receiver>psiHorizontalSlider</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>171</x>
<y>9</y>
</hint>
<hint type="destinationlabel">
<x>155</x>
<y>18</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -0,0 +1,192 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "basic_edit_widget.h"
// Qt includes
// NeL includes
#include "nel/misc/matrix.h"
#include "nel/misc/vector.h"
namespace NLQT {
// build an euler matrix
NLMISC::CMatrix BuildEulerMatrix(float psi, float theta, float phi)
{
float ca = cosf(psi), sa = sinf(psi)
, cb = cosf(theta), sb = sinf(theta)
, cc = cosf(phi), sc = sinf(phi);
NLMISC::CMatrix m;
m.identity();
m.setRot(NLMISC::CVector(ca * cb * cc - sa * sc, -cc * sa - ca * cb *sc, ca * sb)
,NLMISC::CVector(cb * cc * sa + ca * sc, ca * cc - cb * sa * sc, sa *sb)
,NLMISC::CVector(-cc * sb, sb * sc, cb)
);
return m;
}
// get back the euler angles from a matrix
NLMISC::CVector GetEulerAngles(const NLMISC::CMatrix &mat)
{
float m[3][3];
// we got cos theta = m33
NLMISC::CVector v[3];
mat.getRot(v[0], v[1], v[2]);
for (uint l = 0; l < 3; ++l)
{
m[0][l] = v[l].x; m[1][l] = v[l].y; m[2][l] = v[l].z;
}
// there are eight triplet that may satisfy the equation
// we compute them all, and test them against the matrix
float b0, b1, a0, a1, a2, a3, c0, c1, c2, c3;
b0 = acosf(m[2][2]);
b1 = (float) NLMISC::Pi - b0;
float sb0 = sinf(b0), sb1 = sinf(b1);
if (fabsf(sb0) > 10E-6)
{
a0 = m[2][0] / sb0;
c0 = m[1][2] / sb0;
}
else
{
a0 = c0 = 1.f;
}
if (fabs(sb1) > 10E-6)
{
a1 = m[2][0] / sb1;
c1 = m[1][2] / sb1;
}
else
{
a1 = c1 = 1.f;
}
a2 = (float) NLMISC::Pi - a0;
a3 = (float) NLMISC::Pi - a1;
c2 = (float) NLMISC::Pi - c0;
c3 = (float) NLMISC::Pi - c1;
NLMISC::CVector sol[] =
{
NLMISC::CVector(b0, a0, c0)
,NLMISC::CVector(b0, a2, c0)
,NLMISC::CVector(b0, a0, c2)
,NLMISC::CVector(b0, a2, c2)
,NLMISC::CVector(b1, a1, c1)
,NLMISC::CVector(b1, a3, c1)
,NLMISC::CVector(b1, a1, c3)
,NLMISC::CVector(b1, a3, c3)
};
// now we take the triplet that fit best the 6 other equations
float bestGap = 0.f;
uint bestIndex;
for (uint k = 0; k < 8; ++k)
{
float ca = cosf(sol[k].x), sa = sinf(sol[k].x)
, cb = cosf(sol[k].y), sb = sinf(sol[k].y)
, cc = cosf(sol[k].z), sc = sinf(sol[k].z);
float gap = fabsf(m[0][0] - ca * cb * cc + sa * sc);
gap += fabsf(m[1][0] + cc * sa + ca * cb *sc);
gap += fabsf(m[0][1] - cb * cc * sa - ca * sc);
gap += fabsf(m[0][1] - cb * cc * sa - ca * sc);
gap += fabsf(m[1][1] - ca * cc + cb * sa * sc);
gap += fabsf(m[2][1] - sb *ca);
gap += fabsf(m[0][2] + cc * sb);
if (k == 0 || gap < bestGap)
{
bestGap = gap;
bestIndex = k;
}
}
return sol[bestIndex];
}
CBasicEditWidget::CBasicEditWidget(QWidget *parent)
: QWidget(parent), _Wrapper(NULL)
{
_ui.setupUi(this);
connect(_ui.psiSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateGraphics()));
connect(_ui.thetaSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateGraphics()));
connect(_ui.phiSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateGraphics()));
}
CBasicEditWidget::~CBasicEditWidget()
{
}
void CBasicEditWidget::setWrapper(IPSWrapper<NL3D::CPlaneBasis> *wrapper)
{
_Wrapper = wrapper;
}
void CBasicEditWidget::updateUi()
{
if (_Wrapper == NULL) return;
NL3D::CPlaneBasis pb = _Wrapper->get();
NLMISC::CMatrix mat;
mat.setRot(pb.X, pb.Y, pb.X ^ pb.Y);
NLMISC::CVector angles = GetEulerAngles(mat);
_ui.psiSpinBox->blockSignals(true);
_ui.thetaSpinBox->blockSignals(true);
_ui.phiSpinBox->blockSignals(true);
_ui.psiSpinBox->setValue(int(360.f * angles.x / (2.f * (float) NLMISC::Pi)));
_ui.thetaSpinBox->setValue(int(360.f * angles.y / (2.f * (float) NLMISC::Pi)));
_ui.phiSpinBox->setValue(int(360.f * angles.z / (2.f * (float) NLMISC::Pi)));
_ui.psiSpinBox->blockSignals(false);
_ui.thetaSpinBox->blockSignals(false);
_ui.phiSpinBox->blockSignals(false);
repaint();
}
void CBasicEditWidget::updateGraphics()
{
if (_Wrapper == NULL) return;
NLMISC::CVector angles(2.f * (float) NLMISC::Pi * _ui.psiSpinBox->value() / 360.f
, 2.f * (float) NLMISC::Pi * _ui.thetaSpinBox->value() / 360.f
, 2.f * (float) NLMISC::Pi * _ui.phiSpinBox->value() / 360.f
);
NLMISC::CMatrix mat = BuildEulerMatrix(angles.x, angles.y, angles.z);
NL3D::CPlaneBasis pb;
pb.X = mat.getI();
pb.Y = mat.getJ();
_Wrapper->setAndUpdateModifiedFlag(pb);
repaint();
}
} /* namespace NLQT */

View file

@ -0,0 +1,61 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BASIC_EDIT_WIDGET_H
#define BASIC_EDIT_WIDGET_H
#include <nel/misc/types_nl.h>
#include "ui_basic_edit_form.h"
// STL includes
// NeL includes
#include "nel/3d/ps_plane_basis.h"
#include "ps_wrapper.h"
// Project includes
namespace NLQT {
class CBasicEditWidget: public QWidget
{
Q_OBJECT
public:
CBasicEditWidget(QWidget *parent = 0);
~CBasicEditWidget();
void setWrapper(IPSWrapper<NL3D::CPlaneBasis> *wrapper);
void updateUi();
private Q_SLOTS:
void updateGraphics();
private:
// wrapper to the datas
IPSWrapper<NL3D::CPlaneBasis> *_Wrapper ;
Ui::CBasicEditWidget _ui;
}; /* class CBasicEditWidget */
} /* namespace NLQT */
#endif // BASIC_EDIT_WIDGET_H

View file

@ -0,0 +1,63 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "bin_op_dialog.h"
namespace NLQT {
CBinOpDialog::CBinOpDialog(QWidget *widget1, QWidget *widget2, QWidget *parent)
: QDialog(parent)
{
resize(350, 330);
_gridLayout = new QGridLayout(this);
_gridLayout->addWidget(widget1, 0, 0, 1, 2);
_comboBox = new QComboBox(this);
_gridLayout->addWidget(_comboBox, 1, 0, 1, 1);
_horizontalSpacer = new QSpacerItem(267, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
_gridLayout->addItem(_horizontalSpacer, 1, 1, 1, 1);
_gridLayout->addWidget(widget2, 2, 0, 1, 2);
setWindowTitle(tr("Bin operator"));
_comboBox->clear();
_comboBox->insertItems(0, QStringList()
<< tr("SelectArg1")
<< tr("SelectArg2")
<< tr("Modulate")
<< tr("Add")
<< tr("Subtract"));
qobject_cast<QGroupBox*>(widget1)->setTitle(tr("Arg1"));
qobject_cast<QGroupBox*>(widget2)->setTitle(tr("Arg2"));
connect(_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setNewOp(int)));
}
CBinOpDialog::~CBinOpDialog()
{
}
void CBinOpDialog::setNewOp(int index)
{
newOp(uint32(index));
}
} /* namespace NLQT */

View file

@ -0,0 +1,152 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BIN_OP_DIALOG_H
#define BIN_OP_DIALOG_H
#include <nel/misc/types_nl.h>
// Qt includes
#include <QtGui/QComboBox>
#include <QtGui/QDialog>
#include <QtGui/QGridLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QSpacerItem>
#include <QtGui/QWidget>
// NeL includes
#include "nel/3d/ps_attrib_maker_bin_op.h"
// Project includes
#include "ps_wrapper.h"
#include "attrib_widget.h"
namespace NLQT {
class CBinOpDialog : public QDialog
{
Q_OBJECT
public:
CBinOpDialog(QWidget *widget1, QWidget *widget2, QWidget *parent = 0);
~CBinOpDialog();
virtual void init() = 0;
/// called when a new operator has been selected
virtual void newOp(uint32 op) = 0 ;
private Q_SLOTS:
void setNewOp(int index);
protected:
QGridLayout *_gridLayout;
QWidget *_widget1;
QComboBox *_comboBox;
QSpacerItem *_horizontalSpacer;
QWidget *_widget2;
};
/**
@class CBinOpDialogT
@brief Construct a dialog that allow to edit a binary operator that produce argument of a particle system
*/
template <class T> class CBinOpDialogT : public CBinOpDialog
{
public:
/// ctruct the given dialog from the given scheme that owns memory
CBinOpDialogT(NL3D::CPSAttribMakerBinOp<T> *editedScheme, CAttribWidgetT<T> **attrbDlg, QWidget *parent = 0)
: CBinOpDialog(attrbDlg[0], attrbDlg[1], parent), _EditedScheme(editedScheme)
{
for (uint k = 0 ; k < 2 ; ++k)
{
nlassert(attrbDlg);
_AttrbDlg[k] = attrbDlg[k];
_SchemeWrapper[k].S = _EditedScheme ;
_SchemeWrapper[k].Index = k ;
}
}
void init()
{
uint k ;
for (k = 0 ; k < 2 ; ++k)
{
_AttrbDlg[k]->setEnabledConstantValue(false) ;
_AttrbDlg[k]->setWrapper(&_DummyWrapper) ;
_AttrbDlg[k]->setSchemeWrapper(&_SchemeWrapper[k]) ;
_AttrbDlg[k]->init();
}
for (k = 0 ; k < (uint) NL3D::CPSBinOp::last ; ++k)
{
if (_EditedScheme->supportOp( (NL3D::CPSBinOp::BinOp) k))
{
if ((uint) _EditedScheme->getOp() == k)
_comboBox->setCurrentIndex(k);
}
}
}
~CBinOpDialogT()
{
for (uint k = 0 ; k < 2 ; ++k)
{
delete _AttrbDlg[k] ;
}
}
protected:
NL3D::CPSAttribMakerBinOp<T> *_EditedScheme ;
/// the dialogs that allow us to edit the schemes
CAttribWidgetT<T> *_AttrbDlg[2] ;
/// a wrapper to edit the scheme (which himself owns a scheme !!)
struct CSchemeWrapper : public IPSSchemeWrapper<T>
{
NL3D::CPSAttribMakerBinOp<T> *S ;
uint Index ;
virtual NL3D::CPSAttribMaker<T> *getScheme(void) const { return S->getArg(Index) ; }
virtual void setScheme(NL3D::CPSAttribMaker<T> *s) { S->setArg(Index, s) ; } ;
} _SchemeWrapper[2] ;
/// a dummy wrapper for constant value. This shouldn't be called , however
struct CDummyWrapper : public IPSWrapper<T>
{
T get(void) const { nlassert(false) ; return T() ; }
void set(const T &) { nlassert(false) ; }
} _DummyWrapper ;
void newOp(uint32 op)
{
nlassert(_EditedScheme) ;
if (_EditedScheme->getOp() != (NL3D::CPSBinOp::BinOp) op)
_EditedScheme->setOp((NL3D::CPSBinOp::BinOp) op);
}
} ;
} /* namespace NLQT */
#endif // BIN_OP_DIALOG_H

View file

@ -0,0 +1,27 @@
/*
* Copyright (C) 2010 by authors
*
* This file is part of NEL QT.
* NEL QT is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEL QT is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEL QT; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "callback.h"
namespace NLQT {
} /* namespace NLQT */
/* end of file */

View file

@ -0,0 +1,326 @@
/*
* Copyright (C) 2010 by authors
*
* This file is part of NEL QT.
* NEL QT is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEL QT is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEL QT; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef NLQT_CALLBACK_H
#define NLQT_CALLBACK_H
#include <nel/misc/types_nl.h>
// STL includes
// NeL includes
#ifdef NL_COMP_GCC
// temporary fix for GCC 4.4 segmentation fault
# undef nlassert
# define nlassert(x)
#else
# include <nel/misc/debug.h>
#endif // NL_COMP_GCC
// Project includes
namespace NLQT {
#define NLQT_CALLBACK_TEMPLATE \
/** \
* \brief NLQT_CALLBACK_ARGS_CLASS \
* \date 2009-03-03 18:09GMT \
* \author Jan Boon (Kaetemi) \
* Awesome callback template \
*/ \
template<typename TReturn NLQT_CALLBACK_ARGS_TYPENAME> \
class NLQT_CALLBACK_ARGS_CLASS \
{ \
/* Very simple reference counting callback base */ \
class CCallbackBase \
{ \
public: \
CCallbackBase() : m_RefCount(0) \
{ \
\
} \
\
virtual ~CCallbackBase() \
{ \
nlassert(!m_RefCount); \
} \
\
void refAdd() \
{ \
++m_RefCount; \
} \
\
void refRemove() \
{ \
--m_RefCount; \
if (!m_RefCount) \
delete this; \
} \
\
virtual TReturn callback(NLQT_CALLBACK_ARGS_DECL) = 0; \
\
virtual bool equals(const CCallbackBase *callbackBase) = 0; \
\
/* disable copy */ \
CCallbackBase(const CCallbackBase &); \
CCallbackBase &operator=(const CCallbackBase &); \
\
private: \
uint m_RefCount; \
}; \
\
typedef TReturn TCallbackFunction(NLQT_CALLBACK_ARGS_DECL); \
class CCallbackFunction : public CCallbackBase \
{ \
public: \
CCallbackFunction(TCallbackFunction *callbackFunction) : m_CallbackFunction(callbackFunction) \
{ \
nlassert(m_CallbackFunction); \
} \
\
virtual ~CCallbackFunction() \
{ \
m_CallbackFunction = NULL; \
} \
\
virtual TReturn callback(NLQT_CALLBACK_ARGS_DECL) \
{ \
return m_CallbackFunction(NLQT_CALLBACK_ARGS_IMPL); \
} \
\
virtual bool equals(const CCallbackBase *callbackBase) \
{ \
const CCallbackFunction *callbackFunction = \
dynamic_cast<const CCallbackFunction *>(callbackBase); \
if (!callbackFunction) return false; \
return m_CallbackFunction == callbackFunction->m_CallbackFunction; \
} \
\
private: \
TCallbackFunction *m_CallbackFunction; \
}; \
\
template<typename TClass> \
class CCallbackMethod : public CCallbackBase \
{ \
typedef TReturn (TClass::*TCallbackMethod)(NLQT_CALLBACK_ARGS_DECL); \
public: \
CCallbackMethod(TClass *callbackObject, TCallbackMethod callbackMethod) : m_CallbackObject(callbackObject), m_CallbackMethod(callbackMethod) \
{ \
nlassert(m_CallbackObject); \
nlassert(m_CallbackMethod); \
} \
\
virtual ~CCallbackMethod() \
{ \
m_CallbackObject = NULL; \
m_CallbackMethod = NULL; \
} \
\
virtual TReturn callback(NLQT_CALLBACK_ARGS_DECL) \
{ \
return (m_CallbackObject->*m_CallbackMethod)(NLQT_CALLBACK_ARGS_IMPL); \
} \
\
virtual bool equals(const CCallbackBase *callbackBase) \
{ \
const CCallbackMethod *callbackMethod = \
dynamic_cast<const CCallbackMethod *>(callbackBase); \
if (!callbackMethod) return false; \
return m_CallbackObject == callbackMethod->m_CallbackObject \
&& m_CallbackMethod == callbackMethod->m_CallbackMethod; \
} \
\
private: \
TClass *m_CallbackObject; \
TCallbackMethod m_CallbackMethod; \
}; \
\
public: \
CCallback() : m_CallbackBase(NULL) \
{ \
\
} \
\
CCallback(TCallbackFunction *callbackFunction) : m_CallbackBase(new CCallbackFunction(callbackFunction)) \
{ \
nlassert(m_CallbackBase); \
m_CallbackBase->refAdd(); \
} \
\
template<typename TClass> \
CCallback(TClass *callbackObject, TReturn (TClass::*callbackMethod)(NLQT_CALLBACK_ARGS_DECL)) : m_CallbackBase(new CCallbackMethod<TClass>(callbackObject, callbackMethod)) \
{ \
nlassert(m_CallbackBase); \
m_CallbackBase->refAdd(); \
} \
\
CCallback(const CCallback &callback) \
{ \
m_CallbackBase = callback.m_CallbackBase; \
if (m_CallbackBase) \
m_CallbackBase->refAdd(); \
} \
\
CCallback &operator=(const CCallback &callback) \
{ \
if (m_CallbackBase != callback.m_CallbackBase) \
{ \
if (m_CallbackBase) \
m_CallbackBase->refRemove(); \
m_CallbackBase = callback.m_CallbackBase; \
if (m_CallbackBase) \
m_CallbackBase->refAdd(); \
} \
return *this; \
} \
\
~CCallback() \
{ \
if (m_CallbackBase) \
{ \
m_CallbackBase->refRemove(); \
m_CallbackBase = NULL; \
} \
} \
\
TReturn callback(NLQT_CALLBACK_ARGS_DECL) \
{ \
nlassert(m_CallbackBase); \
return m_CallbackBase->callback(NLQT_CALLBACK_ARGS_IMPL); \
} \
\
TReturn operator()(NLQT_CALLBACK_ARGS_DECL) \
{ \
nlassert(m_CallbackBase); \
return m_CallbackBase->callback(NLQT_CALLBACK_ARGS_IMPL); \
} \
\
bool valid() const \
{ \
return m_CallbackBase != NULL; \
} \
\
operator bool() const \
{ \
return m_CallbackBase != NULL; \
} \
\
bool operator==(const CCallback &callback) \
{ \
return m_CallbackBase->equals(callback.m_CallbackBase); \
} \
\
private: \
CCallbackBase *m_CallbackBase; \
\
}; /* class CCallback */ \
template<typename TReturn, typename TArgsA = void, typename TArgsB = void, typename TArgsC = void, typename TArgsD = void, typename TArgsE = void, typename TArgsF = void, typename TArgsG = void, typename TDummy = void>
class CCallback;
#define NLQT_CALLBACK_ARGS_CLASS CCallback<TReturn, void, void, void, void, void, void, void, void>
#define NLQT_CALLBACK_ARGS_TYPENAME
#define NLQT_CALLBACK_ARGS_DECL
#define NLQT_CALLBACK_ARGS_IMPL
NLQT_CALLBACK_TEMPLATE
#undef NLQT_CALLBACK_ARGS_CLASS
#undef NLQT_CALLBACK_ARGS_TYPENAME
#undef NLQT_CALLBACK_ARGS_DECL
#undef NLQT_CALLBACK_ARGS_IMPL
#define NLQT_CALLBACK_ARGS_CLASS CCallback<TReturn, TArgsA, void, void, void, void, void, void, void>
#define NLQT_CALLBACK_ARGS_TYPENAME , typename TArgsA
#define NLQT_CALLBACK_ARGS_DECL TArgsA argsA
#define NLQT_CALLBACK_ARGS_IMPL argsA
NLQT_CALLBACK_TEMPLATE
#undef NLQT_CALLBACK_ARGS_CLASS
#undef NLQT_CALLBACK_ARGS_TYPENAME
#undef NLQT_CALLBACK_ARGS_DECL
#undef NLQT_CALLBACK_ARGS_IMPL
#define NLQT_CALLBACK_ARGS_CLASS CCallback<TReturn, TArgsA, TArgsB, void, void, void, void, void, void>
#define NLQT_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB
#define NLQT_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB
#define NLQT_CALLBACK_ARGS_IMPL argsA, argsB
NLQT_CALLBACK_TEMPLATE
#undef NLQT_CALLBACK_ARGS_CLASS
#undef NLQT_CALLBACK_ARGS_TYPENAME
#undef NLQT_CALLBACK_ARGS_DECL
#undef NLQT_CALLBACK_ARGS_IMPL
#define NLQT_CALLBACK_ARGS_CLASS CCallback<TReturn, TArgsA, TArgsB, TArgsC, void, void, void, void, void>
#define NLQT_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC
#define NLQT_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC
#define NLQT_CALLBACK_ARGS_IMPL argsA, argsB, argsC
NLQT_CALLBACK_TEMPLATE
#undef NLQT_CALLBACK_ARGS_CLASS
#undef NLQT_CALLBACK_ARGS_TYPENAME
#undef NLQT_CALLBACK_ARGS_DECL
#undef NLQT_CALLBACK_ARGS_IMPL
#define NLQT_CALLBACK_ARGS_CLASS CCallback<TReturn, TArgsA, TArgsB, TArgsC, TArgsD, void, void, void, void>
#define NLQT_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC, typename TArgsD
#define NLQT_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC, TArgsD argsD
#define NLQT_CALLBACK_ARGS_IMPL argsA, argsB, argsC, argsD
NLQT_CALLBACK_TEMPLATE
#undef NLQT_CALLBACK_ARGS_CLASS
#undef NLQT_CALLBACK_ARGS_TYPENAME
#undef NLQT_CALLBACK_ARGS_DECL
#undef NLQT_CALLBACK_ARGS_IMPL
#define NLQT_CALLBACK_ARGS_CLASS CCallback<TReturn, TArgsA, TArgsB, TArgsC, TArgsD, TArgsE, void, void, void>
#define NLQT_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC, typename TArgsD, typename TArgsE
#define NLQT_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC, TArgsD argsD, TArgsE argsE
#define NLQT_CALLBACK_ARGS_IMPL argsA, argsB, argsC, argsD, argsE
NLQT_CALLBACK_TEMPLATE
#undef NLQT_CALLBACK_ARGS_CLASS
#undef NLQT_CALLBACK_ARGS_TYPENAME
#undef NLQT_CALLBACK_ARGS_DECL
#undef NLQT_CALLBACK_ARGS_IMPL
#define NLQT_CALLBACK_ARGS_CLASS CCallback<TReturn, TArgsA, TArgsB, TArgsC, TArgsD, TArgsE, TArgsF, void, void>
#define NLQT_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC, typename TArgsD, typename TArgsE, typename TArgsF
#define NLQT_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC, TArgsD argsD, TArgsE argsE, TArgsF argsF
#define NLQT_CALLBACK_ARGS_IMPL argsA, argsB, argsC, argsD, argsE, argsF
NLQT_CALLBACK_TEMPLATE
#undef NLQT_CALLBACK_ARGS_CLASS
#undef NLQT_CALLBACK_ARGS_TYPENAME
#undef NLQT_CALLBACK_ARGS_DECL
#undef NLQT_CALLBACK_ARGS_IMPL
#define NLQT_CALLBACK_ARGS_CLASS CCallback<TReturn, TArgsA, TArgsB, TArgsC, TArgsD, TArgsE, TArgsF, TArgsG, void>
#define NLQT_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC, typename TArgsD, typename TArgsE, typename TArgsF, typename TArgsG
#define NLQT_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC, TArgsD argsD, TArgsE argsE, TArgsF argsF, TArgsG argsG
#define NLQT_CALLBACK_ARGS_IMPL argsA, argsB, argsC, argsD, argsE, argsF, argsG
NLQT_CALLBACK_TEMPLATE
#undef NLQT_CALLBACK_ARGS_CLASS
#undef NLQT_CALLBACK_ARGS_TYPENAME
#undef NLQT_CALLBACK_ARGS_DECL
#undef NLQT_CALLBACK_ARGS_IMPL
#undef NLQT_CALLBACK_ARGS_CLASSNAME
#undef NLQT_CALLBACK_TEMPLATE
typedef CCallback<void> CEmptyCallback;
} /* namespace NLQT */
#endif /* #ifndef NLQT_CALLBACK_H */
/* end of file */

View file

@ -0,0 +1,264 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CColorEditWidget</class>
<widget class="QWidget" name="CColorEditWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>255</width>
<height>116</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QSlider" name="rHorizontalSlider">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="rSpinBox">
<property name="buttonSymbols">
<enum>QAbstractSpinBox::UpDownArrows</enum>
</property>
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="browsePushButton">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QSlider" name="gHorizontalSlider">
<property name="maximum">
<number>255</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="gSpinBox">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item row="1" column="2" rowspan="3">
<widget class="NLQT::CGraphicsInfoWidget" name="graphicsWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>75</width>
<height>75</height>
</size>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QSlider" name="bHorizontalSlider">
<property name="maximum">
<number>255</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="bSpinBox">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QSlider" name="aHorizontalSlider">
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>255</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="aSpinBox">
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>255</number>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>NLQT::CGraphicsInfoWidget</class>
<extends>QWidget</extends>
<header>graphics_info_widget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>rHorizontalSlider</sender>
<signal>valueChanged(int)</signal>
<receiver>rSpinBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>159</x>
<y>75</y>
</hint>
<hint type="destinationlabel">
<x>231</x>
<y>75</y>
</hint>
</hints>
</connection>
<connection>
<sender>gHorizontalSlider</sender>
<signal>valueChanged(int)</signal>
<receiver>gSpinBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>166</x>
<y>115</y>
</hint>
<hint type="destinationlabel">
<x>214</x>
<y>116</y>
</hint>
</hints>
</connection>
<connection>
<sender>bHorizontalSlider</sender>
<signal>valueChanged(int)</signal>
<receiver>bSpinBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>160</x>
<y>160</y>
</hint>
<hint type="destinationlabel">
<x>210</x>
<y>164</y>
</hint>
</hints>
</connection>
<connection>
<sender>aHorizontalSlider</sender>
<signal>valueChanged(int)</signal>
<receiver>aSpinBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>158</x>
<y>201</y>
</hint>
<hint type="destinationlabel">
<x>210</x>
<y>201</y>
</hint>
</hints>
</connection>
<connection>
<sender>rSpinBox</sender>
<signal>valueChanged(int)</signal>
<receiver>rHorizontalSlider</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>217</x>
<y>81</y>
</hint>
<hint type="destinationlabel">
<x>167</x>
<y>81</y>
</hint>
</hints>
</connection>
<connection>
<sender>gSpinBox</sender>
<signal>valueChanged(int)</signal>
<receiver>gHorizontalSlider</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>224</x>
<y>130</y>
</hint>
<hint type="destinationlabel">
<x>184</x>
<y>130</y>
</hint>
</hints>
</connection>
<connection>
<sender>bSpinBox</sender>
<signal>valueChanged(int)</signal>
<receiver>bHorizontalSlider</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>219</x>
<y>154</y>
</hint>
<hint type="destinationlabel">
<x>171</x>
<y>153</y>
</hint>
</hints>
</connection>
<connection>
<sender>aSpinBox</sender>
<signal>valueChanged(int)</signal>
<receiver>aHorizontalSlider</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>228</x>
<y>198</y>
</hint>
<hint type="destinationlabel">
<x>187</x>
<y>199</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -0,0 +1,167 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "color_edit_widget.h"
// Qt includes
#include <QtGui/QColorDialog>
#include <QtGui/QColor>
// Nel includes
#include <nel/misc/rgba.h>
namespace NLQT {
CColorEditWidget::CColorEditWidget(QWidget *parent)
: QWidget(parent), _Wrapper(NULL), _emit(true)
{
_ui.setupUi(this);
connect(_ui.rSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setRed(int)));
connect(_ui.gSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setGreen(int)));
connect(_ui.bSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setBlue(int)));
connect(_ui.aSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setAlpha(int)));
connect(_ui.browsePushButton, SIGNAL(clicked()), this, SLOT(browseColor()));
setColor(QColor(255, 255, 255, 255));
}
CColorEditWidget::~CColorEditWidget()
{
}
void CColorEditWidget::setWrapper(IPSWrapperRGBA *wrapper)
{
_Wrapper = wrapper;
}
void CColorEditWidget::setColor(const NLMISC::CRGBA &color, bool emit)
{
_emit = false;
_ui.rSpinBox->setValue(color.R);
_ui.gSpinBox->setValue(color.G);
_ui.bSpinBox->setValue(color.B);
_ui.aSpinBox->setValue(color.A);
_emit = true;
if (emit)
Q_EMIT colorChanged(color);
}
void CColorEditWidget::setColor(const QColor &color, bool emit)
{
setColor(NLMISC::CRGBA(color.red(), color.green(), color.blue(), color.alpha()), emit);
}
void CColorEditWidget::updateUi()
{
if (_Wrapper == NULL) return;
_ui.rSpinBox->setValue(_Wrapper->get().R);
_ui.gSpinBox->setValue(_Wrapper->get().G);
_ui.bSpinBox->setValue(_Wrapper->get().B);
_ui.aSpinBox->setValue(_Wrapper->get().A);
_ui.graphicsWidget->setColor(QColor(_ui.rSpinBox->value(), _ui.gSpinBox->value(), _ui.bSpinBox->value(), _ui.aSpinBox->value()));
}
void CColorEditWidget::setRed(int r)
{
_ui.graphicsWidget->setColor(QColor(_ui.rSpinBox->value(), _ui.gSpinBox->value(), _ui.bSpinBox->value(), _ui.aSpinBox->value()));
if (_emit)
Q_EMIT colorChanged(NLMISC::CRGBA(r, _ui.gSpinBox->value(), _ui.bSpinBox->value(), _ui.aSpinBox->value()));
if (_Wrapper == NULL)
return;
NLMISC::CRGBA color = _Wrapper->get();
if (r == color.R)
return;
color.R = r;
_Wrapper->setAndUpdateModifiedFlag(color);
}
void CColorEditWidget::setGreen(int g)
{
_ui.graphicsWidget->setColor(QColor(_ui.rSpinBox->value(), _ui.gSpinBox->value(), _ui.bSpinBox->value(), _ui.aSpinBox->value()));
if (_emit)
Q_EMIT colorChanged(NLMISC::CRGBA(_ui.rSpinBox->value(), g, _ui.bSpinBox->value(), _ui.aSpinBox->value()));
if (_Wrapper == NULL) return;
NLMISC::CRGBA color = _Wrapper->get();
if (g == color.G)
return;
color.G = g;
_Wrapper->setAndUpdateModifiedFlag(color);
}
void CColorEditWidget::setBlue(int b)
{
_ui.graphicsWidget->setColor(QColor(_ui.rSpinBox->value(), _ui.gSpinBox->value(), _ui.bSpinBox->value(), _ui.aSpinBox->value()));
if (_emit)
Q_EMIT colorChanged(NLMISC::CRGBA(_ui.rSpinBox->value(), _ui.gSpinBox->value(), b, _ui.aSpinBox->value()));
if (_Wrapper == NULL) return;
NLMISC::CRGBA color = _Wrapper->get();
if (b == color.B)
return;
color.B = b;
_Wrapper->setAndUpdateModifiedFlag(color);
}
void CColorEditWidget::setAlpha(int a)
{
_ui.graphicsWidget->setColor(QColor(_ui.rSpinBox->value(), _ui.gSpinBox->value(), _ui.bSpinBox->value(), a));
if (_emit)
Q_EMIT colorChanged(NLMISC::CRGBA(_ui.rSpinBox->value(), _ui.gSpinBox->value(), _ui.bSpinBox->value(), a));
if (_Wrapper == NULL) return;
NLMISC::CRGBA color = _Wrapper->get();
if (a == color.A)
return;
color.A = a;
_Wrapper->setAndUpdateModifiedFlag(color);
}
void CColorEditWidget::browseColor()
{
QColor color = QColorDialog::getColor(QColor(_ui.rSpinBox->value(),
_ui.gSpinBox->value(),
_ui.bSpinBox->value(),
_ui.aSpinBox->value()));
if (!color.isValid()) return;
setColor(color);
}
} /* namespace NLQT */

View file

@ -0,0 +1,101 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COLOR_EDIT_WIDGET_H
#define COLOR_EDIT_WIDGET_H
#include "ui_color_edit_form.h"
// Qt includes
// Project includes
#include "ps_wrapper.h"
namespace NLQT {
/**
@class CColorEditWidget
@brief The widget provides a 4 horizontal slider or color dialog, to set the color.
@details Using this widget you can set the color(RGBA) using the four sliders or through the color selection dialog.
Widget at the same time displays the color in the shaded rectangle at the side of the sliders.
Use this widget, have two ways: Qt Q_SIGNAL/SLOT or wrapper.
1. Using the Qt Q_SIGNALS/SLOT can be set current color by class methods setColor() and
changes in current color(QSliders or QColorDialog) emits the signal colorChanged().
2. Using wrapper, create wpapper struct, example:
@code
struct CAmbientColorWrapper : public IPSWrapperRGBA
{
NL3D::UScene *S;
void set(const NLMISC::CRGBA &col) { S->setSunAmbient(col); }
NLMISC::CRGBA get() const { return S->getSunAmbient(); }
} _AmbientColorWrapper;
@endcode
to set the current values, need call class methods updateUi();
*/
class CColorEditWidget: public QWidget
{
Q_OBJECT
public:
/// Constructor, sets the default color (255, 255, 255, 255)
CColorEditWidget(QWidget *parent = 0);
~CColorEditWidget();
/// Sets the current color.
/// @param color - NeL NLMISC::CRGBA color
/// @param emit - will emit colorChanged() if the new value is different from the old one and param emit = true
void setColor(const NLMISC::CRGBA &color, bool emit = true);
/// Sets the current color.
/// @param color - Qt QColor color
/// @param emit - will emit colorChanged() if the new value is different from the old one and param emit = true
void setColor(const QColor &color, bool emit = true);
/// Set a wrapper to get/set the datas.
void setWrapper(IPSWrapperRGBA *wrapper);
/// Update the content of the widget using the wrapper.
void updateUi();
Q_SIGNALS:
void colorChanged(NLMISC::CRGBA color);
private Q_SLOTS:
void setRed(int r);
void setGreen(int g);
void setBlue(int b);
void setAlpha(int a);
void browseColor();
private:
// wrapper to the datas
IPSWrapperRGBA *_Wrapper;
bool _emit;
Ui::CColorEditWidget _ui;
}; /* class CColorEditWidget */
} /* namespace NLQT */
#endif // COLOR_EDIT_WIDGET_H

View file

@ -0,0 +1,222 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "configuration.h"
// NeL includes
#include <nel/misc/debug.h>
#include <nel/misc/hierarchical_timer.h>
#include <nel/misc/config_file.h>
#include <nel/misc/path.h>
#include "modules.h"
using namespace std;
using namespace NLMISC;
namespace NLQT {
CConfiguration::CConfiguration()
{
}
CConfiguration::~CConfiguration()
{
}
void CConfiguration::init()
{
nldebug("CConfiguration::init");
// verify data
nlassert(!ConfigCallbacks.size());
// load config
try
{
ConfigFile.load(NLQT_CONFIG_FILE);
}
catch(...)
{
nlerror("Error opening files object_viewer.cfg or object_viewer_default.cfg. Check this files");
}
// setup config file callback
Modules::config().setCallback("SearchPaths", CConfigCallback(this, &CConfiguration::cfcbSearchPaths));
}
void CConfiguration::release()
{
nldebug("CConfiguration::release");
Modules::config().dropCallback("SearchPaths");
// save and release the config file
if (ConfigFile.exists("SaveConfig") && ConfigFile.getVarPtr("SaveConfig")->asBool())
{
ConfigFile.save();
}
ConfigFile.clear();
// release the search paths etc
CPath::releaseInstance();
// verify data
nlassert(!ConfigCallbacks.size());
}
void CConfiguration::updateUtilities()
{
//H_AUTO2
CConfigFile::checkConfigFiles();
}
void CConfiguration::configSearchPaths()
{
cfcbSearchPaths(Modules::config().getConfigFile().getVar("SearchPaths"));
}
void CConfiguration::configRemapExtensions()
{
CConfigFile::CVar *var;
var = ConfigFile.getVarPtr("RemapExtensions");
uint varsize = var->size();
for (uint i = 0; i < varsize; i += 2)
CPath::remapExtension(var->asString(i), var->asString(i + 1), true);
}
void CConfiguration::setAndCallback(const std::string &varName, CConfigCallback configCallback)
{
ConfigCallbacks[varName] = configCallback;
ConfigFile.setCallback(varName, cbConfigCallback);
configCallback(*ConfigFile.getVarPtr(varName));
}
void CConfiguration::setCallback(const std::string &varName, CConfigCallback configCallback)
{
ConfigCallbacks[varName] = configCallback;
ConfigFile.setCallback(varName, cbConfigCallback);
}
void CConfiguration::dropCallback(const std::string &varName)
{
ConfigFile.setCallback(varName, NULL);
ConfigCallbacks.erase(varName);
}
float CConfiguration::getValue(const string &varName, float defaultValue)
{
if (ConfigFile.exists(varName)) return ConfigFile.getVar(varName).asFloat();
CConfigFile::CVar varToCopy;
varToCopy.forceAsDouble((double)defaultValue);
ConfigFile.insertVar(varName, varToCopy);
return defaultValue;
}
double CConfiguration::getValue(const string &varName, double defaultValue)
{
if (ConfigFile.exists(varName)) return ConfigFile.getVar(varName).asDouble();
CConfigFile::CVar varToCopy;
varToCopy.forceAsDouble(defaultValue);
ConfigFile.insertVar(varName, varToCopy);
return defaultValue;
}
int CConfiguration::getValue(const string &varName, int defaultValue)
{
if (ConfigFile.exists(varName)) return ConfigFile.getVar(varName).asInt();
CConfigFile::CVar varToCopy;
varToCopy.forceAsInt(defaultValue);
ConfigFile.insertVar(varName, varToCopy);
return defaultValue;
}
string CConfiguration::getValue(const string &varName, const string &defaultValue)
{
if (ConfigFile.exists(varName)) return ConfigFile.getVar(varName).asString();
CConfigFile::CVar varToCopy;
varToCopy.forceAsString(defaultValue);
ConfigFile.insertVar(varName, varToCopy);
return defaultValue;
}
ucstring CConfiguration::getValue(const string &varName, const ucstring &defaultValue)
{
if (ConfigFile.exists(varName)) return ucstring::makeFromUtf8(ConfigFile.getVar(varName).asString());
CConfigFile::CVar varToCopy;
varToCopy.forceAsString(defaultValue.toUtf8());
ConfigFile.insertVar(varName, varToCopy);
return defaultValue;
}
bool CConfiguration::getValue(const string &varName, bool defaultValue)
{
if (ConfigFile.exists(varName)) return ConfigFile.getVar(varName).asBool();
CConfigFile::CVar varToCopy;
varToCopy.forceAsInt(defaultValue ? 1 : 0);
ConfigFile.insertVar(varName, varToCopy);
return defaultValue;
}
CRGBA CConfiguration::getValue(const string &varName, const CRGBA &defaultValue)
{
if (ConfigFile.exists(varName))
{
return getValue(ConfigFile.getVar(varName), defaultValue);
}
else
{
// create a new value only if one doesn't exist
CConfigFile::CVar varToCopy;
varToCopy.forceAsInt(defaultValue.R);
varToCopy.setAsInt(defaultValue.G, 1);
varToCopy.setAsInt(defaultValue.B, 2);
varToCopy.setAsInt(defaultValue.A, 3);
ConfigFile.insertVar(varName, varToCopy);
}
return defaultValue;
}
CRGBA CConfiguration::getValue(const CConfigFile::CVar &var, const CRGBA &defaultValue)
{
if (var.size() >= 3)
{
if (var.size() > 4) nlwarning("RGBA value in config value '%s' is too long, ignoring unused values");
return CRGBA((uint8)var.asInt(0), (uint8)var.asInt(1), (uint8)var.asInt(2), var.size() >= 4 ? (uint8)var.asInt(3) : 255);
}
nlwarning("Invalid RGBA value in config value '%s', reverting to default { %i, %i, %i, %i }", var.Name.c_str(), (sint)defaultValue.R, (sint)defaultValue.G, (sint)defaultValue.B, (sint)defaultValue.A);
return defaultValue;
}
void CConfiguration::cbConfigCallback(NLMISC::CConfigFile::CVar &var)
{
Modules::config().ConfigCallbacks[var.Name](var);
}
void CConfiguration::cfcbSearchPaths(NLMISC::CConfigFile::CVar &var)
{
uint varsize = var.size();
for (uint i = 0; i < varsize; ++i)
CPath::addSearchPath(var.asString(i), true, false);
}
} /* namespace NLQT */

View file

@ -0,0 +1,93 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONFIGURATION_H
#define CONFIGURATION_H
#include <nel/misc/types_nl.h>
// STL includes
#include <map>
// NeL includes
#include <nel/misc/config_file.h>
#include <nel/misc/rgba.h>
#include <nel/misc/ucstring.h>
// Project includes
#include "callback.h"
#define NLQT_CONFIG_FILE "object_viewer.cfg"
namespace NLQT {
typedef CCallback<void, NLMISC::CConfigFile::CVar &> CConfigCallback;
/**
@class CConfiguration
@date 2010-02-05 15:44GMT
@author Jan Boon (Kaetemi)
@brief Read / write settings from the configuration file
@details Load the configuration file, and then read/write settings.
As well as automatic reading of the search paths and their sets.
*/
class CConfiguration
{
public:
CConfiguration();
virtual ~CConfiguration();
void init();
void release();
void updateUtilities();
void configSearchPaths();
void configRemapExtensions();
void setAndCallback(const std::string &varName, CConfigCallback configCallback);
void setCallback(const std::string &varName, CConfigCallback configCallback);
void dropCallback(const std::string &varName);
float getValue(const std::string &varName, float defaultValue);
double getValue(const std::string &varName, double defaultValue);
int getValue(const std::string &varName, int defaultValue);
std::string getValue(const std::string &varName, const std::string &defaultValue);
ucstring getValue(const std::string &varName, const ucstring &defaultValue);
bool getValue(const std::string &varName, bool defaultValue);
NLMISC::CRGBA getValue(const std::string &varName, const NLMISC::CRGBA &defaultValue);
NLMISC::CRGBA getValue(const NLMISC::CConfigFile::CVar &var, const NLMISC::CRGBA &defaultValue);
inline NLMISC::CConfigFile &getConfigFile() { return ConfigFile; }
private:
static void cbConfigCallback(NLMISC::CConfigFile::CVar &var);
void cfcbSearchPaths(NLMISC::CConfigFile::CVar &var);
CConfiguration(const CConfiguration &);
CConfiguration &operator=(const CConfiguration &);
NLMISC::CConfigFile ConfigFile;
std::map<std::string, CConfigCallback> ConfigCallbacks;
};/* class CConfiguration */
} /* namespace NLQT */
#endif // CONFIGURATION_H

View file

@ -0,0 +1,458 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CConstraintMeshWidget</class>
<widget class="QWidget" name="CConstraintMeshWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>238</width>
<height>460</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Force stage modulation</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QCheckBox" name="stageCheckBox_0">
<property name="text">
<string>Stage 0</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="stageCheckBox_1">
<property name="text">
<string>Stage 1</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="stageCheckBox_2">
<property name="text">
<string>Stage 2</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="stageCheckBox_3">
<property name="text">
<string>Stage 3</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="vertexColorLightingCheckBox">
<property name="text">
<string>Force vertex color lighting</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Texture anim type:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="texAnimTypeComboBox">
<property name="currentIndex">
<number>1</number>
</property>
<item>
<property name="text">
<string>None</string>
</property>
</item>
<item>
<property name="text">
<string>Global</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="reinitCheckBox">
<property name="text">
<string>Reinit when new element is created</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="stageLabel">
<property name="text">
<string>Stage:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="stageSpinBox">
<property name="maximum">
<number>3</number>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QTabWidget" name="tabWidget">
<property name="tabPosition">
<enum>QTabWidget::South</enum>
</property>
<property name="currentIndex">
<number>1</number>
</property>
<property name="movable">
<bool>true</bool>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Translation</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="transUStartDoubleSpinBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>V Start:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="transVStartDoubleSpinBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>U Speed:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="transUSpeedDoubleSpinBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>V Speed:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="transVSpeedDoubleSpinBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>U Accel:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QDoubleSpinBox" name="transUAccelDoubleSpinBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>V Accel:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QDoubleSpinBox" name="transVAccelDoubleSpinBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>U Start:</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Scale</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>U Start:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="scaleUStartDoubleSpinBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>V Start:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="scaleVStartDoubleSpinBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>U Speed:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="scaleUSpeedDoubleSpinBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>V Speed:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="scaleVSpeedDoubleSpinBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>U Accel:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QDoubleSpinBox" name="scaleUAccelDoubleSpinBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>V Accel:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QDoubleSpinBox" name="scaleVAccelDoubleSpinBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Rotation</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Speed:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="rotSpeedDoubleSpinBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>9999999.000000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Accel:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="rotAccelDoubleSpinBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>144</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,220 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "constraint_mesh_widget.h"
// NeL includes
#include "nel/3d/ps_mesh.h"
namespace NLQT {
CConstraintMeshWidget::CConstraintMeshWidget(QWidget *parent )
: QWidget(parent)
{
_ui.setupUi(this);
connect(_ui.stageCheckBox_0, SIGNAL(clicked(bool)), this, SLOT(setForceStage0(bool)));
connect(_ui.stageCheckBox_1, SIGNAL(clicked(bool)), this, SLOT(setForceStage1(bool)));
connect(_ui.stageCheckBox_2, SIGNAL(clicked(bool)), this, SLOT(setForceStage2(bool)));
connect(_ui.stageCheckBox_3, SIGNAL(clicked(bool)), this, SLOT(setForceStage3(bool)));
connect(_ui.vertexColorLightingCheckBox, SIGNAL(clicked(bool)), this, SLOT(setForceVertexColorLighting(bool)));
connect(_ui.texAnimTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setTexAnimType(int)));
connect(_ui.reinitCheckBox, SIGNAL(toggled(bool)), this, SLOT(setReinitWhenNewElementIsCreated(bool)));
connect(_ui.stageSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setStage(int)));
connectGlobalTexAnim();
}
CConstraintMeshWidget::~CConstraintMeshWidget()
{
}
void CConstraintMeshWidget::connectGlobalTexAnim()
{
connect(_ui.transUStartDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
connect(_ui.transVStartDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
connect(_ui.transUSpeedDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
connect(_ui.transVSpeedDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
connect(_ui.transUAccelDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
connect(_ui.transVAccelDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
connect(_ui.scaleUStartDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
connect(_ui.scaleVStartDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
connect(_ui.scaleUSpeedDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
connect(_ui.scaleVSpeedDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
connect(_ui.scaleUAccelDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
connect(_ui.scaleVAccelDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
connect(_ui.rotSpeedDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
connect(_ui.rotAccelDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
}
void CConstraintMeshWidget::disconnectGlobalTexAnim()
{
disconnect(_ui.transUStartDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
disconnect(_ui.transVStartDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
disconnect(_ui.transUSpeedDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
disconnect(_ui.transVSpeedDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
disconnect(_ui.transUAccelDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
disconnect(_ui.transVAccelDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
disconnect(_ui.scaleUStartDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
disconnect(_ui.scaleVStartDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
disconnect(_ui.scaleUSpeedDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
disconnect(_ui.scaleVSpeedDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
disconnect(_ui.scaleUAccelDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
disconnect(_ui.scaleVAccelDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
disconnect(_ui.rotSpeedDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
disconnect(_ui.rotAccelDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setGlobalTexAnimValue()));
}
void CConstraintMeshWidget::setCurrentConstraintMesh(CWorkspaceNode *ownerNode, NL3D::CPSConstraintMesh *cm)
{
_Node = ownerNode;
_CM = cm;
_ui.stageCheckBox_0->setChecked(_CM->isStageModulationForced(0));
_ui.stageCheckBox_1->setChecked(_CM->isStageModulationForced(1));
_ui.stageCheckBox_2->setChecked(_CM->isStageModulationForced(2));
_ui.stageCheckBox_3->setChecked(_CM->isStageModulationForced(3));
_ui.vertexColorLightingCheckBox->setChecked(_CM->isVertexColorLightingForced());
_ui.texAnimTypeComboBox->setCurrentIndex(_CM->getTexAnimType());
if (_CM->getTexAnimType() == NL3D::CPSConstraintMesh::GlobalAnim)
{
_ui.reinitCheckBox->setChecked(_CM->isGlobalAnimTimeResetOnNewElementForced());
updateGlobalTexAnim(0);
}
}
void CConstraintMeshWidget::setForceStage0(bool state)
{
_CM->forceStageModulationByColor(0, state);
}
void CConstraintMeshWidget::setForceStage1(bool state)
{
_CM->forceStageModulationByColor(1, state);
}
void CConstraintMeshWidget::setForceStage2(bool state)
{
_CM->forceStageModulationByColor(2, state);
}
void CConstraintMeshWidget::setForceStage3(bool state)
{
_CM->forceStageModulationByColor(3, state);
}
void CConstraintMeshWidget::setForceVertexColorLighting(bool state)
{
_CM->forceVertexColorLighting(state);
}
void CConstraintMeshWidget::setTexAnimType(int index)
{
switch(index)
{
case 0: // no anim
_CM->setTexAnimType(NL3D::CPSConstraintMesh::NoAnim);
_ui.stageSpinBox->hide();
_ui.stageLabel->hide();
_ui.tabWidget->hide();
_ui.reinitCheckBox->hide();
break;
case 1: // global anim
_CM->setTexAnimType(NL3D::CPSConstraintMesh::GlobalAnim);
_ui.stageSpinBox->show();
_ui.stageLabel->show();
_ui.tabWidget->show();
_ui.reinitCheckBox->show();
_ui.stageSpinBox->setValue(0);
_ui.reinitCheckBox->setChecked(_CM->isGlobalAnimTimeResetOnNewElementForced());
break;
default:
nlstop;
break;
}
}
void CConstraintMeshWidget::setReinitWhenNewElementIsCreated(bool state)
{
_CM->forceGlobalAnimTimeResetOnNewElement(state);
}
void CConstraintMeshWidget::setStage(int value)
{
updateGlobalTexAnim(value);
}
void CConstraintMeshWidget::updateGlobalTexAnim(int value)
{
disconnectGlobalTexAnim();
const NL3D::CPSConstraintMesh::CGlobalTexAnim &gta = _CM->getGlobalTexAnim(value);
_ui.transUStartDoubleSpinBox->setValue(gta.TransOffset.x);
_ui.transVStartDoubleSpinBox->setValue(gta.TransOffset.y);
_ui.transUSpeedDoubleSpinBox->setValue(gta.TransSpeed.x);
_ui.transVSpeedDoubleSpinBox->setValue(gta.TransSpeed.y);
_ui.transUAccelDoubleSpinBox->setValue(gta.TransAccel.x);
_ui.transVAccelDoubleSpinBox->setValue(gta.TransAccel.y);
_ui.scaleUStartDoubleSpinBox->setValue(gta.ScaleStart.x);
_ui.scaleVStartDoubleSpinBox->setValue(gta.ScaleStart.y);
_ui.scaleUSpeedDoubleSpinBox->setValue(gta.ScaleSpeed.x);
_ui.scaleVSpeedDoubleSpinBox->setValue(gta.ScaleSpeed.y);
_ui.scaleUAccelDoubleSpinBox->setValue(gta.ScaleAccel.x);
_ui.scaleVAccelDoubleSpinBox->setValue(gta.ScaleAccel.y);
_ui.rotSpeedDoubleSpinBox->setValue(gta.WRotSpeed);
_ui.rotAccelDoubleSpinBox->setValue(gta.WRotAccel);
connectGlobalTexAnim();
}
void CConstraintMeshWidget::setGlobalTexAnimValue()
{
NL3D::CPSConstraintMesh::CGlobalTexAnim gta;
gta.TransOffset.x = _ui.transUStartDoubleSpinBox->value();
gta.TransOffset.y = _ui.transVStartDoubleSpinBox->value();
gta.TransSpeed.x = _ui.transUSpeedDoubleSpinBox->value();
gta.TransSpeed.y = _ui.transVSpeedDoubleSpinBox->value();
gta.TransAccel.x = _ui.transUAccelDoubleSpinBox->value();
gta.TransAccel.y = _ui.transVAccelDoubleSpinBox->value();
gta.ScaleStart.x = _ui.scaleUStartDoubleSpinBox->value();
gta.ScaleStart.y = _ui.scaleVStartDoubleSpinBox->value();
gta.ScaleSpeed.x = _ui.scaleUSpeedDoubleSpinBox->value();
gta.ScaleSpeed.y = _ui.scaleVSpeedDoubleSpinBox->value();
gta.ScaleAccel.x = _ui.scaleUAccelDoubleSpinBox->value();
gta.ScaleAccel.y = _ui.scaleVAccelDoubleSpinBox->value();
gta.WRotSpeed = _ui.rotSpeedDoubleSpinBox->value();
gta.WRotAccel = _ui.rotAccelDoubleSpinBox->value();
_CM->setGlobalTexAnim(_ui.stageSpinBox->value(), gta);
}
} /* namespace NLQT */

View file

@ -0,0 +1,80 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONSTRAINT_MESH_WIDGET_H
#define CONSTRAINT_MESH_WIDGET_H
#include "ui_constraint_mesh_form.h"
// STL includes
// Qt includes
// NeL includes
// Project includes
#include "particle_node.h"
namespace NL3D {
class CPSConstraintMesh;
}
namespace NLQT {
/**
@class CConstraintMeshWidget
@brief Widget for setup mesh that have very simple geometry.
*/
class CConstraintMeshWidget: public QWidget
{
Q_OBJECT
public:
CConstraintMeshWidget(QWidget *parent = 0);
~CConstraintMeshWidget();
/// Set the constraint mesh to edit.
void setCurrentConstraintMesh(CWorkspaceNode *ownerNode, NL3D::CPSConstraintMesh *cm);
private Q_SLOTS:
void setForceStage0(bool state);
void setForceStage1(bool state);
void setForceStage2(bool state);
void setForceStage3(bool state);
void setForceVertexColorLighting(bool state);
void setTexAnimType(int index);
void setReinitWhenNewElementIsCreated(bool state);
void setStage(int value);
void setGlobalTexAnimValue();
private:
void connectGlobalTexAnim();
void disconnectGlobalTexAnim();
void updateGlobalTexAnim(int value);
CWorkspaceNode *_Node;
NL3D::CPSConstraintMesh *_CM;
Ui::CConstraintMeshWidget _ui;
}; /* class CConstraintMeshWidget */
} /* namespace NLQT */
#endif // CONSTRAINT_MESH_WIDGET_H

View file

@ -0,0 +1,158 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "curve_dialog.h"
// Project includes
#include "particle_node.h"
namespace NLQT {
CurveEditDialog::CurveEditDialog(NL3D::CPSFloatCurveFunctor *curve, CWorkspaceNode *ownerNode, QWidget *parent)
: QDialog(parent) , _Curve(curve), _scale(1.0), _pos(0.0), _Node(ownerNode)
{
_ui.setupUi(this);
show();
_hoverPoints = new HoverPoints(_ui.curveWidget, HoverPoints::CircleShape);
if (_Curve->hasSmoothing())
_hoverPoints->setConnectionType(HoverPoints::CurveConnection);
else
_hoverPoints->setConnectionType(HoverPoints::LineConnection);
_ui.smoothingCheckBox->setChecked(_Curve->hasSmoothing());
buildPoints();
_hoverPoints->setSortType(HoverPoints::XSort);
_hoverPoints->setShapePen(QPen(QColor(0, 0, 100, 127), 1));
_hoverPoints->setShapeBrush(QBrush(QColor(0, 0, 200, 127)));
_hoverPoints->setConnectionPen(QPen(QColor(0, 0, 0, 127), 1));
// FLOAT_CURVE_NB_SAMPLE
_ui.numSamplesWidget->setRange(1, 512);
_ui.numSamplesWidget->enableLowerBound(1, true);
_ui.numSamplesWidget->setValue(_Curve->getNumSamples());
connect(_ui.smoothingCheckBox, SIGNAL(toggled(bool)), this, SLOT(setSmoothing(bool)));
connect(_hoverPoints, SIGNAL(pointsChanged(QPolygonF)), this, SLOT(curveChanged(QPolygonF)));
connect(_ui.posVerticalSlider, SIGNAL(valueChanged(int)), this, SLOT(setPosition(int)));
connect(_ui.sizeVerticalSlider, SIGNAL(valueChanged(int)), this, SLOT(setScale(int)));
connect(_ui.firstLastPushButton, SIGNAL(clicked()), this, SLOT(setLastTiFirst()));
connect(_ui.lastFirstPushButton, SIGNAL(clicked()), this, SLOT(setFirstToLast()));
connect(_ui.centerToolButton, SIGNAL(clicked()), this, SLOT(setCenter()));
connect(_ui.numSamplesWidget, SIGNAL(valueChanged(uint32)), this, SLOT(setNumSamples(uint32)));
//setCenter();
}
CurveEditDialog::~CurveEditDialog()
{
}
void CurveEditDialog::setSmoothing(bool state)
{
if (state)
_hoverPoints->setConnectionType(HoverPoints::CurveConnection);
else
_hoverPoints->setConnectionType(HoverPoints::LineConnection);
_Curve->enableSmoothing(state);
_ui.curveWidget->update();
}
void CurveEditDialog::setDisplayInterpolation(bool state)
{
}
void CurveEditDialog::curveChanged(const QPolygonF &points)
{
if (_Curve->getNumCtrlPoints() > uint(points.size()))
_Curve->removeCtrlPoint(0);
else if (_Curve->getNumCtrlPoints() < uint(points.size()))
_Curve->addControlPoint(NL3D::CPSFloatCurveFunctor::CCtrlPoint(1, 0.5f));
for (int i = 0; i < points.size(); i++)
_Curve->setCtrlPoint(uint(i), NL3D::CPSFloatCurveFunctor::CCtrlPoint(points.at(i).x() / _ui.curveWidget->width(),
(_ui.curveWidget->height() - points.at(i).y() + _pos) / (_ui.curveWidget->height() * _scale)));
}
void CurveEditDialog::setScale(int value)
{
_scale = value / float(_ui.sizeVerticalSlider->maximum() / 2);
buildPoints();
_ui.curveWidget->update();
}
void CurveEditDialog::setPosition(int value)
{
_pos = (value - (_ui.posVerticalSlider->maximum() / 2));
buildPoints();
_ui.curveWidget->update();
}
void CurveEditDialog::setCenter()
{
float maxValue = _Curve->getMaxValue();
float minValue = _Curve->getMinValue();
float fScale = (maxValue == minValue) ? 1.f : 1.f / (maxValue - minValue);
int iScale = int(fScale * _ui.sizeVerticalSlider->maximum() / 2);
_ui.sizeVerticalSlider->setValue(iScale);
int pos = _ui.curveWidget->height() - (_scale * maxValue * _ui.curveWidget->height());
_ui.posVerticalSlider->setValue((_ui.posVerticalSlider->maximum() / 2) - pos);
}
void CurveEditDialog::setLastTiFirst()
{
NL3D::CPSFloatCurveFunctor::CCtrlPoint pt = _Curve->getControlPoint(_Curve->getNumCtrlPoints() - 1);
pt.Date = _Curve->getControlPoint(0).Date;
_Curve->setCtrlPoint(0, pt);
buildPoints();
_ui.curveWidget->update();
}
void CurveEditDialog::setFirstToLast()
{
NL3D::CPSFloatCurveFunctor::CCtrlPoint pt = _Curve->getControlPoint(0);
pt.Date = _Curve->getControlPoint(_Curve->getNumCtrlPoints() - 1).Date;
_Curve->setCtrlPoint(_Curve->getNumCtrlPoints() - 1, pt);
buildPoints();
_ui.curveWidget->update();
}
void CurveEditDialog::setNumSamples(uint32 value)
{
_Curve->setNumSamples(value);
}
void CurveEditDialog::buildPoints()
{
QPolygonF points;
for (uint i = 0; i < _Curve->getNumCtrlPoints(); i++)
points << QPointF((_Curve->getControlPoint(i).Date * _ui.curveWidget->width()),
_pos + _ui.curveWidget->height() - (_scale * _Curve->getControlPoint(i).Value * _ui.curveWidget->height()));
_hoverPoints->setPoints(points);
//_hoverPoints->setPointLock(0, HoverPoints::LockToLeft);
//_hoverPoints->setPointLock(points.size() - 1, HoverPoints::LockToRight);
}
} /* namespace NLQT */

View file

@ -0,0 +1,83 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CURVE_DIALOG_H
#define CURVE_DIALOG_H
#include <nel/misc/types_nl.h>
#include "ui_curve_form.h"
// NeL includes
#include <nel/3d/ps_float.h>
// Qt includes
#include <QtGui/QDialog>
#include <QtGui/QGridLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QWidget>
// Project includes
#include "hoverpoints.h"
#include "ps_wrapper.h"
namespace NLQT {
/**
@class CurveEditDialog
@brief Dialogue editing graphics curve.
@details Adding / removing control points, scaling and moving graphics curve.
The choice of the interpolation algorithm.
*/
class CurveEditDialog : public QDialog
{
Q_OBJECT
public:
CurveEditDialog(NL3D::CPSFloatCurveFunctor *curve, CWorkspaceNode *ownerNode, QWidget *parent = 0);
~CurveEditDialog();
/// the scheme being edited
NL3D::CPSFloatCurveFunctor *_Curve;
private Q_SLOTS:
void setSmoothing(bool state);
void setDisplayInterpolation(bool state);
void curveChanged(const QPolygonF &points);
void setScale(int value);
void setPosition(int value);
void setCenter();
void setLastTiFirst();
void setFirstToLast();
void setNumSamples(uint32 value);
protected:
void buildPoints();
float _scale;
float _pos;
CWorkspaceNode *_Node;
HoverPoints *_hoverPoints;
Ui::CurveEditDialog _ui;
}; /* CurveEditDialog */
} /* namespace NLQT */
#endif // CURVE_DIALOG_H

View file

@ -0,0 +1,253 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CurveEditDialog</class>
<widget class="QDialog" name="CurveEditDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>528</width>
<height>478</height>
</rect>
</property>
<property name="windowTitle">
<string>Curve edit</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QWidget" name="curveWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Left click to add points.
Right click to remove points.</string>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Zoom:</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="sizeVerticalSlider">
<property name="toolTip">
<string>Scale curve</string>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="pageStep">
<number>1000</number>
</property>
<property name="value">
<number>5000</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="invertedAppearance">
<bool>true</bool>
</property>
<property name="invertedControls">
<bool>false</bool>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>1000</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Translate:</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="posVerticalSlider">
<property name="toolTip">
<string>Position curve</string>
</property>
<property name="maximum">
<number>5000</number>
</property>
<property name="pageStep">
<number>500</number>
</property>
<property name="value">
<number>2500</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>500</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Num samples:</string>
</property>
</widget>
</item>
<item row="2" column="1" rowspan="2">
<widget class="QToolButton" name="centerToolButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="object_viewer_qt.qrc">
<normaloff>:/images/refresh.png</normaloff>:/images/refresh.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="NLQT::CEditRangeUIntWidget" name="numSamplesWidget" native="true"/>
</item>
<item row="4" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="lastFirstPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Last=First</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="firstLastPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>First=Last</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="interpolationCheckBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Display interpolation</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="smoothingCheckBox">
<property name="text">
<string>Smoothing</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Ok</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>NLQT::CEditRangeUIntWidget</class>
<extends>QWidget</extends>
<header>edit_range_widget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="object_viewer_qt.qrc"/>
</resources>
<connections>
<connection>
<sender>pushButton</sender>
<signal>clicked()</signal>
<receiver>CurveEditDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>463</x>
<y>401</y>
</hint>
<hint type="destinationlabel">
<x>373</x>
<y>402</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -0,0 +1,48 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "day_night_dialog.h"
// NeL incldes
#include "nel/3d/u_water.h"
// Project includes
#include "modules.h"
namespace NLQT {
CDayNightDialog::CDayNightDialog(QWidget *parent)
: QDockWidget(parent)
{
_ui.setupUi(this);
connect(_ui.horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(setDayNight(int)));
}
CDayNightDialog::~CDayNightDialog()
{
}
void CDayNightDialog::setDayNight(int value)
{
NL3D::UWaterHeightMapManager::setBlendFactor(Modules::objView().getDriver(), float(value) / _ui.horizontalSlider->maximum());
}
} /* namespace NLQT */

View file

@ -0,0 +1,56 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DAY_NIGHT_DIALOG_H
#define DAY_NIGHT_DIALOG_H
#include "ui_day_night_form.h"
// STL includes
// NeL includes
// Project includes
namespace NLQT {
/**
@class CDayNightDialog
@brief Dialog set time of day.
@details Dialogue only affects the water shape.
*/
class CDayNightDialog: public QDockWidget
{
Q_OBJECT
public:
CDayNightDialog(QWidget *parent = 0);
~CDayNightDialog();
private Q_SLOTS:
void setDayNight(int value);
private:
Ui::CDayNightDialog _ui;
}; /* class CDayNightDialog */
} /* namespace NLQT */
#endif // DAY_NIGHT_DIALOG_H

View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CDayNightDialog</class>
<widget class="QDockWidget" name="CDayNightDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>228</width>
<height>59</height>
</rect>
</property>
<property name="windowTitle">
<string>Day/Night</string>
</property>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Day</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="horizontalSlider">
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Night</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,145 @@
/**
@mainpage Object Viewer Qt
@author Dzmitry Kamiahin <dnk-88@tut.by>, (C) 2010
@section introduce Introduce
@details
The Object Viewer Qt (ovqt) is a tool for working with graphics technology NeL data,
which can be useful durung the development and preparation of the game content.
The tool can be used in different tasks:
- Loading and viewing NeL data (.shape, .ps) files with the ability to set wind power, color light.
- Viewing animation shape (loading .anim, .skel, .swt files) using playlist or slot manager(mixing animation).
- Create and modify NeL particle system.
- Viewing water shape with the ability to set day/night.
- Modify skeleton (.skel files, .scale file).
- Create and modify micro-vegetation material (.vegetset files)
- Viewing landscape (.zonel files)
- Dialog allows to specify graphical, sound, search path and landscape settings.
@section project_structure Overview of the Object Viewer Qt Project Structure
@details
OVQT - consists of several major subsystems. Each subsystem performs its defined part of the task.
Through Modules:: provides access to all other program subsystems.
Program has the following subsystems:
- @ref Modules - Main modules aggregated all parts of the program.
- @ref NLQT::CConfiguration - is responsible for loading and saving settings from the configuration file. As well as search path of data.
- @ref NLQT::CObjectViewer - main subsystem of the program, which initializes the driver, creates a scene and other supporting elements.
It is a container for loaded models, which can further be viewed and animated.
- @ref NLQT::CMainWindow - is responsible for the GUI.
- @ref NLQT::CParticleEditor - is responsible for the particle systems and provides access to a container that keeps all the loaded particle systems.
And also allows you to view an animation of particle systems, with the ability to control its parameters.
- @ref NLQT::CVegetableEditor - is responsible for the landscape zones and the editor of vegetation.
Allows you to load and view the landscape. Also has the ability to create and edit the parameters of the micro-vegetation.
- @ref NLQT::CSoundSystem - is responsible for the sound in the program.
<b>
The structure of the GUI in the editor of the particles.
</b><br>
This can be useful for new developers who want to add more new dialogs or to improve the functionality of existing dialogues.
<img src="gui_struct.png" alt="Particle Workspace">
ParticleWorkspace dialogue uses the technique of model-view.
Using the signal/slot link QTreeView with QStackWidget, Editor properties dialog.
When you select an item in QTreeView, QStackWidget displays the necessary page(PageWidget) where you can edit the element of the particles system.
Each page is made in the designer and has a separate forms(.ui).
In accordance with the recommendations of dialogues design, with a large number of items,every page uses QTabWidget.
In case when there is a great number of controls, and not everything you want to display,
it's used the dynamic creation of tabs. Moreover, each tab uses a separate forms(.ui).
@section for_new_developer Guide for new developers of the Object Viewer Qt.
@details
First of all, to begin developing dialogues that add new features ovqt,
it is needed to read the documentation Qt libs (http://doc.qt.nokia.com/) and NeL documentation.
In order to have convenient using of the tool and its further development,
it is expected to make a unified interface that is why all dialogs should adhere to a standard design,
which will be written further. For this goals program provides some additional widgets,
which are recommended to use. As in the development Qt Designer is actively used.
To get access to founded here widgets from the designer,the technique promotion is used,
which can be found <a href="http://doc.qt.nokia.com/4.5/designer-using-custom-widgets.html"> here </a>.
<ol>
<li><b>
CEditRangeUIntWidget / CEditRangeIntWidget / CEditRangeFloatWidget
</b><br>
Widgets provides a slider that allows you to specify an integer (or float, depending on which widget used) number within a set range.
The range is also can be set by the user, or for a more accurate selection of numbers, either for receiving large values.
As there may be situations when the range that a user requests,has to be restricted, and widget provides methods that allow you to do so.
<br><br>
<img src="cedit_range_int_widget.png" alt="CEditRangeIntWidget">
<br>
<img src="cedit_range_float_widget.png" alt="CEditRangeFloatWidget">
@see
@ref NLQT::CEditRangeUIntWidget, @ref NLQT::CEditRangeIntWidget, @ref NLQT::CEditRangeFloatWidget
<li><b>
CColorEditWidget
</b><br>
Using this widget you can set the color(RGBA) using the four sliders or through the color selection dialog.
<br><br>
<img src="cedit_color_widget.png" alt="CColorEditWidget">
@see
@ref NLQT::CColorEditWidget
<li><b>
CDirectionWidget
</b><br>
This widget helps to choose from several preset directions, or to choose a custom one.
To use it you have to create a wrapper.
<br><br>
<img src="cdirection_widget.png" alt="CDirectionWidget">
@see
@ref NLQT::CDirectionWidget
</ol><br><br>
To further convinience of instrument using dialogues interface is recommended to make as follows.
The most sophisticated tools of the program, should take the form of three dock windows (example shown in the screenshot).
<img src="object_viewer_qt_window.png" alt="Object Viewer Qt">
<ol>
<li>
The first dock window - is a control dock window, it should focus all of the control functions of general purpose
(for example: start/stop/pause animations or particles system).
It is recommended to perform of the horizontal type window and placed in the bottom of the main window.
<li>
The second dock window - is a list or a tree of items. In which selecting of the current element,
which assumes to modify or viewis possible.Operations "add/remove/insert or other" items are recommended to make as a popur menu.
It is recommended to perform of the vertical type window and placed in the left of the main window.
<li>
The third dock - is an editor for properties of the element that was selected in the list or in the tree of elements.
As all the controls occupy much space or do not fit at all, you have to use tabs QTabWidget,
which in total can contains quite a lot of elements.
For a small number of tabs it is allowed to use both horizontal and vertical location.
But with a large number of tabs, it is necessary to apply the vertical arrangement.
It is recommended to perform of the vertical type of window and placed in the right of the main window.
</ol>
In the simple dialogues do not necessary to use all three windows, but user has to adhere to the recommendations given above as well.
Also, <b>all dialogs must use the qt layout manager</b>. And if you do not use the designer,
make sure you use the qt tools internationalization applications.
<br><br>
In ovqt for most dialogs their owner is NLQT::CMainWindow and in its methods creating and initializing all dependent dialogs occur.
For the convenience of the program using, most dialogues are created in the form of docking windows.
Creating all the dialogues are carried out in a private method NLQT::CMainWindow::createDialogs().
Hence, it is necessary to add operations in this method to create new dialogues.
But we must take into account that at this moment is fully available only one component of the program CConfiguration,
to read the settings from the configuration file. The remaining components of the program are available only after the main window stays visible.
Calling the dialogues going through the menu or the toolbar, usually it is a checkable item.
Adding of the new menu items or items toolbars is need in methods NLQT::CMainWindow::createMenus(), NLQT::CMainWindow::createToolBars().
@section license_ovqt License Object Viewer Qt
@details
Object Viewer Qt
<br>
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
<br><br>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
<br><br>
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
<br><br>
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

View file

@ -0,0 +1,178 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CDirectionWidget</class>
<widget class="QWidget" name="CDirectionWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>268</width>
<height>101</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>Direction:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="incVecIPushButton">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>+I</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="incVecJPushButton">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>+J</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="incVecKPushButton">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>+K</string>
</property>
</widget>
</item>
<item row="1" column="3" rowspan="3">
<widget class="NLQT::CGraphicsInfoWidget" name="xzWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>75</width>
<height>75</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>75</width>
<height>75</height>
</size>
</property>
</widget>
</item>
<item row="1" column="4" rowspan="3">
<widget class="NLQT::CGraphicsInfoWidget" name="yzWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>75</width>
<height>75</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>75</width>
<height>75</height>
</size>
</property>
</widget>
</item>
<item row="1" column="5" rowspan="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>49</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="decVecIPushButton">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>-I</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="decVecJPushButton">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>-J</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="decVecKPushButton">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>-K</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QPushButton" name="globalPushButton">
<property name="text">
<string>Global</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>NLQT::CGraphicsInfoWidget</class>
<extends>QWidget</extends>
<header>graphics_info_widget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,217 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "direction_widget.h"
// Qt includes
#include <QtGui/QInputDialog>
// NeL includes
#include <nel/misc/vector.h>
#include <nel/3d/particle_system.h>
namespace NLQT {
CDirectionWidget::CDirectionWidget(QWidget *parent)
: QWidget(parent), _Wrapper(NULL), _DirectionWrapper(NULL)
{
_ui.setupUi(this);
_ui.xzWidget->setMode(Mode::Direction);
_ui.yzWidget->setMode(Mode::Direction);
_ui.xzWidget->setText("XZ");
_ui.yzWidget->setText("YZ");
_ui.globalPushButton->hide();
connect(_ui.globalPushButton ,SIGNAL(clicked()), this, SLOT(setGlobalDirection()));
connect(_ui.incVecIPushButton ,SIGNAL(clicked()), this, SLOT(incVecI()));
connect(_ui.incVecJPushButton ,SIGNAL(clicked()), this, SLOT(incVecJ()));
connect(_ui.incVecKPushButton ,SIGNAL(clicked()), this, SLOT(incVecK()));
connect(_ui.decVecIPushButton ,SIGNAL(clicked()), this, SLOT(decVecI()));
connect(_ui.decVecJPushButton ,SIGNAL(clicked()), this, SLOT(decVecJ()));
connect(_ui.decVecKPushButton ,SIGNAL(clicked()), this, SLOT(decVecK()));
connect(_ui.xzWidget, SIGNAL(applyNewVector(float,float)), this, SLOT(setNewVecXZ(float,float)));
connect(_ui.yzWidget, SIGNAL(applyNewVector(float,float)), this, SLOT(setNewVecYZ(float,float)));
}
CDirectionWidget::~CDirectionWidget()
{
}
void CDirectionWidget::setWrapper(IPSWrapper<NLMISC::CVector> *wrapper)
{
_Wrapper = wrapper;
_ui.globalPushButton->hide();
}
void CDirectionWidget::setDirectionWrapper(NL3D::CPSDirection *wrapper)
{
_DirectionWrapper = wrapper;
if (_DirectionWrapper && _DirectionWrapper->supportGlobalVectorValue())
_ui.globalPushButton->show();
else
_ui.globalPushButton->hide();
}
void CDirectionWidget::updateUi()
{
_ui.xzWidget->setVector(_Wrapper->get().x, _Wrapper->get().z);
_ui.yzWidget->setVector(_Wrapper->get().y, _Wrapper->get().z);
_ui.xzWidget->repaint();
_ui.yzWidget->repaint();
checkEnabledGlobalDirection();
}
void CDirectionWidget::setGlobalDirection()
{
nlassert(_DirectionWrapper);
bool ok;
QString text = QInputDialog::getText(this, tr("Enter Name"),
"", QLineEdit::Normal,
QString(_DirectionWrapper->getGlobalVectorValueName().c_str()), &ok);
if (ok)
{
_DirectionWrapper->enableGlobalVectorValue(text.toStdString());
if (!text.isEmpty())
{
// take a non NULL value for the direction
NL3D::CParticleSystem::setGlobalVectorValue(text.toStdString(), NLMISC::CVector::I);
}
checkEnabledGlobalDirection();
}
}
void CDirectionWidget::incVecI()
{
_Wrapper->setAndUpdateModifiedFlag(NLMISC::CVector::I);
_ui.xzWidget->setVector(NLMISC::CVector::I.x, NLMISC::CVector::I.z);
_ui.yzWidget->setVector(NLMISC::CVector::I.y, NLMISC::CVector::I.z);
}
void CDirectionWidget::incVecJ()
{
_Wrapper->setAndUpdateModifiedFlag(NLMISC::CVector::J);
_ui.xzWidget->setVector(NLMISC::CVector::J.x, NLMISC::CVector::J.z);
_ui.yzWidget->setVector(NLMISC::CVector::J.y, NLMISC::CVector::J.z);
}
void CDirectionWidget::incVecK()
{
_Wrapper->setAndUpdateModifiedFlag(NLMISC::CVector::K);
_ui.xzWidget->setVector(NLMISC::CVector::K.x, NLMISC::CVector::K.z);
_ui.yzWidget->setVector(NLMISC::CVector::K.y, NLMISC::CVector::K.z);
}
void CDirectionWidget::decVecI()
{
_Wrapper->setAndUpdateModifiedFlag( - NLMISC::CVector::I);
_ui.xzWidget->setVector((-NLMISC::CVector::I).x, (-NLMISC::CVector::I).z);
_ui.yzWidget->setVector((-NLMISC::CVector::I).y, (-NLMISC::CVector::I).z);
}
void CDirectionWidget::decVecJ()
{
_Wrapper->setAndUpdateModifiedFlag( - NLMISC::CVector::J);
_ui.xzWidget->setVector((-NLMISC::CVector::J).x, (-NLMISC::CVector::J).z);
_ui.yzWidget->setVector((-NLMISC::CVector::J).y, (-NLMISC::CVector::J).z);
}
void CDirectionWidget::decVecK()
{
_Wrapper->setAndUpdateModifiedFlag( - NLMISC::CVector::K);
_ui.xzWidget->setVector((-NLMISC::CVector::K).x, (-NLMISC::CVector::K).z);
_ui.yzWidget->setVector((-NLMISC::CVector::K).y, (-NLMISC::CVector::K).z);
}
void CDirectionWidget::setNewVecXZ(float x, float y)
{
const float epsilon = 10E-3f;
NLMISC::CVector v = _Wrapper->get();
v.x = x;
v.z = y;
float d = v.x * v.x + v.z * v.z;
float f;
if (fabs(d) > epsilon)
f = sqrt((1.f - v.y * v.y) / d);
else
f = 1;
v.x *= f;
v.z *= f;
v.normalize();
_Wrapper->setAndUpdateModifiedFlag(v);
_ui.xzWidget->setVector(_Wrapper->get().x, _Wrapper->get().z);
_ui.yzWidget->setVector(_Wrapper->get().y, _Wrapper->get().z);
}
void CDirectionWidget::setNewVecYZ(float x, float y)
{
const float epsilon = 10E-3f;
NLMISC::CVector v = _Wrapper->get();
v.y = x;
v.z = y;
float d = v.y * v.y + v.z * v.z;
float f;
if (fabs(d) > epsilon)
f = sqrt((1.f - v.x * v.x) / d);
else
f = 1;
v.y *= f;
v.z *= f;
v.normalize();
_Wrapper->setAndUpdateModifiedFlag(v);
_ui.xzWidget->setVector(_Wrapper->get().x, _Wrapper->get().z);
_ui.yzWidget->setVector(_Wrapper->get().y, _Wrapper->get().z);
}
void CDirectionWidget::checkEnabledGlobalDirection()
{
bool enableUserDirection = true;
_ui.xzWidget->show();
_ui.yzWidget->show();
if (_DirectionWrapper && _DirectionWrapper->supportGlobalVectorValue() && !_DirectionWrapper->getGlobalVectorValueName().empty())
{
enableUserDirection = false;
_ui.xzWidget->hide();
_ui.yzWidget->hide();
}
_ui.incVecIPushButton->setEnabled(enableUserDirection);
_ui.incVecJPushButton->setEnabled(enableUserDirection);
_ui.incVecKPushButton->setEnabled(enableUserDirection);
_ui.decVecIPushButton->setEnabled(enableUserDirection);
_ui.decVecJPushButton->setEnabled(enableUserDirection);
_ui.decVecKPushButton->setEnabled(enableUserDirection);
}
} /* namespace NLQT */

View file

@ -0,0 +1,78 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DIRECTION_WIDGET_H
#define DIRECTION_WIDGET_H
#include "ui_direction_form.h"
// STL includes
// NeL includes
#include <nel/3d/ps_direction.h>
// Project includes
#include "ps_wrapper.h"
namespace NLQT {
/**
@class CDirectionWidget
@brief This widget helps to choose from several preset directions, or to choose a custom one.
@details This also allow to bind the direction to a global variable when it is supported
*/
class CDirectionWidget: public QWidget
{
Q_OBJECT
public:
CDirectionWidget(QWidget *parent = 0);
~CDirectionWidget();
void setWrapper(IPSWrapper<NLMISC::CVector> *wrapper);
/// The CPSDirection object is used to see if a global variable can be bound to the direction.
/// When set to NULL it has no effect (the default)
void setDirectionWrapper(NL3D::CPSDirection *wrapper);
void updateUi();
private Q_SLOTS:
void setGlobalDirection();
void incVecI();
void incVecJ();
void incVecK();
void decVecI();
void decVecJ();
void decVecK();
void setNewVecXZ(float x, float y);
void setNewVecYZ(float x, float y);
private:
void checkEnabledGlobalDirection();
IPSWrapper<NLMISC::CVector> *_Wrapper ;
NL3D::CPSDirection *_DirectionWrapper;
Ui::CDirectionWidget _ui;
}; /* class CDirectionWidget */
} /* namespace NLQT */
#endif // DIRECTION_WIDGET_H

View file

@ -0,0 +1,161 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include "nel/3d/ps_located.h"
#include "nel/3d/particle_system.h"
#include "nel/misc/stream.h"
#include "nel/misc/mem_stream.h"
#include "dup_ps.h"
#include <memory>
using namespace NL3D;
//=======================================================================
/** This can duplicate any serializable type by using a serialization policy (polymorphic, non polymorphic ..)
* The serialization policy must have a method to serial a pointer on the object (see example below)
* NB : of course this is slow (but convenient) way of performing a copy
* TODO maybe this could be used elsewhere ?
*/
template <class TSerializePolicy, typename T>
static T *DupSerializable(const T *in) throw(NLMISC::EStream)
{
NLMISC::CMemStream ms;
nlassert(!ms.isReading());
T *nonConstIn = const_cast<T *>(in);
TSerializePolicy::serial(nonConstIn, ms);
std::vector<uint8> datas(ms.length());
std::copy(ms.buffer(), ms.buffer() + ms.length(), datas.begin());
ms.resetPtrTable();
ms.invert();
ms.fill(&datas[0], (uint)datas.size());
nlassert(ms.isReading());
T *newObj = NULL;
TSerializePolicy::serial(newObj, ms);
return newObj;
}
/** A policy to duplicate a non-polymorphic type
*/
struct CDupObjPolicy
{
template <typename T>
static void serial(T *&obj, NLMISC::IStream &dest) throw(NLMISC::EStream)
{
dest.serialPtr(obj);
/*if (dest.isReading())
{
std::auto_ptr<T> newObj(new T);
newObj->serialPtr(dest);
delete obj;
obj = newObj.release();
}
else
{
obj->serial(dest);
}*/
}
};
/** A policy to duplicate a polymorphic type
*/
struct CDupPolymorphicObjPolicy
{
template <typename T>
static void serial(T *&obj, NLMISC::IStream &dest) throw(NLMISC::EStream)
{
dest.serialPolyPtr(obj);
}
};
//=======================================================================
/////////////////////////////////////////
// temp until there is a clone method //
/////////////////////////////////////////
NL3D::CParticleSystemProcess *DupPSLocated(const CParticleSystemProcess *in)
{
if (!in) return NULL;
try
{
// if the located doesn't belon to a system, copy it direclty
if (in->getOwner() == NULL)
{
return DupSerializable<CDupPolymorphicObjPolicy>(in);
}
else
{
uint index = in->getOwner()->getIndexOf(*in);
/** Duplicate the system, and detach.
* We can't duplicate the object direclty (it may be referencing other objects in the system, so these objects will be copied too...)
*/
std::auto_ptr<CParticleSystem> newPS(DupSerializable<CDupObjPolicy>(in->getOwner()));
// scene pointer is not serialised, but 'detach' may need the scene to be specified
newPS->setScene(in->getOwner()->getScene());
return newPS->detach(index);
}
}
catch (NLMISC::EStream &e)
{
nlwarning (e.what());
return NULL;
}
}
//=======================================================================
/////////////////////////////////////////
// temp until there is a clone method //
/////////////////////////////////////////
NL3D::CPSLocatedBindable *DupPSLocatedBindable(CPSLocatedBindable *in)
{
if (!in) return NULL;
try
{
// if no owner, can copy the object directy
if (in->getOwner() == NULL)
{
return DupSerializable<CDupPolymorphicObjPolicy>(in);
}
else
{
CParticleSystem *srcPS = in->getOwner()->getOwner();
std::auto_ptr<CParticleSystem> newPS(DupSerializable<CDupObjPolicy>(srcPS));
// scene pointer is not serialised, but 'detach' may need the scene to be specified
newPS->setScene(in->getOwner()->getOwner()->getScene());
//
uint index = srcPS->getIndexOf(*(in->getOwner()));
uint subIndex = in->getOwner()->getIndexOf(in);
//
newPS->setScene(in->getOwner()->getScene()); // 'unbind' require the scene to be attached
CPSLocated *loc = NLMISC::safe_cast<CPSLocated *>(newPS->getProcess(index));
return loc->unbind(subIndex);
}
}
catch (NLMISC::EStream &e)
{
nlwarning (e.what());
return NULL;
}
}

View file

@ -0,0 +1,52 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_DUP_PS_H
#define NL_DUP_PS_H
namespace NL3D
{
class CParticleSystemProcess;
class CPSLocatedBindable;
}
/** For now there is no duplication method in particle system.
* These are needed for edition, though..
* These functions provide a way to do this (by serializing the system in a memory stream).
* NB this is slow
* These may be removed, but this provide a easy way to accomplish our goal
*/
/** temp : duplicate a process of a particle system.
* return NULL if the copy failed
*/
NL3D::CParticleSystemProcess *DupPSLocated(const NL3D::CParticleSystemProcess *in);
/** temp : duplicate a located bindable of a particle system
* return NULL if the copy failed
*/
NL3D::CPSLocatedBindable *DupPSLocatedBindable(NL3D::CPSLocatedBindable *in);
#endif

View file

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CEditRangeFloatWidget</class>
<widget class="QWidget" name="CEditRangeFloatWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>304</width>
<height>32</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QDoubleSpinBox" name="startSpinBox">
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>-9999.000000000000000</double>
</property>
<property name="maximum">
<double>9999.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="horizontalSlider">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>1000000</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="endSpinBox">
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>-9999.000000000000000</double>
</property>
<property name="maximum">
<double>9999.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="currentSpinBox">
<property name="frame">
<bool>true</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>-9999.000000000000000</double>
</property>
<property name="maximum">
<double>9999.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="object_viewer_qt.qrc"/>
</resources>
<connections/>
</ui>

View file

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CEditRangeUIntWidget</class>
<widget class="QWidget" name="CEditRangeUIntWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>294</width>
<height>32</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSpinBox" name="startSpinBox">
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="maximum">
<number>99998</number>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="horizontalSlider">
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="endSpinBox">
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="maximum">
<number>99999</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="currentSpinBox">
<property name="readOnly">
<bool>false</bool>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="maximum">
<number>99999</number>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="object_viewer_qt.qrc"/>
</resources>
<connections>
<connection>
<sender>horizontalSlider</sender>
<signal>valueChanged(int)</signal>
<receiver>currentSpinBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>104</x>
<y>30</y>
</hint>
<hint type="destinationlabel">
<x>213</x>
<y>34</y>
</hint>
</hints>
</connection>
<connection>
<sender>currentSpinBox</sender>
<signal>valueChanged(int)</signal>
<receiver>horizontalSlider</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>206</x>
<y>29</y>
</hint>
<hint type="destinationlabel">
<x>91</x>
<y>27</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -0,0 +1,361 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "edit_range_widget.h"
// NeL includes
// Project includes
#include "ps_wrapper.h"
using namespace NL3D;
using namespace NLMISC;
namespace NLQT {
const int max_range = 9999;
CEditRangeUIntWidget::CEditRangeUIntWidget(QWidget *parent)
: QWidget(parent), _Wrapper(NULL), _emit(true)
{
_ui.setupUi(this);
_ui.endSpinBox->setMinimum(0);
_ui.startSpinBox->setMinimum(0);
_ui.currentSpinBox->setMinimum(0);
connect(_ui.startSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setMinimum(int)));
connect(_ui.endSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setMaximum(int)));
connect(_ui.horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(changeSlider(int)));
setValue(0, false);
}
CEditRangeUIntWidget::~CEditRangeUIntWidget()
{
}
void CEditRangeUIntWidget::setWrapper(IPSWrapperUInt *wrapper)
{
_Wrapper = wrapper;
}
void CEditRangeUIntWidget::setRange(uint32 minValue, uint32 maxValue)
{
setRangeMin(minValue);
setRangeMax(maxValue);
}
void CEditRangeUIntWidget::setRangeMin(uint32 minValue)
{
_ui.startSpinBox->setValue(minValue);
}
void CEditRangeUIntWidget::setRangeMax(uint32 maxValue)
{
_ui.endSpinBox->setValue(maxValue);
}
void CEditRangeUIntWidget::setValue(uint32 value, bool emit)
{
if (value > uint32(_ui.endSpinBox->value()))
_ui.endSpinBox->setValue(value);
if (value < uint32(_ui.startSpinBox->value()))
_ui.startSpinBox->setValue(value);
_emit = emit;
_ui.horizontalSlider->setValue(value);
_emit = true;
}
void CEditRangeUIntWidget::enableUpperBound(uint32 upperBound, bool upperBoundExcluded)
{
if (upperBoundExcluded)
upperBound--;
_ui.endSpinBox->setMaximum(upperBound);
_ui.startSpinBox->setMaximum(upperBound);
}
void CEditRangeUIntWidget::enableLowerBound(uint32 lowerBound, bool lowerBoundExcluded)
{
if (lowerBoundExcluded)
lowerBound++;
_ui.endSpinBox->setMinimum(lowerBound);
_ui.startSpinBox->setMinimum(lowerBound);
}
void CEditRangeUIntWidget::disableUpperBound(void)
{
_ui.endSpinBox->setMaximum(max_range);
_ui.startSpinBox->setMaximum(max_range);
}
void CEditRangeUIntWidget::disableLowerBound(void)
{
_ui.endSpinBox->setMinimum(0);
_ui.startSpinBox->setMinimum(0);
}
void CEditRangeUIntWidget::setMaximum(int value)
{
_ui.horizontalSlider->setMaximum(value);
_ui.currentSpinBox->setMaximum(value);
}
void CEditRangeUIntWidget::setMinimum(int value)
{
_ui.horizontalSlider->setMinimum(value);
_ui.currentSpinBox->setMinimum(value);
}
void CEditRangeUIntWidget::changeSlider(int value)
{
// NeL wrapper
if ((_Wrapper != NULL) && (_Wrapper->get() != uint32(value)))
_Wrapper->setAndUpdateModifiedFlag(value);
if (_emit)
Q_EMIT valueChanged(value);
}
void CEditRangeUIntWidget::updateUi()
{
if (_Wrapper == NULL) return;
_ui.horizontalSlider->setSliderPosition(_Wrapper->get());
}
CEditRangeIntWidget::CEditRangeIntWidget(QWidget *parent)
: QWidget(parent), _Wrapper(NULL)
{
_ui.setupUi(this);
connect(_ui.startSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setMinimum(int)));
connect(_ui.endSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setMaximum(int)));
connect(_ui.horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(changeSlider(int)));
setValue(0, false);
}
CEditRangeIntWidget::~CEditRangeIntWidget()
{
}
void CEditRangeIntWidget::setWrapper(IPSWrapperInt *wrapper)
{
_Wrapper = wrapper;
}
void CEditRangeIntWidget::setRange(sint32 minValue, sint32 maxValue)
{
setRangeMin(minValue);
setRangeMax(maxValue);
}
void CEditRangeIntWidget::setRangeMin(sint32 minValue)
{
_ui.startSpinBox->setValue(minValue);
}
void CEditRangeIntWidget::setRangeMax(sint32 maxValue)
{
_ui.endSpinBox->setValue(maxValue);
}
void CEditRangeIntWidget::setValue(sint32 value, bool emit)
{
if (value > sint32(_ui.endSpinBox->value()))
_ui.endSpinBox->setValue(value);
if (value < sint32(_ui.startSpinBox->value()))
_ui.startSpinBox->setValue(value);
_emit = emit;
_ui.horizontalSlider->setValue(value);
_emit = true;
}
void CEditRangeIntWidget::enableUpperBound(sint32 upperBound, bool upperBoundExcluded)
{
if (upperBoundExcluded)
upperBound--;
_ui.endSpinBox->setMaximum(upperBound);
_ui.startSpinBox->setMaximum(upperBound);
}
void CEditRangeIntWidget::enableLowerBound(sint32 lowerBound, bool lowerBoundExcluded)
{
if (lowerBoundExcluded)
lowerBound++;
_ui.endSpinBox->setMinimum(lowerBound);
_ui.startSpinBox->setMinimum(lowerBound);
}
void CEditRangeIntWidget::disableUpperBound(void)
{
_ui.endSpinBox->setMaximum(max_range);
_ui.startSpinBox->setMaximum(max_range);
}
void CEditRangeIntWidget::disableLowerBound(void)
{
_ui.endSpinBox->setMinimum(-max_range);
_ui.startSpinBox->setMinimum(-max_range);
}
void CEditRangeIntWidget::setMaximum(int value)
{
_ui.horizontalSlider->setMaximum(value);
_ui.currentSpinBox->setMaximum(value);
}
void CEditRangeIntWidget::setMinimum(int value)
{
_ui.horizontalSlider->setMinimum(value);
_ui.currentSpinBox->setMinimum(value);
}
void CEditRangeIntWidget::changeSlider(int value)
{
// NeL wrapper
if ((_Wrapper != NULL) && (_Wrapper->get() != sint32(value)))
_Wrapper->setAndUpdateModifiedFlag(value);
if (_emit)
Q_EMIT valueChanged(value);
}
void CEditRangeIntWidget::updateUi()
{
if (_Wrapper == NULL) return;
_ui.horizontalSlider->setSliderPosition(_Wrapper->get());
}
CEditRangeFloatWidget::CEditRangeFloatWidget(QWidget *parent )
: QWidget(parent), _Wrapper(NULL), _emit(true)
{
_ui.setupUi(this);
connect(_ui.startSpinBox, SIGNAL(valueChanged(double)), this, SLOT(changeRange()));
connect(_ui.endSpinBox, SIGNAL(valueChanged(double)), this, SLOT(changeRange()));
connect(_ui.horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(changeSlider(int)));
setValue(0.0, false);
}
CEditRangeFloatWidget::~CEditRangeFloatWidget()
{
}
void CEditRangeFloatWidget::setWrapper(IPSWrapperFloat *wrapper)
{
_Wrapper = wrapper;
}
void CEditRangeFloatWidget::setValue(float value, bool emit)
{
if (value > _ui.endSpinBox->value())
_ui.endSpinBox->setValue(value);
if (value < _ui.startSpinBox->value())
_ui.startSpinBox->setValue(value);
float delta = _ui.endSpinBox->value() - _ui.startSpinBox->value();
int deltaSlider = _ui.horizontalSlider->maximum() - _ui.horizontalSlider->minimum();
int newValue = floor((deltaSlider / delta) * (value - _ui.startSpinBox->value()));
_emit = emit;
_ui.horizontalSlider->setSliderPosition(newValue);
_emit = true;
}
void CEditRangeFloatWidget::setRange(float minValue, float maxValue)
{
setRangeMax(maxValue);
setRangeMin(minValue);
}
void CEditRangeFloatWidget::setRangeMin(float minValue)
{
_ui.startSpinBox->setValue(minValue);
}
void CEditRangeFloatWidget::setRangeMax(float maxValue)
{
_ui.endSpinBox->setValue(maxValue);
}
void CEditRangeFloatWidget::enableUpperBound(float upperBound, bool upperBoundExcluded)
{
if (upperBoundExcluded)
upperBound -= 0.001f;
_ui.endSpinBox->setMaximum(upperBound);
_ui.startSpinBox->setMaximum(upperBound);
}
void CEditRangeFloatWidget::enableLowerBound(float lowerBound, bool lowerBoundExcluded)
{
if (lowerBoundExcluded)
lowerBound += 0.01f;
_ui.endSpinBox->setMinimum(lowerBound);
_ui.startSpinBox->setMinimum(lowerBound);
}
void CEditRangeFloatWidget::disableUpperBound(void)
{
_ui.endSpinBox->setMaximum(max_range);
_ui.startSpinBox->setMaximum(max_range);
}
void CEditRangeFloatWidget::disableLowerBound(void)
{
_ui.endSpinBox->setMinimum(-max_range);
_ui.startSpinBox->setMinimum(-max_range);
}
void CEditRangeFloatWidget::changeRange()
{
if ((_ui.startSpinBox->value() < _ui.currentSpinBox->value()) &&
(_ui.endSpinBox->value() > _ui.currentSpinBox->value()))
setValue(_ui.currentSpinBox->value(), false);
}
void CEditRangeFloatWidget::changeSlider(int value)
{
float delta = _ui.endSpinBox->value() - _ui.startSpinBox->value();
int deltaSlider = _ui.horizontalSlider->maximum() - _ui.horizontalSlider->minimum();
float newValue = _ui.startSpinBox->value() + ((delta / deltaSlider) * value);
_ui.currentSpinBox->setValue(newValue);
// NeL wrapper
if ((_Wrapper != NULL) && (fabs(newValue - _Wrapper->get()) > 0.0001))
_Wrapper->setAndUpdateModifiedFlag(newValue);
if (_emit)
Q_EMIT valueChanged(newValue);
}
void CEditRangeFloatWidget::updateUi()
{
if (_Wrapper == NULL) return;
_ui.currentSpinBox->setValue(_Wrapper->get());
float delta = _ui.endSpinBox->value() - _ui.startSpinBox->value();
int deltaSlider = _ui.horizontalSlider->maximum() - _ui.horizontalSlider->minimum();
int newValue = floor((deltaSlider / delta) * (_Wrapper->get() - _ui.startSpinBox->value()));
_ui.horizontalSlider->setSliderPosition(newValue);
}
} /* namespace NLQT */

View file

@ -0,0 +1,290 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EDIT_RANGE_WIDGET_H
#define EDIT_RANGE_WIDGET_H
#include "ui_edit_range_float_form.h"
#include "ui_edit_range_uint_form.h"
// Qt includes
// Project includes
#include "ps_wrapper.h"
namespace NLQT {
/**
@class CEditRangeUIntWidget
@brief The widget provides a horizontal slider and 3 QSpinBox(to set start/end value range and сurrent value from this range.).
@details Slider sets the uint32 value within a specified range (start/end QSpinBox).
The values range can be set through the class methods: setRange() or setRangeMin(), setRangeMax().
Or the user input values in the widgets start/end QSpinBox.
Also the range of start/end values can be restricted through the class methods: enableLowerBound(), enableUpperBound()
this widget can be used by a two ways: Qt Q_SIGNAL/SLOT or wrapper.
1. Using the Qt Q_SIGNAL/SLOT current value can be set by class methods setValue() and
changes in current value(QSlider or QSpinBox) the signal valueChanged() will be emitted.
2. Using wrapper, create wpapper struct, example:
@code
struct CMaxNbParticlesWrapper : public IPSWrapperUInt
{
NL3D::CPSLocated *Located;
uint32 get(void) const { return Located->getMaxSize(); }
void set(const uint32 &v) { Located->setMaxSize(v); }
} _MaxNbParticlesWrapper;
@endcode
to set the current values,it is need to call class methods updateUi();
*/
class CEditRangeUIntWidget: public QWidget
{
Q_OBJECT
public:
/// Constructor, sets 0 default current value
CEditRangeUIntWidget(QWidget *parent = 0);
~CEditRangeUIntWidget();
/// Set an interface of a wrapper to read / write values in the particle system
/// NB : The 'OwnerNode' field of the wrapper
void setWrapper(IPSWrapperUInt *wrapper);
/// Set current value
/// @param value - current value
/// @param emit - will emit valueChanged() if the new value is different from the old one and param emit = true
void setValue(uint32 value, bool emit = true);
/// Convenience function to set the minimum, and maximum values with a single function call
void setRange(uint32 minValue, uint32 maxValue);
/// Set the minimum value that can take range(slider)
void setRangeMin(uint32 minValue);
/// Set the maximum value that can take range(slider)
void setRangeMax(uint32 maxValue);
/// Enable upper bound use (e.g. value must be < or <= upper bound )
/// @param upperBound - maximum value of the range
/// @param upperBoundExcluded - if true then the test is <, otherwise its <=
void enableUpperBound(uint32 upperBound, bool upperBoundExcluded);
/// Enable lower bound use (e.g. value must be < or <= lower bound )
/// @param lowerBound - minimum value of the range
/// @param lowerBoundExcluded - if true then the test is <, otherwise its <=
void enableLowerBound(uint32 lowerBound, bool lowerBoundExcluded);
/// Disable upper bound usage
void disableUpperBound(void);
/// Disable lower bound usage
void disableLowerBound(void);
/// With changes wrapper to be called for the installation of new range values
void updateUi();
Q_SIGNALS:
void valueChanged(uint32 value);
private Q_SLOTS:
void setMaximum(int value);
void setMinimum(int value);
void changeSlider(int value);
private:
IPSWrapperUInt *_Wrapper;
bool _emit;
Ui::CEditRangeUIntWidget _ui;
}; /* class CEditRangeUIntWidget */
/**
@class CEditRangeIntWidget
@brief The widget provides a horizontal slider and 3 QSpinBox(to set start/end value range and сurrent value from this range.).
@details Slider sets the sint32 value within a specified range (start/end QSpinBox).
The values range can be set through the class methods: setRange() or setRangeMin(), setRangeMax().
Or the user input values in the widgets start/end QSpinBox.
Also the range of start/end values can be restricted through the class methods: enableLowerBound(), enableUpperBound()
this widget can be used by a two ways: Qt Q_SIGNAL/SLOT or wrapper.
1. Using the Qt Q_SIGNAL/SLOT current value can be set by class methods setValue() and
changes in current value(QSlider or QSpinBox) the signal valueChanged() will be emitted.
2. Using wrapper, create wpapper struct, example:
@code
struct CRadialViscosityWrapper : public IPSWrapperFloat
{
NL3D::CPSCylindricVortex *V;
sint32 get(void) const { return V->getRadialViscosity(); }
void set(const sint32 &value) { V->setRadialViscosity(value); }
} _RadialViscosityWrapper;
@endcode
to set the current values,it is need to call class methods updateUi();
*/
class CEditRangeIntWidget: public QWidget
{
Q_OBJECT
public:
/// Constructor, sets 0 default current value
CEditRangeIntWidget(QWidget *parent = 0);
~CEditRangeIntWidget();
/// set an interface of a wrapper to read / write values in the particle system
/// NB : The 'OwnerNode' field of the wrapper
void setWrapper(IPSWrapperInt *wrapper);
/// Set current value
/// @param value - current value
/// @param emit - will emit valueChanged() if the new value is different from the old one and param emit = true
void setValue(sint32 value, bool emit = true);
/// Convenience function to set the minimum, and maximum values with a single function call
void setRange(sint32 minValue, sint32 maxValue);
/// Set the minimum value that can take range(slider)
void setRangeMin(sint32 minValue);
/// Set the maximum value that can take range(slider)
void setRangeMax(sint32 maxValue);
/// Enable upper bound use (e.g. value must be < or <= upper bound )
/// @param upperBound - maximum value of the range
/// @param upperBoundExcluded - if true then the test is <, otherwise its <=
void enableUpperBound(sint32 upperBound, bool upperBoundExcluded);
/// Enable lower bound use (e.g. value must be < or <= lower bound )
/// @param lowerBound - minimum value of the range
/// @param lowerBoundExcluded - if true then the test is <, otherwise its <=
void enableLowerBound(sint32 lowerBound, bool lowerBoundExcluded);
/// Disable upper bound usage
void disableUpperBound(void);
/// Disable lower bound usage
void disableLowerBound(void);
/// With changes wrapper to be called for the installation of new range values
void updateUi();
Q_SIGNALS:
void valueChanged(sint32 value);
private Q_SLOTS:
void setMaximum(int value);
void setMinimum(int value);
void changeSlider(int value);
private:
IPSWrapperInt *_Wrapper;
bool _emit;
Ui::CEditRangeUIntWidget _ui;
}; /* class CEditRangeIntWidget */
/**
@class CEditRangeFloatWidget
@brief The widget provides a horizontal slider and 3 QDoubleSpinBox(to set start/end value range and сurrent value from this range.).
@details Slider sets the float value within a specified range (start/end QDoubleSpinBox).
The values range can be set through the class methods: setRange() or setRangeMin(), setRangeMax().
Or the user input values in the widgets start/end QDoubleSpinBox.
Also the range of start/end values can be restricted through the class methods: enableLowerBound(), enableUpperBound()
this widget can be used by a two ways: Qt Q_SIGNAL/SLOT or wrapper.
1. Using the Qt Q_SIGNAL/SLOT current value can be set by class methods setValue() and
changes in current value(only QSlider) the signal valueChanged()will be emitted.
2. Using wrapper, create wpapper struct, example:
@code
struct CTangentialViscosityWrapper : public IPSWrapperFloat
{
NL3D::CPSCylindricVortex *V;
float get(void) const { return V->getTangentialViscosity(); }
void set(const float &value) { V->setTangentialViscosity(value); }
} _TangentialViscosityWrapper;
@endcode
to set the current values,it is need to call class methods updateUi();
*/
class CEditRangeFloatWidget: public QWidget
{
Q_OBJECT
public:
/// Constructor, sets 0 default current value
CEditRangeFloatWidget(QWidget *parent = 0);
~CEditRangeFloatWidget();
/// Set an interface of a wrapper to read / write values in the particle system
/// NB : The 'OwnerNode' field of the wrapper
void setWrapper(IPSWrapperFloat *wrapper);
/// Set current value
/// @param value - current value
/// @param emit - will emit valueChanged() if the new value is different from the old one and param emit = true
void setValue(float value, bool emit = true);
/// Convenience function to set the minimum, and maximum values with a single function call
void setRange(float minValue, float maxValue);
/// Set the minimum value that can take range(slider)
void setRangeMin(float minValue);
/// Set the maximum value that can take range(slider)
void setRangeMax(float maxValue);
/// Enable upper bound use (e.g. value must be < or <= upper bound )
/// @param upperBound - maximum value of the range
/// @param upperBoundExcluded - if true then the test is <, otherwise its <=
void enableUpperBound(float upperBound, bool upperBoundExcluded);
/// Enable lower bound use (e.g. value must be < or <= lower bound )
/// @param lowerBound - minimum value of the range
/// @param lowerBoundExcluded - if true then the test is <, otherwise its <=
void enableLowerBound(float lowerBound, bool lowerBoundExcluded);
/// Disable upper bound usage
void disableUpperBound(void);
/// Disable lower bound usage
void disableLowerBound(void);
/// With changes wrapper to be called for the installation of new range values
void updateUi();
Q_SIGNALS:
void valueChanged(float value);
private Q_SLOTS:
void changeRange();
void changeSlider(int value);
private:
IPSWrapperFloat *_Wrapper;
bool _emit;
Ui::CEditRangeFloatWidget _ui;
}; /* class CEditRangeFloatWidget */
} /* namespace NLQT */
#endif // EDIT_RANGE_WIDGET_H

View file

@ -0,0 +1,293 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CEmitterPage</class>
<widget class="QWidget" name="CEmitterPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>382</width>
<height>450</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="tabPosition">
<enum>QTabWidget::East</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<property name="movable">
<bool>true</bool>
</property>
<widget class="QWidget" name="tabWidgetPage1">
<attribute name="title">
<string>General</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0" colspan="3">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Emitted type:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="emittedTypeComboBox"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Type of emission:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="typeEmissionComboBox">
<item>
<property name="text">
<string>Regular</string>
</property>
</item>
<item>
<property name="text">
<string>On death</string>
</property>
</item>
<item>
<property name="text">
<string>Once</string>
</property>
</item>
<item>
<property name="text">
<string>On bounce</string>
</property>
</item>
<item>
<property name="text">
<string>External only</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Direction:</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="directionComboBox">
<item>
<property name="text">
<string>Default</string>
</property>
</item>
<item>
<property name="text">
<string>Direction is aligned on the emitter direction</string>
</property>
</item>
<item>
<property name="text">
<string>Direction is in world</string>
</property>
</item>
<item>
<property name="text">
<string>Direction is local to the system</string>
</property>
</item>
<item>
<property name="text">
<string>User</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="forceConsistentCheckBox">
<property name="text">
<string>Force consistent emission</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="bypassAutoLODCheckBox">
<property name="text">
<string>Bypass Auto-LOD</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Speed inheritance factor:</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="NLQT::CEditRangeFloatWidget" name="speedInherFactorWidget" native="true"/>
</item>
<item row="6" column="0" colspan="2">
<widget class="QLabel" name="delayedEmissionLabel">
<property name="text">
<string>Delayed emission:</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="3">
<widget class="NLQT::CEditRangeFloatWidget" name="delayedEmissionWidget" native="true"/>
</item>
<item row="8" column="0" colspan="2">
<widget class="QLabel" name="maxEmissinCountLabel">
<property name="text">
<string>Max Emission Count:</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="3">
<widget class="NLQT::CEditRangeUIntWidget" name="maxEmissionCountWidget" native="true"/>
</item>
<item row="10" column="0" colspan="3">
<widget class="NLQT::CDirectionWidget" name="directionWidget" native="true"/>
</item>
<item row="11" column="0">
<widget class="QLabel" name="radiusLabel">
<property name="text">
<string>Radius:</string>
</property>
</widget>
</item>
<item row="12" column="0" rowspan="2" colspan="3">
<widget class="NLQT::CEditRangeFloatWidget" name="radiusWidget" native="true"/>
</item>
<item row="14" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>17</width>
<height>143</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabWidgetPage2">
<attribute name="title">
<string>Emission period</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>291</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="NLQT::CAttribFloatWidget" name="periodWidget">
<property name="title">
<string>Emmision period</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabWidgetPage3">
<attribute name="title">
<string>Emmision quantity/Speed</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="NLQT::CAttribUIntWidget" name="genNbWidget">
<property name="title">
<string>Emmision quantity</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="NLQT::CAttribFloatWidget" name="strenghtModulateWidget">
<property name="title">
<string>Strenght modulation</string>
</property>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>275</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>NLQT::CEditRangeUIntWidget</class>
<extends>QWidget</extends>
<header>edit_range_widget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>NLQT::CEditRangeFloatWidget</class>
<extends>QWidget</extends>
<header>edit_range_widget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>NLQT::CDirectionWidget</class>
<extends>QWidget</extends>
<header>direction_widget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>NLQT::CAttribFloatWidget</class>
<extends>QGroupBox</extends>
<header>attrib_widget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>NLQT::CAttribUIntWidget</class>
<extends>QGroupBox</extends>
<header>attrib_widget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,372 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "emitter_page.h"
// Qt includes
#include <QtGui/QMessageBox>
// NeL includes
// Project includes
#include "edit_range_widget.h"
#include "modules.h"
namespace NLQT {
CEmitterPage::CEmitterPage(QWidget *parent)
: QWidget(parent)
{
_ui.setupUi(this);
// setup the dialog for the period of emission edition
_ui.periodWidget->setRange(0.f, 2.f);
_ui.periodWidget->setWrapper(&_PeriodWrapper);
_ui.periodWidget->setSchemeWrapper(&_PeriodWrapper);
_ui.periodWidget->init();
// setup the dialog that helps tuning the number of particle being emitted at a time
_ui.genNbWidget->setRange(1, 11);
_ui.genNbWidget->setWrapper(&_GenNbWrapper);
_ui.genNbWidget->setSchemeWrapper(&_GenNbWrapper);
_ui.genNbWidget->init();
// deals with emitters that have a direction
_ui.strenghtModulateWidget->setRange(0, 10);
_ui.strenghtModulateWidget->setWrapper(&_ModulatedStrenghtWrapper);
_ui.strenghtModulateWidget->setSchemeWrapper(&_ModulatedStrenghtWrapper);
_ui.strenghtModulateWidget->init();
// SPEED_INHERITANCE_FACTOR
_ui.speedInherFactorWidget->setRange(-1.f, 1.f);
_ui.speedInherFactorWidget->setWrapper(&_SpeedInheritanceFactorWrapper);
// DELAYED_EMISSION
_ui.delayedEmissionWidget->setRange(0.f, 10.f);
_ui.delayedEmissionWidget->enableLowerBound(0.f, false);
_ui.delayedEmissionWidget->setWrapper(&_DelayedEmissionWrapper);
// MAX_EMISSION_COUNT
_ui.maxEmissionCountWidget->setRange(0, 100);
_ui.maxEmissionCountWidget->enableUpperBound(256, false);
_ui.maxEmissionCountWidget->setWrapper(&_MaxEmissionCountWrapper);
_MaxEmissionCountWrapper.widget = _ui.maxEmissionCountWidget;
_MaxEmissionCountWrapper.parent = this;
// radius for conic emitter
_ui.radiusWidget->setRange(0.1f, 2.1f);
_ui.radiusWidget->setWrapper(&_ConicEmitterRadiusWrapper);
_ui.directionWidget->setWrapper(&_DirectionWrapper);
connect(_ui.emittedTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setEmittedType(int)));
connect(_ui.typeEmissionComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setTypeOfEmission(int)));
connect(_ui.directionComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setDirectionMode(int)));
connect(_ui.bypassAutoLODCheckBox, SIGNAL(toggled(bool)), this, SLOT(setBypassAutoLOD(bool)));
connect(_ui.forceConsistentCheckBox, SIGNAL(toggled(bool)), this, SLOT(setConsistentEmission(bool)));
}
CEmitterPage::~CEmitterPage()
{
}
void CEmitterPage::setEditedItem(CWorkspaceNode *ownerNode, NL3D::CPSLocatedBindable *locatedBindable)
{
_Emitter = static_cast<NL3D::CPSEmitter *>(locatedBindable);
_Node = ownerNode;
updateEmittedType();
_SpeedInheritanceFactorWrapper.OwnerNode = _Node;
_SpeedInheritanceFactorWrapper.E = _Emitter;
_ui.speedInherFactorWidget->updateUi();
_DelayedEmissionWrapper.Node = _Node;
_DelayedEmissionWrapper.OwnerNode = _Node;
_DelayedEmissionWrapper.E = _Emitter;
_ui.delayedEmissionWidget->updateUi();
_MaxEmissionCountWrapper.Node = _Node;
_MaxEmissionCountWrapper.OwnerNode = _Node;
_MaxEmissionCountWrapper.E = _Emitter;
_ui.maxEmissionCountWidget->updateUi();
_PeriodWrapper.Node = _Node;
_PeriodWrapper.E = _Emitter;
_ui.periodWidget->setWorkspaceNode(_Node);
_ui.periodWidget->updateUi();
_GenNbWrapper.Node = _Node;
_GenNbWrapper.E = _Emitter;
_ui.genNbWidget->setWorkspaceNode(_Node);
_ui.genNbWidget->updateUi();
if (dynamic_cast<NL3D::CPSModulatedEmitter *>(_Emitter))
{
_ModulatedStrenghtWrapper.E = dynamic_cast<NL3D::CPSModulatedEmitter *>(_Emitter);
_ui.strenghtModulateWidget->setWorkspaceNode(_Node);
_ui.strenghtModulateWidget->updateUi();
_ui.strenghtModulateWidget->show();
}
else
_ui.strenghtModulateWidget->hide();
// deals with emitters that have a direction
if (dynamic_cast<NL3D::CPSDirection *>(_Emitter))
{
_DirectionWrapper.E = dynamic_cast<NL3D::CPSDirection *>(_Emitter);
_ui.directionWidget->setDirectionWrapper(dynamic_cast<NL3D::CPSDirection *>(_Emitter));
_ui.directionWidget->updateUi();
_ui.directionWidget->show();
}
else
_ui.directionWidget->hide();
// radius for conic emitter
if (dynamic_cast<NL3D::CPSEmitterConic *>(_Emitter))
{
_ConicEmitterRadiusWrapper.E = dynamic_cast<NL3D::CPSEmitterConic *>(_Emitter);
_ui.radiusWidget->updateUi();
_ui.radiusWidget->show();
_ui.radiusLabel->show();
}
else
{
_ui.radiusWidget->hide();
_ui.radiusLabel->hide();
}
_ui.directionComboBox->blockSignals(true);
if (_Emitter->isSpeedBasisEmissionEnabled())
{
_ui.directionComboBox->setCurrentIndex(int(AlignOnEmitterDirection));
}
else if (!_Emitter->isUserMatrixModeForEmissionDirectionEnabled())
{
_ui.directionComboBox->setCurrentIndex(int(Default));
}
else if (_Emitter->getUserMatrixModeForEmissionDirection() == NL3D::PSFXWorldMatrix)
{
_ui.directionComboBox->setCurrentIndex(int(LocalToSystem));
}
else if (_Emitter->getUserMatrixModeForEmissionDirection() == NL3D::PSIdentityMatrix)
{
_ui.directionComboBox->setCurrentIndex(int(InWorld));
}
else if (_Emitter->getUserMatrixModeForEmissionDirection() == NL3D::PSUserMatrix)
{
_ui.directionComboBox->setCurrentIndex(int(LocalToFatherSkeleton));
}
else
{
nlassert(0);
}
_ui.directionComboBox->blockSignals(false);
updatePeriodWidget();
_ui.typeEmissionComboBox->setCurrentIndex(int(_Emitter->getEmissionType()));
// bypass auto LOD
nlassert(_Emitter->getOwner() && _Emitter->getOwner()->getOwner());
NL3D::CParticleSystem &ps = *_Emitter->getOwner()->getOwner();
if (ps.isAutoLODEnabled() && !ps.isSharingEnabled())
{
_ui.bypassAutoLODCheckBox->setEnabled(true);
_ui.bypassAutoLODCheckBox->setChecked(_Emitter->getBypassAutoLOD());
}
else
_ui.bypassAutoLODCheckBox->setEnabled(true);
}
void CEmitterPage::setEmittedType(int index)
{
if (!_Emitter->setEmittedType(_LocatedList[index]))
{
if (_Emitter->getOwner()->getOwner()->getBehaviourType() == NL3D::CParticleSystem::SpellFX || _Emitter->getOwner()->getOwner()->getBypassMaxNumIntegrationSteps())
{
QMessageBox::critical(this, tr("NeL Particle Editor"),
tr("Can't perform operation : the system is flagged with 'No max nb steps' or uses the preset 'Spell FX',"
"and thus, should have a finite duration. This operation create a loop in the system, and so is forbidden."),
QMessageBox::Ok);
}
else
{
QMessageBox::critical(this, tr("NeL Particle Editor"),
tr("Loops with emitters are forbidden."),
QMessageBox::Ok);
}
updateEmittedType();
}
Modules::psEdit().resetAutoCount(_Node);
updateModifiedFlag();
}
void CEmitterPage::setTypeOfEmission(int index)
{
if (_Emitter->getEmissionType() == index) return;
if (!_Emitter->setEmissionType((NL3D::CPSEmitter::TEmissionType) index))
{
QMessageBox::critical(this, tr("NeL Particle Editor"),
tr("Can't perform operation : the system is flagged with 'No max nb steps' or uses the preset 'Spell FX', "
"and thus, should have a finite duration. Please remove that flag first."),
QMessageBox::Ok);
_ui.typeEmissionComboBox->setCurrentIndex(int(_Emitter->getEmissionType()));
}
updatePeriodWidget();
Modules::psEdit().resetAutoCount(_Node);
updateModifiedFlag();
}
void CEmitterPage::setConsistentEmission(bool state)
{
if (_Emitter-> isConsistentEmissionEnabled() == state) return;
_Emitter->enableConsistenEmission(state);
updateModifiedFlag();
}
void CEmitterPage::setBypassAutoLOD(bool state)
{
if (_Emitter->getBypassAutoLOD() == state) return;
_Emitter->setBypassAutoLOD(state);
updateModifiedFlag();
}
void CEmitterPage::setDirectionMode(int index)
{
nlassert(_Emitter);
switch(index)
{
case Default:
_Emitter->enableSpeedBasisEmission(false);
_Emitter->enableUserMatrixModeForEmissionDirection(false);
break;
case AlignOnEmitterDirection:
_Emitter->enableSpeedBasisEmission(true);
_Emitter->enableUserMatrixModeForEmissionDirection(false);
break;
case InWorld:
_Emitter->enableSpeedBasisEmission(false);
_Emitter->enableUserMatrixModeForEmissionDirection(true);
_Emitter->setUserMatrixModeForEmissionDirection(NL3D::PSIdentityMatrix);
break;
case LocalToSystem:
_Emitter->enableSpeedBasisEmission(false);
_Emitter->enableUserMatrixModeForEmissionDirection(true);
_Emitter->setUserMatrixModeForEmissionDirection(NL3D::PSFXWorldMatrix);
break;
case LocalToFatherSkeleton:
_Emitter->enableSpeedBasisEmission(false);
_Emitter->enableUserMatrixModeForEmissionDirection(true);
_Emitter->setUserMatrixModeForEmissionDirection(NL3D::PSUserMatrix);
break;
}
updateModifiedFlag();
}
void CEmitterPage::updatePeriodWidget()
{
bool bEnable = _Emitter->getEmissionType() == NL3D::CPSEmitter::regular;
_ui.periodWidget->setEnabled(bEnable);
_ui.delayedEmissionWidget->setEnabled(bEnable);
_ui.delayedEmissionLabel->setEnabled(bEnable);
_ui.maxEmissionCountWidget->setEnabled(bEnable);
_ui.maxEmissinCountLabel->setEnabled(bEnable);
}
void CEmitterPage::updateEmittedType()
{
disconnect(_ui.emittedTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setEmittedType(int)));
_ui.emittedTypeComboBox->clear();
_ui.emittedTypeComboBox->addItem(tr("no emission"));
_LocatedList.clear();
_LocatedList.push_back(NULL);
NL3D::CParticleSystem *ps = _Emitter->getOwner()->getOwner();
uint nbLocated = ps->getNbProcess();
for (uint k = 0; k < nbLocated; ++k)
{
NL3D::CPSLocated *loc = dynamic_cast<NL3D::CPSLocated *>(ps->getProcess(k));
if (loc) // is this a located
{
_ui.emittedTypeComboBox->addItem(QString(loc->getName().c_str()));
_LocatedList.push_back(loc);
if (loc == _Emitter->getEmittedType())
_ui.emittedTypeComboBox->setCurrentIndex(k + 1);
}
}
connect(_ui.emittedTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setEmittedType(int)));
}
void CEmitterPage::CPeriodWrapper::set(const float &v)
{
E->setPeriod(v);
Modules::psEdit().resetAutoCount(Node);
}
void CEmitterPage::CPeriodWrapper::setScheme(scheme_type *s)
{
E->setPeriodScheme(s);
Modules::psEdit().resetAutoCount(Node);
}
void CEmitterPage::CGenNbWrapper::set(const uint32 &v)
{
E->setGenNb(v);
Modules::psEdit().resetAutoCount(Node);
}
void CEmitterPage::CGenNbWrapper::setScheme(scheme_type *s)
{
E->setGenNbScheme(s);
Modules::psEdit().resetAutoCount(Node);
}
void CEmitterPage::CDelayedEmissionWrapper::set(const float &f)
{
E->setEmitDelay(f);
Modules::psEdit().resetAutoCount(Node);
}
void CEmitterPage::CMaxEmissionCountWrapper::set(const uint32 &count)
{
if (!E->setMaxEmissionCount((uint8) count))
{
QMessageBox::critical(parent, tr("NeL Particle Editor"),
tr("Can't perform operation : the system is flagged with 'No max nb steps' or uses the preset 'Spell FX', "
"and thus, should have a finite duration. Please remove that flag first."),
QMessageBox::Ok);
widget->updateUi();
}
Modules::psEdit().resetAutoCount(Node);
}
} /* namespace NLQT */

View file

@ -0,0 +1,168 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EMITTER_PAGE_H
#define EMITTER_PAGE_H
#include <nel/misc/types_nl.h>
#include "ui_emitter_form.h"
// STL includes
// NeL includes
#include "nel/3d/ps_particle.h"
#include "nel/3d/ps_emitter.h"
// Project includes
#include "particle_node.h"
#include "ps_wrapper.h"
namespace NLQT {
/**
@class CEmitterPage
@brief Page for QStackWidget, to edit emitters in a particle system
*/
class CEmitterPage: public QWidget
{
Q_OBJECT
public:
/// This enum match the option in the combo box that allow to choose how the direction of emission is computed.
enum TDirectionMode
{
Default = 0,
AlignOnEmitterDirection,
InWorld,
LocalToSystem,
LocalToFatherSkeleton
};
CEmitterPage(QWidget *parent = 0);
~CEmitterPage();
/// Set the emitter to edit.
void setEditedItem(CWorkspaceNode *ownerNode, NL3D::CPSLocatedBindable *locatedBindable);
private Q_SLOTS:
void setEmittedType(int index);
void setTypeOfEmission(int index);
void setConsistentEmission(bool state);
void setBypassAutoLOD(bool state);
void setDirectionMode(int index);
private:
/// period of emission
struct CPeriodWrapper : public IPSWrapperFloat, IPSSchemeWrapperFloat
{
CWorkspaceNode *Node;
NL3D::CPSEmitter *E;
float get(void) const { return E->getPeriod(); }
void set(const float &v);
scheme_type *getScheme(void) const { return E->getPeriodScheme(); }
void setScheme(scheme_type *s);
} _PeriodWrapper;
/// number of particle to generate each time
struct CGenNbWrapper : public IPSWrapperUInt, IPSSchemeWrapperUInt
{
CWorkspaceNode *Node;
NL3D::CPSEmitter *E;
uint32 get(void) const { return E->getGenNb(); }
void set(const uint32 &v);
scheme_type *getScheme(void) const { return E->getGenNbScheme(); }
void setScheme(scheme_type *s);
} _GenNbWrapper;
/// wrappers to emitters that have strenght modulation
struct CModulateStrenghtWrapper : public IPSWrapperFloat, IPSSchemeWrapperFloat
{
NL3D::CPSModulatedEmitter *E;
float get(void) const { return E->getEmitteeSpeed(); }
void set(const float &v) { E->setEmitteeSpeed(v); }
scheme_type *getScheme(void) const { return E->getEmitteeSpeedScheme(); }
void setScheme(scheme_type *s) { E->setEmitteeSpeedScheme(s); }
} _ModulatedStrenghtWrapper;
/// wrappers to set the speed inheritance factor
struct CSpeedInheritanceFactorWrapper : public IPSWrapperFloat
{
NL3D::CPSEmitter *E;
float get(void) const { return E->getSpeedInheritanceFactor(); }
void set(const float &f) { E->setSpeedInheritanceFactor(f); }
} _SpeedInheritanceFactorWrapper;
/// wrappers to tune the direction of emitters
struct CDirectionWrapper : public IPSWrapper<NLMISC::CVector>
{
NL3D::CPSDirection *E;
NLMISC::CVector get(void) const { return E->getDir(); }
void set(const NLMISC::CVector &d){ E->setDir(d); }
} _DirectionWrapper;
/// wrapper to tune the radius of an emitter
struct CConicEmitterRadiusWrapper : public IPSWrapperFloat
{
NL3D::CPSEmitterConic *E;
float get(void) const { return E->getRadius(); }
void set(const float &f) { E->setRadius(f); }
} _ConicEmitterRadiusWrapper;
/// wrapper to tune delayed emission
struct CDelayedEmissionWrapper : public IPSWrapperFloat
{
CWorkspaceNode *Node;
NL3D::CPSEmitter *E;
float get(void) const { return E->getEmitDelay(); }
void set(const float &f);
} _DelayedEmissionWrapper;
/// wrapper to tune max number of emissions
struct CMaxEmissionCountWrapper : public IPSWrapperUInt
{
CWorkspaceNode *Node;
CEditRangeUIntWidget *widget;
QWidget *parent;
NL3D::CPSEmitter *E;
uint32 get(void) const { return E->getMaxEmissionCount(); }
void set(const uint32 &count);
} _MaxEmissionCountWrapper;
// the emitter being edited
NL3D::CPSEmitter *_Emitter;
// contains pointers to the located
std::vector<NL3D::CPSLocated *> _LocatedList;
void updateEmittedType();
void updatePeriodWidget();
void updateModifiedFlag() { if (_Node) _Node->setModified(true); }
CWorkspaceNode *_Node;
Ui::CEmitterPage _ui;
}; /* class CEmitterPage */
} /* namespace NLQT */
#endif // EMITTER_PAGE_H

View file

@ -0,0 +1,430 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "entity.h"
#include <QtCore/QString>
// NeL includes
#include <nel/misc/path.h>
#include <nel/3d/u_driver.h>
#include <nel/3d/u_instance.h>
#include <nel/3d/u_scene.h>
#include <nel/3d/u_skeleton.h>
#include <nel/3d/u_animation_set.h>
#include <nel/3d/u_animation.h>
#include <nel/3d/u_play_list_manager.h>
#include <nel/3d/u_play_list.h>
#include <nel/3d/u_track.h>
// Project includes
#include "modules.h"
using namespace NLMISC;
using namespace NL3D;
namespace NLQT {
CSlotInfo& CSlotInfo::operator=(const CSlotInfo & slotInfo)
{
if ( this != &slotInfo)
{
Animation = slotInfo.Animation;
ClampMode = slotInfo.ClampMode;
Enable = slotInfo.Enable;
EndBlend = slotInfo.EndBlend;
EndTime = slotInfo.EndTime;
Offset = slotInfo.Offset;
Skeleton = slotInfo.Skeleton;
SkeletonInverted = slotInfo.SkeletonInverted;
Smoothness = slotInfo.Smoothness;
SpeedFactor = slotInfo.SpeedFactor;
StartBlend = slotInfo.StartBlend;
StartTime = slotInfo.StartTime;
}
return *this;
}
CEntity::CEntity(void):
_Name("<Unknown>"), _FileNameShape(""),
_FileNameSkeleton(""), _inPlace(false), _incPos(false),
_Instance(NULL), _Skeleton(NULL),
_PlayList(NULL), _AnimationSet(NULL)
{
_CharacterScalePos = 1;
}
CEntity::~CEntity(void)
{
if (_PlayList != NULL)
{
_PlayList->resetAllChannels();
Modules::objView().getPlayListManager()->deletePlayList (_PlayList);
_PlayList = NULL;
}
if (_AnimationSet != NULL)
{
Modules::objView().getDriver()->deleteAnimationSet(_AnimationSet);
_AnimationSet = NULL;
}
if (!_Skeleton.empty())
{
_Skeleton.detachSkeletonSon(_Instance);
Modules::objView().getScene()->deleteSkeleton(_Skeleton);
_Skeleton = NULL;
}
if (!_Instance.empty())
{
Modules::objView().getScene()->deleteInstance(_Instance);
_Instance = NULL;
}
}
void CEntity::loadAnimation(std::string &fileName)
{
uint id = _AnimationSet->addAnimation(fileName.c_str(),CFile::getFilenameWithoutExtension(fileName).c_str());
_AnimationList.push_back(_AnimationSet->getAnimationName(id));
_AnimationSet->build();
if (!_Skeleton.empty()) _PlayList->registerTransform(_Skeleton);
else _PlayList->registerTransform(_Instance);
}
void CEntity::loadSWT(std::string &fileName)
{
uint id = _AnimationSet->addSkeletonWeight(fileName.c_str(),CFile::getFilenameWithoutExtension(fileName).c_str());
_SWTList.push_back(_AnimationSet->getSkeletonWeightName(id));
}
void CEntity::addAnimToPlayList(std::string &name)
{
_PlayListAnimation.push_back(name);
_AnimationStatus.EndAnim = this->getPlayListLength();
_Instance.start();
}
void CEntity::removeAnimToPlayList(uint row)
{
if (row < _PlayListAnimation.size())
_PlayListAnimation.erase(_PlayListAnimation.begin() + row);
_AnimationStatus.EndAnim = this->getPlayListLength();
}
void CEntity::swapAnimToPlayList(uint row1, uint row2)
{
if ((row1 < _PlayListAnimation.size()) && (row2 < _PlayListAnimation.size()))
std::swap(_PlayListAnimation[row1], _PlayListAnimation[row2]);
}
void CEntity::playbackAnim(bool play)
{
_AnimationStatus.PlayAnim = play;
if (play)
_Instance.start();
else
_Instance.freezeHRC();
}
void CEntity::reset()
{
_PlayListAnimation.clear();
_AnimationList.clear();
_SWTList.clear();
_PlayList->resetAllChannels();
}
float CEntity::getPlayListLength()
{
// Accumul all the time
float time = 0;
for(size_t i = 0; i < _PlayListAnimation.size(); ++i)
time += getAnimLength(_PlayListAnimation[i]);
return time;
}
float CEntity::getAnimLength(std::string name)
{
uint id = _AnimationSet->getAnimationIdByName(name.c_str());
NL3D::UAnimation *anim = _AnimationSet->getAnimation(id);
return anim->getEndTime() - anim->getBeginTime();
}
void CEntity::update(NL3D::TAnimationTime time)
{
this->resetChannel();
switch (_AnimationStatus.Mode)
{
case Mode::PlayList:
animatePlayList(time);
break;
case Mode::Mixer:
animateChannelMixer();
break;
}
}
void CEntity::resetChannel()
{
for(uint i = 0; i < NL3D::CChannelMixer::NumAnimationSlot; i++)
_PlayList->setAnimation(i, UPlayList::empty);
}
void CEntity::addTransformation (CMatrix &current, UAnimation *anim, float begin, float end, UTrack *posTrack, UTrack *rotquatTrack,
UTrack *nextPosTrack, UTrack *nextRotquatTrack, bool removeLast)
{
// In place ?
if (_inPlace)
{
// Just identity
current.identity();
}
else
{
// Remove the start of the animation
CQuat rotEnd (0,0,0,1);
CVector posEnd (0,0,0);
if (rotquatTrack)
{
// Interpolate the rotation
rotquatTrack->interpolate (end, rotEnd);
}
if (posTrack)
{
// Interpolate the position
posTrack->interpolate (end, posEnd);
}
// Add the final rotation and position
CMatrix tmp;
tmp.identity ();
tmp.setRot (rotEnd);
tmp.setPos (posEnd);
// Incremental ?
if (_incPos)
current *= tmp;
else
current = tmp;
if (removeLast)
{
CQuat rotStart (0,0,0,1);
CVector posStart (0,0,0);
if (nextRotquatTrack)
{
// Interpolate the rotation
nextRotquatTrack->interpolate (begin, rotStart);
}
if (nextPosTrack)
{
// Interpolate the position
nextPosTrack->interpolate (begin, posStart);
}
// Remove the init rotation and position of the next animation
tmp.identity ();
tmp.setRot (rotStart);
tmp.setPos (posStart);
tmp.invert ();
current *= tmp;
// Normalize the mt
CVector I = current.getI ();
CVector J = current.getJ ();
I.z = 0;
J.z = 0;
J.normalize ();
CVector K = I^J;
K.normalize ();
I = J^K;
I.normalize ();
tmp.setRot (I, J, K);
tmp.setPos (current.getPos ());
current = tmp;
}
}
}
void CEntity::animatePlayList(NL3D::TAnimationTime time)
{
if (!_PlayListAnimation.empty())
{
// Animation index
uint id = _AnimationSet->getAnimationIdByName(_PlayListAnimation[0].c_str());
// Try channel AnimationSet
NL3D::UAnimation *anim = _AnimationSet->getAnimation(id);
bool there = false;
UTrack *posTrack = NULL;
UTrack *rotQuatTrack = NULL;
// Current matrix
CMatrix current;
current.identity();
// read an animation for init matrix
rotQuatTrack = anim->getTrackByName("rotquat");
posTrack = anim->getTrackByName("pos");
there = posTrack || rotQuatTrack;
// Accumul time
float startTime = 0;
float endTime = anim->getEndTime() - anim->getBeginTime();
uint index = 0;
while (time >= endTime)
{
index++;
if (index < _PlayListAnimation.size())
{
id = _AnimationSet->getAnimationIdByName(_PlayListAnimation[index].c_str());
NL3D::UAnimation *newAnim = _AnimationSet->getAnimation(id);
UTrack *newPosTrack = newAnim->getTrackByName ("pos");
UTrack *newRotquatTrack = newAnim->getTrackByName ("rotquat");
// Add the transformation
addTransformation (current, anim, newAnim->getBeginTime(), anim->getEndTime(), posTrack, rotQuatTrack, newPosTrack, newRotquatTrack, true);
anim = newAnim;
posTrack = newPosTrack;
rotQuatTrack = newRotquatTrack;
// Add start time
startTime = endTime;
endTime = startTime + (anim->getEndTime() - anim->getBeginTime());
}
else
{
// Add the transformation
addTransformation (current, anim, 0, anim->getEndTime(), posTrack, rotQuatTrack, NULL, NULL, false);
break;
}
}
// Time cropped ?
if (index >= _PlayListAnimation.size())
{
// Yes
index--;
id = _AnimationSet->getAnimationIdByName(_PlayListAnimation[index].c_str());
anim = _AnimationSet->getAnimation(id);
// End time for last anim
startTime = anim->getEndTime() - time;
}
else
{
// No
// Add the transformation
addTransformation (current, anim, 0, anim->getBeginTime() + time - startTime, posTrack, rotQuatTrack, NULL, NULL, false);
id = _AnimationSet->getAnimationIdByName(_PlayListAnimation[index].c_str());
anim = _AnimationSet->getAnimation(id);
// Final time
startTime -= anim->getBeginTime();
}
// Set the slot
_PlayList->setAnimation(0, id);
_PlayList->setTimeOrigin(0, startTime);
_PlayList->setSpeedFactor(0, 1.0f);
_PlayList->setWeightSmoothness(0, 1.0f);
_PlayList->setStartWeight(0, 1, 0);
_PlayList->setEndWeight(0, 1, 1);
_PlayList->setWrapMode(0, UPlayList::Clamp);
// Setup the pos and rot for this shape
if (there)
{
CVector pos = current.getPos();
// If a skeleton model
if(!_Skeleton.empty())
{
// scale animated pos value with the CFG scale
pos *= _CharacterScalePos;
_Skeleton.setPos(pos);
_Skeleton.setRotQuat(current.getRot());
}
else
{
_Instance.setPos(pos);
_Instance.setRotQuat(current.getRot());
}
}
}
}
void CEntity::animateChannelMixer()
{
for (uint i = 0; i < NL3D::CChannelMixer::NumAnimationSlot; i++)
{
if (_SlotInfo[i].Enable)
{
// Set the animation
uint animId = _AnimationSet->getAnimationIdByName(_SlotInfo[i].Animation);
if (animId == UAnimationSet::NotFound)
_PlayList->setAnimation(i, UPlayList::empty);
else
_PlayList->setAnimation(i, animId);
// Set the skeleton weight
uint skelId = _AnimationSet->getSkeletonWeightIdByName(_SlotInfo[i].Skeleton);
if (skelId == UAnimationSet::NotFound)
_PlayList->setSkeletonWeight(i, UPlayList::empty, false);
else
_PlayList->setSkeletonWeight(i, skelId, _SlotInfo[i].SkeletonInverted);
// Set others values
_PlayList->setTimeOrigin(i, _SlotInfo[i].Offset);
_PlayList->setSpeedFactor(i, _SlotInfo[i].SpeedFactor);
_PlayList->setStartWeight(i, _SlotInfo[i].StartBlend, _SlotInfo[i].StartTime);
_PlayList->setEndWeight(i, _SlotInfo[i].EndBlend, _SlotInfo[i].EndTime);
_PlayList->setWeightSmoothness(i, _SlotInfo[i].Smoothness);
// Switch between wrap modes
switch (_SlotInfo[i].ClampMode)
{
case 0:
_PlayList->setWrapMode (i, UPlayList::Clamp);
break;
case 1:
_PlayList->setWrapMode (i, UPlayList::Repeat);
break;
case 2:
_PlayList->setWrapMode (i, UPlayList::Disable);
break;
}
}
}
}
} /* namespace NLQT */

View file

@ -0,0 +1,259 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENTITY_H
#define ENTITY_H
#include <nel/misc/types_nl.h>
// STL includes
#include <map>
#include <string>
#include <vector>
// NeL includes
#include <nel/misc/vector.h>
#include <nel/misc/vectord.h>
#include <nel/misc/quat.h>
#include <nel/3d/animation_time.h>
#include <nel/3d/u_instance.h>
#include <nel/3d/u_skeleton.h>
#include <nel/3d/channel_mixer.h>
namespace NL3D {
class UPlayList;
class UAnimationSet;
}
namespace NLQT {
class CSlotInfo
{
public:
CSlotInfo ():
Animation("empty"), Skeleton("empty"),
Offset(0), StartTime(0), EndTime(0),
StartBlend(1), EndBlend (1), Smoothness(1),
SpeedFactor(1), ClampMode(0),
SkeletonInverted(false),
Enable(true) {} ;
std::string Animation;
std::string Skeleton;
float Offset;
float StartTime;
float EndTime;
float StartBlend;
float EndBlend;
float Smoothness;
float SpeedFactor;
sint32 ClampMode;
bool SkeletonInverted;
bool Enable;
CSlotInfo &operator=(const CSlotInfo &);
};
/**
@class CEntity
@brief Class manage animated shape.
@details
Allows you to load animations for shape and skeleton weight.
Contains a built-in playlist. Has management and playback Playlists or Mixer.
*/
class CEntity
{
public:
struct Mode
{
enum List
{
PlayList = 1,
Mixer
};
};
/// Will need for a single or multiple animation shape
struct SAnimationStatus
{
bool LoopAnim;
bool PlayAnim;
float CurrentTimeAnim;
float StartAnim;
float EndAnim;
float SpeedAnim;
int Mode;
SAnimationStatus():
LoopAnim(false), PlayAnim(false),
CurrentTimeAnim(0), StartAnim(0),
EndAnim(0), SpeedAnim(1), Mode(Mode::PlayList) {}
};
/// Destructor
~CEntity(void);
/// Loads a file animations
/// @param fileName - name animation file
void loadAnimation(std::string &fileName);
/// Loads a file skeleton weight
void loadSWT(std::string &fileName);
/// Adds an animation to a playlist
/// @param name - name loaded animations
void addAnimToPlayList(std::string &name);
/// Removes the animation from a playlist
/// @param row - number of animations in the playlist
void removeAnimToPlayList(uint row);
/// Swaps animations to a playlist
/// @param row1 - first number of animations in the playlist
/// @param row2 - second number of animations in the playlist
void swapAnimToPlayList(uint row1, uint row2);
/// Playback animation
void playbackAnim(bool play);
/// Reset playlist and animation
void reset();
/// Get the total time of animation playlist
/// @return total time of animation
float getPlayListLength();
/// get time length single animation
float getAnimLength(std::string name);
/// Get slot infomation
void setSlotInfo(uint num, CSlotInfo& slotInfo) { _SlotInfo[num] = slotInfo; }
/// Set use mode playlist or mixer
void setMode(int mode) { _AnimationStatus.Mode = mode; }
/// Set in place mode animation
void setInPlace(bool enabled) { _inPlace = enabled; }
/// Get in place mode
bool getInPlace() { return _inPlace; }
/// Set inc position
void setIncPos(bool enabled) { _incPos = enabled; }
/// Get inc position
bool getIncPos() { return _incPos; }
/// Get information about the current status of playing a playlist
/// @return struct containing current information playback
SAnimationStatus getStatus() { return _AnimationStatus; }
/// Get name entity
/// @return name entity
std::string getName() { return _Name; }
/// Get file name shape
/// @return file name shape
std::string getFileNameShape() { return _FileNameShape; }
/// Get file name skeleton
/// @return file name skeleton
std::string getFileNameSkeleton() { return _FileNameSkeleton; }
/// Get slot information
CSlotInfo getSlotInfo(uint num) { return _SlotInfo[num]; }
/// Get list loaded animations files
std::vector<std::string>& getAnimationList() { return _AnimationList; }
/// Get playlist animations
std::vector<std::string>& getPlayListAnimation() { return _PlayListAnimation; }
/// Get list loaded skeleton weight template files
std::vector<std::string>& getSWTList() { return _SWTList; }
/// Get game interface for manipulating Skeleton.
NL3D::USkeleton getSkeleton() const { return _Skeleton; }
private:
/// Constructor
CEntity(void);
/// Update the animate from the playlist or channel mixer
/// @param time - current time in second
void update(NL3D::TAnimationTime time);
void resetChannel();
/// Update the animate from the playlist
void animatePlayList(NL3D::TAnimationTime time);
/// Update the animate from the mixer
void animateChannelMixer();
void addTransformation (NLMISC::CMatrix &current, NL3D::UAnimation *anim,
float begin, float end,
NL3D::UTrack *posTrack, NL3D::UTrack *rotquatTrack,
NL3D::UTrack *nextPosTrack, NL3D::UTrack *nextRotquatTrack,
bool removeLast);
// The name of the entity
std::string _Name;
std::string _FileNameShape;
std::string _FileNameSkeleton;
SAnimationStatus _AnimationStatus;
bool _inPlace;
bool _incPos;
float _CharacterScalePos;
// The mesh instance associated to this entity
NL3D::UInstance _Instance;
// The skeleton binded to the instance
NL3D::USkeleton _Skeleton;
NL3D::UPlayList *_PlayList;
NL3D::UAnimationSet *_AnimationSet;
// Animation input file
std::vector<std::string> _AnimationList;
// Skeleton weight input file
std::vector<std::string> _SWTList;
// Play list animation
std::vector<std::string > _PlayListAnimation;
// Slot info for this object
CSlotInfo _SlotInfo[NL3D::CChannelMixer::NumAnimationSlot];
friend class CObjectViewer;
}; /* class CEntity */
typedef std::map<std::string, CEntity> CEntities;
typedef CEntities::iterator EIT;
} /* namespace NLQT */
#endif // ENTITY_H

View file

@ -0,0 +1,81 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "follow_path_dialog.h"
// NeL include
#include <nel/3d/ps_plane_basis_maker.h>
// Project includes
#include "particle_node.h"
namespace NLQT {
CFollowPathDialog::CFollowPathDialog(NL3D::CPSPlaneBasisFollowSpeed *pbfs, CWorkspaceNode *ownerNode, QWidget *parent)
: QDialog(parent), _FollowPath(pbfs), _Node(ownerNode)
{
resize(270, 90);
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(this->sizePolicy().hasHeightForWidth());
setSizePolicy(sizePolicy);
setMinimumSize(QSize(0, 90));
setMaximumSize(QSize(16777215, 90));
gridLayout = new QGridLayout(this);
label = new QLabel(this);
gridLayout->addWidget(label, 0, 0, 1, 1);
comboBox = new QComboBox(this);
gridLayout->addWidget(comboBox, 1, 0, 1, 2);
horizontalSpacer = new QSpacerItem(207, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
gridLayout->addItem(horizontalSpacer, 2, 0, 1, 1);
pushButton = new QPushButton(this);
gridLayout->addWidget(pushButton, 2, 1, 1, 1);
setWindowTitle(tr("Follow path param"));
label->setText(tr("Projection plane:"));
comboBox->clear();
comboBox->insertItems(0, QStringList()
<< tr("No projection")
<< tr("XY plane")
<< tr("XZ plane")
<< tr("YZ plane"));
pushButton->setText(("Ok"));
comboBox->setCurrentIndex(_FollowPath->getProjectionPlane());
setFixedHeight(sizeHint().height());
connect(pushButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setProjectionMode(int)));
}
CFollowPathDialog::~CFollowPathDialog()
{
}
void CFollowPathDialog::setProjectionMode(int index)
{
nlassert(_FollowPath);
_FollowPath->setProjectionPlane((NL3D::CPSPlaneBasisFollowSpeed::TProjectionPlane) index);
if (_Node) _Node->setModified(true);
}
} /* namespace NLQT */

View file

@ -0,0 +1,63 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FOLLOW_PATH_DIALOG_H
#define FOLLOW_PATH_DIALOG_H
#include <QtGui/QComboBox>
#include <QtGui/QDialog>
#include <QtGui/QGridLayout>
#include <QtGui/QLabel>
#include <QtGui/QPushButton>
#include <QtGui/QSpacerItem>
namespace NL3D
{
class CPSPlaneBasisFollowSpeed;
}
namespace NLQT {
class CWorkspaceNode;
class CFollowPathDialog : public QDialog
{
Q_OBJECT
public:
CFollowPathDialog(NL3D::CPSPlaneBasisFollowSpeed *pbfs, CWorkspaceNode *ownerNode, QWidget *parent = 0);
~CFollowPathDialog();
private Q_SLOTS:
void setProjectionMode(int index);
protected:
QGridLayout *gridLayout;
QLabel *label;
QComboBox *comboBox;
QSpacerItem *horizontalSpacer;
QPushButton *pushButton;
NL3D::CPSPlaneBasisFollowSpeed *_FollowPath;
CWorkspaceNode *_Node;
}; /* class CFollowPathDialog */
} /* namespace NLQT */
#endif // FOLLOW_PATH_DIALOG_H

View file

@ -0,0 +1,70 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "global_wind_dialog.h"
// Project includes
#include "modules.h"
#include <nel/3d/u_scene.h>
namespace NLQT {
CGlobalWindDialog::CGlobalWindDialog(QWidget *parent)
: QDockWidget(parent)
{
_ui.setupUi(this);
//_ui.directionWidget->setWrapper(&_DirectionWrapper);
connect(_ui.horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(setWndPower(int)));
connect(this, SIGNAL(visibilityChanged(bool)), this, SLOT(updateWnd(bool)));
}
CGlobalWindDialog::~CGlobalWindDialog()
{
}
void CGlobalWindDialog::setWndPower(int value)
{
float fValue = float(value) / _ui.horizontalSlider->maximum();
_ui.doubleSpinBox->setValue(fValue);
Modules::objView().getScene()->setGlobalWindPower(fValue);
}
void CGlobalWindDialog::updateWnd(bool visible)
{
if (!visible)
return;
_ui.horizontalSlider->setValue(int(Modules::objView().getScene()->getGlobalWindPower() * _ui.horizontalSlider->maximum()));
// _ui.directionWidget->updateUi();
}
/*
NLMISC::CVector CGlobalWindDialog::CDirectionWrapper::get(void) const
{
return Modules::objView().getScene()->getGlobalWindDirection();
}
void CGlobalWindDialog::CDirectionWrapper::set(const NLMISC::CVector &d)
{
Modules::objView().getScene()->setGlobalWindDirection(d);
}
*/
} /* namespace NLQT */

View file

@ -0,0 +1,59 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GLOBAL_WIND_DIALOG_H
#define GLOBAL_WIND_DIALOG_H
#include "ui_global_wind_form.h"
// STL includes
// NeL includes
// Project includes
namespace NLQT {
class CGlobalWindDialog: public QDockWidget
{
Q_OBJECT
public:
CGlobalWindDialog(QWidget *parent = 0);
~CGlobalWindDialog();
private Q_SLOTS:
void setWndPower(int value);
void updateWnd(bool visible);
private:
/// wrappers to tune the direction of wind
/* struct CDirectionWrapper : public IPSWrapper<NLMISC::CVector>
{
NLMISC::CVector get(void) const;
void set(const NLMISC::CVector &d);
} _DirectionWrapper;*/
Ui::CGlobalWindDialog _ui;
}; /* class CGlobalWindDialog */
} /* namespace NLQT */
#endif // GLOBAL_WIND_DIALOG_H

View file

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CGlobalWindDialog</class>
<widget class="QDockWidget" name="CGlobalWindDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>195</width>
<height>64</height>
</rect>
</property>
<property name="maximumSize">
<size>
<width>524287</width>
<height>200</height>
</size>
</property>
<property name="windowTitle">
<string>Weather</string>
</property>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1" colspan="2">
<widget class="QSlider" name="horizontalSlider">
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QDoubleSpinBox" name="doubleSpinBox">
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Power:</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,142 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "graphics_info_widget.h"
// Qt includes
#include <QtGui/QPainter>
#include <QtGui/QColor>
#include <QtGui/QMouseEvent>
// STL includes
namespace NLQT {
const int directionSize = 35;
CGraphicsInfoWidget::CGraphicsInfoWidget(QWidget *parent)
: QWidget(parent)
{
_color = Qt::white;
_mode = Mode::Color;
_x = 0.0;
_y = 0.0;
_text = "";
_braceMode = false;
}
CGraphicsInfoWidget::~CGraphicsInfoWidget()
{
}
void CGraphicsInfoWidget::setMode(int mode)
{
_mode = mode;
}
void CGraphicsInfoWidget::setColor(const QColor &color)
{
_color = color;
repaint();
}
void CGraphicsInfoWidget::setVector(float x, float y)
{
_mode = Mode::Direction;
_x = x;
_y = y;
repaint();
}
void CGraphicsInfoWidget::setText(const QString &text)
{
_text = text;
}
void CGraphicsInfoWidget::setRibbonShape(const std::vector<NLMISC::CVector> &verts, bool braceMode)
{
_mode = Mode::RibbonShape;
_braceMode = braceMode;
_verts = verts;
repaint();
}
void CGraphicsInfoWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setBrush(QBrush(_color));
painter.setPen(QPen(Qt::black, 2, Qt::SolidLine));
painter.drawRoundedRect(QRect(3, 3, width() - 6, height() - 6), 3.0, 3.0);
if (_mode == Mode::Direction)
{
painter.setPen(QPen(Qt::gray, 1, Qt::SolidLine));
painter.drawLine(width() / 2, 4, width() / 2, height() - 4);
painter.drawLine(4, height() / 2, width() - 4, height() / 2);
painter.drawText( 10, 15, _text);
painter.setPen(QPen(Qt::red, 2, Qt::SolidLine));
painter.drawLine(width() / 2, height() / 2,
int((width() / 2) + _x * 0.9f * directionSize), int((height() / 2) - _y * 0.9f * directionSize));
}
if (_mode == Mode::PlaneBasic)
{
}
if (_mode == Mode::RibbonShape)
{
painter.setPen(QPen(Qt::red, 2, Qt::SolidLine));
painter.scale(0.86, 0.86);
painter.translate(6, 6);
if (_braceMode)
{
for(uint k = 0; k < _verts.size() / 2; ++k)
{
painter.drawLine(int((width() / 2.0) * (1 + _verts[2 * k].x)),
int((height() / 2.0) * (1 - _verts[2 * k].y)),
int((width() / 2.0) * (1 + _verts[2 * k + 1].x)),
int((height() / 2.0) * (1 - _verts[2 * k + 1].y)));
}
}
else
{
for(uint k = 1; k < _verts.size(); k++)
{
painter.drawLine(int((width() / 2.0) * (1 + _verts[k - 1].x)),
int((height() / 2.0) * (1 - _verts[k - 1].y)),
int((width() / 2.0) * (1 + _verts[ k].x)),
int((height() / 2.0) * (1 - _verts[k].y)));
}
painter.drawLine(int((width() / 2.0) * (1 + _verts[0].x)),
int((height() / 2.0) * (1 - _verts[0].y)),
int((width() / 2.0) * (1 + _verts[_verts.size() - 1].x)),
int((height() / 2.0) * (1 - _verts[_verts.size() - 1].y)));
}
}
}
void CGraphicsInfoWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
float vx = (event->x() - (width() / 2)) / 0.9f;
float vy = ((height() / 2) - event->y()) / 0.9f;
Q_EMIT applyNewVector(vx, vy);
}
} /* namespace NLQT */

View file

@ -0,0 +1,79 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRAPHICS_INFO_WIDGET_H
#define GRAPHICS_INFO_WIDGET_H
// Qt includes
#include <QtGui/QWidget>
// STL includes
// NeL includes
#include <nel/misc/vector.h>
// Project includes
namespace NLQT {
struct Mode
{
enum List
{
Color = 0,
Direction,
PlaneBasic,
RibbonShape
};
};
class CGraphicsInfoWidget: public QWidget
{
Q_OBJECT
public:
CGraphicsInfoWidget(QWidget *parent = 0);
~CGraphicsInfoWidget();
void setMode(int mode);
void setColor(const QColor &color);
void setVector(float x, float y);
void setText(const QString &text);
void setRibbonShape(const std::vector<NLMISC::CVector> &verts, bool braceMode);
Q_SIGNALS:
void applyNewVector(float x, float y);
protected:
virtual void paintEvent(QPaintEvent *event);
virtual void mouseDoubleClickEvent(QMouseEvent *event);
int _mode;
QColor _color;
float _x;
float _y;
QString _text;
std::vector<NLMISC::CVector> _verts;
bool _braceMode;
}; /* class CGraphicsInfoWidget */
} /* namespace NLQT */
#endif // GRAPHICS_INFO_WIDGET_H

View file

@ -0,0 +1,157 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdpch.h"
#include "graphics_viewport.h"
// STL includes
// Qt includes
#include <QtGui/QAction>
#include <QtGui/QResizeEvent>
#include <QtGui/QColorDialog>
#include <QtGui/QFileDialog>
// NeL includes
#include <nel/misc/rgba.h>
#include <nel/misc/event_server.h>
#include <nel/misc/events.h>
#include <nel/3d/u_driver.h>
#include <nel/3d/driver_user.h>
// Project includes
#include "modules.h"
using namespace std;
using namespace NL3D;
namespace NLQT {
CGraphicsViewport::CGraphicsViewport(QWidget *parent)
: QNLWidget(parent)
{
}
CGraphicsViewport::~CGraphicsViewport()
{
}
void CGraphicsViewport::init()
{
//H_AUTO2
nldebug("CGraphicsViewport::init");
#ifdef NL_OS_UNIX
makeCurrent();
#endif // NL_OS_UNIX
Modules::objView().init(winId(), width(), height());
Modules::psEdit().init();
setMouseTracking(true);
}
void CGraphicsViewport::release()
{
//H_AUTO2
nldebug("CGraphicsViewport::release");
Modules::psEdit().release();
Modules::objView().release();
}
QAction *CGraphicsViewport::createSaveScreenshotAction(QObject *parent)
{
QAction *action = new QAction(parent);
connect(action, SIGNAL(triggered()), this, SLOT(saveScreenshot()));
return action;
}
QAction *CGraphicsViewport::createSetBackgroundColor(QObject *parent)
{
QAction *action = new QAction(parent);
connect(action, SIGNAL(triggered()), this, SLOT(setBackgroundColor()));
return action;
}
void CGraphicsViewport::saveScreenshot()
{
Modules::objView().saveScreenshot("screenshot", false, true, false);
}
void CGraphicsViewport::setBackgroundColor()
{
QColor color = QColorDialog::getColor(QColor(Modules::objView().getBackgroundColor().R,
Modules::objView().getBackgroundColor().G,
Modules::objView().getBackgroundColor().B));
if (color.isValid())
Modules::objView().setBackgroundColor(NLMISC::CRGBA(color.red(), color.green(), color.blue()));
}
void CGraphicsViewport::resizeEvent(QResizeEvent *resizeEvent)
{
QWidget::resizeEvent(resizeEvent);
if (Modules::objView().getDriver())
Modules::objView().setSizeViewport(resizeEvent->size().width(), resizeEvent->size().height());
}
#ifdef NL_OS_WINDOWS
typedef bool (*winProc)(NL3D::IDriver *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
bool CGraphicsViewport::winEvent(MSG * message, long * result)
{
if (Modules::objView().getDriver() && Modules::objView().getDriver()->isActive())
{
NL3D::IDriver *driver = dynamic_cast<NL3D::CDriverUser*>(Modules::objView().getDriver())->getDriver();
if (driver)
{
winProc proc = (winProc)driver->getWindowProc();
return proc(driver, message->hwnd, message->message, message->wParam, message->lParam);
}
}
return false;
}
#else // NL_OS_UNIX
typedef bool (*x11Proc)(NL3D::IDriver *drv, XEvent *e);
bool CGraphicsViewport::x11Event(XEvent *event)
{
if (Modules::objView().getDriver() && Modules::objView().getDriver()->isActive())
{
NL3D::IDriver *driver = dynamic_cast<NL3D::CDriverUser*>(Modules::objView().getDriver())->getDriver();
if (driver)
{
x11Proc proc = (x11Proc)driver->getWindowProc();
return proc(driver, event);
}
}
return false;
}
#endif
} /* namespace NLQT */

View file

@ -0,0 +1,91 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRAPHICS_VIEWPORT_H
#define GRAPHICS_VIEWPORT_H
#include <nel/misc/types_nl.h>
#include <nel/misc/event_emitter.h>
// STL includes
// Qt includes
#include <QtOpenGL/QGLWidget>
#include <QtGui/QWidget>
// NeL includes
// Project includes
#ifdef NL_OS_WINDOWS
typedef QWidget QNLWidget;
#else // NL_OS_UNIX
typedef QGLWidget QNLWidget;
#endif // NL_OS_UNIX
class QAction;
namespace NLQT {
/**
@class CGraphicsViewport
@brief Responsible for interaction between Qt and NeL. Initializes CObjectViewer, CParticleEditor and CVegetableEditor subsystem.
*/
class CGraphicsViewport : public QNLWidget
{
Q_OBJECT
public:
CGraphicsViewport(QWidget *parent);
virtual ~CGraphicsViewport();
virtual QPaintEngine* paintEngine() const { return NULL; }
void init();
void release();
QAction *createSaveScreenshotAction(QObject *parent);
QAction *createSetBackgroundColor(QObject *parent);
private Q_SLOTS:
void saveScreenshot();
void setBackgroundColor();
void submitEvents(NLMISC::CEventServer &server, bool allWindows) { }
void emulateMouseRawMode(bool) { }
protected:
virtual void resizeEvent(QResizeEvent *resizeEvent);
#ifdef NL_OS_WINDOWS
virtual bool winEvent(MSG * message, long * result);
#else // NL_OS_UNIX
virtual bool x11Event(XEvent *event);
#endif
private:
CGraphicsViewport(const CGraphicsViewport &);
CGraphicsViewport &operator=(const CGraphicsViewport &);
}; /* class CGraphicsViewport */
} /* namespace NLQT */
#endif // GRAPHICS_VIEWPORT_H

View file

@ -0,0 +1,408 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the demonstration applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "stdpch.h"
#include "hoverpoints.h"
#define printf
HoverPoints::HoverPoints(QWidget *widget, PointShape shape)
: QObject(widget)
{
m_widget = widget;
widget->installEventFilter(this);
widget->setAttribute(Qt::WA_AcceptTouchEvents);
m_connectionType = CurveConnection;
m_sortType = NoSort;
m_shape = shape;
m_pointPen = QPen(QColor(255, 255, 255, 191), 1);
m_connectionPen = QPen(QColor(255, 255, 255, 127), 2);
m_pointBrush = QBrush(QColor(191, 191, 191, 127));
m_pointSize = QSize(11, 11);
m_currentIndex = -1;
m_editable = true;
m_enabled = true;
m_minCountPoints = 2;
createGradient();
connect(this, SIGNAL(pointsChanged(QPolygonF)),
m_widget, SLOT(update()));
}
void HoverPoints::setEnabled(bool enabled)
{
if (m_enabled != enabled) {
m_enabled = enabled;
m_widget->update();
}
}
bool HoverPoints::eventFilter(QObject *object, QEvent *event)
{
if (object == m_widget && m_enabled) {
switch (event->type()) {
case QEvent::MouseButtonPress:
{
if (!m_fingerPointMapping.isEmpty())
return true;
QMouseEvent *me = (QMouseEvent *) event;
QPointF clickPos = me->pos();
int index = -1;
for (int i=0; i<m_points.size(); ++i) {
QPainterPath path;
if (m_shape == CircleShape)
path.addEllipse(pointBoundingRect(i));
else
path.addRect(pointBoundingRect(i));
if (path.contains(clickPos)) {
index = i;
break;
}
}
if (me->button() == Qt::LeftButton) {
if (index == -1) {
if (!m_editable)
return false;
int pos = 0;
// Insert sort for x or y
if (m_sortType == XSort) {
for (int i=0; i<m_points.size(); ++i)
if (m_points.at(i).x() > clickPos.x()) {
pos = i;
break;
}
} else if (m_sortType == YSort) {
for (int i=0; i<m_points.size(); ++i)
if (m_points.at(i).y() > clickPos.y()) {
pos = i;
break;
}
}
m_points.insert(pos, clickPos);
m_locks.insert(pos, 0);
m_currentIndex = pos;
firePointChange();
} else {
m_currentIndex = index;
}
return true;
} else if (me->button() == Qt::RightButton) {
if (index >= 0 && m_editable) {
if ((m_points.size() - 1) < m_minCountPoints)
return true;
if (m_locks[index] == 0) {
m_locks.remove(index);
m_points.remove(index);
}
firePointChange();
return true;
}
}
}
break;
case QEvent::MouseButtonRelease:
if (!m_fingerPointMapping.isEmpty())
return true;
m_currentIndex = -1;
break;
case QEvent::MouseMove:
if (!m_fingerPointMapping.isEmpty())
return true;
if (m_currentIndex >= 0)
movePoint(m_currentIndex, ((QMouseEvent *)event)->pos());
break;
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
{
const QTouchEvent *const touchEvent = static_cast<const QTouchEvent*>(event);
const QList<QTouchEvent::TouchPoint> points = touchEvent->touchPoints();
const qreal pointSize = qMax(m_pointSize.width(), m_pointSize.height());
Q_FOREACH (const QTouchEvent::TouchPoint &touchPoint, points) {
const int id = touchPoint.id();
switch (touchPoint.state()) {
case Qt::TouchPointPressed:
{
// find the point, move it
QSet<int> activePoints = QSet<int>::fromList(m_fingerPointMapping.values());
int activePoint = -1;
qreal distance = -1;
const int pointsCount = m_points.size();
const int activePointCount = activePoints.size();
if (pointsCount == 2 && activePointCount == 1) { // only two points
activePoint = activePoints.contains(0) ? 1 : 0;
} else {
for (int i=0; i<pointsCount; ++i) {
if (activePoints.contains(i))
continue;
qreal d = QLineF(touchPoint.pos(), m_points.at(i)).length();
if ((distance < 0 && d < 12 * pointSize) || d < distance) {
distance = d;
activePoint = i;
}
}
}
if (activePoint != -1) {
m_fingerPointMapping.insert(touchPoint.id(), activePoint);
movePoint(activePoint, touchPoint.pos());
}
}
break;
case Qt::TouchPointReleased:
{
// move the point and release
QHash<int,int>::iterator it = m_fingerPointMapping.find(id);
movePoint(it.value(), touchPoint.pos());
m_fingerPointMapping.erase(it);
}
break;
case Qt::TouchPointMoved:
{
// move the point
const int pointIdx = m_fingerPointMapping.value(id, -1);
if (pointIdx >= 0) // do we track this point?
movePoint(pointIdx, touchPoint.pos());
}
break;
default:
break;
}
}
if (m_fingerPointMapping.isEmpty()) {
event->ignore();
return false;
} else {
return true;
}
}
break;
case QEvent::TouchEnd:
if (m_fingerPointMapping.isEmpty()) {
event->ignore();
return false;
}
return true;
break;
case QEvent::Resize:
{
QResizeEvent *e = (QResizeEvent *) event;
if (e->oldSize().width() == 0 || e->oldSize().height() == 0)
break;
qreal stretch_x = e->size().width() / qreal(e->oldSize().width());
qreal stretch_y = e->size().height() / qreal(e->oldSize().height());
for (int i=0; i<m_points.size(); ++i) {
QPointF p = m_points[i];
movePoint(i, QPointF(p.x() * stretch_x, p.y() * stretch_y), false);
}
firePointChange();
break;
}
case QEvent::Paint:
{
QWidget *that_widget = m_widget;
m_widget = 0;
QApplication::sendEvent(object, event);
m_widget = that_widget;
paintPoints();
return true;
}
default:
break;
}
}
return false;
}
void HoverPoints::paintPoints()
{
QPainter p;
p.begin(m_widget);
p.setRenderHint(QPainter::Antialiasing);
p.setBrush(m_gradient);
//p.setBrush(QColor(230,230,230));
p.setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
p.drawRoundedRect(QRect(1, 1, m_widget->width() - 2, m_widget->height() - 2), 4.0, 4.0);
p.setBrush(QBrush());
if (m_connectionPen.style() != Qt::NoPen && m_connectionType != NoConnection) {
p.setPen(m_connectionPen);
if (m_connectionType == CurveConnection) {
QPainterPath path;
path.moveTo(m_points.at(0));
for (int i=1; i<m_points.size(); ++i) {
QPointF p1 = m_points.at(i-1);
QPointF p2 = m_points.at(i);
qreal distance = p2.x() - p1.x();
path.cubicTo(p1.x() + distance / 2, p1.y(),
p1.x() + distance / 2, p2.y(),
p2.x(), p2.y());
}
p.drawPath(path);
} else {
p.drawPolyline(m_points);
}
}
p.setPen(m_pointPen);
p.setBrush(m_pointBrush);
for (int i=0; i<m_points.size(); ++i) {
QRectF bounds = pointBoundingRect(i);
if (m_shape == CircleShape)
p.drawEllipse(bounds);
else
p.drawRect(bounds);
}
}
static QPointF bound_point(const QPointF &point, const QRectF &bounds, int lock)
{
QPointF p = point;
qreal left = bounds.left();
qreal right = bounds.right();
qreal top = bounds.top();
qreal bottom = bounds.bottom();
if (p.x() < left || (lock & HoverPoints::LockToLeft)) p.setX(left);
else if (p.x() > right || (lock & HoverPoints::LockToRight)) p.setX(right);
/* if (p.y() < top || (lock & HoverPoints::LockToTop)) p.setY(top);
else if (p.y() > bottom || (lock & HoverPoints::LockToBottom)) p.setY(bottom);
*/
return p;
}
void HoverPoints::setPoints(const QPolygonF &points)
{
if (points.size() != m_points.size())
m_fingerPointMapping.clear();
m_points.clear();
for (int i=0; i<points.size(); ++i)
m_points << bound_point(points.at(i), boundingRect(), 0);
m_locks.clear();
if (m_points.size() > 0) {
m_locks.resize(m_points.size());
m_locks.fill(0);
}
}
void HoverPoints::movePoint(int index, const QPointF &point, bool emitUpdate)
{
m_points[index] = bound_point(point, boundingRect(), m_locks.at(index));
if (emitUpdate)
firePointChange();
}
void HoverPoints::createGradient()
{
m_gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
m_gradient.setCenter(0.45, 0.50);
m_gradient.setFocalPoint(0.40, 0.45);
m_gradient.setColorAt(0.0, QColor(175, 216, 252));
m_gradient.setColorAt(0.4, QColor(151, 183, 220));
m_gradient.setColorAt(0.8, QColor(86, 126, 191));
}
inline static bool x_less_than(const QPointF &p1, const QPointF &p2)
{
return p1.x() < p2.x();
}
inline static bool y_less_than(const QPointF &p1, const QPointF &p2)
{
return p1.y() < p2.y();
}
void HoverPoints::firePointChange()
{
if (m_sortType != NoSort) {
QPointF oldCurrent;
if (m_currentIndex != -1) {
oldCurrent = m_points[m_currentIndex];
}
if (m_sortType == XSort)
qSort(m_points.begin(), m_points.end(), x_less_than);
else if (m_sortType == YSort)
qSort(m_points.begin(), m_points.end(), y_less_than);
// Compensate for changed order...
if (m_currentIndex != -1) {
for (int i=0; i<m_points.size(); ++i) {
if (m_points[i] == oldCurrent) {
m_currentIndex = i;
break;
}
}
}
}
Q_EMIT pointsChanged(m_points);
}

View file

@ -0,0 +1,165 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the demonstration applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef HOVERPOINTS_H
#define HOVERPOINTS_H
#include <QtGui/QtGui>
QT_FORWARD_DECLARE_CLASS(QBypassWidget)
class HoverPoints : public QObject
{
Q_OBJECT
public:
enum PointShape {
CircleShape,
RectangleShape
};
enum LockType {
LockToLeft = 0x01,
LockToRight = 0x02,
LockToTop = 0x04,
LockToBottom = 0x08
};
enum SortType {
NoSort,
XSort,
YSort
};
enum ConnectionType {
NoConnection,
LineConnection,
CurveConnection
};
HoverPoints(QWidget *widget, PointShape shape);
bool eventFilter(QObject *object, QEvent *event);
void paintPoints();
inline QRectF boundingRect() const;
void setBoundingRect(const QRectF &boundingRect) { m_bounds = boundingRect; }
QPolygonF points() const { return m_points; }
void setPoints(const QPolygonF &points);
QSizeF pointSize() const { return m_pointSize; }
void setPointSize(const QSizeF &size) { m_pointSize = size; }
SortType sortType() const { return m_sortType; }
void setSortType(SortType sortType) { m_sortType = sortType; }
ConnectionType connectionType() const { return m_connectionType; }
void setConnectionType(ConnectionType connectionType) { m_connectionType = connectionType; }
void setConnectionPen(const QPen &pen) { m_connectionPen = pen; }
void setShapePen(const QPen &pen) { m_pointPen = pen; }
void setShapeBrush(const QBrush &brush) { m_pointBrush = brush; }
void setPointLock(int pos, LockType lock) { m_locks[pos] = lock; }
void setEditable(bool editable) { m_editable = editable; }
bool editable() const { return m_editable; }
public Q_SLOTS:
void setEnabled(bool enabled);
void setDisabled(bool disabled) { setEnabled(!disabled); }
Q_SIGNALS:
void pointsChanged(const QPolygonF &points);
public:
void firePointChange();
private:
inline QRectF pointBoundingRect(int i) const;
void movePoint(int i, const QPointF &newPos, bool emitChange = true);
void createGradient();
QWidget *m_widget;
QPolygonF m_points;
QRectF m_bounds;
PointShape m_shape;
SortType m_sortType;
ConnectionType m_connectionType;
QVector<uint> m_locks;
QSizeF m_pointSize;
int m_currentIndex;
int m_minCountPoints;
bool m_editable;
bool m_enabled;
QHash<int, int> m_fingerPointMapping;
QPen m_pointPen;
QBrush m_pointBrush;
QPen m_connectionPen;
QRadialGradient m_gradient;
};
inline QRectF HoverPoints::pointBoundingRect(int i) const
{
QPointF p = m_points.at(i);
qreal w = m_pointSize.width();
qreal h = m_pointSize.height();
qreal x = p.x() - w / 2;
qreal y = p.y() - h / 2;
return QRectF(x, y, w, h);
}
inline QRectF HoverPoints::boundingRect() const
{
if (m_bounds.isEmpty())
return m_widget->rect();
else
return m_bounds;
}
#endif // HOVERPOINTS_H

View file

@ -0,0 +1,3 @@
[Dolphin]
ShowPreview=true
Timestamp=2010,8,4,0,59,20

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

Some files were not shown because too many files have changed in this diff Show more