hg/feature/sound
rti 14 years ago
commit ea9a34a6f3

@ -25,7 +25,7 @@ SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_P
# Set CMake 2.6 Policies.
IF(COMMAND cmake_policy)
# Works around warnings libraries linked against that don't
# have absolute paths (e.g. -lpthreads)
# have absolute paths (e.g. -lpthread)
cmake_policy(SET CMP0003 NEW)
# Works around warnings about escaped quotes in ADD_DEFINITIONS

@ -16,6 +16,7 @@ find_path(MAXSDK_INCLUDE_DIR max.h
"$ENV{PROGRAMFILES}/Autodesk/3ds Max 2009 SDK/maxsdk/include"
"$ENV{PROGRAMFILES}/Autodesk/3ds Max 2008 SDK/maxsdk/include"
"$ENV{PROGRAMFILES}/Autodesk/3ds Max 9 SDK/maxsdk/include"
"$ENV{3DSMAX_2011_SDK_PATH}/maxsdk/include"
)
find_path(MAXSDK_CS_INCLUDE_DIR bipexp.h
@ -24,6 +25,7 @@ find_path(MAXSDK_CS_INCLUDE_DIR bipexp.h
"$ENV{PROGRAMFILES}/Autodesk/3ds Max 2009 SDK/maxsdk/include/CS"
"$ENV{PROGRAMFILES}/Autodesk/3ds Max 2008 SDK/maxsdk/include/CS"
"$ENV{PROGRAMFILES}/Autodesk/3ds Max 9 SDK/maxsdk/include/CS"
"$ENV{3DSMAX_2011_SDK_PATH}/maxsdk/include/CS"
)
MACRO(FIND_3DS_LIBRARY MYLIBRARY MYLIBRARYNAME)
@ -34,6 +36,7 @@ MACRO(FIND_3DS_LIBRARY MYLIBRARY MYLIBRARYNAME)
"$ENV{PROGRAMFILES}/Autodesk/3ds Max 2009 SDK/maxsdk/lib"
"$ENV{PROGRAMFILES}/Autodesk/3ds Max 2008 SDK/maxsdk/lib"
"$ENV{PROGRAMFILES}/Autodesk/3ds Max 9 SDK/maxsdk/lib"
"$ENV{3DSMAX_2011_SDK_PATH}/maxsdk/lib"
)
ENDMACRO(FIND_3DS_LIBRARY MYLIBRARY MYLIBRARYNAME)

@ -61,9 +61,9 @@ MACRO(FIND_WWW_LIBRARY MYLIBRARY OPTION)
)
IF(${MYLIBRARY})
IF(${OPTION} STREQUAL REQUIRED)
IF(${OPTION} STREQUAL REQUIRED OR WITH_STATIC)
SET(LIBWWW_LIBRARIES ${LIBWWW_LIBRARIES} ${${MYLIBRARY}})
ENDIF(${OPTION} STREQUAL REQUIRED)
ENDIF(${OPTION} STREQUAL REQUIRED OR WITH_STATIC)
ELSE(${MYIBRARY})
IF(NOT LIBWWW_FIND_QUIETLY)
MESSAGE(STATUS "Warning: Libwww: Library not found: ${MYLIBRARY}")
@ -84,13 +84,15 @@ FIND_WWW_LIBRARY(LIBWWWFILE_LIBRARY REQUIRED wwwfile) # core trans utils html
FIND_WWW_LIBRARY(LIBWWWHTML_LIBRARY REQUIRED wwwhtml) # core utils
FIND_WWW_LIBRARY(LIBWWWHTTP_LIBRARY REQUIRED wwwhttp) # md5 core mime stream utils
FIND_WWW_LIBRARY(LIBWWWMIME_LIBRARY REQUIRED wwwmime) # core cache stream utils
FIND_WWW_LIBRARY(LIBWWWTRANS_LIBRARY REQUIRED wwwtrans) # core utils
FIND_WWW_LIBRARY(LIBWWWUTILS_LIBRARY REQUIRED wwwutils)
# Required for static or if underlinking
FIND_WWW_LIBRARY(LIBWWWCACHE_LIBRARY OPTIONAL wwwcache) # core trans utils
FIND_WWW_LIBRARY(LIBWWWSTREAM_LIBRARY OPTIONAL wwwstream) # core file utils
FIND_WWW_LIBRARY(LIBWWWTRANS_LIBRARY REQUIRED wwwtrans) # core utils
FIND_WWW_LIBRARY(LIBWWWUTILS_LIBRARY REQUIRED wwwutils)
# Required only if underlinking
# Unused protocols

@ -1,46 +0,0 @@
# - Locate XRandR library
# This module defines
# XRandR_LIBRARY, the library to link against
# XRandR_FOUND, if false, do not try to link to XRandR
# XRandR_INCLUDE_DIR, where to find headers.
IF(XRandR_LIBRARY AND XRandR_INCLUDE_DIR)
# in cache already
SET(XRandR_FIND_QUIETLY TRUE)
ENDIF(XRandR_LIBRARY AND XRandR_INCLUDE_DIR)
FIND_PATH(XRandR_INCLUDE_DIR
Xrandr.h
PATHS
$ENV{XRandR_DIR}/include
/usr/include/X11/
/usr/X11R6/include/
PATH_SUFFIXES extensions
)
FIND_LIBRARY(XRandR_LIBRARY
Xrandr
PATHS
$ENV{XRandR_DIR}/lib
/usr/X11R6/lib
/usr/lib
/sw/lib
/opt/local/lib
/opt/csw/lib
/opt/lib
/usr/freeware/lib64
)
IF(XRandR_LIBRARY AND XRandR_INCLUDE_DIR)
SET(XRandR_FOUND "YES")
SET(XRandR_DEFINITIONS -DXRANDR)
IF(NOT XRandR_FIND_QUIETLY)
MESSAGE(STATUS "Found XRandR: ${XRandR_LIBRARY}")
ENDIF(NOT XRandR_FIND_QUIETLY)
ELSE(XRandR_LIBRARY AND XRandR_INCLUDE_DIR)
IF(NOT XRandR_FIND_QUIETLY)
MESSAGE(STATUS "Warning: Unable to find XRandR!")
ENDIF(NOT XRandR_FIND_QUIETLY)
ENDIF(XRandR_LIBRARY AND XRandR_INCLUDE_DIR)

@ -746,6 +746,15 @@ public:
*/
virtual void setCapture (bool b) = 0;
// see if system cursor is currently captured
virtual bool isSystemCursorCaptured() = 0;
// Add a new cursor (name is case unsensitive)
virtual void addCursor(const std::string &name, const NLMISC::CBitmap &bitmap) = 0;
// Display a cursor from its name (case unsensitive)
virtual void setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild = false) = 0;
/** Check whether there is a low level device manager available, and get its interface. Return NULL if not available
* From this interface you can deal with mouse and keyboard as above, but you can also manage game device (joysticks, joypads ...)
*/

@ -430,6 +430,16 @@ public:
virtual void setMousePos (float x, float y);
/// If true, capture the mouse to force it to stay under the window.
virtual void setCapture (bool b);
// see if system cursor is currently captured
virtual bool isSystemCursorCaptured();
// Add a new cursor (name is case unsensitive)
virtual void addCursor(const std::string &name, const NLMISC::CBitmap &bitmap);
// Display a cursor from its name (case unsensitive)
virtual void setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild = false);
// @}

@ -594,6 +594,16 @@ public:
* NB : If a low level mouse is used, it does nothing
*/
virtual void setCapture (bool b) = 0;
// see if system cursor is currently captured
virtual bool isSystemCursorCaptured() = 0;
// Add a new cursor (name is case unsensitive)
virtual void addCursor(const std::string &name, const NLMISC::CBitmap &bitmap) = 0;
// Display a cursor from its name (case unsensitive)
virtual void setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild = false) = 0;
// @}
/// \name Misc.

@ -469,12 +469,12 @@ private:
volatile uint _ProcessExited;
// *** Bitmap sharing
std::map<std::string, NLMISC::CBitmap> _Bitmaps;
std::map<std::string, NLMISC::CBitmap> _Bitmaps;
// *** The zbuffer
// ZBuffer mutex
NLMISC::CFastMutex _Mutex;
NLMISC::CFastMutex _Mutex;
public:
// Zbuffer pixels in meters

@ -621,10 +621,6 @@ public:
void getDibData(uint8*& extractData);
#ifdef NL_OS_WINDOWS
HICON getHICON(sint iconWidth, sint iconHeight, sint iconDepth, const NLMISC::CRGBA &col = NLMISC::CRGBA::White, sint hotSpotX = 0, sint hotSpotY = 0, bool cursor = false) const;
#endif
CBitmap& operator= (const CBitmap& from)
{
if (&from == this)

@ -41,8 +41,6 @@
#include "string_common.h"
#ifdef NL_OS_WINDOWS
struct nameHICON__;
typedef struct HICON__ *HICON;
struct nameHWND__;
typedef struct HWND__ *HWND;
typedef HWND nlWindow;

@ -77,9 +77,6 @@ public:
/// Get desktop current color depth without using UDriver.
static uint getCurrentColorDepth();
/// Check if mouse cursor is in client area.
static bool isSystemCursorInClientArea();
};
} // NLMISC

@ -33,7 +33,7 @@ namespace NL3D
{
// ***************************************************************************
const uint32 IDriver::InterfaceVersion = 0x69; // added clipboard methods
const uint32 IDriver::InterfaceVersion = 0x6a; // added cursors methods
// ***************************************************************************
IDriver::IDriver() : _SyncTexDrvInfos( "IDriver::_SyncTexDrvInfos" )

@ -162,6 +162,19 @@ CDriverD3D::CDriverD3D()
_WindowX = 0;
_WindowY = 0;
_FullScreen = false;
_ColorDepth = ColorDepth32;
_DefaultCursor = EmptyCursor;
_AlphaBlendedCursorSupported = false;
_AlphaBlendedCursorSupportRetrieved = false;
_CurrCol = CRGBA::White;
_CurrRot = 0;
_CurrHotSpotX = 0;
_CurrHotSpotY = 0;
_CursorScale = 0.85f;
_UserViewMtx.identity();
_UserModelMtx.identity();
_PZBCameraPos = CVector::Null;
@ -1214,6 +1227,8 @@ bool CDriverD3D::init (uint windowIcon, emptyProc exitFunc)
ExitFunc = exitFunc;
createCursors();
// Register a window class
WNDCLASSW wc;
@ -1224,7 +1239,7 @@ bool CDriverD3D::init (uint windowIcon, emptyProc exitFunc)
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandleW(NULL);
wc.hIcon = (HICON)windowIcon;
wc.hCursor = LoadCursorW(NULL,(LPCWSTR)IDC_ARROW);
wc.hCursor = _DefaultCursor;
wc.hbrBackground = WHITE_BRUSH;
_WindowClass = "NLD3D" + toString(windowIcon);
ucstring us = _WindowClass;
@ -1712,6 +1727,8 @@ bool CDriverD3D::release()
if (_HWnd)
{
releaseCursors();
// make sure window icons are deleted
std::vector<NLMISC::CBitmap> bitmaps;
setWindowIcon(bitmaps);
@ -2231,10 +2248,10 @@ void CDriverD3D::setWindowIcon(const std::vector<NLMISC::CBitmap> &bitmaps)
}
if (smallIndex > -1)
winIconSmall = bitmaps[smallIndex].getHICON(smallWidth, smallHeight, 32);
convertBitmapToIcon(bitmaps[smallIndex], winIconSmall, smallWidth, smallHeight, 32);
if (bigIndex > -1)
winIconBig = bitmaps[bigIndex].getHICON(bigWidth, bigHeight, 32);
convertBitmapToIcon(bitmaps[bigIndex], winIconBig, bigWidth, bigHeight, 32);
if (winIconBig)
{
@ -3840,4 +3857,84 @@ bool CDriverD3D::pasteTextFromClipboard(ucstring &text)
{
return _EventEmitter.pasteTextFromClipboard(text);
}
bool CDriverD3D::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY, bool cursor)
{
CBitmap src = bitmap;
// resample bitmap if necessary
if (src.getWidth() != iconWidth || src.getHeight() != iconHeight)
{
src.resample(iconWidth, iconHeight);
}
CBitmap colorBm;
colorBm.resize(iconWidth, iconHeight, CBitmap::RGBA);
const CRGBA *srcColorPtr = (CRGBA *) &(src.getPixels()[0]);
const CRGBA *srcColorPtrLast = srcColorPtr + (iconWidth * iconHeight);
CRGBA *destColorPtr = (CRGBA *) &(colorBm.getPixels()[0]);
static volatile uint8 alphaThreshold = 127;
do
{
destColorPtr->modulateFromColor(*srcColorPtr, col);
std::swap(destColorPtr->R, destColorPtr->B);
++ srcColorPtr;
++ destColorPtr;
}
while (srcColorPtr != srcColorPtrLast);
//
HBITMAP colorHbm = NULL;
HBITMAP maskHbm = NULL;
//
if (iconDepth == 16)
{
std::vector<uint16> colorBm16(iconWidth * iconHeight);
const CRGBA *src32 = (const CRGBA *) &colorBm.getPixels(0)[0];
for (uint k = 0; k < colorBm16.size(); ++k)
{
colorBm16[k] = ((uint16)(src32[k].R&0xf8)>>3) | ((uint16)(src32[k].G&0xfc)<<3) | ((uint16)(src32[k].B & 0xf8)<<8);
}
colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 16, &colorBm16[0]);
std::vector<uint8> bitMask((iconWidth * iconHeight + 7) / 8, 0);
for (uint k = 0;k < colorBm16.size(); ++k)
{
if (src32[k].A <= 120)
{
bitMask[k / 8] |= (0x80 >> (k & 7));
}
}
maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 1, &bitMask[0]);
}
else
{
colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]);
maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]);
}
ICONINFO iconInfo;
iconInfo.fIcon = cursor ? FALSE:TRUE;
iconInfo.xHotspot = (DWORD) hotSpotX;
iconInfo.yHotspot = (DWORD) hotSpotY;
iconInfo.hbmMask = maskHbm;
iconInfo.hbmColor = colorHbm;
if (colorHbm && maskHbm)
{
icon = CreateIconIndirect(&iconInfo);
}
//
if (colorHbm) DeleteObject(colorHbm);
if (maskHbm) DeleteObject(maskHbm);
return true;
}
bool CDriverD3D::convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY)
{
return convertBitmapToIcon(bitmap, cursor, iconWidth, iconHeight, iconDepth, col, hotSpotX, hotSpotY, true);
}
} // NL3D

@ -46,6 +46,9 @@
//
#include <algorithm>
typedef HCURSOR nlCursor;
#define EmptyCursor NULL
// *** DEBUG MACRO
@ -916,6 +919,18 @@ public:
virtual void showCursor (bool b);
virtual void setMousePos(float x, float y);
virtual void setCapture (bool b);
// see if system cursor is currently captured
virtual bool isSystemCursorCaptured();
virtual void setHardwareCursorScale(float scale) { _CursorScale = scale; }
// Add a new cursor (name is case unsensitive)
virtual void addCursor(const std::string &name, const NLMISC::CBitmap &bitmap);
// Display a cursor from its name (case unsensitive)
virtual void setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild = false);
virtual NLMISC::IMouseDevice *enableLowLevelMouse(bool enable, bool exclusive);
virtual NLMISC::IKeyboardDevice *enableLowLevelKeyboard(bool enable);
virtual NLMISC::IInputDeviceManager *getLowLevelInputDeviceManager();
@ -2075,10 +2090,62 @@ private:
uint _Interval;
bool _FullScreen;
// cursors
enum TColorDepth { ColorDepth16 = 0, ColorDepth32, ColorDepthCount };
TColorDepth _ColorDepth;
std::string _CurrName;
NLMISC::CRGBA _CurrCol;
uint8 _CurrRot;
uint _CurrHotSpotX;
uint _CurrHotSpotY;
float _CursorScale;
nlCursor _DefaultCursor;
bool _AlphaBlendedCursorSupported;
bool _AlphaBlendedCursorSupportRetrieved;
class CCursor
{
public:
NLMISC::CBitmap Src;
TColorDepth ColorDepth;
uint OrigHeight;
float HotspotScale;
uint HotspotOffsetX;
uint HotspotOffsetY;
sint HotSpotX;
sint HotSpotY;
nlCursor Cursor;
NLMISC::CRGBA Col;
uint8 Rot;
#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
Display *Dpy;
#endif
public:
CCursor();
~CCursor();
CCursor& operator= (const CCursor& from);
void reset();
};
struct CStrCaseUnsensitiveCmp
{
bool operator()(const std::string &lhs, const std::string &rhs) const
{
return NLMISC::nlstricmp(lhs, rhs) < 0;
}
};
typedef std::map<std::string, CCursor, CStrCaseUnsensitiveCmp> TCursorMap;
TCursorMap _Cursors;
// Directx
uint32 _Adapter;
D3DDEVTYPE _Rasterizer;
D3DDEVTYPE _Rasterizer;
LPDIRECT3D9 _D3D;
public:
IDirect3DDevice9 *_DeviceInterface;
@ -2393,6 +2460,34 @@ public:
// Build 16 bit index buffer for quad
bool buildQuadIndexBuffer();
// Test if cursor is in the client area. always true when software cursor is used and window visible
// (displayed in software when DirectInput is used)
bool isSystemCursorInClientArea();
// Check if RGBA cursors are supported
bool isAlphaBlendedCursorSupported();
// Update cursor appearance
void updateCursor(bool forceRebuild = false);
// Create default cursors
void createCursors();
// Release all cursors
void releaseCursors();
// Convert a NLMISC::CBitmap to nlCursor
bool convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY);
// build a cursor from src, src should have the same size that the hardware cursor
// or a assertion is thrown
nlCursor buildCursor(const NLMISC::CBitmap &src, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY);
// reset the cursor shape to the system arrow
void setSystemArrow();
bool convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col = NLMISC::CRGBA::White, sint hotSpotX = 0, sint hotSpotY = 0, bool cursor = false);
virtual bool copyTextToClipboard(const ucstring &text);
virtual bool pasteTextFromClipboard(ucstring &text);

@ -15,143 +15,540 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stddirect3d.h"
#include "driver_direct3d.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/mouse_device.h"
#include "driver_direct3d.h"
using namespace std;
using namespace NLMISC;
namespace NL3D
{
// ***************************************************************************
// *************************************************************************************
CDriverD3D::CCursor::CCursor() : ColorDepth(CDriverD3D::ColorDepth32),
OrigHeight(32),
HotspotScale(1.f),
HotspotOffsetX(0),
HotspotOffsetY(0),
HotSpotX(0),
HotSpotY(0),
Cursor(EmptyCursor),
Col(CRGBA::White),
Rot(0)
{
}
// *************************************************************************************
CDriverD3D::CCursor::~CCursor()
{
reset();
}
// *************************************************************************************
void CDriverD3D::CCursor::reset()
{
if (Cursor != EmptyCursor)
{
DestroyIcon(Cursor);
}
}
// *************************************************************************************
CDriverD3D::CCursor& CDriverD3D::CCursor::operator= (const CDriverD3D::CCursor& from)
{
if (&from == this)
return *this;
Src = from.Src; // requires more than a surface copy
OrigHeight = from.OrigHeight;
HotspotScale = from.HotspotScale;
HotspotOffsetX = from.HotspotOffsetX;
HotspotOffsetY = from.HotspotOffsetY;
HotSpotX = from.HotSpotX;
HotSpotY = from.HotSpotY;
Cursor = from.Cursor;
Col = from.Col;
Rot = from.Rot;
return *this;
}
// *************************************************************************************
bool CDriverD3D::isAlphaBlendedCursorSupported()
{
if (!_AlphaBlendedCursorSupportRetrieved)
{
// Support starts with windows 2000 (not only from XP as seen in most docs)
// NB : Additionnaly, could query D3D caps to know if
// color hardware cursor is supported, not only emulated,
// but can't be sure that using the win32 api 'SetCursor' uses the same resources
// So far, seems to be supported on any modern card used by the game anyway ...
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&osvi))
{
_AlphaBlendedCursorSupported = (osvi.dwMajorVersion >= 5);
}
_AlphaBlendedCursorSupportRetrieved = true;
}
return _AlphaBlendedCursorSupported;
}
void CDriverD3D::showCursor (bool b)
// *************************************************************************************
void CDriverD3D::addCursor(const std::string &name, const NLMISC::CBitmap &cursorBitmap)
{
if (!isAlphaBlendedCursorSupported()) return;
nlassert(cursorBitmap.getWidth() != 0);
nlassert(cursorBitmap.getHeight() != 0);
// find used part base on alpha, to avoid too much shrinking
const CRGBA *pixels = (const CRGBA *) &cursorBitmap.getPixels()[0];
uint minX, maxX, minY, maxY;
uint width = cursorBitmap.getWidth();
uint height = cursorBitmap.getHeight();
//
minX = 0;
for (uint x = 0; x < width; ++x)
{
bool stop = false;
minX = x;
for (uint y = 0; y < height; ++y)
{
if(pixels[x + y * width].A != 0)
{
stop = true;
break;
}
}
if (stop) break;
}
//
maxX = width - 1;
for (sint x = width - 1; x >= 0; --x)
{
bool stop = false;
maxX = (uint) x;
for (uint y = 0; y < height; ++y)
{
if(pixels[x + y * width].A != 0)
{
stop = true;
break;
}
}
if (stop) break;
}
//
minY = 0;
for (uint y = 0; y < height; ++y)
{
bool stop = false;
minY = y;
for (uint x = 0; x < width; ++x)
{
if(pixels[x + y * width].A != 0)
{
stop = true;
break;
}
}
if (stop) break;
}
//
maxY = height - 1;
for (sint y = height - 1; y >= 0; --y)
{
bool stop = false;
maxY = (uint) y;
for (uint x = 0; x < width; ++x)
{
if(pixels[x + y * width].A != 0)
{
stop = true;
break;
}
}
if (stop) break;
}
//
CCursor &curs = _Cursors[name];
curs = CCursor(); // erase possible previous cursor
uint destWidth;
uint destHeight;
destWidth = GetSystemMetrics(SM_CXCURSOR);
destHeight = GetSystemMetrics(SM_CYCURSOR);
// build a square bitmap
uint tmpSize = std::max(maxX - minX + 1, maxY - minY + 1);
curs.Src.resize(tmpSize, tmpSize);
// blit at top left corner
curs.Src.blit(cursorBitmap, minX, minY, maxX - minX + 1, maxY - minY + 1, 0, 0);
curs.OrigHeight = cursorBitmap.getHeight();
curs.HotspotOffsetX = minX;
curs.HotspotOffsetY = minY;
//
curs.HotspotScale = _CursorScale;
clamp(curs.HotspotScale, 0.f, 1.f);
// first resampling, same for all cursors
tmpSize = (uint) (tmpSize * curs.HotspotScale);
if (tmpSize == 0) tmpSize = 1;
/*
curs.Src.resample(tmpSize, tmpSize);
*/
// shrink if necessary
if (tmpSize > destWidth || tmpSize > destHeight) // need to shrink ?
{
// constraint proportions
curs.HotspotScale *= std::min(float(destWidth) / tmpSize, float(destHeight) / tmpSize);
curs.Src.resample(destWidth, destHeight);
}
else
{
CBitmap final;
final.resize(destWidth, destHeight);
final.blit(&curs.Src, 0, 0);
curs.Src.swap(final);
}
if (name == _CurrName)
{
updateCursor();
}
}
// *************************************************************************************
void CDriverD3D::createCursors()
{
_DefaultCursor = LoadCursor(NULL, IDC_ARROW);
}
// *************************************************************************************
void CDriverD3D::releaseCursors()
{
SetClassLongPtr(_HWnd, GCLP_HCURSOR, 0);
_Cursors.clear();
}
// *************************************************************************************
void CDriverD3D::updateCursor(bool forceRebuild)
{
setCursor(_CurrName, _CurrCol, _CurrRot, _CurrHotSpotX, _CurrHotSpotY, forceRebuild);
}
// *************************************************************************************
void CDriverD3D::setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild)
{
// don't update cursor if it's hidden or if custom cursors are not suppported
if (!isAlphaBlendedCursorSupported() || _CurrName == "none") return;
_CurrName = name;
_CurrCol = col;
_CurrRot = rot;
_CurrHotSpotX = hotSpotX;
_CurrHotSpotY = hotSpotY;
// cursor has to be changed next time
if (_CurrName.empty()) return;
if (rot > 3) rot = 3; // same than 'CViewRenderer::drawRotFlipBitmapTiled
TCursorMap::iterator it = _Cursors.find(name);
nlCursor cursorHandle = _DefaultCursor;
if (it != _Cursors.end())
{
// Update cursor if modified or not already built
CCursor &curs = it->second;
hotSpotX = (sint) (curs.HotspotScale * (hotSpotX - curs.HotspotOffsetX));
hotSpotY = (sint) (curs.HotspotScale * ((curs.OrigHeight - hotSpotY) - curs.HotspotOffsetY));
if (curs.Cursor == EmptyCursor ||
curs.HotSpotX != hotSpotX ||
curs.HotSpotY != hotSpotY ||
curs.Col != col ||
curs.Rot != rot ||
curs.ColorDepth != _ColorDepth ||
forceRebuild
)
{
curs.reset();
curs.Cursor = buildCursor(curs.Src, col, rot, hotSpotX, hotSpotY);
curs.Col = col;
curs.Rot = rot;
curs.HotSpotX = hotSpotX;
curs.HotSpotY = hotSpotY;
curs.ColorDepth = _ColorDepth;
}
cursorHandle = curs.Cursor ? curs.Cursor : _DefaultCursor;
}
if (isSystemCursorInClientArea() || isSystemCursorCaptured() || forceRebuild)
{
// if (CInputHandlerManager::getInstance()->hasFocus())
{
::SetCursor(cursorHandle);
SetClassLongPtr(_HWnd, GCLP_HCURSOR, (LONG_PTR) cursorHandle); // set default mouse icon to the last one
}
}
}
// *************************************************************************************
nlCursor CDriverD3D::buildCursor(const CBitmap &src, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY)
{
nlassert(isAlphaBlendedCursorSupported());
uint mouseW;
uint mouseH;
// use cursor size from system
mouseW = GetSystemMetrics(SM_CXCURSOR);
mouseH = GetSystemMetrics(SM_CYCURSOR);
CBitmap rotSrc = src;
if (rot > 3) rot = 3; // mimic behavior of 'CViewRenderer::drawRotFlipBitmapTiled' (why not rot & 3 ??? ...)
switch(rot)
{
case 0: break;
case 1: rotSrc.rot90CW(); break;
case 2: rotSrc.rot90CW(); rotSrc.rot90CW(); break;
case 3: rotSrc.rot90CCW(); break;
}
// create a cursor from bitmap
nlCursor result = NULL;
convertBitmapToCursor(rotSrc, result, mouseW, mouseH, _ColorDepth == ColorDepth16 ? 16:32, col, hotSpotX, hotSpotY);
return result;
}
// *************************************************************************************
void CDriverD3D::setSystemArrow()
{
H_AUTO_D3D(CDriverD3D_setSystemArrow);
if (isSystemCursorInClientArea() || isSystemCursorCaptured())
{
SetCursor(_DefaultCursor);
}
// set default mouse icon to the default one
SetClassLongPtr(_HWnd, GCLP_HCURSOR, (LONG_PTR) _DefaultCursor);
}
// ***************************************************************************
void CDriverD3D::showCursor(bool b)
{
H_AUTO_D3D(CDriverD3D_showCursor);
if (_HWnd == EmptyWindow)
return;
if (b)
{
while (ShowCursor(b) < 0) {}
// update current hardware icon to avoid to have the plain arrow
updateCursor(true);
while (ShowCursor(b) < 0)
;
}
else
{
while (ShowCursor(b) >= 0) {}
while (ShowCursor(b) >= 0)
;
}
};
}
// ***************************************************************************
void CDriverD3D::setMousePos(float x, float y)
{
H_AUTO_D3D(CDriver3D_setMousePos);
if (_HWnd)
H_AUTO_D3D(CDriverD3D_setMousePos);
if (_HWnd == EmptyWindow)
return;
sint x1 = (sint)((float)_CurrentMode.Width*x);
sint y1 = (sint)((float)_CurrentMode.Height*(1.0f-y));
// NeL window coordinate to MSWindows coordinates
POINT pt;
pt.x = x1;
pt.y = y1;
ClientToScreen (_HWnd, &pt);
SetCursorPos(pt.x, pt.y);
}
// ***************************************************************************
bool CDriverD3D::isSystemCursorInClientArea()
{
if (_FullScreen /* || !IsMouseCursorHardware() */)
{
return IsWindowVisible(_HWnd) != FALSE;
}
else
{
// NeL window coordinate to MSWindows coordinates
POINT pt;
pt.x = (int)((float)(_CurrentMode.Width)*x);
pt.y = (int)((float)(_CurrentMode.Height)*(1.0f-y));
ClientToScreen (_HWnd, &pt);
SetCursorPos(pt.x, pt.y);
POINT cursPos;
// the mouse should be in the client area of the window
if (!GetCursorPos(&cursPos))
{
return false;
}
HWND wnd = WindowFromPoint(cursPos);
if (wnd != _HWnd)
{
return false; // not the same window
}
// want that the mouse be in the client area
RECT clientRect;
if (!GetClientRect(_HWnd, &clientRect))
{
return false;
}
POINT tl, br;
tl.x = clientRect.left;
tl.y = clientRect.top;
br.x = clientRect.right;
br.y = clientRect.bottom;
if (!ClientToScreen(_HWnd, &tl))
{
return false;
}
if (!ClientToScreen(_HWnd, &br))
{
return false;
}
if ((cursPos.x < tl.x) || (cursPos.x >= br.x) || (cursPos.y < tl.y) || (cursPos.y >= br.y))
{
return false;
}
}
return true;
}
// ***************************************************************************
void CDriverD3D::setCapture (bool b)
{
if (b)
H_AUTO_D3D(CDriverD3D_setCapture);
if (b && isSystemCursorInClientArea() && !isSystemCursorCaptured())
{
RECT client;
GetClientRect (_HWnd, &client);
POINT pt1,pt2;
pt1.x = client.left;
pt1.y = client.top;
ClientToScreen (_HWnd, &pt1);
pt2.x = client.right;
pt2.y = client.bottom;
ClientToScreen (_HWnd, &pt2);
client.bottom = pt2.y;
client.top = pt1.y;
client.left = pt1.x;
client.right = pt2.x;
ClipCursor (&client);
SetCapture(_HWnd);
}
else if (!b && isSystemCursorCaptured())
{
// if hardware mouse and not in client area, then force to update its aspect by updating its pos
if (!isSystemCursorInClientArea())
{
// force update
showCursor(true);
}
ReleaseCapture();
}
else
ClipCursor (NULL);
}
// ***************************************************************************
bool CDriverD3D::isSystemCursorCaptured()
{
H_AUTO_D3D(CDriverD3D_isSystemCursorCaptured);
return GetCapture() == _HWnd;
}
NLMISC::IMouseDevice *CDriverD3D::enableLowLevelMouse(bool enable, bool exclusive)
// ***************************************************************************
NLMISC::IMouseDevice* CDriverD3D::enableLowLevelMouse(bool enable, bool exclusive)
{
H_AUTO_D3D(CDriverD3D_enableLowLevelMouse);
if (_EventEmitter.getNumEmitters() < 2)
return NULL;
NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast<CDIEventEmitter *>(_EventEmitter.getEmitter(1));
NLMISC::IMouseDevice *res = NULL;
NLMISC::CDIEventEmitter *diee = NULL;
if (_EventEmitter.getNumEmitters() > 1)
diee = NLMISC::safe_cast<CDIEventEmitter *>(_EventEmitter.getEmitter(1));
if (enable)
{
try
{
NLMISC::IMouseDevice *md = diee->getMouseDevice(exclusive);
return md;
if (diee)
res = diee->getMouseDevice(exclusive);
}
catch (EDirectInput &)
{
return NULL;
}
}
else
{
diee->releaseMouse();
return NULL;
if (diee)
diee->releaseMouse();
}
return res;
}
// ***************************************************************************
NLMISC::IKeyboardDevice *CDriverD3D::enableLowLevelKeyboard(bool enable)
NLMISC::IKeyboardDevice* CDriverD3D::enableLowLevelKeyboard(bool enable)
{
H_AUTO_D3D(CDriverD3D_enableLowLevelKeyboard);
if (_EventEmitter.getNumEmitters() < 2) return NULL;
NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast<NLMISC::CDIEventEmitter *>(_EventEmitter.getEmitter(1));
NLMISC::IKeyboardDevice *res = NULL;
NLMISC::CDIEventEmitter *diee = NULL;
if (_EventEmitter.getNumEmitters() > 1)
diee = NLMISC::safe_cast<NLMISC::CDIEventEmitter *>(_EventEmitter.getEmitter(1));
if (enable)
{
try
{
NLMISC::IKeyboardDevice *md = diee->getKeyboardDevice();
return md;
if (diee)
res = diee->getKeyboardDevice();
}
catch (EDirectInput &)
{
return NULL;
}
}
else
{
diee->releaseKeyboard();
return NULL;
if (diee)
diee->releaseKeyboard();
}
return res;
}
// ***************************************************************************
NLMISC::IInputDeviceManager *CDriverD3D::getLowLevelInputDeviceManager()
NLMISC::IInputDeviceManager* CDriverD3D::getLowLevelInputDeviceManager()
{
H_AUTO_D3D(CDriverD3D_getLowLevelInputDeviceManager);
if (_EventEmitter.getNumEmitters() < 2) return NULL;
NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast<NLMISC::CDIEventEmitter *>(_EventEmitter.getEmitter(1));
return diee;
NLMISC::IInputDeviceManager *res = NULL;
if (_EventEmitter.getNumEmitters() > 1)
res = NLMISC::safe_cast<NLMISC::CDIEventEmitter *>(_EventEmitter.getEmitter(1));
return res;
}
// ***************************************************************************
uint CDriverD3D::getDoubleClickDelay(bool hardwareMouse)
{
H_AUTO_D3D(CDriverD3D_getDoubleClickDelay);
uint res = 250;
NLMISC::IMouseDevice *md = NULL;
if (_EventEmitter.getNumEmitters() >= 2)
{
NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast<CDIEventEmitter *>(_EventEmitter.getEmitter(1));
@ -167,14 +564,18 @@ uint CDriverD3D::getDoubleClickDelay(bool hardwareMouse)
}
}
}
if (md)
{
return md->getDoubleClickDelay();
res = md->getDoubleClickDelay();
}
else
{
// try to read the good value from windows
res = ::GetDoubleClickTime();
}
// try to read the good value from windows
return ::GetDoubleClickTime();
}
// ***************************************************************************
return res;
}
} // NL3D

