diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-08-07 17:21:04 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-08-07 17:21:04 +0400 |
commit | ec26abd2db934099bb2cc28510cf255775ae4ab1 (patch) | |
tree | ba77db5750dcefde5add1493605535b665fa9c0c /intern | |
parent | 8318acd1299a44e0b8fd80522993e5367ef2cf07 (diff) | |
parent | a02d7c1ba76adbf3ff432111af4c3c81a0812c3a (diff) |
Cycles: svn merge -r37957:39132 https://svn.blender.org/svnroot/bf-blender/trunk/blender
Diffstat (limited to 'intern')
59 files changed, 3670 insertions, 872 deletions
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt index fca5e7fdf7d..de2c0ab9459 100644 --- a/intern/CMakeLists.txt +++ b/intern/CMakeLists.txt @@ -31,7 +31,6 @@ add_subdirectory(moto) add_subdirectory(memutil) add_subdirectory(iksolver) add_subdirectory(opennl) -add_subdirectory(smoke) add_subdirectory(mikktspace) if(WITH_AUDASPACE) @@ -42,6 +41,10 @@ if(WITH_MOD_FLUID) add_subdirectory(elbeem) endif() +if(WITH_MOD_SMOKE) + add_subdirectory(smoke) +endif() + if(WITH_MOD_DECIMATE) add_subdirectory(container) add_subdirectory(decimation) diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt index ab88c9ecabd..7eef13b103b 100644 --- a/intern/audaspace/CMakeLists.txt +++ b/intern/audaspace/CMakeLists.txt @@ -22,9 +22,9 @@ set(INC . - intern FX SRC + intern ../ffmpeg ) @@ -159,8 +159,12 @@ set(SRC if(WITH_CODEC_FFMPEG) add_definitions(-DWITH_FFMPEG) - list(APPEND INC ffmpeg) - list(APPEND INC_SYS ${FFMPEG_INCLUDE_DIRS}) + list(APPEND INC + ffmpeg + ) + list(APPEND INC_SYS + ${FFMPEG_INCLUDE_DIRS} + ) list(APPEND SRC ffmpeg/AUD_FFMPEGFactory.cpp ffmpeg/AUD_FFMPEGReader.cpp @@ -172,8 +176,12 @@ endif() if(WITH_SDL) add_definitions(-DWITH_SDL) - list(APPEND INC SDL) - list(APPEND INC_SYS ${SDL_INCLUDE_DIR}) + list(APPEND INC + SDL + ) + list(APPEND INC_SYS + ${SDL_INCLUDE_DIR} + ) list(APPEND SRC SDL/AUD_SDLDevice.cpp @@ -183,8 +191,12 @@ endif() if(WITH_OPENAL) add_definitions(-DWITH_OPENAL) - list(APPEND INC OpenAL) - list(APPEND INC_SYS ${OPENAL_INCLUDE_DIR}) + list(APPEND INC + OpenAL + ) + list(APPEND INC_SYS + ${OPENAL_INCLUDE_DIR} + ) list(APPEND SRC OpenAL/AUD_OpenALDevice.cpp @@ -194,8 +206,12 @@ endif() if(WITH_JACK) add_definitions(-DWITH_JACK) - list(APPEND INC jack) - list(APPEND INC_SYS ${JACK_INCLUDE_DIRS}) + list(APPEND INC + jack + ) + list(APPEND INC_SYS + ${JACK_INCLUDE_DIRS} + ) list(APPEND SRC jack/AUD_JackDevice.cpp @@ -205,8 +221,12 @@ endif() if(WITH_CODEC_SNDFILE) add_definitions(-DWITH_SNDFILE) - list(APPEND INC sndfile) - list(APPEND INC_SYS ${SNDFILE_INCLUDE_DIRS}) + list(APPEND INC + sndfile + ) + list(APPEND INC_SYS + ${SNDFILE_INCLUDE_DIRS} + ) list(APPEND SRC sndfile/AUD_SndFileFactory.cpp sndfile/AUD_SndFileReader.cpp @@ -218,7 +238,9 @@ endif() if(WITH_SAMPLERATE) add_definitions(-DWITH_SAMPLERATE) - list(APPEND INC_SYS ${SAMPLERATE_INCLUDE_DIRS}) + list(APPEND INC_SYS + ${SAMPLERATE_INCLUDE_DIRS} + ) list(APPEND SRC SRC/AUD_SRCResampleFactory.cpp SRC/AUD_SRCResampleReader.cpp @@ -230,8 +252,12 @@ endif() if(WITH_FFTW3 AND FALSE) add_definitions(-DWITH_FFTW3) - list(APPEND INC fftw) - list(APPEND INC_SYS ${FFTW3_INCLUDE_DIRS}) + list(APPEND INC + fftw + ) + list(APPEND INC_SYS + ${FFTW3_INCLUDE_DIRS} + ) list(APPEND SRC fftw/AUD_BandPassFactory.cpp fftw/AUD_BandPassReader.cpp @@ -242,8 +268,12 @@ if(WITH_FFTW3 AND FALSE) endif() if(WITH_PYTHON) - list(APPEND INC Python) - list(APPEND INC_SYS ${PYTHON_INCLUDE_DIRS}) + list(APPEND INC + Python + ) + list(APPEND INC_SYS + ${PYTHON_INCLUDE_DIRS} + ) list(APPEND SRC Python/AUD_PyAPI.cpp diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp index b9e30bbf62a..71e7b7677e8 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp @@ -105,12 +105,15 @@ void* AUD_openalRunThread(void* device) return NULL; } -void AUD_OpenALDevice::start() +void AUD_OpenALDevice::start(bool join) { lock(); if(!m_playing) { + if(join) + pthread_join(m_thread, NULL); + pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); @@ -271,8 +274,8 @@ void AUD_OpenALDevice::updateStreams() // stop thread if(m_playingSounds->empty() || (cerr != ALC_NO_ERROR)) { - unlock(); m_playing = false; + unlock(); pthread_exit(NULL); } @@ -366,6 +369,8 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) pthread_mutex_init(&m_mutex, &attr); pthread_mutexattr_destroy(&attr); + + start(false); } AUD_OpenALDevice::~AUD_OpenALDevice() @@ -414,13 +419,8 @@ AUD_OpenALDevice::~AUD_OpenALDevice() alcProcessContext(m_context); // wait for the thread to stop - if(m_playing) - { - unlock(); - pthread_join(m_thread, NULL); - } - else - unlock(); + unlock(); + pthread_join(m_thread, NULL); delete m_playingSounds; delete m_pausedSounds; diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.h b/intern/audaspace/OpenAL/AUD_OpenALDevice.h index 3bbbe85d7e6..127f69beca8 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.h +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.h @@ -106,7 +106,7 @@ private: /** * Starts the streaming thread. */ - void start(); + void start(bool join = true); /** * Checks if a handle is valid. diff --git a/intern/boolop/CMakeLists.txt b/intern/boolop/CMakeLists.txt index 7a95d556172..742c0f1d42c 100644 --- a/intern/boolop/CMakeLists.txt +++ b/intern/boolop/CMakeLists.txt @@ -26,11 +26,11 @@ set(INC . - ./intern - ./extern - ../memutil + extern + intern ../container ../guardedalloc + ../memutil ../moto/include ../../source/blender/blenlib ../../source/blender/makesdna diff --git a/intern/bsp/CMakeLists.txt b/intern/bsp/CMakeLists.txt index 792f6aa1327..a844db3257e 100644 --- a/intern/bsp/CMakeLists.txt +++ b/intern/bsp/CMakeLists.txt @@ -25,11 +25,11 @@ # ***** END GPL LICENSE BLOCK ***** set(INC - ./intern + intern ../container ../guardedalloc - ../moto/include ../memutil + ../moto/include ) set(INC_SYS diff --git a/intern/ffmpeg/ffmpeg_compat.h b/intern/ffmpeg/ffmpeg_compat.h index d8edffbfe0b..fae8590568d 100644 --- a/intern/ffmpeg/ffmpeg_compat.h +++ b/intern/ffmpeg/ffmpeg_compat.h @@ -40,7 +40,7 @@ #define FFMPEG_HAVE_AVIO 1 #endif -#if (LIBAVCODEC_VERSION_MAJOR > 53) || ((LIBAVCODEC_VERSION_MAJOR == 53) && (LIBAVCODEC_VERSION_MINOR > 1)) || ((LIBAVCODEC_VERSION_MAJOR == 53) && (LIBAVCODEC_VERSION_MINOR == 1) && (LIBAVCODEC_VERSION_MICRO >= 1)) || ((LIBAVCODEC_VERSION_MAJOR == 52) && (LIBAVCODEC_VERSION_MINOR >= 122)) +#if (LIBAVCODEC_VERSION_MAJOR > 53) || ((LIBAVCODEC_VERSION_MAJOR == 53) && (LIBAVCODEC_VERSION_MINOR > 1)) || ((LIBAVCODEC_VERSION_MAJOR == 53) && (LIBAVCODEC_VERSION_MINOR == 1) && (LIBAVCODEC_VERSION_MICRO >= 1)) || ((LIBAVCODEC_VERSION_MAJOR == 52) && (LIBAVCODEC_VERSION_MINOR >= 121)) #define FFMPEG_HAVE_DEFAULT_VAL_UNION 1 #endif diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 922f6918392..d7658c50a36 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -37,16 +37,14 @@ set(INC_SYS set(SRC intern/GHOST_Buttons.cpp - intern/GHOST_CallbackEventConsumer.cpp intern/GHOST_C-api.cpp - intern/GHOST_Path-api.cpp + intern/GHOST_CallbackEventConsumer.cpp intern/GHOST_DisplayManager.cpp intern/GHOST_EventManager.cpp - intern/GHOST_EventPrinter.cpp intern/GHOST_ISystem.cpp intern/GHOST_ISystemPaths.cpp intern/GHOST_ModifierKeys.cpp - intern/GHOST_NDOFManager.cpp + intern/GHOST_Path-api.cpp intern/GHOST_Path-api.cpp intern/GHOST_Rect.cpp intern/GHOST_System.cpp @@ -64,6 +62,7 @@ set(SRC GHOST_Path-api.h GHOST_Rect.h GHOST_Types.h + intern/GHOST_Buttons.h intern/GHOST_CallbackEventConsumer.h intern/GHOST_Debug.h @@ -74,13 +73,10 @@ set(SRC intern/GHOST_EventDragnDrop.h intern/GHOST_EventKey.h intern/GHOST_EventManager.h - intern/GHOST_EventNDOF.h - intern/GHOST_EventPrinter.h intern/GHOST_EventString.h intern/GHOST_EventTrackpad.h intern/GHOST_EventWheel.h intern/GHOST_ModifierKeys.h - intern/GHOST_NDOFManager.h intern/GHOST_System.h intern/GHOST_SystemPaths.h intern/GHOST_TimerManager.h @@ -89,13 +85,51 @@ set(SRC intern/GHOST_WindowManager.h ) -if(WITH_HEADLESS) +if(WITH_GHOST_DEBUG) + list(APPEND SRC + intern/GHOST_EventPrinter.cpp + + intern/GHOST_EventPrinter.h + ) + add_definitions(-DWITH_GHOST_DEBUG) +endif() + +if(WITH_INPUT_NDOF) + add_definitions(-DWITH_INPUT_NDOF) + list(APPEND SRC - intern/GHOST_DisplayManagerNULL.h - intern/GHOST_SystemNULL.h - intern/GHOST_WindowNULL.h + intern/GHOST_NDOFManager.cpp + + intern/GHOST_EventNDOF.h + intern/GHOST_NDOFManager.h ) - add_definitions(-DWITH_HEADLESS) + + list(APPEND INC_SYS + ${NDOF_INCLUDE_DIRS} + ) +endif() + +if(WITH_HEADLESS OR WITH_GHOST_SDL) + if(WITH_HEADLESS) + list(APPEND SRC + intern/GHOST_DisplayManagerNULL.h + intern/GHOST_SystemNULL.h + intern/GHOST_WindowNULL.h + ) + add_definitions(-DWITH_HEADLESS) + else() + list(APPEND SRC + intern/GHOST_DisplayManagerSDL.cpp + intern/GHOST_SystemSDL.cpp + intern/GHOST_WindowSDL.cpp + + intern/GHOST_DisplayManagerSDL.h + intern/GHOST_SystemSDL.h + intern/GHOST_WindowSDL.h + ) + add_definitions(-DWITH_GHOST_SDL) + endif() + # ack, this is still system dependant if(APPLE) @@ -124,6 +158,10 @@ if(WITH_HEADLESS) ) endif() + list(APPEND INC_SYS + ${SDL_INCLUDE_DIR} + ) + elseif(APPLE) if(WITH_COCOA) list(APPEND SRC @@ -131,12 +169,21 @@ elseif(APPLE) intern/GHOST_SystemCocoa.mm intern/GHOST_SystemPathsCocoa.mm intern/GHOST_WindowCocoa.mm - + intern/GHOST_DisplayManagerCocoa.h intern/GHOST_SystemCocoa.h intern/GHOST_SystemPathsCocoa.h intern/GHOST_WindowCocoa.h ) + + if(WITH_INPUT_NDOF) + list(APPEND SRC + intern/GHOST_NDOFManagerCocoa.mm + + intern/GHOST_NDOFManagerCocoa.h + ) + endif() + else() list(APPEND SRC intern/GHOST_DisplayManagerCarbon.cpp @@ -161,7 +208,9 @@ elseif(UNIX) add_definitions(-DWITH_X11_XINPUT) endif() - list(APPEND INC_SYS ${X11_X11_INCLUDE_PATH}) + list(APPEND INC_SYS + ${X11_X11_INCLUDE_PATH} + ) list(APPEND SRC intern/GHOST_DisplayManagerX11.cpp @@ -181,7 +230,17 @@ elseif(UNIX) if(X11_XF86keysym_INCLUDE_PATH) add_definitions(-DWITH_XF86KEYSYM) - list(APPEND INC_SYS ${X11_XF86keysym_INCLUDE_PATH}) + list(APPEND INC_SYS + ${X11_XF86keysym_INCLUDE_PATH} + ) + endif() + + if(WITH_INPUT_NDOF) + list(APPEND SRC + intern/GHOST_NDOFManagerX11.cpp + + intern/GHOST_NDOFManagerX11.h + ) endif() elseif(WIN32) @@ -189,7 +248,9 @@ elseif(WIN32) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX") endif() - list(APPEND INC_SYS ${WINTAB_INC}) + list(APPEND INC_SYS + ${WINTAB_INC} + ) list(APPEND SRC intern/GHOST_DisplayManagerWin32.cpp @@ -205,6 +266,15 @@ elseif(WIN32) intern/GHOST_WindowWin32.h intern/GHOST_TaskbarWin32.h ) + + if(WITH_INPUT_NDOF) + list(APPEND SRC + intern/GHOST_NDOFManagerWin32.cpp + + intern/GHOST_NDOFManagerWin32.h + ) + endif() + endif() blender_add_lib(bf_intern_ghost "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 75837239c4a..a315dfa85e9 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -288,21 +288,6 @@ extern GHOST_TSuccess GHOST_SetProgressBar(GHOST_WindowHandle windowhandle, floa * @param windowhandle The handle to the window */ extern GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle); - - -/*************************************************************************************** - ** N-degree of freedom device management functionality - ***************************************************************************************/ - -/** -* Open N-degree of freedom devices - */ -extern int GHOST_OpenNDOF(GHOST_SystemHandle systemhandle, - GHOST_WindowHandle windowhandle, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen - ); /*************************************************************************************** ** Cursor management functionality diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 69e10070be5..015ae780bea 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -298,22 +298,6 @@ public: */ virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer* consumer) = 0; - /*************************************************************************************** - ** N-degree of freedom device management functionality - ***************************************************************************************/ - - /** - * Starts the N-degree of freedom device manager - */ - virtual int openNDOF(GHOST_IWindow*, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen - // original patch only - // GHOST_NDOFEventHandler_fp setNdofEventHandler - ) = 0; - - /*************************************************************************************** ** Cursor management functionality ***************************************************************************************/ diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 705f4916619..f24ab00acd3 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -47,11 +47,6 @@ typedef unsigned short GHOST_TUns16; typedef int GHOST_TInt32; typedef unsigned int GHOST_TUns32; -#ifdef WIN32 -#define WM_BLND_NDOF_AXIS WM_USER + 1 -#define WM_BLND_NDOF_BTN WM_USER + 2 -#endif - #if defined(WIN32) && !defined(FREE_WINDOWS) typedef __int64 GHOST_TInt64; typedef unsigned __int64 GHOST_TUns64; @@ -218,8 +213,9 @@ typedef enum { GHOST_kStandardCursorBottomLeftCorner, GHOST_kStandardCursorCopy, GHOST_kStandardCursorCustom, - GHOST_kStandardCursorNumCursors, - GHOST_kStandardCursorPencil + GHOST_kStandardCursorPencil, + + GHOST_kStandardCursorNumCursors } GHOST_TStandardCursor; @@ -439,37 +435,33 @@ typedef struct { GHOST_TUns8 **strings; } GHOST_TStringArray; +typedef enum { + GHOST_kNotStarted, + GHOST_kStarting, + GHOST_kInProgress, + GHOST_kFinishing, + GHOST_kFinished + } GHOST_TProgress; -/* original patch used floats, but the driver return ints and uns. We will calibrate in view, no sense on doing conversions twice */ -/* as all USB device controls are likely to use ints, this is also more future proof */ -//typedef struct { -// /** N-degree of freedom device data */ -// float tx, ty, tz; /** -x left, +y up, +z forward */ -// float rx, ry, rz; -// float dt; -//} GHOST_TEventNDOFData; +typedef struct { + /** N-degree of freedom device data v3 [GSoC 2010] */ + // Each component normally ranges from -1 to +1, but can exceed that. + // These use blender standard view coordinates, with positive rotations being CCW about the axis. + float tx, ty, tz; // translation + float rx, ry, rz; // rotation: + // axis = (rx,ry,rz).normalized + // amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg] + float dt; // time since previous NDOF Motion event + GHOST_TProgress progress; // Starting, InProgress or Finishing (for modal handlers) +} GHOST_TEventNDOFMotionData; + +typedef enum { GHOST_kPress, GHOST_kRelease } GHOST_TButtonAction; + // good for mouse or other buttons too, hmmm? typedef struct { - /** N-degree of freedom device data v2*/ - int changed; - GHOST_TUns64 client; - GHOST_TUns64 address; - GHOST_TInt16 tx, ty, tz; /** -x left, +y up, +z forward */ - GHOST_TInt16 rx, ry, rz; - GHOST_TInt16 buttons; - GHOST_TUns64 time; - GHOST_TUns64 delta; -} GHOST_TEventNDOFData; - -typedef int (*GHOST_NDOFLibraryInit_fp)(void); -typedef void (*GHOST_NDOFLibraryShutdown_fp)(void* deviceHandle); -typedef void* (*GHOST_NDOFDeviceOpen_fp)(void* platformData); - -// original patch windows callback. In mac os X version the callback is internal to the plug-in and post an event to main thead. -// not necessary faster, but better integration with other events. - -//typedef int (*GHOST_NDOFEventHandler_fp)(float* result7, void* deviceHandle, unsigned int message, unsigned int* wParam, unsigned long* lParam); -//typedef void (*GHOST_NDOFCallBack_fp)(GHOST_TEventNDOFDataV2 *VolDatas); + GHOST_TButtonAction action; + short button; +} GHOST_TEventNDOFButtonData; typedef struct { /** The key code. */ diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript index b67545f216a..234fc0a172e 100644 --- a/intern/ghost/SConscript +++ b/intern/ghost/SConscript @@ -11,14 +11,27 @@ if window_system == 'darwin': sources += env.Glob('intern/*.mm') -pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_SystemPaths', 'GHOST_Window', 'GHOST_DropTarget'] +pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_SystemPaths', 'GHOST_Window', 'GHOST_DropTarget', 'GHOST_NDOFManager'] defs=['_USE_MATH_DEFINES'] -if window_system in ('linux2', 'openbsd3', 'sunos5', 'freebsd7', 'freebsd8', 'freebsd9', 'irix6', 'aix4', 'aix5'): +incs = '. ../string #extern/glew/include #source/blender/imbuf #source/blender/makesdna ' + env['BF_OPENGL_INC'] + +if env['WITH_GHOST_SDL']: + for f in pf: + try: + sources.remove('intern' + os.sep + f + 'Carbon.cpp') + sources.remove('intern' + os.sep + f + 'Win32.cpp') + sources.remove('intern' + os.sep + f + 'X11.cpp') + except ValueError: + pass + incs += ' ' + env['BF_SDL_INC'] + defs += ['WITH_GHOST_SDL'] +elif window_system in ('linux2', 'openbsd3', 'sunos5', 'freebsd7', 'freebsd8', 'freebsd9', 'irix6', 'aix4', 'aix5'): for f in pf: try: sources.remove('intern' + os.sep + f + 'Win32.cpp') sources.remove('intern' + os.sep + f + 'Carbon.cpp') + sources.remove('intern' + os.sep + f + 'SDL.cpp') except ValueError: pass defs += ['PREFIX=\\"/usr/local/\\"'] # XXX, make an option @@ -29,6 +42,7 @@ elif window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64 try: sources.remove('intern' + os.sep + f + 'X11.cpp') sources.remove('intern' + os.sep + f + 'Carbon.cpp') + sources.remove('intern' + os.sep + f + 'SDL.cpp') except ValueError: pass elif window_system == 'darwin': @@ -42,6 +56,7 @@ elif window_system == 'darwin': sources.remove('intern' + os.sep + f + 'Win32.cpp') sources.remove('intern' + os.sep + f + 'X11.cpp') sources.remove('intern' + os.sep + f + 'Carbon.cpp') + sources.remove('intern' + os.sep + f + 'SDL.cpp') except ValueError: pass else: @@ -50,6 +65,7 @@ elif window_system == 'darwin': sources.remove('intern' + os.sep + f + 'Win32.cpp') sources.remove('intern' + os.sep + f + 'X11.cpp') sources.remove('intern' + os.sep + f + 'Cocoa.mm') + sources.remove('intern' + os.sep + f + 'SDL.cpp') except ValueError: pass @@ -58,9 +74,28 @@ else: Exit() if env['BF_GHOST_DEBUG']: - defs.append('BF_GHOST_DEBUG') + defs.append('WITH_GHOST_DEBUG') +else: + sources.remove('intern' + os.sep + 'GHOST_EventPrinter.cpp') + +if env['WITH_BF_3DMOUSE']: + defs.append('WITH_INPUT_NDOF') + + if env['OURPLATFORM']=='linux2': + incs += ' ' + env['BF_3DMOUSE_INC'] +else: + sources.remove('intern' + os.sep + 'GHOST_NDOFManager.cpp') + try: + if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'): + sources.remove('intern' + os.sep + 'GHOST_NDOFManagerWin32.cpp') + elif window_system=='darwin': + sources.remove('intern' + os.sep + 'GHOST_NDOFManagerCocoa.mm') + else: + sources.remove('intern' + os.sep + 'GHOST_NDOFManagerX11.cpp') + except ValueError: + pass + -incs = '. ../string #extern/glew/include #source/blender/imbuf #source/blender/makesdna ' + env['BF_OPENGL_INC'] if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'): incs = env['BF_WINTAB_INC'] + ' ' + incs diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 7ba8d7db411..6332d72a42f 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -275,23 +275,6 @@ GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle) } -int GHOST_OpenNDOF(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen) - //original patch only - /* GHOST_NDOFEventHandler_fp setNdofEventHandler)*/ -{ - GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; - - return system->openNDOF((GHOST_IWindow*) windowhandle, - setNdofLibraryInit, setNdofLibraryShutdown, setNdofDeviceOpen); -// original patch -// setNdofLibraryInit, setNdofLibraryShutdown, setNdofDeviceOpen, setNdofEventHandler); -} - - - GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandle) { GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h index e77f3b9c461..ef1099b5cf6 100644 --- a/intern/ghost/intern/GHOST_Debug.h +++ b/intern/ghost/intern/GHOST_Debug.h @@ -41,9 +41,9 @@ #endif // DEBUG #endif // WIN32 -#ifdef BF_GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG #define GHOST_DEBUG // spit ghost events to stdout -#endif // BF_GHOST_DEBUG +#endif // WITH_GHOST_DEBUG #ifdef GHOST_DEBUG #include <iostream> diff --git a/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp b/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp new file mode 100644 index 00000000000..2e55957e60a --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp @@ -0,0 +1,93 @@ +/* + * $Id$ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ghost/intern/GHOST_DisplayManagerSDL.cpp + * \ingroup GHOST + */ + +#include "GHOST_SystemSDL.h" +#include "GHOST_DisplayManagerSDL.h" + +GHOST_DisplayManagerSDL::GHOST_DisplayManagerSDL(GHOST_SystemSDL *system) + : + GHOST_DisplayManager(), + m_system(system) +{ + /* do nothing */ +} + +GHOST_TSuccess +GHOST_DisplayManagerSDL::getNumDisplays(GHOST_TUns8& numDisplays) +{ + numDisplays= SDL_GetNumVideoDisplays(); + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_DisplayManagerSDL::getNumDisplaySettings(GHOST_TUns8 display, + GHOST_TInt32& numSettings) +{ + GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n"); + numSettings= GHOST_TInt32(1); + return GHOST_kSuccess; +} + +GHOST_TSuccess +GHOST_DisplayManagerSDL::getDisplaySetting(GHOST_TUns8 display, + GHOST_TInt32 index, + GHOST_DisplaySetting& setting) +{ + + GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n"); + GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n"); + SDL_DisplayMode mode; + + SDL_GetDesktopDisplayMode(display, &mode); + + setting.xPixels= mode.w; + setting.yPixels= mode.h; + setting.bpp= SDL_BYTESPERPIXEL(mode.format); + /* assume 60 when unset */ + setting.frequency= mode.refresh_rate ? mode.refresh_rate : 60; + + return GHOST_kSuccess; +} + +GHOST_TSuccess +GHOST_DisplayManagerSDL::getCurrentDisplaySetting(GHOST_TUns8 display, + GHOST_DisplaySetting& setting) +{ + return getDisplaySetting(display,GHOST_TInt32(0),setting); +} + +GHOST_TSuccess +GHOST_DisplayManagerSDL:: setCurrentDisplaySetting(GHOST_TUns8 display, + const GHOST_DisplaySetting& setting) +{ + // This is never going to work robustly in X + // but it's currently part of the full screen interface + + // we fudge it for now. + + return GHOST_kSuccess; +} diff --git a/intern/ghost/intern/GHOST_DisplayManagerSDL.h b/intern/ghost/intern/GHOST_DisplayManagerSDL.h new file mode 100644 index 00000000000..2a815b1dc28 --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerSDL.h @@ -0,0 +1,73 @@ +/* + * $Id$ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ghost/intern/GHOST_DisplayManagerSDL.h + * \ingroup GHOST + * Declaration of GHOST_DisplayManagerSDL class. + */ + +#ifndef _GHOST_DISPLAY_MANAGER_SDL_H_ +#define _GHOST_DISPLAY_MANAGER_SDL_H_ + +#include "GHOST_DisplayManager.h" + +extern "C" { + #include "SDL.h" +} + +#if !SDL_VERSION_ATLEAST(1, 3, 0) +# error "SDL 1.3 or newer is needed to build with Ghost" +#endif + +class GHOST_SystemSDL; + +class GHOST_DisplayManagerSDL : public GHOST_DisplayManager +{ +public: + GHOST_DisplayManagerSDL(GHOST_SystemSDL *system); + + GHOST_TSuccess + getNumDisplays(GHOST_TUns8& numDisplays); + + GHOST_TSuccess + getNumDisplaySettings(GHOST_TUns8 display, + GHOST_TInt32& numSettings); + + GHOST_TSuccess + getDisplaySetting(GHOST_TUns8 display, + GHOST_TInt32 index, + GHOST_DisplaySetting& setting); + + GHOST_TSuccess + getCurrentDisplaySetting(GHOST_TUns8 display, + GHOST_DisplaySetting& setting); + + GHOST_TSuccess + setCurrentDisplaySetting(GHOST_TUns8 display, + const GHOST_DisplaySetting& setting); + +private : + GHOST_SystemSDL * m_system; +}; + +#endif /* _GHOST_DISPLAY_MANAGER_SDL_H_ */ diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp index 30d9aa31207..47f748927ab 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp @@ -35,8 +35,11 @@ #include "GHOST_DisplayManagerWin32.h" #include "GHOST_Debug.h" -// We do not support multiple monitors at the moment +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include <windows.h> + +// We do not support multiple monitors at the moment #define COMPILE_MULTIMON_STUBS #ifndef FREE_WINDOWS #include <multimon.h> diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp index 2e77da42b31..99990a46c2a 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp +++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp @@ -33,6 +33,7 @@ #include "GHOST_Debug.h" #include "GHOST_DropTargetWin32.h" +#include <ShellApi.h> #ifdef GHOST_DEBUG // utility diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.h b/intern/ghost/intern/GHOST_DropTargetWin32.h index 0a553b6701e..980e9f9fe9b 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.h +++ b/intern/ghost/intern/GHOST_DropTargetWin32.h @@ -33,7 +33,6 @@ #ifndef _GHOST_DROP_TARGET_WIN32_H_ #define _GHOST_DROP_TARGET_WIN32_H_ -#include <windows.h> #include <string.h> #include <GHOST_Types.h> #include "GHOST_WindowWin32.h" diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp index 1483555c362..86b87973038 100644 --- a/intern/ghost/intern/GHOST_EventManager.cpp +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -42,7 +42,7 @@ #include "GHOST_EventManager.h" #include <algorithm> #include "GHOST_Debug.h" - +#include <stdio.h> // [mce] temp debug GHOST_EventManager::GHOST_EventManager() { diff --git a/intern/ghost/intern/GHOST_EventNDOF.h b/intern/ghost/intern/GHOST_EventNDOF.h index 70861b08fc6..394aff0493f 100644 --- a/intern/ghost/intern/GHOST_EventNDOF.h +++ b/intern/ghost/intern/GHOST_EventNDOF.h @@ -19,11 +19,6 @@ * * ***** END GPL LICENSE BLOCK ***** */ - -/** \file ghost/intern/GHOST_EventNDOF.h - * \ingroup GHOST - */ - #ifndef _GHOST_EVENT_NDOF_H_ @@ -31,32 +26,33 @@ #include "GHOST_Event.h" -/** - * N-degree of freedom device event. - */ -class GHOST_EventNDOF : public GHOST_Event -{ -public: - /** - * Constructor. - * @param msec The time this event was generated. - * @param type The type of this event. - * @param x The x-coordinate of the location the cursor was at at the time of the event. - * @param y The y-coordinate of the location the cursor was at at the time of the event. - */ - GHOST_EventNDOF(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window, - GHOST_TEventNDOFData data) - : GHOST_Event(msec, type, window) - { - m_ndofEventData = data; - m_data = &m_ndofEventData; - } -protected: - /** translation & rotation from the device. */ - GHOST_TEventNDOFData m_ndofEventData; -}; +class GHOST_EventNDOFMotion : public GHOST_Event + { + protected: + GHOST_TEventNDOFMotionData m_axisData; + + public: + GHOST_EventNDOFMotion(GHOST_TUns64 time, GHOST_IWindow* window) + : GHOST_Event(time, GHOST_kEventNDOFMotion, window) + { + m_data = &m_axisData; + } + }; + + +class GHOST_EventNDOFButton : public GHOST_Event + { + protected: + GHOST_TEventNDOFButtonData m_buttonData; + + public: + GHOST_EventNDOFButton(GHOST_TUns64 time, GHOST_IWindow* window) + : GHOST_Event(time, GHOST_kEventNDOFButton, window) + { + m_data = &m_buttonData; + } + }; #endif // _GHOST_EVENT_NDOF_H_ - diff --git a/intern/ghost/intern/GHOST_EventPrinter.cpp b/intern/ghost/intern/GHOST_EventPrinter.cpp index 139c4beb412..9fa0b278353 100644 --- a/intern/ghost/intern/GHOST_EventPrinter.cpp +++ b/intern/ghost/intern/GHOST_EventPrinter.cpp @@ -37,6 +37,7 @@ #include "GHOST_EventDragnDrop.h" #include "GHOST_Debug.h" +#include <stdio.h> bool GHOST_EventPrinter::processEvent(GHOST_IEvent* event) { @@ -82,17 +83,17 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent* event) case GHOST_kEventKeyUp: { GHOST_TEventKeyData* keyData = (GHOST_TEventKeyData*)((GHOST_IEvent*)event)->getData(); - STR_String str; + char str[32]= {'\0'}; getKeyString(keyData->key, str); - std::cout << "GHOST_kEventKeyUp, key: " << str.Ptr(); + std::cout << "GHOST_kEventKeyUp, key: " << str; } break; case GHOST_kEventKeyDown: { GHOST_TEventKeyData* keyData = (GHOST_TEventKeyData*)((GHOST_IEvent*)event)->getData(); - STR_String str; + char str[32]= {'\0'}; getKeyString(keyData->key, str); - std::cout << "GHOST_kEventKeyDown, key: " << str.Ptr(); + std::cout << "GHOST_kEventKeyDown, key: " << str; } break; @@ -183,165 +184,161 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent* event) } -void GHOST_EventPrinter::getKeyString(GHOST_TKey key, STR_String& str) const +void GHOST_EventPrinter::getKeyString(GHOST_TKey key, char str[32]) const { if ((key >= GHOST_kKeyComma) && (key <= GHOST_kKeyRightBracket)) { - str = ((char)key); + sprintf(str, "%c", (char)key); } else if ((key >= GHOST_kKeyNumpad0) && (key <= GHOST_kKeyNumpad9)) { - int number = key - GHOST_kKeyNumpad0; - STR_String numberStr (number); - str = "Numpad"; - str += numberStr; + sprintf(str, "Numpad %d", (key - GHOST_kKeyNumpad0)); #if defined(__sun__) || defined(__sun) } else if (key == 268828432) { /* solaris keyboards are messed up */ /* This should really test XK_F11 but that doesn't work */ - str = "F11"; + strcpy(str, "F11"); } else if (key == 268828433) { /* solaris keyboards are messed up */ /* This should really test XK_F12 but that doesn't work */ - str = "F12"; + strcpy(str, "F12"); #endif } else if ((key >= GHOST_kKeyF1) && (key <= GHOST_kKeyF24)) { - int number = key - GHOST_kKeyF1 + 1; - STR_String numberStr (number); - str = "F"; - str += numberStr; + sprintf(str, "F%d", key - GHOST_kKeyF1 + 1); } else { - switch (key) - { + const char *tstr= NULL; + switch (key) { case GHOST_kKeyBackSpace: - str = "BackSpace"; + tstr = "BackSpace"; break; case GHOST_kKeyTab: - str = "Tab"; + tstr = "Tab"; break; case GHOST_kKeyLinefeed: - str = "Linefeed"; + tstr = "Linefeed"; break; case GHOST_kKeyClear: - str = "Clear"; + tstr = "Clear"; break; case GHOST_kKeyEnter: - str = "Enter"; + tstr = "Enter"; break; case GHOST_kKeyEsc: - str = "Esc"; + tstr = "Esc"; break; case GHOST_kKeySpace: - str = "Space"; + tstr = "Space"; break; case GHOST_kKeyQuote: - str = "Quote"; + tstr = "Quote"; break; case GHOST_kKeyBackslash: - str = "\\"; + tstr = "\\"; break; case GHOST_kKeyAccentGrave: - str = "`"; + tstr = "`"; break; case GHOST_kKeyLeftShift: - str = "LeftShift"; + tstr = "LeftShift"; break; case GHOST_kKeyRightShift: - str = "RightShift"; + tstr = "RightShift"; break; case GHOST_kKeyLeftControl: - str = "LeftControl"; + tstr = "LeftControl"; break; case GHOST_kKeyRightControl: - str = "RightControl"; + tstr = "RightControl"; break; case GHOST_kKeyLeftAlt: - str = "LeftAlt"; + tstr = "LeftAlt"; break; case GHOST_kKeyRightAlt: - str = "RightAlt"; + tstr = "RightAlt"; break; case GHOST_kKeyOS: - str = "OS"; + tstr = "OS"; break; case GHOST_kKeyGrLess: // PC german! - str = "GrLess"; + tstr = "GrLess"; break; case GHOST_kKeyCapsLock: - str = "CapsLock"; + tstr = "CapsLock"; break; case GHOST_kKeyNumLock: - str = "NumLock"; + tstr = "NumLock"; break; case GHOST_kKeyScrollLock: - str = "ScrollLock"; + tstr = "ScrollLock"; break; case GHOST_kKeyLeftArrow: - str = "LeftArrow"; + tstr = "LeftArrow"; break; case GHOST_kKeyRightArrow: - str = "RightArrow"; + tstr = "RightArrow"; break; case GHOST_kKeyUpArrow: - str = "UpArrow"; + tstr = "UpArrow"; break; case GHOST_kKeyDownArrow: - str = "DownArrow"; + tstr = "DownArrow"; break; case GHOST_kKeyPrintScreen: - str = "PrintScreen"; + tstr = "PrintScreen"; break; case GHOST_kKeyPause: - str = "Pause"; + tstr = "Pause"; break; case GHOST_kKeyInsert: - str = "Insert"; + tstr = "Insert"; break; case GHOST_kKeyDelete: - str = "Delete"; + tstr = "Delete"; break; case GHOST_kKeyHome: - str = "Home"; + tstr = "Home"; break; case GHOST_kKeyEnd: - str = "End"; + tstr = "End"; break; case GHOST_kKeyUpPage: - str = "UpPage"; + tstr = "UpPage"; break; case GHOST_kKeyDownPage: - str = "DownPage"; + tstr = "DownPage"; break; case GHOST_kKeyNumpadPeriod: - str = "NumpadPeriod"; + tstr = "NumpadPeriod"; break; case GHOST_kKeyNumpadEnter: - str = "NumpadEnter"; + tstr = "NumpadEnter"; break; case GHOST_kKeyNumpadPlus: - str = "NumpadPlus"; + tstr = "NumpadPlus"; break; case GHOST_kKeyNumpadMinus: - str = "NumpadMinus"; + tstr = "NumpadMinus"; break; case GHOST_kKeyNumpadAsterisk: - str = "NumpadAsterisk"; + tstr = "NumpadAsterisk"; break; case GHOST_kKeyNumpadSlash: - str = "NumpadSlash"; + tstr = "NumpadSlash"; break; case GHOST_kKeyMediaPlay: - str = "MediaPlayPause"; + tstr = "MediaPlayPause"; break; case GHOST_kKeyMediaStop: - str = "MediaStop"; + tstr = "MediaStop"; break; case GHOST_kKeyMediaFirst: - str = "MediaFirst"; + tstr = "MediaFirst"; break; case GHOST_kKeyMediaLast: - str = "MediaLast"; + tstr = "MediaLast"; break; default: - str = "unknown"; + tstr = "unknown"; break; } + + sprintf(str, "%s", tstr); } } diff --git a/intern/ghost/intern/GHOST_EventPrinter.h b/intern/ghost/intern/GHOST_EventPrinter.h index 74c379e76a8..d9b7f86c04e 100644 --- a/intern/ghost/intern/GHOST_EventPrinter.h +++ b/intern/ghost/intern/GHOST_EventPrinter.h @@ -58,7 +58,7 @@ protected: * @param key The GHOST key code to convert. * @param str The GHOST key code converted to a readable string. */ - void getKeyString(GHOST_TKey key, STR_String& str) const; + void getKeyString(GHOST_TKey key, char str[32]) const; }; #endif // _GHOST_EVENT_PRINTER_H_ diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp index 7f170d2e876..278c224ff85 100644 --- a/intern/ghost/intern/GHOST_ISystem.cpp +++ b/intern/ghost/intern/GHOST_ISystem.cpp @@ -43,6 +43,8 @@ #ifdef WITH_HEADLESS # include "GHOST_SystemNULL.h" +#elif defined(WITH_GHOST_SDL) +# include "GHOST_SystemSDL.h" #elif defined(WIN32) # include "GHOST_SystemWin32.h" #else @@ -67,6 +69,8 @@ GHOST_TSuccess GHOST_ISystem::createSystem() if (!m_system) { #ifdef WITH_HEADLESS m_system = new GHOST_SystemNULL(); +#elif defined(WITH_GHOST_SDL) + m_system = new GHOST_SystemSDL(); #elif defined(WIN32) m_system = new GHOST_SystemWin32 (); #else diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 7721b1708f9..855e27b9964 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -1,4 +1,6 @@ /* + * $Id$ + * * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -15,120 +17,458 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Contributor(s): none yet. + * Contributor(s): + * Mike Erwin * * ***** END GPL LICENSE BLOCK ***** */ -/** \file ghost/intern/GHOST_NDOFManager.cpp - * \ingroup GHOST - */ +#include "GHOST_Debug.h" +#include "GHOST_NDOFManager.h" +#include "GHOST_EventNDOF.h" +#include "GHOST_EventKey.h" +#include "GHOST_WindowManager.h" +#include <string.h> // for memory functions +#include <stdio.h> // for error/info reporting +#include <math.h> +#ifdef DEBUG_NDOF_MOTION +// printable version of each GHOST_TProgress value +static const char* progress_string[] = + {"not started","starting","in progress","finishing","finished"}; +#endif -#include <stdio.h> /* just for printf */ +#ifdef DEBUG_NDOF_BUTTONS +static const char* ndof_button_names[] = { + // used internally, never sent + "NDOF_BUTTON_NONE", + // these two are available from any 3Dconnexion device + "NDOF_BUTTON_MENU", + "NDOF_BUTTON_FIT", + // standard views + "NDOF_BUTTON_TOP", + "NDOF_BUTTON_BOTTOM", + "NDOF_BUTTON_LEFT", + "NDOF_BUTTON_RIGHT", + "NDOF_BUTTON_FRONT", + "NDOF_BUTTON_BACK", + // more views + "NDOF_BUTTON_ISO1", + "NDOF_BUTTON_ISO2", + // 90 degree rotations + "NDOF_BUTTON_ROLL_CW", + "NDOF_BUTTON_ROLL_CCW", + "NDOF_BUTTON_SPIN_CW", + "NDOF_BUTTON_SPIN_CCW", + "NDOF_BUTTON_TILT_CW", + "NDOF_BUTTON_TILT_CCW", + // device control + "NDOF_BUTTON_ROTATE", + "NDOF_BUTTON_PANZOOM", + "NDOF_BUTTON_DOMINANT", + "NDOF_BUTTON_PLUS", + "NDOF_BUTTON_MINUS", + // general-purpose buttons + "NDOF_BUTTON_1", + "NDOF_BUTTON_2", + "NDOF_BUTTON_3", + "NDOF_BUTTON_4", + "NDOF_BUTTON_5", + "NDOF_BUTTON_6", + "NDOF_BUTTON_7", + "NDOF_BUTTON_8", + "NDOF_BUTTON_9", + "NDOF_BUTTON_10", +}; +#endif -#include "GHOST_NDOFManager.h" +static const NDOF_ButtonT SpaceNavigator_HID_map[] = { + NDOF_BUTTON_MENU, + NDOF_BUTTON_FIT +}; +static const NDOF_ButtonT SpaceExplorer_HID_map[] = { + NDOF_BUTTON_1, + NDOF_BUTTON_2, + NDOF_BUTTON_TOP, + NDOF_BUTTON_LEFT, + NDOF_BUTTON_RIGHT, + NDOF_BUTTON_FRONT, + NDOF_BUTTON_NONE, // esc key + NDOF_BUTTON_NONE, // alt key + NDOF_BUTTON_NONE, // shift key + NDOF_BUTTON_NONE, // ctrl key + NDOF_BUTTON_FIT, + NDOF_BUTTON_MENU, + NDOF_BUTTON_PLUS, + NDOF_BUTTON_MINUS, + NDOF_BUTTON_ROTATE +}; -// the variable is outside the class because it must be accessed from plugin -static volatile GHOST_TEventNDOFData currentNdofValues = {0,0,0,0,0,0,0,0,0,0,0}; +static const NDOF_ButtonT SpacePilotPro_HID_map[] = { + NDOF_BUTTON_MENU, + NDOF_BUTTON_FIT, + NDOF_BUTTON_TOP, + NDOF_BUTTON_LEFT, + NDOF_BUTTON_RIGHT, + NDOF_BUTTON_FRONT, + NDOF_BUTTON_BOTTOM, + NDOF_BUTTON_BACK, + NDOF_BUTTON_ROLL_CW, + NDOF_BUTTON_ROLL_CCW, + NDOF_BUTTON_ISO1, + NDOF_BUTTON_ISO2, + NDOF_BUTTON_1, + NDOF_BUTTON_2, + NDOF_BUTTON_3, + NDOF_BUTTON_4, + NDOF_BUTTON_5, + NDOF_BUTTON_6, + NDOF_BUTTON_7, + NDOF_BUTTON_8, + NDOF_BUTTON_9, + NDOF_BUTTON_10, + NDOF_BUTTON_NONE, // esc key + NDOF_BUTTON_NONE, // alt key + NDOF_BUTTON_NONE, // shift key + NDOF_BUTTON_NONE, // ctrl key + NDOF_BUTTON_ROTATE, + NDOF_BUTTON_PANZOOM, + NDOF_BUTTON_DOMINANT, + NDOF_BUTTON_PLUS, + NDOF_BUTTON_MINUS +}; -#if !defined(_WIN32) && !defined(__APPLE__) -#include "GHOST_SystemX11.h" -#endif +/* this is the older SpacePilot (sans Pro) + * thanks to polosson for the info in this table */ +static const NDOF_ButtonT SpacePilot_HID_map[] = { + NDOF_BUTTON_1, + NDOF_BUTTON_2, + NDOF_BUTTON_3, + NDOF_BUTTON_4, + NDOF_BUTTON_5, + NDOF_BUTTON_6, + NDOF_BUTTON_TOP, + NDOF_BUTTON_LEFT, + NDOF_BUTTON_RIGHT, + NDOF_BUTTON_FRONT, + NDOF_BUTTON_NONE, // esc key + NDOF_BUTTON_NONE, // alt key + NDOF_BUTTON_NONE, // shift key + NDOF_BUTTON_NONE, // ctrl key + NDOF_BUTTON_FIT, + NDOF_BUTTON_MENU, + NDOF_BUTTON_PLUS, + NDOF_BUTTON_MINUS, + NDOF_BUTTON_DOMINANT, + NDOF_BUTTON_ROTATE, + NDOF_BUTTON_NONE // the CONFIG button -- what does it do? +}; -namespace +GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) + : m_system(sys) + , m_deviceType(NDOF_UnknownDevice) // each platform has its own device detection code + , m_buttonCount(0) + , m_buttonMask(0) + , m_buttons(0) + , m_motionTime(0) + , m_prevMotionTime(0) + , m_motionState(GHOST_kNotStarted) + , m_motionEventPending(false) + , m_deadZone(0.f) { - GHOST_NDOFLibraryInit_fp ndofLibraryInit = 0; - GHOST_NDOFLibraryShutdown_fp ndofLibraryShutdown = 0; - GHOST_NDOFDeviceOpen_fp ndofDeviceOpen = 0; + // to avoid the rare situation where one triple is updated and + // the other is not, initialize them both here: + memset(m_translation, 0, sizeof(m_translation)); + memset(m_rotation, 0, sizeof(m_rotation)); } -GHOST_NDOFManager::GHOST_NDOFManager() +bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short product_id) { - m_DeviceHandle = 0; + // default to NDOF_UnknownDevice so rogue button events will get discarded + // "mystery device" owners can help build a HID_map for their hardware + + switch (vendor_id) { + case 0x046D: // Logitech (3Dconnexion) + switch (product_id) { + // -- current devices -- + case 0xC626: + puts("ndof: using SpaceNavigator"); + m_deviceType = NDOF_SpaceNavigator; + m_buttonCount = 2; + break; + case 0xC628: + puts("ndof: using SpaceNavigator for Notebooks"); + m_deviceType = NDOF_SpaceNavigator; // for Notebooks + m_buttonCount = 2; + break; + case 0xC627: + puts("ndof: using SpaceExplorer"); + m_deviceType = NDOF_SpaceExplorer; + m_buttonCount = 15; + break; + case 0xC629: + puts("ndof: using SpacePilotPro"); + m_deviceType = NDOF_SpacePilotPro; + m_buttonCount = 31; + break; - // discover the API from the plugin - ndofLibraryInit = 0; - ndofLibraryShutdown = 0; - ndofDeviceOpen = 0; + // -- older devices -- + case 0xC625: + puts("ndof: using SpacePilot"); + m_deviceType = NDOF_SpacePilot; + m_buttonCount = 21; + break; + + case 0xC623: + puts("ndof: SpaceTraveler not supported, please file a bug report"); + m_buttonCount = 8; + break; + + default: + printf("ndof: unknown Logitech product %04hx\n", product_id); + } + break; + default: + printf("ndof: unknown device %04hx:%04hx\n", vendor_id, product_id); + } + + if (m_deviceType == NDOF_UnknownDevice) { + return false; + } + else { + m_buttonMask = ~(-1 << m_buttonCount); + +#ifdef DEBUG_NDOF_BUTTONS + printf("ndof: %d buttons -> hex:%X\n", m_buttonCount, m_buttonMask); +#endif + + return true; + } } -GHOST_NDOFManager::~GHOST_NDOFManager() +void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time) { - if (ndofLibraryShutdown) - ndofLibraryShutdown(m_DeviceHandle); + memcpy(m_translation, t, sizeof(m_translation)); + m_motionTime = time; + m_motionEventPending = true; +} - m_DeviceHandle = 0; +void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time) +{ + memcpy(m_rotation, r, sizeof(m_rotation)); + m_motionTime = time; + m_motionEventPending = true; +} + +void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, bool press, GHOST_TUns64 time, GHOST_IWindow* window) +{ + GHOST_EventNDOFButton* event = new GHOST_EventNDOFButton(time, window); + GHOST_TEventNDOFButtonData* data = (GHOST_TEventNDOFButtonData*) event->getData(); + + data->action = press ? GHOST_kPress : GHOST_kRelease; + data->button = button; + +#ifdef DEBUG_NDOF_BUTTONS + printf("%s %s\n", ndof_button_names[button], press ? "pressed" : "released"); +#endif + + m_system.pushEvent(event); } +void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key, bool press, GHOST_TUns64 time, GHOST_IWindow* window) +{ + GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp; + GHOST_EventKey* event = new GHOST_EventKey(time, type, window, key); + +#ifdef DEBUG_NDOF_BUTTONS + printf("keyboard %s\n", press ? "down" : "up"); +#endif -int -GHOST_NDOFManager::deviceOpen(GHOST_IWindow* window, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen) + m_system.pushEvent(event); +} + +void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 time) { - int Pid; - - ndofLibraryInit = setNdofLibraryInit; - ndofLibraryShutdown = setNdofLibraryShutdown; - ndofDeviceOpen = setNdofDeviceOpen; - - if (ndofLibraryInit && ndofDeviceOpen) - { - Pid= ndofLibraryInit(); -#if 0 - printf("%i client \n", Pid); + GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); + +#ifdef DEBUG_NDOF_BUTTONS + if (m_deviceType != NDOF_UnknownDevice) + printf("ndof: button %d -> ", button_number); #endif - #if defined(WITH_HEADLESS) - /* do nothing */ - #elif defined(_WIN32) || defined(__APPLE__) - m_DeviceHandle = ndofDeviceOpen((void *)¤tNdofValues); - #else - GHOST_SystemX11 *sys; - sys = static_cast<GHOST_SystemX11*>(GHOST_ISystem::getSystem()); - void *ndofInfo = sys->prepareNdofInfo(¤tNdofValues); - m_DeviceHandle = ndofDeviceOpen(ndofInfo); - #endif - return (Pid > 0) ? 0 : 1; - - } else - return 1; + + switch (m_deviceType) { + case NDOF_SpaceNavigator: + sendButtonEvent(SpaceNavigator_HID_map[button_number], press, time, window); + break; + case NDOF_SpaceExplorer: + switch (button_number) { + case 6: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; + case 7: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; + case 8: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; + case 9: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; + default: sendButtonEvent(SpaceExplorer_HID_map[button_number], press, time, window); + } + break; + case NDOF_SpacePilotPro: + switch (button_number) { + case 22: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; + case 23: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; + case 24: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; + case 25: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; + default: sendButtonEvent(SpacePilotPro_HID_map[button_number], press, time, window); + } + break; + case NDOF_SpacePilot: + switch (button_number) { + case 10: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; + case 11: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; + case 12: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; + case 13: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; + case 20: puts("ndof: ignoring CONFIG button"); break; + default: sendButtonEvent(SpacePilot_HID_map[button_number], press, time, window); + } + break; + case NDOF_UnknownDevice: + printf("ndof: button %d on unknown device (ignoring)\n", button_number); + } + + int mask = 1 << button_number; + if (press) { + m_buttons |= mask; // set this button's bit + } + else { + m_buttons &= ~mask; // clear this button's bit + } } +void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time) +{ + button_bits &= m_buttonMask; // discard any "garbage" bits + + int diff = m_buttons ^ button_bits; -bool -GHOST_NDOFManager::available() const -{ - return m_DeviceHandle != 0; + for (int button_number = 0; button_number < m_buttonCount; ++button_number) { + int mask = 1 << button_number; + + if (diff & mask) { + bool press = button_bits & mask; + updateButton(button_number, press, time); + } + } } -bool -GHOST_NDOFManager::event_present() const -{ - if( currentNdofValues.changed >0) { - printf("time %llu but%u x%i y%i z%i rx%i ry%i rz%i \n" , - currentNdofValues.time, currentNdofValues.buttons, - currentNdofValues.tx,currentNdofValues.ty,currentNdofValues.tz, - currentNdofValues.rx,currentNdofValues.ry,currentNdofValues.rz); - return true; - }else - return false; +void GHOST_NDOFManager::setDeadZone(float dz) +{ + if (dz < 0.f) { + // negative values don't make sense, so clamp at zero + dz = 0.f; + } + else if (dz > 0.5f) { + // warn the rogue user/programmer, but allow it + printf("ndof: dead zone of %.2f is rather high...\n", dz); + } + m_deadZone = dz; + printf("ndof: dead zone set to %.2f\n", dz); } -void GHOST_NDOFManager::GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const +static bool atHomePosition(GHOST_TEventNDOFMotionData* ndof) { - datas.tx = currentNdofValues.tx; - datas.ty = currentNdofValues.ty; - datas.tz = currentNdofValues.tz; - datas.rx = currentNdofValues.rx; - datas.ry = currentNdofValues.ry; - datas.rz = currentNdofValues.rz; - datas.buttons = currentNdofValues.buttons; - datas.client = currentNdofValues.client; - datas.address = currentNdofValues.address; - datas.time = currentNdofValues.time; - datas.delta = currentNdofValues.delta; +#define HOME(foo) (ndof->foo == 0) + return HOME(tx) && HOME(ty) && HOME(tz) && HOME(rx) && HOME(ry) && HOME(rz); +#undef HOME +} + +static bool nearHomePosition(GHOST_TEventNDOFMotionData* ndof, float threshold) +{ + if (threshold == 0.f) { + return atHomePosition(ndof); + } + else { +#define HOME1(foo) (fabsf(ndof->foo) < threshold) + return HOME1(tx) && HOME1(ty) && HOME1(tz) && HOME1(rx) && HOME1(ry) && HOME1(rz); +#undef HOME1 + } +} + +bool GHOST_NDOFManager::sendMotionEvent() +{ + if (!m_motionEventPending) + return false; + + m_motionEventPending = false; // any pending motion is handled right now + + GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); + + if (window == NULL) { + return false; // delivery will fail, so don't bother sending + } + + GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, window); + GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData(); + + // scale axis values here to normalize them to around +/- 1 + // they are scaled again for overall sensitivity in the WM based on user prefs + + const float scale = 1.f / 350.f; // 3Dconnexion devices send +/- 350 usually + + data->tx = scale * m_translation[0]; + data->ty = scale * m_translation[1]; + data->tz = scale * m_translation[2]; + + data->rx = scale * m_rotation[0]; + data->ry = scale * m_rotation[1]; + data->rz = scale * m_rotation[2]; + + data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds + + bool handMotion = !nearHomePosition(data, m_deadZone); + + // determine what kind of motion event to send (Starting, InProgress, Finishing) + // and where that leaves this NDOF manager (NotStarted, InProgress, Finished) + switch (m_motionState) { + case GHOST_kNotStarted: + case GHOST_kFinished: + if (handMotion) { + data->progress = GHOST_kStarting; + m_motionState = GHOST_kInProgress; + // prev motion time will be ancient, so just make up something reasonable + data->dt = 0.0125f; + } + else { + // send no event and keep current state + delete event; + return false; + } + break; + case GHOST_kInProgress: + if (handMotion) { + data->progress = GHOST_kInProgress; + // keep InProgress state + } + else { + data->progress = GHOST_kFinishing; + m_motionState = GHOST_kFinished; + } + break; + default: + break; + } + +#ifdef DEBUG_NDOF_MOTION + printf("ndof motion sent -- %s\n", progress_string[data->progress]); + + // show details about this motion event + printf(" T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", + data->tx, data->ty, data->tz, + data->rx, data->ry, data->rz, + data->dt); +#endif + + m_system.pushEvent(event); + + m_prevMotionTime = m_motionTime; + + return true; } diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index c9e09370e09..5bdbe7a6833 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -1,4 +1,6 @@ /* + * $Id$ + * * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -15,43 +17,144 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Contributor(s): none yet. + * Contributor(s): + * Mike Erwin * * ***** END GPL LICENSE BLOCK ***** */ - -/** \file ghost/intern/GHOST_NDOFManager.h - * \ingroup GHOST - */ - #ifndef _GHOST_NDOFMANAGER_H_ #define _GHOST_NDOFMANAGER_H_ #include "GHOST_System.h" -#include "GHOST_IWindow.h" +// #define DEBUG_NDOF_MOTION +// #define DEBUG_NDOF_BUTTONS + +typedef enum { + NDOF_UnknownDevice, // <-- motion will work fine, buttons are ignored + + // current devices + NDOF_SpaceNavigator, + NDOF_SpaceExplorer, + NDOF_SpacePilotPro, + + // older devices + NDOF_SpacePilot + + } NDOF_DeviceT; + +// NDOF device button event types +typedef enum { + // used internally, never sent + NDOF_BUTTON_NONE, + // these two are available from any 3Dconnexion device + NDOF_BUTTON_MENU, + NDOF_BUTTON_FIT, + // standard views + NDOF_BUTTON_TOP, + NDOF_BUTTON_BOTTOM, + NDOF_BUTTON_LEFT, + NDOF_BUTTON_RIGHT, + NDOF_BUTTON_FRONT, + NDOF_BUTTON_BACK, + // more views + NDOF_BUTTON_ISO1, + NDOF_BUTTON_ISO2, + // 90 degree rotations + // these don't all correspond to physical buttons + NDOF_BUTTON_ROLL_CW, + NDOF_BUTTON_ROLL_CCW, + NDOF_BUTTON_SPIN_CW, + NDOF_BUTTON_SPIN_CCW, + NDOF_BUTTON_TILT_CW, + NDOF_BUTTON_TILT_CCW, + // device control + NDOF_BUTTON_ROTATE, + NDOF_BUTTON_PANZOOM, + NDOF_BUTTON_DOMINANT, + NDOF_BUTTON_PLUS, + NDOF_BUTTON_MINUS, + // general-purpose buttons + // users can assign functions via keymap editor + NDOF_BUTTON_1, + NDOF_BUTTON_2, + NDOF_BUTTON_3, + NDOF_BUTTON_4, + NDOF_BUTTON_5, + NDOF_BUTTON_6, + NDOF_BUTTON_7, + NDOF_BUTTON_8, + NDOF_BUTTON_9, + NDOF_BUTTON_10, + + } NDOF_ButtonT; class GHOST_NDOFManager { public: - GHOST_NDOFManager(); - virtual ~GHOST_NDOFManager(); - - int deviceOpen(GHOST_IWindow* window, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen); - - void GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const; - - bool available() const; - bool event_present() const; + GHOST_NDOFManager(GHOST_System&); + + virtual ~GHOST_NDOFManager() {}; + + // whether multi-axis functionality is available (via the OS or driver) + // does not imply that a device is plugged in or being used + virtual bool available() = 0; + + // each platform's device detection should call this + // use standard USB/HID identifiers + bool setDevice(unsigned short vendor_id, unsigned short product_id); + + // filter out small/accidental/uncalibrated motions by + // setting up a "dead zone" around home position + // set to 0 to disable + // 0.1 is a safe and reasonable value + void setDeadZone(float); + + // the latest raw axis data from the device + // NOTE: axis data should be in blender view coordinates + // +X is to the right + // +Y is up + // +Z is out of the screen + // for rotations, look from origin to each +axis + // rotations are + when CCW, - when CW + // each platform is responsible for getting axis data into this form + // these values should not be scaled (just shuffled or flipped) + void updateTranslation(short t[3], GHOST_TUns64 time); + void updateRotation(short r[3], GHOST_TUns64 time); + + // the latest raw button data from the device + // use HID button encoding (not NDOF_ButtonT) + void updateButton(int button_number, bool press, GHOST_TUns64 time); + void updateButtons(int button_bits, GHOST_TUns64 time); + // NDOFButton events are sent immediately + + // processes and sends most recent raw data as an NDOFMotion event + // returns whether an event was sent + bool sendMotionEvent(); protected: - void* m_DeviceHandle; -}; + GHOST_System& m_system; +private: + void sendButtonEvent(NDOF_ButtonT, bool press, GHOST_TUns64 time, GHOST_IWindow*); + void sendKeyEvent(GHOST_TKey, bool press, GHOST_TUns64 time, GHOST_IWindow*); + + NDOF_DeviceT m_deviceType; + int m_buttonCount; + int m_buttonMask; + + short m_translation[3]; + short m_rotation[3]; + int m_buttons; // bit field + + GHOST_TUns64 m_motionTime; // in milliseconds + GHOST_TUns64 m_prevMotionTime; // time of most recent Motion event sent + + GHOST_TProgress m_motionState; + bool m_motionEventPending; + float m_deadZone; // discard motion with each component < this +}; #endif diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h new file mode 100644 index 00000000000..27397b711b7 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h @@ -0,0 +1,50 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): + * Mike Erwin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef _GHOST_NDOFMANAGERCOCOA_H_ +#define _GHOST_NDOFMANAGERCOCOA_H_ + +#include "GHOST_NDOFManager.h" + +// Event capture is handled within the NDOF manager on Macintosh, +// so there's no need for SystemCocoa to look for them. + +class GHOST_NDOFManagerCocoa : public GHOST_NDOFManager +{ +public: + GHOST_NDOFManagerCocoa(GHOST_System&); + + ~GHOST_NDOFManagerCocoa(); + + // whether multi-axis functionality is available (via the OS or driver) + // does not imply that a device is plugged in or being used + bool available(); + +private: + unsigned short m_clientID; +}; + + +#endif diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm new file mode 100644 index 00000000000..53a991a7396 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -0,0 +1,172 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): + * Mike Erwin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "GHOST_NDOFManagerCocoa.h" +#include "GHOST_SystemCocoa.h" + +extern "C" { + #include <3DconnexionClient/ConnexionClientAPI.h> + #include <stdio.h> + } + +// static functions need to talk to these objects: +static GHOST_SystemCocoa* ghost_system = NULL; +static GHOST_NDOFManager* ndof_manager = NULL; + +// 3Dconnexion drivers before 10.x are "old" +// not all buttons will work +static bool has_old_driver = true; + +static void NDOF_DeviceAdded(io_connect_t connection) +{ + printf("ndof: device added\n"); // change these: printf --> informational reports + +#if 0 // device preferences will be useful some day + ConnexionDevicePrefs p; + ConnexionGetCurrentDevicePrefs(kDevID_AnyDevice, &p); +#endif + + // determine exactly which device is plugged in + SInt32 result = 0; + ConnexionControl(kConnexionCtlGetDeviceID, 0, &result); + unsigned short vendorID = result >> 16; + unsigned short productID = result & 0xffff; + + ndof_manager->setDevice(vendorID, productID); +} + +static void NDOF_DeviceRemoved(io_connect_t connection) +{ + printf("ndof: device removed\n"); +} + +static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, void* messageArgument) +{ + switch (messageType) + { + case kConnexionMsgDeviceState: + { + ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument; + + GHOST_TUns64 now = ghost_system->getMilliSeconds(); + + switch (s->command) + { + case kConnexionCmdHandleAxis: + { + // convert to blender view coordinates + short t[3] = {s->axis[0], -(s->axis[2]), s->axis[1]}; + short r[3] = {-(s->axis[3]), s->axis[5], -(s->axis[4])}; + + ndof_manager->updateTranslation(t, now); + ndof_manager->updateRotation(r, now); + + ghost_system->notifyExternalEventProcessed(); + break; + } + case kConnexionCmdHandleButtons: + { + int button_bits = has_old_driver ? s->buttons8 : s->buttons; + ndof_manager->updateButtons(button_bits, now); + ghost_system->notifyExternalEventProcessed(); + break; + } + case kConnexionCmdAppSpecific: + printf("ndof: app-specific command, param = %hd, value = %d\n", s->param, s->value); + break; + + default: + printf("ndof: mystery device command %d\n", s->command); + } + break; + } + case kConnexionMsgPrefsChanged: + // printf("ndof: prefs changed\n"); // this includes app switches + // TODO: look through updated prefs for things blender cares about + break; + case kConnexionMsgCalibrateDevice: + printf("ndof: calibrate\n"); // but what should blender do? + break; + case kConnexionMsgDoMapping: + // printf("ndof: driver did something\n"); + // sent when the driver itself consumes an NDOF event + // and performs whatever action is set in user prefs + // 3Dx header file says to ignore these + break; + default: + printf("ndof: mystery event %d\n", messageType); + } +} + +GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) + : GHOST_NDOFManager(sys) +{ + if (available()) + { + // give static functions something to talk to: + ghost_system = dynamic_cast<GHOST_SystemCocoa*>(&sys); + ndof_manager = this; + + OSErr error = InstallConnexionHandlers(NDOF_DeviceEvent, NDOF_DeviceAdded, NDOF_DeviceRemoved); + if (error) { + printf("ndof: error %d while installing handlers\n", error); + return; + } + + // Pascal string *and* a four-letter constant. How old-skool. + m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\007blender", + kConnexionClientModeTakeOver, kConnexionMaskAll); + + // printf("ndof: client id = %d\n", m_clientID); + + if (SetConnexionClientButtonMask != NULL) { + has_old_driver = false; + SetConnexionClientButtonMask(m_clientID, kConnexionMaskAllButtons); + } + else { + printf("ndof: old 3Dx driver installed, some buttons may not work\n"); + } + } + else { + printf("ndof: 3Dx driver not found\n"); + // This isn't a hard error, just means the user doesn't have a 3D mouse. + } +} + +GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() +{ + UnregisterConnexionClient(m_clientID); + CleanupConnexionHandlers(); + ghost_system = NULL; + ndof_manager = NULL; +} + +bool GHOST_NDOFManagerCocoa::available() +{ + // extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); + // ^^ not needed since the entire framework is weak-linked + return InstallConnexionHandlers != NULL; + // this means that the driver is installed and dynamically linked to blender +} diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp new file mode 100644 index 00000000000..fd62e845f7d --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp @@ -0,0 +1,45 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): + * Mike Erwin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifdef WITH_INPUT_NDOF // use contents of this file + +#include "GHOST_NDOFManagerWin32.h" + + +GHOST_NDOFManagerWin32::GHOST_NDOFManagerWin32(GHOST_System& sys) + : GHOST_NDOFManager(sys) +{ + setDeadZone(0.1f); +} + +// whether multi-axis functionality is available (via the OS or driver) +// does not imply that a device is plugged in or being used +bool GHOST_NDOFManagerWin32::available() +{ + // always available since RawInput is built into Windows + return true; +} + +#endif // WITH_INPUT_NDOF diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.h b/intern/ghost/intern/GHOST_NDOFManagerWin32.h new file mode 100644 index 00000000000..9f3eddeb3c8 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.h @@ -0,0 +1,44 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): + * Mike Erwin + * + * ***** END GPL LICENSE BLOCK ***** + */ + + +#ifndef _GHOST_NDOFMANAGERWIN32_H_ +#define _GHOST_NDOFMANAGERWIN32_H_ + +#ifdef WITH_INPUT_NDOF + +#include "GHOST_NDOFManager.h" + + +class GHOST_NDOFManagerWin32 : public GHOST_NDOFManager +{ +public: + GHOST_NDOFManagerWin32(GHOST_System&); + bool available(); +}; + + +#endif // WITH_INPUT_NDOF +#endif // #include guard diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp new file mode 100644 index 00000000000..099fa15d179 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp @@ -0,0 +1,106 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): + * Mike Erwin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "GHOST_NDOFManagerX11.h" +#include "GHOST_SystemX11.h" +#include <spnav.h> +#include <stdio.h> + + +GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys) + : + GHOST_NDOFManager(sys), + m_available(false) +{ + setDeadZone(0.1f); // how to calibrate on Linux? throw away slight motion! + + if (spnav_open() != -1) { + // determine exactly which device (if any) is plugged in + +#define MAX_LINE_LENGTH 100 + + // look for USB devices with Logitech's vendor ID + FILE* command_output = popen("lsusb -d 046d:","r"); + if (command_output) { + char line[MAX_LINE_LENGTH] = {0}; + while (fgets(line, MAX_LINE_LENGTH, command_output)) { + unsigned short vendor_id = 0, product_id = 0; + if (sscanf(line, "Bus %*d Device %*d: ID %hx:%hx", &vendor_id, &product_id) == 2) + if (setDevice(vendor_id, product_id)) { + m_available = true; + break; // stop looking once the first 3D mouse is found + } + } + pclose(command_output); + } + } + else { + printf("ndof: spacenavd not found\n"); + // This isn't a hard error, just means the user doesn't have a 3D mouse. + } +} + +GHOST_NDOFManagerX11::~GHOST_NDOFManagerX11() +{ + if (m_available) + spnav_close(); +} + +bool GHOST_NDOFManagerX11::available() +{ + return m_available; +} + +//bool GHOST_NDOFManagerX11::identifyDevice() +//{ +// +//} + +bool GHOST_NDOFManagerX11::processEvents() +{ + GHOST_TUns64 now = m_system.getMilliSeconds(); + + bool anyProcessed = false; + spnav_event e; + while (spnav_poll_event(&e)) { + switch (e.type) { + case SPNAV_EVENT_MOTION: + { + // convert to blender view coords + short t[3] = {e.motion.x, e.motion.y, -e.motion.z}; + short r[3] = {-e.motion.rx, -e.motion.ry, e.motion.rz}; + + updateTranslation(t, now); + updateRotation(r, now); + break; + } + case SPNAV_EVENT_BUTTON: + updateButton(e.button.bnum, e.button.press, now); + break; + } + anyProcessed = true; + } + return anyProcessed; +} diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.h b/intern/ghost/intern/GHOST_NDOFManagerX11.h new file mode 100644 index 00000000000..82bd256c707 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.h @@ -0,0 +1,49 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): + * Mike Erwin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef _GHOST_NDOFMANAGERX11_H_ +#define _GHOST_NDOFMANAGERX11_H_ + +#include "GHOST_NDOFManager.h" + +/* Event capture is handled within the NDOF manager on Linux, + * so there's no need for SystemX11 to look for them. */ + +class GHOST_NDOFManagerX11 : public GHOST_NDOFManager +{ +public: + GHOST_NDOFManagerX11(GHOST_System&); + ~GHOST_NDOFManagerX11(); + bool available(); + bool processEvents(); + +private: + // bool identifyDevice(); + + bool m_available; +}; + +#endif + diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index cb3e97fc574..64c2c218a07 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -46,7 +46,13 @@ GHOST_System::GHOST_System() -: m_displayManager(0), m_timerManager(0), m_windowManager(0), m_eventManager(0), m_ndofManager(0) + : m_displayManager(0), + m_timerManager(0), + m_windowManager(0), + m_eventManager(0) +#ifdef WITH_INPUT_NDOF + , m_ndofManager(0) +#endif { } @@ -194,12 +200,17 @@ bool GHOST_System::getFullScreen(void) bool GHOST_System::dispatchEvents() { - bool handled; - if (m_eventManager) { - handled = m_eventManager->dispatchEvents(); + bool handled = false; + +#ifdef WITH_INPUT_NDOF + // NDOF Motion event is sent only once per dispatch, so do it now: + if (m_ndofManager) { + handled |= m_ndofManager->sendMotionEvent(); } - else { - handled = false; +#endif + + if (m_eventManager) { + handled |= m_eventManager->dispatchEvents(); } m_timerManager->fireTimers(getMilliSeconds()); @@ -243,18 +254,6 @@ GHOST_TSuccess GHOST_System::pushEvent(GHOST_IEvent* event) return success; } -int GHOST_System::openNDOF(GHOST_IWindow* w, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen) -{ - return m_ndofManager->deviceOpen(w, - setNdofLibraryInit, - setNdofLibraryShutdown, - setNdofDeviceOpen); -} - - GHOST_TSuccess GHOST_System::getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const { GHOST_ModifierKeys keys; @@ -285,12 +284,6 @@ GHOST_TSuccess GHOST_System::init() m_timerManager = new GHOST_TimerManager (); m_windowManager = new GHOST_WindowManager (); m_eventManager = new GHOST_EventManager (); - m_ndofManager = new GHOST_NDOFManager(); - -#if 0 - if(m_ndofManager) - printf("ndof manager \n"); -#endif #ifdef GHOST_DEBUG if (m_eventManager) { @@ -328,10 +321,12 @@ GHOST_TSuccess GHOST_System::exit() delete m_eventManager; m_eventManager = 0; } +#ifdef WITH_INPUT_NDOF if (m_ndofManager) { delete m_ndofManager; m_ndofManager = 0; } +#endif return GHOST_kSuccess; } diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index b5c64bfceb6..c1e70916be6 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -191,25 +191,6 @@ public: virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer* consumer); /*************************************************************************************** - ** N-degree of freedom devcice management functionality - ***************************************************************************************/ - - /** Inherited from GHOST_ISystem - * Opens the N-degree of freedom device manager - * return 0 if device found, 1 otherwise - */ - virtual int openNDOF(GHOST_IWindow* w, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen); - -// original patch only -// GHOST_NDOFEventHandler_fp setNdofEventHandler); - - - - - /*************************************************************************************** ** Cursor management functionality ***************************************************************************************/ @@ -268,11 +249,13 @@ public: */ virtual inline GHOST_WindowManager* getWindowManager() const; +#ifdef WITH_INPUT_NDOF /** * Returns a pointer to our n-degree of freedeom manager. * @return A pointer to our n-degree of freedeom manager. */ virtual inline GHOST_NDOFManager* getNDOFManager() const; +#endif /** * Returns the state of all modifier keys. @@ -337,8 +320,10 @@ protected: /** The event manager. */ GHOST_EventManager* m_eventManager; - /** The N-degree of freedom device manager */ - GHOST_NDOFManager* m_ndofManager; +#ifdef WITH_INPUT_NDOF + /** The N-degree of freedom device manager */ + GHOST_NDOFManager* m_ndofManager; +#endif /** Prints all the events. */ #ifdef GHOST_DEBUG @@ -364,10 +349,12 @@ inline GHOST_WindowManager* GHOST_System::getWindowManager() const return m_windowManager; } +#ifdef WITH_INPUT_NDOF inline GHOST_NDOFManager* GHOST_System::getNDOFManager() const { return m_ndofManager; } +#endif #endif // _GHOST_SYSTEM_H_ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index ce777358389..d20aed63f42 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -221,6 +221,11 @@ public: GHOST_TSuccess handleApplicationBecomeActiveEvent(); /** + * External objects should call this when they send an event outside processEvents. + */ + void notifyExternalEventProcessed(); + + /** * @see GHOST_ISystem */ int toggleConsole(int action) { return 0; } @@ -267,7 +272,7 @@ protected: /** Start time at initialization. */ GHOST_TUns64 m_start_time; - /** Event has been processed directly by Cocoa and has sent a ghost event to be dispatched */ + /** Event has been processed directly by Cocoa (or NDOF manager) and has sent a ghost event to be dispatched */ bool m_outsideLoopEventProcessed; /** Raised window is not yet known by the window manager, so delay application become active event handling */ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 69423f2dfbf..17f0f2d6ecd 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -52,7 +52,7 @@ #include "GHOST_TimerTask.h" #include "GHOST_WindowManager.h" #include "GHOST_WindowCocoa.h" -#include "GHOST_NDOFManager.h" +#include "GHOST_NDOFManagerCocoa.h" #include "AssertMacros.h" #pragma mark KeyMap, mouse converters @@ -596,6 +596,11 @@ GHOST_TSuccess GHOST_SystemCocoa::init() GHOST_TSuccess success = GHOST_System::init(); if (success) { + +#ifdef WITH_INPUT_NDOF + m_ndofManager = new GHOST_NDOFManagerCocoa(*this); +#endif + //ProcessSerialNumber psn; //Carbon stuff to move window & menu to foreground @@ -1007,6 +1012,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() return GHOST_kSuccess; } +void GHOST_SystemCocoa::notifyExternalEventProcessed() +{ + m_outsideLoopEventProcessed = true; +} + //Note: called from NSWindow delegate GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window) { @@ -1498,15 +1508,18 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) GHOST_TInt32 x_mouse= mousePos.x; GHOST_TInt32 y_mouse= mousePos.y; GHOST_TInt32 x_accum, y_accum, x_cur, y_cur, x, y; - GHOST_Rect bounds, correctedBounds; + GHOST_Rect bounds, windowBounds, correctedBounds; /* fallback to window bounds */ if(window->getCursorGrabBounds(bounds)==GHOST_kFailure) window->getClientBounds(bounds); //Switch back to Cocoa coordinates orientation (y=0 at botton,the same as blender internal btw!), and to client coordinates - window->screenToClient(bounds.m_l, bounds.m_b, correctedBounds.m_l, correctedBounds.m_b); - window->screenToClient(bounds.m_r, bounds.m_t, correctedBounds.m_r, correctedBounds.m_t); + window->getClientBounds(windowBounds); + window->screenToClient(bounds.m_l, bounds.m_b, correctedBounds.m_l, correctedBounds.m_t); + window->screenToClient(bounds.m_r, bounds.m_t, correctedBounds.m_r, correctedBounds.m_b); + correctedBounds.m_b = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_b; + correctedBounds.m_t = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_t; //Update accumulation counts window->getCursorGrabAccum(x_accum, y_accum); @@ -1557,6 +1570,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) GHOST_TInt32 delta; double deltaF = [event deltaY]; + + if (deltaF == 0.0) deltaF = [event deltaX]; // make blender decide if it's horizontal scroll if (deltaF == 0.0) break; //discard trackpad delta=0 events delta = deltaF > 0.0 ? 1 : -1; diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp index becccc2c29f..523d119c7e7 100644 --- a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp @@ -32,12 +32,9 @@ #include "GHOST_SystemPathsWin32.h" -#define WIN32_LEAN_AND_MEAN -#ifdef _WIN32_IE -#undef _WIN32_IE -#endif +#ifndef _WIN32_IE #define _WIN32_IE 0x0501 -#include <windows.h> +#endif #include <shlobj.h> #if defined(__MINGW32__) || defined(__CYGWIN__) diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.h b/intern/ghost/intern/GHOST_SystemPathsWin32.h index 67cc2140e0e..3de7bbf934e 100644 --- a/intern/ghost/intern/GHOST_SystemPathsWin32.h +++ b/intern/ghost/intern/GHOST_SystemPathsWin32.h @@ -38,6 +38,8 @@ #error WIN32 only! #endif // WIN32 +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include <windows.h> #include "GHOST_SystemPaths.h" diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp new file mode 100644 index 00000000000..69a9f936cf6 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemSDL.cpp @@ -0,0 +1,596 @@ +/* + * $Id$ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ghost/intern/GHOST_SystemSDL.cpp + * \ingroup GHOST + */ + +#include <assert.h> + +#include "GHOST_SystemSDL.h" + +#include "GHOST_WindowManager.h" + +#include "GHOST_EventCursor.h" +#include "GHOST_EventKey.h" +#include "GHOST_EventButton.h" +#include "GHOST_EventWheel.h" + +GHOST_SystemSDL::GHOST_SystemSDL() + : + GHOST_System() +{ + if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) { + printf ("Error initializing SDL: %s\n", SDL_GetError()); + } + + /* SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); */ + /* SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); */ + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); +} + +GHOST_SystemSDL::~GHOST_SystemSDL() +{ + SDL_Quit(); +} + +GHOST_IWindow * +GHOST_SystemSDL::createWindow(const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + bool stereoVisual, + const GHOST_TUns16 numOfAASamples, + const GHOST_TEmbedderWindowID parentWindow + ) +{ + GHOST_WindowSDL *window= NULL; + + window= new GHOST_WindowSDL (this, title, left, top, width, height, state, parentWindow, type, stereoVisual, 1); + + if (window) { + if (window->getValid()) { + m_windowManager->addWindow(window); + pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window)); + } + else { + delete window; + window= NULL; + } + } + return window; +} + +GHOST_TSuccess +GHOST_SystemSDL::init() { + GHOST_TSuccess success = GHOST_System::init(); + + if (success) { + m_displayManager = new GHOST_DisplayManagerSDL(this); + + if (m_displayManager) { + return GHOST_kSuccess; + } + } + + return GHOST_kFailure; +} + +void +GHOST_SystemSDL::getMainDisplayDimensions(GHOST_TUns32& width, + GHOST_TUns32& height) const +{ + SDL_DisplayMode mode; + SDL_GetCurrentDisplayMode(0, &mode); /* note, always 0 display */ + width= mode.w; + height= mode.h; +} + +GHOST_TUns8 +GHOST_SystemSDL::getNumDisplays() const +{ + return SDL_GetNumVideoDisplays(); +} + +GHOST_TSuccess +GHOST_SystemSDL::getModifierKeys(GHOST_ModifierKeys& keys) const +{ + SDL_Keymod mod= SDL_GetModState(); + + keys.set(GHOST_kModifierKeyLeftShift, (mod & KMOD_LSHIFT) != 0); + keys.set(GHOST_kModifierKeyRightShift, (mod & KMOD_RSHIFT) != 0); + keys.set(GHOST_kModifierKeyLeftControl, (mod & KMOD_LCTRL) != 0); + keys.set(GHOST_kModifierKeyRightControl, (mod & KMOD_RCTRL) != 0); + keys.set(GHOST_kModifierKeyLeftAlt, (mod & KMOD_LALT) != 0); + keys.set(GHOST_kModifierKeyRightAlt, (mod & KMOD_RALT) != 0); + keys.set(GHOST_kModifierKeyOS, (mod & (KMOD_LGUI|KMOD_RGUI)) != 0); + + return GHOST_kSuccess; +} + +#define GXMAP(k,x,y) case x: k= y; break; + +static GHOST_TKey +convertSDLKey(SDL_Scancode key) +{ + GHOST_TKey type; + + if ((key >= SDL_SCANCODE_A) && (key <= SDL_SCANCODE_Z)) { + type= GHOST_TKey( key - SDL_SCANCODE_A + int(GHOST_kKeyA)); + } else if ((key >= SDL_SCANCODE_1) && (key <= SDL_SCANCODE_0)) { + type= GHOST_TKey(key - SDL_SCANCODE_1 + int(GHOST_kKey0)); + } else if ((key >= SDL_SCANCODE_F1) && (key <= SDL_SCANCODE_F12)) { + type= GHOST_TKey(key - SDL_SCANCODE_F1 + int(GHOST_kKeyF1)); + } else if ((key >= SDL_SCANCODE_F13) && (key <= SDL_SCANCODE_F24)) { + type= GHOST_TKey(key - SDL_SCANCODE_F13 + int(GHOST_kKeyF13)); + } else { + switch(key) { + /* TODO SDL_SCANCODE_NONUSBACKSLASH */ + + GXMAP(type,SDL_SCANCODE_BACKSPACE, GHOST_kKeyBackSpace); + GXMAP(type,SDL_SCANCODE_TAB, GHOST_kKeyTab); + GXMAP(type,SDL_SCANCODE_RETURN, GHOST_kKeyEnter); + GXMAP(type,SDL_SCANCODE_ESCAPE, GHOST_kKeyEsc); + GXMAP(type,SDL_SCANCODE_SPACE, GHOST_kKeySpace); + + GXMAP(type,SDL_SCANCODE_SEMICOLON, GHOST_kKeySemicolon); + GXMAP(type,SDL_SCANCODE_PERIOD, GHOST_kKeyPeriod); + GXMAP(type,SDL_SCANCODE_COMMA, GHOST_kKeyComma); + GXMAP(type,SDL_SCANCODE_APOSTROPHE, GHOST_kKeyQuote); + GXMAP(type,SDL_SCANCODE_GRAVE, GHOST_kKeyAccentGrave); + GXMAP(type,SDL_SCANCODE_MINUS, GHOST_kKeyMinus); + GXMAP(type,SDL_SCANCODE_SLASH, GHOST_kKeySlash); + GXMAP(type,SDL_SCANCODE_BACKSLASH, GHOST_kKeyBackslash); + GXMAP(type,SDL_SCANCODE_KP_EQUALS, GHOST_kKeyEqual); + GXMAP(type,SDL_SCANCODE_LEFTBRACKET, GHOST_kKeyLeftBracket); + GXMAP(type,SDL_SCANCODE_RIGHTBRACKET, GHOST_kKeyRightBracket); + GXMAP(type,SDL_SCANCODE_PAUSE, GHOST_kKeyPause); + + GXMAP(type,SDL_SCANCODE_LSHIFT, GHOST_kKeyLeftShift); + GXMAP(type,SDL_SCANCODE_RSHIFT, GHOST_kKeyRightShift); + GXMAP(type,SDL_SCANCODE_LCTRL, GHOST_kKeyLeftControl); + GXMAP(type,SDL_SCANCODE_RCTRL, GHOST_kKeyRightControl); + GXMAP(type,SDL_SCANCODE_LALT, GHOST_kKeyLeftAlt); + GXMAP(type,SDL_SCANCODE_RALT, GHOST_kKeyRightAlt); + GXMAP(type,SDL_SCANCODE_LGUI, GHOST_kKeyOS); + GXMAP(type,SDL_SCANCODE_RGUI, GHOST_kKeyOS); + + GXMAP(type,SDL_SCANCODE_INSERT, GHOST_kKeyInsert); + GXMAP(type,SDL_SCANCODE_DELETE, GHOST_kKeyDelete); + GXMAP(type,SDL_SCANCODE_HOME, GHOST_kKeyHome); + GXMAP(type,SDL_SCANCODE_END, GHOST_kKeyEnd); + GXMAP(type,SDL_SCANCODE_PAGEUP, GHOST_kKeyUpPage); + GXMAP(type,SDL_SCANCODE_PAGEDOWN, GHOST_kKeyDownPage); + + GXMAP(type,SDL_SCANCODE_LEFT, GHOST_kKeyLeftArrow); + GXMAP(type,SDL_SCANCODE_RIGHT, GHOST_kKeyRightArrow); + GXMAP(type,SDL_SCANCODE_UP, GHOST_kKeyUpArrow); + GXMAP(type,SDL_SCANCODE_DOWN, GHOST_kKeyDownArrow); + + GXMAP(type,SDL_SCANCODE_CAPSLOCK, GHOST_kKeyCapsLock); + GXMAP(type,SDL_SCANCODE_SCROLLLOCK, GHOST_kKeyScrollLock); + GXMAP(type,SDL_SCANCODE_NUMLOCKCLEAR, GHOST_kKeyNumLock); + + /* keypad events */ + + /* note, sdl defines a bunch of kp defines I never saw before like + * SDL_SCANCODE_KP_PERCENT, SDL_SCANCODE_KP_XOR - campbell */ + GXMAP(type,SDL_SCANCODE_KP_0, GHOST_kKeyNumpad0); + GXMAP(type,SDL_SCANCODE_KP_1, GHOST_kKeyNumpad1); + GXMAP(type,SDL_SCANCODE_KP_2, GHOST_kKeyNumpad2); + GXMAP(type,SDL_SCANCODE_KP_3, GHOST_kKeyNumpad3); + GXMAP(type,SDL_SCANCODE_KP_4, GHOST_kKeyNumpad4); + GXMAP(type,SDL_SCANCODE_KP_5, GHOST_kKeyNumpad5); + GXMAP(type,SDL_SCANCODE_KP_6, GHOST_kKeyNumpad6); + GXMAP(type,SDL_SCANCODE_KP_7, GHOST_kKeyNumpad7); + GXMAP(type,SDL_SCANCODE_KP_8, GHOST_kKeyNumpad8); + GXMAP(type,SDL_SCANCODE_KP_9, GHOST_kKeyNumpad9); + GXMAP(type,SDL_SCANCODE_KP_PERIOD, GHOST_kKeyNumpadPeriod); + + GXMAP(type,SDL_SCANCODE_KP_ENTER, GHOST_kKeyNumpadEnter); + GXMAP(type,SDL_SCANCODE_KP_PLUS, GHOST_kKeyNumpadPlus); + GXMAP(type,SDL_SCANCODE_KP_MINUS, GHOST_kKeyNumpadMinus); + GXMAP(type,SDL_SCANCODE_KP_MULTIPLY, GHOST_kKeyNumpadAsterisk); + GXMAP(type,SDL_SCANCODE_KP_DIVIDE, GHOST_kKeyNumpadSlash); + + /* Media keys in some keyboards and laptops with XFree86/Xorg */ + GXMAP(type,SDL_SCANCODE_AUDIOPLAY, GHOST_kKeyMediaPlay); + GXMAP(type,SDL_SCANCODE_AUDIOSTOP, GHOST_kKeyMediaStop); + GXMAP(type,SDL_SCANCODE_AUDIOPREV, GHOST_kKeyMediaFirst); + // GXMAP(type,XF86XK_AudioRewind, GHOST_kKeyMediaFirst); + GXMAP(type,SDL_SCANCODE_AUDIONEXT, GHOST_kKeyMediaLast); + + default: + printf("Unknown\n"); + type= GHOST_kKeyUnknown; + break; + } + } + + return type; +} +#undef GXMAP + + +void +GHOST_SystemSDL::processEvent(SDL_Event *sdl_event) +{ + GHOST_Event * g_event= NULL; + + switch(sdl_event->type) { + case SDL_WINDOWEVENT: + { + SDL_WindowEvent &sdl_sub_evt= sdl_event->window; + GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID)); + //assert(window != NULL); // can be NULL on close window. + + switch (sdl_sub_evt.event) { + case SDL_WINDOWEVENT_EXPOSED: + g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window); + break; + case SDL_WINDOWEVENT_RESIZED: + g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window); + break; + case SDL_WINDOWEVENT_MOVED: + g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window); + break; + case SDL_WINDOWEVENT_FOCUS_GAINED: + g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window); + break; + case SDL_WINDOWEVENT_FOCUS_LOST: + g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window); + break; + case SDL_WINDOWEVENT_CLOSE: + g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window); + break; + } + } + break; + case SDL_QUIT: + g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL); + break; + + case SDL_MOUSEMOTION: + { + SDL_MouseMotionEvent &sdl_sub_evt= sdl_event->motion; + SDL_Window *sdl_win= SDL_GetWindowFromID(sdl_sub_evt.windowID); + GHOST_WindowSDL *window= findGhostWindow(sdl_win); + assert(window != NULL); + + int x_win, y_win; + SDL_GetWindowPosition(sdl_win, &x_win, &y_win); + + GHOST_TInt32 x_root= sdl_sub_evt.x + x_win; + GHOST_TInt32 y_root= sdl_sub_evt.y + y_win; + +#if 0 + if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal) + { + GHOST_TInt32 x_new= x_root; + GHOST_TInt32 y_new= y_root; + GHOST_TInt32 x_accum, y_accum; + GHOST_Rect bounds; + + /* fallback to window bounds */ + if(window->getCursorGrabBounds(bounds)==GHOST_kFailure) + window->getClientBounds(bounds); + + /* could also clamp to screen bounds + * wrap with a window outside the view will fail atm */ + bounds.wrapPoint(x_new, y_new, 8); /* offset of one incase blender is at screen bounds */ + window->getCursorGrabAccum(x_accum, y_accum); + + // cant use setCursorPosition because the mouse may have no focus! + if(x_new != x_root || y_new != y_root) { + if (1 ) { //xme.time > m_last_warp) { + /* when wrapping we don't need to add an event because the + * setCursorPosition call will cause a new event after */ + SDL_WarpMouseInWindow(sdl_win, x_new - x_win, y_new - y_win); /* wrap */ + window->setCursorGrabAccum(x_accum + (x_root - x_new), y_accum + (y_root - y_new)); + // m_last_warp= lastEventTime(xme.time); + } else { + // setCursorPosition(x_new, y_new); /* wrap but don't accumulate */ + SDL_WarpMouseInWindow(sdl_win, x_new - x_win, y_new - y_win); + } + + g_event = new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, x_new, y_new); + } + else { + g_event = new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, x_root + x_accum, y_root + y_accum); + } + } + else +#endif + { + g_event= new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, x_root, y_root); + } + break; + } + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEBUTTONDOWN: + { + SDL_MouseButtonEvent &sdl_sub_evt= sdl_event->button; + GHOST_TButtonMask gbmask= GHOST_kButtonMaskLeft; + GHOST_TEventType type= (sdl_sub_evt.state==SDL_PRESSED) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp; + + GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID)); + assert(window != NULL); + + /* process rest of normal mouse buttons */ + if(sdl_sub_evt.button == SDL_BUTTON_LEFT) + gbmask= GHOST_kButtonMaskLeft; + else if(sdl_sub_evt.button == SDL_BUTTON_MIDDLE) + gbmask= GHOST_kButtonMaskMiddle; + else if(sdl_sub_evt.button == SDL_BUTTON_RIGHT) + gbmask= GHOST_kButtonMaskRight; + /* these buttons are untested! */ + else if(sdl_sub_evt.button == SDL_BUTTON_X1) + gbmask= GHOST_kButtonMaskButton4; + else if(sdl_sub_evt.button == SDL_BUTTON_X2) + gbmask= GHOST_kButtonMaskButton5; + else + break; + + g_event= new GHOST_EventButton(getMilliSeconds(), type, window, gbmask); + break; + } + case SDL_MOUSEWHEEL: + { + SDL_MouseWheelEvent &sdl_sub_evt= sdl_event->wheel; + GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID)); + assert(window != NULL); + g_event= new GHOST_EventWheel(getMilliSeconds(), window, sdl_sub_evt.y); + } + break; + case SDL_KEYDOWN: + case SDL_KEYUP: + { + SDL_KeyboardEvent &sdl_sub_evt= sdl_event->key; + SDL_Keycode sym= sdl_sub_evt.keysym.sym; + GHOST_TEventType type= (sdl_sub_evt.state == SDL_PRESSED) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp; + + GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID)); + assert(window != NULL); + + GHOST_TKey gkey= convertSDLKey(sdl_sub_evt.keysym.scancode); + /* note, the sdl_sub_evt.keysym.sym is truncated, for unicode support ghost has to be modified */ + if(sym > 127) { + sym= 0; + } + else { + if(sdl_sub_evt.keysym.mod & (KMOD_LSHIFT|KMOD_RSHIFT)) { + /* lame US keyboard assumptions */ + if(sym >= 'a' && sym <= ('a' + 32)) { + sym -= 32; + } + else { + switch(sym) { + case '`': sym= '~'; break; + case '1': sym= '!'; break; + case '2': sym= '@'; break; + case '3': sym= '#'; break; + case '4': sym= '$'; break; + case '5': sym= '%'; break; + case '6': sym= '^'; break; + case '7': sym= '&'; break; + case '8': sym= '*'; break; + case '9': sym= '('; break; + case '0': sym= ')'; break; + case '-': sym= '_'; break; + case '=': sym= '+'; break; + case '[': sym= '{'; break; + case ']': sym= '}'; break; + case '\\': sym= '|'; break; + case ';': sym= ':'; break; + case '\'': sym= '"'; break; + case ',': sym= '<'; break; + case '.': sym= '>'; break; + case '/': sym= '?'; break; + default: break; + } + } + } + } + + g_event= new GHOST_EventKey(getMilliSeconds(), type, window, gkey, sym); + } + break; + } + + if (g_event) { + pushEvent(g_event); + } +} + +GHOST_TSuccess +GHOST_SystemSDL::getCursorPosition(GHOST_TInt32& x, + GHOST_TInt32& y) const +{ + int x_win, y_win; + SDL_Window *win= SDL_GetMouseFocus(); + SDL_GetWindowPosition(win, &x_win, &y_win); + + int xi, yi; + SDL_GetMouseState(&xi, &yi); + x= xi + x_win; + y= yi + x_win; + + return GHOST_kSuccess; +} + +GHOST_TSuccess +GHOST_SystemSDL::setCursorPosition(GHOST_TInt32 x, + GHOST_TInt32 y) +{ + int x_win, y_win; + SDL_Window *win= SDL_GetMouseFocus(); + SDL_GetWindowPosition(win, &x_win, &y_win); + + SDL_WarpMouseInWindow(win, x - x_win, y - y_win); + return GHOST_kSuccess; +} + +bool +GHOST_SystemSDL::generateWindowExposeEvents() +{ + vector<GHOST_WindowSDL *>::iterator w_start= m_dirty_windows.begin(); + vector<GHOST_WindowSDL *>::const_iterator w_end= m_dirty_windows.end(); + bool anyProcessed= false; + + for (;w_start != w_end; ++w_start) { + GHOST_Event * g_event= new + GHOST_Event( + getMilliSeconds(), + GHOST_kEventWindowUpdate, + *w_start + ); + + (*w_start)->validate(); + + if (g_event) { + printf("Expose events pushed\n"); + pushEvent(g_event); + anyProcessed= true; + } + } + + m_dirty_windows.clear(); + return anyProcessed; +} + + +bool +GHOST_SystemSDL::processEvents(bool waitForEvent) +{ + // Get all the current events -- translate them into + // ghost events and call base class pushEvent() method. + + bool anyProcessed= false; + + do { + GHOST_TimerManager* timerMgr= getTimerManager(); + + if (waitForEvent && m_dirty_windows.empty() && !SDL_HasEvents(SDL_FIRSTEVENT, SDL_LASTEVENT)) { + GHOST_TUns64 next= timerMgr->nextFireTime(); + + if (next==GHOST_kFireTimeNever) { + SDL_WaitEventTimeout(NULL, -1); + //SleepTillEvent(m_display, -1); + } else { + GHOST_TInt64 maxSleep= next - getMilliSeconds(); + + if(maxSleep >= 0) { + SDL_WaitEventTimeout(NULL, next - getMilliSeconds()); + // SleepTillEvent(m_display, next - getMilliSeconds()); // X11 + } + } + } + + if (timerMgr->fireTimers(getMilliSeconds())) { + anyProcessed= true; + } + + SDL_Event sdl_event; + while (SDL_PollEvent(&sdl_event)) { + processEvent(&sdl_event); + anyProcessed= true; + } + + if (generateWindowExposeEvents()) { + anyProcessed= true; + } + } while (waitForEvent && !anyProcessed); + + return anyProcessed; +} + + +GHOST_WindowSDL * +GHOST_SystemSDL::findGhostWindow(SDL_Window *sdl_win) +{ + if (sdl_win == NULL) return NULL; + + // It is not entirely safe to do this as the backptr may point + // to a window that has recently been removed. + // We should always check the window manager's list of windows + // and only process events on these windows. + + vector<GHOST_IWindow *> & win_vec= m_windowManager->getWindows(); + + vector<GHOST_IWindow *>::iterator win_it= win_vec.begin(); + vector<GHOST_IWindow *>::const_iterator win_end= win_vec.end(); + + for (; win_it != win_end; ++win_it) { + GHOST_WindowSDL * window= static_cast<GHOST_WindowSDL *>(*win_it); + if (window->getSDLWindow() == sdl_win) { + return window; + } + } + return NULL; +} + + +void +GHOST_SystemSDL::addDirtyWindow(GHOST_WindowSDL *bad_wind) +{ + GHOST_ASSERT((bad_wind != NULL), "addDirtyWindow() NULL ptr trapped (window)"); + + m_dirty_windows.push_back(bad_wind); +} + + +GHOST_TSuccess GHOST_SystemSDL::getButtons(GHOST_Buttons& buttons) const +{ + Uint8 state= SDL_GetMouseState(NULL, NULL); + buttons.set(GHOST_kButtonMaskLeft, (state & SDL_BUTTON_LMASK) != 0); + buttons.set(GHOST_kButtonMaskMiddle, (state & SDL_BUTTON_MMASK) != 0); + buttons.set(GHOST_kButtonMaskRight, (state & SDL_BUTTON_RMASK) != 0); + + return GHOST_kSuccess; +} + +GHOST_TUns8 * +GHOST_SystemSDL::getClipboard(bool selection) const +{ + return (GHOST_TUns8 *)SDL_GetClipboardText(); +} + +void +GHOST_SystemSDL::putClipboard(GHOST_TInt8 *buffer, bool selection) const +{ + SDL_SetClipboardText(buffer); +} + +GHOST_TUns64 +GHOST_SystemSDL::getMilliSeconds() +{ + return GHOST_TUns64(SDL_GetTicks()); /* note, 32 -> 64bits */ +} diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h new file mode 100644 index 00000000000..87d288117c5 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemSDL.h @@ -0,0 +1,126 @@ +/* + * $Id$ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ghost/intern/GHOST_SystemSDL.h + * \ingroup GHOST + * Declaration of GHOST_SystemSDL class. + */ + +#ifndef _GHOST_SYSTEM_SDL_H_ +#define _GHOST_SYSTEM_SDL_H_ + +#include "GHOST_System.h" +#include "../GHOST_Types.h" +#include "GHOST_DisplayManagerSDL.h" +#include "GHOST_TimerManager.h" +#include "GHOST_WindowSDL.h" +#include "GHOST_Event.h" + +extern "C" { + #include "SDL.h" +} + +#if !SDL_VERSION_ATLEAST(1, 3, 0) +# error "SDL 1.3 or newer is needed to build with Ghost" +#endif + + +class GHOST_WindowSDL; + + +class GHOST_SystemSDL : public GHOST_System { +public: + + void addDirtyWindow(GHOST_WindowSDL *bad_wind); + + GHOST_SystemSDL(); + ~GHOST_SystemSDL(); + + bool + processEvents(bool waitForEvent); + + int + toggleConsole(int action) { return 0; } + + GHOST_TSuccess + getModifierKeys(GHOST_ModifierKeys& keys) const; + + GHOST_TSuccess + getButtons(GHOST_Buttons& buttons) const; + + GHOST_TUns8 * + getClipboard(bool selection) const; + + void + putClipboard(GHOST_TInt8 *buffer, bool selection) const; + + GHOST_TUns64 + getMilliSeconds(); + + GHOST_TUns8 + getNumDisplays() const; + + GHOST_TSuccess + getCursorPosition(GHOST_TInt32& x, + GHOST_TInt32& y) const; + + GHOST_TSuccess + setCursorPosition(GHOST_TInt32 x, + GHOST_TInt32 y); + + void + getMainDisplayDimensions(GHOST_TUns32& width, + GHOST_TUns32& height) const; + +private: + + GHOST_TSuccess + init(); + + GHOST_IWindow * + createWindow(const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + bool stereoVisual, + const GHOST_TUns16 numOfAASamples, + const GHOST_TEmbedderWindowID parentWindow + ); + + /* SDL spesific */ + GHOST_WindowSDL * findGhostWindow(SDL_Window *sdl_win); + + bool + generateWindowExposeEvents(); + + void + processEvent(SDL_Event *sdl_event); + + /// The vector of windows that need to be updated. + std::vector<GHOST_WindowSDL *> m_dirty_windows; +}; + +#endif diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 143f7e97f2d..38f3985b139 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -39,22 +39,20 @@ * @date May 7, 2001 */ +#ifdef BF_GHOST_DEBUG #include <iostream> - -#ifdef FREE_WINDOWS -# define WINVER 0x0501 /* GetConsoleWindow() for MinGW */ #endif +#include <stdio.h> // [mce] temporary debug, remove soon! + #include "GHOST_SystemWin32.h" #include "GHOST_EventDragnDrop.h" -#define WIN32_LEAN_AND_MEAN -#ifdef _WIN32_IE -#undef _WIN32_IE +#ifndef _WIN32_IE +#define _WIN32_IE 0x0501 /* shipped before XP, so doesn't impose additional requirements */ #endif -#define _WIN32_IE 0x0501 -#include <windows.h> #include <shlobj.h> +#include <tlhelp32.h> // win64 doesn't define GWL_USERDATA #ifdef WIN32 @@ -64,48 +62,19 @@ #endif #endif -/* - * According to the docs the mouse wheel message is supported from windows 98 - * upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the - * wheel detent value are undefined. - */ -#ifndef WM_MOUSEWHEEL -#define WM_MOUSEWHEEL 0x020A -#endif // WM_MOUSEWHEEL -#ifndef WHEEL_DELTA -#define WHEEL_DELTA 120 /* Value for rolling one detent, (old convention! MS changed it) */ -#endif // WHEEL_DELTA - -/* - * Defines for mouse buttons 4 and 5 aka xbutton1 and xbutton2. - * MSDN: Declared in Winuser.h, include Windows.h - * This does not seem to work with MinGW so we define our own here. - */ -#ifndef XBUTTON1 -#define XBUTTON1 0x0001 -#endif // XBUTTON1 -#ifndef XBUTTON2 -#define XBUTTON2 0x0002 -#endif // XBUTTON2 -#ifndef WM_XBUTTONUP -#define WM_XBUTTONUP 524 -#endif // WM_XBUTTONUP -#ifndef WM_XBUTTONDOWN -#define WM_XBUTTONDOWN 523 -#endif // WM_XBUTTONDOWN - -#include "GHOST_Debug.h" #include "GHOST_DisplayManagerWin32.h" #include "GHOST_EventButton.h" #include "GHOST_EventCursor.h" #include "GHOST_EventKey.h" #include "GHOST_EventWheel.h" -#include "GHOST_EventNDOF.h" #include "GHOST_TimerTask.h" #include "GHOST_TimerManager.h" #include "GHOST_WindowManager.h" #include "GHOST_WindowWin32.h" -#include "GHOST_NDOFManager.h" + +#ifdef WITH_INPUT_NDOF +#include "GHOST_NDOFManagerWin32.h" +#endif // Key code values not found in winuser.h #ifndef VK_MINUS @@ -158,18 +127,35 @@ #define VK_MEDIA_PLAY_PAUSE 0xB3 #endif // VK_MEDIA_PLAY_PAUSE -/* - Initiates WM_INPUT messages from keyboard - That way GHOST can retrieve true keys -*/ -GHOST_TInt32 GHOST_SystemWin32::initKeyboardRawInput(void) +static void initRawInput() { - RAWINPUTDEVICE device = {0}; - device.usUsagePage = 0x01; /* usUsagePage & usUsage for keyboard*/ - device.usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */ +#ifdef WITH_INPUT_NDOF +#define DEVICE_COUNT 2 +#else +#define DEVICE_COUNT 1 +#endif + + RAWINPUTDEVICE devices[DEVICE_COUNT]; + memset(devices, 0, DEVICE_COUNT * sizeof(RAWINPUTDEVICE)); - return RegisterRawInputDevices(&device, 1, sizeof(device)); -}; + // Initiates WM_INPUT messages from keyboard + // That way GHOST can retrieve true keys + devices[0].usUsagePage = 0x01; + devices[0].usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */ + +#ifdef WITH_INPUT_NDOF + // multi-axis mouse (SpaceNavigator, etc.) + devices[1].usUsagePage = 0x01; + devices[1].usUsage = 0x08; +#endif + + if (RegisterRawInputDevices(devices, DEVICE_COUNT, sizeof(RAWINPUTDEVICE))) + ; // yay! + else + printf("could not register for RawInput: %d\n", (int)GetLastError()); + +#undef DEVICE_COUNT +} GHOST_SystemWin32::GHOST_SystemWin32() : m_hasPerformanceCounter(false), m_freq(0), m_start(0) @@ -186,6 +172,10 @@ GHOST_SystemWin32::GHOST_SystemWin32() this->handleKeyboardChange(); // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32. OleInitialize(0); + +#ifdef WITH_INPUT_NDOF + m_ndofManager = new GHOST_NDOFManagerWin32(*this); +#endif } GHOST_SystemWin32::~GHOST_SystemWin32() @@ -244,6 +234,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow( // Store the pointer to the window // if (state != GHOST_kWindowStateFullScreen) { m_windowManager->addWindow(window); + m_windowManager->setActiveWindow(window); // } } else { @@ -384,22 +375,15 @@ GHOST_TSuccess GHOST_SystemWin32::init() GHOST_TSuccess success = GHOST_System::init(); /* Disable scaling on high DPI displays on Vista */ + HMODULE user32 = ::LoadLibraryA("user32.dll"); typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)(); LPFNSETPROCESSDPIAWARE SetProcessDPIAware = (LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware"); if (SetProcessDPIAware) SetProcessDPIAware(); - #ifdef NEED_RAW_PROC - pRegisterRawInputDevices = (LPFNDLLRRID)GetProcAddress(user32, "RegisterRawInputDevices"); - pGetRawInputData = (LPFNDLLGRID)GetProcAddress(user32, "GetRawInputData"); - #else - FreeLibrary(user32); - #endif - - /* Initiates WM_INPUT messages from keyboard */ - initKeyboardRawInput(); - + FreeLibrary(user32); + initRawInput(); // Determine whether this system has a high frequency performance counter. */ m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE; @@ -440,104 +424,84 @@ GHOST_TSuccess GHOST_SystemWin32::init() GHOST_TSuccess GHOST_SystemWin32::exit() { - #ifdef NEED_RAW_PROC - FreeLibrary(user32); - #endif - return GHOST_System::exit(); } -GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, int * keyDown, char * vk) +GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int * keyDown, char * vk) { - unsigned int size = 0; - char * data; GHOST_TKey key = GHOST_kKeyUnknown; if(!keyDown) return GHOST_kKeyUnknown; - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, 0, &size, sizeof(RAWINPUTHEADER)); + GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); - if((data = (char*)malloc(size)) && - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER))) + GHOST_ModifierKeys modifiers; + system->retrieveModifierKeys(modifiers); + + *keyDown = !(raw.data.keyboard.Flags & RI_KEY_BREAK); + key = this->convertKey(window, raw.data.keyboard.VKey, raw.data.keyboard.MakeCode, (raw.data.keyboard.Flags&(RI_KEY_E1|RI_KEY_E0))); + + // extra handling of modifier keys: don't send repeats out from GHOST + if(key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt) { - RAWINPUT ri; - memcpy(&ri,data,(size < sizeof(ri)) ? size : sizeof(ri)); - - if (ri.header.dwType == RIM_TYPEKEYBOARD) - { - GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); - - GHOST_ModifierKeys modifiers; - system->retrieveModifierKeys(modifiers); - - *keyDown = !(ri.data.keyboard.Flags & RI_KEY_BREAK); - key = this->convertKey(window, ri.data.keyboard.VKey, ri.data.keyboard.MakeCode, (ri.data.keyboard.Flags&(RI_KEY_E1|RI_KEY_E0))); - - // extra handling of modifier keys: don't send repeats out from GHOST - if(key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt) - { - bool changed = false; - GHOST_TModifierKeyMask modifier; - switch(key) { - case GHOST_kKeyLeftShift: - { - changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != (bool)*keyDown); - modifier = GHOST_kModifierKeyLeftShift; - } - break; - case GHOST_kKeyRightShift: - { - changed = (modifiers.get(GHOST_kModifierKeyRightShift) != (bool)*keyDown); - modifier = GHOST_kModifierKeyRightShift; - } - break; - case GHOST_kKeyLeftControl: - { - changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != (bool)*keyDown); - modifier = GHOST_kModifierKeyLeftControl; - } - break; - case GHOST_kKeyRightControl: - { - changed = (modifiers.get(GHOST_kModifierKeyRightControl) != (bool)*keyDown); - modifier = GHOST_kModifierKeyRightControl; - } - break; - case GHOST_kKeyLeftAlt: - { - changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != (bool)*keyDown); - modifier = GHOST_kModifierKeyLeftAlt; - } - break; - case GHOST_kKeyRightAlt: - { - changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != (bool)*keyDown); - modifier = GHOST_kModifierKeyRightAlt; - } - break; - default: break; + bool changed = false; + GHOST_TModifierKeyMask modifier; + switch(key) { + case GHOST_kKeyLeftShift: + { + changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != (bool)*keyDown); + modifier = GHOST_kModifierKeyLeftShift; } - - if(changed) + break; + case GHOST_kKeyRightShift: { - modifiers.set(modifier, (bool)*keyDown); - system->storeModifierKeys(modifiers); + changed = (modifiers.get(GHOST_kModifierKeyRightShift) != (bool)*keyDown); + modifier = GHOST_kModifierKeyRightShift; } - else + break; + case GHOST_kKeyLeftControl: { - key = GHOST_kKeyUnknown; + changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != (bool)*keyDown); + modifier = GHOST_kModifierKeyLeftControl; } - } - + break; + case GHOST_kKeyRightControl: + { + changed = (modifiers.get(GHOST_kModifierKeyRightControl) != (bool)*keyDown); + modifier = GHOST_kModifierKeyRightControl; + } + break; + case GHOST_kKeyLeftAlt: + { + changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != (bool)*keyDown); + modifier = GHOST_kModifierKeyLeftAlt; + } + break; + case GHOST_kKeyRightAlt: + { + changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != (bool)*keyDown); + modifier = GHOST_kModifierKeyRightAlt; + } + break; + default: break; + } + + if(changed) + { + modifiers.set(modifier, (bool)*keyDown); + system->storeModifierKeys(modifiers); + } + else + { + key = GHOST_kKeyUnknown; + } + } - if(vk) *vk = ri.data.keyboard.VKey; - }; - }; - free(data); + if(vk) *vk = raw.data.keyboard.VKey; return key; } @@ -741,12 +705,12 @@ GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WP } -GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam) +GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINPUT const& raw) { int keyDown=0; char vk; GHOST_SystemWin32 * system = (GHOST_SystemWin32 *)getSystem(); - GHOST_TKey key = system->hardKey(window, wParam, lParam, &keyDown, &vk); + GHOST_TKey key = system->hardKey(window, raw, &keyDown, &vk); GHOST_EventKey* event; if (key != GHOST_kKeyUnknown) { char ascii = '\0'; @@ -763,7 +727,7 @@ GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, WPARAM event = new GHOST_EventKey(system->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii); -#ifdef BF_GHOST_DEBUG +#ifdef GHOST_DEBUG std::cout << ascii << std::endl; #endif } @@ -776,7 +740,13 @@ GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, WPARAM GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window) { - return new GHOST_Event(getSystem()->getMilliSeconds(), type, window); + GHOST_System* system = (GHOST_System*)getSystem(); + + if (type == GHOST_kEventWindowActivate) { + system->getWindowManager()->setActiveWindow(window); + } + + return new GHOST_Event(system->getMilliSeconds(), type, window); } GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType, @@ -799,9 +769,95 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax) minmax->ptMinTrackSize.y=240; } +#ifdef WITH_INPUT_NDOF +bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) +{ + bool eventSent = false; + GHOST_TUns64 now = getMilliSeconds(); + + static bool firstEvent = true; + if (firstEvent) { // determine exactly which device is plugged in + RID_DEVICE_INFO info; + unsigned infoSize = sizeof(RID_DEVICE_INFO); + info.cbSize = infoSize; + + GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize); + if (info.dwType == RIM_TYPEHID) + m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId); + else + puts("<!> not a HID device... mouse/kb perhaps?"); + + firstEvent = false; + } + + // The NDOF manager sends button changes immediately, and *pretends* to + // send motion. Mark as 'sent' so motion will always get dispatched. + eventSent = true; + +#ifdef _MSC_VER + // using Microsoft compiler & header files + // they invented the RawInput API, so this version is (probably) correct + BYTE const* data = raw.data.hid.bRawData; + // struct RAWHID { + // DWORD dwSizeHid; + // DWORD dwCount; + // BYTE bRawData[1]; + // }; +#else + // MinGW's definition (below) doesn't agree, so we need a slight + // workaround until it's fixed + BYTE const* data = &raw.data.hid.bRawData; + // struct RAWHID { + // DWORD dwSizeHid; + // DWORD dwCount; + // BYTE bRawData; // <== isn't this s'posed to be a BYTE*? + // }; +#endif + + BYTE packetType = data[0]; + switch (packetType) + { + case 1: // translation + { + short* axis = (short*)(data + 1); + // massage into blender view coords (same goes for rotation) + short t[3] = {axis[0], -axis[2], axis[1]}; + m_ndofManager->updateTranslation(t, now); + + if (raw.data.hid.dwSizeHid == 13) + { // this report also includes rotation + short r[3] = {-axis[3], axis[5], -axis[4]}; + m_ndofManager->updateRotation(r, now); + + // I've never gotten one of these, has anyone else? + puts("ndof: combined T + R"); + } + break; + } + case 2: // rotation + { + short* axis = (short*)(data + 1); + short r[3] = {-axis[0], axis[2], -axis[1]}; + m_ndofManager->updateRotation(r, now); + break; + } + case 3: // buttons + { + int button_bits; + memcpy(&button_bits, data + 1, sizeof(button_bits)); + m_ndofManager->updateButtons(button_bits, now); + break; + } + } + return eventSent; +} +#endif // WITH_INPUT_NDOF + LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { GHOST_Event* event = 0; + bool eventHandled = false; + LRESULT lResult = 0; GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem()); GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized") @@ -818,18 +874,38 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, // Keyboard events, processed //////////////////////////////////////////////////////////////////////// case WM_INPUT: + { // check WM_INPUT from input sink when ghost window is not in the foreground if (wParam == RIM_INPUTSINK) { if (GetFocus() != hwnd) // WM_INPUT message not for this window return 0; - } //else wPAram == RIM_INPUT - event = processKeyEvent(window, wParam, lParam); - if (!event) { - GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") - GHOST_PRINT(msg) - GHOST_PRINT(" key ignored\n") + } //else wParam == RIM_INPUT + + RAWINPUT raw; + RAWINPUT* raw_ptr = &raw; + UINT rawSize = sizeof(RAWINPUT); + + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); + + switch (raw.header.dwType) + { + case RIM_TYPEKEYBOARD: + event = processKeyEvent(window, raw); + if (!event) { + GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") + GHOST_PRINT(msg) + GHOST_PRINT(" key ignored\n") + } + break; +#ifdef WITH_INPUT_NDOF + case RIM_TYPEHID: + if (system->processNDOF(raw)) + eventHandled = true; + break; +#endif } - break; + break; + } //////////////////////////////////////////////////////////////////////// // Keyboard events, ignored //////////////////////////////////////////////////////////////////////// @@ -839,9 +915,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, case WM_SYSKEYUP: /* These functions were replaced by WM_INPUT*/ case WM_CHAR: - /* The WM_CHAR message is posted to the window with the keyboard focus when - * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR - * contains the character code of the key that was pressed. + /* The WM_CHAR message is posted to the window with the keyboard focus when + * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR + * contains the character code of the key that was pressed. */ case WM_DEADCHAR: /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a @@ -989,11 +1065,16 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * procedure of the top-level window being activated. If the windows use different input queues, * the message is sent asynchronously, so the window is activated immediately. */ + { + GHOST_ModifierKeys modifiers; + modifiers.clear(); + system->storeModifierKeys(modifiers); event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window); /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL will not be dispatched to OUR active window if we minimize one of OUR windows. */ lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); break; + } case WM_PAINT: /* An application sends the WM_PAINT message when the system or another application * makes a request to paint a portion of an application's window. The message is sent @@ -1122,28 +1203,6 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * In GHOST, we let DefWindowProc call the timer callback. */ break; - case WM_BLND_NDOF_AXIS: - { - GHOST_TEventNDOFData ndofdata; - system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata); - system->m_eventManager-> - pushEvent(new GHOST_EventNDOF( - system->getMilliSeconds(), - GHOST_kEventNDOFMotion, - window, ndofdata)); - } - break; - case WM_BLND_NDOF_BTN: - { - GHOST_TEventNDOFData ndofdata; - system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata); - system->m_eventManager-> - pushEvent(new GHOST_EventNDOF( - system->getMilliSeconds(), - GHOST_kEventNDOFButton, - window, ndofdata)); - } - break; } } else { @@ -1165,10 +1224,12 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, if (event) { system->pushEvent(event); + eventHandled = true; } - else { + + if (!eventHandled) lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); - } + return lResult; } @@ -1237,8 +1298,32 @@ int GHOST_SystemWin32::toggleConsole(int action) { case 3: //hide if no console { - CONSOLE_SCREEN_BUFFER_INFO csbi = {{0}}; - if(!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) || csbi.dwCursorPosition.X || csbi.dwCursorPosition.Y>1) + DWORD sp = GetCurrentProcessId(); + HANDLE ptree = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + PROCESSENTRY32 e = {0}; e.dwSize = sizeof(PROCESSENTRY32); + + if( Process32First(ptree, &e)) { + do { //Searches for Blender's PROCESSENTRY32 + if (e.th32ProcessID == sp) { + sp = e.th32ParentProcessID; + Process32First(ptree, &e); + do { //Got parent id, searches for its PROCESSENTRY32 + if (e.th32ProcessID == sp) { + if(strcmp("explorer.exe",e.szExeFile)==0) + { //If explorer, hide cmd + ShowWindow(GetConsoleWindow(),SW_HIDE); + m_consoleStatus = 0; + } + break; + } + + } while( Process32Next(ptree, &e)); + break; + } + } while( Process32Next(ptree, &e)); + } + + CloseHandle(ptree); break; } case 0: //hide diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 729ad56d875..858312b3eb1 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -38,7 +38,10 @@ #error WIN32 only! #endif // WIN32 +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include <windows.h> +#include <ole2.h> // for drag-n-drop #include "GHOST_System.h" @@ -46,95 +49,6 @@ # define __int64 long long #endif -#ifndef WM_INPUT -#define WM_INPUT 0x00FF -#endif -#ifndef RID_INPUT -#define RID_INPUT 0x10000003 -#endif -#ifndef RIM_INPUTSINK -#define RIM_INPUTSINK 0x1 -#endif -#ifndef RI_KEY_BREAK -#define RI_KEY_BREAK 0x1 -#endif -#ifndef RI_KEY_E0 -#define RI_KEY_E0 0x2 -#endif -#ifndef RI_KEY_E1 -#define RI_KEY_E1 0x4 -#endif -#ifndef RIM_TYPEMOUSE -#define RIM_TYPEMOUSE 0x0 -#define RIM_TYPEKEYBOARD 0x1 -#define RIM_TYPEHID 0x2 - -typedef struct tagRAWINPUTDEVICE { - USHORT usUsagePage; - USHORT usUsage; - DWORD dwFlags; - HWND hwndTarget; -} RAWINPUTDEVICE; - - - -typedef struct tagRAWINPUTHEADER { - DWORD dwType; - DWORD dwSize; - HANDLE hDevice; - WPARAM wParam; -} RAWINPUTHEADER; - -typedef struct tagRAWMOUSE { - USHORT usFlags; - union { - ULONG ulButtons; - struct { - USHORT usButtonFlags; - USHORT usButtonData; - }; - }; - ULONG ulRawButtons; - LONG lLastX; - LONG lLastY; - ULONG ulExtraInformation; -} RAWMOUSE; - -typedef struct tagRAWKEYBOARD { - USHORT MakeCode; - USHORT Flags; - USHORT Reserved; - USHORT VKey; - UINT Message; - ULONG ExtraInformation; -} RAWKEYBOARD; - -typedef struct tagRAWHID { - DWORD dwSizeHid; - DWORD dwCount; - BYTE bRawData[1]; -} RAWHID; - -typedef struct tagRAWINPUT { - RAWINPUTHEADER header; - union { - RAWMOUSE mouse; - RAWKEYBOARD keyboard; - RAWHID hid; - } data; -} RAWINPUT; - -DECLARE_HANDLE(HRAWINPUT); -#endif - -#ifdef FREE_WINDOWS -#define NEED_RAW_PROC -typedef BOOL (WINAPI * LPFNDLLRRID)(RAWINPUTDEVICE*,UINT, UINT); - -typedef UINT (WINAPI * LPFNDLLGRID)(HRAWINPUT, UINT, LPVOID, PUINT, UINT); -#define GetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader) ((pGetRawInputData)?pGetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader):(UINT)-1) -#endif - class GHOST_EventButton; class GHOST_EventCursor; class GHOST_EventKey; @@ -314,14 +228,13 @@ protected: /** * Catches raw WIN32 key codes from WM_INPUT in the wndproc. - * @param window-> The window for this handling - * @param wParam The wParam from the wndproc - * @param lParam The lParam from the wndproc + * @param window The window for this handling + * @param raw RawInput structure with detailed info about the key event * @param keyDown Pointer flag that specify if a key is down * @param vk Pointer to virtual key * @return The GHOST key (GHOST_kKeyUnknown if no match). */ - virtual GHOST_TKey hardKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, int * keyDown, char * vk); + virtual GHOST_TKey hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int * keyDown, char * vk); /** * Creates modifier key event(s) and updates the key data stored locally (m_modifierKeys). @@ -362,10 +275,9 @@ protected: * In most cases this is a straightforward conversion of key codes. * For the modifier keys however, we want to distinguish left and right keys. * @param window The window receiving the event (the active window). - * @param wParam The wParam from the wndproc - * @param lParam The lParam from the wndproc + * @param raw RawInput structure with detailed info about the key event */ - static GHOST_EventKey* processKeyEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam); + static GHOST_EventKey* processKeyEvent(GHOST_IWindow *window, RAWINPUT const& raw); /** * Process special keys (VK_OEM_*), to see if current key layout @@ -383,12 +295,24 @@ protected: * @return The event created. */ static GHOST_Event* processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window); - /** + + /** * Handles minimum window size. * @param minmax The MINMAXINFO structure. */ static void processMinMaxInfo(MINMAXINFO * minmax); - + +#ifdef WITH_INPUT_NDOF + /** + * Handles Motion and Button events from a SpaceNavigator or related device. + * Instead of returning an event object, this function communicates directly + * with the GHOST_NDOFManager. + * @param raw RawInput structure with detailed info about the NDOF event + * @return Whether an event was generated and sent. + */ + bool processNDOF(RAWINPUT const& raw); +#endif + /** * Returns the local state of the modifier keys (from the message queue). * @param keys The state of the keys. @@ -413,11 +337,6 @@ protected: static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); /** - * Initiates WM_INPUT messages from keyboard - */ - GHOST_TInt32 initKeyboardRawInput(void); - - /** * Toggles console * @action 0 - Hides * 1 - Shows @@ -445,15 +364,6 @@ protected: /** Console status */ int m_consoleStatus; - - /** handle for user32.dll*/ - HMODULE user32; - #ifdef NEED_RAW_PROC - /* pointer to RegisterRawInputDevices function */ - LPFNDLLRRID pRegisterRawInputDevices; - /* pointer to GetRawInputData function */ - LPFNDLLGRID pGetRawInputData; - #endif }; inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const @@ -487,4 +397,3 @@ inline void GHOST_SystemWin32::handleKeyboardChange(void) } } #endif // _GHOST_SYSTEM_WIN32_H_ - diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index c53bf7de36c..105f71b514f 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -42,8 +42,7 @@ #include "GHOST_EventKey.h" #include "GHOST_EventButton.h" #include "GHOST_EventWheel.h" -#include "GHOST_EventNDOF.h" -#include "GHOST_NDOFManager.h" +#include "GHOST_NDOFManagerX11.h" #include "GHOST_DisplayManagerX11.h" #include "GHOST_Debug.h" @@ -76,18 +75,8 @@ #include <stdio.h> // for fprintf only #include <cstdlib> // for exit -typedef struct NDOFPlatformInfo { - Display *display; - Window window; - volatile GHOST_TEventNDOFData *currValues; - Atom cmdAtom; - Atom motionAtom; - Atom btnPressAtom; - Atom btnRelAtom; -} NDOFPlatformInfo; - -static NDOFPlatformInfo sNdofInfo = {NULL, 0, NULL, 0, 0, 0, 0}; - +static GHOST_TKey +convertXKey(KeySym key); //these are for copy and select copy static char *txt_cut_buffer= NULL; @@ -147,8 +136,9 @@ GHOST_SystemX11( if (gettimeofday(&tv,NULL) == -1) { GHOST_ASSERT(false,"Could not instantiate timer!"); } - - m_start_time = GHOST_TUns64(tv.tv_sec*1000 + tv.tv_usec/1000); + + // Taking care not to overflow the tv.tv_sec*1000 + m_start_time = GHOST_TUns64(tv.tv_sec)*1000 + tv.tv_usec/1000; /* use detectable autorepeate, mac and windows also do this */ @@ -177,6 +167,9 @@ init( GHOST_TSuccess success = GHOST_System::init(); if (success) { +#ifdef WITH_INPUT_NDOF + m_ndofManager = new GHOST_NDOFManagerX11(*this); +#endif m_displayManager = new GHOST_DisplayManagerX11(this); if (m_displayManager) { @@ -196,7 +189,8 @@ getMilliSeconds( GHOST_ASSERT(false,"Could not compute time!"); } - return GHOST_TUns64(tv.tv_sec*1000 + tv.tv_usec/1000) - m_start_time; + // Taking care not to overflow the tv.tv_sec*1000 + return GHOST_TUns64(tv.tv_sec)*1000 + tv.tv_usec/1000 - m_start_time; } GHOST_TUns8 @@ -270,7 +264,7 @@ createWindow( if (window->getValid()) { // Store the pointer to the window m_windowManager->addWindow(window); - + m_windowManager->setActiveWindow(window); pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); } else { @@ -381,8 +375,6 @@ lastEventTime(Time default_time) { return data.timestamp; } - - bool GHOST_SystemX11:: processEvents( @@ -423,6 +415,13 @@ processEvents( if (generateWindowExposeEvents()) { anyProcessed = true; } + +#ifdef WITH_INPUT_NDOF + if (dynamic_cast<GHOST_NDOFManagerX11*>(m_ndofManager)->processEvents()) { + anyProcessed = true; + } +#endif + } while (waitForEvent && !anyProcessed); return anyProcessed; @@ -606,6 +605,9 @@ GHOST_SystemX11::processEvent(XEvent *xe) case FocusOut: { XFocusChangeEvent &xfe = xe->xfocus; + + // TODO: make sure this is the correct place for activate/deactivate + // printf("X: focus %s for window %d\n", xfe.type == FocusIn ? "in" : "out", (int) xfe.window); // May have to look at the type of event and filter some // out. @@ -636,32 +638,8 @@ GHOST_SystemX11::processEvent(XEvent *xe) ); } else #endif - if (sNdofInfo.currValues) { - static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0}; - if (xcme.message_type == sNdofInfo.motionAtom) - { - data.changed = 1; - data.delta = xcme.data.s[8] - data.time; - data.time = xcme.data.s[8]; - data.tx = xcme.data.s[2] >> 2; - data.ty = xcme.data.s[3] >> 2; - data.tz = xcme.data.s[4] >> 2; - data.rx = xcme.data.s[5]; - data.ry = xcme.data.s[6]; - data.rz =-xcme.data.s[7]; - g_event = new GHOST_EventNDOF(getMilliSeconds(), - GHOST_kEventNDOFMotion, - window, data); - } else if (xcme.message_type == sNdofInfo.btnPressAtom) { - data.changed = 2; - data.delta = xcme.data.s[8] - data.time; - data.time = xcme.data.s[8]; - data.buttons = xcme.data.s[2]; - g_event = new GHOST_EventNDOF(getMilliSeconds(), - GHOST_kEventNDOFButton, - window, data); - } - } else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) { + + if (((Atom)xcme.data.l[0]) == m_wm_take_focus) { XWindowAttributes attr; Window fwin; int revert_to; @@ -718,6 +696,14 @@ GHOST_SystemX11::processEvent(XEvent *xe) xce.y_root ); } + + // printf("X: %s window %d\n", xce.type == EnterNotify ? "entering" : "leaving", (int) xce.window); + + if (xce.type == EnterNotify) + m_windowManager->setActiveWindow(window); + else + m_windowManager->setWindowInactive(window); + break; } case MapNotify: @@ -829,6 +815,8 @@ GHOST_SystemX11::processEvent(XEvent *xe) } } +#if 0 // obsolete SpaceNav code + void * GHOST_SystemX11:: prepareNdofInfo(volatile GHOST_TEventNDOFData *currentNdofValues) @@ -841,6 +829,8 @@ prepareNdofInfo(volatile GHOST_TEventNDOFData *currentNdofValues) return (void*)&sNdofInfo; } +#endif + GHOST_TSuccess GHOST_SystemX11:: getModifierKeys( @@ -856,60 +846,28 @@ getModifierKeys( // now translate key symobols into keycodes and // test with vector. - const KeyCode shift_l = XKeysymToKeycode(m_display,XK_Shift_L); - const KeyCode shift_r = XKeysymToKeycode(m_display,XK_Shift_R); - const KeyCode control_l = XKeysymToKeycode(m_display,XK_Control_L); - const KeyCode control_r = XKeysymToKeycode(m_display,XK_Control_R); - const KeyCode alt_l = XKeysymToKeycode(m_display,XK_Alt_L); - const KeyCode alt_r = XKeysymToKeycode(m_display,XK_Alt_R); - const KeyCode super_l = XKeysymToKeycode(m_display,XK_Super_L); - const KeyCode super_r = XKeysymToKeycode(m_display,XK_Super_R); - - // Shift - if ((m_keyboard_vector[shift_l >> 3] >> (shift_l & 7)) & 1) { - keys.set(GHOST_kModifierKeyLeftShift,true); - } else { - keys.set(GHOST_kModifierKeyLeftShift,false); - } - if ((m_keyboard_vector[shift_r >> 3] >> (shift_r & 7)) & 1) { - - keys.set(GHOST_kModifierKeyRightShift,true); - } else { - keys.set(GHOST_kModifierKeyRightShift,false); - } - - // control (weep) - if ((m_keyboard_vector[control_l >> 3] >> (control_l & 7)) & 1) { - keys.set(GHOST_kModifierKeyLeftControl,true); - } else { - keys.set(GHOST_kModifierKeyLeftControl,false); - } - if ((m_keyboard_vector[control_r >> 3] >> (control_r & 7)) & 1) { - keys.set(GHOST_kModifierKeyRightControl,true); - } else { - keys.set(GHOST_kModifierKeyRightControl,false); - } - - // Alt (yawn) - if ((m_keyboard_vector[alt_l >> 3] >> (alt_l & 7)) & 1) { - keys.set(GHOST_kModifierKeyLeftAlt,true); - } else { - keys.set(GHOST_kModifierKeyLeftAlt,false); - } - if ((m_keyboard_vector[alt_r >> 3] >> (alt_r & 7)) & 1) { - keys.set(GHOST_kModifierKeyRightAlt,true); - } else { - keys.set(GHOST_kModifierKeyRightAlt,false); - } + const static KeyCode shift_l = XKeysymToKeycode(m_display,XK_Shift_L); + const static KeyCode shift_r = XKeysymToKeycode(m_display,XK_Shift_R); + const static KeyCode control_l = XKeysymToKeycode(m_display,XK_Control_L); + const static KeyCode control_r = XKeysymToKeycode(m_display,XK_Control_R); + const static KeyCode alt_l = XKeysymToKeycode(m_display,XK_Alt_L); + const static KeyCode alt_r = XKeysymToKeycode(m_display,XK_Alt_R); + const static KeyCode super_l = XKeysymToKeycode(m_display,XK_Super_L); + const static KeyCode super_r = XKeysymToKeycode(m_display,XK_Super_R); + + // shift + keys.set(GHOST_kModifierKeyLeftShift, ((m_keyboard_vector[shift_l >> 3] >> (shift_l & 7)) & 1) != 0); + keys.set(GHOST_kModifierKeyRightShift, ((m_keyboard_vector[shift_r >> 3] >> (shift_r & 7)) & 1) != 0); + // control + keys.set(GHOST_kModifierKeyLeftControl, ((m_keyboard_vector[control_l >> 3] >> (control_l & 7)) & 1) != 0); + keys.set(GHOST_kModifierKeyRightControl, ((m_keyboard_vector[control_r >> 3] >> (control_r & 7)) & 1) != 0); + // alt + keys.set(GHOST_kModifierKeyLeftAlt, ((m_keyboard_vector[alt_l >> 3] >> (alt_l & 7)) & 1) != 0); + keys.set(GHOST_kModifierKeyRightAlt, ((m_keyboard_vector[alt_r >> 3] >> (alt_r & 7)) & 1) != 0); + // super (windows) - only one GHOST-kModifierKeyOS, so mapping to either + keys.set(GHOST_kModifierKeyOS, ( ((m_keyboard_vector[super_l >> 3] >> (super_l & 7)) & 1) || + ((m_keyboard_vector[super_r >> 3] >> (super_r & 7)) & 1) ) != 0); - // Super (Windows) - only one GHOST-kModifierKeyOS, so mapping - // to either - if ( ((m_keyboard_vector[super_l >> 3] >> (super_l & 7)) & 1) || - ((m_keyboard_vector[super_r >> 3] >> (super_r & 7)) & 1) ) { - keys.set(GHOST_kModifierKeyOS,true); - } else { - keys.set(GHOST_kModifierKeyOS,false); - } return GHOST_kSuccess; } @@ -923,35 +881,20 @@ getButtons( int rx,ry,wx,wy; unsigned int mask_return; - if (XQueryPointer( - m_display, - RootWindow(m_display,DefaultScreen(m_display)), - &root_return, - &child_return, - &rx,&ry, - &wx,&wy, - &mask_return - ) == False) { + if (XQueryPointer(m_display, + RootWindow(m_display,DefaultScreen(m_display)), + &root_return, + &child_return, + &rx,&ry, + &wx,&wy, + &mask_return) == True) + { + buttons.set(GHOST_kButtonMaskLeft, (mask_return & Button1Mask) != 0); + buttons.set(GHOST_kButtonMaskMiddle, (mask_return & Button2Mask) != 0); + buttons.set(GHOST_kButtonMaskRight, (mask_return & Button3Mask) != 0); + } + else { return GHOST_kFailure; - } else { - - if (mask_return & Button1Mask) { - buttons.set(GHOST_kButtonMaskLeft,true); - } else { - buttons.set(GHOST_kButtonMaskLeft,false); - } - - if (mask_return & Button2Mask) { - buttons.set(GHOST_kButtonMaskMiddle,true); - } else { - buttons.set(GHOST_kButtonMaskMiddle,false); - } - - if (mask_return & Button3Mask) { - buttons.set(GHOST_kButtonMaskRight,true); - } else { - buttons.set(GHOST_kButtonMaskRight,false); - } } return GHOST_kSuccess; @@ -1056,11 +999,9 @@ generateWindowExposeEvents( #define GXMAP(k,x,y) case x: k = y; break; - GHOST_TKey -GHOST_SystemX11:: -convertXKey( - KeySym key -){ +static GHOST_TKey +convertXKey(KeySym key) +{ GHOST_TKey type; if ((key >= XK_A) && (key <= XK_Z)) { @@ -1175,8 +1116,10 @@ convertXKey( GXMAP(type,XF86XK_AudioPrev, GHOST_kKeyMediaFirst); GXMAP(type,XF86XK_AudioRewind, GHOST_kKeyMediaFirst); GXMAP(type,XF86XK_AudioNext, GHOST_kKeyMediaLast); +#ifdef XF86XK_AudioForward /* Debian lenny's XF86keysym.h has no XF86XK_AudioForward define */ GXMAP(type,XF86XK_AudioForward, GHOST_kKeyMediaLast); #endif +#endif /* some extra sun cruft (NICE KEYBOARD!) */ #ifdef __sun__ diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 0b001273634..845243f92e5 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -203,11 +203,6 @@ public: return m_display; } - void * - prepareNdofInfo( - volatile GHOST_TEventNDOFData *current_values - ); - /* Helped function for get data from the clipboard. */ void getClipboard_xcout(XEvent evt, Atom sel, Atom target, unsigned char **txt, unsigned long *len, @@ -300,12 +295,6 @@ private : bool generateWindowExposeEvents( ); - - GHOST_TKey - convertXKey( - KeySym key - ); - }; #endif diff --git a/intern/ghost/intern/GHOST_TaskbarWin32.h b/intern/ghost/intern/GHOST_TaskbarWin32.h index ef9ebdf5860..eddff8bb91b 100644 --- a/intern/ghost/intern/GHOST_TaskbarWin32.h +++ b/intern/ghost/intern/GHOST_TaskbarWin32.h @@ -3,20 +3,16 @@ */ #ifndef GHOST_TASKBARWIN32_H_ #define GHOST_TASKBARWIN32_H_ + #ifndef WIN32 #error WIN32 only! #endif // WIN32 +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include <windows.h> #include <shlobj.h> -/* MinGW needs it */ -#ifdef FREE_WINDOWS -#ifdef WINVER -#undef WINVER -#endif -#define WINVER 0x0501 -#endif /* FREE_WINDOWS */ // ITaskbarList, ITaskbarList2 and ITaskbarList3 might be missing, present here in that case. // Note, ITaskbarList3 is supported only since Windows 7, though. Check for that is done in diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h index 0ec3c6f5700..f979313af5c 100644 --- a/intern/ghost/intern/GHOST_WindowNULL.h +++ b/intern/ghost/intern/GHOST_WindowNULL.h @@ -54,7 +54,7 @@ public: const bool stereoVisual, const GHOST_TUns16 numOfAASamples ) : - GHOST_Window(title,left,top,width,height,state,type,stereoVisual,numOfAASamples), + GHOST_Window(width,height,state,type,stereoVisual,numOfAASamples), m_system (system) { setTitle(title); diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp new file mode 100644 index 00000000000..1675c1fb12b --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowSDL.cpp @@ -0,0 +1,628 @@ +/* + * $Id$ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ghost/intern/GHOST_WindowSDL.cpp + * \ingroup GHOST + */ + +#include "GHOST_WindowSDL.h" +#include "SDL_mouse.h" +#include <assert.h> + +static SDL_GLContext s_firstContext= NULL; + +GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system, + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + const GHOST_TEmbedderWindowID parentWindow, + GHOST_TDrawingContextType type, + const bool stereoVisual, + const GHOST_TUns16 numOfAASamples + ) + : + GHOST_Window(width,height,state,type,stereoVisual,numOfAASamples), + m_system (system), + m_invalid_window(false), + m_sdl_custom_cursor(NULL) +{ + m_sdl_win= SDL_CreateWindow(title, + left, + top, + width, + height, + SDL_WINDOW_RESIZABLE|SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN); + + //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + + m_sdl_glcontext= SDL_GL_CreateContext(m_sdl_win); + + //fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n", + // theEvent->error_code, theEvent->request_code) ; + + setTitle(title); +} + +GHOST_WindowSDL::~GHOST_WindowSDL() +{ + if(m_sdl_custom_cursor) { + SDL_FreeCursor(m_sdl_custom_cursor); + } + + if (m_sdl_glcontext != s_firstContext) { + SDL_GL_DeleteContext(m_sdl_glcontext); + } + + SDL_DestroyWindow(m_sdl_win); +} + + +GHOST_TSuccess +GHOST_WindowSDL::installDrawingContext(GHOST_TDrawingContextType type) +{ + // only support openGL for now. + GHOST_TSuccess success; + switch (type) { + case GHOST_kDrawingContextTypeOpenGL: + m_sdl_glcontext= SDL_GL_CreateContext(m_sdl_win); + + if (m_sdl_glcontext != NULL) { + if (!s_firstContext) { + s_firstContext= m_sdl_glcontext; + } + + success= (SDL_GL_MakeCurrent(m_sdl_win, m_sdl_glcontext) < 0) ? + GHOST_kFailure : GHOST_kSuccess; + } + else { + success= GHOST_kFailure; + } + + break; + + case GHOST_kDrawingContextTypeNone: + success= GHOST_kSuccess; + break; + + default: + success= GHOST_kFailure; + } + return success; +} + + +GHOST_TSuccess +GHOST_WindowSDL::invalidate(void) +{ + // So the idea of this function is to generate an expose event + // for the window. + // Unfortunately X does not handle expose events for you and + // it is the client's job to refresh the dirty part of the window. + // We need to queue up invalidate calls and generate GHOST events + // for them in the system. + + // We implement this by setting a boolean in this class to concatenate + // all such calls into a single event for this window. + + // At the same time we queue the dirty windows in the system class + // and generate events for them at the next processEvents call. + + if (m_invalid_window == false) { + m_system->addDirtyWindow(this); + m_invalid_window= true; + } + + return GHOST_kSuccess; +} + + +GHOST_TSuccess +GHOST_WindowSDL::swapBuffers() +{ + if (getDrawingContextType() == GHOST_kDrawingContextTypeOpenGL) { + SDL_GL_SwapWindow(m_sdl_win); + return GHOST_kSuccess; + } + else { + return GHOST_kFailure; + } +} + + +GHOST_TSuccess +GHOST_WindowSDL::activateDrawingContext() +{ + if (m_sdl_glcontext !=NULL) { + int status=SDL_GL_MakeCurrent(m_sdl_win, m_sdl_glcontext); + (void)status; + return GHOST_kSuccess; + } + return GHOST_kFailure; +} + + +GHOST_TSuccess +GHOST_WindowSDL::removeDrawingContext() +{ + GHOST_TSuccess success; + + if (m_sdl_glcontext != NULL) { + SDL_GL_DeleteContext(m_sdl_glcontext); + success= GHOST_kSuccess; + } + else { + success= GHOST_kFailure; + } + return success; +} + + +GHOST_TSuccess +GHOST_WindowSDL::setState(GHOST_TWindowState state) +{ + switch(state) { + case GHOST_kWindowStateNormal: + SDL_SetWindowFullscreen(m_sdl_win, SDL_FALSE); + SDL_RestoreWindow(m_sdl_win); + break; + case GHOST_kWindowStateMaximized: + SDL_SetWindowFullscreen(m_sdl_win, SDL_FALSE); + SDL_MaximizeWindow(m_sdl_win); + break; + case GHOST_kWindowStateMinimized: + SDL_MinimizeWindow(m_sdl_win); + break; + case GHOST_kWindowStateFullScreen: + SDL_SetWindowFullscreen(m_sdl_win, SDL_TRUE); + break; + default: + break; + } + + return GHOST_kSuccess; +} + + +GHOST_TWindowState +GHOST_WindowSDL::getState() const +{ + Uint32 flags= SDL_GetWindowFlags(m_sdl_win); + + if(flags & SDL_WINDOW_FULLSCREEN) return GHOST_kWindowStateFullScreen; + else if(flags & SDL_WINDOW_MAXIMIZED) return GHOST_kWindowStateMaximized; + else if(flags & SDL_WINDOW_MINIMIZED) return GHOST_kWindowStateMinimized; + return GHOST_kWindowStateNormal; +} + + +void +GHOST_WindowSDL::setTitle(const STR_String& title) +{ + SDL_SetWindowTitle(m_sdl_win, title.ReadPtr()); +} + + +void +GHOST_WindowSDL::getTitle(STR_String& title) const +{ + title= SDL_GetWindowTitle(m_sdl_win); +} + + +void +GHOST_WindowSDL::getWindowBounds(GHOST_Rect& bounds) const +{ + getClientBounds(bounds); +} + + +void +GHOST_WindowSDL::getClientBounds(GHOST_Rect& bounds) const +{ + int x, y, w, h; + SDL_GetWindowSize(m_sdl_win, &w, &h); + SDL_GetWindowPosition(m_sdl_win, &x, &y); + + bounds.m_l= x; + bounds.m_r= x + w; + bounds.m_t= y; + bounds.m_b= y + h; +} + +GHOST_TSuccess +GHOST_WindowSDL::setClientWidth(GHOST_TUns32 width) +{ + int height; + SDL_GetWindowSize(m_sdl_win, NULL, &height); + SDL_SetWindowSize(m_sdl_win, width, height); + return GHOST_kSuccess; +} + +GHOST_TSuccess +GHOST_WindowSDL::setClientHeight(GHOST_TUns32 height) +{ + int width; + SDL_GetWindowSize(m_sdl_win, &width, NULL); + SDL_SetWindowSize(m_sdl_win, width, height); + return GHOST_kSuccess; +} + +GHOST_TSuccess +GHOST_WindowSDL::setClientSize(GHOST_TUns32 width, + GHOST_TUns32 height) +{ + SDL_SetWindowSize(m_sdl_win, width, height); + return GHOST_kSuccess; +} + +void +GHOST_WindowSDL::screenToClient( GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY ) const +{ + /* XXXSDL_WEAK_ABS_COORDS */ + int x_win, y_win; + SDL_GetWindowPosition(m_sdl_win, &x_win, &y_win); + + outX = inX - x_win; + outY = inY - y_win; +} +void +GHOST_WindowSDL::clientToScreen( GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY ) const +{ + /* XXXSDL_WEAK_ABS_COORDS */ + int x_win, y_win; + SDL_GetWindowPosition(m_sdl_win, &x_win, &y_win); + + outX = inX + x_win; + outY = inY + y_win; +} + +/* mouse cursor */ +static unsigned char sdl_std_cursor_mask_xterm[]= {0xef,0x01,0xff,0x01,0xff,0x01,0x7c,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x7c,0x00,0xff,0x01,0xff,0x01,0xef,0x01,}; +static unsigned char sdl_std_cursor_xterm[]= {0x00,0x77,0x00,0x1c,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x1c,0x00,0x77,0x00,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_xterm 9 +#define sdl_std_cursor_HEIGHT_xterm 16 +#define sdl_std_cursor_HOT_X_xterm -3 +#define sdl_std_cursor_HOT_Y_xterm -7 + +static unsigned char sdl_std_cursor_mask_watch[]= {0xfc,0x0f,0xfc,0x0f,0xfc,0x0f,0xfe,0x1f,0xff,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xfe,0x1f,0xfc,0x0f,0xfc,0x0f,0xfc,0x0f,}; +static unsigned char sdl_std_cursor_watch[]= {0xf8,0x07,0xf8,0x07,0xf8,0x07,0xfc,0x0f,0x86,0x18,0x83,0x30,0x81,0xe0,0xc1,0xe1,0xc1,0xe1,0x21,0xe0,0x13,0x30,0x06,0x18,0xfc,0x0f,0xf8,0x07,0xf8,0x07,0xf8,0x07,}; +#define sdl_std_cursor_WIDTH_watch 16 +#define sdl_std_cursor_HEIGHT_watch 16 +#define sdl_std_cursor_HOT_X_watch -15 +#define sdl_std_cursor_HOT_Y_watch -7 + +static unsigned char sdl_std_cursor_mask_umbrella[]= {0xe8,0x76,0xfb,0xdf,0xfd,0x3f,0xfe,0xff,0xff,0x3f,0xff,0xff,0xcf,0x79,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x07,0xc0,0x07,0xc0,0x07,0xc0,0x07,0x80,0x03,}; +static unsigned char sdl_std_cursor_umbrella[]= {0x88,0x04,0x20,0x0a,0xc9,0x32,0xf2,0x09,0x4c,0x06,0x43,0x18,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x01,0x40,0x01,0x80,0x00,0x00,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_umbrella 16 +#define sdl_std_cursor_HEIGHT_umbrella 16 +#define sdl_std_cursor_HOT_X_umbrella -7 +#define sdl_std_cursor_HOT_Y_umbrella -12 + +static unsigned char sdl_std_cursor_mask_top_side[]= {0xff,0x7f,0xff,0x7f,0xff,0x7f,0xff,0x7f,0xc0,0x01,0xe0,0x03,0xf0,0x07,0xf8,0x0f,0xdc,0x1d,0xcc,0x19,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,}; +static unsigned char sdl_std_cursor_top_side[]= {0xff,0x1f,0xff,0x1f,0x00,0x00,0x40,0x00,0xe0,0x00,0x50,0x01,0x48,0x02,0x44,0x04,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_top_side 15 +#define sdl_std_cursor_HEIGHT_top_side 16 +#define sdl_std_cursor_HOT_X_top_side -6 +#define sdl_std_cursor_HOT_Y_top_side -14 + +static unsigned char sdl_std_cursor_mask_top_right_corner[]= {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf0,0xfc,0xf7,0xfc,0xf7,0xfc,0xf7,0xc0,0xf7,0xe0,0xf7,0x70,0xf7,0x38,0xf7,0x1c,0xf7,0x0c,0xf7,0x00,0xf0,0x00,0xf0,}; +static unsigned char sdl_std_cursor_top_right_corner[]= {0xff,0x3f,0xff,0x3f,0x00,0x30,0x00,0x30,0x00,0x30,0xfc,0x31,0x80,0x31,0x40,0x31,0x20,0x31,0x10,0x31,0x08,0x31,0x04,0x31,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_top_right_corner 16 +#define sdl_std_cursor_HEIGHT_top_right_corner 16 +#define sdl_std_cursor_HOT_X_top_right_corner -13 +#define sdl_std_cursor_HOT_Y_top_right_corner -14 + +static unsigned char sdl_std_cursor_mask_top_left_corner[]= {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0xef,0x3f,0xef,0x3f,0xef,0x3f,0xef,0x03,0xef,0x07,0xef,0x0e,0xef,0x1c,0xef,0x38,0xef,0x30,0x0f,0x00,0x0f,0x00,}; +static unsigned char sdl_std_cursor_top_left_corner[]= {0xff,0x3f,0xff,0x3f,0x03,0x00,0x03,0x00,0x03,0x00,0xe3,0x0f,0x63,0x00,0xa3,0x00,0x23,0x01,0x23,0x02,0x23,0x04,0x23,0x08,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_top_left_corner 16 +#define sdl_std_cursor_HEIGHT_top_left_corner 16 +#define sdl_std_cursor_HOT_X_top_left_corner 0 +#define sdl_std_cursor_HOT_Y_top_left_corner -14 + +static unsigned char sdl_std_cursor_mask_spraycan[]= {0x00,0x0c,0x18,0x0d,0x7c,0x0d,0x7c,0x0d,0x7e,0x0d,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,}; +static unsigned char sdl_std_cursor_spraycan[]= {0x00,0x06,0x80,0x00,0x2c,0x06,0x9e,0x00,0x16,0x06,0x3f,0x00,0x21,0x00,0x27,0x00,0x25,0x00,0x27,0x00,0x25,0x00,0x27,0x00,0x27,0x00,0x21,0x00,0x21,0x00,0x3f,0x00,}; +#define sdl_std_cursor_WIDTH_spraycan 12 +#define sdl_std_cursor_HEIGHT_spraycan 16 +#define sdl_std_cursor_HOT_X_spraycan -9 +#define sdl_std_cursor_HOT_Y_spraycan -14 + +static unsigned char sdl_std_cursor_mask_sb_v_double_arrow[]= {0x38,0x00,0x7c,0x00,0xfe,0x00,0xff,0x01,0xff,0x01,0x7c,0x00,0x7c,0x00,0x7c,0x00,0x7c,0x00,0x7c,0x00,0xff,0x01,0xff,0x01,0xfe,0x00,0x7c,0x00,0x38,0x00,}; +static unsigned char sdl_std_cursor_sb_v_double_arrow[]= {0x10,0x00,0x38,0x00,0x7c,0x00,0xfe,0x00,0x28,0x00,0x28,0x00,0x28,0x00,0x28,0x00,0x28,0x00,0x28,0x00,0x28,0x00,0xfe,0x00,0x7c,0x00,0x38,0x00,0x10,0x00,}; +#define sdl_std_cursor_WIDTH_sb_v_double_arrow 9 +#define sdl_std_cursor_HEIGHT_sb_v_double_arrow 15 +#define sdl_std_cursor_HOT_X_sb_v_double_arrow -3 +#define sdl_std_cursor_HOT_Y_sb_v_double_arrow -8 + +static unsigned char sdl_std_cursor_mask_sb_h_double_arrow[]= {0x18,0x0c,0x1c,0x1c,0xfe,0x3f,0xff,0x7f,0xff,0x7f,0xff,0x7f,0xfe,0x3f,0x1c,0x1c,0x18,0x0c,}; +static unsigned char sdl_std_cursor_sb_h_double_arrow[]= {0x00,0x00,0x08,0x08,0x0c,0x18,0xfe,0x3f,0x0f,0x78,0xfe,0x3f,0x0c,0x18,0x08,0x08,0x00,0x00}; +#define sdl_std_cursor_WIDTH_sb_h_double_arrow 15 +#define sdl_std_cursor_HEIGHT_sb_h_double_arrow 9 +#define sdl_std_cursor_HOT_X_sb_h_double_arrow -7 +#define sdl_std_cursor_HOT_Y_sb_h_double_arrow -4 + +static unsigned char sdl_std_cursor_mask_right_side[]= {0x00,0xf0,0x00,0xf0,0xc0,0xf0,0xc0,0xf1,0x80,0xf3,0x00,0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf7,0x80,0xf3,0xc0,0xf1,0xc0,0xf0,0x00,0xf0,0x00,0xf0,}; +static unsigned char sdl_std_cursor_right_side[]= {0x00,0x30,0x00,0x30,0x40,0x30,0x80,0x30,0x00,0x31,0x00,0x32,0xff,0x37,0x00,0x32,0x00,0x31,0x80,0x30,0x40,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_right_side 16 +#define sdl_std_cursor_HEIGHT_right_side 15 +#define sdl_std_cursor_HOT_X_right_side -13 +#define sdl_std_cursor_HOT_Y_right_side -7 + +static unsigned char sdl_std_cursor_mask_right_ptr[]= {0x00,0x03,0x80,0x03,0xc0,0x03,0xe0,0x03,0xf0,0x03,0xf8,0x03,0xfc,0x03,0xfe,0x03,0xff,0x03,0xff,0x03,0xf8,0x03,0xbc,0x03,0x3c,0x03,0x1e,0x00,0x1e,0x00,0x0c,0x00,}; +static unsigned char sdl_std_cursor_right_ptr[]= {0x00,0x80,0x00,0xc0,0x00,0xe0,0x00,0xf0,0x00,0xf8,0x00,0xfc,0x00,0xfe,0x00,0xff,0x00,0xf8,0x00,0xd8,0x00,0x8c,0x00,0x0c,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_right_ptr 10 +#define sdl_std_cursor_HEIGHT_right_ptr 16 +#define sdl_std_cursor_HOT_X_right_ptr -7 +#define sdl_std_cursor_HOT_Y_right_ptr -14 + +static unsigned char sdl_std_cursor_mask_question_arrow[]= {0xf8,0x00,0xfc,0x01,0xfe,0x03,0xff,0x07,0x8f,0x07,0x9f,0x07,0xde,0x07,0xfc,0x03,0xf8,0x01,0xf8,0x00,0xf8,0x00,0xfc,0x01,0xfe,0x03,0xfc,0x01,0xf8,0x00,0x70,0x00,}; +static unsigned char sdl_std_cursor_question_arrow[]= {0x7c,0x00,0xfe,0x00,0xc7,0x01,0x83,0x01,0x87,0x01,0xc6,0x01,0xe0,0x00,0x78,0x00,0x38,0x00,0x28,0x00,0x28,0x00,0xee,0x00,0x6c,0x00,0x38,0x00,0x10,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_question_arrow 11 +#define sdl_std_cursor_HEIGHT_question_arrow 16 +#define sdl_std_cursor_HOT_X_question_arrow -4 +#define sdl_std_cursor_HOT_Y_question_arrow -8 + +static unsigned char sdl_std_cursor_mask_pirate[]= {0xf0,0x03,0xf8,0x07,0xfc,0x0f,0xfe,0x1f,0xfe,0x1f,0xfc,0x0f,0xf8,0x07,0xf1,0x83,0xf1,0xe3,0xf3,0xf3,0xef,0x39,0x1e,0x1e,0xe0,0x01,0xfe,0xc7,0xff,0xff,0x0f,0x7c,}; +static unsigned char sdl_std_cursor_pirate[]= {0xe0,0x01,0xf0,0x03,0xf8,0x07,0xcc,0x0c,0xcc,0x0c,0xf8,0x07,0xf0,0x03,0xe0,0x01,0xe1,0x21,0xe1,0x61,0xc2,0x10,0x1c,0x0e,0xe0,0x01,0xf8,0x47,0x0f,0x7c,0x01,0x20,}; +#define sdl_std_cursor_WIDTH_pirate 16 +#define sdl_std_cursor_HEIGHT_pirate 16 +#define sdl_std_cursor_HOT_X_pirate -7 +#define sdl_std_cursor_HOT_Y_pirate -4 + +static unsigned char sdl_std_cursor_mask_left_side[]= {0x0f,0x00,0x0f,0x00,0x0f,0x03,0x8f,0x03,0xcf,0x01,0xef,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x00,0xcf,0x01,0x8f,0x03,0x0f,0x03,0x0f,0x00,0x0f,0x00,}; +static unsigned char sdl_std_cursor_left_side[]= {0x03,0x00,0x03,0x00,0x83,0x00,0x43,0x00,0x23,0x00,0x13,0x00,0xfb,0x3f,0x13,0x00,0x23,0x00,0x43,0x00,0x83,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_left_side 16 +#define sdl_std_cursor_HEIGHT_left_side 15 +#define sdl_std_cursor_HOT_X_left_side 0 +#define sdl_std_cursor_HOT_Y_left_side -7 + +static unsigned char sdl_std_cursor_mask_left_ptr[]= {0x03,0x00,0x07,0x00,0x0f,0x00,0x1f,0x00,0x3f,0x00,0x7f,0x00,0xff,0x00,0xff,0x01,0xff,0x03,0xff,0x03,0x7f,0x00,0xf7,0x00,0xf3,0x00,0xe0,0x01,0xe0,0x01,0xc0,0x00,}; +static unsigned char sdl_std_cursor_left_ptr[]= {0x00,0x00,0x02,0x00,0x06,0x00,0x0e,0x00,0x1e,0x00,0x3e,0x00,0x7e,0x00,0xfe,0x00,0xfe,0x00,0x3e,0x00,0x36,0x00,0x62,0x00,0x60,0x00,0xc0,0x00,0xc0,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_left_ptr 10 +#define sdl_std_cursor_HEIGHT_left_ptr 16 +#define sdl_std_cursor_HOT_X_left_ptr -8 +#define sdl_std_cursor_HOT_Y_left_ptr -14 + +static unsigned char sdl_std_cursor_mask_exchange[]= {0xe3,0x07,0xf7,0x0f,0xff,0x1f,0xff,0x3f,0x3f,0x38,0xff,0x30,0xff,0x00,0xff,0x00,0x00,0xff,0x00,0xff,0x0c,0xfe,0x1c,0xfc,0xfc,0xff,0xf8,0xff,0xf0,0xef,0xe0,0xc7,}; +static unsigned char sdl_std_cursor_exchange[]= {0xf1,0x03,0xfb,0x07,0x1f,0x0c,0x09,0x08,0x19,0x00,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x00,0x26,0x04,0x24,0x0c,0x3e,0xf8,0x37,0xf0,0x23,0x00,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_exchange 16 +#define sdl_std_cursor_HEIGHT_exchange 16 +#define sdl_std_cursor_HOT_X_exchange -6 +#define sdl_std_cursor_HOT_Y_exchange -8 + +static unsigned char sdl_std_cursor_mask_crosshair[]= {0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,}; +static unsigned char sdl_std_cursor_crosshair[]= {0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x7f,0xff,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_crosshair 16 +#define sdl_std_cursor_HEIGHT_crosshair 16 +#define sdl_std_cursor_HOT_X_crosshair -7 +#define sdl_std_cursor_HOT_Y_crosshair -8 + +static unsigned char sdl_std_cursor_mask_bottom_side[]= {0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xcc,0x19,0xdc,0x1d,0xf8,0x0f,0xf0,0x07,0xe0,0x03,0xc0,0x01,0xff,0x7f,0xff,0x7f,0xff,0x7f,0xff,0x7f,}; +static unsigned char sdl_std_cursor_bottom_side[]= {0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x44,0x04,0x48,0x02,0x50,0x01,0xe0,0x00,0x40,0x00,0x00,0x00,0xff,0x1f,0xff,0x1f,0x00,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_bottom_side 15 +#define sdl_std_cursor_HEIGHT_bottom_side 16 +#define sdl_std_cursor_HOT_X_bottom_side -6 +#define sdl_std_cursor_HOT_Y_bottom_side -1 + +static unsigned char sdl_std_cursor_mask_bottom_right_corner[]= {0x00,0xf0,0x00,0xf0,0x0c,0xf7,0x1c,0xf7,0x38,0xf7,0x70,0xf7,0xe0,0xf7,0xc0,0xf7,0xfc,0xf7,0xfc,0xf7,0xfc,0xf7,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,}; +static unsigned char sdl_std_cursor_bottom_right_corner[]= {0x00,0x30,0x00,0x30,0x04,0x31,0x08,0x31,0x10,0x31,0x20,0x31,0x40,0x31,0x80,0x31,0xfc,0x31,0x00,0x30,0x00,0x30,0x00,0x30,0xff,0x3f,0xff,0x3f,0x00,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_bottom_right_corner 16 +#define sdl_std_cursor_HEIGHT_bottom_right_corner 16 +#define sdl_std_cursor_HOT_X_bottom_right_corner -13 +#define sdl_std_cursor_HOT_Y_bottom_right_corner -1 + +static unsigned char sdl_std_cursor_mask_bottom_left_corner[]= {0x0f,0x00,0x0f,0x00,0xef,0x30,0xef,0x38,0xef,0x1c,0xef,0x0e,0xef,0x07,0xef,0x03,0xef,0x3f,0xef,0x3f,0xef,0x3f,0x0f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,}; +static unsigned char sdl_std_cursor_bottom_left_corner[]= {0x03,0x00,0x03,0x00,0x23,0x08,0x23,0x04,0x23,0x02,0x23,0x01,0xa3,0x00,0x63,0x00,0xe3,0x0f,0x03,0x00,0x03,0x00,0x03,0x00,0xff,0x3f,0xff,0x3f,0x00,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_bottom_left_corner 16 +#define sdl_std_cursor_HEIGHT_bottom_left_corner 16 +#define sdl_std_cursor_HOT_X_bottom_left_corner 0 +#define sdl_std_cursor_HOT_Y_bottom_left_corner -1 + +static unsigned char sdl_std_cursor_mask_arrow[]= {0x00,0xe0,0x00,0xf8,0x00,0xfe,0x80,0x7f,0xe0,0x7f,0xf8,0x3f,0xfc,0x3f,0xfc,0x1f,0xe0,0x1f,0xf0,0x0f,0xf8,0x0f,0x7c,0x07,0x3e,0x07,0x1f,0x02,0x0e,0x00,0x04,0x00,}; +static unsigned char sdl_std_cursor_arrow[]= {0x00,0x30,0x00,0x3c,0x00,0x1f,0xc0,0x1f,0xf0,0x0f,0xfc,0x0f,0xc0,0x07,0xe0,0x07,0x70,0x03,0x38,0x03,0x1c,0x01,0x0e,0x01,0x07,0x00,0x02,0x00,0x00,0x00,0x00,0x00,}; +#define sdl_std_cursor_WIDTH_arrow 16 +#define sdl_std_cursor_HEIGHT_arrow 16 +#define sdl_std_cursor_HOT_X_arrow -13 +#define sdl_std_cursor_HOT_Y_arrow -14 +/* end cursor data */ + + +static SDL_Cursor *sdl_std_cursor_array[(int)GHOST_kStandardCursorNumCursors]= {0}; + +/* utility function mostly a copy of SDL_CreateCursor but allows us to change + * color and supports blenders flipped bits */ +static SDL_Cursor * +sdl_ghost_CreateCursor(const Uint8 *data, + const Uint8 *mask, + int w, + int h, + int hot_x, + int hot_y) +{ + SDL_Surface *surface; + SDL_Cursor *cursor; + int x, y; + Uint32 *pixel; + Uint8 datab= 0, maskb= 0; + const Uint32 black= 0xFF000000; + const Uint32 white= 0xFFFFFFFF; + const Uint32 transparent= 0x00000000; + + /* Make sure the width is a multiple of 8 */ + w= ((w + 7) & ~7); + + /* Create the surface from a bitmap */ + surface= SDL_CreateRGBSurface(0, w, h, 32, + 0x00FF0000, + 0x0000FF00, + 0x000000FF, + 0xFF000000); + if (!surface) { + return NULL; + } + for (y= 0; y < h; ++y) { + pixel= (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch); + for (x= 0; x < w; ++x) { + if ((x % 8) == 0) { + datab= *data++; + maskb= *mask++; + + /* reverse bit order */ + datab= (datab * 0x0202020202ULL & 0x010884422010ULL) % 1023; + maskb= (maskb * 0x0202020202ULL & 0x010884422010ULL) % 1023; + } + if (maskb & 0x80) { + *pixel++= (datab & 0x80) ? white : black; + } + else { + *pixel++= (datab & 0x80) ? white : transparent; + } + datab <<= 1; + maskb <<= 1; + } + } + + cursor= SDL_CreateColorCursor(surface, hot_x, hot_y); + + SDL_FreeSurface(surface); + + return cursor; +} + +/* TODO, this is currently never freed but it wont leak either. */ +static void sdl_cursor_init(void) +{ + +#define DEF_CURSOR(name, ind) \ + assert(\ + (\ + sdl_std_cursor_array[(int)ind]= \ + sdl_ghost_CreateCursor(sdl_std_cursor_##name, \ + sdl_std_cursor_mask_##name, \ + sdl_std_cursor_WIDTH_##name, \ + sdl_std_cursor_HEIGHT_##name, \ + (sdl_std_cursor_WIDTH_##name + (sdl_std_cursor_HOT_X_##name)) - 1, \ + (sdl_std_cursor_HEIGHT_##name + (sdl_std_cursor_HOT_Y_##name)) - 1) \ + ) != NULL) \ + + + DEF_CURSOR(left_ptr, GHOST_kStandardCursorDefault); + DEF_CURSOR(right_ptr, GHOST_kStandardCursorRightArrow); + DEF_CURSOR(left_ptr, GHOST_kStandardCursorLeftArrow); + DEF_CURSOR(umbrella, GHOST_kStandardCursorInfo); // TODO, replace this one. + DEF_CURSOR(pirate, GHOST_kStandardCursorDestroy); + DEF_CURSOR(question_arrow, GHOST_kStandardCursorHelp); + DEF_CURSOR(exchange, GHOST_kStandardCursorCycle); + DEF_CURSOR(spraycan, GHOST_kStandardCursorSpray); + DEF_CURSOR(watch, GHOST_kStandardCursorWait); + DEF_CURSOR(xterm, GHOST_kStandardCursorText); + DEF_CURSOR(crosshair, GHOST_kStandardCursorCrosshair); + DEF_CURSOR(sb_v_double_arrow, GHOST_kStandardCursorUpDown); + DEF_CURSOR(sb_h_double_arrow, GHOST_kStandardCursorLeftRight); + DEF_CURSOR(top_side, GHOST_kStandardCursorTopSide); + DEF_CURSOR(bottom_side, GHOST_kStandardCursorBottomSide); + DEF_CURSOR(left_side, GHOST_kStandardCursorLeftSide); + DEF_CURSOR(right_side, GHOST_kStandardCursorRightSide); + DEF_CURSOR(top_left_corner, GHOST_kStandardCursorTopLeftCorner); + DEF_CURSOR(top_right_corner, GHOST_kStandardCursorTopRightCorner); + DEF_CURSOR(bottom_right_corner, GHOST_kStandardCursorBottomRightCorner); + DEF_CURSOR(bottom_left_corner , GHOST_kStandardCursorBottomLeftCorner); + DEF_CURSOR(arrow , GHOST_kStandardCursorCopy); + //DEF_CURSOR(arrow, GHOST_kStandardCursorCustom); + DEF_CURSOR(arrow, GHOST_kStandardCursorPencil); + +#undef DEF_CURSOR + +} + + + +GHOST_TSuccess +GHOST_WindowSDL::setWindowCursorGrab(GHOST_TGrabCursorMode mode) +{ + return GHOST_kSuccess; +} + + +GHOST_TSuccess +GHOST_WindowSDL::setWindowCursorShape(GHOST_TStandardCursor shape) +{ + if(sdl_std_cursor_array[0] == NULL) { + sdl_cursor_init(); + } + + SDL_SetCursor(sdl_std_cursor_array[(int)shape]); + return GHOST_kSuccess; +} + + +GHOST_TSuccess +GHOST_WindowSDL::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], + GHOST_TUns8 mask[16][2], + int hotX, + int hotY) +{ + return setWindowCustomCursorShape((GHOST_TUns8 *)bitmap, + (GHOST_TUns8 *)mask, + 16, 16, + hotX, hotY, + 0, 1); +} + + +GHOST_TSuccess +GHOST_WindowSDL::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, + GHOST_TUns8 *mask, + int sizex, int sizey, + int hotX, int hotY, + int fg_color, int bg_color) +{ + if(m_sdl_custom_cursor) { + SDL_FreeCursor(m_sdl_custom_cursor); + } + + m_sdl_custom_cursor= sdl_ghost_CreateCursor((const Uint8 *)bitmap, + (const Uint8 *)mask, + sizex, sizex, + hotX, hotY); + + SDL_SetCursor(m_sdl_custom_cursor); + return GHOST_kSuccess; +} + + +GHOST_TSuccess +GHOST_WindowSDL::setWindowCursorVisibility(bool visible) +{ + SDL_ShowCursor(visible); + return GHOST_kSuccess; +} diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h new file mode 100644 index 00000000000..6b016b85126 --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowSDL.h @@ -0,0 +1,167 @@ +/* + * $Id$ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ghost/intern/GHOST_WindowSDL.h + * \ingroup GHOST + * Declaration of GHOST_WindowSDL class. + */ + +#ifndef _GHOST_WINDOWSDL_H_ +#define _GHOST_WINDOWSDL_H_ + +#include "GHOST_Window.h" +#include "GHOST_SystemSDL.h" +#include <map> + +extern "C" { + #include "SDL.h" +} + +#if !SDL_VERSION_ATLEAST(1, 3, 0) +# error "SDL 1.3 or newer is needed to build with Ghost" +#endif + +class STR_String; + +class GHOST_WindowSDL : public GHOST_Window +{ +private : + GHOST_SystemSDL * m_system; + bool m_invalid_window; + + SDL_Window * m_sdl_win; + SDL_GLContext m_sdl_glcontext; + SDL_Cursor * m_sdl_custom_cursor; + +public: + + const GHOST_TabletData* GetTabletData() { return NULL; } + + GHOST_WindowSDL(GHOST_SystemSDL *system, + const STR_String& title, + GHOST_TInt32 left, GHOST_TInt32 top, + GHOST_TUns32 width, GHOST_TUns32 height, + GHOST_TWindowState state, + const GHOST_TEmbedderWindowID parentWindow, + GHOST_TDrawingContextType type, + const bool stereoVisual, + const GHOST_TUns16 numOfAASamples + ); + + ~GHOST_WindowSDL(); + + /* SDL spesific */ + SDL_Window * + getSDLWindow() + { + return m_sdl_win; + } + + + GHOST_TSuccess invalidate(void); + + /** + * called by the X11 system implementation when expose events + * for the window have been pushed onto the GHOST queue + */ + + void validate() + { + m_invalid_window = false; + } + + bool getValid() const + { + return (m_sdl_win != NULL); + } + + void getWindowBounds(GHOST_Rect& bounds) const; + void getClientBounds(GHOST_Rect& bounds) const; + +protected: + GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type); + GHOST_TSuccess removeDrawingContext(); + + GHOST_TSuccess + setWindowCursorGrab(GHOST_TGrabCursorMode mode); + + GHOST_TSuccess + setWindowCursorShape(GHOST_TStandardCursor shape); + + GHOST_TSuccess + setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], + GHOST_TUns8 mask[16][2], + int hotX, int hotY); + + GHOST_TSuccess + setWindowCustomCursorShape(GHOST_TUns8 *bitmap, + GHOST_TUns8 *mask, + int sizex, int sizey, + int hotX, int hotY, + int fg_color, int bg_color); + + GHOST_TSuccess + setWindowCursorVisibility(bool visible); + + void + setTitle(const STR_String& title); + + void + getTitle(STR_String& title) const; + + GHOST_TSuccess + setClientWidth(GHOST_TUns32 width); + + GHOST_TSuccess + setClientHeight(GHOST_TUns32 height); + + GHOST_TSuccess + setClientSize(GHOST_TUns32 width, + GHOST_TUns32 height); + + void + screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, + GHOST_TInt32& outX, GHOST_TInt32& outY) const; + + void + clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, + GHOST_TInt32& outX, GHOST_TInt32& outY) const; + + GHOST_TSuccess + swapBuffers(); + + GHOST_TSuccess + activateDrawingContext(); + + GHOST_TSuccess + setState(GHOST_TWindowState state); + + GHOST_TWindowState + getState() const; + + GHOST_TSuccess setOrder(GHOST_TWindowOrder order) { return GHOST_kSuccess; } // TODO + +}; + + +#endif // _GHOST_WINDOWSDL_H_ diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 4055c3acf56..70914d9d2ef 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -39,19 +39,11 @@ #endif // WIN32 #include "GHOST_Window.h" +#include "GHOST_TaskbarWin32.h" -/* MinGW needs it */ -#ifdef FREE_WINDOWS -#ifdef WINVER -#undef WINVER -#endif -#define WINVER 0x0501 -#endif - - - +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include <windows.h> -#include "GHOST_TaskbarWin32.h" #include <wintab.h> diff --git a/intern/ghost/test/CMakeLists.txt b/intern/ghost/test/CMakeLists.txt new file mode 100644 index 00000000000..f834b55b387 --- /dev/null +++ b/intern/ghost/test/CMakeLists.txt @@ -0,0 +1,155 @@ + +cmake_policy(SET CMP0003 NEW) +cmake_policy(SET CMP0005 NEW) + +cmake_minimum_required(VERSION 2.8) + +# ----------------------------------------------------------------------------- +# Macros + + +# stub macro, does nothing +macro(blender_add_lib + name + sources + includes + includes_sys + ) + +endmacro() + +# suffix relative paths so we can use external cmake files +macro(suffix_relpaths + new_files files prefix) + + set(${new_files}) + foreach(_file ${files}) + if(IS_ABSOLUTE _file) + list(APPEND ${new_files} ${_file}) + else() + list(APPEND ${new_files} "${prefix}${_file}") + endif() + endforeach() + unset(_file) +endmacro() + + +# ----------------------------------------------------------------------------- +# Libraries + +# ghost +include(${CMAKE_SOURCE_DIR}/../CMakeLists.txt) +suffix_relpaths(INC_NEW "${INC}" "../") +suffix_relpaths(SRC_NEW "${SRC}" "../") +include_directories(${INC_NEW}) +add_library(ghost_lib ${SRC_NEW}) + +# string +include(${CMAKE_SOURCE_DIR}/../../string/CMakeLists.txt) +suffix_relpaths(INC_NEW "${INC}" "../../string/") +suffix_relpaths(SRC_NEW "${SRC}" "../../string/") +include_directories(${INC_NEW}) +add_library(string_lib ${SRC_NEW}) + +# guardedalloc +include(${CMAKE_SOURCE_DIR}/../../guardedalloc/CMakeLists.txt) +suffix_relpaths(INC_NEW "${INC}" "../../guardedalloc/") +suffix_relpaths(SRC_NEW "${SRC}" "../../guardedalloc/") +include_directories(${INC_NEW}) +add_library(guardedalloc_lib ${SRC_NEW}) + +# blenfont +include(${CMAKE_SOURCE_DIR}/../../../source/blender/blenfont/CMakeLists.txt) +suffix_relpaths(INC_NEW "${INC}" "../../../source/blender/blenfont/") +suffix_relpaths(SRC_NEW "${SRC}" "../../../source/blender/blenfont/") +include_directories(${INC_NEW}) +add_library(blenfont_lib ${SRC_NEW}) + +# grr, blenfont needs BLI +include_directories( + "../../../source/blender/blenlib" + "../../../source/blender/blenloader" + ) +add_library(bli_lib + "../../../source/blender/blenlib/intern/fileops.c" + "../../../source/blender/blenlib/intern/rct.c" + "../../../source/blender/blenlib/intern/string.c" + "../../../source/blender/blenlib/intern/listbase.c" + "../../../source/blender/blenlib/intern/storage.c" + "../../../source/blender/blenlib/intern/path_util.c" + "../../../source/blender/blenlib/intern/BLI_dynstr.c" + "../../../source/blender/blenlib/intern/BLI_linklist.c" + "../../../source/blender/blenlib/intern/BLI_memarena.c" + ) + + +find_package(OpenGL REQUIRED) + +find_package(Freetype REQUIRED) + +include_directories(${CMAKE_SOURCE_DIR}/../) +include_directories(${OPENGL_INCLUDE_DIR}) +include_directories(${FREETYPE_INCLUDE_DIRS}) +include_directories(${CMAKE_SOURCE_DIR}/../../../source/blender/blenfont) + +if(UNIX AND NOT APPLE) + find_package(X11 REQUIRED) + + set(PLATFORM_LINKLIBS + ${X11_X11_LIB} + ${X11_Xinput_LIB} + ) +endif() + +# ----------------------------------------------------------------------------- +# Executables + + +# Gears (C) +add_executable(gears_c + ${CMAKE_SOURCE_DIR}/gears/GHOST_C-Test.c) + +target_link_libraries(gears_c + ghost_lib + string_lib + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${PLATFORM_LINKLIBS} + ) + + +# Gears (C++) +add_executable(gears_cpp + ${CMAKE_SOURCE_DIR}/gears/GHOST_Test.cpp) + +target_link_libraries(gears_cpp + ghost_lib + string_lib + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${PLATFORM_LINKLIBS} + ) + + +# MultiTest (C) +add_executable(multitest_c + ${CMAKE_SOURCE_DIR}/../../../source/blender/editors/datafiles/bfont.ttf.c + ${CMAKE_SOURCE_DIR}/multitest/Basic.c + ${CMAKE_SOURCE_DIR}/multitest/EventToBuf.c + ${CMAKE_SOURCE_DIR}/multitest/MultiTest.c + ${CMAKE_SOURCE_DIR}/multitest/ScrollBar.c + ${CMAKE_SOURCE_DIR}/multitest/Util.c + ${CMAKE_SOURCE_DIR}/multitest/WindowData.c +) + +target_link_libraries(multitest_c + blenfont_lib + bli_lib + ghost_lib + string_lib + guardedalloc_lib + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${FREETYPE_LIBRARY} + ${PLATFORM_LINKLIBS} + ) diff --git a/intern/ghost/test/gears/GHOST_C-Test.c b/intern/ghost/test/gears/GHOST_C-Test.c index b34a37132b6..c582d205258 100644 --- a/intern/ghost/test/gears/GHOST_C-Test.c +++ b/intern/ghost/test/gears/GHOST_C-Test.c @@ -474,6 +474,7 @@ int main(int argc, char** argv) 200, GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL, + FALSE, FALSE); if (!sMainWindow) { @@ -490,6 +491,7 @@ int main(int argc, char** argv) 200, GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL, + FALSE, FALSE); if (!sSecondaryWindow) { diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp index 6e269e1cede..930faf463b6 100644 --- a/intern/ghost/test/gears/GHOST_Test.cpp +++ b/intern/ghost/test/gears/GHOST_Test.cpp @@ -428,7 +428,7 @@ Application::Application(GHOST_ISystem* system) // Create the main window STR_String title1 ("gears - main window"); m_mainWindow = system->createWindow(title1, 10, 64, 320, 200, GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, true /* stereo flag */); + GHOST_kDrawingContextTypeOpenGL, false, false); if (!m_mainWindow) { std::cout << "could not create main window\n"; @@ -438,7 +438,7 @@ Application::Application(GHOST_ISystem* system) // Create a secondary window STR_String title2 ("gears - secondary window"); m_secondaryWindow = system->createWindow(title2, 340, 64, 320, 200, GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, false /* stereo flag */); + GHOST_kDrawingContextTypeOpenGL, false, false); if (!m_secondaryWindow) { cout << "could not create secondary window\n"; exit(-1); diff --git a/intern/ghost/test/multitest/MultiTest.c b/intern/ghost/test/multitest/MultiTest.c index 848601b2cc7..00939e907d6 100644 --- a/intern/ghost/test/multitest/MultiTest.c +++ b/intern/ghost/test/multitest/MultiTest.c @@ -42,7 +42,18 @@ #include "MEM_guardedalloc.h" #include "GHOST_C-api.h" -#include "BMF_Api.h" + +#ifdef USE_BMF +# include "BMF_Api.h" +#else +# include "BLF_api.h" + extern int datatoc_bfont_ttf_size; + extern char datatoc_bfont_ttf[]; + + // XXX, bad, but BLI uses these + char bprogname[160]= ""; +char U[1024]= {0}; +#endif #include "Util.h" #include "Basic.h" @@ -291,7 +302,7 @@ MainWindow *mainwindow_new(MultiTestApp *app) { win= GHOST_CreateWindow(sys, "MultiTest:Main", 40, 40, 400, 400, GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL, - FALSE); + FALSE, FALSE); if (win) { MainWindow *mw= MEM_callocN(sizeof(*mw), "mainwindow_new"); @@ -324,8 +335,12 @@ struct _LoggerWindow { MultiTestApp *app; GHOST_WindowHandle win; - + +#ifdef USE_BMF BMF_Font *font; +#else + int font; +#endif int fonttexid; int fontheight; @@ -429,18 +444,26 @@ static void loggerwindow_do_draw(LoggerWindow *lw) { char *line= lw->loglines[(lw->nloglines-1)-(i+startline)]; int x_pos= lw->textarea[0][0] + 4; int y_pos= lw->textarea[0][1] + 4 + i*lw->fontheight; - + +#ifdef USE_BMF if (lw->fonttexid==-1) { glRasterPos2i(x_pos, y_pos); BMF_DrawString(lw->font, line); } else { BMF_DrawStringTexture(lw->font, line, x_pos, y_pos, 0.0); } +#else + BLF_position(lw->font, x_pos, y_pos, 0.0); + BLF_draw(lw->font, line, 256); // XXX +#endif } + +#ifdef USE_BMF if (lw->fonttexid!=-1) { glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); } +#endif GHOST_SwapWindowBuffers(lw->win); } @@ -531,19 +554,25 @@ LoggerWindow *loggerwindow_new(MultiTestApp *app) { GHOST_GetMainDisplayDimensions(sys, &screensize[0], &screensize[1]); win= GHOST_CreateWindow(sys, "MultiTest:Logger", 40, screensize[1]-432, 800, 300, GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, FALSE); + GHOST_kDrawingContextTypeOpenGL, FALSE, FALSE); if (win) { LoggerWindow *lw= MEM_callocN(sizeof(*lw), "loggerwindow_new"); int bbox[2][2]; lw->app= app; lw->win= win; - + +#ifdef USE_BMF lw->font= BMF_GetFont(BMF_kScreen12); lw->fonttexid= BMF_GetFontTexture(lw->font); BMF_GetBoundingBox(lw->font, &bbox[0][0], &bbox[0][1], &bbox[1][0], &bbox[1][1]); lw->fontheight= rect_height(bbox); +#else + lw->font= BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size); + BLF_size(lw->font, 11, 72); + lw->fontheight= BLF_height(lw->font, "A_"); +#endif lw->nloglines= lw->logsize= 0; lw->loglines= MEM_mallocN(sizeof(*lw->loglines)*lw->nloglines, "loglines"); @@ -711,7 +740,7 @@ ExtraWindow *extrawindow_new(MultiTestApp *app) { win= GHOST_CreateWindow(sys, "MultiTest:Extra", 500, 40, 400, 400, GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL, - FALSE); + FALSE, FALSE); if (win) { ExtraWindow *ew= MEM_callocN(sizeof(*ew), "mainwindow_new"); @@ -786,7 +815,7 @@ static int multitest_event_handler(GHOST_EventHandle evt, GHOST_TUserDataPtr dat MultiTestApp *multitestapp_new(void) { MultiTestApp *app= MEM_mallocN(sizeof(*app), "multitestapp_new"); GHOST_EventConsumerHandle consumer= GHOST_CreateEventConsumer(multitest_event_handler, app); - + app->sys= GHOST_CreateSystem(); if (!app->sys) fatal("Unable to create ghost system"); @@ -850,6 +879,10 @@ void multitestapp_free(MultiTestApp *app) { /***/ int main(int argc, char **argv) { +#ifndef USE_BMF + BLF_init(11, 72); +#endif + MultiTestApp *app= multitestapp_new(); multitestapp_run(app); diff --git a/intern/iksolver/intern/IK_QJacobian.cpp b/intern/iksolver/intern/IK_QJacobian.cpp index 6cc73e9c808..5a216309cee 100644 --- a/intern/iksolver/intern/IK_QJacobian.cpp +++ b/intern/iksolver/intern/IK_QJacobian.cpp @@ -59,6 +59,7 @@ void IK_QJacobian::ArmMatrices(int dof, int task_size) m_d_theta.newsize(dof); m_d_theta_tmp.newsize(dof); + m_d_norm_weight.newsize(dof); m_norm.newsize(dof); m_norm = 0.0; @@ -111,11 +112,13 @@ void IK_QJacobian::SetBetas(int id, int, const MT_Vector3& v) m_beta[id+2] = v.z(); } -void IK_QJacobian::SetDerivatives(int id, int dof_id, const MT_Vector3& v) +void IK_QJacobian::SetDerivatives(int id, int dof_id, const MT_Vector3& v, MT_Scalar norm_weight) { m_jacobian[id][dof_id] = v.x()*m_weight_sqrt[dof_id]; m_jacobian[id+1][dof_id] = v.y()*m_weight_sqrt[dof_id]; m_jacobian[id+2][dof_id] = v.z()*m_weight_sqrt[dof_id]; + + m_d_norm_weight[dof_id] = norm_weight; } void IK_QJacobian::Invert() @@ -429,7 +432,7 @@ MT_Scalar IK_QJacobian::AngleUpdateNorm() const MT_Scalar mx = 0.0, dtheta_abs; for (i = 0; i < m_d_theta.size(); i++) { - dtheta_abs = MT_abs(m_d_theta[i]); + dtheta_abs = MT_abs(m_d_theta[i]*m_d_norm_weight[i]); if (dtheta_abs > mx) mx = dtheta_abs; } diff --git a/intern/iksolver/intern/IK_QJacobian.h b/intern/iksolver/intern/IK_QJacobian.h index 438b9a02c67..ecfaee5ff97 100644 --- a/intern/iksolver/intern/IK_QJacobian.h +++ b/intern/iksolver/intern/IK_QJacobian.h @@ -56,7 +56,7 @@ public: // Iteratively called void SetBetas(int id, int size, const MT_Vector3& v); - void SetDerivatives(int id, int dof_id, const MT_Vector3& v); + void SetDerivatives(int id, int dof_id, const MT_Vector3& v, MT_Scalar norm_weight); void Invert(); @@ -89,6 +89,7 @@ private: /// the vector of computed angle changes TVector m_d_theta; + TVector m_d_norm_weight; /// space required for SVD computation diff --git a/intern/iksolver/intern/IK_QTask.cpp b/intern/iksolver/intern/IK_QTask.cpp index 32ecb833899..32143518533 100644 --- a/intern/iksolver/intern/IK_QTask.cpp +++ b/intern/iksolver/intern/IK_QTask.cpp @@ -95,10 +95,10 @@ void IK_QPositionTask::ComputeJacobian(IK_QJacobian& jacobian) MT_Vector3 axis = seg->Axis(i)*m_weight; if (seg->Translational()) - jacobian.SetDerivatives(m_id, seg->DoFId()+i, axis); + jacobian.SetDerivatives(m_id, seg->DoFId()+i, axis, 1e2); else { MT_Vector3 pa = p.cross(axis); - jacobian.SetDerivatives(m_id, seg->DoFId()+i, pa); + jacobian.SetDerivatives(m_id, seg->DoFId()+i, pa, 1e0); } } } @@ -147,10 +147,10 @@ void IK_QOrientationTask::ComputeJacobian(IK_QJacobian& jacobian) for (i = 0; i < seg->NumberOfDoF(); i++) { if (seg->Translational()) - jacobian.SetDerivatives(m_id, seg->DoFId()+i, MT_Vector3(0, 0, 0)); + jacobian.SetDerivatives(m_id, seg->DoFId()+i, MT_Vector3(0, 0, 0), 1e2); else { MT_Vector3 axis = seg->Axis(i)*m_weight; - jacobian.SetDerivatives(m_id, seg->DoFId()+i, axis); + jacobian.SetDerivatives(m_id, seg->DoFId()+i, axis, 1e0); } } } @@ -202,10 +202,10 @@ void IK_QCenterOfMassTask::JacobianSegment(IK_QJacobian& jacobian, MT_Vector3& c axis *= /*segment->Mass()**/m_total_mass_inv; if (segment->Translational()) - jacobian.SetDerivatives(m_id, segment->DoFId()+i, axis); + jacobian.SetDerivatives(m_id, segment->DoFId()+i, axis, 1e2); else { MT_Vector3 pa = axis.cross(p); - jacobian.SetDerivatives(m_id, segment->DoFId()+i, pa); + jacobian.SetDerivatives(m_id, segment->DoFId()+i, pa, 1e0); } } diff --git a/intern/mikktspace/mikktspace.c b/intern/mikktspace/mikktspace.c index c05ada84773..1bb73553012 100644 --- a/intern/mikktspace/mikktspace.c +++ b/intern/mikktspace/mikktspace.c @@ -243,7 +243,7 @@ tbool genTangSpace(const SMikkTSpaceContext * pContext, const float fAngularThre int iNrActiveGroups = 0, index = 0; const int iNrFaces = pContext->m_pInterface->m_getNumFaces(pContext); tbool bRes = TFALSE; - const float fThresCos = (const float) cos((fAngularThreshold*(float)M_PI)/180.0f); + const float fThresCos = (float) cos((fAngularThreshold*(float)M_PI)/180.0f); // verify all call-backs have been set if( pContext->m_pInterface->m_getNumFaces==NULL || @@ -1411,7 +1411,7 @@ STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[] // weight contribution by the angle // between the two edge vectors fCos = vdot(v1,v2); fCos=fCos>1?1:(fCos<(-1) ? (-1) : fCos); - fAngle = (const float) acos(fCos); + fAngle = (float) acos(fCos); fMagS = pTriInfos[f].fMagS; fMagT = pTriInfos[f].fMagT; diff --git a/intern/smoke/CMakeLists.txt b/intern/smoke/CMakeLists.txt index 30313f45a92..094d398a83c 100644 --- a/intern/smoke/CMakeLists.txt +++ b/intern/smoke/CMakeLists.txt @@ -84,12 +84,14 @@ set(SRC ) if(WITH_OPENMP) - add_definitions(-DPARALLEL=1) + add_definitions(-DPARALLEL=1) endif() if(WITH_FFTW3) add_definitions(-DFFTW3=1) - list(APPEND INC ${FFTW3_INCLUDE_DIRS}) + list(APPEND INC + ${FFTW3_INCLUDE_DIRS} + ) endif() blender_add_lib(bf_intern_smoke "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/smoke/intern/WAVELET_NOISE.h b/intern/smoke/intern/WAVELET_NOISE.h index b556b4a2e66..66dfb95d143 100644 --- a/intern/smoke/intern/WAVELET_NOISE.h +++ b/intern/smoke/intern/WAVELET_NOISE.h @@ -45,6 +45,11 @@ #include <MERSENNETWISTER.h> +#ifdef WIN32 +#include <float.h> +#define isnan _isnan +#endif + // Tile file header, update revision upon any change done to the noise generator static const char tilefile_headerstring[] = "Noise Tile File rev. "; static const char tilefile_revision[] = "001"; @@ -69,7 +74,7 @@ static void downsampleX(float *from, float *to, int n){ const float *a = &downCoeffs[16]; for (int i = 0; i < n / 2; i++) { to[i] = 0; - for (int k = 2 * i - 16; k <= 2 * i + 16; k++) + for (int k = 2 * i - 16; k < 2 * i + 16; k++) to[i] += a[k - 2 * i] * from[modFast128(k)]; } } @@ -79,7 +84,7 @@ static void downsampleY(float *from, float *to, int n){ const float *a = &downCoeffs[16]; for (int i = 0; i < n / 2; i++) { to[i * n] = 0; - for (int k = 2 * i - 16; k <= 2 * i + 16; k++) + for (int k = 2 * i - 16; k < 2 * i + 16; k++) to[i * n] += a[k - 2 * i] * from[modFast128(k) * n]; } } @@ -89,7 +94,7 @@ static void downsampleZ(float *from, float *to, int n){ const float *a = &downCoeffs[16]; for (int i = 0; i < n / 2; i++) { to[i * n * n] = 0; - for (int k = 2 * i - 16; k <= 2 * i + 16; k++) + for (int k = 2 * i - 16; k < 2 * i + 16; k++) to[i * n * n] += a[k - 2 * i] * from[modFast128(k) * n * n]; } } @@ -262,6 +267,14 @@ static bool loadTile(float* const noiseTileData, std::string filename) printf("loadTile: Noise tile '%s' is wrong size %d.\n", filename.c_str(), (int)bread); return false; } + + // check for invalid nan tile data that could be generated. bug is now + // fixed, but invalid files may still hang around + if (isnan(noiseTileData[0])) { + printf("loadTile: Noise tile '%s' contains nan values.\n", filename.c_str()); + return false; + } + return true; } |