@ -202,7 +202,6 @@ CDriverGL::CDriverGL()
#elif defined (NL_OS_UNIX)
_cursor = None;
_dpy = 0;
_visual_info = NULL;
@ -213,6 +212,20 @@ CDriverGL::CDriverGL()
#endif // NL_OS_UNIX
_ColorDepth = ColorDepth32;
_DefaultCursor = EmptyCursor;
_BlankCursor = EmptyCursor;
_AlphaBlendedCursorSupported = false;
_AlphaBlendedCursorSupportRetrieved = false;
_CurrCol = CRGBA::White;
_CurrRot = 0;
_CurrHotSpotX = 0;
_CurrHotSpotY = 0;
_CursorScale = 0.85f;
_MouseCaptured = false;
_NeedToRestaureGammaRamp = false;
_Interval = 1;
@ -584,9 +597,9 @@ bool CDriverGL::setupDisplay()
// if EXTVertexShader is used, bind the standard GL arrays, and allocate constant
if (!_Extensions.NVVertexProgram && !_Extensions.ARBVertexProgram && _Extensions.EXTVertexShader)
{
_EVSPositionHandle = nglBindParameterEXT(GL_CURRENT_VERTEX_EXT);
_EVSNormalHandle = nglBindParameterEXT(GL_CURRENT_NORMAL);
_EVSColorHandle = nglBindParameterEXT(GL_CURRENT_COLOR);
_EVSPositionHandle = nglBindParameterEXT(GL_CURRENT_VERTEX_EXT);
_EVSNormalHandle = nglBindParameterEXT(GL_CURRENT_NORMAL);
_EVSColorHandle = nglBindParameterEXT(GL_CURRENT_COLOR);
if (!_EVSPositionHandle || !_EVSNormalHandle || !_EVSColorHandle)
{
@ -1465,7 +1478,7 @@ void CDriverGL::setMatrix2DForTextureOffsetAddrMode(const uint stage, const floa
// ***************************************************************************
void CDriverGL::enableNVTextureShader(bool enabled)
void CDriverGL::enableNVTextureShader(bool enabled)
{
H_AUTO_OGL(CDriverGL_enableNVTextureShader)

@ -46,30 +46,33 @@
# endif //XF86VIDMODE
#endif // NL_OS_UNIX
#include "driver_opengl_extension.h"
#include "nel/3d/driver.h"
#include "nel/3d/material.h"
#include "nel/3d/shader.h"
#include "nel/3d/vertex_buffer.h"
#include "nel/misc/matrix.h"
#include "nel/misc/smart_ptr.h"
#include "nel/misc/rgba.h"
#include "nel/misc/event_emitter.h"
#include "nel/misc/bit_set.h"
#include "nel/misc/hierarchical_timer.h"
#include "nel/3d/ptr_set.h"
#include "nel/misc/bitmap.h"
#include "nel/misc/common.h"
#include "nel/misc/heap_memory.h"
#include "nel/misc/event_emitter_multi.h"
#include "driver_opengl_states.h"
#include "nel/misc/time_nl.h"
#include "nel/3d/driver.h"
#include "nel/3d/material.h"
#include "nel/3d/shader.h"
#include "nel/3d/vertex_buffer.h"
#include "nel/3d/ptr_set.h"
#include "nel/3d/texture_cube.h"
#include "nel/3d/vertex_program_parse.h"
#include "nel/3d/viewport.h"
#include "nel/3d/scissor.h"
#include "nel/3d/light.h"
#include "nel/misc/time_nl.h"
#include "nel/3d/occlusion_query.h"
#include "driver_opengl_states.h"
#include "driver_opengl_extension.h"
#ifdef NL_OS_WINDOWS
#include "nel/misc/win_event_emitter.h"
@ -113,14 +116,20 @@ class COcclusionQueryGL;
#ifdef NL_OS_WINDOWS
bool GlWndProc(CDriverGL *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
typedef HCURSOR nlCursor;
#define EmptyCursor NULL
#elif defined (NL_OS_MAC)
bool GlWndProc(CDriverGL *driver, const void* e);
typedef void* nlCursor;
#define EmptyCursor NULL
#elif defined (NL_OS_UNIX)
bool GlWndProc(CDriverGL *driver, XEvent &e);
typedef Cursor nlCursor;
#define EmptyCursor None
#endif
@ -511,6 +520,17 @@ public:
virtual void setCapture (bool b);
// see if system cursor is currently captured
virtual bool isSystemCursorCaptured();
virtual void setHardwareCursorScale(float scale) { _CursorScale = scale; }
// Add a new cursor (name is case unsensitive)
virtual void addCursor(const std::string &name, const NLMISC::CBitmap &bitmap);
// Display a cursor from its name (case unsensitive)
virtual void setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild = false);
virtual NLMISC::IMouseDevice *enableLowLevelMouse(bool enable, bool exclusive);
virtual NLMISC::IKeyboardDevice *enableLowLevelKeyboard(bool enable);
@ -689,8 +709,65 @@ private:
sint32 _DecorationWidth;
sint32 _DecorationHeight;
// cursors
enum TColorDepth { ColorDepth16 = 0, ColorDepth32, ColorDepthCount };
TColorDepth _ColorDepth;
std::string _CurrName;
NLMISC::CRGBA _CurrCol;
uint8 _CurrRot;
uint _CurrHotSpotX;
uint _CurrHotSpotY;
float _CursorScale;
bool _MouseCaptured;
nlCursor _DefaultCursor;
nlCursor _BlankCursor;
bool _AlphaBlendedCursorSupported;
bool _AlphaBlendedCursorSupportRetrieved;
class CCursor
{
public:
NLMISC::CBitmap Src;
TColorDepth ColorDepth;
uint OrigHeight;
float HotspotScale;
uint HotspotOffsetX;
uint HotspotOffsetY;
sint HotSpotX;
sint HotSpotY;
nlCursor Cursor;
NLMISC::CRGBA Col;
uint8 Rot;
#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
Display *Dpy;
#endif
public:
CCursor();
~CCursor();
CCursor& operator= (const CCursor& from);
void reset();
};
struct CStrCaseUnsensitiveCmp
{
bool operator()(const std::string &lhs, const std::string &rhs) const
{
return NLMISC::nlstricmp(lhs, rhs) < 0;
}
};
typedef std::map<std::string, CCursor, CStrCaseUnsensitiveCmp> TCursorMap;
TCursorMap _Cursors;
#ifdef NL_OS_WINDOWS
bool convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col = NLMISC::CRGBA::White, sint hotSpotX = 0, sint hotSpotY = 0, bool cursor = false);
friend bool GlWndProc(CDriverGL *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
HDC _hDC;
@ -721,11 +798,12 @@ private:
#elif defined (NL_OS_UNIX)
bool convertBitmapToIcon(const NLMISC::CBitmap &bitmap, std::vector<long> &icon);
friend bool GlWndProc(CDriverGL *driver, XEvent &e);
Display* _dpy;
GLXContext _ctx;
Cursor _cursor;
NLMISC::CUnixEventEmitter _EventEmitter;
XVisualInfo* _visual_info;
uint32 _xrandr_version;
@ -905,6 +983,32 @@ private:
bool saveScreenMode();
bool setScreenMode(const GfxMode &mode);
// Test if cursor is in the client area. always true when software cursor is used and window visible
// (displayed in software when DirectInput is used)
bool isSystemCursorInClientArea();
// Check if RGBA cursors are supported
bool isAlphaBlendedCursorSupported();
// Update cursor appearance
void updateCursor(bool forceRebuild = false);
// Create default cursors
void createCursors();
// Release all cursors
void releaseCursors();
// Convert a NLMISC::CBitmap to nlCursor
bool convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY);
// build a cursor from src, src should have the same size that the hardware cursor
// or a assertion is thrown
nlCursor buildCursor(const NLMISC::CBitmap &src, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY);
// reset the cursor shape to the system arrow
void setSystemArrow();
// Get the proj matrix setupped in GL
void refreshProjMatrixFromGL();

@ -445,7 +445,7 @@ PFNWGLGETEXTENSIONSSTRINGARBPROC nwglGetExtensionsStringARB;
#elif defined(NL_OS_UNIX)
// Swap control extensions
PFNGLXSWAPINTERVALEXTPROC nglXSwapIntervalEXT;
NEL_PFNGLXSWAPINTERVALEXTPROC nglXSwapIntervalEXT;
PFNGLXSWAPINTERVALSGIPROC nglXSwapIntervalSGI;
@ -1429,7 +1429,7 @@ static bool setupGLXEXTSwapControl(const char *glext)
CHECK_EXT("GLX_EXT_swap_control");
#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
CHECK_ADDRESS(PFNGLXSWAPINTERVALEXTPROC, glXSwapIntervalEXT);
CHECK_ADDRESS(NEL_PFNGLXSWAPINTERVALEXTPROC, glXSwapIntervalEXT);
#endif
return true;

@ -698,7 +698,7 @@ extern PFNWGLGETEXTENSIONSSTRINGARBPROC nwglGetExtensionsStringARB;
// Swap control extensions
//===========================
extern PFNGLXSWAPINTERVALEXTPROC nglXSwapIntervalEXT;
extern NEL_PFNGLXSWAPINTERVALEXTPROC nglXSwapIntervalEXT;
extern PFNGLXSWAPINTERVALSGIPROC nglXSwapIntervalSGI;

@ -376,6 +376,27 @@ typedef GLvoid (APIENTRY * NEL_PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, G
typedef GLvoid (APIENTRY * NEL_PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert);
#endif
#if defined(NL_OS_MAC)
// Mac GL extensions
#elif defined(NL_OS_UNIX)
// GLX extensions
#ifndef NL_GLX_EXT_swap_control
#define NL_GLX_EXT_swap_control 1
#ifndef GLX_EXT_swap_control
#define GLX_SWAP_INTERVAL_EXT 0x20F1
#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
#endif
typedef GLint (APIENTRY * NEL_PFNGLXSWAPINTERVALEXTPROC) (Display *dpy, GLXDrawable drawable, GLint interval);
#endif // NL_GLX_EXT_swap_control
#endif // NL_OS_MAC
#ifdef __cplusplus
}
#endif

@ -0,0 +1,814 @@
// 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 "stdopengl.h"
#include "driver_opengl.h"
#ifdef NL_OS_WINDOWS
# include <windowsx.h>
#elif defined(NL_OS_MAC)
#elif defined (NL_OS_UNIX)
# include <GL/gl.h>
# include <GL/glx.h>
# include <X11/Xatom.h>
#endif // NL_OS_UNIX
#include "nel/misc/mouse_device.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/3d/u_driver.h"
#include "nel/misc/file.h"
using namespace std;
using namespace NLMISC;
namespace NL3D
{
// *************************************************************************************
CDriverGL::CCursor::CCursor() : ColorDepth(CDriverGL::ColorDepth32),
OrigHeight(32),
HotspotScale(1.f),
HotspotOffsetX(0),
HotspotOffsetY(0),
HotSpotX(0),
HotSpotY(0),
Cursor(EmptyCursor),
Col(CRGBA::White),
Rot(0)
{
#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
Dpy = NULL;
#endif
}
// *************************************************************************************
CDriverGL::CCursor::~CCursor()
{
reset();
}
// *************************************************************************************
void CDriverGL::CCursor::reset()
{
if (Cursor != EmptyCursor)
{
#ifdef NL_OS_WINDOWS
DestroyIcon(Cursor);
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
XFreeCursor(Dpy, Cursor);
XSync(Dpy, False);
#endif
}
}
// *************************************************************************************
CDriverGL::CCursor& CDriverGL::CCursor::operator= (const CDriverGL::CCursor& from)
{
if (&from == this)
return *this;
Src = from.Src; // requires more than a surface copy
OrigHeight = from.OrigHeight;
HotspotScale = from.HotspotScale;
HotspotOffsetX = from.HotspotOffsetX;
HotspotOffsetY = from.HotspotOffsetY;
HotSpotX = from.HotSpotX;
HotSpotY = from.HotSpotY;
Cursor = from.Cursor;
Col = from.Col;
Rot = from.Rot;
#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
Dpy = from.Dpy;
#endif
return *this;
}
// *************************************************************************************
bool CDriverGL::isAlphaBlendedCursorSupported()
{
if (!_AlphaBlendedCursorSupportRetrieved)
{
#ifdef NL_OS_WINDOWS
// Support starts with windows 2000 (not only from XP as seen in most docs)
// NB : Additionnaly, could query D3D caps to know if
// color hardware cursor is supported, not only emulated,
// but can't be sure that using the win32 api 'SetCursor' uses the same resources
// So far, seems to be supported on any modern card used by the game anyway ...
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&osvi))
{
_AlphaBlendedCursorSupported = (osvi.dwMajorVersion >= 5);
}
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
_AlphaBlendedCursorSupported = _xrender_version > 0;
#endif
_AlphaBlendedCursorSupportRetrieved = true;
}
return _AlphaBlendedCursorSupported;
}
// *************************************************************************************
void CDriverGL::addCursor(const std::string &name, const NLMISC::CBitmap &cursorBitmap)
{
if (!isAlphaBlendedCursorSupported()) return;
nlassert(cursorBitmap.getWidth() != 0);
nlassert(cursorBitmap.getHeight() != 0);
// find used part base on alpha, to avoid too much shrinking
const CRGBA *pixels = (const CRGBA *) &cursorBitmap.getPixels()[0];
uint minX, maxX, minY, maxY;
uint width = cursorBitmap.getWidth();
uint height = cursorBitmap.getHeight();
//
minX = 0;
for (uint x = 0; x < width; ++x)
{
bool stop = false;
minX = x;
for (uint y = 0; y < height; ++y)
{
if(pixels[x + y * width].A != 0)
{
stop = true;
break;
}
}
if (stop) break;
}
//
maxX = width - 1;
for (sint x = width - 1; x >= 0; --x)
{
bool stop = false;
maxX = (uint) x;
for (uint y = 0; y < height; ++y)
{
if(pixels[x + y * width].A != 0)
{
stop = true;
break;
}
}
if (stop) break;
}
//
minY = 0;
for (uint y = 0; y < height; ++y)
{
bool stop = false;
minY = y;
for (uint x = 0; x < width; ++x)
{
if(pixels[x + y * width].A != 0)
{
stop = true;
break;
}
}
if (stop) break;
}
//
maxY = height - 1;
for (sint y = height - 1; y >= 0; --y)
{
bool stop = false;
maxY = (uint) y;
for (uint x = 0; x < width; ++x)
{
if(pixels[x + y * width].A != 0)
{
stop = true;
break;
}
}
if (stop) break;
}
//
CCursor &curs = _Cursors[name];
curs = CCursor(); // erase possible previous cursor
uint destWidth;
uint destHeight;
#ifdef NL_OS_WINDOWS
destWidth = GetSystemMetrics(SM_CXCURSOR);
destHeight = GetSystemMetrics(SM_CYCURSOR);
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
Status res = XQueryBestCursor(_dpy, _win, width, height, &destWidth, &destHeight);
#endif
// build a square bitmap
uint tmpSize = std::max(maxX - minX + 1, maxY - minY + 1);
curs.Src.resize(tmpSize, tmpSize);
// blit at top left corner
curs.Src.blit(cursorBitmap, minX, minY, maxX - minX + 1, maxY - minY + 1, 0, 0);
curs.OrigHeight = cursorBitmap.getHeight();
curs.HotspotOffsetX = minX;
curs.HotspotOffsetY = minY;
//
curs.HotspotScale = _CursorScale;
clamp(curs.HotspotScale, 0.f, 1.f);
// first resampling, same for all cursors
tmpSize = (uint) (tmpSize * curs.HotspotScale);
if (tmpSize == 0) tmpSize = 1;
if (curs.HotspotScale < 1.f)
{
curs.Src.resample(tmpSize, tmpSize);
}
// shrink if necessary
if (tmpSize > destWidth || tmpSize > destHeight) // need to shrink ?
{
// constraint proportions
curs.HotspotScale *= std::min(float(destWidth) / tmpSize, float(destHeight) / tmpSize);
curs.Src.resample(destWidth, destHeight);
}
else
{
CBitmap final;
final.resize(destWidth, destHeight);
final.blit(&curs.Src, 0, 0);
curs.Src.swap(final);
}
if (name == _CurrName)
{
updateCursor();
}
}
// *************************************************************************************
void CDriverGL::createCursors()
{
#ifdef NL_OS_WINDOWS
_DefaultCursor = LoadCursor(NULL, IDC_ARROW);
_BlankCursor = NULL;
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
_DefaultCursor = None;
if (_dpy && _win && _BlankCursor == EmptyCursor)
{
// create blank cursor
char bm_no_data[] = { 0,0,0,0,0,0,0,0 };
Pixmap pixmap_no_data = XCreateBitmapFromData (_dpy, _win, bm_no_data, 8, 8);
XColor black;
memset(&black, 0, sizeof (XColor));
black.flags = DoRed | DoGreen | DoBlue;
_BlankCursor = XCreatePixmapCursor (_dpy, pixmap_no_data, pixmap_no_data, &black, &black, 0, 0);
XFreePixmap(_dpy, pixmap_no_data);
}
#endif
}
// *************************************************************************************
void CDriverGL::releaseCursors()
{
#ifdef NL_OS_WINDOWS
SetClassLongPtr(_win, GCLP_HCURSOR, 0);
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
XUndefineCursor(_dpy, _win);
XFreeCursor(_dpy, _BlankCursor);
#endif
_Cursors.clear();
}
// *************************************************************************************
void CDriverGL::updateCursor(bool forceRebuild)
{
setCursor(_CurrName, _CurrCol, _CurrRot, _CurrHotSpotX, _CurrHotSpotY, forceRebuild);
}
// *************************************************************************************
void CDriverGL::setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild)
{
// don't update cursor if it's hidden or if custom cursors are not suppported
if (!isAlphaBlendedCursorSupported() || _CurrName == "none") return;
_CurrName = name;
_CurrCol = col;
_CurrRot = rot;
_CurrHotSpotX = hotSpotX;
_CurrHotSpotY = hotSpotY;
// cursor has to be changed next time
if (_CurrName.empty()) return;
if (rot > 3) rot = 3; // same than 'CViewRenderer::drawRotFlipBitmapTiled
TCursorMap::iterator it = _Cursors.find(name);
nlCursor cursorHandle = _DefaultCursor;
if (it != _Cursors.end())
{
// Update cursor if modified or not already built
CCursor &curs = it->second;
hotSpotX = (sint) (curs.HotspotScale * (hotSpotX - curs.HotspotOffsetX));
hotSpotY = (sint) (curs.HotspotScale * ((curs.OrigHeight - hotSpotY) - curs.HotspotOffsetY));
if (curs.Cursor == EmptyCursor ||
curs.HotSpotX != hotSpotX ||
curs.HotSpotY != hotSpotY ||
curs.Col != col ||
curs.Rot != rot ||
curs.ColorDepth != _ColorDepth ||
forceRebuild
)
{
curs.reset();
curs.Cursor = buildCursor(curs.Src, col, rot, hotSpotX, hotSpotY);
curs.Col = col;
curs.Rot = rot;
curs.HotSpotX = hotSpotX;
curs.HotSpotY = hotSpotY;
curs.ColorDepth = _ColorDepth;
#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
curs.Dpy = _dpy;
#endif
}
cursorHandle = curs.Cursor ? curs.Cursor : _DefaultCursor;
}
if (isSystemCursorInClientArea() || isSystemCursorCaptured() || forceRebuild)
{
// if (CInputHandlerManager::getInstance()->hasFocus())
#ifdef NL_OS_WINDOWS
{
::SetCursor(cursorHandle);
SetClassLongPtr(_win, GCLP_HCURSOR, (LONG_PTR) cursorHandle); // set default mouse icon to the last one
}
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
if (cursorHandle == _DefaultCursor)
{
XUndefineCursor(_dpy, _win);
}
else
{
XDefineCursor(_dpy, _win, cursorHandle);
}
#endif
}
}
// *************************************************************************************
nlCursor CDriverGL::buildCursor(const CBitmap &src, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY)
{
nlassert(isAlphaBlendedCursorSupported());
uint mouseW;
uint mouseH;
#ifdef NL_OS_WINDOWS
// use cursor size from system
mouseW = GetSystemMetrics(SM_CXCURSOR);
mouseH = GetSystemMetrics(SM_CYCURSOR);
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
// use best cursor size for bitmap
Status res = XQueryBestCursor(_dpy, _win, src.getWidth(), src.getHeight(), &mouseW, &mouseH);
#endif
CBitmap rotSrc = src;
if (rot > 3) rot = 3; // mimic behavior of 'CViewRenderer::drawRotFlipBitmapTiled' (why not rot & 3 ??? ...)
switch(rot)
{
case 0: break;
case 1: rotSrc.rot90CW(); break;
case 2: rotSrc.rot90CW(); rotSrc.rot90CW(); break;
case 3: rotSrc.rot90CCW(); break;
}
// create a cursor from bitmap
nlCursor result = NULL;
convertBitmapToCursor(rotSrc, result, mouseW, mouseH, _ColorDepth == ColorDepth16 ? 16:32, col, hotSpotX, hotSpotY);
return result;
}
// *************************************************************************************
void CDriverGL::setSystemArrow()
{
H_AUTO_OGL(CDriverGL_setSystemArrow);
#ifdef NL_OS_WINDOWS
if (isSystemCursorInClientArea() || isSystemCursorCaptured())
{
SetCursor(_DefaultCursor);
}
// set default mouse icon to the default one
SetClassLongPtr(_win, GCLP_HCURSOR, (LONG_PTR) _DefaultCursor);
#elif defined(NL_OS_MAC)
#elif defined(NL_OS_UNIX)
XUndefineCursor(_dpy, _win);
#endif
}
// --------------------------------------------------
void CDriverGL::showCursor(bool b)
{
H_AUTO_OGL(CDriverGL_showCursor);
if (_win == EmptyWindow)
return;
#ifdef NL_OS_WINDOWS
if (b)
{
// update current hardware icon to avoid to have the plain arrow
updateCursor(true);
while (ShowCursor(b) < 0)
;
}
else
{
while (ShowCursor(b) >= 0)
;
}
#elif defined(NL_OS_MAC)
// Mac OS manages a show/hide counter for the cursor, so hiding the cursor
// twice requires two calls to "show" to make the cursor visible again.
// Since other platforms seem to not do this, the functionality is masked here
// by only calling hide if the cursor is visible and only calling show if
// the cursor was hidden.
CGDisplayErr error = kCGErrorSuccess;
static bool visible = true;
if(b && !visible)
{
error = CGDisplayShowCursor(kCGDirectMainDisplay);
visible = true;
}
else if(!b && visible)
{
error = CGDisplayHideCursor(kCGDirectMainDisplay);
visible = false;
}
if(error != kCGErrorSuccess)
nlerror("cannot show / hide cursor");
#elif defined (NL_OS_UNIX)
if (!b)
{
XDefineCursor(_dpy, _win, _BlankCursor);
_CurrName = "none";
}
else
{
_CurrName = "";
}
// update current hardware icon to avoid to have the plain arrow
updateCursor(true);
#endif // NL_OS_UNIX
}
// --------------------------------------------------
void CDriverGL::setMousePos(float x, float y)
{
H_AUTO_OGL(CDriverGL_setMousePos)
if (_win == EmptyWindow)
return;
sint x1 = (sint)((float)_WindowWidth*x);
sint y1 = (sint)((float)_WindowHeight*(1.0f-y));
#ifdef NL_OS_WINDOWS
// NeL window coordinate to MSWindows coordinates
POINT pt;
pt.x = x1;
pt.y = y1;
ClientToScreen (_win, &pt);
SetCursorPos(pt.x, pt.y);
#elif defined(NL_OS_MAC)
// CG wants absolute coordinates related to first screen's top left
// get the first screen's (conaints menubar) rect (this is not mainScreen)
NSRect firstScreenRect = [[[NSScreen screens] objectAtIndex:0] frame];
// get the rect (position, size) of the window
NSRect windowRect;
if([containerView() isInFullScreenMode])
windowRect = [[[containerView() window] screen] frame];
else
windowRect = [[containerView() window] frame];
// get the view's rect for height and width
NSRect viewRect = [containerView() frame];
// set the cursor position
CGDisplayErr error = CGDisplayMoveCursorToPoint(
kCGDirectMainDisplay, CGPointMake(
windowRect.origin.x + (viewRect.size.width * x),
firstScreenRect.size.height - windowRect.origin.y -
viewRect.size.height + ((1.0 - y) * viewRect.size.height)));
if(error != kCGErrorSuccess)
nlerror("cannot set mouse position");
#elif defined (NL_OS_UNIX)
XWarpPointer (_dpy, None, _win, None, None, None, None, x1, y1);
#endif // NL_OS_UNIX
}
void CDriverGL::setCapture (bool b)
{
H_AUTO_OGL(CDriverGL_setCapture )
#ifdef NL_OS_WINDOWS
if (b && isSystemCursorInClientArea() && !isSystemCursorCaptured())
{
SetCapture(_win);
}
else if (!b && isSystemCursorCaptured())
{
// if hardware mouse and not in client area, then force to update its aspect by updating its pos
if (!isSystemCursorInClientArea())
{
// force update
showCursor(true);
}
ReleaseCapture();
}
#elif defined(NL_OS_MAC)
// no need to capture
_MouseCaptured = b;
#elif defined (NL_OS_UNIX)
if(b /* && isSystemCursorInClientArea() && !isSystemCursorCaptured()*/) // capture the cursor.
{
// capture the cursor
XGrabPointer(_dpy, _win, True, 0, GrabModeAsync, GrabModeAsync, _win, None, CurrentTime);
_MouseCaptured = true;
}
else if (!b/* && isSystemCursorCaptured()*/)
{
// release the cursor
XUngrabPointer(_dpy, CurrentTime);
_MouseCaptured = false;
}
#endif // NL_OS_UNIX
}
bool CDriverGL::isSystemCursorInClientArea()
{
if (_FullScreen /* || !IsMouseCursorHardware() */)
{
#ifdef NL_OS_WINDOWS
return IsWindowVisible(_win) != FALSE;
#endif
}
else
{
#ifdef NL_OS_WINDOWS
POINT cursPos;
// the mouse should be in the client area of the window
if (!GetCursorPos(&cursPos))
{
return false;
}
HWND wnd = WindowFromPoint(cursPos);
if (wnd != _win)
{
return false; // not the same window
}
// want that the mouse be in the client area
RECT clientRect;
if (!GetClientRect(_win, &clientRect))
{
return false;
}
POINT tl, br;
tl.x = clientRect.left;
tl.y = clientRect.top;
br.x = clientRect.right;
br.y = clientRect.bottom;
if (!ClientToScreen(_win, &tl))
{
return false;
}
if (!ClientToScreen(_win, &br))
{
return false;
}
if ((cursPos.x < tl.x) || (cursPos.x >= br.x) || (cursPos.y < tl.y) || (cursPos.y >= br.y))
{
return false;
}
#endif
}
return true;
}
// ***************************************************************************
bool CDriverGL::isSystemCursorCaptured()
{
H_AUTO_OGL(CDriverGL_isSystemCursorCaptured);
#ifdef NL_OS_WINDOWS
return GetCapture() == _win;
#else
return _MouseCaptured;
#endif
}
// ***************************************************************************
NLMISC::IMouseDevice* CDriverGL::enableLowLevelMouse(bool enable, bool exclusive)
{
H_AUTO_OGL(CDriverGL_enableLowLevelMouse);
NLMISC::IMouseDevice *res = NULL;
#ifdef NL_OS_WINDOWS
NLMISC::CDIEventEmitter *diee = NULL;
if (_EventEmitter.getNumEmitters() > 1)
diee = NLMISC::safe_cast<CDIEventEmitter *>(_EventEmitter.getEmitter(1));
if (enable)
{
try
{
if (diee)
res = diee->getMouseDevice(exclusive);
}
catch (EDirectInput &)
{
}
}
else
{
if (diee)
diee->releaseMouse();
}
#elif defined(NL_OS_MAC)
#elif defined (NL_OS_UNIX)
#endif
return res;
}
// ***************************************************************************
NLMISC::IKeyboardDevice* CDriverGL::enableLowLevelKeyboard(bool enable)
{
H_AUTO_OGL(CDriverGL_enableLowLevelKeyboard);
NLMISC::IKeyboardDevice *res = NULL;
#ifdef NL_OS_WINDOWS
NLMISC::CDIEventEmitter *diee = NULL;
if (_EventEmitter.getNumEmitters() > 1)
diee = NLMISC::safe_cast<NLMISC::CDIEventEmitter *>(_EventEmitter.getEmitter(1));
if (enable)
{
try
{
if (diee)
res = diee->getKeyboardDevice();
}
catch (EDirectInput &)
{
}
}
else
{
if (diee)
diee->releaseKeyboard();
}
#elif defined(NL_OS_MAC)
#elif defined (NL_OS_UNIX)
#endif
return res;
}
// ***************************************************************************
NLMISC::IInputDeviceManager* CDriverGL::getLowLevelInputDeviceManager()
{
H_AUTO_OGL(CDriverGL_getLowLevelInputDeviceManager);
NLMISC::IInputDeviceManager *res = NULL;
#ifdef NL_OS_WINDOWS
if (_EventEmitter.getNumEmitters() > 1)
res = NLMISC::safe_cast<NLMISC::CDIEventEmitter *>(_EventEmitter.getEmitter(1));
#elif defined(NL_OS_MAC)
#elif defined (NL_OS_UNIX)
#endif
return res;
}
// ***************************************************************************
uint CDriverGL::getDoubleClickDelay(bool hardwareMouse)
{
H_AUTO_OGL(CDriverGL_getDoubleClickDelay);
uint res = 250;
#ifdef NL_OS_WINDOWS
NLMISC::IMouseDevice *md = NULL;
if (_EventEmitter.getNumEmitters() >= 2)
{
NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast<CDIEventEmitter *>(_EventEmitter.getEmitter(1));
if (diee->isMouseCreated())
{
try
{
md = diee->getMouseDevice(hardwareMouse);
}
catch (EDirectInput &)
{
// could not get device ..
}
}
}
if (md)
{
res = md->getDoubleClickDelay();
}
else
{
// try to read the good value from windows
res = ::GetDoubleClickTime();
}
#elif defined(NL_OS_MAC)
# warning "OpenGL Driver: Missing Mac Implementation for getDoubleClickDelay"
nlwarning("OpenGL Driver: Missing Mac Implementation for getDoubleClickDelay");
#elif defined (NL_OS_UNIX)
// TODO for Linux
#endif
return res;
}
} // NL3D

@ -743,9 +743,8 @@ void CDriverGLStates::enableVertexArray(bool enable)
glEnableClientState(GL_VERTEX_ARRAY);
else
glDisableClientState(GL_VERTEX_ARRAY);
_VertexArrayEnabled= enable;
_VertexArrayEnabled= enable;
}
}
// ***************************************************************************

@ -1016,7 +1016,6 @@ void CDriverGL::toggleGlArraysForNVVertexProgram()
_DriverGLStates.enableTexCoordArray(false);
}
// now, vertex program setup.
_LastSetupGLArrayVertexProgram= true;
}
@ -1080,6 +1079,7 @@ void CDriverGL::toggleGlArraysForARBVertexProgram()
_DriverGLStates.clientActiveTextureARB(i);
_DriverGLStates.enableTexCoordArray(false);
}
// now, vertex program setup.
_LastSetupGLArrayVertexProgram= true;
}
@ -1129,7 +1129,6 @@ void CDriverGL::toggleGlArraysForEXTVertexShader()
_DriverGLStates.enableTexCoordArray(false);
}
// now, vertex program setup.
_LastSetupGLArrayVertexProgram= true;
}

@ -26,6 +26,7 @@
# include <windowsx.h>
#elif defined(NL_OS_MAC)
# import "mac/cocoa_window_delegate.h"
# import <OpenGL/OpenGL.h>
#elif defined (NL_OS_UNIX)
# include <GL/gl.h>
# include <GL/glx.h>
@ -272,6 +273,8 @@ bool CDriverGL::init (uint windowIcon, emptyProc exitFunc)
ExitFunc = exitFunc;
createCursors();
#ifdef NL_OS_WINDOWS
WNDCLASSW wc;
@ -284,7 +287,7 @@ bool CDriverGL::init (uint windowIcon, emptyProc exitFunc)
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(NULL);
wc.hIcon = (HICON)windowIcon;
wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
wc.hCursor = _DefaultCursor;
wc.hbrBackground = WHITE_BRUSH;
wc.lpszClassName = L"NLClass";
wc.lpszMenuName = NULL;
@ -355,10 +358,13 @@ bool CDriverGL::init (uint windowIcon, emptyProc exitFunc)
#ifdef HAVE_XRENDER
sint render_major, render_event, render_error;
if (XQueryExtension(_dpy, "RENDER", &render_major, &render_event, &render_error))
if (XQueryExtension(_dpy, "RENDER", &render_major, &render_event, &render_error) &&
XRenderQueryExtension(_dpy, &render_event, &render_error))
{
_xrender_version = render_major * 100;
nlinfo("3D: XRender %d.%d found", render_major, 0);
sint render_minor = 0;
XRenderQueryVersion(_dpy, &render_major, &render_minor);
_xrender_version = render_major * 100 + render_minor;
nlinfo("3D: XRender %d.%d found", render_major, render_minor);
}
#endif // HAVE_XRENDER
@ -478,10 +484,10 @@ void CDriverGL::setWindowIcon(const std::vector<NLMISC::CBitmap> &bitmaps)
}
if (smallIndex > -1)
winIconSmall = bitmaps[smallIndex].getHICON(smallWidth, smallHeight, 32);
convertBitmapToIcon(bitmaps[smallIndex], winIconSmall, smallWidth, smallHeight, 32);
if (bigIndex > -1)
winIconBig = bitmaps[bigIndex].getHICON(bigWidth, bigHeight, 32);
convertBitmapToIcon(bitmaps[bigIndex], winIconBig, bigWidth, bigHeight, 32);
if (winIconBig)
{
@ -507,24 +513,7 @@ void CDriverGL::setWindowIcon(const std::vector<NLMISC::CBitmap> &bitmaps)
// process each bitmap
for(uint i = 0; i < bitmaps.size(); ++i)
{
// get bitmap width and height
uint width = bitmaps[i].getWidth();
uint height = bitmaps[i].getHeight();
// icon_data position for bitmap
uint pos = (uint)icon_data.size();
// extend icon_data size for bitmap
icon_data.resize(pos + 2 + width*height);
// set bitmap width and height
icon_data[pos++] = width;
icon_data[pos++] = height;
// convert RGBA to ARGB
CObjectVector<uint8> pixels = bitmaps[i].getPixels();
for(uint j = 0; j < pixels.size(); j+=4)
icon_data[pos++] = pixels[j] << 16 | pixels[j+1] << 8 | pixels[j+2] | pixels[j+3] << 24;
convertBitmapToIcon(bitmaps[i], icon_data);
}
}
@ -1502,6 +1491,8 @@ bool CDriverGL::createWindow(const GfxMode &mode)
setWindowTitle(ucstring("NeL window"));
createCursors();
return true;
}
@ -1511,6 +1502,8 @@ bool CDriverGL::destroyWindow()
{
H_AUTO_OGL(CDriverGL_destroyWindow)
releaseCursors();
// make sure window icons are deleted
std::vector<NLMISC::CBitmap> bitmaps;
setWindowIcon(bitmaps);
@ -1679,14 +1672,14 @@ bool CDriverGL::setWindowStyle(EWindowStyle windowStyle)
// put the view in fullscreen mode, hiding the dock but enabling the menubar
// to pop up if the mouse hits the top screen border.
// NOTE: withOptions:nil disables <CMD>+<Tab> application switching!
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#if MAC_OS_X_VERSION_10_6 > MAC_OS_X_VERSION_MAX_ALLOWED
[containerView() enterFullScreenMode:[NSScreen mainScreen] withOptions:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:
NSApplicationPresentationHideDock |
NSApplicationPresentationAutoHideMenuBar],
NSFullScreenModeApplicationPresentationOptions, nil]];
#endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#endif
/*
TODO check if simply using NSView enterFullScreenMode is a good idea.
the context can be set to full screen as well, performance differences?
@ -1770,10 +1763,20 @@ bool CDriverGL::setMode(const GfxMode& mode)
setWindowSize(mode.Width, mode.Height);
setWindowPos(_WindowX, _WindowY);
switch (_Depth)
{
case 16: _ColorDepth = ColorDepth16; break;
case 24:
case 32: _ColorDepth = ColorDepth32; break;
}
// set color depth for custom cursor
updateCursor(true);
return true;
}
#if defined(NL_OS_MAC) && defined(AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER)
#if defined(NL_OS_MAC) && (MAC_OS_X_VERSION_10_6 > MAC_OS_X_VERSION_MAX_ALLOWED)
/// helper to extract bits per pixel value from screen mode, only 16 or 32 bits
static int bppFromDisplayMode(CGDisplayModeRef mode)
@ -1791,7 +1794,7 @@ static int bppFromDisplayMode(CGDisplayModeRef mode)
return 0;
}
#elif defined(NL_OS_MAC) && !defined(AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER)
#elif defined(NL_OS_MAC) && (MAC_OS_X_VERSION_10_6 < MAC_OS_X_VERSION_MAX_ALLOWED)
long GetDictionaryLong(CFDictionaryRef theDict, const void* key)
{
@ -1855,11 +1858,11 @@ bool CDriverGL::getModes(std::vector<GfxMode> &modes)
{
CGDirectDisplayID dspy = display[i];
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#if MAC_OS_X_VERSION_10_6 > MAC_OS_X_VERSION_MAX_ALLOWED
CFArrayRef modeList = CGDisplayCopyAllDisplayModes(dspy, NULL);
#else
CFArrayRef modeList = CGDisplayAvailableModes(dspy);
#endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#endif
if (modeList == NULL)
{
@ -1869,23 +1872,23 @@ bool CDriverGL::getModes(std::vector<GfxMode> &modes)
for (CFIndex j = 0; j < CFArrayGetCount(modeList); ++j)
{
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#if MAC_OS_X_VERSION_10_6 > MAC_OS_X_VERSION_MAX_ALLOWED
CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modeList, j);
uint8 bpp = bppFromDisplayMode(mode);
#else
CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(modeList, j);
uint8 bpp = (uint8)GetModeBitsPerPixel(mode);
#endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#endif
if (bpp >= 16)
{
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#if MAC_OS_X_VERSION_10_6 > MAC_OS_X_VERSION_MAX_ALLOWED
uint16 w = CGDisplayModeGetWidth(mode);
uint16 h = CGDisplayModeGetHeight(mode);
#else
uint16 w = (uint16)GetModeWidth(mode);
uint16 h = (uint16)GetModeHeight(mode);
#endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#endif
// Add this mode
GfxMode mode;
@ -2322,135 +2325,6 @@ IDriver::TMessageBoxId CDriverGL::systemMessageBox (const char* message, const c
return okId;
}
// --------------------------------------------------
void CDriverGL::showCursor(bool b)
{
H_AUTO_OGL(CDriverGL_showCursor)
if (_win == EmptyWindow)
return;
#ifdef NL_OS_WINDOWS
if (b)
{
while (ShowCursor(b) < 0)
;
}
else
{
while (ShowCursor(b) >= 0)
;
}
#elif defined(NL_OS_MAC)
// Mac OS manages a show/hide counter for the cursor, so hiding the cursor
// twice requires two calls to "show" to make the cursor visible again.
// Since other platforms seem to not do this, the functionality is masked here
// by only calling hide if the cursor is visible and only calling show if
// the cursor was hidden.
CGDisplayErr error = kCGErrorSuccess;
static bool visible = true;
if(b && !visible)
{
error = CGDisplayShowCursor(kCGDirectMainDisplay);
visible = true;
}
else if(!b && visible)
{
error = CGDisplayHideCursor(kCGDirectMainDisplay);
visible = false;
}
if(error != kCGErrorSuccess)
nlerror("cannot show / hide cursor");
#elif defined (NL_OS_UNIX)
if (b)
{
if (_cursor != None)
{
XFreeCursor(_dpy, _cursor);
_cursor = None;
}
XUndefineCursor(_dpy, _win);
}
else
{
if (_cursor == None)
{
char bm_no_data[] = { 0,0,0,0, 0,0,0,0 };
Pixmap pixmap_no_data = XCreateBitmapFromData (_dpy, _win, bm_no_data, 8, 8);
XColor black;
memset(&black, 0, sizeof (XColor));
black.flags = DoRed | DoGreen | DoBlue;
_cursor = XCreatePixmapCursor (_dpy, pixmap_no_data, pixmap_no_data, &black, &black, 0, 0);
XFreePixmap(_dpy, pixmap_no_data);
}
XDefineCursor(_dpy, _win, _cursor);
}
#endif // NL_OS_UNIX
}
// --------------------------------------------------
void CDriverGL::setMousePos(float x, float y)
{
H_AUTO_OGL(CDriverGL_setMousePos)
if (_win == EmptyWindow)
return;
sint x1 = (sint)((float)_WindowWidth*x);
sint y1 = (sint)((float)_WindowHeight*(1.0f-y));
#ifdef NL_OS_WINDOWS
// NeL window coordinate to MSWindows coordinates
POINT pt;
pt.x = x1;
pt.y = y1;
ClientToScreen (_win, &pt);
SetCursorPos(pt.x, pt.y);
#elif defined(NL_OS_MAC)
// CG wants absolute coordinates related to first screen's top left
// get the first screen's (conaints menubar) rect (this is not mainScreen)
NSRect firstScreenRect = [[[NSScreen screens] objectAtIndex:0] frame];
// get the rect (position, size) of the window
NSRect windowRect;
if([containerView() isInFullScreenMode])
windowRect = [[[containerView() window] screen] frame];
else
windowRect = [[containerView() window] frame];
// get the view's rect for height and width
NSRect viewRect = [containerView() frame];
// set the cursor position
CGDisplayErr error = CGDisplayMoveCursorToPoint(
kCGDirectMainDisplay, CGPointMake(
windowRect.origin.x + (viewRect.size.width * x),
firstScreenRect.size.height - windowRect.origin.y -
viewRect.size.height + ((1.0 - y) * viewRect.size.height)));
if(error != kCGErrorSuccess)
nlerror("cannot set mouse position");
#elif defined (NL_OS_UNIX)
XWarpPointer (_dpy, None, _win, None, None, None, None, x1, y1);
#endif // NL_OS_UNIX
}
void CDriverGL::getWindowSize(uint32 &width, uint32 &height)
{
H_AUTO_OGL(CDriverGL_getWindowSize)
@ -2622,337 +2496,387 @@ bool CDriverGL::isActive()
return res;
}
void CDriverGL::setCapture (bool b)
// ***************************************************************************
bool CDriverGL::setMonitorColorProperties (const CMonitorColorProperties &properties)
{
H_AUTO_OGL(CDriverGL_setCapture )
H_AUTO_OGL(CDriverGL_setMonitorColorProperties )
#ifdef NL_OS_WINDOWS
if (b)
{
RECT client;
GetClientRect (_win, &client);
POINT pt1,pt2;
pt1.x = client.left;
pt1.y = client.top;
ClientToScreen (_win, &pt1);
pt2.x = client.right;
pt2.y = client.bottom;
ClientToScreen (_win, &pt2);
client.bottom = pt2.y;
client.top = pt1.y;
client.left = pt1.x;
client.right = pt2.x;
ClipCursor (&client);
}
else
ClipCursor (NULL);
// Get a DC
HDC dc = CreateDC ("DISPLAY", NULL, NULL, NULL);
if (dc)
{
// The ramp
WORD ramp[256*3];
/*
if (b)
SetCapture (_hWnd);
else
ReleaseCapture ();
*/
// For each composant
uint c;
for( c=0; c<3; c++ )
{
uint i;
for( i=0; i<256; i++ )
{
// Floating value
float value = (float)i / 256;
#elif defined(NL_OS_MAC)
// Contrast
value = (float) max (0.0f, (value-0.5f) * (float) pow (3.f, properties.Contrast[c]) + 0.5f );
// no need to capture
// Gamma
value = (float) pow (value, (properties.Gamma[c]>0) ? 1 - 3 * properties.Gamma[c] / 4 : 1 - properties.Gamma[c] );
#elif defined (NL_OS_UNIX)
// Luminosity
value = value + properties.Luminosity[c] / 2.f;
ramp[i+(c<<8)] = (WORD)min ((int)65535, max (0, (int)(value * 65535)));
}
}
/*
TODO x11 funtion: setCapture
*/
// Set the ramp
bool result = SetDeviceGammaRamp (dc, ramp) != FALSE;
if(b) // capture the cursor.
{
XGrabPointer(_dpy, _win, True, 0, GrabModeAsync, GrabModeAsync, _win, None, CurrentTime);
// Release the DC
ReleaseDC (NULL, dc);
// Returns result
return result;
}
else // release the cursor.
else
{
XUngrabPointer(_dpy, CurrentTime);
nlwarning ("(CDriverGL::setMonitorColorProperties): can't create DC");
}
#endif // NL_OS_UNIX
#elif defined(NL_OS_MAC)
// TODO for Mac: implement CDriverGL::setMonitorColorProperties
nlwarning ("CDriverGL::setMonitorColorProperties not implemented");
#elif defined (NL_OS_UNIX)
// TODO for Linux: implement CDriverGL::setMonitorColorProperties
nlwarning ("CDriverGL::setMonitorColorProperties not implemented");
#endif
return false;
}
// ***************************************************************************
NLMISC::IMouseDevice* CDriverGL::enableLowLevelMouse(bool enable, bool exclusive)
#ifdef NL_OS_MAC
void CDriverGL::setupApplicationMenu()
{
H_AUTO_OGL(CDriverGL_enableLowLevelMouse)
NSMenu* menu;
NSMenuItem* menuItem;
NSString* title;
NSString* appName;
NLMISC::IMouseDevice *res = NULL;
// get the applications name from it's process info
appName = [[NSProcessInfo processInfo] processName];
#ifdef NL_OS_WINDOWS
// create an empty menu object
menu = [[NSMenu alloc] initWithTitle:@""];
NLMISC::CDIEventEmitter *diee = NULL;
// add the about menu item
title = [@"About " stringByAppendingString:appName];
[menu addItemWithTitle:title
action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
if (_EventEmitter.getNumEmitters() > 1)
diee = NLMISC::safe_cast<CDIEventEmitter *>(_EventEmitter.getEmitter(1));
// separator
[menu addItem:[NSMenuItem separatorItem]];
if (enable)
{
try
{
if (diee)
res = diee->getMouseDevice(exclusive);
}
catch (EDirectInput &)
{
}
}
else
{
if (diee)
diee->releaseMouse();
}
// add the hide application menu item
title = [@"Hide " stringByAppendingString:appName];
[menu addItemWithTitle:title
action:@selector(hide:) keyEquivalent:@"h"];
#elif defined(NL_OS_MAC)
#elif defined (NL_OS_UNIX)
#endif
// add the hide others menu item
menuItem = [menu addItemWithTitle:@"Hide Others"
action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
[menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
return res;
// add the show all menu item
[menu addItemWithTitle:@"Show All"
action:@selector(unhideAllApplications:) keyEquivalent:@""];
// separator
[menu addItem:[NSMenuItem separatorItem]];
/*
TODO on quit send EventDestroyWindowId
*/
// add the quit menu item
title = [@"Quit " stringByAppendingString:appName];
[menu addItemWithTitle:title
action:@selector(terminate:) keyEquivalent:@"q"];
// create an empty menu item and put the new menu into it as a subitem
menuItem = [[NSMenuItem alloc] initWithTitle:@""
action:nil keyEquivalent:@""];
[menuItem setSubmenu:menu];
// create a menu for the application
[NSApp setMainMenu:[[NSMenu alloc] initWithTitle:@""]];
// attach the new menu to the applications menu
[[NSApp mainMenu] addItem:menuItem];
}
#endif
// ***************************************************************************
NLMISC::IKeyboardDevice* CDriverGL::enableLowLevelKeyboard(bool enable)
bool CDriverGL::copyTextToClipboard(const ucstring &text)
{
H_AUTO_OGL(CDriverGL_enableLowLevelKeyboard)
return _EventEmitter.copyTextToClipboard(text);
}
NLMISC::IKeyboardDevice *res = NULL;
bool CDriverGL::pasteTextFromClipboard(ucstring &text)
{
return _EventEmitter.pasteTextFromClipboard(text);
}
#ifdef NL_OS_WINDOWS
NLMISC::CDIEventEmitter *diee = NULL;
if (_EventEmitter.getNumEmitters() > 1)
diee = NLMISC::safe_cast<NLMISC::CDIEventEmitter *>(_EventEmitter.getEmitter(1));
if (enable)
bool CDriverGL::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY, bool cursor)
{
CBitmap src = bitmap;
// resample bitmap if necessary
if (src.getWidth() != iconWidth || src.getHeight() != iconHeight)
{
try
src.resample(iconWidth, iconHeight);
}
CBitmap colorBm;
colorBm.resize(iconWidth, iconHeight, CBitmap::RGBA);
const CRGBA *srcColorPtr = (CRGBA *) &(src.getPixels()[0]);
const CRGBA *srcColorPtrLast = srcColorPtr + (iconWidth * iconHeight);
CRGBA *destColorPtr = (CRGBA *) &(colorBm.getPixels()[0]);
static volatile uint8 alphaThreshold = 127;
do
{
destColorPtr->modulateFromColor(*srcColorPtr, col);
std::swap(destColorPtr->R, destColorPtr->B);
++ srcColorPtr;
++ destColorPtr;
}
while (srcColorPtr != srcColorPtrLast);
//
HBITMAP colorHbm = NULL;
HBITMAP maskHbm = NULL;
//
if (iconDepth == 16)
{
std::vector<uint16> colorBm16(iconWidth * iconHeight);
const CRGBA *src32 = (const CRGBA *) &colorBm.getPixels(0)[0];
for (uint k = 0; k < colorBm16.size(); ++k)
{
if (diee)
res = diee->getKeyboardDevice();
colorBm16[k] = ((uint16)(src32[k].R&0xf8)>>3) | ((uint16)(src32[k].G&0xfc)<<3) | ((uint16)(src32[k].B & 0xf8)<<8);
}
catch (EDirectInput &)
colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 16, &colorBm16[0]);
std::vector<uint8> bitMask((iconWidth * iconHeight + 7) / 8, 0);
for (uint k = 0;k < colorBm16.size(); ++k)
{
if (src32[k].A <= 120)
{
bitMask[k / 8] |= (0x80 >> (k & 7));
}
}
maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 1, &bitMask[0]);
}
else
{
if (diee)
diee->releaseKeyboard();
colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]);
maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]);
}
ICONINFO iconInfo;
iconInfo.fIcon = cursor ? FALSE:TRUE;
iconInfo.xHotspot = (DWORD) hotSpotX;
iconInfo.yHotspot = (DWORD) hotSpotY;
iconInfo.hbmMask = maskHbm;
iconInfo.hbmColor = colorHbm;
if (colorHbm && maskHbm)
{
icon = CreateIconIndirect(&iconInfo);
}
//
if (colorHbm) DeleteObject(colorHbm);
if (maskHbm) DeleteObject(maskHbm);
return true;
}
bool CDriverGL::convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY)
{
return convertBitmapToIcon(bitmap, cursor, iconWidth, iconHeight, iconDepth, col, hotSpotX, hotSpotY, true);
}
#elif defined(NL_OS_MAC)
#elif defined (NL_OS_UNIX)
#endif
return res;
bool CDriverGL::convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY)
{
return false;
}
// ***************************************************************************
NLMISC::IInputDeviceManager* CDriverGL::getLowLevelInputDeviceManager()
#elif defined(NL_OS_UNIX)
bool CDriverGL::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, std::vector<long> &icon)
{
H_AUTO_OGL(CDriverGL_getLowLevelInputDeviceManager)
// get bitmap width and height
uint width = bitmap.getWidth();
uint height = bitmap.getHeight();
NLMISC::IInputDeviceManager *res = NULL;
// icon position for bitmap
uint pos = (uint)icon.size();
#ifdef NL_OS_WINDOWS
// extend icon_data size for bitmap
icon.resize(pos + 2 + width*height);
if (_EventEmitter.getNumEmitters() > 1)
res = NLMISC::safe_cast<NLMISC::CDIEventEmitter *>(_EventEmitter.getEmitter(1));
// set bitmap width and height
icon[pos++] = width;
icon[pos++] = height;
#elif defined(NL_OS_MAC)
#elif defined (NL_OS_UNIX)
#endif
// convert RGBA to ARGB
CObjectVector<uint8> pixels = bitmap.getPixels();
for(uint j = 0; j < pixels.size(); j+=4)
icon[pos++] = pixels[j] << 16 | pixels[j+1] << 8 | pixels[j+2] | pixels[j+3] << 24;
return res;
return true;
}
// ***************************************************************************
uint CDriverGL::getDoubleClickDelay(bool hardwareMouse)
bool CDriverGL::convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY)
{
H_AUTO_OGL(CDriverGL_getDoubleClickDelay)
#ifdef HAVE_XRENDER
uint res = 250;
CBitmap src = bitmap;
#ifdef NL_OS_WINDOWS
// resample bitmap if necessary
if (src.getWidth() != iconWidth || src.getHeight() != iconHeight)
{
src.resample(iconWidth, iconHeight);
}
NLMISC::IMouseDevice *md = NULL;
CBitmap colorBm;
colorBm.resize(iconWidth, iconHeight, CBitmap::RGBA);
const CRGBA *srcColorPtr = (CRGBA *) &(src.getPixels()[0]);
const CRGBA *srcColorPtrLast = srcColorPtr + (iconWidth * iconHeight);
CRGBA *destColorPtr = (CRGBA *) &(colorBm.getPixels()[0]);
if (_EventEmitter.getNumEmitters() >= 2)
do
{
NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast<CDIEventEmitter *>(_EventEmitter.getEmitter(1));
if (diee->isMouseCreated())
// colorize icon
destColorPtr->modulateFromColor(*srcColorPtr, col);
// X11 wants BGRA pixels : swap red and blue channels
std::swap(destColorPtr->R, destColorPtr->B);
// premultiplied alpha
if (destColorPtr->A < 255)
{
try
{
md = diee->getMouseDevice(hardwareMouse);
}
catch (EDirectInput &)
{
// could not get device ..
}
destColorPtr->R = (destColorPtr->R * destColorPtr->A) / 255;
destColorPtr->G = (destColorPtr->G * destColorPtr->A) / 255;
destColorPtr->B = (destColorPtr->B * destColorPtr->A) / 255;
}
++ srcColorPtr;
++ destColorPtr;
}
while (srcColorPtr != srcColorPtrLast);
// use malloc() because X will free() data itself
CRGBA *src32 = (CRGBA*)malloc(colorBm.getSize()*4);
memcpy(src32, &colorBm.getPixels(0)[0], colorBm.getSize()*4);
if (md)
uint size = iconWidth * iconHeight;
// Create the icon pixmap
sint screen = DefaultScreen(_dpy);
Visual *visual = DefaultVisual(_dpy, screen);
if (!visual)
{
res = md->getDoubleClickDelay();
nlwarning("Failed to get a default visual for screen %d", screen);
return false;
}
else
// create the icon pixmap
XImage* image = XCreateImage(_dpy, visual, 32, ZPixmap, 0, (char*)src32, iconWidth, iconHeight, 32, 0);
if (!image)
{
// try to read the good value from windows
res = ::GetDoubleClickTime();
nlwarning("Failed to set the window's icon");
return false;
}
#elif defined(NL_OS_MAC)
# warning "OpenGL Driver: Missing Mac Implementation for getDoubleClickDelay"
nlwarning("OpenGL Driver: Missing Mac Implementation for getDoubleClickDelay");
#elif defined (NL_OS_UNIX)
Pixmap pixmap = XCreatePixmap(_dpy, _win, iconWidth, iconHeight, 32 /* defDepth */);
// TODO for Linux
if (!pixmap)
{
nlwarning("Failed to create a pixmap %ux%ux%d", iconWidth, iconHeight, 32);
return false;
}
#endif
GC gc = XCreateGC(_dpy, pixmap, 0, NULL);
return res;
}
if (!gc)
{
nlwarning("Failed to create a GC");
return false;
}
// ***************************************************************************
bool CDriverGL::setMonitorColorProperties (const CMonitorColorProperties &properties)
{
H_AUTO_OGL(CDriverGL_setMonitorColorProperties )
sint res = XPutImage(_dpy, pixmap, gc, image, 0, 0, 0, 0, iconWidth, iconHeight);
// should return 0
nlwarning("XPutImage returned %d", res);
#ifdef NL_OS_WINDOWS
res = XFreeGC(_dpy, gc);
// should return 1
nlwarning("XFreeGC returned %d", res);
// Get a DC
HDC dc = CreateDC ("DISPLAY", NULL, NULL, NULL);
if (dc)
if (image->data)
{
// The ramp
WORD ramp[256*3];
free(image->data);
image->data = NULL;
}
// For each composant
uint c;
for( c=0; c<3; c++ )
{
uint i;
for( i=0; i<256; i++ )
{
// Floating value
float value = (float)i / 256;
XDestroyImage(image);
// Contrast
value = (float) max (0.0f, (value-0.5f) * (float) pow (3.f, properties.Contrast[c]) + 0.5f );
XRenderPictFormat *format = XRenderFindStandardFormat(_dpy, PictStandardARGB32);
// Gamma
value = (float) pow (value, (properties.Gamma[c]>0) ? 1 - 3 * properties.Gamma[c] / 4 : 1 - properties.Gamma[c] );
if (!format)
{
nlwarning("Failed to find a standard format");
return false;
}
// Luminosity
value = value + properties.Luminosity[c] / 2.f;
ramp[i+(c<<8)] = (WORD)min ((int)65535, max (0, (int)(value * 65535)));
}
}
Picture picture = XRenderCreatePicture(_dpy, pixmap, format, 0, 0);
// Set the ramp
bool result = SetDeviceGammaRamp (dc, ramp) != FALSE;
if (!picture)
{
nlwarning("Failed to create picture");
return false;
}
// Release the DC
ReleaseDC (NULL, dc);
cursor = XRenderCreateCursor(_dpy, picture, (uint)hotSpotX, (uint)hotSpotY);
// Returns result
return result;
}
else
if (!cursor)
{
nlwarning ("(CDriverGL::setMonitorColorProperties): can't create DC");
nlwarning("Failed to create cursor");
return false;
}
#elif defined(NL_OS_MAC)
// TODO for Mac: implement CDriverGL::setMonitorColorProperties
nlwarning ("CDriverGL::setMonitorColorProperties not implemented");
XRenderFreePicture(_dpy, picture);
res = XFreePixmap(_dpy, pixmap);
// should return 1
nlwarning("XFreePixmap returned %d", res);
#elif defined (NL_OS_UNIX)
// TODO for Linux: implement CDriverGL::setMonitorColorProperties
nlwarning ("CDriverGL::setMonitorColorProperties not implemented");
return true;
#endif
#else
return false;
}
#ifdef NL_OS_MAC
void CDriverGL::setupApplicationMenu()
{
NSMenu* menu;
NSMenuItem* menuItem;
NSString* title;
NSString* appName;
// get the applications name from it's process info
appName = [[NSProcessInfo processInfo] processName];
// create an empty menu object
menu = [[NSMenu alloc] initWithTitle:@""];
// add the about menu item
title = [@"About " stringByAppendingString:appName];
[menu addItemWithTitle:title
action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
// separator
[menu addItem:[NSMenuItem separatorItem]];
// add the hide application menu item
title = [@"Hide " stringByAppendingString:appName];
[menu addItemWithTitle:title
action:@selector(hide:) keyEquivalent:@"h"];
// add the hide others menu item
menuItem = [menu addItemWithTitle:@"Hide Others"
action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
[menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
// add the show all menu item
[menu addItemWithTitle:@"Show All"
action:@selector(unhideAllApplications:) keyEquivalent:@""];
// separator
[menu addItem:[NSMenuItem separatorItem]];
/*
TODO on quit send EventDestroyWindowId
*/
// add the quit menu item
title = [@"Quit " stringByAppendingString:appName];
[menu addItemWithTitle:title
action:@selector(terminate:) keyEquivalent:@"q"];
// create an empty menu item and put the new menu into it as a subitem
menuItem = [[NSMenuItem alloc] initWithTitle:@""
action:nil keyEquivalent:@""];
[menuItem setSubmenu:menu];
// create a menu for the application
[NSApp setMainMenu:[[NSMenu alloc] initWithTitle:@""]];
// attach the new menu to the applications menu
[[NSApp mainMenu] addItem:menuItem];
}
#endif
bool CDriverGL::copyTextToClipboard(const ucstring &text)
{
return _EventEmitter.copyTextToClipboard(text);
}
bool CDriverGL::pasteTextFromClipboard(ucstring &text)
{
return _EventEmitter.pasteTextFromClipboard(text);
}
#endif
} // NL3D

@ -241,7 +241,7 @@ bool CCocoaEventEmitter::processMessage(NSEvent* event, CEventServer* server)
server = _server;
NSRect viewRect = [_glView frame];
CGPoint mousePos = [_glView convertPoint:event.locationInWindow fromView:nil];
NSPoint mousePos = [_glView convertPoint:event.locationInWindow fromView:nil];
mousePos.x /= (float)viewRect.size.width;
mousePos.y /= (float)viewRect.size.height;
@ -391,14 +391,14 @@ bool CCocoaEventEmitter::processMessage(NSEvent* event, CEventServer* server)
case NSOtherMouseDown:break;
case NSOtherMouseUp:break;
case NSOtherMouseDragged:break;
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#if MAC_OS_X_VERSION_10_6 > MAC_OS_X_VERSION_MAX_ALLOWED
case NSEventTypeGesture:break;
case NSEventTypeMagnify:break;
case NSEventTypeSwipe:break;
case NSEventTypeRotate:break;
case NSEventTypeBeginGesture:break;
case NSEventTypeEndGesture:break;
#endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#endif
default:
{
nlwarning("Unknown event type. dropping.");

@ -53,9 +53,9 @@ namespace NL3D {
-(void)keyDown:(NSEvent*)event
{
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#if MAC_OS_X_VERSION_10_6 > MAC_OS_X_VERSION_MAX_ALLOWED
[[self inputContext] handleEvent:event];
#endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#endif
}
-(void)setDriver:(NL3D::CDriverGL*)driver

@ -23,8 +23,10 @@ namespace NL3D {
void windowDidMove(NSWindow*, NL3D::CDriverGL*);
}
@interface CocoaWindowDelegate : NSObject<NSWindowDelegate>
@interface CocoaWindowDelegate : NSObject
#if MAC_OS_X_VERSION_10_6 > MAC_OS_X_VERSION_MAX_ALLOWED
<NSWindowDelegate>
#endif
{
NL3D::CDriverGL* _driver;
}

@ -32,6 +32,7 @@ static Atom XA_CLIPBOARD = 0;
static Atom XA_UTF8_STRING = 0;
static Atom XA_TARGETS = 0;
static Atom XA_NEL_SEL = 0;
static Atom XA_WM_DELETE_WINDOW = 0;
namespace NLMISC {
@ -54,7 +55,7 @@ void CUnixEventEmitter::init(Display *dpy, Window win, NL3D::IDriver *driver)
_win = win;
_driver = driver;
XSelectInput (_dpy, _win, KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|StructureNotifyMask|ExposureMask);
XSelectInput (_dpy, _win, KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|StructureNotifyMask|ExposureMask|EnterWindowMask|LeaveWindowMask);
// define Atoms used by clipboard
XA_CLIPBOARD = XInternAtom(dpy, "CLIPBOARD", False);
@ -62,9 +63,13 @@ void CUnixEventEmitter::init(Display *dpy, Window win, NL3D::IDriver *driver)
XA_TARGETS = XInternAtom(dpy, "TARGETS", False);
XA_NEL_SEL = XInternAtom(dpy, "NeL_SEL", False);
// define Atom used by delete window
XA_WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
XSetWMProtocols(dpy, win, &XA_WM_DELETE_WINDOW, 1);
/*
TODO: implements all useful events processing
EnterWindowMask|LeaveWindowMask|ButtonMotionMask|Button1MotionMask|Button2MotionMask|
ButtonMotionMask|Button1MotionMask|Button2MotionMask|
Button3MotionMask|Button4MotionMask|Button5MotionMask|KeymapStateMask|
SubstructureNotifyMask|VisibilityChangeMask|FocusChangeMask|PropertyChangeMask|
ColormapChangeMask|OwnerGrabButtonMask
@ -775,10 +780,10 @@ bool CUnixEventEmitter::processMessage (XEvent &event, CEventServer *server)
createIM();
break;
case ClientMessage:
// if ((xevent.xclient.format == 32) && (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW))
// {
// server->postEvent (new CEventDestroyWindow (this));
// }
if ((event.xclient.format == 32) && ((Atom)event.xclient.data.l[0] == XA_WM_DELETE_WINDOW))
{
server->postEvent(new CEventDestroyWindow(this));
}
break;
default:
// nlinfo("UnknownEvent");

@ -22,6 +22,8 @@
#include "nel/misc/events.h"
#include "nel/misc/game_device_events.h"
#include "nel/3d/driver.h"
#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
#include <X11/Xlib.h>

@ -1643,6 +1643,26 @@ void CDriverUser::setCapture (bool b)
_Driver->setCapture (b);
}
bool CDriverUser::isSystemCursorCaptured()
{
NL3D_HAUTO_UI_DRIVER;
return _Driver->isSystemCursorCaptured();
}
void CDriverUser::addCursor(const std::string &name, const NLMISC::CBitmap &bitmap)
{
NL3D_HAUTO_UI_DRIVER;
_Driver->addCursor(name, bitmap);
}
void CDriverUser::setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild)
{
NL3D_HAUTO_UI_DRIVER;
_Driver->setCursor(name, col, rot, hotSpotX, hotSpotY, forceRebuild);
}
// ***************************************************************************
// ***************************************************************************

@ -1614,9 +1614,6 @@ void CBitmap::releaseMipMaps()
}
}
bool TempMaxVerboseResample = false;
#define logResample if (TempMaxVerboseResample) nldebug
/*-------------------------------------------------------------------*\
resample
\*-------------------------------------------------------------------*/
@ -4107,84 +4104,5 @@ void CBitmap::getDibData(uint8*& extractData)
}
#ifdef NL_OS_WINDOWS
HICON CBitmap::getHICON(sint iconWidth, sint iconHeight, sint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY, bool cursor) const
{
HICON result = NULL;
CBitmap src = *this;
// resample bitmap if necessary
if (_Width != iconWidth || _Height != iconHeight)
{
src.resample(iconWidth, iconHeight);
}
CBitmap colorBm;
colorBm.resize(iconWidth, iconHeight, CBitmap::RGBA);
const CRGBA *srcColorPtr = (CRGBA *) &(src.getPixels()[0]);
const CRGBA *srcColorPtrLast = srcColorPtr + (iconWidth * iconHeight);
CRGBA *destColorPtr = (CRGBA *) &(colorBm.getPixels()[0]);
static volatile uint8 alphaThreshold = 127;
do
{
destColorPtr->modulateFromColor(*srcColorPtr, col);
std::swap(destColorPtr->R, destColorPtr->B);
++ srcColorPtr;
++ destColorPtr;
}
while (srcColorPtr != srcColorPtrLast);
//
HBITMAP colorHbm = NULL;
HBITMAP maskHbm = NULL;
//
if (iconDepth == 16)
{
std::vector<uint16> colorBm16(iconWidth * iconHeight);
const CRGBA *src32 = (const CRGBA *) &colorBm.getPixels(0)[0];
for (uint k = 0; k < colorBm16.size(); ++k)
{
colorBm16[k] = ((uint16)(src32[k].R&0xf8)>>3) | ((uint16)(src32[k].G&0xfc)<<3) | ((uint16)(src32[k].B & 0xf8)<<8);
}
colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 16, &colorBm16[0]);
std::vector<uint8> bitMask((iconWidth * iconHeight + 7) / 8, 0);
for (uint k = 0;k < colorBm16.size(); ++k)
{
if (src32[k].A <= 120)
{
bitMask[k / 8] |= (0x80 >> (k & 7));
}
}
maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 1, &bitMask[0]);
}
else
{
colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]);
maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]);
}
ICONINFO iconInfo;
iconInfo.fIcon = cursor ? FALSE:TRUE;
iconInfo.xHotspot = (DWORD) hotSpotX;
iconInfo.yHotspot = (DWORD) hotSpotY;
iconInfo.hbmMask = maskHbm;
iconInfo.hbmColor = colorHbm;
if (colorHbm && maskHbm)
{
result = CreateIconIndirect(&iconInfo);
}
//
if (colorHbm) DeleteObject(colorHbm);
if (maskHbm) DeleteObject(maskHbm);
return result;
}
#endif
} // NLMISC

@ -78,7 +78,7 @@ namespace NLMISC
// the thread of the task
IThread *_TaskThread;
/// The mutex of the task task
CFastMutex _TaskMutex;
CFastMutex _TaskMutex;
CCoTask *_CoTask;
@ -371,7 +371,7 @@ namespace NLMISC
nlverify(getcontext(&_PImpl->_Ctx) == 0);
// change the task context
_PImpl->_Ctx.uc_stack.ss_sp = _PImpl->_Stack;
_PImpl->_Ctx.uc_stack.ss_sp = _PImpl->_Stack;
_PImpl->_Ctx.uc_stack.ss_size = NL_TASK_STACK_SIZE;
_PImpl->_Ctx.uc_link = NULL;

@ -352,56 +352,4 @@ uint CSystemUtils::getCurrentColorDepth()
return depth;
}
bool CSystemUtils::isSystemCursorInClientArea()
{
#ifdef NL_OS_WINDOWS
if (s_window == NULL)
{
nlwarning("No window has be set with CSystemUtils::setWindow()");
return false;
}
POINT cursPos;
// the mouse should be in the client area of the window
if (!GetCursorPos(&cursPos))
{
return false;
}
HWND wnd = WindowFromPoint(cursPos);
if (wnd != s_window)
{
return false; // not the same window
}
// want that the mouse be in the client area
RECT clientRect;
if (!GetClientRect(s_window, &clientRect))
{
return false;
}
POINT tl, br;
tl.x = clientRect.left;
tl.y = clientRect.top;
br.x = clientRect.right;
br.y = clientRect.bottom;
if (!ClientToScreen(s_window, &tl))
{
return false;
}
if (!ClientToScreen(s_window, &br))
{
return false;
}
if (cursPos.x < tl.x ||
cursPos.x >= br.x ||
cursPos.y < tl.y ||
cursPos.y >= br.y)
{
return false;
}
#else
// TODO for Linux and Mac OS
#endif
return true;
}
} // NLMISC

@ -8,6 +8,6 @@ TARGET_LINK_LIBRARIES(nel_unit_test ${CPPTEST_LIBRARIES} nelmisc nelnet nelligo)
NL_DEFAULT_PROPS(nel_unit_test "Unit Tests")
NL_ADD_RUNTIME_FLAGS(nel_unit_test)
ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DNEL_UNIT_BASE="\\"${PROJECT_SOURCE_DIR}/tools/nel_unit_test/\\"")
ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DNEL_UNIT_BASE="${PROJECT_SOURCE_DIR}/tools/nel_unit_test/")
INSTALL(TARGETS nel_unit_test RUNTIME DESTINATION bin)

@ -1406,7 +1406,7 @@ void CCharacterCL::updateVisualPropertyBehaviour(const NLMISC::TGameCycle &gameC
// New Behaviour Received.
CBehaviour beh(prop);
if(verboseVP(this))
nlinfo("(%05d,%03d) CH::updateVPBeha:%d: '%s(%d)' received.", sint32(T1%100000), NetMngr.getCurrentServerTick(), _Slot, behaviourToString((EBehaviour)beh.Behaviour).c_str(), beh.Behaviour);
nlinfo("(%05d,%03d) CH::updateVPBeha:%d: '%s(%d)' received.", sint32(T1%100000), NetMngr.getCurrentServerTick(), _Slot, behaviourToString((EBehaviour)beh.Behaviour).c_str(), (sint)beh.Behaviour);
// Add in right stage.
_Stages.addStage(gameCycle, PROPERTY_BEHAVIOUR, prop);
@ -4691,7 +4691,7 @@ void CCharacterCL::applyBehaviour(const CBehaviourContext &bc) // virtual
// INFO : display some debug information.
if((VerboseAnimUser && _Slot==0) || (VerboseAnimSelection && _Slot == UserEntity->selection()))
nlinfo("CH:applyBeh:%d: '%d(%s)'", _Slot, behaviour.Behaviour, behaviourToString((EBehaviour)behaviour.Behaviour).c_str());
nlinfo("CH:applyBeh:%d: '%d(%s)'", _Slot, (sint)behaviour.Behaviour, behaviourToString((EBehaviour)behaviour.Behaviour).c_str());
// ***** Apply the behaviour according to type
@ -8330,7 +8330,7 @@ ADD_METHOD(void CCharacterCL::displayDebug(float x, float &y, float lineStep)) /
y += lineStep;
}
// Skeleton Ptr
TextContext->printfAt(x, y, "Skel Ptr: %p", _Skeleton);
TextContext->printfAt(x, y, "Skel Ptr: %p", &_Skeleton);
y += lineStep;
// Animset Ptr
TextContext->printfAt(x, y, "AnimSet Ptr: %p", _CurrentAnimSet[MOVE]);

@ -1983,54 +1983,42 @@ void CClientConfig::release ()
// Do we have to save the cfg file ?
if (ClientCfg.SaveConfig)
{
// Driver still alive ?
if (Driver && Driver->isActive ())
// Save values
try
{
sint32 x, y;
uint32 width, height;
CConfigFile::CVar *varPtr = NULL;
Driver->getWindowPos(x, y);
Driver->getWindowSize(width, height);
// Save values
try
// Driver still alive ?
if (Driver && Driver->isActive ())
{
CConfigFile::CVar *varPtr = NULL;
sint32 x, y;
uint32 width, height;
Driver->getWindowPos(x, y);
Driver->getWindowSize(width, height);
// Are we in window mode ?
if (ClientCfg.Windowed /* && !isWindowMaximized() */)
{
// Save windows position
varPtr = ClientCfg.ConfigFile.getVarPtr ("PositionX");
if (varPtr)
varPtr->forceAsInt (x);
varPtr = ClientCfg.ConfigFile.getVarPtr ("PositionY");
if (varPtr)
varPtr->forceAsInt (y);
writeInt("PositionX", x);
writeInt("PositionY", y);
// Save windows size
varPtr = ClientCfg.ConfigFile.getVarPtr ("Width");
if (varPtr)
varPtr->forceAsInt (std::max((int)width, 800));
varPtr = ClientCfg.ConfigFile.getVarPtr ("Height");
if (varPtr)
varPtr->forceAsInt (std::max((int)height, 600));
writeInt("Width", std::max((sint)width, 800));
writeInt("Height", std::max((sint)height, 600));
}
}
// Save if in FPV or TPV.
varPtr = ClientCfg.ConfigFile.getVarPtr("FPV");
if(varPtr)
varPtr->forceAsInt((sint)ClientCfg.FPV);
// Save if in FPV or TPV.
writeBool("FPV", ClientCfg.FPV);
// Save the camera distance
varPtr = ClientCfg.ConfigFile.getVarPtr("CameraDistance");
if(varPtr)
varPtr->forceAsDouble(ClientCfg.CameraDistance);
}
catch (Exception &e)
{
nlwarning ("Error while set config file variables : %s", e.what ());
}
// Save the camera distance
writeDouble("CameraDistance", ClientCfg.CameraDistance);
}
catch (Exception &e)
{
nlwarning ("Error while set config file variables : %s", e.what ());
}
// Save it

@ -90,8 +90,6 @@
#include "login_progress_post_thread.h"
#include "interface_v3/custom_mouse.h"
#include "browse_faq.h"
@ -797,16 +795,6 @@ void prelogInit()
FPU_CHECKER_ONCE
switch (getCurrentColorDepth())
{
case 16: CustomMouse.setColorDepth(CCustomMouse::ColorDepth16); break;
case 24:
case 32: CustomMouse.setColorDepth(CCustomMouse::ColorDepth32); break;
default:
ExitClientError(CI18N::get("uiUnsupportedColorDepth").toUtf8().c_str());
break;
}
// Check driver version
checkDriverVersion();

@ -27,7 +27,6 @@
#include "interface_v3/input_handler_manager.h"
#include "client_cfg.h"
#include "time_client.h"
#include "interface_v3/custom_mouse.h"
// 3D
#include "nel/3d/u_driver.h"
// Misc
@ -66,11 +65,6 @@ bool SetMousePosFirstTime = true;
// mask for mouse buttons that are known to be down
uint DownMouseButtons = 0;
#ifdef NL_OS_UNIX
// on X11 and cocoa, store whether the mouse was captured or not
bool MouseCapture = false;
#endif
//////////////
// FUNCTION //
//////////////
@ -128,12 +122,14 @@ bool InitMouseWithCursor (bool hardware)
// Get the current mouse position
if (hardware)
{
if (CInterfaceManager::getInstance()->getPointer())
Driver->showCursor(true);
CViewPointer *pointer = CInterfaceManager::getInstance()->getPointer();
if (pointer)
{
float x = (float)CInterfaceManager::getInstance()->getPointer()->getX()/(float)Driver->getWindowWidth();
float y = (float)CInterfaceManager::getInstance()->getPointer()->getY()/(float)Driver->getWindowHeight();
CustomMouse.updateCursor(); // update current hardware icon to avoid to have the plain arrow
Driver->showCursor(true);
float x = (float)pointer->getX()/(float)Driver->getWindowWidth();
float y = (float)pointer->getY()/(float)Driver->getWindowHeight();
if (SetMousePosFirstTime)
{
SetMousePosFirstTime = false;
@ -141,12 +137,9 @@ bool InitMouseWithCursor (bool hardware)
else
{
Driver->setMousePos(x, y);
nlwarning("mouse pos %f,%f", x, y);
}
}
else
{
CustomMouse.updateCursor(); // update current hardware icon to avoid to have the plain arrow
Driver->showCursor(true);
}
}
else
@ -232,7 +225,7 @@ void UpdateMouse ()
Driver->emulateMouseRawMode(false);
}
}
if (!IsSystemCursorCaptured())
if (!Driver->isSystemCursorCaptured())
{
DownMouseButtons = 0;
}
@ -246,7 +239,9 @@ void SetMouseFreeLook ()
{
MouseFreeLook = true;
if (MouseHardware)
{
Driver->showCursor(false);
}
else
{
CInterfaceManager *im = CInterfaceManager::getInstance();
@ -306,9 +301,13 @@ void SetMouseCursor (bool updatePos)
if (updatePos)
{
if (MouseDevice)
{
MouseDevice->setMousePos((float)ix, (float)iy);
}
else
{
Driver->setMousePos(x, y);
}
if (MouseHardware)
{
@ -367,53 +366,6 @@ void SetMouseAcceleration (uint accel)
UpdateMouse ();
}
// *********************************************************************************
void CaptureSystemCursor()
{
if (IsSystemCursorCaptured()) return;
#ifdef NL_OS_WINDOWS
HWND drvWnd = Driver->getDisplay();
if (!drvWnd) return;
SetCapture(drvWnd);
#else
// on X11 and cocoa, set driver mouse capture on and store it locally as well
Driver->setCapture(MouseCapture = true);
#endif
}
// *********************************************************************************
void ReleaseSystemCursor()
{
if (!IsSystemCursorCaptured()) return;
#ifdef NL_OS_WINDOWS
// if hardware mouse and not in client area, then force to update its aspect by updating its pos
if (!IsSystemCursorInClientArea())
{
// force update
ShowCursor(FALSE);
ShowCursor(TRUE);
}
ReleaseCapture();
#else
// on X11 and cocoa, set driver mouse capture off and store it locally as well
Driver->setCapture(MouseCapture = false);
#endif
}
// *********************************************************************************
bool IsSystemCursorCaptured()
{
if (!Driver) return false;
#ifdef NL_OS_WINDOWS
return GetCapture() == Driver->getDisplay();
#else
/*
TODO there should be a way to ask the driver if capturing is on or off
*/
return MouseCapture;
#endif
}
// *********************************************************************************
void HandleSystemCursorCapture(const CEvent &event)
{
@ -421,10 +373,7 @@ void HandleSystemCursorCapture(const CEvent &event)
{
CEventMouseDown &em = (CEventMouseDown &) event;
DownMouseButtons |= em.Button & (leftButton | middleButton | rightButton);
if (IsSystemCursorInClientArea())
{
CaptureSystemCursor();
}
Driver->setCapture(true);
}
if (event == EventMouseUpId)
@ -434,7 +383,7 @@ void HandleSystemCursorCapture(const CEvent &event)
DownMouseButtons &= ~(em.Button & (leftButton | middleButton | rightButton));
if (DownMouseButtons == 0)
{
ReleaseSystemCursor();
Driver->setCapture(false);
}
}
@ -445,66 +394,6 @@ void HandleSystemCursorCapture(const CEvent &event)
}
}
// *********************************************************************************
bool IsSystemCursorInClientArea()
{
if (!Driver) return false;
#ifdef NL_OS_WINDOWS
HWND drvWnd = Driver->getDisplay();
if (!drvWnd) return false;
UDriver::CMode videoMode;
Driver->getCurrentScreenMode(videoMode);
if (!videoMode.Windowed || !IsMouseCursorHardware())
{
// just test visibility
return IsWindowVisible(drvWnd) != FALSE;
}
else
{
POINT cursPos;
// the mouse should be in the client area of the window
if (!GetCursorPos(&cursPos))
{
return false;
}
HWND wnd = WindowFromPoint(cursPos);
if (wnd != drvWnd)
{
return false; // not the same window
}
// want that the mouse be in the client area
RECT clientRect;
if (!GetClientRect(drvWnd, &clientRect))
{
return false;
}
POINT tl, br;
tl.x = clientRect.left;
tl.y = clientRect.top;
br.x = clientRect.right;
br.y = clientRect.bottom;
if (!ClientToScreen(drvWnd, &tl))
{
return false;
}
if (!ClientToScreen(drvWnd, &br))
{
return false;
}
if (cursPos.x < tl.x ||
cursPos.x >= br.x ||
cursPos.y < tl.y ||
cursPos.y >= br.y)
{
return false;
}
}
#else
// TODO for Linux and Mac OS
#endif
return true;
}
sint CNiceInputAuto::_Count = 0;
@ -516,7 +405,7 @@ CNiceInputAuto::CNiceInputAuto()
Driver->enableLowLevelMouse(false, false); // but ignore direct input (win 32 msg only)
CustomMouse.setCursor("curs_default.tga", CRGBA::White, 0, 0x15, 0x18);
Driver->setCursor("curs_default.tga", CRGBA::White, 0, 0x15, 0x18);
Driver->showCursor(true); // keep cursor visible in windowed mode
MouseDevice = NULL;
Driver->enableLowLevelKeyboard (false);

@ -62,22 +62,9 @@ void SetMouseSpeed (float speed);
// Use this method to set the cursor acceleration
void SetMouseAcceleration (uint accel);
// capture the system cursor
void CaptureSystemCursor();
// release the system cursor
void ReleaseSystemCursor();
// see if system cursor is currently captured
bool IsSystemCursorCaptured();
// handle capturing of mouse on button up / button down
void HandleSystemCursorCapture(const NLMISC::CEvent &event);
// Test if cursor is in the client area. always true when software cursor is used and window visible
// (displayed in software when DirectInput is used)
bool IsSystemCursorInClientArea();
// get state of mouse button, as a bitfield formatted like NLMISC::TMouseButton (modifier keys are not included)
uint GetMouseButtonsState();

@ -1,458 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include "custom_mouse.h"
//
#include "../global.h"
#include "../input.h"
#include "input_handler_manager.h"
CCustomMouse CustomMouse;
using namespace NLMISC;
using namespace NL3D;
#ifdef NL_OS_WINDOWS
// *************************************************************************************
CCustomMouse::CCursor::CCursor() : ColorDepth(CCustomMouse::ColorDepth32),
OrigHeight(32),
HotspotScale(1.f),
HotspotOffsetX(0),
HotspotOffsetY(0),
HotSpotX(0),
HotSpotY(0),
Icon(0),
Col(CRGBA::White),
Rot(0)
{
}
// *************************************************************************************
CCustomMouse::CCursor::~CCursor()
{
if (Icon)
{
DestroyIcon(Icon);
}
}
// *************************************************************************************
CCustomMouse::CCustomMouse()
{
_ColorDepth = CCustomMouse::ColorDepth32;
_DefaultCursor = LoadCursor(NULL, IDC_ARROW);
_AlphaBlendedCursorSupported = false;
_AlphaBlendedCursorSupportRetrieved = false;
_CurrCol = CRGBA::White;
_CurrRot = 0;
_CurrHotSpotX = 0;
_CurrHotSpotY = 0;
}
// *************************************************************************************
bool CCustomMouse::isAlphaBlendedCursorSupported()
{
if (!_AlphaBlendedCursorSupportRetrieved)
{
// Support starts with windows 2000 (not only from XP as seen in most docs)
// NB : Additionnaly, could query D3D caps to know if
// color hardware cursor is supported, not only emulated,
// but can't be sure that using the win32 api 'SetCursor' uses the same resources
// So far, seems to be supported on any modern card used by the game anyway ...
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&osvi))
{
_AlphaBlendedCursorSupported = (osvi.dwMajorVersion >= 5);
}
_AlphaBlendedCursorSupportRetrieved = true;
}
return _AlphaBlendedCursorSupported;
}
bool VerboseCursorRT12516 = true;
namespace NLMISC
{
extern bool TempMaxVerboseResample;
}
// *************************************************************************************
void CCustomMouse::addCursor(const std::string &name, const NLMISC::CBitmap &cursorBitmap)
{
if (!isAlphaBlendedCursorSupported()) return;
nlassert(cursorBitmap.getWidth() != 0);
nlassert(cursorBitmap.getHeight() != 0);
// find used part base on alpha, to avoid too much shrinking
const CRGBA *pixels = (const CRGBA *) &cursorBitmap.getPixels()[0];
uint minX, maxX, minY, maxY;
uint width = cursorBitmap.getWidth();
uint height = cursorBitmap.getHeight();
//
minX = 0;
for (uint x = 0; x < width; ++x)
{
bool stop = false;
minX = x;
for (uint y = 0; y < height; ++y)
{
if(pixels[x + y * width].A != 0)
{
stop = true;
break;
}
}
if (stop) break;
}
//
maxX = width - 1;
for (sint x = width - 1; x >= 0; --x)
{
bool stop = false;
maxX = (uint) x;
for (uint y = 0; y < height; ++y)
{
if(pixels[x + y * width].A != 0)
{
stop = true;
break;
}
}
if (stop) break;
}
//
minY = 0;
for (uint y = 0; y < height; ++y)
{
bool stop = false;
minY = y;
for (uint x = 0; x < width; ++x)
{
if(pixels[x + y * width].A != 0)
{
stop = true;
break;
}
}
if (stop) break;
}
//
maxY = height - 1;
for (sint y = height - 1; y >= 0; --y)
{
bool stop = false;
maxY = (uint) y;
for (uint x = 0; x < width; ++x)
{
if(pixels[x + y * width].A != 0)
{
stop = true;
break;
}
}
if (stop) break;
}
//
CCursor &curs = _Cursors[name];
curs = CCursor(); // erase possible previous cursor
uint destWidth = GetSystemMetrics(SM_CXCURSOR);
uint destHeight = GetSystemMetrics(SM_CYCURSOR);
// build a square bitmap
uint tmpSize = std::max(maxX - minX + 1, maxY - minY + 1);
curs.Src.resize(tmpSize, tmpSize),
// blit at top left corner
curs.Src.blit(cursorBitmap, minX, minY, maxX - minX + 1, maxY - minY + 1, 0, 0);
curs.OrigHeight = cursorBitmap.getHeight();
curs.HotspotOffsetX = minX;
curs.HotspotOffsetY = minY;
//
curs.HotspotScale = ClientCfg.HardwareCursorScale;
clamp(curs.HotspotScale, 0.f, 1.f);
// first resampling, same for all cursors
tmpSize = (uint) (tmpSize * curs.HotspotScale);
if (tmpSize == 0) tmpSize = 1;
if (VerboseCursorRT12516 && ((name == "curs_stop.tga") || (name == "curs_pick_dup.tga")))
TempMaxVerboseResample = true;
if (TempMaxVerboseResample)
{
try
{
//nldebug("RT12516: BEFORE FIRST RESAMPLE");
//nldebug("RT12516: %s: curs=%p curs.Src=%p curs.Src.PixelPtr=%p", name.c_str(), &curs, &(curs.Src), &curs.Src.getPixels(0)[0]);
//nldebug("RT12516: %s: curs.Src.PixelSize=%u", name.c_str(), curs.Src.getPixels(0).size());
}
catch (...)
{
//nldebug("RT12516: An exception occurred!");
}
}
// TMP for RT 12406
/* nlwarning("Resampling mouse %s cursor : initial size = %d x %d, new size = %d x %d",
name.c_str(),
curs.Src.getWidth(),
curs.Src.getHeight(),
tmpSize,
tmpSize
);*/
curs.Src.resample(tmpSize, tmpSize);
if (TempMaxVerboseResample)
{
try
{
//nldebug("RT12516: AFTER FIRST RESAMPLE");
//nldebug("RT12516: %s: curs=%p curs.Src=%p curs.Src.PixelPtr=%p", name.c_str(), &curs, &(curs.Src), &curs.Src.getPixels(0)[0]);
//nldebug("RT12516: %s: curs.Src.PixelSize=%u", name.c_str(), curs.Src.getPixels(0).size());
}
catch (...)
{
//nldebug("RT12516: An exception occurred!");
}
}
// shrink if necessary
if (tmpSize > destWidth || tmpSize > destHeight) // need to shrink ?
{
// constraint proportions
curs.HotspotScale *= std::min(float(destWidth) / tmpSize, float(destHeight) / tmpSize);
// TMP for RT 12406
/* nlwarning("Resampling mouse %s cursor : initial size = %d x %d, new size = %d x %d",
name.c_str(),
curs.Src.getWidth(),
curs.Src.getHeight(),
destWidth,
destHeight
);*/
curs.Src.resample(destWidth, destHeight);
}
else
{
CBitmap final;
final.resize(destWidth, destHeight);
final.blit(&curs.Src, 0, 0);
curs.Src.swap(final);
}
if (TempMaxVerboseResample)
{
try
{
//nldebug("RT12516: AFTER SECOND RESAMPLE");
//nldebug("RT12516: %s: curs=%p curs.Src=%p curs.Src.PixelPtr=%p", name.c_str(), &curs, &(curs.Src), &curs.Src.getPixels(0)[0]);
//nldebug("RT12516: %s: curs.Src.PixelSize=%u", name.c_str(), curs.Src.getPixels(0).size());
}
catch (...)
{
//nldebug("RT12516: An exception occurred!");
}
}
if (name == _CurrName)
{
updateCursor();
}
TempMaxVerboseResample = false;
}
// *************************************************************************************
void CCustomMouse::release()
{
if (!isAlphaBlendedCursorSupported()) return;
nlassert(Driver);
HWND drvWnd = Driver->getDisplay();
if (drvWnd)
{
SetClassLongPtr(drvWnd, GCLP_HCURSOR, 0);
}
_Cursors.clear();
}
// *************************************************************************************
void CCustomMouse::setColorDepth(TColorDepth colorDepth)
{
if (colorDepth == _ColorDepth) return;
_ColorDepth = colorDepth;
updateCursor(true);
}
// *************************************************************************************
void CCustomMouse::updateCursor(bool forceRebuild)
{
if (!Driver) return;
setCursor(_CurrName, _CurrCol, _CurrRot, _CurrHotSpotX, _CurrHotSpotY, forceRebuild);
}
// *************************************************************************************
void CCustomMouse::setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild)
{
if (!isAlphaBlendedCursorSupported()) return;
_CurrName = name;
_CurrCol = col;
_CurrRot = rot;
_CurrHotSpotX = hotSpotX;
_CurrHotSpotY = hotSpotY;
//
if (rot > 3) rot = 3; // same than 'CViewRenderer::drawRotFlipBitmapTiled
TIconMap::iterator it = _Cursors.find(name);
HCURSOR cursorHandle = _DefaultCursor;
if (it != _Cursors.end())
{
// Update cursor if modified or not already built
CCursor &curs = it->second;
hotSpotX = (sint) (curs.HotspotScale * (hotSpotX - curs.HotspotOffsetX));
hotSpotY = (sint) (curs.HotspotScale * ((curs.OrigHeight - hotSpotY) - curs.HotspotOffsetY));
if (curs.Icon == 0 ||
curs.HotSpotX != hotSpotX ||
curs.HotSpotY != hotSpotY ||
curs.Col != col ||
curs.Rot != rot ||
curs.ColorDepth != _ColorDepth ||
forceRebuild
)
{
if (curs.Icon != 0)
{
DestroyIcon(curs.Icon);
}
curs.Icon = buildCursor(curs.Src, col, rot, hotSpotX, hotSpotY);
curs.Col = col;
curs.Rot = rot;
curs.HotSpotX = hotSpotX;
curs.HotSpotY = hotSpotY;
curs.ColorDepth = _ColorDepth;
}
cursorHandle = curs.Icon ? (HCURSOR) curs.Icon : _DefaultCursor;
}
if (IsSystemCursorInClientArea() || IsSystemCursorCaptured() || forceRebuild)
{
if (CInputHandlerManager::getInstance()->hasFocus())
{
::SetCursor(cursorHandle);
HWND drvWnd = Driver->getDisplay();
if (drvWnd)
{
SetClassLongPtr(drvWnd, GCLP_HCURSOR, (LONG_PTR) cursorHandle); // set default mouse icon to the last one
}
}
}
}
// *************************************************************************************
HICON CCustomMouse::buildCursor(const CBitmap &src, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY)
{
nlassert(isAlphaBlendedCursorSupported());
uint mouseW = GetSystemMetrics(SM_CXCURSOR);
uint mouseH = GetSystemMetrics(SM_CYCURSOR);
nlassert(src.getWidth() == mouseW);
nlassert(src.getHeight() == mouseH);
CBitmap rotSrc = src;
if (rot > 3) rot = 3; // mimic behavior of 'CViewRenderer::drawRotFlipBitmapTiled' (why not rot & 3 ??? ...)
switch(rot)
{
case 0: break;
case 1: rotSrc.rot90CW(); break;
case 2: rotSrc.rot90CW(); rotSrc.rot90CW(); break;
case 3: rotSrc.rot90CCW(); break;
}
return rotSrc.getHICON(mouseW, mouseH, _ColorDepth == ColorDepth16 ? 16:32, col, hotSpotX, hotSpotY, true);
}
// *************************************************************************************
void CCustomMouse::setSystemArrow()
{
extern HINSTANCE HInstance;
HCURSOR arrow = LoadCursor(NULL, IDC_ARROW);
if (IsSystemCursorInClientArea() || IsSystemCursorCaptured())
{
::SetCursor(arrow);
}
HWND drvWnd = Driver->getDisplay();
if (drvWnd)
{
SetClassLongPtr(drvWnd, GCLP_HCURSOR, (LONG_PTR) arrow); // set default mouse icon to the last one
}
}
#else
// not implemented yet for other OS
// *************************************************************************************
CCustomMouse::CCustomMouse()
{
// NOT IMPLEMENTED
}
// *************************************************************************************
void CCustomMouse::setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild)
{
// NOT IMPLEMENTED
}
// *************************************************************************************
void CCustomMouse::release()
{
// NOT IMPLEMENTED
}
// *************************************************************************************
bool CCustomMouse::isAlphaBlendedCursorSupported()
{
return false;
}
// *************************************************************************************
void CCustomMouse::setSystemArrow()
{
//
}
void CCustomMouse::addCursor(const std::string &name, const NLMISC::CBitmap &cursorBitmap)
{
// TODO for Linux
}
// *************************************************************************************
void CCustomMouse::setColorDepth(TColorDepth colorDepth)
{
// TODO for Linux
}
// *************************************************************************************
void CCustomMouse::updateCursor(bool forceRebuild)
{
// TODO for Linux
}
#endif // NL_OS_WINDOWS

@ -1,116 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef RY_CUSTOM_MOUSE_H
#define RY_CUSTOM_MOUSE_H
#ifdef NL_OS_WINDOWS
#include <windows.h>
#endif
#include "nel/misc/rgba.h"
#include "nel/misc/bitmap.h"
#include "nel/misc/common.h"
namespace NL3D
{
class UTexture;
}
// TMP Nico : made a separate class to avoid a lot of compilation until it works
class CCustomMouse
{
public:
enum TColorDepth { ColorDepth16 = 0, ColorDepth32, ColorDepthCount };
CCustomMouse();
/** Signal a change of color depth (of desktop if windowed, or video mode if fullscreen)
* This is necessary to have the cursor built with good format
*/
void setColorDepth(TColorDepth colorDepth);
// Add a new cursor (name is case unsensitive)
void addCursor(const std::string &name, const NLMISC::CBitmap &cursorBitmap);
// Display a cursor from its name (case unsensitive)
void setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild = false);
void updateCursor(bool forceRebuild = false);
void release();
bool isAlphaBlendedCursorSupported();
// reset the cursor shape to the system arrow
void setSystemArrow();
private:
#ifdef NL_OS_WINDOWS
TColorDepth _ColorDepth;
std::string _CurrName;
NLMISC::CRGBA _CurrCol;
uint8 _CurrRot;
uint _CurrHotSpotX;
uint _CurrHotSpotY;
//
class CCursor
{
public:
NLMISC::CBitmap Src;
TColorDepth ColorDepth;
uint OrigHeight;
float HotspotScale;
uint HotspotOffsetX;
uint HotspotOffsetY;
sint HotSpotX;
sint HotSpotY;
HICON Icon;
NLMISC::CRGBA Col;
uint8 Rot;
public:
CCursor();
~CCursor();
CCursor& operator= (const CCursor& from)
{
if (&from == this)
return *this;
Src = from.Src; // requires more than a surface copy
OrigHeight = from.OrigHeight;
HotspotScale = from.HotspotScale;
HotspotOffsetX = from.HotspotOffsetX;
HotspotOffsetY = from.HotspotOffsetY;
HotSpotX = from.HotSpotX;
HotSpotY = from.HotSpotY;
Icon = from.Icon;
Col = from.Col;
Rot = from.Rot;
return *this;
}
};
struct CStrCaseUnsensitiveCmp
{
bool operator()(const std::string &lhs, const std::string &rhs) const
{
return NLMISC::nlstricmp(lhs, rhs) < 0;
}
};
typedef std::map<std::string, CCursor, CStrCaseUnsensitiveCmp> TIconMap;
TIconMap _Cursors;
HCURSOR _DefaultCursor;
bool _AlphaBlendedCursorSupported;
bool _AlphaBlendedCursorSupportRetrieved;
private:
// build a cursor from src, src should have the same size that the hardware cursor
// or a assertion is thrown
HICON buildCursor(const NLMISC::CBitmap &src, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY);
#endif // NL_OS_WINDOWS
};
extern CCustomMouse CustomMouse;
#endif

@ -29,7 +29,6 @@
#include "../actions.h"
#include "../input.h"
#include "../client_cfg.h"
#include "custom_mouse.h"
#include "../motion/user_controls.h"
#include "../init.h"
#include "../release.h"
@ -65,6 +64,7 @@ CInputHandlerManager::CInputHandlerManager()
_MouseButtonsState = noButton;
_MouseX = _MouseY = _MouseLastX = _MouseLastY = 0;
_Focus = true;
// Driver->setFocus(true);
_MouseWheel = 0;
_SkipInterfaceManager=false;
_RecoverFocusLost = false;
@ -141,19 +141,8 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event)
{
HandleSystemCursorCapture(event);
if (event == EventDisplayChangeId)
{
switch (getCurrentColorDepth())
{
case 16: CustomMouse.setColorDepth(CCustomMouse::ColorDepth16); break;
case 24:
case 32: CustomMouse.setColorDepth(CCustomMouse::ColorDepth32); break;
default:
release();
ExitClientError(CI18N::get("uiUnsupportedNewColorDepth").toUtf8().c_str());
break;
}
}
// Process message to InterfaceManager
@ -169,6 +158,7 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event)
_MouseButtonsReleased = noButton;
_MouseButtonsState = noButton;
_Focus = false;
// Driver->setFocus(false);
if (!_SkipInterfaceManager)
{
@ -187,13 +177,14 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event)
}
// be nice with other app : let the mouse reappear (useful in direct 3D mode with no hardware cursor)
Driver->showCursor(true);
CustomMouse.setSystemArrow();
// Driver->setSystemArrow();
}
else
{
_RecoverFocusLost = true; // force to update mouse pos on next click or move
Driver->showCursor(IsMouseCursorHardware());
_Focus = true;
// Driver->setFocus(true);
}
if(!_SkipInterfaceManager)
@ -334,7 +325,6 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event)
_MouseButtonsState = (TMouseButton) (_MouseButtonsState | pEvent->Button);
rIP.setButtonState(_MouseButtonsState);
updateMousePos((CEventMouse&)event, eventDesc);
// handle Event
if(pEvent->Button & leftButton)
@ -359,7 +349,6 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event)
_MouseButtonsState = (TMouseButton) (_MouseButtonsState & ~(pEvent->Button));
rIP.setButtonState(_MouseButtonsState);
updateMousePos((CEventMouse&)event, eventDesc);
// handle Event
if(pEvent->Button & leftButton)
@ -379,7 +368,6 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event)
// TODO: yoyo make it work if needed (for now, seems preferable to manage in each ActionHandler)
CEventMouseDblClk* pEvent=(CEventMouseDblClk*)&event;
updateMousePos((CEventMouse&)event, eventDesc);
// handle Event
if(pEvent->Button & leftButton)
@ -407,8 +395,6 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event)
else
_MouseWheel -= 1;
updateMousePos((CEventMouse&)event, eventDesc);
// handle Event now.
if (_MouseWheel != 0)
{

@ -5718,7 +5718,7 @@ void CInterfaceManager::connectYuboChat()
if(KlientChatPort != 0 && !_YuboChat.connected())
{
// NB: hard code url, to avoid "client.cfg trojan"
// (a client.cfg with an url pointing to a hackcer site, to grab login/password)
// (a client.cfg with an url pointing to a hacker site, to grab login/password)
extern std::string LoginLogin, LoginPassword;
_YuboChat.connect(string("chat.ryzom.com:")+toString(KlientChatPort), LoginLogin, LoginPassword);

@ -19,7 +19,6 @@
#include "stdpch.h"
#include "../input.h"
#include "custom_mouse.h"
//
#include "view_pointer.h"
#include "interface_manager.h"
@ -692,17 +691,17 @@ void CViewPointer::drawCursor(sint32 texId, NLMISC::CRGBA col, uint8 rot)
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CViewRenderer &rVR = pIM->getViewRenderer();
sint32 xPos = _XReal + _OffsetX;
sint32 yPos = _YReal + _OffsetY;
if (!IsMouseCursorHardware())
{
sint32 xPos = _XReal + _OffsetX;
sint32 yPos = _YReal + _OffsetY;
rVR.draw11RotFlipBitmap (_RenderLayer, xPos, yPos, rot, false, texId, col);
}
else
{
// set new cursor for the hardware mouse
std::string name = rVR.getTextureNameFromId(texId);
CustomMouse.setCursor(name, col, rot, (uint32) std::max(getX() - (_XReal + _OffsetX), (sint32) 0), (uint32) std::max(getY() - (_YReal + _OffsetY), (sint32) 0));
Driver->setCursor(name, col, rot, (uint32) std::max(getX() - xPos, (sint32) 0), (uint32) std::max(getY() - yPos, (sint32) 0));
}
}

@ -24,7 +24,6 @@
#include "nel/misc/uv.h"
#include "nel/misc/hierarchical_timer.h"
#include "interface_manager.h"
#include "custom_mouse.h"
#include "../client_cfg.h"
using namespace NLMISC;
@ -730,6 +729,8 @@ void CViewRenderer::loadTextures (const std::string &textureFileName, const std:
_GlobalTextures.push_back (gt);
// Driver->setHardwareCursorScale(ClientCfg.HardwareCursorScale);
char bufTmp[256], tgaName[256];
string sTGAname;
float uvMinU, uvMinV, uvMaxU, uvMaxV;
@ -765,24 +766,22 @@ void CViewRenderer::loadTextures (const std::string &textureFileName, const std:
// Insert in map.
_TextureMap.insert( make_pair(image.Name, textureId) );
}
// if this is a cursor texture, extract it now (supported for rgba only now, because of the blit)
if (CustomMouse.isAlphaBlendedCursorSupported())
if (texDatas && texDatas->getPixelFormat() == CBitmap::RGBA)
{
if (texDatas && texDatas->getPixelFormat() == CBitmap::RGBA)
if (ClientCfg.HardwareCursors.count(image.Name))
{
if (ClientCfg.HardwareCursors.count(image.Name))
uint x0 = (uint) (image.UVMin.U * gt.Width);
uint y0 = (uint) (image.UVMin.V * gt.Height);
uint x1 = (uint) (image.UVMax.U * gt.Width);
uint y1 = (uint) (image.UVMax.V * gt.Height);
if (x1 != x0 && y1 != y0)
{
uint x0 = (uint) (image.UVMin.U * gt.Width);
uint y0 = (uint) (image.UVMin.V * gt.Height);
uint x1 = (uint) (image.UVMax.U * gt.Width);
uint y1 = (uint) (image.UVMax.V * gt.Height);
if (x1 != x0 && y1 != y0)
{
CBitmap curs;
curs.resize(x1 - x0, y1 - y0);
curs.blit(*texDatas, x0, y0, (x1 - x0), (y1 - y0), 0, 0);
CustomMouse.addCursor(image.Name, curs);
}
CBitmap curs;
curs.resize(x1 - x0, y1 - y0);
curs.blit(*texDatas, x0, y0, (x1 - x0), (y1 - y0), 0, 0);
Driver->addCursor(image.Name, curs);
}
}
}

@ -1095,8 +1095,6 @@ void initShardDisplay()
void onlogin(bool vanishScreen = true)
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
// Remove space before and after each string login & password

@ -7366,7 +7366,7 @@ class CAHR2StopLive : public IActionHandler
{
// Now we expect to receive an impulsion FAR_TP to mainland, triggered
// by the DSS. We'll disobey it by FarTPing to the Edition session instead!
nldebug( "Will return to editing session %u", R2::getEditor().getDMC().getEditionModule().getEditSessionLink() );
nldebug( "Will return to editing session %u", R2::getEditor().getDMC().getEditionModule().getEditSessionLink().asInt() );
FarTP.hookNextFarTPForEditor();
}
// otherwise, let accomplish the FAR_TP to mainland (returnToPreviousSession)

@ -71,7 +71,6 @@
#include "interface_v3/music_player.h"
#include "http_client.h"
#include "actions_client.h"
#include "interface_v3/custom_mouse.h"
#include "login_progress_post_thread.h"
//
#include "r2/editor.h"
@ -502,8 +501,6 @@ void releaseOutGame()
// Remove the Actions listener from the Events Server.
EventsListener.removeFromServer(CInputHandlerManager::getInstance()->FilteredEventServer);
CustomMouse.release();
// Release Bloom
CBloomEffect::releaseInstance();
@ -574,8 +571,6 @@ void release()
Driver->deleteTextContext(TextContext);
TextContext = NULL;
CustomMouse.release();
// Release Bloom
CBloomEffect::releaseInstance();

@ -271,7 +271,7 @@ void CView::cameraDistance(float dist)
void CView::changeCameraHeight(bool up, bool down)
{
// If the user is not inside a building.
if(UserEntity->forceIndoorFPV() == false)
if(!UserEntity->forceIndoorFPV())
{
if(up)
{
@ -293,7 +293,7 @@ void CView::changeCameraHeight(bool up, bool down)
void CView::changeCameraDist(bool forward, bool backward)
{
// If the user is not inside a building.
if(UserEntity->forceIndoorFPV() == false)
if(!UserEntity->forceIndoorFPV())
{
if(forward)
decreaseCameraDist();

@ -5704,7 +5704,6 @@ bool CCharacter::onAnimalHungry( uint petIndex, bool justBecameHungry )
// Consume to full satiety (last useful unit is entirely consumed)
animal.Satiety = animal.MaxSatiety;
nbUnits = (sint)ceil(caloriesNeeded / caloriesPerUnit);
}
nbItemsLeftToConsume -= nbUnits;

@ -9,6 +9,10 @@ IF(WIN32)
ADD_SUBDIRECTORY(world_editor)
ENDIF(WIN32)
IF(WITH_QT)
ADD_SUBDIRECTORY(georges_editor_qt)
ENDIF(WITH_QT)
# folders not handled yet.
#georges_convert
#georges_dll

@ -0,0 +1,19 @@
#-----------------------------------------------------------------------------
#
# Georges Editor Qt
# Copyright (C) 2010 Adrian Jäkel <aj at elane2k dot com>
#
#-----------------------------------------------------------------------------
# This tells the application(s) where to find the installed data.
ADD_DEFINITIONS(-DDATA_DIR="\\"${NL_SHARE_PREFIX}/georges_editor_qt/\\"")
ADD_SUBDIRECTORY(src)
INSTALL(DIRECTORY data/
DESTINATION share/georges_editor_qt/data
COMPONENT data
PATTERN "CVS" EXCLUDE
PATTERN ".svn" EXCLUDE
PATTERN "Makefile*" EXCLUDE)

@ -0,0 +1,11 @@
RootConfigFilename = "georges_editor_default.cfg";
SearchPaths = {
"G:/ryzom_assets/ryzom_assets/Stuff/Matis", "G:/ryzom_assets/bnps/characters_shapes"
};
GraphicsDriver = "OpenGL";
BackgroundColor = {
173, 205, 234
};
LeveldesignPath = "D:/Dev/Ryzom/code/ryzom/common/data_leveldesign/leveldesign";
QtWindowState = "%00%00%00%FF%00%00%00%00%FD%00%00%00%03%00%00%00%00%00%00%02%A6%00%00%00%E9%FC%02%00%00%00%01%FB%00%00%00%2A%00C%00G%00e%00o%00r%00g%00e%00s%00D%00i%00r%00T%00r%00e%00e%00D%00i%00a%00l%00o%00g%01%00%00%00%3B%00%00%00%E9%00%00%00t%00%FF%FF%FF%00%00%00%02%00%00%00%00%00%00%00%00%FC%01%00%00%00%01%FB%00%00%00%26%00C%00O%00b%00j%00e%00c%00t%00V%00i%00e%00w%00e%00r%00D%00i%00a%00l%00o%00g%00%00%00%00%00%FF%FF%FF%FF%00%00%00N%00%FF%FF%FF%00%00%00%03%00%00%02%A6%00%00%01c%FC%01%00%00%00%01%FB%00%00%00%22%00C%00G%00e%00o%00r%00g%00e%00s%00L%00o%00g%00D%00i%00a%00l%00o%00g%01%00%00%00%00%00%00%02%A6%00%00%00%5D%00%FF%FF%FF%00%00%00%00%00%00%00%E9%00%00%00%04%00%00%00%04%00%00%00%08%00%00%00%08%FC%00%00%00%01%00%00%00%02%00%00%00%01%FF%FF%FF%FF%01%00%00%00%00%FF%FF%FF%FF%00%00%00%00%00%00%00%00";
QtWindowGeometry = "%01%D9%D0%CB%00%01%00%00%00%00%00%D6%00%00%00%C0%00%00%03%83%00%00%03%82%00%00%00%DA%00%00%00%DE%00%00%03%7F%00%00%03~%00%00%00%00%00%00";

@ -0,0 +1,113 @@
//////////////////////////////////////////////////////////////////////////////
// Config file for Georges Editor Qt ////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// This file is used to setup the georges editor 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" };
LeveldesignPath = "";
// Which extensions to remap to what if needed (pairs of 2)
RemapExtensions = { "png", "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";
// 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 };
SunDirection = { -2.935, +0.107, -1.22 };
SunAmbient = { 190, 170, 150 };
SunDiffuse = { 255, 248, 255 };
SunSpecular = { 255, 255, 255};
//////////////////////////////////////////////////////////////////////////////
// Time //////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
FpsSmoothing = 64;
//////////////////////////////////////////////////////////////////////////////
// Interface /////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// This setting is used to bind keys to actions.
// "key_handler", "args", "***", "Key1|Key2",
// *** -> CTRL, SHIFT, ALT don't matter
// --- -> CTRL, SHIFT, ALT must all be disabled
// -+- -> only SHIFT must be down
KeySettings = {
"screenshot", "", "***", "KeyF5",
"command", "set_state Exit", "-+-", "KeyESCAPE",
"command", "set_state Login", "+--", "KeyESCAPE",
"command", "set_state Unload", "***", "KeyF8",
"command", "set_state Demo", "***", "KeyF7",
"move_forward", "", "***", "KeyUP|KeyZ|KeyW",
"move_backward", "", "***", "KeyDOWN|KeyS",
"move_left", "", "***", "KeyLEFT|KeyQ|KeyA",
"move_right", "", "***", "KeyRIGHT|KeyD",
"move_forward", "", "***", "KeyZ|KeyW",
"move_backward", "", "***", "KeyS",
"move_left", "", "***", "KeyQ|KeyA",
"move_right", "", "***", "KeyD",
"chat_begin", "", "***", "KeyT",
"chat_send", "", "***", "KeyENTER",
"chat_leave", "", "***", "KeyESCAPE",
"display_test", "", "***", "KeyTAB",
"send_action", "0", "---", "Key1",
"send_action", "1", "---", "Key2",
"send_action", "2", "---", "Key3",
"send_action", "3", "---", "Key4",
"send_action", "4", "---", "Key5",
"send_action", "5", "---", "Key6",
"send_action", "6", "---", "Key7",
"send_action", "7", "---", "Key8",
"send_action", "8", "---", "Key9",
"send_action", "9", "---", "Key0",
"demo_crystal_spawn", "", "---", "KeyO",
"demo_crystal_explode", "", "---", "KeyP",
"free_camera_forward", "", "---", "KeyNUMPAD8",
"free_camera_backward", "", "---", "KeyNUMPAD2",
"free_camera_left", "", "---", "KeyNUMPAD4",
"free_camera_right", "", "---", "KeyNUMPAD6",
"switch_camera", "", "---", "KeyF4",
"switch_ui_visible" ,"", "---", "KeyF6",
};
// end of file

@ -0,0 +1,35 @@
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${LIBXML2_INCLUDE_DIR} ${NEL_INCLUDE_DIR} ${QT_INCLUDES})
INCLUDE( ${QT_USE_FILE} )
FILE(GLOB GEORGES_EDITOR_SRC *.cpp)
SET(GEORGES_EDITOR_HDR georges_dirtree_dialog.h georges_treeview_dialog.h main_window.h
objectviewer_dialog.h settings_dialog.h)
SET(GEORGES_EDITOR_UIS settings_form.ui objectviewer_form.ui log_form.ui georges_treeview_form.ui georges_dirtree_form.ui)
SET(GEORGES_EDITOR_RCS georges_editor_qt.qrc)
SET(QT_USE_QTGUI TRUE)
SET(QT_USE_QTOPENGL TRUE)
QT4_ADD_RESOURCES( GEORGES_EDITOR_RC_SRCS ${GEORGES_EDITOR_RCS} )
QT4_WRAP_CPP( GEORGES_EDITOR_MOC_SRCS ${GEORGES_EDITOR_HDR} )
QT4_WRAP_UI( GEORGES_EDITOR_UI_HDRS ${GEORGES_EDITOR_UIS} )
ADD_EXECUTABLE(georges_editor_qt WIN32 ${GEORGES_EDITOR_SRC} ${GEORGES_EDITOR_MOC_SRCS} ${GEORGES_EDITOR_RC_SRCS} ${GEORGES_EDITOR_UI_HDRS})
TARGET_LINK_LIBRARIES(georges_editor_qt
nelmisc
nel3d
nelgeorges
${QT_LIBRARIES}
${QT_QTOPENGL_LIBRARY}
${QT_QTMAIN_LIBRARY})
ADD_DEFINITIONS(-DQT_NO_KEYWORDS ${LIBXML2_DEFINITIONS} ${QT_DEFINITIONS})
NL_DEFAULT_PROPS(georges_editor_qt "Ryzom, Tools, World: Georges Editor Qt")
NL_ADD_RUNTIME_FLAGS(georges_editor_qt)
IF(WITH_PCH)
ADD_NATIVE_PRECOMPILED_HEADER(georges_editor_qt ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.h ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.cpp)
ENDIF(WITH_PCH)
INSTALL(TARGETS georges_editor_qt RUNTIME DESTINATION bin COMPONENT runtime)

@ -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 <nel/misc/types_nl.h>
#include "callback.h"
namespace NLQT {
} /* namespace NLQT */
/* end of 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 */

@ -0,0 +1,242 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "configuration.h"
// STL includes
// Qt includes
#include <QFile>
// 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"
#include <QFile>
using namespace std;
using namespace NLMISC;
namespace NLQT {
CConfiguration::CConfiguration()
{
}
CConfiguration::~CConfiguration()
{
}
void CConfiguration::init()
{
// verify data
nlassert(!ConfigCallbacks.size());
// load config
QFile file(NLQT_CONFIG_FILE);
if (!file.exists()) {
file.open( QIODevice::WriteOnly | QIODevice::Text );
file.write("GraphicsDrivers = { \"OpenGL\", \"Direct3D\" };");
file.write("\nSearchPaths = {\"\"};");
file.write("\nRemapExtensions = { \"png\", \"tga\" };");
file.write("\nBackgroundColor = { 0, 0, 0 };");
file.write("\nQtStyle = \"\";");
file.write("\nQtPalette = \"\";");
file.close();
}
try {
ConfigFile.load(NLQT_CONFIG_FILE);
} catch(...) {
}
// setup config file callback
Modules::config().setCallback("SearchPaths", CConfigCallback(this, &CConfiguration::cfcbSearchPaths));
}
void 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"));
}
std::string CConfiguration::configLeveldesignPath()
{
std::string path = Modules::config().getValue("LeveldesignPath", QString("").toStdString());
cfcbSearchPaths(Modules::config().getConfigFile().getVar("LeveldesignPath"));
return path;
}
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();
//CPath::clearMap();
for (uint i = 0; i < varsize; ++i)
CPath::addSearchPath(var.asString(i), true, false);
}
} /* namespace NLQT */

@ -0,0 +1,92 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "georges_editor.cfg"
namespace NLQT {
typedef CCallback<void, NLMISC::CConfigFile::CVar &> CConfigCallback;
/**
* CConfiguration
* \brief CConfiguration
* \date 2010-02-05 15:44GMT
* \author Jan Boon (Kaetemi)
*/
class CConfiguration
{
public:
CConfiguration();
virtual ~CConfiguration();
void init();
void release();
void updateUtilities();
void configSearchPaths();
std::string configLeveldesignPath();
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

@ -0,0 +1,269 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "entity.h"
// NeL includes
#include <nel/misc/path.h>
#include <nel/3d/u_camera.h>
#include <nel/3d/u_driver.h>
#include <nel/3d/u_text_context.h>
#include <nel/3d/u_instance.h>
#include <nel/3d/u_scene.h>
#include <nel/3d/u_material.h>
#include <nel/3d/u_landscape.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>"),
_Instance(NULL), _Skeleton(NULL),
_PlayList(NULL), _AnimationSet(NULL)
{
}
CEntity::~CEntity(void)
{
}
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();
}
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;
}
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(size_t i = 0; i < NL3D::CChannelMixer::NumAnimationSlot; i++)
_PlayList->setAnimation(i, UPlayList::empty);
}
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);
// 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());
anim = _AnimationSet->getAnimation(id);
// Add start time
startTime = endTime;
endTime = startTime + (anim->getEndTime() - anim->getBeginTime());
}
else
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
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->setWeightSmoothness(0, 1.0f);
_PlayList->setStartWeight(0, 1, 0);
_PlayList->setEndWeight(0, 1, 1);
_PlayList->setWrapMode(0, UPlayList::Clamp);
}
}
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 */

@ -0,0 +1,217 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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
// STL includes
#include <map>
#include <string>
#include <vector>
// NeL includes
#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
Animated object. Allows you to upload animations for the shape.
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 reproduction
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) {}
};
/// Constructor
CEntity(void);
/// 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; }
/// 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 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; }
private:
/// 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();
// The name of the entity
std::string _Name;
SAnimationStatus _AnimationStatus;
// 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

@ -0,0 +1,79 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "filesystem_model.h"
#include <QtGui/QApplication>
#include <QtGui/QStyle>
namespace NLQT
{
CFileSystemModel::CFileSystemModel(QString ldPath, QObject *parent)
: QFileSystemModel(parent),
_ldPath(ldPath)
{
}
CFileSystemModel::~CFileSystemModel()
{
}
QVariant CFileSystemModel::data(const QModelIndex& index, int role) const {
if (role == Qt::DecorationRole)
{
if (_ldPath.isEmpty())
return QVariant();
if (isDir(index))
return QApplication::style()->standardIcon(QStyle::SP_DirIcon);
}
if (_ldPath.isEmpty() && role == Qt::DisplayRole)
{
if (index.parent().isValid())
return QVariant();
return QString("Set a correct leveldesign path ...");
}
return QFileSystemModel::data(index, role);
}
int CFileSystemModel::columnCount(const QModelIndex &/*parent*/) const
{
return 1;
}
int CFileSystemModel::rowCount(const QModelIndex &parent) const
{
if (_ldPath.isEmpty())
{
if(parent.isValid())
{
return 0;
}
else
{
return qMin(QFileSystemModel::rowCount(parent),1);
}
}
return QFileSystemModel::rowCount(parent);
}
} /* namespace NLQT */
/* end of file */

@ -0,0 +1,44 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 FILESYSTEM_MODEL_H
#define FILESYSTEM_MODEL_H
#include <QtGui/QFileSystemModel>
namespace NLQT
{
class CFileSystemModel : public QFileSystemModel
{
QString _ldPath;
public:
CFileSystemModel(QString ldPath, QObject *parent = 0);
~CFileSystemModel();
int columnCount(const QModelIndex &/*parent*/) const;
int rowCount(const QModelIndex &/*parent*/) const;
QVariant data(const QModelIndex& index, int role) const ;
};/* class CFileSystemModel */
} /* namespace NLQT */
#endif // FILESYSTEM_MODEL_H

@ -0,0 +1,302 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "formdelegate.h"
// NeL includes
#include <nel/misc/debug.h>
#include <nel/georges/u_type.h>
#include <nel/georges/u_form_elm.h>
// Qt includes
#include <QSpinBox>
#include <QLineEdit>
#include <QDoubleSpinBox>
#include <QColorDialog>
#include <QComboBox>
#include <QApplication>
#include <QTextDocument>
#include <QAbstractTextDocumentLayout>
#include <QPainter>
// Project includes
#include "georgesform_model.h"
#include "formitem.h"
namespace NLQT
{
FormDelegate::FormDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
QWidget *FormDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem & option ,
const QModelIndex &index) const
{
CFormItem *item = static_cast<CFormItem*>(index.internalPointer());
QString value = item->data(1).toString();
if (value.isEmpty())
return 0;
const NLGEORGES::UType *type = dynamic_cast<const CGeorgesFormModel *>(index.model())->
getItem(index)->getFormElm()->getType();
if(type)
{
int numDefinitions = type->getNumDefinition();
if (numDefinitions)
{
std::string l, v;
QString label,value;
QComboBox *editor = new QComboBox(parent);
for (int i = 0; i < numDefinitions; i++)
{
type->getDefinition(i,l,v);
label = l.c_str();
value = v.c_str();
editor->addItem(label);
}
return editor;
}
else
{
switch (type->getType())
{
case NLGEORGES::UType::UnsignedInt:
case NLGEORGES::UType::SignedInt:
{
QSpinBox *editor = new QSpinBox(parent);
//QString min = QString(type->getMin().c_str());
//QString max = QString(type->getMax().c_str());
//QString inc = QString(type->getIncrement().c_str());
//nldebug(QString("min %1 max %2 inc %3").arg(min).arg(max).arg(inc).toStdString().c_str());
// TODO: use saved min/max values
editor->setMinimum(-99999);
editor->setMaximum(99999);
editor->setSingleStep(1);
return editor;
}
case NLGEORGES::UType::Double:
{
QDoubleSpinBox *editor = new QDoubleSpinBox(parent);
//QString min = QString(type->getMin().c_str());
//QString max = QString(type->getMax().c_str());
//QString inc = QString(type->getIncrement().c_str());
//nldebug(QString("min %1 max %2 inc %3").arg(min).arg(max).arg(inc).toStdString().c_str());
// TODO: use saved min/max values
editor->setMinimum(-99999);
editor->setMaximum(99999);
editor->setSingleStep(0.1);
editor->setDecimals(1);
return editor;
}
case NLGEORGES::UType::Color:
{
return new QColorDialog();
}
default: // UType::String
{
QLineEdit *editor = new QLineEdit(parent);
return editor;
}
}
}
}
return 0;
}
void FormDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
const NLGEORGES::UType *type = dynamic_cast<const CGeorgesFormModel *>(index.model())->
getItem(index)->getFormElm()->getType();
int numDefinitions = type->getNumDefinition();
QString value = index.model()->data(index, Qt::DisplayRole).toString();
if (numDefinitions)
{
QComboBox *cb = static_cast<QComboBox*>(editor);
cb->setCurrentIndex(cb->findText(value));
//cb->setIconSize()
}
else
{
switch (type->getType())
{
case NLGEORGES::UType::UnsignedInt:
case NLGEORGES::UType::SignedInt:
{
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->setValue((int)value.toDouble());
break;
}
case NLGEORGES::UType::Double:
{
QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
spinBox->setValue(value.toDouble());
break;
}
case NLGEORGES::UType::Color:
{
break;
}
default:
{
QLineEdit *textEdit = static_cast<QLineEdit*>(editor);
textEdit->setText(value);
break;
}
}
}
}
void FormDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
const NLGEORGES::UType *type = dynamic_cast<const CGeorgesFormModel *>(index.model())->
getItem(index)->getFormElm()->getType();
int numDefinitions = type->getNumDefinition();
if (numDefinitions)
{
QComboBox *comboBox = static_cast<QComboBox*>(editor);
QString value = comboBox->currentText();
QString oldValue = index.model()->data(index, Qt::DisplayRole).toString();
if (value == oldValue)
{
// nothing's changed
}
else
{
nldebug(QString("setModelData from %1 to %2")
.arg(oldValue).arg(value).toStdString().c_str());
model->setData(index, value, Qt::EditRole);
}
}
else
{
switch (type->getType())
{
case NLGEORGES::UType::UnsignedInt:
case NLGEORGES::UType::SignedInt:
{
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
int value = spinBox->value();
QString oldValue = index.model()->data(index, Qt::DisplayRole).toString();
if (QString("%1").arg(value) == oldValue)
{
// nothing's changed
}
else
{
nldebug(QString("setModelData from %1 to %2")
.arg(oldValue).arg(value).toStdString().c_str());
model->setData(index, value, Qt::EditRole);
}
break;
}
case NLGEORGES::UType::Double:
{
QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
double value = spinBox->value();
QString oldValue = index.model()->data(index, Qt::DisplayRole).toString();
if (QString("%1").arg(value) == oldValue)
{
// nothing's changed
}
else
{
nldebug(QString("setModelData from %1 to %2")
.arg(oldValue).arg(value).toStdString().c_str());
model->setData(index, value, Qt::EditRole);
}
break;
}
case NLGEORGES::UType::Color:
{
break; // TODO
}
default: // UType::String
{
QLineEdit *textEdit = static_cast<QLineEdit*>(editor);
QString value = textEdit->text();
QString oldValue = index.model()->data(index, Qt::DisplayRole).toString();
if (value == oldValue)
{
// nothing's changed
}
else
{
nldebug(QString("setModelData from %1 to %2")
.arg(oldValue).arg(value).toStdString().c_str());
model->setData(index, value, Qt::EditRole);
}
break;
}
}
}
}
void FormDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QRect r = option.rect;
editor->setGeometry(r);
//option.decorationAlignment = QStyleOptionViewItem::Right;
}
void FormDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItemV4 optionV4 = option;
optionV4.decorationPosition = QStyleOptionViewItem::Right;
//optionV4.decorationSize = QSize(32,32);
initStyleOption(&optionV4, index);
QStyledItemDelegate::paint(painter,optionV4,index);
//QStyle *style = optionV4.widget? optionV4.widget->style() : QApplication::style();
//QTextDocument doc;
//doc.setHtml(optionV4.text);
///// Painting item without text
//optionV4.text = QString();
//style->drawControl(QStyle::CE_ItemViewItem, &optionV4, painter);
//QAbstractTextDocumentLayout::PaintContext ctx;
//// Highlighting text if item is selected
//if (optionV4.state & QStyle::State_Selected)
// ctx.palette.setColor(QPalette::Text, optionV4.palette.color(QPalette::Active, QPalette::HighlightedText));
//QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &optionV4);
//painter->save();
//painter->translate(textRect.topLeft());
//painter->setClipRect(textRect.translated(-textRect.topLeft()));
//doc.documentLayout()->draw(painter, ctx);
//painter->restore();
}
} /* namespace NLQT */

@ -0,0 +1,45 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 FORMDELEGATE_H
#define FORMDELEGATE_H
#include <QStyledItemDelegate>
namespace NLQT
{
class FormDelegate : public QStyledItemDelegate
{
public:
FormDelegate(QObject *parent = 0);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const;
void updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &index) const;
void paint ( QPainter * painter, const QStyleOptionViewItem & option,
const QModelIndex & index ) const;
};
}
#endif // FORMDELEGATE_H

@ -0,0 +1,116 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "formitem.h"
// Qt includes
// NeL includes
#include <nel/georges/u_type.h>
namespace NLQT
{
CFormItem::CFormItem(NLGEORGES::UFormElm* elm, const QList<QVariant> &data, CFormItem *parent,
NLGEORGES::UFormElm::TWhereIsValue wV, NLGEORGES::UFormElm::TWhereIsNode wN)
{
parentItem = parent;
itemData = data;
formElm = elm;
whereV = wV;
whereN = wN;
}
CFormItem::~CFormItem()
{
qDeleteAll(childItems);
}
void CFormItem::appendChild(CFormItem *item)
{
childItems.append(item);
}
CFormItem *CFormItem::child(int row)
{
return childItems.value(row);
}
int CFormItem::childCount() const
{
return childItems.count();
}
int CFormItem::columnCount() const
{
return itemData.count();
}
QVariant CFormItem::data(int column) const
{
return itemData.value(column);
}
CFormItem *CFormItem::parent()
{
return parentItem;
}
int CFormItem::row() const
{
if (parentItem)
return parentItem->childItems.indexOf(const_cast<CFormItem*>(this));
return 0;
}
bool CFormItem::setData(int column, const QVariant &value)
{
if (column < 0 || column >= itemData.size())
return false;
itemData[column] = value;
if (formElm->isAtom())
{
const NLGEORGES::UType *type = formElm->getType();
if (type)
{
switch (type->getType())
{
case NLGEORGES::UType::UnsignedInt:
case NLGEORGES::UType::SignedInt:
case NLGEORGES::UType::Double:
case NLGEORGES::UType::String:
nldebug(QString("string %1 %2")
.arg(itemData[0].toString()).arg(value.toString())
.toStdString().c_str());
parentItem->formElm->setValueByName(
value.toString().toStdString().c_str(),itemData[0].toString().toStdString().c_str());
break;
case NLGEORGES::UType::Color:
break;
default:
break;
}
}
}
//formElm->setValueByName();
return true;
}
}

@ -0,0 +1,71 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 FORMITEM_H
#define FORMITEM_H
// NeL includes
#include <nel/georges/u_form_elm.h>
// Qt includes
#include <QList>
#include <QVariant>
namespace NLQT
{
class CFormItem
{
public:
CFormItem(NLGEORGES::UFormElm *elm, const QList<QVariant> &data,
CFormItem *parent = 0,
NLGEORGES::UFormElm::TWhereIsValue = NLGEORGES::UFormElm::ValueForm,
NLGEORGES::UFormElm::TWhereIsNode = NLGEORGES::UFormElm::NodeForm);
~CFormItem();
void appendChild(CFormItem *child);
CFormItem *child(int row);
int childCount() const;
int columnCount() const;
QVariant data(int column) const;
int row() const;
CFormItem *parent();
bool setData(int column, const QVariant &value);
NLGEORGES::UFormElm* getFormElm() {return formElm;}
NLGEORGES::UFormElm::TWhereIsValue valueFrom()
{
return whereV;
}
NLGEORGES::UFormElm::TWhereIsNode nodeFrom()
{
return whereN;
}
private:
QList<CFormItem*> childItems;
QList<QVariant> itemData;
CFormItem *parentItem;
NLGEORGES::UFormElm* formElm;
NLGEORGES::UFormElm::TWhereIsValue whereV;
NLGEORGES::UFormElm::TWhereIsNode whereN;
}; // CFormItem
}
#endif // FORMITEM_H

@ -0,0 +1,51 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "georges.h"
#include "nel/misc/o_xml.h"
// STL includes
// NeL includes
#include <nel/georges/u_form_loader.h>
#include <nel/georges/u_form.h>
// Project includes
using namespace NLGEORGES;
namespace NLQT
{
CGeorges::CGeorges(): FormLoader(0)
{
FormLoader = UFormLoader::createLoader();
}
CGeorges::~CGeorges()
{
}
UForm *CGeorges::loadForm(std::string formName)
{
UForm *form = FormLoader->loadForm(formName.c_str());
return form;
}
} /* namespace NLQT */

@ -0,0 +1,65 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 GEORGES_H
#define GEORGES_H
// Misc
// STL includes
#include <string>
// NeL includes
// Qt includes
// Project includes
namespace NLGEORGES
{
class UForm;
class UFormLoader;
}
using namespace NLGEORGES;
namespace NLQT
{
/**
@class CGeorges
A CGeorges class loading and viewing sheets.
*/
class CGeorges
{
public:
/// Default constructor.
CGeorges();
virtual ~CGeorges();
// Load the given form root
UForm* loadForm(std::string formName);
// A form loader
UFormLoader *FormLoader;
};/* class CGeorges */
} /* namespace NLQT */
#endif // GEORGES_H

@ -0,0 +1,142 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "georges_dirtree_dialog.h"
// Qt includes
#include <QtGui/QWidget>
#include <QSettings>
// NeL includes
// Project includes
#include "modules.h"
using namespace NLMISC;
namespace NLQT
{
CGeorgesDirTreeDialog::CGeorgesDirTreeDialog(QString ldPath, QWidget *parent)
:QDockWidget(parent), _ldPath(ldPath)
{
_ui.setupUi(this);
//QStyleOptionViewItem myButtonOption;
// const QStyleOptionViewItem *buttonOption =
// qstyleoption_cast<const QStyleOptionViewItem *>(_ui.dirTree->style());
/*setStyleSheet(" \
QTreeView { \
alternate-background-color: yellow; \
} \
QTreeView::item { \
border: 1px solid #d9d9d9; \
border-top-color: transparent; \
border-bottom-color: transparent; \
} \
QTreeView::item:hover { \
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1);\
border: 1px solid #bfcde4; \
} \
QTreeView::item:selected { \
border: 1px solid #567dbc; \
} \
QTreeView::item:selected:active{ \
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);\
} \
QTreeView::item:selected:!active { \
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);\
}\
");*/
//QString leveldata = Modules::config().getConfigFile().getVar("SearchPaths").asString().c_str();
_dirModel = new CFileSystemModel(_ldPath);
_ui.dirTree->setModel(_dirModel);
QFileInfo info(_ldPath);
if (!_ldPath.isEmpty() && info.isDir())
{
_dirModel->setRootPath(_ldPath);
_ui.dirTree->setRootIndex(_dirModel->index(_ldPath));
}
else
{
_dirModel->setRootPath(QDir::currentPath());
}
_ui.dirTree->setAnimated(false);
_ui.dirTree->setIndentation(20);
//_ui.dirTree->setSortingEnabled(true);
/*connect(_ui.dirTree, SIGNAL(clicked(QModelIndex)),
this, SLOT(fileSelected(QModelIndex)));*/
connect(_ui.dirTree, SIGNAL(activated(QModelIndex)),
this, SLOT(fileSelected(QModelIndex)));
}
CGeorgesDirTreeDialog::~CGeorgesDirTreeDialog()
{
delete _dirModel;
}
void CGeorgesDirTreeDialog::fileSelected(QModelIndex index)
{
QString name;
if (index.isValid() && !_dirModel->isDir(index))
{
Q_EMIT selectedForm(_dirModel->fileName(index));
}
}
void CGeorgesDirTreeDialog::changeFile(QString file)
{
QModelIndex index = _dirModel->index(file);
//_dirModel->;
_ui.dirTree->selectionModel()->select(index,QItemSelectionModel::ClearAndSelect);
_ui.dirTree->scrollTo(index,QAbstractItemView::PositionAtCenter);
fileSelected(index);
}
void CGeorgesDirTreeDialog::ldPathChanged(QString path)
{
_ldPath = path;
QFileInfo info(_ldPath);
delete _dirModel;
if (!_ldPath.isEmpty() && info.isDir())
{
_dirModel = new CFileSystemModel(_ldPath);
_ui.dirTree->setModel(_dirModel);
_dirModel->setRootPath(_ldPath);
_ui.dirTree->setRootIndex(_dirModel->index(_ldPath));
}
else
{
_dirModel = new CFileSystemModel("");
_ui.dirTree->setModel(_dirModel);
_dirModel->setRootPath(QDir::currentPath());
_ldPath = "";
}
}
} /* namespace NLQT */

@ -0,0 +1,65 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 GEORGES_DIRTREE_DIALOG_H
#define GEORGES_DIRTREE_DIALOG_H
// Qt includes
#include <QtGui/QWidget>
// STL includes
// NeL includes
// Project includes
#include "ui_georges_dirtree_form.h"
#include "filesystem_model.h"
namespace NLQT
{
class CGeorgesDirTreeDialog: public QDockWidget
{
Q_OBJECT
public:
CGeorgesDirTreeDialog(QString ldPath, QWidget *parent = 0);
~CGeorgesDirTreeDialog();
private:
Ui::CGeorgesDirTreeDialog _ui;
CFileSystemModel *_dirModel;
QString _ldPath;
Q_SIGNALS:
void selectedForm(QString);
public Q_SLOTS:
void ldPathChanged(QString path);
private Q_SLOTS:
void fileSelected(QModelIndex index);
void changeFile(QString file);
friend class CMainWindow;
}; /* CGEorgesDirTreeDialog */
} /* namespace NLQT */
#endif // GEORGES_DIRTREE_DIALOG_H

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CGeorgesDirTreeDialog</class>
<widget class="QDockWidget" name="CGeorgesDirTreeDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>111</height>
</size>
</property>
<property name="windowTitle">
<string>Dir Tree</string>
</property>
<widget class="QWidget" name="dockWidgetContents">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTreeView" name="dirTree">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

@ -0,0 +1,13 @@
<RCC>
<qresource>
<file>images/nel.png</file>
<file>images/open-file.png</file>
<file>images/go-down.png</file>
<file>images/go-up.png</file>
<file>images/list-add.png</file>
<file>images/list-remove.png</file>
<file>images/preferences.png</file>
<file>images/pqrticles.png</file>
<file>images/khead.png</file>
</qresource>
</RCC>

@ -0,0 +1,316 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "georges_treeview_dialog.h"
// Qt includes
#include <QtGui/QWidget>
#include <QSettings>
// NeL includes
#include <nel/georges/u_form.h>
#include <nel/misc/path.h>
#include <nel/misc/file.h>
#include <nel/misc/o_xml.h>
// Project includes
#include "modules.h"
#include "georgesform_model.h"
#include "georgesform_proxy_model.h"
#include "formitem.h"
#include "formdelegate.h"
using namespace NLMISC;
using namespace NLGEORGES;
namespace NLQT
{
CGeorgesTreeViewDialog::CGeorgesTreeViewDialog(QWidget *parent /*= 0*/, bool emptyView /*= false*/)
: QDockWidget(parent)
{
loadedForm = "";
_modified = false;
_ui.setupUi(this);
_ui.treeViewTabWidget->setTabEnabled (2,false);
if (emptyView)
{
_ui.treeViewTabWidget->clear();
setWindowTitle("Form Area");
}
_ui.checkBoxParent->setStyleSheet("background-color: rgba(0,255,0,30)");
_ui.checkBoxDefaults->setStyleSheet("background-color: rgba(255,0,0,30)");
_form = 0;
FormDelegate *formdelegate = new FormDelegate(this);
_ui.treeView->setItemDelegateForColumn(1, formdelegate);
connect(_ui.treeView, SIGNAL(doubleClicked (QModelIndex)),
this, SLOT(doubleClicked (QModelIndex)));
connect(_ui.checkBoxParent, SIGNAL(stateChanged(int)),
this, SLOT(showParentRows (int)));
}
CGeorgesTreeViewDialog::~CGeorgesTreeViewDialog()
{
delete _ui.treeView->itemDelegateForColumn(1);
deleteLater();
//QSettings settings("RyzomCore", "GeorgesQt");
//settings.setValue("dirViewGeometry", saveGeometry());
}
void CGeorgesTreeViewDialog::selectedForm(QString formName)
{
_form = Modules::georges().loadForm(formName.toStdString());
if (_form)
{
UFormElm *root = 0;
root = &_form->getRootNode();
QStringList parents;
for (uint i = 0; i < _form->getNumParent(); i++)
{
UForm *u = _form->getParentForm(i);
parents << u->getFilename().c_str();
}
QString comments;
comments = _form->getComment().c_str();
if (!comments.isEmpty())
{
_ui.treeViewTabWidget->setTabEnabled (1,true);
_ui.commentEdit->setPlainText(comments);
}
QStringList strList;
std::set<std::string> dependencies;
_form->getDependencies(dependencies);
QMap< QString, QStringList> deps;
Q_FOREACH(std::string str, dependencies)
{
QString file = str.c_str();
if (file == formName) continue;
deps[file.remove(0,file.indexOf(".")+1)] << str.c_str();
}
nlinfo("typ's %d",deps["typ"].count());
nlinfo("dfn's %d",deps["dfn"].count());
//nlwarning(strList.join(";").toStdString().c_str());
if (root)
{
loadedForm = formName;
CGeorgesFormModel *model = new CGeorgesFormModel(root,deps,comments,parents);
CGeorgesFormProxyModel *proxyModel = new CGeorgesFormProxyModel();
proxyModel->setSourceModel(model);
_ui.treeView->setModel(proxyModel);
_ui.treeView->expandAll();
_ui.treeView->resizeColumnToContents(0);
_ui.treeView->resizeColumnToContents(1);
_ui.treeView->resizeColumnToContents(2);
_ui.treeView->hideColumn(3);
showParentRows(_ui.checkBoxParent->isChecked());
//_ui.treeView->setRowHidden(0,QModelIndex(),true);
connect(model, SIGNAL(dataChanged(const QModelIndex, const QModelIndex)),
this, SLOT(modifiedFile()));
Modules::mainWin().setWindowTitle("Qt Georges Editor - " + formName);
//Modules::mainWin().getTabBar();
}
}
}
void CGeorgesTreeViewDialog::modifiedFile( )
{
if (!_modified)
{
_modified = true;
setWindowTitle(windowTitle()+"*");
Modules::mainWin().setWindowTitle(Modules::mainWin().windowTitle()+"*");
Q_EMIT modified(_modified);
}
}
void CGeorgesTreeViewDialog::write( )
{
COFile file;
std::string s = CPath::lookup(loadedForm.toStdString());
if (file.open (s))
{
try
{
if (loadedForm.contains(".typ"))
{
//nlassert (Type != NULL);
//// Write the file
//// Modified ?
//if (IsModified ())
//{
// Type->Header.MinorVersion++;
// flushValueChange ();
//}
//Type->write (xmlStream.getDocument (), theApp.Georges4CVS);
//modify (NULL, NULL, false);
//flushValueChange ();
//UpdateAllViews (NULL);
//return TRUE;
}
else if (loadedForm.contains(".dfn"))
{
//nlassert (Dfn != NULL);
//// Write the file
//if (IsModified ())
//{
// Dfn->Header.MinorVersion++;
// flushValueChange ();
//}
//Dfn->write (xmlStream.getDocument (), lpszPathName, theApp.Georges4CVS);
//modify (NULL, NULL, false);
//UpdateAllViews (NULL);
//return TRUE;
}
else
{
nlassert (_form != NULL);
// Write the file
/*if (IsModified ())
{
((CForm*)(UForm*)Form)->Header.MinorVersion++;
}*/
//((CForm*)(UForm*)Form)->write (xmlStream.getDocument (), lpszPathName, theApp.Georges4CVS);
_form->write(file, false);
setWindowTitle(windowTitle().remove("*"));
_modified = false;
//if (strcmp (xmlStream.getErrorString (), "") != 0)
//{
// char message[512];
// smprintf (message, 512, "Error while saving file: %s", xmlStream.getErrorString ());
//theApp.outputError (message);
//}
//modify (NULL, NULL, false);
//flushValueChange ();
//UpdateAllViews (NULL);
// Get the left view
//CView* pView = getLeftView ();
}
}
catch (Exception &e)
{
nlerror("Error while loading file: %s", e.what());
}
}
else
{ //if (!file.open())
nlerror("Can't open the file %s for writing.", s.c_str());
}
}
void CGeorgesTreeViewDialog::doubleClicked ( const QModelIndex & index )
{
if (index.column() == 1)
return;
CFormItem *item = static_cast<CFormItem*>(index.internalPointer());
QString value = item->data(1).toString();
QString path = CPath::lookup(value.toStdString(),false).c_str();
if (!path.isEmpty() && !path.contains(".shape"))
Q_EMIT changeFile(path);
if (path.contains(".shape"))
{
Modules::objView().resetScene();
Modules::config().configRemapExtensions();
Modules::objView().loadMesh(path.toStdString(),"");
}
int i = 0;
}
void CGeorgesTreeViewDialog::closeEvent(QCloseEvent *event)
{
if (Modules::mainWin().getEmptyView() == this)
{
event->ignore();
}
else
{
Modules::mainWin().getTreeViewList().removeOne(this);
if(!Modules::mainWin().getTreeViewList().size())
{
Modules::mainWin().createEmptyView();
}
deleteLater();
}
}
void CGeorgesTreeViewDialog::showParentRows(int newState)
{
CGeorgesFormProxyModel * mp = dynamic_cast<CGeorgesFormProxyModel *>(_ui.treeView->model());
CGeorgesFormModel *m = dynamic_cast<CGeorgesFormModel *>(mp->sourceModel());
for (int i = 0; i < m->rowCount(); i++)
{
const QModelIndex in = m->index(i,0);
if (m->getItem(in)->nodeFrom() == UFormElm::NodeParentForm)
{
if (newState == Qt::Checked)
{
_ui.treeView->setRowHidden(in.row(),in.parent(),false);
}
else
{
_ui.treeView->setRowHidden(in.row(),in.parent(),true);
}
}
else
{ // search childs // recursive?
for (int j = 0; j < m->rowCount(in); j++)
{
const QModelIndex in2 = m->index(j,0,in);
if (m->getItem(in2)->nodeFrom() == UFormElm::NodeParentForm)
{
if (newState == Qt::Checked)
{
_ui.treeView->setRowHidden(in2.row(),in,false);
}
else
{
_ui.treeView->setRowHidden(in2.row(),in,true);
}
}
}
} // end of search childs
}
}
} /* namespace NLQT */

@ -0,0 +1,81 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 GEORGES_TREEVIEWER_DIALOG_H
#define GEORGES_TREEVIEWER_DIALOG_H
#include "ui_georges_treeview_form.h"
// Qt includes
#include <QtGui/QDockWidget>
// STL includes
// NeL includes
// Project includes
namespace NLGEORGES
{
class UForm;
}
using namespace NLGEORGES;
namespace NLQT
{
class CGeorgesTreeViewDialog: public QDockWidget
{
Q_OBJECT
public:
CGeorgesTreeViewDialog(QWidget *parent = 0, bool empty = false);
~CGeorgesTreeViewDialog();
bool modified() {return _modified;}
void setModified(bool m) {_modified = m;}
void write ( );
QString loadedForm;
protected:
void closeEvent(QCloseEvent *event);
Q_SIGNALS:
void changeFile(QString);
void modified(bool);
public Q_SLOTS:
void selectedForm(QString);
private Q_SLOTS:
void doubleClicked ( const QModelIndex & index );
void modifiedFile( );
void showParentRows(int);
private:
Ui::CGeorgesTreeViewDialog _ui;
UForm *_form;
bool _modified;
}; /* CGeorgesTreeViewDialog */
} /* namespace NLQT */
#endif // GEORGES_TREEVIEWER_DIALOG_H

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CGeorgesTreeViewDialog</class>
<widget class="QDockWidget" name="CGeorgesTreeViewDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>241</width>
<height>236</height>
</size>
</property>
<property name="windowTitle">
<string/>
</property>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTabWidget" name="treeViewTabWidget">
<property name="tabPosition">
<enum>QTabWidget::West</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="form_tab">
<attribute name="title">
<string>Form</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0" colspan="4">
<widget class="QTreeView" name="treeView">
<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>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBoxParent">
<property name="text">
<string>Parent</string>
</property>
</widget>
</item>
<item row="1" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkBoxDefaults">
<property name="text">
<string>Defaults</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="comment_tab">
<attribute name="title">
<string>Comment</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QPlainTextEdit" name="commentEdit">
<property name="readOnly">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="log_tab">
<attribute name="title">
<string>Log</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QPlainTextEdit" name="logEdit"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

@ -0,0 +1,479 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "georgesform_model.h"
// NeL includes
#include <nel/misc/types_nl.h>
#include <nel/misc/rgba.h>
#include <nel/misc/path.h>
#include <nel/georges/u_form_elm.h>
#include <nel/georges/u_type.h>
#include <nel/georges/u_form_dfn.h>
// Qt includes
#include <QColor>
#include <QBrush>
#include <QApplication>
#include <QStyle>
#include <QDebug>
// project includes
#include "formitem.h"
using namespace NLGEORGES;
namespace NLQT
{
CGeorgesFormModel::CGeorgesFormModel(UFormElm *rootElm, QMap< QString, QStringList> deps,
QString comment, QStringList parents, QObject *parent) : QAbstractItemModel(parent)
{
QList<QVariant> rootData;
rootData << "Value" << "Data" << "Extra" << "Type";
_rootElm = rootElm;
_rootItem = new CFormItem(_rootElm, rootData);
_dependencies = deps;
_comments = comment;
_parents = parents;
_parentRows = new QList<const QModelIndex*>;
setupModelData();
}
CGeorgesFormModel::~CGeorgesFormModel()
{
delete _rootItem;
}
/******************************************************************************/
QVariant CGeorgesFormModel::data(const QModelIndex &p_index, int p_role) const
{
if (!p_index.isValid())
return QVariant();
switch (p_role)
{
case Qt::DisplayRole:
{
return getItem(p_index)->data(p_index.column());
}
case Qt::BackgroundRole:
{
if (getItem(p_index)->valueFrom() == UFormElm::ValueDefaultDfn)
return QBrush(QColor(255,0,0,30));
if (getItem(p_index)->nodeFrom() == UFormElm::NodeParentForm)
return QBrush(QColor(0,255,0,30));
return QVariant();
}
case Qt::DecorationRole:
{
if (p_index.column() == 2)
{
//p_index.
QModelIndex in = index(p_index.row(),p_index.column()-1,p_index.parent());
CFormItem *item = getItem(in);
QString value = item->data(1).toString();
//QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str();
if (value.contains(".shape"))
{
return QIcon(":/images/pqrticles.png");
}
else if(value.contains(".tga") || value.contains(".png"))
{
qDebug() << p_index << p_role;
QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str();
return QIcon(":/images/pqrticles.png");
}
}
return QVariant();
break;
}
default:
return QVariant();
}
}
/******************************************************************************/
CFormItem *CGeorgesFormModel::getItem(const QModelIndex &index) const
{
if (index.isValid())
{
CFormItem *item = static_cast<CFormItem*>(index.internalPointer());
if (item)
return item;
}
return _rootItem;
}
/******************************************************************************/
bool CGeorgesFormModel::setData(const QModelIndex &index, const QVariant &value,
int role)
{
if (role != Qt::EditRole)
return false;
CFormItem *item = getItem(index);
bool result = item->setData(index.column(), value);
if (result)
Q_EMIT dataChanged(index, index);
return result;
}
/******************************************************************************/
Qt::ItemFlags CGeorgesFormModel::flags(const QModelIndex& index) const {
if (!index.isValid())
return 0;
Qt::ItemFlags returnValue = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
if(index.column() == 1)
returnValue |= Qt::ItemIsEditable;
return returnValue;
}
/******************************************************************************/
QVariant CGeorgesFormModel::headerData(int section,
Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
return _rootItem->data(section);
return QVariant();
}
/******************************************************************************/
QModelIndex CGeorgesFormModel::index(int row, int column, const QModelIndex &parent)
const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
CFormItem *parentItem;
if (!parent.isValid())
parentItem = _rootItem;
else
parentItem = static_cast<CFormItem*>(parent.internalPointer());
CFormItem *childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
else
return QModelIndex();
}
/******************************************************************************/
QModelIndex CGeorgesFormModel::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
CFormItem *childItem = static_cast<CFormItem*>(index.internalPointer());
CFormItem *parentItem = childItem->parent();
if (parentItem == _rootItem)
return QModelIndex();
return createIndex(parentItem->row(), 0, parentItem);
}
/******************************************************************************/
int CGeorgesFormModel::rowCount(const QModelIndex &parent) const {
CFormItem *parentItem;
if (parent.column() > 0)
return 0;
if (!parent.isValid())
parentItem = _rootItem;
else
parentItem = static_cast<CFormItem*>(parent.internalPointer());
return parentItem->childCount();
}
/******************************************************************************/
int CGeorgesFormModel::columnCount(const QModelIndex &parent) const {
if (parent.isValid())
return static_cast<CFormItem*>(parent.internalPointer())->columnCount();
else
return _rootItem->columnCount();
}
/******************************************************************************/
void CGeorgesFormModel::loadFormData(UFormElm *root, CFormItem *parent) {
if (!root)
return;
uint num = 0;
UFormElm::TWhereIsNode *whereN = new UFormElm::TWhereIsNode;
UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue;
if (root->isStruct())
{
//((CFormElm*)root)->getForm()->getComment();
uint structSize = 0;
root->getStructSize(structSize);
while (num < structSize)
{
// Append a new item to the current parent's list of children.
std::string elmName;
if(root->getStructNodeName(num, elmName))
{
QList<QVariant> columnData;
//QVariant value;
std::string value;
//NLMISC::CRGBA value_color;
//uint value_uint;
//sint value_sint;
//double value_double;
QString elmtType = "";
UFormElm *elmt = 0;
if(root->getNodeByName(&elmt, elmName.c_str(), whereN, true))
{
if (elmt)
{
if (elmt->isArray())
elmtType = "Array";
if (elmt->isStruct())
elmtType = "Struct";
if (elmt->isAtom()) {
elmtType = "Atom";
uint numDefinitions = 0;
const UType *type = elmt->getType();
if (type)
{
numDefinitions = type->getNumDefinition();
root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV);
switch (type->getType())
{
case UType::UnsignedInt:
value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString();
elmtType.append("_uint");break;
case UType::SignedInt:
value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString();
elmtType.append("_sint");break;
case UType::Double:
value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble(),0,'f',1).toStdString();
elmtType.append("_double");break;
case UType::String:
elmtType.append("_string");break;
case UType::Color:
elmtType.append("_color");break;
default:
elmtType.append("_unknownType");
}
}
if (numDefinitions)
{
std::string l, v;
QString tmpLabel, tmpValue;
for (uint i = 0; i < numDefinitions; i++)
{
type->getDefinition(i,l,v);
tmpLabel = l.c_str();
tmpValue = v.c_str();
if (type->getType() == UType::SignedInt)
{
if (QString("%1").arg(value.c_str()).toDouble() == tmpValue.toDouble()) {
value = l;
break;
}
}
if (type->getType() == UType::String)
{
if (QString(value.c_str()) == tmpValue)
{
value = l;
break;
}
}
}
}
}
if (elmt->isVirtualStruct())
{
root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV);
elmtType = "VirtualStruct";
}
switch (*whereN)
{
case UFormElm::NodeForm:
elmtType.append("_fromForm"); break;
case UFormElm::NodeParentForm:
elmtType.append("_fromParentForm"); break;
case UFormElm::NodeDfn:
elmtType.append("_isDFN"); break;
case UFormElm::NodeType:
elmtType.append("_isType"); break;
default:
elmtType.append("_noNode");
}
switch (*whereV)
{
case UFormElm::ValueForm:
elmtType.append("_formValue"); break;
case UFormElm::ValueParentForm:
elmtType.append("_parentValue"); break;
case UFormElm::ValueDefaultDfn:
elmtType.append("_dfnValue"); break;
case UFormElm::ValueDefaultType:
elmtType.append("_typeValue"); break;
default:
elmtType.append("_noValue");
}
columnData << QString(elmName.c_str()) << QString(value.c_str()) << "" << elmtType;
parent->appendChild(new CFormItem(elmt, columnData, parent, *whereV, *whereN));
//if (parents.last()->childCount() > 0) {
// parents << parents.last()->child(parents.last()->childCount()-1);
//}
loadFormData(elmt, parent->child(parent->childCount()-1));
}
else
{
// add Defaults
//columnData << QString(elmName.c_str()) << QString("default") << QString("default");
//parent->appendChild(new CFormItem(elmt, columnData, parent, UFormElm::ValueDefaultDfn, UFormElm::NodeDfn));
}
}
}
num++;
}
}
if (root->isArray())
{
uint arraySize = 0;
root->getArraySize(arraySize);
while (num < arraySize)
{
std::string elmName;
if(root->getArrayNodeName(elmName, num))
{
QList<QVariant> columnData;
std::string value;
QString elmtType = "";
//root->getValueByName(value, elmName.c_str());
UFormElm *elmt = 0;
if(root->getArrayNode(&elmt,0) && elmt)
{
if (elmt->isArray())
elmtType = "Array";
if (elmt->isStruct()) {
elmtType = "Struct";
}
if (elmt->isAtom())
{
elmt->getValue(value);
elmtType = "Atom";
}
if (elmt->isVirtualStruct())
elmtType = "VirtualStruct";
columnData << QString(elmName.c_str()) << QString(value.c_str()) << "" << elmtType;
parent->appendChild(new CFormItem(elmt, columnData, parent));
loadFormData(elmt, parent->child(parent->childCount()-1));
}
}
num++;
}
}
}
/******************************************************************************/
void CGeorgesFormModel::loadFormHeader()
{
CFormItem *fi_pars = new CFormItem(_rootElm, QList<QVariant>() << "parents", _rootItem);
_rootItem->appendChild(fi_pars);
Q_FOREACH(QString str, _parents)
{
fi_pars->appendChild(new CFormItem(_rootElm, QList<QVariant>() << str, fi_pars));
}
/*QStringList dfns = _dependencies["dfn"];
QStringList typs = _dependencies["typ"];
_dependencies.remove("dfn");
_dependencies.remove("typ");
CFormItem *fi_dep = new CFormItem(_rootElm, QList<QVariant>() << "dependencies", _rootItem);
_rootItem->appendChild(fi_dep);
if (!dfns.isEmpty()) {
CFormItem *fi_dfn = new CFormItem(_rootElm, QList<QVariant>() << "dfn", fi_dep);
fi_dep->appendChild(fi_dfn);
foreach(QString str, dfns) {
fi_dfn->appendChild(new CFormItem(_rootElm, QList<QVariant>() << str, fi_dfn));
}
}
if (!typs.isEmpty()) {
CFormItem *fi_typ = new CFormItem(_rootElm, QList<QVariant>() << "typ", fi_dep);
fi_dep->appendChild(fi_typ);
foreach(QString str, typs) {
fi_typ->appendChild(new CFormItem(_rootElm, QList<QVariant>() << str, fi_typ));
}
}
if (!_dependencies.isEmpty()) {
CFormItem *fi_other = new CFormItem(_rootElm, QList<QVariant>() << "other", fi_dep);
fi_dep->appendChild(fi_other);
foreach(QStringList list, _dependencies) {
foreach(QString str, list) {
fi_other->appendChild(new CFormItem(_rootElm, QList<QVariant>() << str, fi_other));
}
}
}*/
}
/******************************************************************************/
void CGeorgesFormModel::setupModelData()
{
loadFormHeader();
loadFormData(_rootElm, _rootItem);
}
} /* namespace NLQT */
/* end of file */

@ -0,0 +1,75 @@
/*
Georges Viewer Qt
Copyright (C) 2010 Adrian Jaekel
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 GEORGESFORM_MODEL_H
#define GEORGESFORM_MODEL_H
// Qt includes
#include <QAbstractItemModel>
#include <QModelIndex>
#include <QStringList>
#include <QVariant>
// project includes
namespace NLGEORGES {
class UFormElm;
}
namespace NLQT
{
class CFormItem;
class CGeorgesFormModel : public QAbstractItemModel
{
public:
CGeorgesFormModel(NLGEORGES::UFormElm *root, QMap< QString, QStringList> deps,
QString comment, QStringList parents, QObject *parent = 0);
~CGeorgesFormModel();
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &index) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
CFormItem *getItem(const QModelIndex &index) const;
CGeorgesFormModel *model() { return this; }
private:
void setupModelData();
void loadFormData(NLGEORGES::UFormElm *rootElm, CFormItem *parent);
void loadFormHeader();
CFormItem* _rootItem;
NLGEORGES::UFormElm* _rootElm;
QMap< QString, QStringList> _dependencies;
QString _comments;
QStringList _parents;
QList<const QModelIndex*>* _parentRows;
};/* class CGeorgesFormModel */
} /* namespace NLQT */
#endif // GEORGESFORM_MODEL_H

@ -0,0 +1,57 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "georgesform_proxy_model.h"
// NeL includes
#include <nel/misc/debug.h>
namespace NLQT
{
bool CGeorgesFormProxyModel::filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const
{
nlinfo("CGeorgesFormProxyModel::filterAcceptsRow");
//QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
//QModelIndex index1 = sourceModel()->index(sourceRow, 1, sourceParent);
//QModelIndex index2 = sourceModel()->index(sourceRow, 2, sourceParent);
//return (sourceModel()->data(index0).toString().contains(filterRegExp())
// || sourceModel()->data(index1).toString().contains(filterRegExp()))
// && dateInRange(sourceModel()->data(index2).toDate());
// if (getItem(p_index)->valueFrom() == UFormElm::ValueDefaultDfn)
// return QBrush(QColor(255,0,0,30));
// if (getItem(p_index)->nodeFrom() == UFormElm::NodeParentForm)
// return QBrush(QColor(0,255,0,30));
// return QVariant();
return true;
}
/******************************************************************************/
bool CGeorgesFormProxyModel::filterAcceptsColumn(int sourceRow,
const QModelIndex &sourceParent) const
{
nlinfo("CGeorgesFormProxyModel::filterAcceptsColumn");
return QSortFilterProxyModel::filterAcceptsColumn(sourceRow, sourceParent);
}
} /* namespace NLQT */
/* end of file */

@ -0,0 +1,48 @@
/*
Georges Viewer Qt
Copyright (C) 2010 Adrian Jaekel
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 GEORGESFORM_PROXY_MODEL_H
#define GEORGESFORM_PROXY_MODEL_H
// Qt includes
#include <QSortFilterProxyModel>
namespace NLQT
{
class CGeorgesFormProxyModel : public QSortFilterProxyModel
{
public:
CGeorgesFormProxyModel(QObject *parent = 0): QSortFilterProxyModel(parent)
{
}
~CGeorgesFormProxyModel()
{
}
protected:
virtual bool filterAcceptsColumn ( int source_column, const QModelIndex & source_parent ) const ;
virtual bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const ;
};/* class CGeorgesFormProxyModel */
} /* namespace NLQT */
#endif // GEORGESFORM_PROXY_MODEL_H

@ -0,0 +1,3 @@
[Dolphin]
ShowPreview=true
Timestamp=2010,6,13,17,20,25

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@ -0,0 +1,61 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "log_dialog.h"
// Qt includes
#include <QtGui/QWidget>
#include <QFile>
#include <QDateTime>
#include <QTextStream>
// NeL includes
// Project includes
#include "qt_displayer.h"
namespace NLQT
{
CGeorgesLogDialog::CGeorgesLogDialog(QWidget *parent):
QDockWidget(parent)
{
_ui.setupUi(this);
_displayer = new CQtDisplayer(_ui.plainTextEdit);
NLMISC::ErrorLog->addDisplayer(_displayer);
NLMISC::WarningLog->addDisplayer(_displayer);
NLMISC::DebugLog->addDisplayer(_displayer);
NLMISC::AssertLog->addDisplayer(_displayer);
NLMISC::InfoLog->addDisplayer(_displayer);
}
CGeorgesLogDialog::~CGeorgesLogDialog()
{
NLMISC::ErrorLog->removeDisplayer(_displayer);
NLMISC::WarningLog->removeDisplayer(_displayer);
NLMISC::DebugLog->removeDisplayer(_displayer);
NLMISC::AssertLog->removeDisplayer(_displayer);
NLMISC::InfoLog->removeDisplayer(_displayer);
delete _displayer;
}
} /* namespace NLQT */

@ -0,0 +1,54 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 LOG_DIALOG_H
#define LOG_DIALOG_H
// Qt includes
#include <QtGui/QWidget>
// STL includes
// NeL includes
#include <nel/misc/types_nl.h>
// Project includes
#include "ui_log_form.h"
namespace NLQT
{
class CQtDisplayer;
class CGeorgesLogDialog: public QDockWidget
{
public:
CGeorgesLogDialog(QWidget *parent = 0);
~CGeorgesLogDialog();
private:
Ui::CGeorgesLogDialog _ui;
CQtDisplayer *_displayer;
friend class CMainWindow;
}; /* CGeorgesLogDialog */
} /* namespace NLQT */
#endif // LOG_DIALOG_H

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CGeorgesLogDialog</class>
<widget class="QDockWidget" name="CGeorgesLogDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>472</width>
<height>310</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>89</width>
<height>122</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>524287</width>
<height>524287</height>
</size>
</property>
<property name="windowTitle">
<string>Log</string>
</property>
<widget class="QWidget" name="dockWidgetContents">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPlainTextEdit" name="plainTextEdit"/>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

@ -0,0 +1,120 @@
#include <nel/misc/types_nl.h>
#include <nel/misc/app_context.h>
// Qt includes
#include <QtGui/QApplication>
#include <QFile>
#include <QDateTime>
#include <QTextStream>
// NeL includes
#include <nel/misc/debug.h>
#include <nel/misc/common.h>
#include <nel/misc/file.h>
#include <nel/misc/path.h>
#include <nel/misc/command.h>
// Project includes
#include "modules.h"
// nel_qt log file name
#define NLQT_LOG_FILE "nel_qt.log"
// clear nel_qt log before use
#define NLQT_ERASE_LOG true
#if !defined (NLQT_USE_LOG_LOG)
# define NLQT_USE_LOG_LOG true
#endif
#if !defined (NLQT_USE_LOG)
# define NLQT_USE_LOG 1
#endif
using namespace std;
using namespace NLMISC;
namespace NLQT
{
namespace
{
CFileDisplayer *s_FileDisplayer = NULL;
} /* anonymous namespace */
} /* namespace NLQT */
void messageHandler(QtMsgType p_type, const char* p_msg)
{
fprintf(stderr, "%s\n", p_msg);
QFile file("qt.log");
file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text);
QChar code;
switch (p_type)
{
case QtDebugMsg: code = 'D'; break;
case QtWarningMsg: code = 'W'; break;
case QtCriticalMsg: code = 'C'; break;
case QtFatalMsg: code = 'F'; break;
}
QString dt = QDateTime::currentDateTime().toString("yyyyMMdd hh:mm:ss");
QTextStream(&file) << QString("%1 [%2] %3\n").arg(dt).arg(code).arg(QString(p_msg));
}
#ifndef DATA_DIR
# define DATA_DIR "."
#endif
#ifdef NL_OS_WINDOWS
# ifdef _UNICODE
# define tstring wstring
# else
# define tstring string
# endif
#endif
sint main(int argc, char **argv)
{
// go nel!
{
// use log.log if NEL_LOG_IN_FILE and NLQT_USE_LOG_LOG defined as 1
createDebug(NULL, NLQT_USE_LOG_LOG, false);
if (QFile::exists("qt.log"))
QFile::remove("qt.log");
qInstallMsgHandler(messageHandler);
#if NLQT_USE_LOG
// create toverhex_client.log
// filedisplayer only deletes the 001 etc
if (NLQT_ERASE_LOG && CFile::isExists(NLQT_LOG_FILE))
CFile::deleteFile(NLQT_LOG_FILE);
// initialize the log file
NLQT::s_FileDisplayer = new CFileDisplayer();
NLQT::s_FileDisplayer->setParam(NLQT_LOG_FILE, NLQT_ERASE_LOG);
DebugLog->addDisplayer(NLQT::s_FileDisplayer);
InfoLog->addDisplayer(NLQT::s_FileDisplayer);
WarningLog->addDisplayer(NLQT::s_FileDisplayer);
AssertLog->addDisplayer(NLQT::s_FileDisplayer);
ErrorLog->addDisplayer(NLQT::s_FileDisplayer);
#endif
nlinfo("Welcome to NeL!");
NLMISC::CPath::remapExtension("tga", "png", true);
}
QApplication app(argc, argv);
Modules::init();
//Modules::mainWin().resize(800,600);
Modules::mainWin().show();
int result = app.exec();
Modules::release();
return result;
}

@ -0,0 +1,508 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "main_window.h"
// STL includes
// Qt includes
#include <QtGui/QtGui>
// NeL includes
// Project includes
#include "modules.h"
#include "settings_dialog.h"
#include "log_dialog.h"
#include "objectviewer_dialog.h"
#include "georges_dirtree_dialog.h"
#include "georges_treeview_dialog.h"
using namespace std;
using namespace NLMISC;
namespace NLQT
{
CMainWindow::CMainWindow(QWidget *parent)
: QMainWindow(parent), _GeorgesLogDialog(0), _ObjectViewerDialog(0),
_GeorgesDirTreeDialog(0)
{
setWindowTitle("Qt Georges Editor");
setDockNestingEnabled(true);
setCentralWidget(0);
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
// create log dock widget
_GeorgesLogDialog = new CGeorgesLogDialog(this);
addDockWidget(Qt::RightDockWidgetArea, _GeorgesLogDialog);
// empty form view as placeholder
createEmptyView();
_currentView = 0;
// load and set leveldesign path from config
QString ldPath = Modules::config().configLeveldesignPath().c_str();
QFileInfo info(ldPath);
if (!info.isDir())
ldPath = "";
// create georges dir dock widget
_GeorgesDirTreeDialog = new CGeorgesDirTreeDialog(ldPath, this);
addDockWidget(Qt::LeftDockWidgetArea, _GeorgesDirTreeDialog);
if (ldPath == "")
{
if (QMessageBox::information(this, tr("Missing leveldesign path"),
tr("Your leveldesign path seems to be empty or incorrect.\nDo you want to set it now?"),
QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok)
{
settings();
}
}
// create NeL viewport dock widget
_ObjectViewerDialog = new CObjectViewerDialog(this);
//_ObjectViewerDialog->setAllowedAreas(Qt::LeftDockWidgetArea );
//_ObjectViewerDialog->hide();
addDockWidget(Qt::LeftDockWidgetArea, _ObjectViewerDialog);
createActions();
createMenus();
createToolBars();
createStatusBar();
//_ObjectViewerDialog->toggleViewAction()->trigger();
QSettings settings("georges_editor_qt.ini", QSettings::IniFormat);
settings.beginGroup("WindowSettings");
restoreState(settings.value("QtWindowState").toByteArray());
restoreGeometry(settings.value("QtWindowGeometry").toByteArray());
settings.endGroup();
// setup Qt style and palette from config file
//_originalPalette = QApplication::palette();
//Modules::config().setAndCallback("QtStyle", CConfigCallback(this, &CMainWindow::cfcbQtStyle));
//Modules::config().setAndCallback("QtPalette", CConfigCallback(this, &CMainWindow::cfcbQtPalette));
setWindowIcon(QIcon(":/images/khead.png"));
_statusBarTimer = new QTimer(this);
connect(_statusBarTimer, SIGNAL(timeout()), this, SLOT(updateStatusBar()));
_statusBarTimer->start(5000);
connect(_GeorgesDirTreeDialog, SIGNAL(selectedForm(QString)),
this, SLOT(openTreeView(QString)));
}
CMainWindow::~CMainWindow()
{
// save state & geometry of window and widgets
QSettings settings("georges_editor_qt.ini", QSettings::IniFormat);
settings.beginGroup("WindowSettings");
settings.setValue("QtWindowState", saveState());
settings.setValue("QtWindowGeometry", saveGeometry());
settings.endGroup();
//Modules::config().dropCallback("QtPalette");
//Modules::config().dropCallback("QtStyle");
_statusBarTimer->stop();
delete _ObjectViewerDialog;
delete _GeorgesDirTreeDialog;
delete _GeorgesLogDialog;
}
void CMainWindow::openTreeView(QString file)
{
// create or/and raise tree view dock widget for current file
setCurrentFile(file);
CGeorgesTreeViewDialog *newView = 0;
Q_FOREACH(CGeorgesTreeViewDialog* dlg, _treeViewList)
{
if (dlg->loadedForm == file)
newView = dlg;
}
if (!newView)
{
newView = new CGeorgesTreeViewDialog(this);
//newView->setAllowedAreas(Qt::TopDockWidgetArea | Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
newView->setWindowTitle(file);
if (_treeViewList.isEmpty())
{
_emptyView->deleteLater();
addDockWidget(Qt::TopDockWidgetArea, newView);
}
else
{
tabifyDockWidget(_treeViewList.first(),newView);
QTabBar* tb = Modules::mainWin().getTabBar();
if (tb)
{
disconnect(tb, SIGNAL(currentChanged ( int ) ),
this,SLOT(tabChanged(int)));
connect(tb, SIGNAL(currentChanged ( int ) ),
this,SLOT(tabChanged(int)));
}
}
_treeViewList.append(newView);
newView->selectedForm(file);
_currentView = newView;
connect(newView, SIGNAL(changeFile(QString)),
_GeorgesDirTreeDialog, SLOT(changeFile(QString)));
connect(newView, SIGNAL(modified(bool)),
_saveAction, SLOT(setEnabled(bool)));
}
newView->raise();
}
void CMainWindow::settings()
{
CSettingsDialog _settingsDialog(this);
connect(&_settingsDialog,SIGNAL(ldPathChanged(QString)),
_GeorgesDirTreeDialog,SLOT(ldPathChanged(QString)));
//_settingsDialog.show();
_settingsDialog.exec();
}
void CMainWindow::about()
{
QMessageBox::about(this, tr("About Georges Viewer Qt"),
tr("<h2>Georges Viewer Qt</h2>"
"Author: aquiles<br>Credits:Thx to dnk-88 for parts of his code"));
}
void CMainWindow::updateStatusBar()
{
//if (_isGraphicsInitialized)
// statusBar()->showMessage(QString(Modules::objView().getDriver()->getVideocardInformation()));
}
void CMainWindow::open()
{
/*QStringList fileNames = QFileDialog::getOpenFileNames(this,
tr("Open NeL data file"), _lastDir,
tr("All NeL files (*.shape *.ps);;"
"NeL shape files (*.shape);;"
"NeL particle system files (*.ps)"));
setCursor(Qt::WaitCursor);
if (!fileNames.isEmpty())
{
QStringList list = fileNames;
QStringList::Iterator it = list.begin();
_lastDir = QFileInfo(*it).absolutePath();
QString skelFileName = QFileDialog::getOpenFileName(this,
tr("Open skeleton file"), _lastDir,
tr("NeL skeleton file (*.skel)"));
while(it != list.end())
{
loadFile(*it, skelFileName);
++it;
}
_AnimationSetDialog->updateListObject();
_AnimationSetDialog->updateListAnim();
_SlotManagerDialog->updateUiSlots();
}
setCursor(Qt::ArrowCursor);*/
}
void CMainWindow::save()
{
if(!_currentView)
return;
setCursor(Qt::WaitCursor);
_currentView->write();
setWindowTitle(windowTitle().remove("*"));
_saveAction->setEnabled(false);
setCursor(Qt::ArrowCursor);
}
void CMainWindow::create()
{
}
void CMainWindow::createEmptyView()
{
_emptyView = new CGeorgesTreeViewDialog(this, true);
//_emptyView->setAllowedAreas(Qt::TopDockWidgetArea);
addDockWidget(Qt::TopDockWidgetArea,_emptyView);
}
void CMainWindow::createActions()
{
_openAction = new QAction(tr("&Open..."), this);
_openAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_DialogOpenButton));
_openAction->setShortcut(QKeySequence::Open);
_openAction->setStatusTip(tr("Open an existing file"));
connect(_openAction, SIGNAL(triggered()), this, SLOT(open()));
_createAction = new QAction(tr("&New..."), this);
_createAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_FileDialogNewFolder));
_createAction->setShortcut(QKeySequence::New);
_createAction->setStatusTip(tr("Create a new file"));
connect(_createAction, SIGNAL(triggered()), this, SLOT(create()));
_saveAction = new QAction(tr("&Save..."), this);
_saveAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_DialogSaveButton));
_saveAction->setShortcut(QKeySequence::Save);
_saveAction->setStatusTip(tr("Saves the current file"));
_saveAction->setDisabled(true);
connect(_saveAction, SIGNAL(triggered()), this, SLOT(save()));
_exitAction = new QAction(tr("E&xit"), this);
_exitAction->setShortcut(QKeySequence::Close);
_exitAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_DialogCloseButton));
_exitAction->setStatusTip(tr("Exit the application"));
connect(_exitAction, SIGNAL(triggered()), this, SLOT(close()));
_setBackColorAction = _ObjectViewerDialog->createSetBackgroundColor(this);
_setBackColorAction->setText(tr("Set &background color"));
_setBackColorAction->setStatusTip(tr("Set background color"));
_settingsAction = new QAction(tr("&Settings"), this);
_settingsAction->setIcon(QIcon(":/images/preferences.png"));
_settingsAction->setStatusTip(tr("Settings"));
connect(_settingsAction, SIGNAL(triggered()), this, SLOT(settings()));
_aboutAction = new QAction(tr("&About"), this);
_aboutAction->setStatusTip(tr("Show the application's About box"));
connect(_aboutAction, SIGNAL(triggered()), this, SLOT(about()));
_aboutQtAction = new QAction(tr("About &Qt"), this);
_aboutQtAction->setStatusTip(tr("Show the Qt library's About box"));
connect(_aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
for (int i = 0; i < MaxRecentFiles; ++i) {
recentFileActs[i] = new QAction(this);
recentFileActs[i]->setVisible(false);
connect(recentFileActs[i], SIGNAL(triggered()),
this, SLOT(openRecentFile()));
}
}
void CMainWindow::createMenus()
{
_fileMenu = menuBar()->addMenu(tr("&File"));
_fileMenu->addAction(_createAction);
_fileMenu->addAction(_openAction);
_fileMenu->addAction(_saveAction);
_separatorAction = _fileMenu->addSeparator();
for (int i = 0; i < MaxRecentFiles; ++i)
_fileMenu->addAction(recentFileActs[i]);
_fileMenu->addSeparator();
_fileMenu->addAction(_exitAction);
updateRecentFileActions();
_viewMenu = menuBar()->addMenu(tr("&View"));
_viewMenu->addAction(_setBackColorAction);
if (_GeorgesDirTreeDialog)
_viewMenu->addAction(_GeorgesDirTreeDialog->toggleViewAction());
_toolsMenu = menuBar()->addMenu(tr("&Tools"));
if (_ObjectViewerDialog)
{
_toolsMenu->addAction(_ObjectViewerDialog->toggleViewAction());
_ObjectViewerDialog->toggleViewAction()->setIcon(QIcon(":/images/pqrticles.png"));
}
_toolsMenu->addSeparator();
_toolsMenu->addAction(_settingsAction);
menuBar()->addSeparator();
_helpMenu = menuBar()->addMenu(tr("&Help"));
_helpMenu->addAction(_aboutAction);
_helpMenu->addAction(_aboutQtAction);
}
void CMainWindow::createToolBars()
{
_fileToolBar = addToolBar(tr("&File"));
_fileToolBar->addAction(_createAction);
_fileToolBar->addAction(_openAction);
_fileToolBar->addAction(_saveAction);
_toolsBar = addToolBar(tr("&Tools"));
if (_ObjectViewerDialog)
_toolsBar->addAction(_ObjectViewerDialog->toggleViewAction());
}
void CMainWindow::createStatusBar()
{
statusBar()->showMessage(tr("StatusReady"));
}
void CMainWindow::cfcbQtStyle(NLMISC::CConfigFile::CVar &var)
{
QApplication::setStyle(QStyleFactory::create(var.asString().c_str()));
}
void CMainWindow::cfcbQtPalette(NLMISC::CConfigFile::CVar &var)
{
if (var.asBool())
QApplication::setPalette(QApplication::style()->standardPalette());
else
QApplication::setPalette(_originalPalette);
}
QTabBar* CMainWindow::getTabBar()
{
// get the QTabBar
QList<QTabBar *> tabList = findChildren<QTabBar *>();
//tabList = _mainWindow->findChildren<QTabBar *>();
//nlinfo(QString("%1 %2").arg(QString::number((int)this,16)).
// arg(QString::number((int)_mainWindow,16)).
// toStdString().c_str());
QTabBar *tb = 0;
Q_FOREACH(QTabBar *tabBar, tabList)
{
if (tabBar->parent() != this)
continue;
//nlinfo(QString("%1 %2 %3 %4").arg(tabBar->objectName()).
// arg(QString::number((int)tabBar,16)).
// arg(QString::number((int)tabBar->parentWidget(),16)).
// arg(QString::number((int)tabBar->parent(),16)).
// toStdString().c_str());
for (int i = 0; i < tabBar->count(); i++)
{
QString currentTab = tabBar->tabText(i);
//nlinfo(currentTab.toStdString().c_str());
}
tb = tabBar;
}
return tb;
}
void CMainWindow::tabChanged(int index)
{
if (index == -1)
{
setWindowTitle("Qt Georges Editor");
return;
}
QTabBar *tb = getTabBar();
//nlinfo(QString("%1").arg(index).toStdString().c_str());
Q_FOREACH(CGeorgesTreeViewDialog* dlg, _treeViewList)
{
if (dlg->windowTitle() == tb->tabText(index))
{
//nlinfo(QString("%1 modified %2").arg(tb->tabText(index)).
// arg(dlg->modified()).
// toStdString().c_str());
_currentView = dlg;
setWindowTitle("Qt Georges Editor - " + tb->tabText(index));
_saveAction->setEnabled(dlg->modified());
}
}
}
void CMainWindow::openRecentFile()
{
QAction *action = qobject_cast<QAction *>(sender());
if (action)
loadFile(action->data().toString());
}
void CMainWindow::setCurrentFile(const QString &fileName)
{
//curFile = fileName;
//setWindowFilePath(curFile);
QSettings settings("georges_editor_qt.ini", QSettings::IniFormat);
settings.beginGroup("RecentFileList");
QStringList files = settings.value("List").toStringList();
settings.endGroup();
files.removeAll(fileName);
files.prepend(fileName);
while (files.size() > MaxRecentFiles)
files.removeLast();
settings.beginGroup("RecentFileList");
settings.setValue("List",files);
settings.endGroup();
Q_FOREACH (QWidget *widget, QApplication::topLevelWidgets())
{
CMainWindow *mainWin = qobject_cast<CMainWindow *>(widget);
if (mainWin)
mainWin->updateRecentFileActions();
}
}
void CMainWindow::updateRecentFileActions()
{
QSettings settings("georges_editor_qt.ini", QSettings::IniFormat);
settings.beginGroup("RecentFileList");
QStringList files = settings.value("List").toStringList();
settings.endGroup();
int numRecentFiles = qMin(files.size(), (int)MaxRecentFiles);
for (int i = 0; i < numRecentFiles; ++i)
{
QString text = tr("&%1 %2").arg(i + 1).arg(QFileInfo(files[i]).fileName());
recentFileActs[i]->setText(text);
recentFileActs[i]->setData(files[i]);
recentFileActs[i]->setVisible(true);
}
for (int j = numRecentFiles; j < MaxRecentFiles; ++j)
recentFileActs[j]->setVisible(false);
_separatorAction->setVisible(numRecentFiles > 0);
}
void CMainWindow::loadFile(const QString &fileName)
{
/*QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("Recent Files"),
tr("Cannot read file %1:\n%2.")
.arg(fileName)
.arg(file.errorString()));
return;
}
QTextStream in(&file);
QApplication::setOverrideCursor(Qt::WaitCursor);
textEdit->setPlainText(in.readAll());
QApplication::restoreOverrideCursor();*/
openTreeView(fileName);
setCurrentFile(fileName);
//statusBar()->showMessage(tr("File loaded"), 2000);
}
} /* namespace NLQT */
/* end of file */

@ -0,0 +1,123 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 MAIN_WINDOW_H
#define MAIN_WINDOW_H
#include <nel/misc/types_nl.h>
// STL includes
// Qt includes
#include <QtGui/QMainWindow>
#include <QPlainTextEdit>
// NeL includes
#include <nel/misc/config_file.h>
// Project includes
namespace NLMISC
{
class CConfigFile;
}
namespace NLQT
{
class CGeorgesLogDialog;
class CObjectViewerDialog;
class CGeorgesDirTreeDialog;
class CGeorgesTreeViewDialog;
class CMainWindow : public QMainWindow
{
Q_OBJECT
public:
CMainWindow(QWidget *parent = 0);
~CMainWindow();
CGeorgesTreeViewDialog* getEmptyView() { return _emptyView;}
QList<CGeorgesTreeViewDialog*>& getTreeViewList() { return _treeViewList; }
QTabBar* getTabBar();
void createEmptyView();
private Q_SLOTS:
void open();
void create();
void save();
void settings();
void about();
void updateStatusBar();
void openTreeView(QString);
void tabChanged(int);
void openRecentFile();
private:
void createActions();
void createMenus();
void createToolBars();
void createStatusBar();
void createDialogs();
void loadFile(const QString &fileName);
void updateRecentFileActions();
void setCurrentFile(const QString &fileName);
void cfcbQtStyle(NLMISC::CConfigFile::CVar &var);
void cfcbQtPalette(NLMISC::CConfigFile::CVar &var);
CGeorgesLogDialog *_GeorgesLogDialog;
CObjectViewerDialog *_ObjectViewerDialog;
CGeorgesDirTreeDialog *_GeorgesDirTreeDialog;
QList<CGeorgesTreeViewDialog*> _treeViewList;
CGeorgesTreeViewDialog *_emptyView;
CGeorgesTreeViewDialog *_currentView;
QPalette _originalPalette;
QTimer *_statusBarTimer;
QMenu *_fileMenu;
QMenu *_viewMenu;
QMenu *_toolsMenu;
QMenu *_helpMenu;
QToolBar *_fileToolBar;
QToolBar *_editToolBar;
QToolBar *_toolsBar;
QAction *_openAction;
QAction *_createAction;
QAction *_saveAction;
QAction *_exitAction;
QAction *_setBackColorAction;
QAction *_settingsAction;
QAction *_aboutAction;
QAction *_aboutQtAction;
QAction *_separatorAction;
enum { MaxRecentFiles = 5 };
QAction *recentFileActs[MaxRecentFiles];
};/* class CMainWindow */
} /* namespace NLQT */
#endif // MAIN_WINDOW_H

@ -0,0 +1,44 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "modules.h"
NLQT::CConfiguration *Modules::_configuration = NULL;
NLQT::CObjectViewer *Modules::_objectViewer = NULL;
NLQT::CGeorges *Modules::_georges = NULL;
NLQT::CMainWindow *Modules::_mainWindow = NULL;
void Modules::init()
{
if (_configuration == NULL) _configuration = new NLQT::CConfiguration;
config().init();
if (_objectViewer == NULL) _objectViewer = new NLQT::CObjectViewer;
if (_georges == NULL) _georges = new NLQT::CGeorges;
if (_mainWindow == NULL) _mainWindow = new NLQT::CMainWindow;
}
void Modules::release()
{
delete _mainWindow; _mainWindow = NULL;
delete _objectViewer; _objectViewer = NULL;
delete _georges; _georges = NULL;
config().release();
delete _configuration; _configuration = NULL;
}

@ -0,0 +1,44 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 MODULES_H
#define MODULES_H
#include "configuration.h"
#include "object_viewer.h"
#include "main_window.h"
#include "georges.h"
class Modules
{
public:
static void init();
static void release();
static NLQT::CConfiguration &config() { return *_configuration; }
static NLQT::CObjectViewer &objView() { return *_objectViewer; }
static NLQT::CGeorges &georges() { return *_georges;}
static NLQT::CMainWindow &mainWin() { return *_mainWindow; }
private:
static NLQT::CConfiguration *_configuration;
static NLQT::CObjectViewer *_objectViewer;
static NLQT::CMainWindow *_mainWindow;
static NLQT::CGeorges *_georges;
};
#endif // MODULES_H

@ -0,0 +1,412 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 "object_viewer.h"
// STL includes
// NeL includes
#include <nel/misc/common.h>
#include <nel/misc/debug.h>
#include <nel/misc/file.h>
#include <nel/misc/bitmap.h>
#include <nel/misc/path.h>
#include <nel/3d/u_driver.h>
#include <nel/3d/u_text_context.h>
#include <nel/3d/u_scene.h>
#include <nel/3d/u_light.h>
#include <nel/3d/u_camera.h>
#include <nel/3d/u_instance.h>
#include <nel/3d/u_skeleton.h>
#include <nel/3d/u_play_list.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_3d_mouse_listener.h>
#include <nel/3d/event_mouse_listener.h>
// Project includes
#include "modules.h"
#include "configuration.h"
using namespace std;
using namespace NLMISC;
using namespace NL3D;
namespace NLQT
{
CObjectViewer::CObjectViewer()
: _Driver(NULL),
_phi(0), _psi(0),_dist(20),
_CurrentInstance("")
{
}
CObjectViewer::~CObjectViewer()
{
}
void CObjectViewer::reinit(nlWindow wnd, uint16 w, uint16 h)
{
nldebug("CObjectViewert::reinit");
//release();
//init(wnd, w, h);
_Driver->setDisplay(wnd, NL3D::UDriver::CMode(w, h, 32));
}
void CObjectViewer::init(nlWindow wnd, uint16 w, uint16 h)
{
//H_AUTO2
nldebug("CObjectViewer::init");
// load and set remap extensions from config
//Modules::config().configRemapExtensions();
// load and set search paths from config
//Modules::config().configSearchPaths();
// set background color from config
Modules::config().setAndCallback("BackgroundColor", CConfigCallback(this, &CObjectViewer::cfcbBackgroundColor));
// set graphics driver from config
Modules::config().setAndCallback("GraphicsDriver",CConfigCallback(this,&CObjectViewer::cfcbGraphicsDriver));
// create the driver
nlassert(!_Driver);
_Driver = UDriver::createDriver(NULL, _Direct3D, NULL);
nlassert(_Driver);
// initialize the window with config file values
_Driver->setDisplay(wnd, NL3D::UDriver::CMode(w, h, 32));
_Light = ULight::createLight();
// set mode of the light
_Light->setMode(ULight::DirectionalLight);
// set position of the light
_Light->setPosition(CVector(-20.f, 30.f, 10.f));
// white light
_Light->setAmbiant(CRGBA(255, 255, 255));
// set and enable the light
_Driver->setLight(0, *_Light);
_Driver->enableLight(0);
// Create a scene
_Scene = _Driver->createScene(true);
_PlayListManager = _Scene->createPlayListManager();
_Scene->enableLightingSystem(true);
// create the camera
UCamera camera = _Scene->getCam();
camera.setTransformMode (UTransformable::DirectMatrix);
setSizeViewport(w, h);
// camera will look at entities
updateCamera(0,0,0);
NLMISC::CVector hotSpot=NLMISC::CVector(0,0,0);
_MouseListener = _Driver->create3dMouseListener();
_MouseListener->setMatrix(Modules::objView().getScene()->getCam().getMatrix());
_MouseListener->setFrustrum(Modules::objView().getScene()->getCam().getFrustum());
_MouseListener->setHotSpot(hotSpot);
_MouseListener->setMouseMode(U3dMouseListener::edit3d);
}
void CObjectViewer::release()
{
//H_AUTO2
nldebug("CObjectViewer::release");
Modules::config().dropCallback("BackgroundColor");
Modules::config().dropCallback("GraphicsDriver");
_Driver->delete3dMouseListener(_MouseListener);
// delete all entities
deleteEntities();
_Scene->deletePlayListManager(_PlayListManager);
// delete the scene
_Driver->deleteScene(_Scene);
// delete the light
delete _Light;
// release driver
nlassert(_Driver);
_Driver->release();
delete _Driver;
_Driver = NULL;
}
void CObjectViewer::updateInput()
{
_Driver->EventServer.pump();
// New matrix from camera
_Scene->getCam().setTransformMode(NL3D::UTransformable::DirectMatrix);
_Scene->getCam().setMatrix (_MouseListener->getViewMatrix());
}
void CObjectViewer::renderDriver()
{
_Driver->clearBuffers(_BackgroundColor);
}
void CObjectViewer::renderScene()
{
// render the scene
_Scene->render();
}
void CObjectViewer::renderDebug2D()
{
}
void CObjectViewer::saveScreenshot(const std::string &nameFile, bool jpg, bool png, bool tga)
{
//H_AUTO2
// FIXME: create screenshot path if it doesn't exist!
// empty bitmap
CBitmap bitmap;
// copy the driver buffer to the bitmap
_Driver->getBuffer(bitmap);
// create the file name
string filename = std::string("./") + nameFile;
// write the bitmap as a jpg, png or tga to the file
if (jpg)
{
string newfilename = CFile::findNewFile(filename + ".jpg");
COFile outputFile(newfilename);
bitmap.writeJPG(outputFile, 100);
nlinfo("Screenshot '%s' saved", newfilename.c_str());
}
if (png)
{
string newfilename = CFile::findNewFile(filename + ".png");
COFile outputFile(newfilename);
bitmap.writePNG(outputFile, 24);
nlinfo("Screenshot '%s' saved", newfilename.c_str());
}
if (tga)
{
string newfilename = CFile::findNewFile(filename + ".tga");
COFile outputFile(newfilename);
bitmap.writeTGA(outputFile, 24, false);
nlinfo("Screenshot '%s' saved", newfilename.c_str());
}
}
bool CObjectViewer::loadMesh(const std::string &meshFileName, const std::string &skelFileName)
{
CPath::addSearchPath(CFile::getPath(meshFileName), false, false);
// create instance of the mesh character
UInstance Entity = _Scene->createInstance(meshFileName);
USkeleton Skeleton = _Scene->createSkeleton(skelFileName);
// if we can't create entity, skip it
if (Entity.empty()) return false;
// create a new entity
EIT eit = (_Entities.insert (make_pair (CFile::getFilenameWithoutExtension(meshFileName), CEntity()))).first;
CEntity &entity = (*eit).second;
// set the entity up
entity._Name = CFile::getFilenameWithoutExtension(meshFileName);
entity._Instance = Entity;
if (!Skeleton.empty())
{
entity._Skeleton = Skeleton;
entity._Skeleton.bindSkin (entity._Instance);
}
entity._AnimationSet = _Driver->createAnimationSet(false);
entity._PlayList = _PlayListManager->createPlayList(entity._AnimationSet);
return true;
}
void CObjectViewer::resetScene()
{
deleteEntities();
// Reset camera.
//..
// to load files with the same name but located in different directories
//CPath::clearMap();
// load and set search paths from config
//Modules::config().configSearchPaths();
_CurrentInstance = "";
nlinfo("Scene cleared");
}
void CObjectViewer::updateCamera(float deltaPsi, float deltaPhi, float deltaDist)
{
_phi += deltaPhi;
_psi += deltaPsi;
_dist += deltaDist;
if(_phi < -NLMISC::Pi/2) _phi -= deltaPhi;
if(_phi > NLMISC::Pi/2) _phi -= deltaPsi;
if (_dist < 1) _dist = 1;
NLMISC::CQuat q0,q1,q2;
NLMISC::CVector up(0,0,1);
NLMISC::CVector v(0,0,1);
q0.setAngleAxis(v,_psi);
v = NLMISC::CVector(0,1,0);
q1.setAngleAxis(v,_phi);
q2 = q0 * q1;
NLMISC::CMatrix m0;
m0.setRot(q2);
NLMISC::CVector camera = m0 * NLMISC::CVector(_dist,0,0);
_Scene->getCam().lookAt(camera, up);
}
void CObjectViewer::setBackgroundColor(NLMISC::CRGBA backgroundColor)
{
_BackgroundColor = backgroundColor;
// config file variable changes
Modules::config().getConfigFile().getVar("BackgroundColor").setAsInt(_BackgroundColor.R, 0);
Modules::config().getConfigFile().getVar("BackgroundColor").setAsInt(_BackgroundColor.G, 1);
Modules::config().getConfigFile().getVar("BackgroundColor").setAsInt(_BackgroundColor.B, 2);
}
void CObjectViewer::setGraphicsDriver(bool Direct3D)
{
_Direct3D = Direct3D;
if (_Direct3D) Modules::config().getConfigFile().getVar("GraphicsDriver").setAsString("Direct3D");
else Modules::config().getConfigFile().getVar("GraphicsDriver").setAsString("OpenGL");
}
void CObjectViewer::setSizeViewport(uint16 w, uint16 h)
{
_Scene->getCam().setPerspective((float)Pi/2.f, (float)w/h, 0.1f, 1000);
}
void CObjectViewer::getSizeViewport(float &left, float &right, float &bottom, float &top, float &znear, float &zfar)
{
//_Scene->getCam().setPerspective((float)Pi/2.f, (float)w/h, 0.1f, 1000);
_Scene->getCam().getFrustum(left, right, bottom, top, znear, zfar);
}
void CObjectViewer::setCurrentObject(const std::string &name)
{
if ((_Entities.count(name) != 0) || ( name.empty() )) _CurrentInstance = name;
else nlerror ("Entity %s not found", name.c_str());
nlinfo("set current entity %s", _CurrentInstance.c_str());
}
CEntity& CObjectViewer::getEntity(const std::string &name)
{
if ( _Entities.count(name) == 0) nlerror("Entity %s not found", name.c_str());
EIT eit = _Entities.find (name);
return (*eit).second;
}
void CObjectViewer::getListObjects(std::vector<std::string> &listObj)
{
listObj.clear();
for (EIT eit = _Entities.begin(); eit != _Entities.end(); ++eit)
listObj.push_back((*eit).second._Name);
}
void CObjectViewer::deleteEntity(CEntity &entity)
{
if (entity._PlayList != NULL)
{
_PlayListManager->deletePlayList (entity._PlayList);
entity._PlayList = NULL;
}
if (entity._AnimationSet != NULL)
{
_Driver->deleteAnimationSet(entity._AnimationSet);
entity._AnimationSet = NULL;
}
if (!entity._Skeleton.empty())
{
entity._Skeleton.detachSkeletonSon(entity._Instance);
_Scene->deleteSkeleton(entity._Skeleton);
entity._Skeleton = NULL;
}
if (!entity._Instance.empty())
{
_Scene->deleteInstance(entity._Instance);
entity._Instance = NULL;
}
}
void CObjectViewer::deleteEntities()
{
for (EIT eit = _Entities.begin(); eit != _Entities.end(); ++eit)
{
CEntity &entity = (*eit).second;
deleteEntity(entity);
}
_Entities.clear();
}
void CObjectViewer::cfcbBackgroundColor(NLMISC::CConfigFile::CVar &var)
{
// read variable from config file
_BackgroundColor = CRGBA(var.asInt(0), var.asInt(1), var.asInt(2));
}
void CObjectViewer::cfcbGraphicsDriver(NLMISC::CConfigFile::CVar &var)
{
// Choose driver opengl to work correctly under Linux example
_Direct3D = false; //_Driver = OpenGL;
#ifdef NL_OS_WINDOWS
std::string driver = var.asString();
if (driver == "Direct3D") _Direct3D = true; //m_Driver = Direct3D;
else if (driver == "OpenGL") _Direct3D = false; //m_Driver = OpenGL;
else nlwarning("Invalid driver specified, defaulting to OpenGL");
#endif
}
} /* namespace NLQT */

@ -0,0 +1,193 @@
/*
Georges Editor Qt
Copyright (C) 2010 Adrian Jaekel <aj at elane2k dot com>
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 OBJECT_VIEWER_H
#define OBJECT_VIEWER_H
#include <nel/misc/types_nl.h>
// STL includes
#include <string>
#include <map>
// NeL includes
#include <nel/misc/config_file.h>
#include <nel/misc/rgba.h>
#include <nel/3d/event_mouse_listener.h>
// Project includes
#include "entity.h"
namespace NL3D
{
class UDriver;
class UScene;
class ULight;
class UInstance;
class UCamera;
class USkeleton;
class UPlayListManager;
class U3dMouseListener;
}
/**
namespace NLQT
@brief namespace NLQT
*/
namespace NLQT
{
/**
@class CObjectViewer
A CObjectViewer class loading and viewing shape, particle system files.
*/
class CObjectViewer
{
public:
/// Default constructor.
CObjectViewer();
virtual ~CObjectViewer();
/// Init a driver and create scene.
/// @param wnd - handle window.
/// @param w - width window.
/// @param h - height window.
void init(nlWindow wnd, uint16 w, uint16 h);
void reinit(nlWindow wnd, uint16 w, uint16 h);
/// Release class.
void release();
/// Update mouse and keyboard events. And update camera matrix.
void updateInput();
/// Render Driver (clear all buffers and set background color).
void renderDriver();
/// Render current scene.
void renderScene();
/// Render Debug 2D (stuff for dev).
void renderDebug2D();
/// Make a screenshot of the current scene and save.
void saveScreenshot(const std::string &nameFile, bool jpg, bool png, bool tga);
/// Load a mesh or particle system and add to current scene.
/// @param meshFileName - name loading shape or ps file.
/// @param skelFileName - name loading skeletin file.
/// @return true if file have been loaded, false if file have not been loaded.
bool loadMesh (const std::string &meshFileName, const std::string &skelFileName);
/// Reset current scene.
void resetScene();
/// Update the navigation camera.
/// @param deltaPsi - delta angle horizontal (radians).
/// @param deltaPhi - delta angle vertical (radians).
/// @param deltaDist - delta distance.
void updateCamera(float deltaPsi, float deltaPhi, float deltaDist);
/// Set the background color.
/// @param backgroundColor - background color.
void setBackgroundColor(NLMISC::CRGBA backgroundColor);
/// Set type driver.
/// @param Direct3D - type driver (true - Direct3D) or (false -OpenGL)
void setGraphicsDriver(bool Direct3D);
/// Set size viewport for correct set perspective
/// @param w - width window.
/// @param h - height window.
void setSizeViewport(uint16 w, uint16 h);
void getSizeViewport(float &left, float &right, float &bottom, float &top, float &znear, float &zfar);
/// Select instance from the scene
/// @param name - name instance, "" if no instance edited
void setCurrentObject(const std::string &name);
/// Get current instance from the scene
/// @return name current instance, "" if no instance edited
const std::string& getCurrentObject() { return _CurrentInstance; }
/// Get entity from the scene
/// @return ref Entity
CEntity& getEntity(const std::string &name);
/// Get full list instances from the scene
/// @param listObj - ref of return list instances
void getListObjects(std::vector<std::string> &listObj);
/// Get value background color.
/// @return background color.
NLMISC::CRGBA getBackgroundColor() { return _BackgroundColor; }
/// Get type driver.
/// @return true if have used Direct3D driver, false OpenGL driver.
inline bool getDirect3D() { return _Direct3D; }
/// Get a pointer to the driver.
/// @return pointer to the driver.
inline NL3D::UDriver *getDriver() { return _Driver; }
/// Get a pointer to the scene.
/// @return pointer to the scene.
inline NL3D::UScene *getScene() { return _Scene; }
/// Get a manager of playlist
/// @return pointer to the UPlayListManager
inline NL3D::UPlayListManager *getPlayListManager() { return _PlayListManager; }
private:
void deleteEntity (CEntity &entity);
/// Delete all entities
void deleteEntities();
/// Load background color from config file, intended for CConfiguration.
void cfcbBackgroundColor(NLMISC::CConfigFile::CVar &var);
void cfcbGraphicsDriver(NLMISC::CConfigFile::CVar &var);
NLMISC::CRGBA _BackgroundColor;
NL3D::UDriver *_Driver;
NL3D::UScene *_Scene;
NL3D::UPlayListManager *_PlayListManager;
NL3D::ULight *_Light;
NL3D::UCamera *_Camera;
NL3D::U3dMouseListener *_MouseListener;
// The entities storage
CEntities _Entities;
/// Camera parameters.
float _phi, _psi, _dist;
bool _Direct3D;
std::string _CurrentInstance;
// a temporary solution, and later remove
friend class CAnimationSetDialog;
};/* class CObjectViewer */
} /* namespace NLQT */
#endif // OBJECT_VIEWER_H

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

Loading…
Cancel
Save