merge with trunk r39216

This commit is contained in:
Xiao Xiangquan
2011-08-10 14:32:03 +00:00
210 changed files with 6222 additions and 3313 deletions

View File

@@ -179,6 +179,7 @@ option(WITH_LZO "Enable fast LZO compression (used for pointcache)" ON
option(WITH_LZMA "Enable best LZMA compression, (used for pointcache)" ON) option(WITH_LZMA "Enable best LZMA compression, (used for pointcache)" ON)
# Misc # Misc
option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON)
option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON) option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON)
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON) option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON)
@@ -452,6 +453,19 @@ if(UNIX AND NOT APPLE)
endif() endif()
endif() endif()
if (WITH_INPUT_NDOF)
find_package(Spacenav)
if(NOT SPACENAV_FOUND)
set(WITH_INPUT_NDOF OFF)
endif()
# use generic names within blenders buildsystem.
if(SPACENAV_FOUND)
set(NDOF_INCLUDE_DIRS ${SPACENAV_INCLUDE_DIRS})
set(NDOF_LIBRARIES ${SPACENAV_LIBRARIES})
endif()
endif()
# OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed # OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed
set(PLATFORM_LINKLIBS "-lutil -lc -lm -lpthread -lstdc++") set(PLATFORM_LINKLIBS "-lutil -lc -lm -lpthread -lstdc++")
@@ -896,28 +910,15 @@ elseif(APPLE)
endif() endif()
if(WITH_PYTHON) if(WITH_PYTHON)
set(PYTHON_VERSION 3.2)
if(PYTHON_VERSION MATCHES 3.2)
# we use precompiled libraries for py 3.2 and up by default # we use precompiled libraries for py 3.2 and up by default
# normally cached but not since we include them with blender # normally cached but not since we include them with blender
set(PYTHON_VERSION 3.2)
set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}") set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}")
# set(PYTHON_BINARY "${LIBDIR}/python/bin/python${PYTHON_VERSION}") # not used yet # set(PYTHON_BINARY "${LIBDIR}/python/bin/python${PYTHON_VERSION}") # not used yet
set(PYTHON_LIBRARY python${PYTHON_VERSION}) set(PYTHON_LIBRARY python${PYTHON_VERSION})
set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}") set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}")
# set(PYTHON_LINKFLAGS "-u _PyMac_Error") # won't build with this enabled # set(PYTHON_LINKFLAGS "-u _PyMac_Error") # won't build with this enabled
else()
# otherwise, use custom system framework
# *not used but maintained incase some dev wants to*
set(PYTHON "/System/Library/Frameworks/Python.framework/Versions/" CACHE PATH)
set(PYTHON_INCLUDE_DIR "${PYTHON}${PYTHON_VERSION}/include/python${PYTHON_VERSION}" CACHE PATH)
# set(PYTHON_BINARY ${PYTHON}${PYTHON_VERSION}/bin/python${PYTHON_VERSION}) # not used yet
set(PYTHON_LIBRARY "" CACHE FILEPATH)
set(PYTHON_LIBPATH "${PYTHON}${PYTHON_VERSION}/lib/python${PYTHON_VERSION}/config" CACHE PATH)
set(PYTHON_LINKFLAGS "-u _PyMac_Error -framework System -framework Python" CACHE STRING)
unset(PYTHON)
endif()
# uncached vars # uncached vars
set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
@@ -972,7 +973,17 @@ elseif(APPLE)
set(SAMPLERATE_LIBPATH ${SAMPLERATE}/lib) set(SAMPLERATE_LIBPATH ${SAMPLERATE}/lib)
endif() endif()
find_library(SYSTEMSTUBS_LIBRARY
NAMES
SystemStubs
PATHS
)
mark_as_advanced(SYSTEMSTUBS_LIBRARY)
if(SYSTEMSTUBS_LIBRARY)
set(PLATFORM_LINKLIBS stdc++ SystemStubs) set(PLATFORM_LINKLIBS stdc++ SystemStubs)
else()
set(PLATFORM_LINKLIBS stdc++)
endif()
if(WITH_COCOA) if(WITH_COCOA)
set(PLATFORM_CFLAGS "-pipe -funsigned-char -DGHOST_COCOA") set(PLATFORM_CFLAGS "-pipe -funsigned-char -DGHOST_COCOA")
@@ -987,9 +998,28 @@ elseif(APPLE)
elseif(WITH_CODEC_QUICKTIME) elseif(WITH_CODEC_QUICKTIME)
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -framework QuickTime") set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -framework QuickTime")
endif() endif()
# XXX - SOME MAC DEV PLEASE TEST WITH THE SDK INSTALLED!
# ALSO SHOULD BE MOVED INTO OWN MODULE WHEN FUNCTIONAL
if(WITH_INPUT_NDOF)
# This thread it *should* work and check the framework - campbell
# http://www.cmake.org/pipermail/cmake/2005-December/007740.html
find_library(3D_CONNEXION_CLIENT_LIBRARY
NAMES 3DconnexionClient
)
if(NOT 3D_CONNEXION_CLIENT_LIBRARY)
set(WITH_INPUT_NDOF OFF)
endif()
if(WITH_INPUT_NDOF)
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework 3DconnexionClient")
endif()
endif()
else() else()
set(PLATFORM_CFLAGS "-pipe -funsigned-char") set(PLATFORM_CFLAGS "-pipe -funsigned-char")
set(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime") set(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime")
set(WITH_INPUT_NDOF OFF) # unsupported
endif() endif()
if(WITH_OPENCOLLADA) if(WITH_OPENCOLLADA)
@@ -1029,6 +1059,10 @@ elseif(APPLE)
set(TIFF_LIBPATH ${TIFF}/lib) set(TIFF_LIBPATH ${TIFF}/lib)
endif() endif()
if (WITH_INPUT_NDOF)
# linker needs "-weak_framework 3DconnexionClient"
endif()
set(EXETYPE MACOSX_BUNDLE) set(EXETYPE MACOSX_BUNDLE)
set(CMAKE_C_FLAGS_DEBUG "-fno-strict-aliasing -g") set(CMAKE_C_FLAGS_DEBUG "-fno-strict-aliasing -g")
@@ -1054,20 +1088,34 @@ if(APPLE OR WIN32)
endif() endif()
endif() endif()
# See TEST_SSE_SUPPORT() for how this is defined.
if(WITH_RAYOPTIMIZATION) if(WITH_RAYOPTIMIZATION)
if(CMAKE_COMPILER_IS_GNUCC) if(CMAKE_COMPILER_IS_GNUCC)
set(_sse "-msse")
set(_sse2 "-msse2")
elseif(MSVC)
set(_sse "/arch:SSE")
set(_sse2 "/arch:SSE2")
else()
message(WARNING "SSE flags for this compiler not known")
set(_sse)
set(_sse2)
endif()
if(SUPPORT_SSE_BUILD) if(SUPPORT_SSE_BUILD)
set(PLATFORM_CFLAGS " -msse ${PLATFORM_CFLAGS}") set(PLATFORM_CFLAGS " ${_sse} ${PLATFORM_CFLAGS}")
add_definitions(-D__SSE__ -D__MMX__) add_definitions(-D__SSE__ -D__MMX__)
endif() endif()
if(SUPPORT_SSE2_BUILD) if(SUPPORT_SSE2_BUILD)
set(PLATFORM_CFLAGS " -msse2 ${PLATFORM_CFLAGS}") set(PLATFORM_CFLAGS " ${_sse2} ${PLATFORM_CFLAGS}")
add_definitions(-D__SSE2__) add_definitions(-D__SSE2__)
if(NOT SUPPORT_SSE_BUILD) # dont double up if(NOT SUPPORT_SSE_BUILD) # dont double up
add_definitions(-D__MMX__) add_definitions(-D__MMX__)
endif() endif()
endif() endif()
endif() unset(_sse)
unset(_sse2)
endif() endif()
if(WITH_IMAGE_OPENJPEG) if(WITH_IMAGE_OPENJPEG)
@@ -1306,6 +1354,7 @@ if(FIRST_RUN)
info_cfg_option(WITH_OPENCOLLADA) info_cfg_option(WITH_OPENCOLLADA)
info_cfg_option(WITH_FFTW3) info_cfg_option(WITH_FFTW3)
info_cfg_option(WITH_INTERNATIONAL) info_cfg_option(WITH_INTERNATIONAL)
info_cfg_option(WITH_INPUT_NDOF)
info_cfg_text("Compiler Options:") info_cfg_text("Compiler Options:")
info_cfg_option(WITH_BUILDINFO) info_cfg_option(WITH_BUILDINFO)

View File

@@ -111,6 +111,11 @@ btools.print_targets(B.targets, B.bc)
# handling cmd line arguments & config file # handling cmd line arguments & config file
# bitness stuff
tempbitness = int(B.arguments.get('BF_BITNESS', bitness)) # default to bitness found as per starting python
if tempbitness in (32, 64): # only set if 32 or 64 has been given
bitness = int(tempbitness)
# first check cmdline for toolset and we create env to work on # first check cmdline for toolset and we create env to work on
quickie = B.arguments.get('BF_QUICK', None) quickie = B.arguments.get('BF_QUICK', None)
quickdebug = B.arguments.get('BF_QUICKDEBUG', None) quickdebug = B.arguments.get('BF_QUICKDEBUG', None)
@@ -241,12 +246,30 @@ if 'blenderlite' in B.targets:
target_env_defs['BF_BUILDINFO'] = False target_env_defs['BF_BUILDINFO'] = False
target_env_defs['BF_NO_ELBEEM'] = True target_env_defs['BF_NO_ELBEEM'] = True
target_env_defs['WITH_BF_PYTHON'] = False target_env_defs['WITH_BF_PYTHON'] = False
target_env_defs['WITH_BF_3DMOUSE'] = False
# Merge blenderlite, let command line to override # Merge blenderlite, let command line to override
for k,v in target_env_defs.iteritems(): for k,v in target_env_defs.iteritems():
if k not in B.arguments: if k not in B.arguments:
env[k] = v env[k] = v
# Extended OSX_SDK and 3D_CONNEXION_CLIENT_LIBRARY detection for OSX
if env['OURPLATFORM']=='darwin':
print B.bc.OKGREEN + "Detected Xcode version: -- " + B.bc.ENDC + env['XCODE_CUR_VER'][:9] + " --"
print "Available " + env['MACOSX_SDK_CHECK']
if not 'Mac OS X 10.5' in env['MACOSX_SDK_CHECK']:
print B.bc.OKGREEN + "MacOSX10.5.sdk not available:" + B.bc.ENDC + " using MacOSX10.6.sdk"
else:
print B.bc.OKGREEN + "Found recommended sdk :" + B.bc.ENDC + " using MacOSX10.5.sdk"
# for now, Mac builders must download and install the driver framework from 3Dconnexion
# necessary header file lives here when installed:
# /Library/Frameworks/3DconnexionClient.framework/Versions/Current/Headers/ConnexionClientAPI.h
if env['WITH_BF_3DMOUSE'] == 1 and not os.path.exists('/Library/Frameworks/3DconnexionClient.framework'):
print "3D_CONNEXION_CLIENT_LIBRARY not found, disabling WITH_BF_3DMOUSE" # avoid build errors !
env['WITH_BF_3DMOUSE'] = 0
env['FOUND_NDOF_DRIVERS'] = 0
if env['WITH_BF_OPENMP'] == 1: if env['WITH_BF_OPENMP'] == 1:
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
@@ -658,11 +681,7 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
dllsources.append('${LCGDIR}/sndfile/lib/libsndfile-1.dll') dllsources.append('${LCGDIR}/sndfile/lib/libsndfile-1.dll')
if env['WITH_BF_FFMPEG']: if env['WITH_BF_FFMPEG']:
dllsources += ['${BF_FFMPEG_LIBPATH}/avcodec-52.dll', dllsources += env['BF_FFMPEG_DLL'].split()
'${BF_FFMPEG_LIBPATH}/avformat-52.dll',
'${BF_FFMPEG_LIBPATH}/avdevice-52.dll',
'${BF_FFMPEG_LIBPATH}/avutil-50.dll',
'${BF_FFMPEG_LIBPATH}/swscale-0.dll']
# Since the thumb handler is loaded by Explorer, architecture is # Since the thumb handler is loaded by Explorer, architecture is
# strict: the x86 build fails on x64 Windows. We need to ship # strict: the x86 build fails on x64 Windows. We need to ship

View File

@@ -22,7 +22,7 @@ BF_EXPAT_LIB = ''
WITH_BF_FFMPEG = True WITH_BF_FFMPEG = True
WITH_BF_STATICFFMPEG = True WITH_BF_STATICFFMPEG = True
BF_FFMPEG = '/home/sources/staticlibs/ffmpeg' BF_FFMPEG = '/home/sources/staticlibs/ffmpeg-0.8'
BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib32' BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib32'
BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \ BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \
'${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \ '${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \
@@ -81,6 +81,12 @@ WITH_BF_STATICJEMALLOC = True
BF_JEMALLOC = '/home/sources/staticlibs/jemalloc' BF_JEMALLOC = '/home/sources/staticlibs/jemalloc'
BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib32' BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib32'
# Use 3d mouse library
WITH_BF_3DMOUSE = True
WITH_BF_STATIC3DMOUSE = True
BF_3DMOUSE = '/home/sources/staticlibs/spnav'
BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib32'
# Compilation and optimization # Compilation and optimization
BF_DEBUG = False BF_DEBUG = False
REL_CFLAGS = ['-O2'] REL_CFLAGS = ['-O2']

View File

@@ -13,7 +13,18 @@ WITH_BF_STATICPYTHON = True
WITH_BF_COLLADA = False WITH_BF_COLLADA = False
# FFMPEG configuration # FFMPEG configuration
WITH_BF_FFMPEG = False WITH_BF_FFMPEG = True
WITH_BF_STATICFFMPEG = True
BF_FFMPEG = '/home/sources/staticlibs/ffmpeg-0.8'
BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib32'
BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \
'${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \
'${BF_FFMPEG_LIBPATH}/libxvidcore.a ${BF_FFMPEG_LIBPATH}/libx264.a ${BF_FFMPEG_LIBPATH}/libmp3lame.a ' + \
'${BF_FFMPEG_LIBPATH}/libvpx.a ${BF_FFMPEG_LIBPATH}/libvorbis.a ${BF_FFMPEG_LIBPATH}/libogg.a ' + \
'${BF_FFMPEG_LIBPATH}/libvorbisenc.a ${BF_FFMPEG_LIBPATH}/libtheora.a ' + \
'${BF_FFMPEG_LIBPATH}/libschroedinger-1.0.a ${BF_FFMPEG_LIBPATH}/liborc-0.4.a ${BF_FFMPEG_LIBPATH}/libdirac_encoder.a ' + \
'${BF_FFMPEG_LIBPATH}/libfaad.a'
# Don't depend on system's libstdc++ # Don't depend on system's libstdc++
WITH_BF_STATICCXX = True WITH_BF_STATICCXX = True
@@ -65,6 +76,12 @@ WITH_BF_STATICJEMALLOC = True
BF_JEMALLOC = '/home/sources/staticlibs/jemalloc' BF_JEMALLOC = '/home/sources/staticlibs/jemalloc'
BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib32' BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib32'
# Use 3d mouse library
WITH_BF_3DMOUSE = True
WITH_BF_STATIC3DMOUSE = True
BF_3DMOUSE = '/home/sources/staticlibs/spnav'
BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib32'
# Compilation and optimization # Compilation and optimization
BF_DEBUG = False BF_DEBUG = False
REL_CFLAGS = ['-O2'] REL_CFLAGS = ['-O2']

View File

@@ -13,7 +13,18 @@ WITH_BF_STATICPYTHON = True
WITH_BF_COLLADA = False WITH_BF_COLLADA = False
# FFMPEG configuration # FFMPEG configuration
WITH_BF_FFMPEG = False WITH_BF_FFMPEG = True
WITH_BF_STATICFFMPEG = True
BF_FFMPEG = '/home/sources/staticlibs/ffmpeg-0.8'
BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib64'
BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \
'${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \
'${BF_FFMPEG_LIBPATH}/libxvidcore.a ${BF_FFMPEG_LIBPATH}/libx264.a ${BF_FFMPEG_LIBPATH}/libmp3lame.a ' + \
'${BF_FFMPEG_LIBPATH}/libvpx.a ${BF_FFMPEG_LIBPATH}/libvorbis.a ${BF_FFMPEG_LIBPATH}/libogg.a ' + \
'${BF_FFMPEG_LIBPATH}/libvorbisenc.a ${BF_FFMPEG_LIBPATH}/libtheora.a ' + \
'${BF_FFMPEG_LIBPATH}/libschroedinger-1.0.a ${BF_FFMPEG_LIBPATH}/liborc-0.4.a ${BF_FFMPEG_LIBPATH}/libdirac_encoder.a ' + \
'${BF_FFMPEG_LIBPATH}/libfaad.a'
# Don't depend on system's libstdc++ # Don't depend on system's libstdc++
WITH_BF_STATICCXX = True WITH_BF_STATICCXX = True
@@ -65,6 +76,12 @@ WITH_BF_STATICJEMALLOC = True
BF_JEMALLOC = '/home/sources/staticlibs/jemalloc' BF_JEMALLOC = '/home/sources/staticlibs/jemalloc'
BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib64' BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib64'
# Use 3d mouse library
WITH_BF_3DMOUSE = True
WITH_BF_STATIC3DMOUSE = True
BF_3DMOUSE = '/home/sources/staticlibs/spnav'
BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib64'
# Compilation and optimization # Compilation and optimization
BF_DEBUG = False BF_DEBUG = False
REL_CFLAGS = ['-O2'] REL_CFLAGS = ['-O2']

View File

@@ -22,7 +22,7 @@ BF_EXPAT_LIB = ''
WITH_BF_FFMPEG = True WITH_BF_FFMPEG = True
WITH_BF_STATICFFMPEG = True WITH_BF_STATICFFMPEG = True
BF_FFMPEG = '/home/sources/staticlibs/ffmpeg' BF_FFMPEG = '/home/sources/staticlibs/ffmpeg-0.8'
BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib64' BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib64'
BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \ BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \
'${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \ '${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \
@@ -81,6 +81,12 @@ WITH_BF_STATICJEMALLOC = True
BF_JEMALLOC = '/home/sources/staticlibs/jemalloc' BF_JEMALLOC = '/home/sources/staticlibs/jemalloc'
BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib64' BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib64'
# Use 3d mouse library
WITH_BF_3DMOUSE = True
WITH_BF_STATIC3DMOUSE = True
BF_3DMOUSE = '/home/sources/staticlibs/spnav'
BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib64'
# Compilation and optimization # Compilation and optimization
BF_DEBUG = False BF_DEBUG = False
REL_CFLAGS = ['-O2'] REL_CFLAGS = ['-O2']

View File

@@ -116,6 +116,7 @@ add_builder(c, 'linux_x86_64_scons', '', generic_builder)
add_builder(c, 'salad_linux_x86_64_scons', '', generic_builder, 'soc-2011-salad') add_builder(c, 'salad_linux_x86_64_scons', '', generic_builder, 'soc-2011-salad')
add_builder(c, 'win32_scons', 'windows', generic_builder) add_builder(c, 'win32_scons', 'windows', generic_builder)
add_builder(c, 'salad_win32_scons', 'windows', generic_builder, 'soc-2011-salad') add_builder(c, 'salad_win32_scons', 'windows', generic_builder, 'soc-2011-salad')
add_builder(c, 'win64_scons', 'windows', generic_builder)
#add_builder(c, 'freebsd_i386_cmake', '', generic_builder) #add_builder(c, 'freebsd_i386_cmake', '', generic_builder)
#add_builder(c, 'freebsd_x86_64_cmake', '', generic_builder) #add_builder(c, 'freebsd_x86_64_cmake', '', generic_builder)

View File

@@ -108,5 +108,33 @@ else:
sys.exit(0) sys.exit(0)
else: else:
bitness = '32'
# Switch to new FFmpeg library
if builder.find('win') != -1:
if builder.find('win32') != -1:
LCGDIR = '#../lib/windows'
elif builder.find('win64') != -1:
LCGDIR = '#../lib/win64'
bitness = '64'
all_ffmpeg_libs = ['avcodec-53',
'avdevice-53',
'avformat-53',
'avutil-51',
'swscale-2']
ffmpeg_lib = []
ffmpeg_dll = []
for lib in all_ffmpeg_libs:
ffmpeg_lib.append(lib + '.lib')
ffmpeg_dll.append('${BF_FFMPEG_LIBPATH}/' + lib + '.dll')
scons_options.append('BF_FFMPEG=' + LCGDIR + '/ffmpeg-0.8')
scons_options.append('BF_FFMPEG_LIB=' + (' '.join(ffmpeg_lib)))
scons_options.append('BF_FFMPEG_DLL=' + (' '.join(ffmpeg_dll)))
scons_options.append('BF_BITNESS=' + bitness)
retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options) retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options)
sys.exit(retcode) sys.exit(retcode)

View File

@@ -72,6 +72,34 @@ if builder.find('scons') != -1:
retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options) retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options)
sys.exit(retcode) sys.exit(retcode)
else: else:
bitness = '32'
# Switch to new FFmpeg library
if builder.find('win') != -1:
if builder.find('win32') != -1:
LCGDIR = '#../lib/windows'
elif builder.find('win64') != -1:
LCGDIR = '#../lib/win64'
bitness = '64'
all_ffmpeg_libs = ['avcodec-53',
'avdevice-53',
'avformat-53',
'avutil-51',
'swscale-2']
ffmpeg_lib = []
ffmpeg_dll = []
for lib in all_ffmpeg_libs:
ffmpeg_lib.append(lib + '.lib')
ffmpeg_dll.append('${BF_FFMPEG_LIBPATH}/' + lib + '.dll')
scons_options.append('BF_FFMPEG=' + LCGDIR + '/ffmpeg-0.8')
scons_options.append('BF_FFMPEG_LIB=' + (' '.join(ffmpeg_lib)))
scons_options.append('BF_FFMPEG_DLL=' + (' '.join(ffmpeg_dll)))
scons_options.append('BF_BITNESS=' + bitness)
retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options) retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options)
sys.exit(retcode) sys.exit(retcode)

View File

@@ -0,0 +1,70 @@
# - Find Spacenav library
# Find the native Spacenav includes and library
# This module defines
# SPACENAV_INCLUDE_DIRS, where to find spnav.h, Set when
# SPACENAV_INCLUDE_DIR is found.
# SPACENAV_LIBRARIES, libraries to link against to use Spacenav.
# SPACENAV_ROOT_DIR, The base directory to search for Spacenav.
# This can also be an environment variable.
# SPACENAV_FOUND, If false, do not try to use Spacenav.
#
# also defined, but not for general use are
# SPACENAV_LIBRARY, where to find the Spacenav library.
#=============================================================================
# Copyright 2011 Blender Foundation.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# If SPACENAV_ROOT_DIR was defined in the environment, use it.
IF(NOT SPACENAV_ROOT_DIR AND NOT $ENV{SPACENAV_ROOT_DIR} STREQUAL "")
SET(SPACENAV_ROOT_DIR $ENV{SPACENAV_ROOT_DIR})
ENDIF()
SET(_spacenav_SEARCH_DIRS
${SPACENAV_ROOT_DIR}
/usr/local
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
)
FIND_PATH(SPACENAV_INCLUDE_DIR
NAMES
spnav.h
HINTS
${_spacenav_SEARCH_DIRS}
PATH_SUFFIXES
include
)
FIND_LIBRARY(SPACENAV_LIBRARY
NAMES
spnav
HINTS
${_spacenav_SEARCH_DIRS}
PATH_SUFFIXES
lib64 lib
)
# handle the QUIETLY and REQUIRED arguments and set SPACENAV_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Spacenav DEFAULT_MSG
SPACENAV_LIBRARY SPACENAV_INCLUDE_DIR)
IF(SPACENAV_FOUND)
SET(SPACENAV_LIBRARIES ${SPACENAV_LIBRARY})
SET(SPACENAV_INCLUDE_DIRS ${SPACENAV_INCLUDE_DIR})
ENDIF(SPACENAV_FOUND)
MARK_AS_ADVANCED(
SPACENAV_INCLUDE_DIR
SPACENAV_LIBRARY
)

View File

@@ -30,7 +30,18 @@ Example linux usage
Windows not supported so far Windows not supported so far
""" """
from project_info import * from project_info import (SIMPLE_PROJECTFILE,
SOURCE_DIR,
CMAKE_DIR,
PROJECT_DIR,
source_list,
is_project_file,
is_c_header,
# is_py,
cmake_advanced_info,
cmake_compiler_defines,
)
import os import os
from os.path import join, dirname, normpath, relpath, exists from os.path import join, dirname, normpath, relpath, exists

View File

@@ -31,7 +31,17 @@ example linux usage
python .~/blenderSVN/blender/build_files/cmake/cmake_qtcreator_project.py ~/blenderSVN/cmake python .~/blenderSVN/blender/build_files/cmake/cmake_qtcreator_project.py ~/blenderSVN/cmake
""" """
from project_info import * from project_info import (SIMPLE_PROJECTFILE,
SOURCE_DIR,
# CMAKE_DIR,
PROJECT_DIR,
source_list,
is_project_file,
is_c_header,
is_py,
cmake_advanced_info,
cmake_compiler_defines,
)
import os import os
import sys import sys

View File

@@ -62,6 +62,10 @@ macro(blender_include_dirs
foreach(_INC ${ARGV}) foreach(_INC ${ARGV})
get_filename_component(_ABS_INC ${_INC} ABSOLUTE) get_filename_component(_ABS_INC ${_INC} ABSOLUTE)
list(APPEND _ALL_INCS ${_ABS_INC}) list(APPEND _ALL_INCS ${_ABS_INC})
# for checking for invalid includes, disable for regular use
##if(NOT EXISTS "${_ABS_INC}/")
## message(FATAL_ERROR "Include not found: ${_ABS_INC}/")
##endif()
endforeach() endforeach()
include_directories(${_ALL_INCS}) include_directories(${_ALL_INCS})
unset(_INC) unset(_INC)
@@ -75,6 +79,9 @@ macro(blender_include_dirs_sys
foreach(_INC ${ARGV}) foreach(_INC ${ARGV})
get_filename_component(_ABS_INC ${_INC} ABSOLUTE) get_filename_component(_ABS_INC ${_INC} ABSOLUTE)
list(APPEND _ALL_INCS ${_ABS_INC}) list(APPEND _ALL_INCS ${_ABS_INC})
##if(NOT EXISTS "${_ABS_INC}/")
## message(FATAL_ERROR "Include not found: ${_ABS_INC}/")
##endif()
endforeach() endforeach()
include_directories(SYSTEM ${_ALL_INCS}) include_directories(SYSTEM ${_ALL_INCS})
unset(_INC) unset(_INC)
@@ -314,6 +321,10 @@ macro(setup_liblinks
if(WITH_MEM_JEMALLOC) if(WITH_MEM_JEMALLOC)
target_link_libraries(${target} ${JEMALLOC_LIBRARIES}) target_link_libraries(${target} ${JEMALLOC_LIBRARIES})
endif() endif()
if(WITH_INPUT_NDOF)
target_link_libraries(${target} ${NDOF_LIBRARIES})
endif()
if(WIN32 AND NOT UNIX) if(WIN32 AND NOT UNIX)
target_link_libraries(${target} ${PTHREADS_LIBRARIES}) target_link_libraries(${target} ${PTHREADS_LIBRARIES})
endif() endif()

View File

@@ -21,14 +21,23 @@ cmd = 'uname -p'
MAC_PROC=commands.getoutput(cmd) MAC_PROC=commands.getoutput(cmd)
cmd = 'uname -r' cmd = 'uname -r'
cmd_res=commands.getoutput(cmd) cmd_res=commands.getoutput(cmd)
if cmd_res[0]=='7':
if cmd_res[:1]=='7':
MAC_CUR_VER='10.3' MAC_CUR_VER='10.3'
elif cmd_res[0]=='8': elif cmd_res[:1]=='8':
MAC_CUR_VER='10.4' MAC_CUR_VER='10.4'
elif cmd_res[0]=='9': elif cmd_res[:1]=='9':
MAC_CUR_VER='10.5' MAC_CUR_VER='10.5'
elif cmd_res[0]=='10': elif cmd_res[:2]=='10':
MAC_CUR_VER='10.6' MAC_CUR_VER='10.6'
elif cmd_res[:2]=='11':
MAC_CUR_VER='10.7'
cmd = 'xcodebuild -version'
cmd_xcode=commands.getoutput(cmd)
XCODE_CUR_VER=cmd_xcode
cmd = 'xcodebuild -showsdks'
cmd_sdk=commands.getoutput(cmd)
MACOSX_SDK_CHECK=cmd_sdk
if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'ppc64': if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'ppc64':
USE_QTKIT=True # Carbon quicktime is not available for 64bit USE_QTKIT=True # Carbon quicktime is not available for 64bit
@@ -37,8 +46,8 @@ if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'ppc64':
# Default target OSX settings per architecture # Default target OSX settings per architecture
# Can be customized # Can be customized
if MACOSX_ARCHITECTURE == 'ppc': if MACOSX_ARCHITECTURE == 'ppc' and MAC_CUR_VER == '10.4':
# ppc release are now made for 10.4 # all releases are now made for 10.5 !
# MAC_MIN_VERS = '10.3' # MAC_MIN_VERS = '10.3'
# MACOSX_SDK='/Developer/SDKs/MacOSX10.3.9.sdk' # MACOSX_SDK='/Developer/SDKs/MacOSX10.3.9.sdk'
# LCGDIR = '#../lib/darwin-6.1-powerpc' # LCGDIR = '#../lib/darwin-6.1-powerpc'
@@ -50,7 +59,7 @@ if MACOSX_ARCHITECTURE == 'ppc':
LCGDIR = '#../lib/darwin-8.0.0-powerpc' LCGDIR = '#../lib/darwin-8.0.0-powerpc'
CC = 'gcc-4.0' CC = 'gcc-4.0'
CXX = 'g++-4.0' CXX = 'g++-4.0'
elif MACOSX_ARCHITECTURE == 'i386': elif MACOSX_ARCHITECTURE == 'i386' and MAC_CUR_VER == '10.4':
MAC_MIN_VERS = '10.4' MAC_MIN_VERS = '10.4'
MACOSX_DEPLOYMENT_TARGET = '10.4' MACOSX_DEPLOYMENT_TARGET = '10.4'
MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk' MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
@@ -58,12 +67,22 @@ elif MACOSX_ARCHITECTURE == 'i386':
CC = 'gcc-4.0' CC = 'gcc-4.0'
CXX = 'g++-4.0' CXX = 'g++-4.0'
else : else :
if 'Mac OS X 10.5' in MACOSX_SDK_CHECK:
# OSX 10.5/6 with Xcode 3.x
MAC_MIN_VERS = '10.5' MAC_MIN_VERS = '10.5'
MACOSX_DEPLOYMENT_TARGET = '10.5' MACOSX_DEPLOYMENT_TARGET = '10.5'
MACOSX_SDK='/Developer/SDKs/MacOSX10.5.sdk' MACOSX_SDK='/Developer/SDKs/MacOSX10.5.sdk'
LCGDIR = '#../lib/darwin-9.x.universal' LCGDIR = '#../lib/darwin-9.x.universal'
CC = 'gcc-4.2' CC = 'gcc-4.2'
CXX = 'g++-4.2' CXX = 'g++-4.2'
else:
# OSX 10.6/7 with Xcode 4.x
MAC_MIN_VERS = '10.6'
MACOSX_DEPLOYMENT_TARGET = '10.6'
MACOSX_SDK='/Developer/SDKs/MacOSX10.6.sdk'
LCGDIR = '#../lib/darwin-9.x.universal'
CC = 'gcc-4.2'
CXX = 'g++-4.2'
LIBDIR = '${LCGDIR}' LIBDIR = '${LCGDIR}'
@@ -71,8 +90,8 @@ LIBDIR = '${LCGDIR}'
################### Dependency settings ################## ################### Dependency settings ##################
############################################################################# #############################################################################
#Defaults openMP to true if compiler (currently only gcc 4.2) handles it #Defaults openMP to true if compiler handles it
if CC == 'gcc-4.2': if CC == 'gcc-4.2' or CC == 'llvm-gcc-4.2':
WITH_BF_OPENMP = True # multithreading for fluids, cloth and smoke WITH_BF_OPENMP = True # multithreading for fluids, cloth and smoke
else: else:
WITH_BF_OPENMP = False WITH_BF_OPENMP = False
@@ -188,8 +207,8 @@ BF_GETTEXT_INC = '${BF_GETTEXT}/include'
BF_GETTEXT_LIB = 'intl' BF_GETTEXT_LIB = 'intl'
BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE=True WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = False WITH_BF_PLAYER = True
WITH_BF_BULLET = True WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src' BF_BULLET = '#extern/bullet2/src'
@@ -240,7 +259,7 @@ BF_OPENGL_LIBPATH = '/System/Library/Frameworks/OpenGL.framework/Libraries'
BF_OPENGL_LINKFLAGS = ['-framework', 'OpenGL'] BF_OPENGL_LINKFLAGS = ['-framework', 'OpenGL']
#OpenCollada flags #OpenCollada flags
WITH_BF_COLLADA = False WITH_BF_COLLADA = True
BF_COLLADA = '#source/blender/collada' BF_COLLADA = '#source/blender/collada'
BF_COLLADA_INC = '${BF_COLLADA}' BF_COLLADA_INC = '${BF_COLLADA}'
BF_COLLADA_LIB = 'bf_collada' BF_COLLADA_LIB = 'bf_collada'
@@ -265,6 +284,8 @@ if MACOSX_ARCHITECTURE == 'i386':
elif MACOSX_ARCHITECTURE == 'x86_64': elif MACOSX_ARCHITECTURE == 'x86_64':
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-msse2'] BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-msse2']
# SpaceNavigator and related 3D mice
WITH_BF_3DMOUSE = True
############################################################################# #############################################################################
################### various compile settings and flags ################## ################### various compile settings and flags ##################
@@ -283,28 +304,31 @@ CPPFLAGS = []+ARCH_FLAGS
CCFLAGS = ['-pipe','-funsigned-char']+ARCH_FLAGS CCFLAGS = ['-pipe','-funsigned-char']+ARCH_FLAGS
CXXFLAGS = ['-pipe','-funsigned-char']+ARCH_FLAGS CXXFLAGS = ['-pipe','-funsigned-char']+ARCH_FLAGS
if WITH_GHOST_COCOA==True: if WITH_GHOST_COCOA:
PLATFORM_LINKFLAGS = ['-fexceptions','-framework','CoreServices','-framework','Foundation','-framework','IOKit','-framework','AppKit','-framework','Cocoa','-framework','Carbon','-framework','AudioUnit','-framework','AudioToolbox','-framework','CoreAudio','-framework','OpenAL']+ARCH_FLAGS PLATFORM_LINKFLAGS = ['-fexceptions','-framework','CoreServices','-framework','Foundation','-framework','IOKit','-framework','AppKit','-framework','Cocoa','-framework','Carbon','-framework','AudioUnit','-framework','AudioToolbox','-framework','CoreAudio','-framework','OpenAL']+ARCH_FLAGS
else: else:
PLATFORM_LINKFLAGS = ['-fexceptions','-framework','CoreServices','-framework','Foundation','-framework','IOKit','-framework','AppKit','-framework','Carbon','-framework','AGL','-framework','AudioUnit','-framework','AudioToolbox','-framework','CoreAudio','-framework','OpenAL']+ARCH_FLAGS PLATFORM_LINKFLAGS = ['-fexceptions','-framework','CoreServices','-framework','Foundation','-framework','IOKit','-framework','AppKit','-framework','Carbon','-framework','AGL','-framework','AudioUnit','-framework','AudioToolbox','-framework','CoreAudio','-framework','OpenAL']+ARCH_FLAGS
if WITH_BF_QUICKTIME == True: if WITH_BF_QUICKTIME:
if USE_QTKIT == True: if USE_QTKIT:
PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QTKit'] PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QTKit']
else: else:
PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QuickTime'] PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QuickTime']
if FOUND_NDOF_DRIVERS:
PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS + ['-weak_framework','3DconnexionClient']
#note to build succesfully on 10.3.9 SDK you need to patch 10.3.9 by adding the SystemStubs.a lib from 10.4 #note to build succesfully on 10.3.9 SDK you need to patch 10.3.9 by adding the SystemStubs.a lib from 10.4
LLIBS = ['stdc++', 'SystemStubs'] LLIBS = ['stdc++', 'SystemStubs']
# some flags shuffling for different Os versions # some flags shuffling for different OS versions
if MAC_MIN_VERS == '10.3': if MAC_MIN_VERS == '10.3':
CFLAGS = ['-fuse-cxa-atexit']+CFLAGS CFLAGS = ['-fuse-cxa-atexit']+CFLAGS
CXXFLAGS = ['-fuse-cxa-atexit']+CXXFLAGS CXXFLAGS = ['-fuse-cxa-atexit']+CXXFLAGS
PLATFORM_LINKFLAGS = ['-fuse-cxa-atexit']+PLATFORM_LINKFLAGS PLATFORM_LINKFLAGS = ['-fuse-cxa-atexit']+PLATFORM_LINKFLAGS
LLIBS.append('crt3.o') LLIBS.append('crt3.o')
if USE_SDK==True: if USE_SDK:
SDK_FLAGS=['-isysroot', MACOSX_SDK,'-mmacosx-version-min='+MAC_MIN_VERS,'-arch',MACOSX_ARCHITECTURE] SDK_FLAGS=['-isysroot', MACOSX_SDK,'-mmacosx-version-min='+MAC_MIN_VERS,'-arch',MACOSX_ARCHITECTURE]
PLATFORM_LINKFLAGS = ['-mmacosx-version-min='+MAC_MIN_VERS,'-Wl','-isysroot',MACOSX_SDK,'-arch',MACOSX_ARCHITECTURE]+PLATFORM_LINKFLAGS PLATFORM_LINKFLAGS = ['-mmacosx-version-min='+MAC_MIN_VERS,'-Wl','-isysroot',MACOSX_SDK,'-arch',MACOSX_ARCHITECTURE]+PLATFORM_LINKFLAGS
CCFLAGS=SDK_FLAGS+CCFLAGS CCFLAGS=SDK_FLAGS+CCFLAGS

View File

@@ -192,6 +192,14 @@ WITH_BF_OPENMP = True
WITH_BF_RAYOPTIMIZATION = True WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-pthread'] BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-pthread']
#SpaceNavigator and friends
WITH_BF_3DMOUSE = True
BF_3DMOUSE = '/usr'
BF_3DMOUSE_INC = '${BF_3DMOUSE}/include'
BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib'
BF_3DMOUSE_LIB = 'spnav'
BF_3DMOUSE_LIB_STATIC = '${BF_3DMOUSE_LIBPATH}/libspnav.a'
## ##
CC = 'gcc' CC = 'gcc'
CXX = 'g++' CXX = 'g++'

View File

@@ -7,6 +7,7 @@ BF_FFMPEG = LIBDIR +'/ffmpeg'
BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}/include/msvc' BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}/include/msvc'
BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib'
BF_FFMPEG_LIB = 'avformat-52.lib avcodec-52.lib avdevice-52.lib avutil-50.lib swscale-0.lib' BF_FFMPEG_LIB = 'avformat-52.lib avcodec-52.lib avdevice-52.lib avutil-50.lib swscale-0.lib'
BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-52.dll ${BF_FFMPEG_LIBPATH}/avcodec-52.dll ${BF_FFMPEG_LIBPATH}/avdevice-52.dll ${BF_FFMPEG_LIBPATH}/avutil-50.dll ${BF_FFMPEG_LIBPATH}/swscale-0.dll'
BF_PYTHON = LIBDIR + '/python' BF_PYTHON = LIBDIR + '/python'
BF_PYTHON_VERSION = '3.2' BF_PYTHON_VERSION = '3.2'
@@ -149,6 +150,8 @@ BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include'
BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser MathMLSolver xml2 pcre buffer ftoa UTF' BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser MathMLSolver xml2 pcre buffer ftoa UTF'
BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib' BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
WITH_BF_3DMOUSE = True
#Ray trace optimization #Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE'] BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE']

View File

@@ -7,6 +7,7 @@ BF_FFMPEG = LIBDIR +'/ffmpeg'
BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}/include/msvc ' BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}/include/msvc '
BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib'
BF_FFMPEG_LIB = 'avformat-52.lib avcodec-52.lib avdevice-52.lib avutil-50.lib swscale-0.lib' BF_FFMPEG_LIB = 'avformat-52.lib avcodec-52.lib avdevice-52.lib avutil-50.lib swscale-0.lib'
BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-52.dll ${BF_FFMPEG_LIBPATH}/avcodec-52.dll ${BF_FFMPEG_LIBPATH}/avdevice-52.dll ${BF_FFMPEG_LIBPATH}/avutil-50.dll ${BF_FFMPEG_LIBPATH}/swscale-0.dll'
BF_PYTHON = LIBDIR + '/python' BF_PYTHON = LIBDIR + '/python'
BF_PYTHON_VERSION = '3.2' BF_PYTHON_VERSION = '3.2'
@@ -153,6 +154,8 @@ BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include'
BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser MathMLSolver xml2 pcre buffer ftoa UTF' BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser MathMLSolver xml2 pcre buffer ftoa UTF'
BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib' BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
WITH_BF_3DMOUSE = True
#Ray trace optimization #Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE','/arch:SSE2'] BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE','/arch:SSE2']

View File

@@ -206,6 +206,12 @@ def setup_staticlibs(lenv):
if lenv['WITH_BF_STATICJEMALLOC']: if lenv['WITH_BF_STATICJEMALLOC']:
statlibs += Split(lenv['BF_JEMALLOC_LIB_STATIC']) statlibs += Split(lenv['BF_JEMALLOC_LIB_STATIC'])
if lenv['OURPLATFORM']=='linux2':
if lenv['WITH_BF_3DMOUSE']:
libincs += Split(lenv['BF_3DMOUSE_LIBPATH'])
if lenv['WITH_BF_STATIC3DMOUSE']:
statlibs += Split(lenv['BF_3DMOUSE_LIB_STATIC'])
return statlibs, libincs return statlibs, libincs
def setup_syslibs(lenv): def setup_syslibs(lenv):
@@ -271,6 +277,11 @@ def setup_syslibs(lenv):
if not lenv['WITH_BF_STATICJEMALLOC']: if not lenv['WITH_BF_STATICJEMALLOC']:
syslibs += Split(lenv['BF_JEMALLOC_LIB']) syslibs += Split(lenv['BF_JEMALLOC_LIB'])
if lenv['OURPLATFORM']=='linux2':
if lenv['WITH_BF_3DMOUSE']:
if not lenv['WITH_BF_STATIC3DMOUSE']:
syslibs += Split(lenv['BF_3DMOUSE_LIB'])
syslibs += lenv['LLIBS'] syslibs += lenv['LLIBS']
return syslibs return syslibs

View File

@@ -87,7 +87,7 @@ def validate_arguments(args, bc):
'BF_PTHREADS', 'BF_PTHREADS_INC', 'BF_PTHREADS_LIB', 'BF_PTHREADS_LIBPATH', 'BF_PTHREADS', 'BF_PTHREADS_INC', 'BF_PTHREADS_LIB', 'BF_PTHREADS_LIBPATH',
'WITH_BF_OPENEXR', 'BF_OPENEXR', 'BF_OPENEXR_INC', 'BF_OPENEXR_LIB', 'BF_OPENEXR_LIBPATH', 'WITH_BF_STATICOPENEXR', 'BF_OPENEXR_LIB_STATIC', 'WITH_BF_OPENEXR', 'BF_OPENEXR', 'BF_OPENEXR_INC', 'BF_OPENEXR_LIB', 'BF_OPENEXR_LIBPATH', 'WITH_BF_STATICOPENEXR', 'BF_OPENEXR_LIB_STATIC',
'WITH_BF_DDS', 'WITH_BF_CINEON', 'WITH_BF_HDR', 'WITH_BF_DDS', 'WITH_BF_CINEON', 'WITH_BF_HDR',
'WITH_BF_FFMPEG', 'BF_FFMPEG_LIB','BF_FFMPEG_EXTRA', 'BF_FFMPEG', 'BF_FFMPEG_INC', 'WITH_BF_FFMPEG', 'BF_FFMPEG_LIB','BF_FFMPEG_EXTRA', 'BF_FFMPEG', 'BF_FFMPEG_INC', 'BF_FFMPEG_DLL',
'WITH_BF_STATICFFMPEG', 'BF_FFMPEG_LIB_STATIC', 'WITH_BF_STATICFFMPEG', 'BF_FFMPEG_LIB_STATIC',
'WITH_BF_OGG', 'BF_OGG', 'BF_OGG_LIB', 'WITH_BF_OGG', 'BF_OGG', 'BF_OGG_LIB',
'WITH_BF_JPEG', 'BF_JPEG', 'BF_JPEG_INC', 'BF_JPEG_LIB', 'BF_JPEG_LIBPATH', 'WITH_BF_JPEG', 'BF_JPEG', 'BF_JPEG_INC', 'BF_JPEG_LIB', 'BF_JPEG_LIBPATH',
@@ -136,7 +136,7 @@ def validate_arguments(args, bc):
'BF_NO_ELBEEM', 'BF_NO_ELBEEM',
'WITH_BF_CXX_GUARDEDALLOC', 'WITH_BF_CXX_GUARDEDALLOC',
'WITH_BF_JEMALLOC', 'WITH_BF_STATICJEMALLOC', 'BF_JEMALLOC', 'BF_JEMALLOC_INC', 'BF_JEMALLOC_LIBPATH', 'BF_JEMALLOC_LIB', 'BF_JEMALLOC_LIB_STATIC', 'WITH_BF_JEMALLOC', 'WITH_BF_STATICJEMALLOC', 'BF_JEMALLOC', 'BF_JEMALLOC_INC', 'BF_JEMALLOC_LIBPATH', 'BF_JEMALLOC_LIB', 'BF_JEMALLOC_LIB_STATIC',
'BUILDBOT_BRANCH' 'BUILDBOT_BRANCH', 'WITH_BF_3DMOUSE', 'FOUND_NDOF_DRIVERS', 'WITH_BF_STATIC3DMOUSE', 'BF_3DMOUSE', 'BF_3DMOUSE_INC', 'BF_3DMOUSE_LIB', 'BF_3DMOUSE_LIBPATH', 'BF_3DMOUSE_LIB_STATIC'
] ]
# Have options here that scons expects to be lists # Have options here that scons expects to be lists
@@ -149,7 +149,7 @@ def validate_arguments(args, bc):
'BF_PROFILE_CFLAGS', 'BF_PROFILE_CCFLAGS', 'BF_PROFILE_CXXFLAGS', 'BF_PROFILE_LINKFLAGS', 'BF_PROFILE_CFLAGS', 'BF_PROFILE_CCFLAGS', 'BF_PROFILE_CXXFLAGS', 'BF_PROFILE_LINKFLAGS',
'BF_DEBUG_CFLAGS', 'BF_DEBUG_CCFLAGS', 'BF_DEBUG_CXXFLAGS', 'BF_DEBUG_CFLAGS', 'BF_DEBUG_CCFLAGS', 'BF_DEBUG_CXXFLAGS',
'C_WARN', 'CC_WARN', 'CXX_WARN', 'C_WARN', 'CC_WARN', 'CXX_WARN',
'LLIBS', 'PLATFORM_LINKFLAGS','MACOSX_ARCHITECTURE', 'LLIBS', 'PLATFORM_LINKFLAGS','MACOSX_ARCHITECTURE', 'MACOSX_SDK_CHECK', 'XCODE_CUR_VER',
] ]
@@ -159,7 +159,7 @@ def validate_arguments(args, bc):
'BF_BSC', 'BF_CONFIG', 'BF_BSC', 'BF_CONFIG',
'BF_PRIORITYLIST', 'BF_BUILDINFO','CC', 'CXX', 'BF_QUICKDEBUG', 'BF_PRIORITYLIST', 'BF_BUILDINFO','CC', 'CXX', 'BF_QUICKDEBUG',
'BF_LISTDEBUG', 'LCGDIR', 'BF_X264_CONFIG', 'BF_XVIDCORE_CONFIG', 'BF_LISTDEBUG', 'LCGDIR', 'BF_X264_CONFIG', 'BF_XVIDCORE_CONFIG',
'BF_UNIT_TEST'] 'BF_UNIT_TEST', 'BF_BITNESS']
okdict = {} okdict = {}
@@ -291,6 +291,7 @@ def read_opts(env, cfg, args):
(BoolVariable('WITH_BF_FFMPEG', 'Use FFMPEG if true', False)), (BoolVariable('WITH_BF_FFMPEG', 'Use FFMPEG if true', False)),
('BF_FFMPEG', 'FFMPEG base path', ''), ('BF_FFMPEG', 'FFMPEG base path', ''),
('BF_FFMPEG_LIB', 'FFMPEG library', ''), ('BF_FFMPEG_LIB', 'FFMPEG library', ''),
('BF_FFMPEG_DLL', 'FFMPEG dll libraries to be installed', ''),
('BF_FFMPEG_EXTRA', 'FFMPEG flags that must be preserved', ''), ('BF_FFMPEG_EXTRA', 'FFMPEG flags that must be preserved', ''),
('BF_FFMPEG_INC', 'FFMPEG includes', ''), ('BF_FFMPEG_INC', 'FFMPEG includes', ''),
@@ -437,6 +438,15 @@ def read_opts(env, cfg, args):
(BoolVariable('WITH_BF_PLAYER', 'Build blenderplayer if true', False)), (BoolVariable('WITH_BF_PLAYER', 'Build blenderplayer if true', False)),
(BoolVariable('WITH_BF_NOBLENDER', 'Do not build blender if true', False)), (BoolVariable('WITH_BF_NOBLENDER', 'Do not build blender if true', False)),
(BoolVariable('WITH_BF_3DMOUSE', 'Build blender with support of 3D mouses', False)),
(BoolVariable('FOUND_NDOF_DRIVERS', 'We detected NDOF libs or framework', False)),
(BoolVariable('WITH_BF_STATIC3DMOUSE', 'Staticly link to 3d mouse library', False)),
('BF_3DMOUSE', '3d mouse library base path', ''),
('BF_3DMOUSE_INC', '3d mouse library include path', ''),
('BF_3DMOUSE_LIB', '3d mouse library', ''),
('BF_3DMOUSE_LIBPATH', '3d mouse library path', ''),
('BF_3DMOUSE_LIB_STATIC', '3d mouse static library', ''),
('CFLAGS', 'C only flags', []), ('CFLAGS', 'C only flags', []),
('CCFLAGS', 'Generic C and C++ flags', []), ('CCFLAGS', 'Generic C and C++ flags', []),
('CXXFLAGS', 'C++ only flags', []), ('CXXFLAGS', 'C++ only flags', []),
@@ -453,6 +463,8 @@ def read_opts(env, cfg, args):
('LLIBS', 'Platform libs', []), ('LLIBS', 'Platform libs', []),
('PLATFORM_LINKFLAGS', 'Platform linkflags', []), ('PLATFORM_LINKFLAGS', 'Platform linkflags', []),
('MACOSX_ARCHITECTURE', 'python_arch.zip select', ''), ('MACOSX_ARCHITECTURE', 'python_arch.zip select', ''),
('MACOSX_SDK_CHECK', 'detect available OSX sdk`s', ''),
('XCODE_CUR_VER', 'detect XCode version', ''),
(BoolVariable('BF_PROFILE', 'Add profiling information if true', False)), (BoolVariable('BF_PROFILE', 'Add profiling information if true', False)),
('BF_PROFILE_CFLAGS', 'C only profiling flags', []), ('BF_PROFILE_CFLAGS', 'C only profiling flags', []),

View File

@@ -31,7 +31,7 @@ PROJECT_NAME = Blender
# This could be handy for archiving the generated documentation or # This could be handy for archiving the generated documentation or
# if some version control system is used. # if some version control system is used.
PROJECT_NUMBER = "V2.58" PROJECT_NUMBER = "V2.59"
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer # for a project that appears at the top of each page and should give viewer

View File

@@ -219,7 +219,7 @@ div.sphinxsidebarwrapper.fixed {
} }
{%- if theme_stickysidebar|tobool %} {%- if theme_stickysidebar|tobool %}
/* this is nice, but it it leads to hidden headings when jumping /* this is nice, but it leads to hidden headings when jumping
to an anchor */ to an anchor */
/* /*
div.related { div.related {

4
doc/python_api/examples/bge.constraints.py Executable file → Normal file
View File

@@ -31,7 +31,7 @@ edge_angle_y = 1.0
edge_angle_z = 0.0 edge_angle_z = 0.0
# create an edge constraint # create an edge constraint
constraints.createConstraint( physics_id_1, physics_id_2, constraints.createConstraint(physics_id_1, physics_id_2,
constraint_type, constraint_type,
edge_position_x, edge_position_y, edge_position_z, edge_position_x, edge_position_y, edge_position_z,
edge_angle_x, edge_angle_y, edge_angle_z ) edge_angle_x, edge_angle_y, edge_angle_z)

2
doc/python_api/examples/bge.texture.1.py Executable file → Normal file
View File

@@ -8,6 +8,7 @@ Controller.
from bge import logic from bge import logic
from bge import texture from bge import texture
def createTexture(cont): def createTexture(cont):
"""Create a new Dynamic Texture""" """Create a new Dynamic Texture"""
object = cont.owner object = cont.owner
@@ -29,6 +30,7 @@ def createTexture(cont):
logic.texture.source = new_source logic.texture.source = new_source
logic.texture.refresh(False) logic.texture.refresh(False)
def removeTexture(cont): def removeTexture(cont):
"""Delete the Dynamic Texture, reversing back the final to its original state.""" """Delete the Dynamic Texture, reversing back the final to its original state."""
try: try:

0
doc/python_api/examples/bge.texture.py Executable file → Normal file
View File

7
doc/python_api/examples/blf.py Executable file → Normal file
View File

@@ -1,6 +1,7 @@
""" """
Hello World Text Example Hello World Text Example
++++++++++++++++++++++++ ++++++++++++++++++++++++
Blender Game Engine example of using the blf module. For this module to work we Blender Game Engine example of using the blf module. For this module to work we
need to use the OpenGL wrapper :class:`~bgl` as well. need to use the OpenGL wrapper :class:`~bgl` as well.
""" """
@@ -11,6 +12,7 @@ from bge import logic
import bgl import bgl
import blf import blf
def init(): def init():
"""init function - runs once""" """init function - runs once"""
# create a new font object, use external ttf file # create a new font object, use external ttf file
@@ -20,7 +22,8 @@ def init():
# set the font drawing routine to run every frame # set the font drawing routine to run every frame
scene = logic.getCurrentScene() scene = logic.getCurrentScene()
scene.post_draw=[write] scene.post_draw = [write]
def write(): def write():
"""write on screen""" """write on screen"""
@@ -36,6 +39,6 @@ def write():
# BLF drawing routine # BLF drawing routine
font_id = logic.font_id font_id = logic.font_id
blf.position(font_id, (width*0.2), (height*0.3), 0) blf.position(font_id, (width * 0.2), (height * 0.3), 0)
blf.size(font_id, 50, 72) blf.size(font_id, 50, 72)
blf.draw(font_id, "Hello World") blf.draw(font_id, "Hello World")

238
doc/python_api/rst/bge.constraints.rst Executable file → Normal file
View File

@@ -1,28 +1,51 @@
Game Engine bge.constraints Module Physics Constraints (bge.constraints)
================================== =====================================
.. note:: .. module:: bge.constraints
This documentation is still very weak, and needs some help!
.. function:: createConstraint([obj1, [obj2, [restLength, [restitution, [damping]]]]]) .. literalinclude:: ../examples/bge.constraints.py
.. function:: createConstraint(physicsid, physicsid2, constrainttype, [pivotX, pivotY, pivotZ, [axisX, axisY, axisZ, [flag]]]])
Creates a constraint. Creates a constraint.
:arg obj1: first object on Constraint :arg physicsid: the physics id of the first object in constraint
:type obj1: :class:'bge.types.KX_GameObject' #I think, there is no error when I use one :type physicsid: int
:arg obj2: second object on Constraint :arg physicsid2: the physics id of the second object in constraint
:type obj2: :class:'bge.types.KX_GameObject' #too :type physicsid2: int
:arg restLength: #to be filled :arg constrainttype: the type of the constraint. The constraint types are:
:type restLength: float
:arg restitution: #to be filled - :class:`POINTTOPOINT_CONSTRAINT`
:type restitution: float - :class:`LINEHINGE_CONSTRAINT`
- :class:`ANGULAR_CONSTRAINT`
- :class:`CONETWIST_CONSTRAINT`
- :class:`VEHICLE_CONSTRAINT`
:arg damping: #to be filled :type constrainttype: int
:type damping: float
:arg pivotX: pivot X position
:type pivotX: float
:arg pivotY: pivot Y position
:type pivotY: float
:arg pivotZ: pivot Z position
:type pivotZ: float
:arg axisX: X axis
:type axisX: float
:arg axisY: Y axis
:type axisY: float
:arg axisZ: Z axis
:type axisZ: float
:arg flag: .. to do
:type flag: int
.. attribute:: error .. attribute:: error
@@ -49,7 +72,7 @@ Game Engine bge.constraints Module
:type constraintId: int :type constraintId: int
:return: a vehicle constraint object. :return: a vehicle constraint object.
:rtype: :class:'KX_VehicleWrapper' :rtype: :class:`bge.types.KX_VehicleWrapper`
.. function:: removeConstraint(constraintId) .. function:: removeConstraint(constraintId)
@@ -60,10 +83,10 @@ Game Engine bge.constraints Module
.. function:: setCcdMode(ccdMode) .. function:: setCcdMode(ccdMode)
..note:: .. note::
Very experimental, not recommended Very experimental, not recommended
Sets the CCD mode in the Physics Environment. Sets the CCD (Continous Colision Detection) mode in the Physics Environment.
:arg ccdMode: The new CCD mode. :arg ccdMode: The new CCD mode.
:type ccdMode: int :type ccdMode: int
@@ -73,21 +96,21 @@ Game Engine bge.constraints Module
.. note:: .. note::
Reasonable default is 0.02 (if units are meters) Reasonable default is 0.02 (if units are meters)
Sets the contact breaking treshold in the Physics Environment. Sets tresholds to do with contact point management.
:arg breakingTreshold: The new contact breaking treshold. :arg breakingTreshold: The new contact breaking treshold.
:type breakingTreshold: float :type breakingTreshold: float
.. function:: setDeactivationAngularTreshold(angularTreshold) .. function:: setDeactivationAngularTreshold(angularTreshold)
Sets the deactivation angular treshold. Sets the angular velocity treshold.
:arg angularTreshold: New deactivation angular treshold. :arg angularTreshold: New deactivation angular treshold.
:type angularTreshold: float :type angularTreshold: float
.. function:: setDeactivationLinearTreshold(linearTreshold) .. function:: setDeactivationLinearTreshold(linearTreshold)
Sets the deactivation linear treshold. Sets the linear velocity treshold.
:arg linearTreshold: New deactivation linear treshold. :arg linearTreshold: New deactivation linear treshold.
:type linearTreshold: float :type linearTreshold: float
@@ -104,21 +127,20 @@ Game Engine bge.constraints Module
Sets the debug mode. Sets the debug mode.
Debug modes: Debug modes:
- No debug: 0 - :class:`DBG_NODEBUG`
- Draw wireframe: 1 - :class:`DBG_DRAWWIREFRAME`
- Draw Aabb: 2 #What's Aabb? - :class:`DBG_DRAWAABB`
- Draw freatures text: 4 - :class:`DBG_DRAWFREATURESTEXT`
- Draw contact points: 8 - :class:`DBG_DRAWCONTACTPOINTS`
- No deactivation: 16 - :class:`DBG_NOHELPTEXT`
- No help text: 32 - :class:`DBG_DRAWTEXT`
- Draw text: 64 - :class:`DBG_PROFILETIMINGS`
- Profile timings: 128 - :class:`DBG_ENABLESATCOMPARISION`
- Enable sat comparision: 256 - :class:`DBG_DISABLEBULLETLCP`
- Disable Bullet LCP: 512 - :class:`DBG_ENABLECCD`
- Enable CCD: 1024 - :class:`DBG_DRAWCONSTRAINTS`
- Draw Constraints: #(1 << 11) = ? - :class:`DBG_DRAWCONSTRAINTLIMITS`
- Draw Constraint Limits: #(1 << 12) = ? - :class:`DBG_FASTWIREFRAME`
- Fast Wireframe: #(1 << 13) = ?
:arg mode: The new debug mode. :arg mode: The new debug mode.
:type mode: int :type mode: int
@@ -138,8 +160,11 @@ Game Engine bge.constraints Module
.. function:: setLinearAirDamping(damping) .. function:: setLinearAirDamping(damping)
.. note::
Not implemented. Not implemented.
Sets the linear air damping for rigidbodies.
.. function:: setNumIterations(numiter) .. function:: setNumIterations(numiter)
Sets the number of iterations for an iterative constraint solver. Sets the number of iterations for an iterative constraint solver.
@@ -156,10 +181,10 @@ Game Engine bge.constraints Module
.. function:: setSolverDamping(damping) .. function:: setSolverDamping(damping)
..note:: .. note::
Very experimental, not recommended Very experimental, not recommended
Sets the solver damping. Sets the damper constant of a penalty based solver.
:arg damping: New damping for the solver. :arg damping: New damping for the solver.
:type damping: float :type damping: float
@@ -169,7 +194,7 @@ Game Engine bge.constraints Module
.. note:: .. note::
Very experimental, not recommended Very experimental, not recommended
Sets the solver tau. Sets the spring constant of a penalty based solver.
:arg tau: New tau for the solver. :arg tau: New tau for the solver.
:type tau: float :type tau: float
@@ -189,7 +214,7 @@ Game Engine bge.constraints Module
.. note:: .. note::
Very experimental, not recommended Very experimental, not recommended
Sets the sor constant. Sets the successive overrelaxation constant.
:arg sor: New sor value. :arg sor: New sor value.
:type sor: float :type sor: float
@@ -197,3 +222,136 @@ Game Engine bge.constraints Module
.. function:: setUseEpa(epa) .. function:: setUseEpa(epa)
Not implemented. Not implemented.
.. data:: DBG_NODEBUG
.. note::
Debug mode to be used with function :class:`setDebugMode`
No debug.
.. data:: DBG_DRAWWIREFRAME
.. note::
Debug mode to be used with function :class:`setDebugMode`
Draw wireframe in debug.
.. data:: DBG_DRAWAABB
.. note::
Debug mode to be used with function :class:`setDebugMode`
Draw Axis Aligned Bounding Box in debug.
.. data:: DBG_DRAWFREATURESTEXT
.. note::
Debug mode to be used with function :class:`setDebugMode`
Draw freatures text in debug.
.. data:: DBG_DRAWCONTACTPOINTS
.. note::
Debug mode to be used with function :class:`setDebugMode`
Draw contact points in debug.
.. data:: DBG_NOHELPTEXT
.. note::
Debug mode to be used with function :class:`setDebugMode`
Debug without help text.
.. data:: DBG_DRAWTEXT
.. note::
Debug mode to be used with function :class:`setDebugMode`
Draw text in debug.
.. data:: DBG_PROFILETIMINGS
.. note::
Debug mode to be used with function :class:`setDebugMode`
Draw profile timings in debug.
.. data:: DBG_ENABLESATCOMPARISION
.. note::
Debug mode to be used with function :class:`setDebugMode`
Enable sat comparision in debug.
.. data:: DBG_DISABLEBULLETLCP
.. note::
Debug mode to be used with function :class:`setDebugMode`
Disable Bullet LCP.
.. data:: DBG_ENABLECCD
.. note::
Debug mode to be used with function :class:`setDebugMode`
Enable Continous Colision Detection in debug.
.. data:: DBG_DRAWCONSTRAINTS
.. note::
Debug mode to be used with function :class:`setDebugMode`
Draw constraints in debug.
.. data:: DBG_DRAWCONSTRAINTLIMITS
.. note::
Debug mode to be used with function :class:`setDebugMode`
Draw constraint limits in debug.
.. data:: DBG_FASTWIREFRAME
.. note::
Debug mode to be used with function :class:`setDebugMode`
Draw a fast wireframe in debug.
.. data:: POINTTOPOINT_CONSTRAINT
.. note::
Constraint type to be used with function :class:`createConstraint`
.. to do
.. data:: LINEHINGE_CONSTRAINT
.. note::
Constraint type to be used with function :class:`createConstraint`
.. to do
.. data:: ANGULAR_CONSTRAINT
.. note::
Constraint type to be used with function :class:`createConstraint`
.. to do
.. data:: CONETWIST_CONSTRAINT
.. note::
Constraint type to be used with function :class:`createConstraint`
.. to do
.. data:: VEHICLE_CONSTRAINT
.. note::
Constraint type to be used with function :class:`createConstraint`
.. to do

View File

@@ -1,6 +1,6 @@
Game Engine bge.events Module Game Keys (bge.events)
============================= ======================
***** *****
Intro Intro

View File

@@ -1,6 +1,7 @@
Game Engine bge.logic Module Game Logic (bge.logic)
============================ ======================
***** *****
Intro Intro
***** *****
@@ -216,6 +217,12 @@ General functions
Loads a scene into the game engine. Loads a scene into the game engine.
.. note::
This function is not effective immediately, the scene is queued
and added on the next logic cycle where it will be available
from `getSceneList`
:arg name: The name of the scene :arg name: The name of the scene
:type name: string :type name: string
:arg overlay: Overlay or underlay (optional) :arg overlay: Overlay or underlay (optional)

View File

@@ -1,6 +1,6 @@
Game Engine bge.render Module Rasterizer (bge.render)
============================= =======================
***** *****
Intro Intro
@@ -16,8 +16,8 @@ Intro
import bge.render import bge.render
import bge.logic import bge.logic
# SCALE sets the speed of motion # scale sets the speed of motion
SCALE=[1, 0.5] scale = 1.0, 0.5
co = bge.logic.getCurrentController() co = bge.logic.getCurrentController()
obj = co.getOwner() obj = co.getOwner()
@@ -27,8 +27,8 @@ Intro
# Transform the mouse coordinates to see how far the mouse has moved. # Transform the mouse coordinates to see how far the mouse has moved.
def mousePos(): def mousePos():
x = (bge.render.getWindowWidth()/2 - mouse.getXPosition())*SCALE[0] x = (bge.render.getWindowWidth() / 2 - mouse.getXPosition()) * scale[0]
y = (bge.render.getWindowHeight()/2 - mouse.getYPosition())*SCALE[1] y = (bge.render.getWindowHeight() / 2 - mouse.getYPosition()) * scale[1]
return (x, y) return (x, y)
pos = mousePos() pos = mousePos()
@@ -43,7 +43,7 @@ Intro
bge.logic.addActiveActuator(wmotion, True) bge.logic.addActiveActuator(wmotion, True)
# Centre the mouse # Centre the mouse
bge.render.setMousePosition(bge.render.getWindowWidth()/2, bge.render.getWindowHeight()/2) bge.render.setMousePosition(bge.render.getWindowWidth() / 2, bge.render.getWindowHeight() / 2)
********* *********
Constants Constants

12
doc/python_api/rst/bge.texture.rst Executable file → Normal file
View File

@@ -1,10 +1,6 @@
Game Engine bge.texture Module Video Texture (bge.texture)
============================== ===========================
.. note::
This documentation is still very weak, and needs some help! Right now they are mostly a collection
of the docstrings found in the bge.texture source code + some random places filled with text.
***** *****
Intro Intro
@@ -40,6 +36,10 @@ When the texture object is deleted, the new texture is deleted and the old textu
.. module:: bge.texture .. module:: bge.texture
.. literalinclude:: ../examples/bge.texture.py
.. literalinclude:: ../examples/bge.texture.1.py
.. class:: VideoFFmpeg(file [, capture=-1, rate=25.0, width=0, height=0]) .. class:: VideoFFmpeg(file [, capture=-1, rate=25.0, width=0, height=0])
FFmpeg video source FFmpeg video source

View File

@@ -1,6 +1,6 @@
Game Engine bge.types Module Game Types (bge.types)
============================= ======================
.. module:: bge.types .. module:: bge.types

14
doc/python_api/rst/bgl.rst Executable file → Normal file
View File

@@ -1,6 +1,6 @@
bgl module (OpenGL wrapper) OpenGL Wrapper (bgl)
=========================== ====================
.. module:: bgl .. module:: bgl
@@ -15,7 +15,7 @@ collections of tutorials.
The "red book": "I{OpenGL Programming Guide: The Official Guide to Learning The "red book": "I{OpenGL Programming Guide: The Official Guide to Learning
OpenGL}" and the online NeHe tutorials are two of the best resources. OpenGL}" and the online NeHe tutorials are two of the best resources.
..note:: .. note::
You can use the :class:`Image` type to load and set textures. You can use the :class:`Image` type to load and set textures.
See :class:`Image.gl_load` and :class:`Image.gl_load`, See :class:`Image.gl_load` and :class:`Image.gl_load`,
for example. for example.
@@ -71,8 +71,8 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
.. seealso:: `OpenGL Docs <http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/begin.html>`_ .. seealso:: `OpenGL Docs <http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/begin.html>`_
:type mode: Enumerated constant :type mode: Enumerated constant
:arg mode: Specifies the primitive that will be create from vertices between glBegin and :arg mode: Specifies the primitive that will be create from vertices between
glEnd. glBegin and glEnd.
.. function:: glBindTexture(target, texture): .. function:: glBindTexture(target, texture):
@@ -1848,10 +1848,13 @@ class Buffer:
.. code-block:: python .. code-block:: python
import bgl import bgl
myByteBuffer = bgl.Buffer(bgl.GL_BYTE, [32, 32]) myByteBuffer = bgl.Buffer(bgl.GL_BYTE, [32, 32])
bgl.glGetPolygonStipple(myByteBuffer) bgl.glGetPolygonStipple(myByteBuffer)
print(myByteBuffer.dimensions) print(myByteBuffer.dimensions)
print(myByteBuffer.to_list()) print(myByteBuffer.to_list())
sliceBuffer = myByteBuffer[0:16] sliceBuffer = myByteBuffer[0:16]
print(sliceBuffer) print(sliceBuffer)
@@ -1886,4 +1889,3 @@ class Buffer:
the Buffer. If a template is not passed in all fields will be initialized to 0. the Buffer. If a template is not passed in all fields will be initialized to 0.
:rtype: Buffer object :rtype: Buffer object
:return: The newly created buffer as a PyObject. :return: The newly created buffer as a PyObject.

View File

@@ -416,6 +416,7 @@ def pymodule2sphinx(BASEPATH, module_name, module, title):
del key, descr del key, descr
classes = [] classes = []
submodules = []
for attribute in module_dir: for attribute in module_dir:
if not attribute.startswith("_"): if not attribute.startswith("_"):
@@ -437,6 +438,8 @@ def pymodule2sphinx(BASEPATH, module_name, module, title):
py_c_func2sphinx("", fw, module_name, None, attribute, value, is_class=False) py_c_func2sphinx("", fw, module_name, None, attribute, value, is_class=False)
elif value_type == type: elif value_type == type:
classes.append((attribute, value)) classes.append((attribute, value))
elif issubclass(value_type, types.ModuleType):
submodules.append((attribute, value))
elif value_type in (bool, int, float, str, tuple): elif value_type in (bool, int, float, str, tuple):
# constant, not much fun we can do here except to list it. # constant, not much fun we can do here except to list it.
# TODO, figure out some way to document these! # TODO, figure out some way to document these!
@@ -444,12 +447,26 @@ def pymodule2sphinx(BASEPATH, module_name, module, title):
write_indented_lines(" ", fw, "constant value %s" % repr(value), False) write_indented_lines(" ", fw, "constant value %s" % repr(value), False)
fw("\n") fw("\n")
else: else:
print("\tnot documenting %s.%s" % (module_name, attribute)) print("\tnot documenting %s.%s of %r type" % (module_name, attribute, value_type.__name__))
continue continue
attribute_set.add(attribute) attribute_set.add(attribute)
# TODO, more types... # TODO, more types...
# TODO, bpy_extras does this already, mathutils not.
"""
if submodules:
fw("\n"
"**********\n"
"Submodules\n"
"**********\n"
"\n"
)
for attribute, submod in submodules:
fw("* :mod:`%s.%s`\n" % (module_name, attribute))
fw("\n")
"""
# write collected classes now # write collected classes now
for (type_name, value) in classes: for (type_name, value) in classes:
# May need to be its own function # May need to be its own function

View File

@@ -44,7 +44,6 @@ set(SRC
intern/GHOST_ISystem.cpp intern/GHOST_ISystem.cpp
intern/GHOST_ISystemPaths.cpp intern/GHOST_ISystemPaths.cpp
intern/GHOST_ModifierKeys.cpp intern/GHOST_ModifierKeys.cpp
intern/GHOST_NDOFManager.cpp
intern/GHOST_Path-api.cpp intern/GHOST_Path-api.cpp
intern/GHOST_Path-api.cpp intern/GHOST_Path-api.cpp
intern/GHOST_Rect.cpp intern/GHOST_Rect.cpp
@@ -74,12 +73,10 @@ set(SRC
intern/GHOST_EventDragnDrop.h intern/GHOST_EventDragnDrop.h
intern/GHOST_EventKey.h intern/GHOST_EventKey.h
intern/GHOST_EventManager.h intern/GHOST_EventManager.h
intern/GHOST_EventNDOF.h
intern/GHOST_EventString.h intern/GHOST_EventString.h
intern/GHOST_EventTrackpad.h intern/GHOST_EventTrackpad.h
intern/GHOST_EventWheel.h intern/GHOST_EventWheel.h
intern/GHOST_ModifierKeys.h intern/GHOST_ModifierKeys.h
intern/GHOST_NDOFManager.h
intern/GHOST_System.h intern/GHOST_System.h
intern/GHOST_SystemPaths.h intern/GHOST_SystemPaths.h
intern/GHOST_TimerManager.h intern/GHOST_TimerManager.h
@@ -97,6 +94,20 @@ if(WITH_GHOST_DEBUG)
add_definitions(-DWITH_GHOST_DEBUG) add_definitions(-DWITH_GHOST_DEBUG)
endif() endif()
if(WITH_INPUT_NDOF)
add_definitions(-DWITH_INPUT_NDOF)
list(APPEND SRC
intern/GHOST_NDOFManager.cpp
intern/GHOST_EventNDOF.h
intern/GHOST_NDOFManager.h
)
list(APPEND INC_SYS
${NDOF_INCLUDE_DIRS}
)
endif()
if(WITH_HEADLESS OR WITH_GHOST_SDL) if(WITH_HEADLESS OR WITH_GHOST_SDL)
if(WITH_HEADLESS) if(WITH_HEADLESS)
@@ -138,6 +149,10 @@ if(WITH_HEADLESS OR WITH_GHOST_SDL)
intern/GHOST_SystemPathsX11.cpp intern/GHOST_SystemPathsX11.cpp
intern/GHOST_SystemPathsX11.h intern/GHOST_SystemPathsX11.h
) )
if(NOT WITH_INSTALL_PORTABLE)
add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}")
endif()
elseif(WIN32) elseif(WIN32)
list(APPEND SRC list(APPEND SRC
@@ -164,6 +179,15 @@ elseif(APPLE)
intern/GHOST_SystemPathsCocoa.h intern/GHOST_SystemPathsCocoa.h
intern/GHOST_WindowCocoa.h intern/GHOST_WindowCocoa.h
) )
if(WITH_INPUT_NDOF)
list(APPEND SRC
intern/GHOST_NDOFManagerCocoa.mm
intern/GHOST_NDOFManagerCocoa.h
)
endif()
else() else()
list(APPEND SRC list(APPEND SRC
intern/GHOST_DisplayManagerCarbon.cpp intern/GHOST_DisplayManagerCarbon.cpp
@@ -184,10 +208,6 @@ elseif(APPLE)
elseif(UNIX) elseif(UNIX)
if(WITH_X11_XINPUT)
add_definitions(-DWITH_X11_XINPUT)
endif()
list(APPEND INC_SYS list(APPEND INC_SYS
${X11_X11_INCLUDE_PATH} ${X11_X11_INCLUDE_PATH}
) )
@@ -204,10 +224,6 @@ elseif(UNIX)
intern/GHOST_WindowX11.h intern/GHOST_WindowX11.h
) )
if(NOT WITH_INSTALL_PORTABLE)
add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}")
endif()
if(X11_XF86keysym_INCLUDE_PATH) if(X11_XF86keysym_INCLUDE_PATH)
add_definitions(-DWITH_XF86KEYSYM) add_definitions(-DWITH_XF86KEYSYM)
list(APPEND INC_SYS list(APPEND INC_SYS
@@ -215,6 +231,22 @@ elseif(UNIX)
) )
endif() endif()
if(WITH_INPUT_NDOF)
list(APPEND SRC
intern/GHOST_NDOFManagerX11.cpp
intern/GHOST_NDOFManagerX11.h
)
endif()
if(NOT WITH_INSTALL_PORTABLE)
add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}")
endif()
if(WITH_X11_XINPUT)
add_definitions(-DWITH_X11_XINPUT)
endif()
elseif(WIN32) elseif(WIN32)
if(MSVC) if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX")
@@ -238,6 +270,15 @@ elseif(WIN32)
intern/GHOST_WindowWin32.h intern/GHOST_WindowWin32.h
intern/GHOST_TaskbarWin32.h intern/GHOST_TaskbarWin32.h
) )
if(WITH_INPUT_NDOF)
list(APPEND SRC
intern/GHOST_NDOFManagerWin32.cpp
intern/GHOST_NDOFManagerWin32.h
)
endif()
endif() endif()
blender_add_lib(bf_intern_ghost "${SRC}" "${INC}" "${INC_SYS}") blender_add_lib(bf_intern_ghost "${SRC}" "${INC}" "${INC_SYS}")

View File

@@ -289,21 +289,6 @@ extern GHOST_TSuccess GHOST_SetProgressBar(GHOST_WindowHandle windowhandle, floa
*/ */
extern GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle); 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 ** Cursor management functionality
***************************************************************************************/ ***************************************************************************************/

View File

@@ -298,22 +298,6 @@ public:
*/ */
virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer* consumer) = 0; 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 ** Cursor management functionality
***************************************************************************************/ ***************************************************************************************/

View File

@@ -47,11 +47,6 @@ typedef unsigned short GHOST_TUns16;
typedef int GHOST_TInt32; typedef int GHOST_TInt32;
typedef unsigned int GHOST_TUns32; 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) #if defined(WIN32) && !defined(FREE_WINDOWS)
typedef __int64 GHOST_TInt64; typedef __int64 GHOST_TInt64;
typedef unsigned __int64 GHOST_TUns64; typedef unsigned __int64 GHOST_TUns64;
@@ -440,37 +435,33 @@ typedef struct {
GHOST_TUns8 **strings; GHOST_TUns8 **strings;
} GHOST_TStringArray; } GHOST_TStringArray;
typedef enum {
/* original patch used floats, but the driver return ints and uns. We will calibrate in view, no sense on doing conversions twice */ GHOST_kNotStarted,
/* as all USB device controls are likely to use ints, this is also more future proof */ GHOST_kStarting,
//typedef struct { GHOST_kInProgress,
// /** N-degree of freedom device data */ GHOST_kFinishing,
// float tx, ty, tz; /** -x left, +y up, +z forward */ GHOST_kFinished
// float rx, ry, rz; } GHOST_TProgress;
// float dt;
//} GHOST_TEventNDOFData;
typedef struct { typedef struct {
/** N-degree of freedom device data v2*/ /** N-degree of freedom device data v3 [GSoC 2010] */
int changed; // Each component normally ranges from -1 to +1, but can exceed that.
GHOST_TUns64 client; // These use blender standard view coordinates, with positive rotations being CCW about the axis.
GHOST_TUns64 address; float tx, ty, tz; // translation
GHOST_TInt16 tx, ty, tz; /** -x left, +y up, +z forward */ float rx, ry, rz; // rotation:
GHOST_TInt16 rx, ry, rz; // axis = (rx,ry,rz).normalized
GHOST_TInt16 buttons; // amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg]
GHOST_TUns64 time; float dt; // time since previous NDOF Motion event
GHOST_TUns64 delta; GHOST_TProgress progress; // Starting, InProgress or Finishing (for modal handlers)
} GHOST_TEventNDOFData; } GHOST_TEventNDOFMotionData;
typedef int (*GHOST_NDOFLibraryInit_fp)(void); typedef enum { GHOST_kPress, GHOST_kRelease } GHOST_TButtonAction;
typedef void (*GHOST_NDOFLibraryShutdown_fp)(void* deviceHandle); // good for mouse or other buttons too, hmmm?
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. typedef struct {
// not necessary faster, but better integration with other events. GHOST_TButtonAction action;
short button;
//typedef int (*GHOST_NDOFEventHandler_fp)(float* result7, void* deviceHandle, unsigned int message, unsigned int* wParam, unsigned long* lParam); } GHOST_TEventNDOFButtonData;
//typedef void (*GHOST_NDOFCallBack_fp)(GHOST_TEventNDOFDataV2 *VolDatas);
typedef struct { typedef struct {
/** The key code. */ /** The key code. */

View File

@@ -11,7 +11,7 @@ if window_system == 'darwin':
sources += env.Glob('intern/*.mm') 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'] defs=['_USE_MATH_DEFINES']
incs = '. ../string #extern/glew/include #source/blender/imbuf #source/blender/makesdna ' + env['BF_OPENGL_INC'] incs = '. ../string #extern/glew/include #source/blender/imbuf #source/blender/makesdna ' + env['BF_OPENGL_INC']
@@ -78,6 +78,24 @@ if env['BF_GHOST_DEBUG']:
else: else:
sources.remove('intern' + os.sep + 'GHOST_EventPrinter.cpp') 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
if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'): if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
incs = env['BF_WINTAB_INC'] + ' ' + incs incs = env['BF_WINTAB_INC'] + ' ' + incs

View File

@@ -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_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandle)
{ {
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;

View File

@@ -35,8 +35,11 @@
#include "GHOST_DisplayManagerWin32.h" #include "GHOST_DisplayManagerWin32.h"
#include "GHOST_Debug.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> #include <windows.h>
// We do not support multiple monitors at the moment
#define COMPILE_MULTIMON_STUBS #define COMPILE_MULTIMON_STUBS
#ifndef FREE_WINDOWS #ifndef FREE_WINDOWS
#include <multimon.h> #include <multimon.h>

View File

@@ -33,6 +33,7 @@
#include "GHOST_Debug.h" #include "GHOST_Debug.h"
#include "GHOST_DropTargetWin32.h" #include "GHOST_DropTargetWin32.h"
#include <ShellApi.h>
#ifdef GHOST_DEBUG #ifdef GHOST_DEBUG
// utility // utility

View File

@@ -33,7 +33,6 @@
#ifndef _GHOST_DROP_TARGET_WIN32_H_ #ifndef _GHOST_DROP_TARGET_WIN32_H_
#define _GHOST_DROP_TARGET_WIN32_H_ #define _GHOST_DROP_TARGET_WIN32_H_
#include <windows.h>
#include <string.h> #include <string.h>
#include <GHOST_Types.h> #include <GHOST_Types.h>
#include "GHOST_WindowWin32.h" #include "GHOST_WindowWin32.h"

View File

@@ -42,7 +42,7 @@
#include "GHOST_EventManager.h" #include "GHOST_EventManager.h"
#include <algorithm> #include <algorithm>
#include "GHOST_Debug.h" #include "GHOST_Debug.h"
#include <stdio.h> // [mce] temp debug
GHOST_EventManager::GHOST_EventManager() GHOST_EventManager::GHOST_EventManager()
{ {

View File

@@ -20,43 +20,39 @@
* ***** END GPL LICENSE BLOCK ***** * ***** END GPL LICENSE BLOCK *****
*/ */
/** \file ghost/intern/GHOST_EventNDOF.h
* \ingroup GHOST
*/
#ifndef _GHOST_EVENT_NDOF_H_ #ifndef _GHOST_EVENT_NDOF_H_
#define _GHOST_EVENT_NDOF_H_ #define _GHOST_EVENT_NDOF_H_
#include "GHOST_Event.h" #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: class GHOST_EventNDOFMotion : public GHOST_Event
/** translation & rotation from the device. */ {
GHOST_TEventNDOFData m_ndofEventData; 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_ #endif // _GHOST_EVENT_NDOF_H_

View File

@@ -1,4 +1,6 @@
/* /*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK ***** * ***** BEGIN GPL LICENSE BLOCK *****
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@@ -15,122 +17,458 @@
* along with this program; if not, write to the Free Software Foundation, * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
* Contributor(s): none yet. * Contributor(s):
* Mike Erwin
* *
* ***** END GPL LICENSE BLOCK ***** * ***** END GPL LICENSE BLOCK *****
*/ */
/** \file ghost/intern/GHOST_NDOFManager.cpp #include "GHOST_Debug.h"
* \ingroup GHOST
*/
#include <stdio.h> /* just for printf */
#include "GHOST_NDOFManager.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
// the variable is outside the class because it must be accessed from plugin // printable version of each GHOST_TProgress value
static volatile GHOST_TEventNDOFData currentNdofValues = {0,0,0,0,0,0,0,0,0,0,0}; static const char* progress_string[] =
{"not started","starting","in progress","finishing","finished"};
#if !defined(_WIN32) && !defined(__APPLE__)
#include "GHOST_SystemX11.h"
#endif #endif
namespace #ifdef DEBUG_NDOF_BUTTONS
{ static const char* ndof_button_names[] = {
GHOST_NDOFLibraryInit_fp ndofLibraryInit = 0; // used internally, never sent
GHOST_NDOFLibraryShutdown_fp ndofLibraryShutdown = 0; "NDOF_BUTTON_NONE",
GHOST_NDOFDeviceOpen_fp ndofDeviceOpen = 0; // these two are available from any 3Dconnexion device
} "NDOF_BUTTON_MENU",
"NDOF_BUTTON_FIT",
GHOST_NDOFManager::GHOST_NDOFManager() // standard views
{ "NDOF_BUTTON_TOP",
m_DeviceHandle = 0; "NDOF_BUTTON_BOTTOM",
"NDOF_BUTTON_LEFT",
// discover the API from the plugin "NDOF_BUTTON_RIGHT",
ndofLibraryInit = 0; "NDOF_BUTTON_FRONT",
ndofLibraryShutdown = 0; "NDOF_BUTTON_BACK",
ndofDeviceOpen = 0; // more views
} "NDOF_BUTTON_ISO1",
"NDOF_BUTTON_ISO2",
GHOST_NDOFManager::~GHOST_NDOFManager() // 90 degree rotations
{ "NDOF_BUTTON_ROLL_CW",
if (ndofLibraryShutdown) "NDOF_BUTTON_ROLL_CCW",
ndofLibraryShutdown(m_DeviceHandle); "NDOF_BUTTON_SPIN_CW",
"NDOF_BUTTON_SPIN_CCW",
m_DeviceHandle = 0; "NDOF_BUTTON_TILT_CW",
} "NDOF_BUTTON_TILT_CCW",
// device control
"NDOF_BUTTON_ROTATE",
int "NDOF_BUTTON_PANZOOM",
GHOST_NDOFManager::deviceOpen(GHOST_IWindow* window, "NDOF_BUTTON_DOMINANT",
GHOST_NDOFLibraryInit_fp setNdofLibraryInit, "NDOF_BUTTON_PLUS",
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, "NDOF_BUTTON_MINUS",
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen) // general-purpose buttons
{ "NDOF_BUTTON_1",
int Pid; "NDOF_BUTTON_2",
"NDOF_BUTTON_3",
ndofLibraryInit = setNdofLibraryInit; "NDOF_BUTTON_4",
ndofLibraryShutdown = setNdofLibraryShutdown; "NDOF_BUTTON_5",
ndofDeviceOpen = setNdofDeviceOpen; "NDOF_BUTTON_6",
"NDOF_BUTTON_7",
if (ndofLibraryInit && ndofDeviceOpen) "NDOF_BUTTON_8",
{ "NDOF_BUTTON_9",
Pid= ndofLibraryInit(); "NDOF_BUTTON_10",
#if 0 };
printf("%i client \n", Pid);
#endif #endif
#if defined(WITH_HEADLESS)
/* do nothing */
#elif defined(_WIN32) || defined(__APPLE__)
m_DeviceHandle = ndofDeviceOpen((void *)&currentNdofValues);
#elif defined(WITH_GHOST_SDL)
/* do nothing */
#else
GHOST_SystemX11 *sys;
sys = static_cast<GHOST_SystemX11*>(GHOST_ISystem::getSystem());
void *ndofInfo = sys->prepareNdofInfo(&currentNdofValues);
m_DeviceHandle = ndofDeviceOpen(ndofInfo);
#endif
return (Pid > 0) ? 0 : 1;
} else static const NDOF_ButtonT SpaceNavigator_HID_map[] = {
return 1; 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
};
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
};
/* 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?
};
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)
{
// 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));
} }
bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short product_id)
bool
GHOST_NDOFManager::available() const
{ {
return 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;
// -- 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
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; return true;
}else }
}
void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time)
{
memcpy(m_translation, t, sizeof(m_translation));
m_motionTime = time;
m_motionEventPending = true;
}
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
m_system.pushEvent(event);
}
void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 time)
{
GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow();
#ifdef DEBUG_NDOF_BUTTONS
if (m_deviceType != NDOF_UnknownDevice)
printf("ndof: button %d -> ", button_number);
#endif
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;
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);
}
}
}
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);
}
static bool atHomePosition(GHOST_TEventNDOFMotionData* ndof)
{
#define HOME(foo) (ndof->foo == 0.f)
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 HOME(foo) (fabsf(ndof->foo) < threshold)
return HOME(tx) && HOME(ty) && HOME(tz) && HOME(rx) && HOME(ry) && HOME(rz);
#undef HOME
}
}
bool GHOST_NDOFManager::sendMotionEvent()
{
if (!m_motionEventPending)
return false; return false;
} m_motionEventPending = false; // any pending motion is handled right now
void GHOST_NDOFManager::GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow();
{
datas.tx = currentNdofValues.tx; if (window == NULL) {
datas.ty = currentNdofValues.ty; return false; // delivery will fail, so don't bother sending
datas.tz = currentNdofValues.tz; }
datas.rx = currentNdofValues.rx;
datas.ry = currentNdofValues.ry; GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, window);
datas.rz = currentNdofValues.rz; GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData();
datas.buttons = currentNdofValues.buttons;
datas.client = currentNdofValues.client; // scale axis values here to normalize them to around +/- 1
datas.address = currentNdofValues.address; // they are scaled again for overall sensitivity in the WM based on user prefs
datas.time = currentNdofValues.time;
datas.delta = currentNdofValues.delta; 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 weHaveMotion = !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 (weHaveMotion) {
data->progress = GHOST_kStarting;
m_motionState = GHOST_kInProgress;
// prev motion time will be ancient, so just make up a reasonable time delta
data->dt = 0.0125f;
}
else {
// send no event and keep current state
delete event;
return false;
}
break;
case GHOST_kInProgress:
if (weHaveMotion) {
data->progress = GHOST_kInProgress;
// remain 'InProgress'
}
else {
data->progress = GHOST_kFinishing;
m_motionState = GHOST_kFinished;
}
break;
default:
; // will always be one of the above
}
#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;
} }

View File

@@ -1,4 +1,6 @@
/* /*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK ***** * ***** BEGIN GPL LICENSE BLOCK *****
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@@ -15,43 +17,142 @@
* along with this program; if not, write to the Free Software Foundation, * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
* Contributor(s): none yet. * Contributor(s):
* Mike Erwin
* *
* ***** END GPL LICENSE BLOCK ***** * ***** END GPL LICENSE BLOCK *****
*/ */
/** \file ghost/intern/GHOST_NDOFManager.h
* \ingroup GHOST
*/
#ifndef _GHOST_NDOFMANAGER_H_ #ifndef _GHOST_NDOFMANAGER_H_
#define _GHOST_NDOFMANAGER_H_ #define _GHOST_NDOFMANAGER_H_
#include "GHOST_System.h" #include "GHOST_System.h"
#include "GHOST_IWindow.h"
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 class GHOST_NDOFManager
{ {
public: public:
GHOST_NDOFManager(); GHOST_NDOFManager(GHOST_System&);
virtual ~GHOST_NDOFManager();
int deviceOpen(GHOST_IWindow* window, virtual ~GHOST_NDOFManager() {};
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen);
void GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const; // 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;
bool available() const; // each platform's device detection should call this
bool event_present() const; // 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: 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 #endif

View File

@@ -0,0 +1,53 @@
/*
* $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_
#ifdef WITH_INPUT_NDOF
#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 // WITH_INPUT_NDOF
#endif // #include guard

View File

@@ -0,0 +1,176 @@
/*
* $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
#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
}
#endif // WITH_INPUT_NDOF

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,105 @@
/*
* $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
#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 {
puts("ndof: spacenavd not found");
/* 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::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;
}
#endif /* WITH_INPUT_NDOF */

View File

@@ -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_NDOFMANAGERX11_H_
#define _GHOST_NDOFMANAGERX11_H_
#ifdef WITH_INPUT_NDOF
#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 m_available;
};
#endif /* WITH_INPUT_NDOF */
#endif /* #include guard */

View File

@@ -46,7 +46,13 @@
GHOST_System::GHOST_System() 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 GHOST_System::dispatchEvents()
{ {
bool handled; bool handled = false;
if (m_eventManager) {
handled = m_eventManager->dispatchEvents(); #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 { #endif
handled = false;
if (m_eventManager) {
handled |= m_eventManager->dispatchEvents();
} }
m_timerManager->fireTimers(getMilliSeconds()); m_timerManager->fireTimers(getMilliSeconds());
@@ -243,18 +254,6 @@ GHOST_TSuccess GHOST_System::pushEvent(GHOST_IEvent* event)
return success; 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_TSuccess GHOST_System::getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const
{ {
GHOST_ModifierKeys keys; GHOST_ModifierKeys keys;
@@ -285,12 +284,6 @@ GHOST_TSuccess GHOST_System::init()
m_timerManager = new GHOST_TimerManager (); m_timerManager = new GHOST_TimerManager ();
m_windowManager = new GHOST_WindowManager (); m_windowManager = new GHOST_WindowManager ();
m_eventManager = new GHOST_EventManager (); m_eventManager = new GHOST_EventManager ();
m_ndofManager = new GHOST_NDOFManager();
#if 0
if(m_ndofManager)
printf("ndof manager \n");
#endif
#ifdef GHOST_DEBUG #ifdef GHOST_DEBUG
if (m_eventManager) { if (m_eventManager) {
@@ -328,10 +321,12 @@ GHOST_TSuccess GHOST_System::exit()
delete m_eventManager; delete m_eventManager;
m_eventManager = 0; m_eventManager = 0;
} }
#ifdef WITH_INPUT_NDOF
if (m_ndofManager) { if (m_ndofManager) {
delete m_ndofManager; delete m_ndofManager;
m_ndofManager = 0; m_ndofManager = 0;
} }
#endif
return GHOST_kSuccess; return GHOST_kSuccess;
} }

View File

@@ -190,25 +190,6 @@ public:
*/ */
virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer* consumer); 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 ** Cursor management functionality
***************************************************************************************/ ***************************************************************************************/
@@ -268,11 +249,13 @@ public:
*/ */
virtual inline GHOST_WindowManager* getWindowManager() const; virtual inline GHOST_WindowManager* getWindowManager() const;
#ifdef WITH_INPUT_NDOF
/** /**
* Returns a pointer to our n-degree of freedeom manager. * Returns a pointer to our n-degree of freedeom manager.
* @return 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; virtual inline GHOST_NDOFManager* getNDOFManager() const;
#endif
/** /**
* Returns the state of all modifier keys. * Returns the state of all modifier keys.
@@ -337,8 +320,10 @@ protected:
/** The event manager. */ /** The event manager. */
GHOST_EventManager* m_eventManager; GHOST_EventManager* m_eventManager;
#ifdef WITH_INPUT_NDOF
/** The N-degree of freedom device manager */ /** The N-degree of freedom device manager */
GHOST_NDOFManager* m_ndofManager; GHOST_NDOFManager* m_ndofManager;
#endif
/** Prints all the events. */ /** Prints all the events. */
#ifdef GHOST_DEBUG #ifdef GHOST_DEBUG
@@ -364,10 +349,12 @@ inline GHOST_WindowManager* GHOST_System::getWindowManager() const
return m_windowManager; return m_windowManager;
} }
#ifdef WITH_INPUT_NDOF
inline GHOST_NDOFManager* GHOST_System::getNDOFManager() const inline GHOST_NDOFManager* GHOST_System::getNDOFManager() const
{ {
return m_ndofManager; return m_ndofManager;
} }
#endif
#endif // _GHOST_SYSTEM_H_ #endif // _GHOST_SYSTEM_H_

View File

@@ -220,6 +220,11 @@ public:
*/ */
GHOST_TSuccess handleApplicationBecomeActiveEvent(); GHOST_TSuccess handleApplicationBecomeActiveEvent();
/**
* External objects should call this when they send an event outside processEvents.
*/
void notifyExternalEventProcessed();
/** /**
* @see GHOST_ISystem * @see GHOST_ISystem
*/ */
@@ -267,7 +272,7 @@ protected:
/** Start time at initialization. */ /** Start time at initialization. */
GHOST_TUns64 m_start_time; 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; bool m_outsideLoopEventProcessed;
/** Raised window is not yet known by the window manager, so delay application become active event handling */ /** Raised window is not yet known by the window manager, so delay application become active event handling */

View File

@@ -21,7 +21,7 @@
* *
* The Original Code is: all of this file. * The Original Code is: all of this file.
* *
* Contributor(s): Maarten Gribnau 05/2001 * Contributors: Maarten Gribnau 05/2001
* Damien Plisson 09/2009 * Damien Plisson 09/2009
* *
* ***** END GPL LICENSE BLOCK ***** * ***** END GPL LICENSE BLOCK *****
@@ -43,16 +43,17 @@
#include "GHOST_EventButton.h" #include "GHOST_EventButton.h"
#include "GHOST_EventCursor.h" #include "GHOST_EventCursor.h"
#include "GHOST_EventWheel.h" #include "GHOST_EventWheel.h"
#include "GHOST_EventNDOF.h"
#include "GHOST_EventTrackpad.h" #include "GHOST_EventTrackpad.h"
#include "GHOST_EventDragnDrop.h" #include "GHOST_EventDragnDrop.h"
#include "GHOST_EventString.h" #include "GHOST_EventString.h"
#include "GHOST_TimerManager.h" #include "GHOST_TimerManager.h"
#include "GHOST_TimerTask.h" #include "GHOST_TimerTask.h"
#include "GHOST_WindowManager.h" #include "GHOST_WindowManager.h"
#include "GHOST_WindowCocoa.h" #include "GHOST_WindowCocoa.h"
#include "GHOST_NDOFManager.h" #ifdef WITH_INPUT_NDOF
#include "GHOST_NDOFManagerCocoa.h"
#endif
#include "AssertMacros.h" #include "AssertMacros.h"
#pragma mark KeyMap, mouse converters #pragma mark KeyMap, mouse converters
@@ -596,6 +597,11 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
GHOST_TSuccess success = GHOST_System::init(); GHOST_TSuccess success = GHOST_System::init();
if (success) { if (success) {
#ifdef WITH_INPUT_NDOF
m_ndofManager = new GHOST_NDOFManagerCocoa(*this);
#endif
//ProcessSerialNumber psn; //ProcessSerialNumber psn;
//Carbon stuff to move window & menu to foreground //Carbon stuff to move window & menu to foreground
@@ -1007,6 +1013,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
return GHOST_kSuccess; return GHOST_kSuccess;
} }
void GHOST_SystemCocoa::notifyExternalEventProcessed()
{
m_outsideLoopEventProcessed = true;
}
//Note: called from NSWindow delegate //Note: called from NSWindow delegate
GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window) GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window)
{ {
@@ -1560,6 +1571,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
GHOST_TInt32 delta; GHOST_TInt32 delta;
double deltaF = [event deltaY]; 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 if (deltaF == 0.0) break; //discard trackpad delta=0 events
delta = deltaF > 0.0 ? 1 : -1; delta = deltaF > 0.0 ? 1 : -1;

View File

@@ -32,12 +32,9 @@
#include "GHOST_SystemPathsWin32.h" #include "GHOST_SystemPathsWin32.h"
#define WIN32_LEAN_AND_MEAN #ifndef _WIN32_IE
#ifdef _WIN32_IE
#undef _WIN32_IE
#endif
#define _WIN32_IE 0x0501 #define _WIN32_IE 0x0501
#include <windows.h> #endif
#include <shlobj.h> #include <shlobj.h>
#if defined(__MINGW32__) || defined(__CYGWIN__) #if defined(__MINGW32__) || defined(__CYGWIN__)

View File

@@ -38,6 +38,8 @@
#error WIN32 only! #error WIN32 only!
#endif // WIN32 #endif // WIN32
#define _WIN32_WINNT 0x501 // require Windows XP or newer
#define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#include "GHOST_SystemPaths.h" #include "GHOST_SystemPaths.h"

View File

@@ -43,7 +43,11 @@
#include <stdio.h> // for fprintf only #include <stdio.h> // for fprintf only
#include <cstdlib> // for exit #include <cstdlib> // for exit
using namespace std; #ifdef PREFIX
static const char *static_path= PREFIX "/share" ;
#else
static const char *static_path= NULL;
#endif
GHOST_SystemPathsX11::GHOST_SystemPathsX11() GHOST_SystemPathsX11::GHOST_SystemPathsX11()
{ {
@@ -56,21 +60,12 @@ GHOST_SystemPathsX11::~GHOST_SystemPathsX11()
const GHOST_TUns8* GHOST_SystemPathsX11::getSystemDir() const const GHOST_TUns8* GHOST_SystemPathsX11::getSystemDir() const
{ {
/* no prefix assumes a portable build which only uses bundled scripts */ /* no prefix assumes a portable build which only uses bundled scripts */
#ifdef PREFIX return (const GHOST_TUns8 *)static_path;
return (GHOST_TUns8*) PREFIX "/share";
#else
return NULL;
#endif
} }
const GHOST_TUns8* GHOST_SystemPathsX11::getUserDir() const const GHOST_TUns8* GHOST_SystemPathsX11::getUserDir() const
{ {
const char* env = getenv("HOME"); return (const GHOST_TUns8 *)getenv("HOME");
if(env) {
return (GHOST_TUns8*) env;
} else {
return NULL;
}
} }
const GHOST_TUns8* GHOST_SystemPathsX11::getBinaryDir() const const GHOST_TUns8* GHOST_SystemPathsX11::getBinaryDir() const

View File

@@ -146,7 +146,7 @@ convertSDLKey(SDL_Scancode key)
if ((key >= SDL_SCANCODE_A) && (key <= SDL_SCANCODE_Z)) { if ((key >= SDL_SCANCODE_A) && (key <= SDL_SCANCODE_Z)) {
type= GHOST_TKey( key - SDL_SCANCODE_A + int(GHOST_kKeyA)); type= GHOST_TKey( key - SDL_SCANCODE_A + int(GHOST_kKeyA));
} else if ((key >= SDL_SCANCODE_1) && (key <= SDL_SCANCODE_0)) { } else if ((key >= SDL_SCANCODE_1) && (key <= SDL_SCANCODE_0)) {
type= GHOST_TKey(key - SDL_SCANCODE_1 + int(GHOST_kKey0)); type= (key == SDL_SCANCODE_0) ? GHOST_kKey0 : GHOST_TKey(key - SDL_SCANCODE_1 + int(GHOST_kKey1));
} else if ((key >= SDL_SCANCODE_F1) && (key <= SDL_SCANCODE_F12)) { } else if ((key >= SDL_SCANCODE_F1) && (key <= SDL_SCANCODE_F12)) {
type= GHOST_TKey(key - SDL_SCANCODE_F1 + int(GHOST_kKeyF1)); type= GHOST_TKey(key - SDL_SCANCODE_F1 + int(GHOST_kKeyF1));
} else if ((key >= SDL_SCANCODE_F13) && (key <= SDL_SCANCODE_F24)) { } else if ((key >= SDL_SCANCODE_F13) && (key <= SDL_SCANCODE_F24)) {
@@ -167,6 +167,8 @@ convertSDLKey(SDL_Scancode key)
GXMAP(type,SDL_SCANCODE_APOSTROPHE, GHOST_kKeyQuote); GXMAP(type,SDL_SCANCODE_APOSTROPHE, GHOST_kKeyQuote);
GXMAP(type,SDL_SCANCODE_GRAVE, GHOST_kKeyAccentGrave); GXMAP(type,SDL_SCANCODE_GRAVE, GHOST_kKeyAccentGrave);
GXMAP(type,SDL_SCANCODE_MINUS, GHOST_kKeyMinus); GXMAP(type,SDL_SCANCODE_MINUS, GHOST_kKeyMinus);
GXMAP(type,SDL_SCANCODE_EQUALS, GHOST_kKeyEqual);
GXMAP(type,SDL_SCANCODE_SLASH, GHOST_kKeySlash); GXMAP(type,SDL_SCANCODE_SLASH, GHOST_kKeySlash);
GXMAP(type,SDL_SCANCODE_BACKSLASH, GHOST_kKeyBackslash); GXMAP(type,SDL_SCANCODE_BACKSLASH, GHOST_kKeyBackslash);
GXMAP(type,SDL_SCANCODE_KP_EQUALS, GHOST_kKeyEqual); GXMAP(type,SDL_SCANCODE_KP_EQUALS, GHOST_kKeyEqual);
@@ -180,6 +182,7 @@ convertSDLKey(SDL_Scancode key)
GXMAP(type,SDL_SCANCODE_RCTRL, GHOST_kKeyRightControl); GXMAP(type,SDL_SCANCODE_RCTRL, GHOST_kKeyRightControl);
GXMAP(type,SDL_SCANCODE_LALT, GHOST_kKeyLeftAlt); GXMAP(type,SDL_SCANCODE_LALT, GHOST_kKeyLeftAlt);
GXMAP(type,SDL_SCANCODE_RALT, GHOST_kKeyRightAlt); 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_RGUI, GHOST_kKeyOS);
GXMAP(type,SDL_SCANCODE_INSERT, GHOST_kKeyInsert); GXMAP(type,SDL_SCANCODE_INSERT, GHOST_kKeyInsert);
@@ -197,6 +200,7 @@ convertSDLKey(SDL_Scancode key)
GXMAP(type,SDL_SCANCODE_CAPSLOCK, GHOST_kKeyCapsLock); GXMAP(type,SDL_SCANCODE_CAPSLOCK, GHOST_kKeyCapsLock);
GXMAP(type,SDL_SCANCODE_SCROLLLOCK, GHOST_kKeyScrollLock); GXMAP(type,SDL_SCANCODE_SCROLLLOCK, GHOST_kKeyScrollLock);
GXMAP(type,SDL_SCANCODE_NUMLOCKCLEAR, GHOST_kKeyNumLock); GXMAP(type,SDL_SCANCODE_NUMLOCKCLEAR, GHOST_kKeyNumLock);
GXMAP(type,SDL_SCANCODE_PRINTSCREEN, GHOST_kKeyPrintScreen);
/* keypad events */ /* keypad events */
@@ -228,6 +232,7 @@ convertSDLKey(SDL_Scancode key)
GXMAP(type,SDL_SCANCODE_AUDIONEXT, GHOST_kKeyMediaLast); GXMAP(type,SDL_SCANCODE_AUDIONEXT, GHOST_kKeyMediaLast);
default: default:
printf("Unknown\n");
type= GHOST_kKeyUnknown; type= GHOST_kKeyUnknown;
break; break;
} }
@@ -372,6 +377,7 @@ GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
case SDL_KEYUP: case SDL_KEYUP:
{ {
SDL_KeyboardEvent &sdl_sub_evt= sdl_event->key; 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_TEventType type= (sdl_sub_evt.state == SDL_PRESSED) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID)); GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID));
@@ -379,7 +385,45 @@ GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
GHOST_TKey gkey= convertSDLKey(sdl_sub_evt.keysym.scancode); 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 */ /* note, the sdl_sub_evt.keysym.sym is truncated, for unicode support ghost has to be modified */
g_event= new GHOST_EventKey(getMilliSeconds(), type, window, gkey, sdl_sub_evt.keysym.sym); 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; break;
} }

View File

@@ -39,22 +39,20 @@
* @date May 7, 2001 * @date May 7, 2001
*/ */
#ifdef BF_GHOST_DEBUG
#include <iostream> #include <iostream>
#ifdef FREE_WINDOWS
# define WINVER 0x0501 /* GetConsoleWindow() for MinGW */
#endif #endif
#include <stdio.h> // [mce] temporary debug, remove soon!
#include "GHOST_SystemWin32.h" #include "GHOST_SystemWin32.h"
#include "GHOST_EventDragnDrop.h" #include "GHOST_EventDragnDrop.h"
#define WIN32_LEAN_AND_MEAN #ifndef _WIN32_IE
#ifdef _WIN32_IE #define _WIN32_IE 0x0501 /* shipped before XP, so doesn't impose additional requirements */
#undef _WIN32_IE
#endif #endif
#define _WIN32_IE 0x0501
#include <windows.h>
#include <shlobj.h> #include <shlobj.h>
#include <tlhelp32.h>
// win64 doesn't define GWL_USERDATA // win64 doesn't define GWL_USERDATA
#ifdef WIN32 #ifdef WIN32
@@ -64,48 +62,19 @@
#endif #endif
#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_DisplayManagerWin32.h"
#include "GHOST_EventButton.h" #include "GHOST_EventButton.h"
#include "GHOST_EventCursor.h" #include "GHOST_EventCursor.h"
#include "GHOST_EventKey.h" #include "GHOST_EventKey.h"
#include "GHOST_EventWheel.h" #include "GHOST_EventWheel.h"
#include "GHOST_EventNDOF.h"
#include "GHOST_TimerTask.h" #include "GHOST_TimerTask.h"
#include "GHOST_TimerManager.h" #include "GHOST_TimerManager.h"
#include "GHOST_WindowManager.h" #include "GHOST_WindowManager.h"
#include "GHOST_WindowWin32.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 // Key code values not found in winuser.h
#ifndef VK_MINUS #ifndef VK_MINUS
@@ -158,18 +127,35 @@
#define VK_MEDIA_PLAY_PAUSE 0xB3 #define VK_MEDIA_PLAY_PAUSE 0xB3
#endif // VK_MEDIA_PLAY_PAUSE #endif // VK_MEDIA_PLAY_PAUSE
/* static void initRawInput()
Initiates WM_INPUT messages from keyboard
That way GHOST can retrieve true keys
*/
GHOST_TInt32 GHOST_SystemWin32::initKeyboardRawInput(void)
{ {
RAWINPUTDEVICE device = {0}; #ifdef WITH_INPUT_NDOF
device.usUsagePage = 0x01; /* usUsagePage & usUsage for keyboard*/ #define DEVICE_COUNT 2
device.usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */ #else
#define DEVICE_COUNT 1
#endif
return RegisterRawInputDevices(&device, 1, sizeof(device)); RAWINPUTDEVICE devices[DEVICE_COUNT];
}; memset(devices, 0, DEVICE_COUNT * sizeof(RAWINPUTDEVICE));
// 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() GHOST_SystemWin32::GHOST_SystemWin32()
: m_hasPerformanceCounter(false), m_freq(0), m_start(0) : m_hasPerformanceCounter(false), m_freq(0), m_start(0)
@@ -186,6 +172,10 @@ GHOST_SystemWin32::GHOST_SystemWin32()
this->handleKeyboardChange(); this->handleKeyboardChange();
// Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32. // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32.
OleInitialize(0); OleInitialize(0);
#ifdef WITH_INPUT_NDOF
m_ndofManager = new GHOST_NDOFManagerWin32(*this);
#endif
} }
GHOST_SystemWin32::~GHOST_SystemWin32() GHOST_SystemWin32::~GHOST_SystemWin32()
@@ -244,6 +234,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow(
// Store the pointer to the window // Store the pointer to the window
// if (state != GHOST_kWindowStateFullScreen) { // if (state != GHOST_kWindowStateFullScreen) {
m_windowManager->addWindow(window); m_windowManager->addWindow(window);
m_windowManager->setActiveWindow(window);
// } // }
} }
else { else {
@@ -384,22 +375,15 @@ GHOST_TSuccess GHOST_SystemWin32::init()
GHOST_TSuccess success = GHOST_System::init(); GHOST_TSuccess success = GHOST_System::init();
/* Disable scaling on high DPI displays on Vista */ /* Disable scaling on high DPI displays on Vista */
HMODULE
user32 = ::LoadLibraryA("user32.dll"); user32 = ::LoadLibraryA("user32.dll");
typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)(); typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)();
LPFNSETPROCESSDPIAWARE SetProcessDPIAware = LPFNSETPROCESSDPIAWARE SetProcessDPIAware =
(LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware"); (LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware");
if (SetProcessDPIAware) if (SetProcessDPIAware)
SetProcessDPIAware(); SetProcessDPIAware();
#ifdef NEED_RAW_PROC
pRegisterRawInputDevices = (LPFNDLLRRID)GetProcAddress(user32, "RegisterRawInputDevices");
pGetRawInputData = (LPFNDLLGRID)GetProcAddress(user32, "GetRawInputData");
#else
FreeLibrary(user32); FreeLibrary(user32);
#endif initRawInput();
/* Initiates WM_INPUT messages from keyboard */
initKeyboardRawInput();
// Determine whether this system has a high frequency performance counter. */ // Determine whether this system has a high frequency performance counter. */
m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE; m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE;
@@ -440,41 +424,25 @@ GHOST_TSuccess GHOST_SystemWin32::init()
GHOST_TSuccess GHOST_SystemWin32::exit() GHOST_TSuccess GHOST_SystemWin32::exit()
{ {
#ifdef NEED_RAW_PROC
FreeLibrary(user32);
#endif
return GHOST_System::exit(); 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; GHOST_TKey key = GHOST_kKeyUnknown;
if(!keyDown) if(!keyDown)
return GHOST_kKeyUnknown; return GHOST_kKeyUnknown;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, 0, &size, sizeof(RAWINPUTHEADER));
if((data = (char*)malloc(size)) &&
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER)))
{
RAWINPUT ri;
memcpy(&ri,data,(size < sizeof(ri)) ? size : sizeof(ri));
if (ri.header.dwType == RIM_TYPEKEYBOARD)
{
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
GHOST_ModifierKeys modifiers; GHOST_ModifierKeys modifiers;
system->retrieveModifierKeys(modifiers); system->retrieveModifierKeys(modifiers);
*keyDown = !(ri.data.keyboard.Flags & RI_KEY_BREAK); *keyDown = !(raw.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))); 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 // extra handling of modifier keys: don't send repeats out from GHOST
if(key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt) if(key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt)
@@ -533,11 +501,7 @@ GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, WPARAM wParam, LPAR
} }
if(vk) *vk = ri.data.keyboard.VKey; if(vk) *vk = raw.data.keyboard.VKey;
};
};
free(data);
return key; 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; int keyDown=0;
char vk; char vk;
GHOST_SystemWin32 * system = (GHOST_SystemWin32 *)getSystem(); 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; GHOST_EventKey* event;
if (key != GHOST_kKeyUnknown) { if (key != GHOST_kKeyUnknown) {
char ascii = '\0'; char ascii = '\0';
@@ -776,7 +740,13 @@ GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, WPARAM
GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window) 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, GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType,
@@ -799,9 +769,95 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax)
minmax->ptMinTrackSize.y=240; 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) LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
GHOST_Event* event = 0; GHOST_Event* event = 0;
bool eventHandled = false;
LRESULT lResult = 0; LRESULT lResult = 0;
GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem()); GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized") 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 // Keyboard events, processed
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
case WM_INPUT: case WM_INPUT:
{
// check WM_INPUT from input sink when ghost window is not in the foreground // check WM_INPUT from input sink when ghost window is not in the foreground
if (wParam == RIM_INPUTSINK) { if (wParam == RIM_INPUTSINK) {
if (GetFocus() != hwnd) // WM_INPUT message not for this window if (GetFocus() != hwnd) // WM_INPUT message not for this window
return 0; return 0;
} //else wPAram == RIM_INPUT } //else wParam == RIM_INPUT
event = processKeyEvent(window, wParam, lParam);
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) { if (!event) {
GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
GHOST_PRINT(msg) GHOST_PRINT(msg)
GHOST_PRINT(" key ignored\n") GHOST_PRINT(" key ignored\n")
} }
break; break;
#ifdef WITH_INPUT_NDOF
case RIM_TYPEHID:
if (system->processNDOF(raw))
eventHandled = true;
break;
#endif
}
break;
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Keyboard events, ignored // Keyboard events, ignored
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@@ -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, * 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. * 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); event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window);
/* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
will not be dispatched to OUR active window if we minimize one of OUR windows. */ will not be dispatched to OUR active window if we minimize one of OUR windows. */
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
break; break;
}
case WM_PAINT: case WM_PAINT:
/* An application sends the WM_PAINT message when the system or another application /* 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 * 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. * In GHOST, we let DefWindowProc call the timer callback.
*/ */
break; 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 { else {
@@ -1165,10 +1224,12 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
if (event) { if (event) {
system->pushEvent(event); system->pushEvent(event);
eventHandled = true;
} }
else {
if (!eventHandled)
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
}
return lResult; return lResult;
} }
@@ -1237,8 +1298,32 @@ int GHOST_SystemWin32::toggleConsole(int action)
{ {
case 3: //hide if no console case 3: //hide if no console
{ {
CONSOLE_SCREEN_BUFFER_INFO csbi = {{0}}; DWORD sp = GetCurrentProcessId();
if(!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) || csbi.dwCursorPosition.X || csbi.dwCursorPosition.Y>1) 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; break;
} }
case 0: //hide case 0: //hide

View File

@@ -38,7 +38,10 @@
#error WIN32 only! #error WIN32 only!
#endif // WIN32 #endif // WIN32
#define _WIN32_WINNT 0x501 // require Windows XP or newer
#define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#include <ole2.h> // for drag-n-drop
#include "GHOST_System.h" #include "GHOST_System.h"
@@ -46,95 +49,6 @@
# define __int64 long long # define __int64 long long
#endif #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_EventButton;
class GHOST_EventCursor; class GHOST_EventCursor;
class GHOST_EventKey; class GHOST_EventKey;
@@ -314,14 +228,13 @@ protected:
/** /**
* Catches raw WIN32 key codes from WM_INPUT in the wndproc. * Catches raw WIN32 key codes from WM_INPUT in the wndproc.
* @param window-> The window for this handling * @param window The window for this handling
* @param wParam The wParam from the wndproc * @param raw RawInput structure with detailed info about the key event
* @param lParam The lParam from the wndproc
* @param keyDown Pointer flag that specify if a key is down * @param keyDown Pointer flag that specify if a key is down
* @param vk Pointer to virtual key * @param vk Pointer to virtual key
* @return The GHOST key (GHOST_kKeyUnknown if no match). * @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). * 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. * In most cases this is a straightforward conversion of key codes.
* For the modifier keys however, we want to distinguish left and right keys. * For the modifier keys however, we want to distinguish left and right keys.
* @param window The window receiving the event (the active window). * @param window The window receiving the event (the active window).
* @param wParam The wParam from the wndproc * @param raw RawInput structure with detailed info about the key event
* @param lParam The lParam from the wndproc
*/ */
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 * Process special keys (VK_OEM_*), to see if current key layout
@@ -383,12 +295,24 @@ protected:
* @return The event created. * @return The event created.
*/ */
static GHOST_Event* processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window); static GHOST_Event* processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window);
/** /**
* Handles minimum window size. * Handles minimum window size.
* @param minmax The MINMAXINFO structure. * @param minmax The MINMAXINFO structure.
*/ */
static void processMinMaxInfo(MINMAXINFO * minmax); 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). * Returns the local state of the modifier keys (from the message queue).
* @param keys The state of the keys. * @param keys The state of the keys.
@@ -412,11 +336,6 @@ protected:
*/ */
static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); 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 * Toggles console
* @action 0 - Hides * @action 0 - Hides
@@ -445,15 +364,6 @@ protected:
/** Console status */ /** Console status */
int m_consoleStatus; 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 inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const
@@ -487,4 +397,3 @@ inline void GHOST_SystemWin32::handleKeyboardChange(void)
} }
} }
#endif // _GHOST_SYSTEM_WIN32_H_ #endif // _GHOST_SYSTEM_WIN32_H_

View File

@@ -42,9 +42,10 @@
#include "GHOST_EventKey.h" #include "GHOST_EventKey.h"
#include "GHOST_EventButton.h" #include "GHOST_EventButton.h"
#include "GHOST_EventWheel.h" #include "GHOST_EventWheel.h"
#include "GHOST_EventNDOF.h"
#include "GHOST_NDOFManager.h"
#include "GHOST_DisplayManagerX11.h" #include "GHOST_DisplayManagerX11.h"
#ifdef WITH_INPUT_NDOF
#include "GHOST_NDOFManagerX11.h"
#endif
#include "GHOST_Debug.h" #include "GHOST_Debug.h"
@@ -79,19 +80,6 @@
static GHOST_TKey static GHOST_TKey
convertXKey(KeySym key); convertXKey(KeySym key);
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};
//these are for copy and select copy //these are for copy and select copy
static char *txt_cut_buffer= NULL; static char *txt_cut_buffer= NULL;
static char *txt_select_buffer= NULL; static char *txt_select_buffer= NULL;
@@ -181,6 +169,9 @@ init(
GHOST_TSuccess success = GHOST_System::init(); GHOST_TSuccess success = GHOST_System::init();
if (success) { if (success) {
#ifdef WITH_INPUT_NDOF
m_ndofManager = new GHOST_NDOFManagerX11(*this);
#endif
m_displayManager = new GHOST_DisplayManagerX11(this); m_displayManager = new GHOST_DisplayManagerX11(this);
if (m_displayManager) { if (m_displayManager) {
@@ -275,7 +266,7 @@ createWindow(
if (window->getValid()) { if (window->getValid()) {
// Store the pointer to the window // Store the pointer to the window
m_windowManager->addWindow(window); m_windowManager->addWindow(window);
m_windowManager->setActiveWindow(window);
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
} }
else { else {
@@ -386,8 +377,6 @@ lastEventTime(Time default_time) {
return data.timestamp; return data.timestamp;
} }
bool bool
GHOST_SystemX11:: GHOST_SystemX11::
processEvents( processEvents(
@@ -428,6 +417,13 @@ processEvents(
if (generateWindowExposeEvents()) { if (generateWindowExposeEvents()) {
anyProcessed = true; anyProcessed = true;
} }
#ifdef WITH_INPUT_NDOF
if (dynamic_cast<GHOST_NDOFManagerX11*>(m_ndofManager)->processEvents()) {
anyProcessed = true;
}
#endif
} while (waitForEvent && !anyProcessed); } while (waitForEvent && !anyProcessed);
return anyProcessed; return anyProcessed;
@@ -612,6 +608,9 @@ GHOST_SystemX11::processEvent(XEvent *xe)
{ {
XFocusChangeEvent &xfe = xe->xfocus; 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 // May have to look at the type of event and filter some
// out. // out.
@@ -641,32 +640,8 @@ GHOST_SystemX11::processEvent(XEvent *xe)
); );
} else } else
#endif #endif
if (sNdofInfo.currValues) {
static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0}; if (((Atom)xcme.data.l[0]) == m_wm_take_focus) {
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) {
XWindowAttributes attr; XWindowAttributes attr;
Window fwin; Window fwin;
int revert_to; int revert_to;
@@ -723,6 +698,14 @@ GHOST_SystemX11::processEvent(XEvent *xe)
xce.y_root 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; break;
} }
case MapNotify: case MapNotify:
@@ -834,18 +817,6 @@ GHOST_SystemX11::processEvent(XEvent *xe)
} }
} }
void *
GHOST_SystemX11::
prepareNdofInfo(volatile GHOST_TEventNDOFData *currentNdofValues)
{
const vector<GHOST_IWindow*>& v(m_windowManager->getWindows());
if (v.size() > 0)
sNdofInfo.window = static_cast<GHOST_WindowX11*>(v[0])->getXWindow();
sNdofInfo.display = m_display;
sNdofInfo.currValues = currentNdofValues;
return (void*)&sNdofInfo;
}
GHOST_TSuccess GHOST_TSuccess
GHOST_SystemX11:: GHOST_SystemX11::
getModifierKeys( getModifierKeys(

View File

@@ -203,11 +203,6 @@ public:
return m_display; return m_display;
} }
void *
prepareNdofInfo(
volatile GHOST_TEventNDOFData *current_values
);
/* Helped function for get data from the clipboard. */ /* Helped function for get data from the clipboard. */
void getClipboard_xcout(XEvent evt, Atom sel, Atom target, void getClipboard_xcout(XEvent evt, Atom sel, Atom target,
unsigned char **txt, unsigned long *len, unsigned char **txt, unsigned long *len,

View File

@@ -3,20 +3,16 @@
*/ */
#ifndef GHOST_TASKBARWIN32_H_ #ifndef GHOST_TASKBARWIN32_H_
#define GHOST_TASKBARWIN32_H_ #define GHOST_TASKBARWIN32_H_
#ifndef WIN32 #ifndef WIN32
#error WIN32 only! #error WIN32 only!
#endif // WIN32 #endif // WIN32
#define _WIN32_WINNT 0x501 // require Windows XP or newer
#define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#include <shlobj.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. // 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 // Note, ITaskbarList3 is supported only since Windows 7, though. Check for that is done in

View File

@@ -39,20 +39,12 @@
#endif // WIN32 #endif // WIN32
#include "GHOST_Window.h" #include "GHOST_Window.h"
/* MinGW needs it */
#ifdef FREE_WINDOWS
#ifdef WINVER
#undef WINVER
#endif
#define WINVER 0x0501
#endif
#include <windows.h>
#include "GHOST_TaskbarWin32.h" #include "GHOST_TaskbarWin32.h"
#define _WIN32_WINNT 0x501 // require Windows XP or newer
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wintab.h> #include <wintab.h>
#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR) #define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR)

View File

@@ -16,7 +16,7 @@
# #
# ##### END GPL LICENSE BLOCK ##### # ##### END GPL LICENSE BLOCK #####
# <pep8 compliant> # <pep8-80 compliant>
__all__ = ( __all__ = (
"paths", "paths",
@@ -26,12 +26,14 @@ __all__ = (
"disable", "disable",
"reset_all", "reset_all",
"module_bl_info", "module_bl_info",
) )
import bpy as _bpy import bpy as _bpy
error_duplicates = False error_duplicates = False
error_encoding = False
def paths(): def paths():
# RELEASE SCRIPTS: official scripts distributed in Blender releases # RELEASE SCRIPTS: official scripts distributed in Blender releases
@@ -50,14 +52,18 @@ def paths():
def modules(module_cache): def modules(module_cache):
global error_duplicates global error_duplicates
global error_encoding
import os import os
error_duplicates = False error_duplicates = False
error_encoding = False
path_list = paths() path_list = paths()
# fake module importing # fake module importing
def fake_module(mod_name, mod_path, speedy=True): def fake_module(mod_name, mod_path, speedy=True):
global error_encoding
if _bpy.app.debug: if _bpy.app.debug:
print("fake_module", mod_path, mod_name) print("fake_module", mod_path, mod_name)
import ast import ast
@@ -68,12 +74,28 @@ def modules(module_cache):
line_iter = iter(file_mod) line_iter = iter(file_mod)
l = "" l = ""
while not l.startswith("bl_info"): while not l.startswith("bl_info"):
try:
l = line_iter.readline() l = line_iter.readline()
except UnicodeDecodeError as e:
if not error_encoding:
error_encoding = True
print("Error reading file as UTF-8:", mod_path, e)
file_mod.close()
return None
if len(l) == 0: if len(l) == 0:
break break
while l.rstrip(): while l.rstrip():
lines.append(l) lines.append(l)
try:
l = line_iter.readline() l = line_iter.readline()
except UnicodeDecodeError as e:
if not error_encoding:
error_encoding = True
print("Error reading file as UTF-8:", mod_path, e)
file_mod.close()
return None
data = "".join(lines) data = "".join(lines)
else: else:
@@ -128,7 +150,12 @@ def modules(module_cache):
error_duplicates = True error_duplicates = True
elif mod.__time__ != os.path.getmtime(mod_path): elif mod.__time__ != os.path.getmtime(mod_path):
print("reloading addon:", mod_name, mod.__time__, os.path.getmtime(mod_path), mod_path) print("reloading addon:",
mod_name,
mod.__time__,
os.path.getmtime(mod_path),
mod_path,
)
del module_cache[mod_name] del module_cache[mod_name]
mod = None mod = None
@@ -143,7 +170,9 @@ def modules(module_cache):
del modules_stale del modules_stale
mod_list = list(module_cache.values()) mod_list = list(module_cache.values())
mod_list.sort(key=lambda mod: (mod.bl_info['category'], mod.bl_info['name'])) mod_list.sort(key=lambda mod: (mod.bl_info['category'],
mod.bl_info['name'],
))
return mod_list return mod_list
@@ -163,8 +192,9 @@ def check(module_name):
loaded_state = mod and getattr(mod, "__addon_enabled__", Ellipsis) loaded_state = mod and getattr(mod, "__addon_enabled__", Ellipsis)
if loaded_state is Ellipsis: if loaded_state is Ellipsis:
print("Warning: addon-module %r found module but without" print("Warning: addon-module %r found module "
" __addon_enabled__ field, possible name collision from file: %r" % "but without __addon_enabled__ field, "
"possible name collision from file: %r" %
(module_name, getattr(mod, "__file__", "<unknown>"))) (module_name, getattr(mod, "__file__", "<unknown>")))
loaded_state = False loaded_state = False
@@ -207,7 +237,8 @@ def enable(module_name, default_set=True):
return None return None
mod.__addon_enabled__ = False mod.__addon_enabled__ = False
# Split registering up into 3 steps so we can undo if it fails par way through # Split registering up into 3 steps so we can undo
# if it fails par way through.
# 1) try import # 1) try import
try: try:
mod = __import__(module_name) mod = __import__(module_name)
@@ -254,8 +285,9 @@ def disable(module_name, default_set=True):
import sys import sys
mod = sys.modules.get(module_name) mod = sys.modules.get(module_name)
# possible this addon is from a previous session and didnt load a module this time. # possible this addon is from a previous session and didnt load a
# so even if the module is not found, still disable the addon in the user prefs. # module this time. So even if the module is not found, still disable
# the addon in the user prefs.
if mod: if mod:
mod.__addon_enabled__ = False mod.__addon_enabled__ = False
@@ -310,7 +342,22 @@ def reset_all(reload_scripts=False):
disable(mod_name) disable(mod_name)
def module_bl_info(mod, info_basis={"name": "", "author": "", "version": (), "blender": (), "api": 0, "location": "", "description": "", "wiki_url": "", "tracker_url": "", "support": 'COMMUNITY', "category": "", "warning": "", "show_expanded": False}): def module_bl_info(mod, info_basis={"name": "",
"author": "",
"version": (),
"blender": (),
"api": 0,
"location": "",
"description": "",
"wiki_url": "",
"tracker_url": "",
"support": 'COMMUNITY',
"category": "",
"warning": "",
"show_expanded": False,
}
):
addon_info = getattr(mod, "bl_info", {}) addon_info = getattr(mod, "bl_info", {})
# avoid re-initializing # avoid re-initializing

View File

@@ -16,7 +16,7 @@
# #
# ##### END GPL LICENSE BLOCK ##### # ##### END GPL LICENSE BLOCK #####
# <pep8 compliant> # <pep8-80 compliant>
""" """
Give access to blender data and utility functions. Give access to blender data and utility functions.
@@ -31,7 +31,7 @@ __all__ = (
"props", "props",
"types", "types",
"utils", "utils",
) )
# internal blender C module # internal blender C module
@@ -43,12 +43,14 @@ from . import utils, path, ops
# fake operator module # fake operator module
ops = ops.ops_fake_module ops = ops.ops_fake_module
def _main(): def _main():
import sys as _sys import sys as _sys
# Possibly temp. addons path # Possibly temp. addons path
from os.path import join, dirname, normpath from os.path import join, dirname, normpath
_sys.path.append(normpath(join(dirname(__file__), "..", "..", "addons", "modules"))) _sys.path.append(normpath(join(dirname(__file__),
"..", "..", "addons", "modules")))
# if "-d" in sys.argv: # Enable this to measure startup speed # if "-d" in sys.argv: # Enable this to measure startup speed
if 0: if 0:

View File

@@ -16,26 +16,44 @@
# #
# ##### END GPL LICENSE BLOCK ##### # ##### END GPL LICENSE BLOCK #####
# <pep8 compliant> # <pep8-80 compliant>
""" """
This module has a similar scope to os.path, containing utility This module has a similar scope to os.path, containing utility
functions for dealing with paths in Blender. functions for dealing with paths in Blender.
""" """
__all__ = (
"abspath",
"basename",
"clean_name",
"display_name",
"display_name_from_filepath",
"ensure_ext",
"is_subdir",
"module_names",
"relpath",
"resolve_ncase",
)
import bpy as _bpy import bpy as _bpy
import os as _os import os as _os
def abspath(path, start=None): def abspath(path, start=None):
""" """
Returns the absolute path relative to the current blend file using the "//" prefix. Returns the absolute path relative to the current blend file
using the "//" prefix.
:arg start: Relative to this path, when not set the current filename is used. :arg start: Relative to this path,
when not set the current filename is used.
:type start: string :type start: string
""" """
if path.startswith("//"): if path.startswith("//"):
return _os.path.join(_os.path.dirname(_bpy.data.filepath if start is None else start), path[2:]) return _os.path.join(_os.path.dirname(_bpy.data.filepath)
if start is None else start,
path[2:],
)
return path return path
@@ -44,7 +62,8 @@ def relpath(path, start=None):
""" """
Returns the path relative to the current blend file using the "//" prefix. Returns the path relative to the current blend file using the "//" prefix.
:arg start: Relative to this path, when not set the current filename is used. :arg start: Relative to this path,
when not set the current filename is used.
:type start: string :type start: string
""" """
if not path.startswith("//"): if not path.startswith("//"):
@@ -68,27 +87,28 @@ def is_subdir(path, directory):
def clean_name(name, replace="_"): def clean_name(name, replace="_"):
""" """
Returns a name with characters replaced that may cause problems under various circumstances, such as writing to a file. Returns a name with characters replaced that
may cause problems under various circumstances,
such as writing to a file.
All characters besides A-Z/a-z, 0-9 are replaced with "_" All characters besides A-Z/a-z, 0-9 are replaced with "_"
or the replace argument if defined. or the replace argument if defined.
""" """
unclean_chars = \ bad_chars = ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\ "\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d"
\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\ "\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c"
\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\ "\x2e\x2f\x3a\x3b\x3c\x3d\x3e\x3f\x40\x5b\x5c\x5d\x5e\x60\x7b"
\x2e\x2f\x3a\x3b\x3c\x3d\x3e\x3f\x40\x5b\x5c\x5d\x5e\x60\x7b\ "\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a"
\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\ "\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99"
\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\ "\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8"
\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\ "\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\ "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6"
\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\ "\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5"
\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\ "\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4"
\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\ "\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3"
\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\ "\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe")
\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe"
for ch in unclean_chars: for ch in bad_chars:
name = name.replace(ch, replace) name = name.replace(ch, replace)
return name return name
@@ -96,8 +116,9 @@ def clean_name(name, replace="_"):
def display_name(name): def display_name(name):
""" """
Creates a display string from name to be used menus and the user interface. Creates a display string from name to be used menus and the user interface.
Capitalize the first letter in all lowercase names, mixed case names are kept as is. Capitalize the first letter in all lowercase names,
Intended for use with filenames and module names. mixed case names are kept as is. Intended for use with
filenames and module names.
""" """
name_base = _os.path.splitext(name)[0] name_base = _os.path.splitext(name)[0]
@@ -115,9 +136,11 @@ def display_name(name):
def display_name_from_filepath(name): def display_name_from_filepath(name):
""" """
Returns the path stripped of directort and extension, ensured to be utf8 compatible. Returns the path stripped of directory and extension,
ensured to be utf8 compatible.
""" """
return _os.path.splitext(basename(name))[0].encode("utf8", "replace").decode("utf8") name = _os.path.splitext(basename(name))[0]
return name.encode("utf8", "replace").decode("utf8")
def resolve_ncase(path): def resolve_ncase(path):
@@ -132,7 +155,8 @@ def resolve_ncase(path):
if not path or os.path.exists(path): if not path or os.path.exists(path):
return path, True return path, True
filename = os.path.basename(path) # filename may be a directory or a file # filename may be a directory or a file
filename = os.path.basename(path)
dirpath = os.path.dirname(path) dirpath = os.path.dirname(path)
suffix = path[:0] # "" but ensure byte/str match suffix = path[:0] # "" but ensure byte/str match
@@ -180,7 +204,7 @@ def resolve_ncase(path):
def ensure_ext(filepath, ext, case_sensitive=False): def ensure_ext(filepath, ext, case_sensitive=False):
""" """
Return the path with the extension added its its not alredy set. Return the path with the extension added if it is not already set.
:arg ext: The extension to check for. :arg ext: The extension to check for.
:type ext: string :type ext: string
@@ -190,7 +214,9 @@ def ensure_ext(filepath, ext, case_sensitive=False):
import os import os
fn_base, fn_ext = os.path.splitext(filepath) fn_base, fn_ext = os.path.splitext(filepath)
if fn_base and fn_ext: if fn_base and fn_ext:
if (case_sensitive and ext == fn_ext) or (ext.lower() == fn_ext.lower()): if ((case_sensitive and ext == fn_ext) or
(ext.lower() == fn_ext.lower())):
return filepath return filepath
else: else:
return fn_base + ext return fn_base + ext
@@ -228,7 +254,9 @@ def module_names(path, recursive=False):
modules.append((filename, fullpath)) modules.append((filename, fullpath))
if recursive: if recursive:
for mod_name, mod_path in module_names(directory, True): for mod_name, mod_path in module_names(directory, True):
modules.append(("%s.%s" % (filename, mod_name), mod_path)) modules.append(("%s.%s" % (filename, mod_name),
mod_path,
))
return modules return modules

View File

@@ -16,13 +16,33 @@
# #
# ##### END GPL LICENSE BLOCK ##### # ##### END GPL LICENSE BLOCK #####
# <pep8 compliant> # <pep8-80 compliant>
""" """
This module contains utility functions specific to blender but This module contains utility functions specific to blender but
not assosiated with blenders internal data. not assosiated with blenders internal data.
""" """
__all__ = (
"blend_paths",
"keyconfig_set",
"load_scripts",
"modules_from_path",
"preset_find",
"preset_paths",
"refresh_script_paths",
"register_class",
"register_module",
"resource_path",
"script_paths",
"smpte_from_frame",
"smpte_from_seconds",
"unregister_class",
"unregister_module",
"user_resource",
"user_script_path",
)
from _bpy import register_class, unregister_class, blend_paths, resource_path from _bpy import register_class, unregister_class, blend_paths, resource_path
from _bpy import script_paths as _bpy_script_paths from _bpy import script_paths as _bpy_script_paths
from _bpy import user_resource as _user_resource from _bpy import user_resource as _user_resource
@@ -42,7 +62,8 @@ def _test_import(module_name, loaded_modules):
if module_name in loaded_modules: if module_name in loaded_modules:
return None return None
if "." in module_name: if "." in module_name:
print("Ignoring '%s', can't import files containing multiple periods." % module_name) print("Ignoring '%s', can't import files containing "
"multiple periods." % module_name)
return None return None
if use_time: if use_time:
@@ -74,7 +95,8 @@ def modules_from_path(path, loaded_modules):
:arg path: this path is scanned for scripts and packages. :arg path: this path is scanned for scripts and packages.
:type path: string :type path: string
:arg loaded_modules: already loaded module names, files matching these names will be ignored. :arg loaded_modules: already loaded module names, files matching these
names will be ignored.
:type loaded_modules: set :type loaded_modules: set
:return: all loaded modules. :return: all loaded modules.
:rtype: list :rtype: list
@@ -97,13 +119,17 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
""" """
Load scripts and run each modules register function. Load scripts and run each modules register function.
:arg reload_scripts: Causes all scripts to have their unregister method called before loading. :arg reload_scripts: Causes all scripts to have their unregister method
called before loading.
:type reload_scripts: bool :type reload_scripts: bool
:arg refresh_scripts: only load scripts which are not already loaded as modules. :arg refresh_scripts: only load scripts which are not already loaded
as modules.
:type refresh_scripts: bool :type refresh_scripts: bool
""" """
use_time = _bpy.app.debug use_time = _bpy.app.debug
prefs = _bpy.context.user_preferences
if use_time: if use_time:
import time import time
t_main = time.time() t_main = time.time()
@@ -116,10 +142,11 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
if reload_scripts: if reload_scripts:
_bpy_types.TypeMap.clear() _bpy_types.TypeMap.clear()
# just unload, dont change user defaults, this means we can sync to reload. # just unload, dont change user defaults, this means we can sync
# note that they will only actually reload of the modification time changes. # to reload. note that they will only actually reload of the
# this `wont` work for packages so... its not perfect. # modification time changes. This `wont` work for packages so...
for module_name in [ext.module for ext in _bpy.context.user_preferences.addons]: # its not perfect.
for module_name in [ext.module for ext in prefs.addons]:
_addon_utils.disable(module_name, default_set=False) _addon_utils.disable(module_name, default_set=False)
def register_module_call(mod): def register_module_call(mod):
@@ -131,7 +158,9 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
import traceback import traceback
traceback.print_exc() traceback.print_exc()
else: else:
print("\nWarning! '%s' has no register function, this is now a requirement for registerable scripts." % mod.__file__) print("\nWarning! '%s' has no register function, "
"this is now a requirement for registerable scripts." %
mod.__file__)
def unregister_module_call(mod): def unregister_module_call(mod):
unregister = getattr(mod, "unregister", None) unregister = getattr(mod, "unregister", None)
@@ -172,7 +201,8 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
if reload_scripts: if reload_scripts:
# module names -> modules # module names -> modules
_global_loaded_modules[:] = [_sys.modules[mod_name] for mod_name in _global_loaded_modules] _global_loaded_modules[:] = [_sys.modules[mod_name]
for mod_name in _global_loaded_modules]
# loop over and unload all scripts # loop over and unload all scripts
_global_loaded_modules.reverse() _global_loaded_modules.reverse()
@@ -201,7 +231,8 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
_addon_utils.reset_all(reload_scripts) _addon_utils.reset_all(reload_scripts)
# run the active integration preset # run the active integration preset
filepath = preset_find(_bpy.context.user_preferences.inputs.active_keyconfig, "keyconfig") filepath = preset_find(prefs.inputs.active_keyconfig, "keyconfig")
if filepath: if filepath:
keyconfig_set(filepath) keyconfig_set(filepath)
@@ -214,12 +245,16 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
# base scripts # base scripts
_scripts = _os.path.join(_os.path.dirname(__file__), _os.path.pardir, _os.path.pardir) _scripts = _os.path.join(_os.path.dirname(__file__),
_os.path.pardir,
_os.path.pardir,
)
_scripts = (_os.path.normpath(_scripts), ) _scripts = (_os.path.normpath(_scripts), )
def user_script_path(): def user_script_path():
path = _bpy.context.user_preferences.filepaths.script_directory prefs = _bpy.context.user_preferences
path = prefs.filepaths.script_directory
if path: if path:
path = _os.path.normpath(path) path = _os.path.normpath(path)
@@ -236,22 +271,25 @@ def script_paths(subdir=None, user_pref=True, all=False):
:type subdir: string :type subdir: string
:arg user_pref: Include the user preference script path. :arg user_pref: Include the user preference script path.
:type user_pref: bool :type user_pref: bool
:arg all: Include local, user and system paths rather just the paths blender uses. :arg all: Include local, user and system paths rather just the paths
blender uses.
:type all: bool :type all: bool
:return: script paths. :return: script paths.
:rtype: list :rtype: list
""" """
scripts = list(_scripts) scripts = list(_scripts)
prefs = _bpy.context.user_preferences
# add user scripts dir # add user scripts dir
if user_pref: if user_pref:
user_script_path = _bpy.context.user_preferences.filepaths.script_directory user_script_path = prefs.filepaths.script_directory
else: else:
user_script_path = None user_script_path = None
if all: if all:
# all possible paths # all possible paths
base_paths = tuple(_os.path.join(resource_path(res), "scripts") for res in ('LOCAL', 'USER', 'SYSTEM')) base_paths = tuple(_os.path.join(resource_path(res), "scripts")
for res in ('LOCAL', 'USER', 'SYSTEM'))
else: else:
# only paths blender uses # only paths blender uses
base_paths = _bpy_script_paths() base_paths = _bpy_script_paths()
@@ -426,7 +464,8 @@ def user_resource(type, path="", create=False):
:type type: string :type type: string
:arg subdir: Optional subdirectory. :arg subdir: Optional subdirectory.
:type subdir: string :type subdir: string
:arg create: Treat the path as a directory and create it if its not existing. :arg create: Treat the path as a directory and create
it if its not existing.
:type create: boolean :type create: boolean
:return: a path. :return: a path.
:rtype: string :rtype: string
@@ -477,7 +516,8 @@ def register_module(module, verbose=False):
try: try:
register_class(cls) register_class(cls)
except: except:
print("bpy.utils.register_module(): failed to registering class %r" % cls) print("bpy.utils.register_module(): "
"failed to registering class %r" % cls)
import traceback import traceback
traceback.print_exc() traceback.print_exc()
if verbose: if verbose:
@@ -495,7 +535,8 @@ def unregister_module(module, verbose=False):
try: try:
unregister_class(cls) unregister_class(cls)
except: except:
print("bpy.utils.unregister_module(): failed to unregistering class %r" % cls) print("bpy.utils.unregister_module(): "
"failed to unregistering class %r" % cls)
import traceback import traceback
traceback.print_exc() traceback.print_exc()
if verbose: if verbose:

View File

@@ -16,7 +16,7 @@
# #
# ##### END GPL LICENSE BLOCK ##### # ##### END GPL LICENSE BLOCK #####
# <pep8 compliant> # <pep8-80 compliant>
""" """
Utility modules assosiated with the bpy module. Utility modules assosiated with the bpy module.
@@ -28,4 +28,4 @@ __all__ = (
"image_utils", "image_utils",
"mesh_utils", "mesh_utils",
"view3d_utils", "view3d_utils",
) )

View File

@@ -16,11 +16,11 @@
# #
# ##### END GPL LICENSE BLOCK ##### # ##### END GPL LICENSE BLOCK #####
# <pep8 compliant> # <pep8-80 compliant>
__all__ = ( __all__ = (
"load_image", "load_image",
) )
# limited replacement for BPyImage.comprehensiveImageLoad # limited replacement for BPyImage.comprehensiveImageLoad
@@ -33,8 +33,8 @@ def load_image(imagepath,
verbose=False, verbose=False,
): ):
""" """
Return an image from the file path with options to search multiple paths and Return an image from the file path with options to search multiple paths
return a placeholder if its not found. and return a placeholder if its not found.
:arg filepath: The image filename :arg filepath: The image filename
If a path precedes it, this will be searched as well. If a path precedes it, this will be searched as well.
@@ -51,9 +51,10 @@ def load_image(imagepath,
:type recursive: bool :type recursive: bool
:arg ncase_cmp: on non windows systems, find the correct case for the file. :arg ncase_cmp: on non windows systems, find the correct case for the file.
:type ncase_cmp: bool :type ncase_cmp: bool
:arg convert_callback: a function that takes an existing path and returns a new one. :arg convert_callback: a function that takes an existing path and returns
Use this when loading image formats blender may not support, the CONVERT_CALLBACK a new one. Use this when loading image formats blender may not support,
can take the path for a GIF (for example), convert it to a PNG and return the PNG's path. the CONVERT_CALLBACK can take the path for a GIF (for example),
convert it to a PNG and return the PNG's path.
For formats blender can read, simply return the path that is given. For formats blender can read, simply return the path that is given.
:type convert_callback: function :type convert_callback: function
:return: an image or None :return: an image or None
@@ -92,7 +93,9 @@ def load_image(imagepath,
for filepath_test in variants: for filepath_test in variants:
if ncase_cmp: if ncase_cmp:
ncase_variants = filepath_test, bpy.path.resolve_ncase(filepath_test) ncase_variants = (filepath_test,
bpy.path.resolve_ncase(filepath_test),
)
else: else:
ncase_variants = (filepath_test, ) ncase_variants = (filepath_test, )

View File

@@ -16,7 +16,7 @@
# #
# ##### END GPL LICENSE BLOCK ##### # ##### END GPL LICENSE BLOCK #####
# <pep8 compliant> # <pep8-80 compliant>
__all__ = ( __all__ = (
"ExportHelper", "ExportHelper",
@@ -31,15 +31,34 @@ __all__ = (
"path_reference_copy", "path_reference_copy",
"path_reference_mode", "path_reference_mode",
"unique_name" "unique_name"
) )
import bpy import bpy
from bpy.props import StringProperty, BoolProperty, EnumProperty from bpy.props import StringProperty, BoolProperty, EnumProperty
def _check_axis_conversion(op):
if hasattr(op, "axis_forward") and hasattr(op, "axis_up"):
return axis_conversion_ensure(op,
"axis_forward",
"axis_up",
)
return False
class ExportHelper: class ExportHelper:
filepath = StringProperty(name="File Path", description="Filepath used for exporting the file", maxlen=1024, default="", subtype='FILE_PATH') filepath = StringProperty(
check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'}) name="File Path",
description="Filepath used for exporting the file",
maxlen=1024,
subtype='FILE_PATH',
)
check_existing = BoolProperty(
name="Check Existing",
description="Check and warn on overwriting existing files",
default=True,
options={'HIDDEN'},
)
# subclasses can override with decorator # subclasses can override with decorator
# True == use ext, False == no ext, None == do nothing. # True == use ext, False == no ext, None == do nothing.
@@ -60,27 +79,39 @@ class ExportHelper:
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
def check(self, context): def check(self, context):
change_ext = False
change_axis = _check_axis_conversion(self)
check_extension = self.check_extension check_extension = self.check_extension
if check_extension is None: if check_extension is not None:
return False filepath = bpy.path.ensure_ext(self.filepath,
self.filename_ext
filepath = bpy.path.ensure_ext(self.filepath, self.filename_ext if check_extension else "") if check_extension
else "")
if filepath != self.filepath: if filepath != self.filepath:
self.filepath = filepath self.filepath = filepath
return True change_ext = True
return False return (change_ext or change_axis)
class ImportHelper: class ImportHelper:
filepath = StringProperty(name="File Path", description="Filepath used for importing the file", maxlen=1024, default="", subtype='FILE_PATH') filepath = StringProperty(
name="File Path",
description="Filepath used for importing the file",
maxlen=1024,
subtype='FILE_PATH',
)
def invoke(self, context, event): def invoke(self, context, event):
context.window_manager.fileselect_add(self) context.window_manager.fileselect_add(self)
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
def check(self, context):
return _check_axis_conversion(self)
# Axis conversion function, not pretty LUT # Axis conversion function, not pretty LUT
# use lookup tabes to convert between any axis # use lookup tabes to convert between any axis
@@ -116,29 +147,75 @@ _axis_convert_matrix = (
# where all 4 values are or'd into a single value... # where all 4 values are or'd into a single value...
# (i1<<0 | i1<<3 | i1<<6 | i1<<9) # (i1<<0 | i1<<3 | i1<<6 | i1<<9)
_axis_convert_lut = ( _axis_convert_lut = (
{0x8C8, 0x4D0, 0x2E0, 0xAE8, 0x701, 0x511, 0x119, 0xB29, 0x682, 0x88A, 0x09A, 0x2A2, 0x80B, 0x413, 0x223, 0xA2B, 0x644, 0x454, 0x05C, 0xA6C, 0x745, 0x94D, 0x15D, 0x365}, {0x8C8, 0x4D0, 0x2E0, 0xAE8, 0x701, 0x511, 0x119, 0xB29, 0x682, 0x88A,
{0xAC8, 0x8D0, 0x4E0, 0x2E8, 0x741, 0x951, 0x159, 0x369, 0x702, 0xB0A, 0x11A, 0x522, 0xA0B, 0x813, 0x423, 0x22B, 0x684, 0x894, 0x09C, 0x2AC, 0x645, 0xA4D, 0x05D, 0x465}, 0x09A, 0x2A2, 0x80B, 0x413, 0x223, 0xA2B, 0x644, 0x454, 0x05C, 0xA6C,
{0x4C8, 0x2D0, 0xAE0, 0x8E8, 0x681, 0x291, 0x099, 0x8A9, 0x642, 0x44A, 0x05A, 0xA62, 0x40B, 0x213, 0xA23, 0x82B, 0x744, 0x354, 0x15C, 0x96C, 0x705, 0x50D, 0x11D, 0xB25}, 0x745, 0x94D, 0x15D, 0x365},
{0x2C8, 0xAD0, 0x8E0, 0x4E8, 0x641, 0xA51, 0x059, 0x469, 0x742, 0x34A, 0x15A, 0x962, 0x20B, 0xA13, 0x823, 0x42B, 0x704, 0xB14, 0x11C, 0x52C, 0x685, 0x28D, 0x09D, 0x8A5}, {0xAC8, 0x8D0, 0x4E0, 0x2E8, 0x741, 0x951, 0x159, 0x369, 0x702, 0xB0A,
{0x708, 0xB10, 0x120, 0x528, 0x8C1, 0xAD1, 0x2D9, 0x4E9, 0x942, 0x74A, 0x35A, 0x162, 0x64B, 0xA53, 0x063, 0x46B, 0x804, 0xA14, 0x21C, 0x42C, 0x885, 0x68D, 0x29D, 0x0A5}, 0x11A, 0x522, 0xA0B, 0x813, 0x423, 0x22B, 0x684, 0x894, 0x09C, 0x2AC,
{0xB08, 0x110, 0x520, 0x728, 0x941, 0x151, 0x359, 0x769, 0x802, 0xA0A, 0x21A, 0x422, 0xA4B, 0x053, 0x463, 0x66B, 0x884, 0x094, 0x29C, 0x6AC, 0x8C5, 0xACD, 0x2DD, 0x4E5}, 0x645, 0xA4D, 0x05D, 0x465},
{0x508, 0x710, 0xB20, 0x128, 0x881, 0x691, 0x299, 0x0A9, 0x8C2, 0x4CA, 0x2DA, 0xAE2, 0x44B, 0x653, 0xA63, 0x06B, 0x944, 0x754, 0x35C, 0x16C, 0x805, 0x40D, 0x21D, 0xA25}, {0x4C8, 0x2D0, 0xAE0, 0x8E8, 0x681, 0x291, 0x099, 0x8A9, 0x642, 0x44A,
{0x108, 0x510, 0x720, 0xB28, 0x801, 0x411, 0x219, 0xA29, 0x882, 0x08A, 0x29A, 0x6A2, 0x04B, 0x453, 0x663, 0xA6B, 0x8C4, 0x4D4, 0x2DC, 0xAEC, 0x945, 0x14D, 0x35D, 0x765}, 0x05A, 0xA62, 0x40B, 0x213, 0xA23, 0x82B, 0x744, 0x354, 0x15C, 0x96C,
{0x748, 0x350, 0x160, 0x968, 0xAC1, 0x2D1, 0x4D9, 0x8E9, 0xA42, 0x64A, 0x45A, 0x062, 0x68B, 0x293, 0x0A3, 0x8AB, 0xA04, 0x214, 0x41C, 0x82C, 0xB05, 0x70D, 0x51D, 0x125}, 0x705, 0x50D, 0x11D, 0xB25},
{0x948, 0x750, 0x360, 0x168, 0xB01, 0x711, 0x519, 0x129, 0xAC2, 0x8CA, 0x4DA, 0x2E2, 0x88B, 0x693, 0x2A3, 0x0AB, 0xA44, 0x654, 0x45C, 0x06C, 0xA05, 0x80D, 0x41D, 0x225}, {0x2C8, 0xAD0, 0x8E0, 0x4E8, 0x641, 0xA51, 0x059, 0x469, 0x742, 0x34A,
{0x348, 0x150, 0x960, 0x768, 0xA41, 0x051, 0x459, 0x669, 0xA02, 0x20A, 0x41A, 0x822, 0x28B, 0x093, 0x8A3, 0x6AB, 0xB04, 0x114, 0x51C, 0x72C, 0xAC5, 0x2CD, 0x4DD, 0x8E5}, 0x15A, 0x962, 0x20B, 0xA13, 0x823, 0x42B, 0x704, 0xB14, 0x11C, 0x52C,
{0x148, 0x950, 0x760, 0x368, 0xA01, 0x811, 0x419, 0x229, 0xB02, 0x10A, 0x51A, 0x722, 0x08B, 0x893, 0x6A3, 0x2AB, 0xAC4, 0x8D4, 0x4DC, 0x2EC, 0xA45, 0x04D, 0x45D, 0x665}, 0x685, 0x28D, 0x09D, 0x8A5},
{0x688, 0x890, 0x0A0, 0x2A8, 0x4C1, 0x8D1, 0xAD9, 0x2E9, 0x502, 0x70A, 0xB1A, 0x122, 0x74B, 0x953, 0x163, 0x36B, 0x404, 0x814, 0xA1C, 0x22C, 0x445, 0x64D, 0xA5D, 0x065}, {0x708, 0xB10, 0x120, 0x528, 0x8C1, 0xAD1, 0x2D9, 0x4E9, 0x942, 0x74A,
{0x888, 0x090, 0x2A0, 0x6A8, 0x501, 0x111, 0xB19, 0x729, 0x402, 0x80A, 0xA1A, 0x222, 0x94B, 0x153, 0x363, 0x76B, 0x444, 0x054, 0xA5C, 0x66C, 0x4C5, 0x8CD, 0xADD, 0x2E5}, 0x35A, 0x162, 0x64B, 0xA53, 0x063, 0x46B, 0x804, 0xA14, 0x21C, 0x42C,
{0x288, 0x690, 0x8A0, 0x0A8, 0x441, 0x651, 0xA59, 0x069, 0x4C2, 0x2CA, 0xADA, 0x8E2, 0x34B, 0x753, 0x963, 0x16B, 0x504, 0x714, 0xB1C, 0x12C, 0x405, 0x20D, 0xA1D, 0x825}, 0x885, 0x68D, 0x29D, 0x0A5},
{0x088, 0x290, 0x6A0, 0x8A8, 0x401, 0x211, 0xA19, 0x829, 0x442, 0x04A, 0xA5A, 0x662, 0x14B, 0x353, 0x763, 0x96B, 0x4C4, 0x2D4, 0xADC, 0x8EC, 0x505, 0x10D, 0xB1D, 0x725}, {0xB08, 0x110, 0x520, 0x728, 0x941, 0x151, 0x359, 0x769, 0x802, 0xA0A,
{0x648, 0x450, 0x060, 0xA68, 0x2C1, 0x4D1, 0x8D9, 0xAE9, 0x282, 0x68A, 0x89A, 0x0A2, 0x70B, 0x513, 0x123, 0xB2B, 0x204, 0x414, 0x81C, 0xA2C, 0x345, 0x74D, 0x95D, 0x165}, 0x21A, 0x422, 0xA4B, 0x053, 0x463, 0x66B, 0x884, 0x094, 0x29C, 0x6AC,
{0xA48, 0x650, 0x460, 0x068, 0x341, 0x751, 0x959, 0x169, 0x2C2, 0xACA, 0x8DA, 0x4E2, 0xB0B, 0x713, 0x523, 0x12B, 0x284, 0x694, 0x89C, 0x0AC, 0x205, 0xA0D, 0x81D, 0x425}, 0x8C5, 0xACD, 0x2DD, 0x4E5},
{0x448, 0x050, 0xA60, 0x668, 0x281, 0x091, 0x899, 0x6A9, 0x202, 0x40A, 0x81A, 0xA22, 0x50B, 0x113, 0xB23, 0x72B, 0x344, 0x154, 0x95C, 0x76C, 0x2C5, 0x4CD, 0x8DD, 0xAE5}, {0x508, 0x710, 0xB20, 0x128, 0x881, 0x691, 0x299, 0x0A9, 0x8C2, 0x4CA,
{0x048, 0xA50, 0x660, 0x468, 0x201, 0xA11, 0x819, 0x429, 0x342, 0x14A, 0x95A, 0x762, 0x10B, 0xB13, 0x723, 0x52B, 0x2C4, 0xAD4, 0x8DC, 0x4EC, 0x285, 0x08D, 0x89D, 0x6A5}, 0x2DA, 0xAE2, 0x44B, 0x653, 0xA63, 0x06B, 0x944, 0x754, 0x35C, 0x16C,
{0x808, 0xA10, 0x220, 0x428, 0x101, 0xB11, 0x719, 0x529, 0x142, 0x94A, 0x75A, 0x362, 0x8CB, 0xAD3, 0x2E3, 0x4EB, 0x044, 0xA54, 0x65C, 0x46C, 0x085, 0x88D, 0x69D, 0x2A5}, 0x805, 0x40D, 0x21D, 0xA25},
{0xA08, 0x210, 0x420, 0x828, 0x141, 0x351, 0x759, 0x969, 0x042, 0xA4A, 0x65A, 0x462, 0xACB, 0x2D3, 0x4E3, 0x8EB, 0x084, 0x294, 0x69C, 0x8AC, 0x105, 0xB0D, 0x71D, 0x525}, {0x108, 0x510, 0x720, 0xB28, 0x801, 0x411, 0x219, 0xA29, 0x882, 0x08A,
{0x408, 0x810, 0xA20, 0x228, 0x081, 0x891, 0x699, 0x2A9, 0x102, 0x50A, 0x71A, 0xB22, 0x4CB, 0x8D3, 0xAE3, 0x2EB, 0x144, 0x954, 0x75C, 0x36C, 0x045, 0x44D, 0x65D, 0xA65}, 0x29A, 0x6A2, 0x04B, 0x453, 0x663, 0xA6B, 0x8C4, 0x4D4, 0x2DC, 0xAEC,
0x945, 0x14D, 0x35D, 0x765},
{0x748, 0x350, 0x160, 0x968, 0xAC1, 0x2D1, 0x4D9, 0x8E9, 0xA42, 0x64A,
0x45A, 0x062, 0x68B, 0x293, 0x0A3, 0x8AB, 0xA04, 0x214, 0x41C, 0x82C,
0xB05, 0x70D, 0x51D, 0x125},
{0x948, 0x750, 0x360, 0x168, 0xB01, 0x711, 0x519, 0x129, 0xAC2, 0x8CA,
0x4DA, 0x2E2, 0x88B, 0x693, 0x2A3, 0x0AB, 0xA44, 0x654, 0x45C, 0x06C,
0xA05, 0x80D, 0x41D, 0x225},
{0x348, 0x150, 0x960, 0x768, 0xA41, 0x051, 0x459, 0x669, 0xA02, 0x20A,
0x41A, 0x822, 0x28B, 0x093, 0x8A3, 0x6AB, 0xB04, 0x114, 0x51C, 0x72C,
0xAC5, 0x2CD, 0x4DD, 0x8E5},
{0x148, 0x950, 0x760, 0x368, 0xA01, 0x811, 0x419, 0x229, 0xB02, 0x10A,
0x51A, 0x722, 0x08B, 0x893, 0x6A3, 0x2AB, 0xAC4, 0x8D4, 0x4DC, 0x2EC,
0xA45, 0x04D, 0x45D, 0x665},
{0x688, 0x890, 0x0A0, 0x2A8, 0x4C1, 0x8D1, 0xAD9, 0x2E9, 0x502, 0x70A,
0xB1A, 0x122, 0x74B, 0x953, 0x163, 0x36B, 0x404, 0x814, 0xA1C, 0x22C,
0x445, 0x64D, 0xA5D, 0x065},
{0x888, 0x090, 0x2A0, 0x6A8, 0x501, 0x111, 0xB19, 0x729, 0x402, 0x80A,
0xA1A, 0x222, 0x94B, 0x153, 0x363, 0x76B, 0x444, 0x054, 0xA5C, 0x66C,
0x4C5, 0x8CD, 0xADD, 0x2E5},
{0x288, 0x690, 0x8A0, 0x0A8, 0x441, 0x651, 0xA59, 0x069, 0x4C2, 0x2CA,
0xADA, 0x8E2, 0x34B, 0x753, 0x963, 0x16B, 0x504, 0x714, 0xB1C, 0x12C,
0x405, 0x20D, 0xA1D, 0x825},
{0x088, 0x290, 0x6A0, 0x8A8, 0x401, 0x211, 0xA19, 0x829, 0x442, 0x04A,
0xA5A, 0x662, 0x14B, 0x353, 0x763, 0x96B, 0x4C4, 0x2D4, 0xADC, 0x8EC,
0x505, 0x10D, 0xB1D, 0x725},
{0x648, 0x450, 0x060, 0xA68, 0x2C1, 0x4D1, 0x8D9, 0xAE9, 0x282, 0x68A,
0x89A, 0x0A2, 0x70B, 0x513, 0x123, 0xB2B, 0x204, 0x414, 0x81C, 0xA2C,
0x345, 0x74D, 0x95D, 0x165},
{0xA48, 0x650, 0x460, 0x068, 0x341, 0x751, 0x959, 0x169, 0x2C2, 0xACA,
0x8DA, 0x4E2, 0xB0B, 0x713, 0x523, 0x12B, 0x284, 0x694, 0x89C, 0x0AC,
0x205, 0xA0D, 0x81D, 0x425},
{0x448, 0x050, 0xA60, 0x668, 0x281, 0x091, 0x899, 0x6A9, 0x202, 0x40A,
0x81A, 0xA22, 0x50B, 0x113, 0xB23, 0x72B, 0x344, 0x154, 0x95C, 0x76C,
0x2C5, 0x4CD, 0x8DD, 0xAE5},
{0x048, 0xA50, 0x660, 0x468, 0x201, 0xA11, 0x819, 0x429, 0x342, 0x14A,
0x95A, 0x762, 0x10B, 0xB13, 0x723, 0x52B, 0x2C4, 0xAD4, 0x8DC, 0x4EC,
0x285, 0x08D, 0x89D, 0x6A5},
{0x808, 0xA10, 0x220, 0x428, 0x101, 0xB11, 0x719, 0x529, 0x142, 0x94A,
0x75A, 0x362, 0x8CB, 0xAD3, 0x2E3, 0x4EB, 0x044, 0xA54, 0x65C, 0x46C,
0x085, 0x88D, 0x69D, 0x2A5},
{0xA08, 0x210, 0x420, 0x828, 0x141, 0x351, 0x759, 0x969, 0x042, 0xA4A,
0x65A, 0x462, 0xACB, 0x2D3, 0x4E3, 0x8EB, 0x084, 0x294, 0x69C, 0x8AC,
0x105, 0xB0D, 0x71D, 0x525},
{0x408, 0x810, 0xA20, 0x228, 0x081, 0x891, 0x699, 0x2A9, 0x102, 0x50A,
0x71A, 0xB22, 0x4CB, 0x8D3, 0xAE3, 0x2EB, 0x144, 0x954, 0x75C, 0x36C,
0x045, 0x44D, 0x65D, 0xA65},
) )
_axis_convert_num = {'X': 0, 'Y': 1, 'Z': 2, '-X': 3, '-Y': 4, '-Z': 5} _axis_convert_num = {'X': 0, 'Y': 1, 'Z': 2, '-X': 3, '-Y': 4, '-Z': 5}
@@ -159,7 +236,12 @@ def axis_conversion(from_forward='Y', from_up='Z', to_forward='Y', to_up='Z'):
raise Exception("invalid axis arguments passed, " raise Exception("invalid axis arguments passed, "
"can't use up/forward on the same axis.") "can't use up/forward on the same axis.")
value = reduce(int.__or__, (_axis_convert_num[a] << (i * 3) for i, a in enumerate((from_forward, from_up, to_forward, to_up)))) value = reduce(int.__or__, (_axis_convert_num[a] << (i * 3)
for i, a in enumerate((from_forward,
from_up,
to_forward,
to_up,
))))
for i, axis_lut in enumerate(_axis_convert_lut): for i, axis_lut in enumerate(_axis_convert_lut):
if value in axis_lut: if value in axis_lut:
@@ -174,9 +256,9 @@ def axis_conversion_ensure(operator, forward_attr, up_attr):
:arg operator: the operator to access axis attributes from. :arg operator: the operator to access axis attributes from.
:type operator: :class:`Operator` :type operator: :class:`Operator`
:arg forward_attr: :arg forward_attr: attribute storing the forward axis
:type forward_attr: string :type forward_attr: string
:arg up_attr: the directory the *filepath* will be referenced from (normally the export path). :arg up_attr: attribute storing the up axis
:type up_attr: string :type up_attr: string
:return: True if the value was modified. :return: True if the value was modified.
:rtype: boolean :rtype: boolean
@@ -201,7 +283,8 @@ def axis_conversion_ensure(operator, forward_attr, up_attr):
return False return False
# return a tuple (free, object list), free is True if memory should be freed later with free_derived_objects() # return a tuple (free, object list), free is True if memory should be freed
# later with free_derived_objects()
def create_derived_objects(scene, ob): def create_derived_objects(scene, ob):
if ob.parent and ob.parent.dupli_type in {'VERTS', 'FACES'}: if ob.parent and ob.parent.dupli_type in {'VERTS', 'FACES'}:
return False, None return False, None
@@ -249,31 +332,45 @@ path_reference_mode = EnumProperty(
description="Method used to reference paths", description="Method used to reference paths",
items=(('AUTO', "Auto", "Use Relative paths with subdirectories only"), items=(('AUTO', "Auto", "Use Relative paths with subdirectories only"),
('ABSOLUTE', "Absolute", "Always write absolute paths"), ('ABSOLUTE', "Absolute", "Always write absolute paths"),
('RELATIVE', "Relative", "Always write relative patsh (where possible)"), ('RELATIVE', "Relative", "Always write relative patsh "
('MATCH', "Match", "Match Absolute/Relative setting with input path"), "(where possible)"),
('MATCH', "Match", "Match Absolute/Relative "
"setting with input path"),
('STRIP', "Strip Path", "Filename only"), ('STRIP', "Strip Path", "Filename only"),
('COPY', "Copy", "copy the file to the destination path (or subdirectory)"), ('COPY', "Copy", "copy the file to the destination path "
"(or subdirectory)"),
), ),
default='AUTO' default='AUTO'
) )
def path_reference(filepath, base_src, base_dst, mode='AUTO', copy_subdir="", copy_set=None): def path_reference(filepath,
base_src,
base_dst,
mode='AUTO',
copy_subdir="",
copy_set=None,
):
""" """
Return a filepath relative to a destination directory, for use with Return a filepath relative to a destination directory, for use with
exporters. exporters.
:arg filepath: the file path to return, supporting blenders relative '//' prefix. :arg filepath: the file path to return,
supporting blenders relative '//' prefix.
:type filepath: string :type filepath: string
:arg base_src: the directory the *filepath* is relative too (normally the blend file). :arg base_src: the directory the *filepath* is relative too
(normally the blend file).
:type base_src: string :type base_src: string
:arg base_dst: the directory the *filepath* will be referenced from (normally the export path). :arg base_dst: the directory the *filepath* will be referenced from
(normally the export path).
:type base_dst: string :type base_dst: string
:arg mode: the method used get the path in ['AUTO', 'ABSOLUTE', 'RELATIVE', 'MATCH', 'STRIP', 'COPY'] :arg mode: the method used get the path in
['AUTO', 'ABSOLUTE', 'RELATIVE', 'MATCH', 'STRIP', 'COPY']
:type mode: string :type mode: string
:arg copy_subdir: the subdirectory of *base_dst* to use when mode='COPY'. :arg copy_subdir: the subdirectory of *base_dst* to use when mode='COPY'.
:type copy_subdir: string :type copy_subdir: string
:arg copy_set: collect from/to pairs when mode='COPY', pass to *path_reference_copy* when exportign is done. :arg copy_set: collect from/to pairs when mode='COPY',
pass to *path_reference_copy* when exportign is done.
:type copy_set: set :type copy_set: set
:return: the new filepath. :return: the new filepath.
:rtype: string :rtype: string
@@ -282,12 +379,14 @@ def path_reference(filepath, base_src, base_dst, mode='AUTO', copy_subdir="", co
is_relative = filepath.startswith("//") is_relative = filepath.startswith("//")
filepath_abs = os.path.normpath(bpy.path.abspath(filepath, base_src)) filepath_abs = os.path.normpath(bpy.path.abspath(filepath, base_src))
if mode in ('ABSOLUTE', 'RELATIVE', 'STRIP'): if mode in {'ABSOLUTE', 'RELATIVE', 'STRIP'}:
pass pass
elif mode == 'MATCH': elif mode == 'MATCH':
mode = 'RELATIVE' if is_relative else 'ABSOLUTE' mode = 'RELATIVE' if is_relative else 'ABSOLUTE'
elif mode == 'AUTO': elif mode == 'AUTO':
mode = 'RELATIVE' if bpy.path.is_subdir(filepath, base_dst) else 'ABSOLUTE' mode = ('RELATIVE'
if bpy.path.is_subdir(filepath, base_dst)
else 'ABSOLUTE')
elif mode == 'COPY': elif mode == 'COPY':
if copy_subdir: if copy_subdir:
subdir_abs = os.path.join(os.path.normpath(base_dst), copy_subdir) subdir_abs = os.path.join(os.path.normpath(base_dst), copy_subdir)
@@ -362,7 +461,8 @@ def unique_name(key, name, name_dict, name_max=-1, clean_func=None):
if name_new is None: if name_new is None:
count = 1 count = 1
name_dict_values = name_dict.values() name_dict_values = name_dict.values()
name_new = name_new_orig = name if clean_func is None else clean_func(name) name_new = name_new_orig = (name if clean_func is None
else clean_func(name))
if name_max == -1: if name_max == -1:
while name_new in name_dict_values: while name_new in name_dict_values:
@@ -372,7 +472,10 @@ def unique_name(key, name, name_dict, name_max=-1, clean_func=None):
name_new = name_new[:name_max] name_new = name_new[:name_max]
while name_new in name_dict_values: while name_new in name_dict_values:
count_str = "%03d" % count count_str = "%03d" % count
name_new = "%.*s.%s" % (name_max - (len(count_str) + 1), name_new_orig, count_str) name_new = "%.*s.%s" % (name_max - (len(count_str) + 1),
name_new_orig,
count_str,
)
count += 1 count += 1
name_dict[key] = name_new name_dict[key] = name_new

View File

@@ -26,7 +26,7 @@ __all__ = (
"edge_loops_from_edges", "edge_loops_from_edges",
"ngon_tesselate", "ngon_tesselate",
"face_random_points", "face_random_points",
) )
def mesh_linked_faces(mesh): def mesh_linked_faces(mesh):
@@ -170,8 +170,8 @@ def edge_loops_from_faces(mesh, faces=None, seams=()):
# from knowing the last 2, look for th next. # from knowing the last 2, look for th next.
ed_adj = edges[context_loop[-1]] ed_adj = edges[context_loop[-1]]
if len(ed_adj) != 2: if len(ed_adj) != 2:
# the original edge had 2 other edges
if other_dir and flipped == False: # the original edge had 2 other edges if other_dir and flipped == False:
flipped = True # only flip the list once flipped = True # only flip the list once
context_loop.reverse() context_loop.reverse()
ed_adj[:] = [] ed_adj[:] = []
@@ -259,13 +259,15 @@ def edge_loops_from_edges(mesh, edges=None):
def ngon_tesselate(from_data, indices, fix_loops=True): def ngon_tesselate(from_data, indices, fix_loops=True):
''' '''
Takes a polyline of indices (fgon) Takes a polyline of indices (fgon) and returns a list of face
and returns a list of face indicie lists. indicie lists. Designed to be used for importers that need indices for an
Designed to be used for importers that need indices for an fgon to create from existing verts. fgon to create from existing verts.
from_data: either a mesh, or a list/tuple of vectors. from_data: either a mesh, or a list/tuple of vectors.
indices: a list of indices to use this list is the ordered closed polyline to fill, and can be a subset of the data given. indices: a list of indices to use this list is the ordered closed polyline
fix_loops: If this is enabled polylines that use loops to make multiple polylines are delt with correctly. to fill, and can be a subset of the data given.
fix_loops: If this is enabled polylines that use loops to make multiple
polylines are delt with correctly.
''' '''
from mathutils.geometry import tesselate_polygon from mathutils.geometry import tesselate_polygon
@@ -276,7 +278,8 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
return [] return []
def mlen(co): def mlen(co):
return abs(co[0]) + abs(co[1]) + abs(co[2]) # manhatten length of a vector, faster then length # manhatten length of a vector, faster then length
return abs(co[0]) + abs(co[1]) + abs(co[2])
def vert_treplet(v, i): def vert_treplet(v, i):
return v, vector_to_tuple(v, 6), i, mlen(v) return v, vector_to_tuple(v, 6), i, mlen(v)
@@ -291,12 +294,13 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
''' '''
Normal single concave loop filling Normal single concave loop filling
''' '''
if type(from_data) in (tuple, list): if type(from_data) in {tuple, list}:
verts = [Vector(from_data[i]) for ii, i in enumerate(indices)] verts = [Vector(from_data[i]) for ii, i in enumerate(indices)]
else: else:
verts = [from_data.vertices[i].co for ii, i in enumerate(indices)] verts = [from_data.vertices[i].co for ii, i in enumerate(indices)]
for i in range(len(verts) - 1, 0, -1): # same as reversed(xrange(1, len(verts))): # same as reversed(range(1, len(verts))):
for i in range(len(verts) - 1, 0, -1):
if verts[i][1] == verts[i - 1][0]: if verts[i][1] == verts[i - 1][0]:
verts.pop(i - 1) verts.pop(i - 1)
@@ -304,14 +308,16 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
else: else:
''' '''
Seperate this loop into multiple loops be finding edges that are used twice Seperate this loop into multiple loops be finding edges that are
This is used by lightwave LWO files a lot used twice. This is used by lightwave LWO files a lot
''' '''
if type(from_data) in (tuple, list): if type(from_data) in {tuple, list}:
verts = [vert_treplet(Vector(from_data[i]), ii) for ii, i in enumerate(indices)] verts = [vert_treplet(Vector(from_data[i]), ii)
for ii, i in enumerate(indices)]
else: else:
verts = [vert_treplet(from_data.vertices[i].co, ii) for ii, i in enumerate(indices)] verts = [vert_treplet(from_data.vertices[i].co, ii)
for ii, i in enumerate(indices)]
edges = [(i, i - 1) for i in range(len(verts))] edges = [(i, i - 1) for i in range(len(verts))]
if edges: if edges:

View File

@@ -16,12 +16,12 @@
# #
# ##### END GPL LICENSE BLOCK ##### # ##### END GPL LICENSE BLOCK #####
# <pep8 compliant> # <pep8-80 compliant>
__all__ = ( __all__ = (
"add_object_align_init", "add_object_align_init",
"object_data_add", "object_data_add",
) )
import bpy import bpy
@@ -39,42 +39,49 @@ def add_object_align_init(context, operator):
:return: the matrix from the context and settings. :return: the matrix from the context and settings.
:rtype: :class:`Matrix` :rtype: :class:`Matrix`
""" """
from mathutils import Matrix, Vector, Euler
properties = operator.properties if operator is not None else None
space_data = context.space_data space_data = context.space_data
if space_data.type != 'VIEW_3D': if space_data.type != 'VIEW_3D':
space_data = None space_data = None
# location # location
if operator and operator.properties.is_property_set("location"): if operator and properties.is_property_set("location"):
location = mathutils.Matrix.Translation(mathutils.Vector(operator.properties.location)) location = Matrix.Translation(Vector(properties.location))
else: else:
if space_data: # local view cursor is detected below if space_data: # local view cursor is detected below
location = mathutils.Matrix.Translation(space_data.cursor_location) location = Matrix.Translation(space_data.cursor_location)
else: else:
location = mathutils.Matrix.Translation(context.scene.cursor_location) location = Matrix.Translation(context.scene.cursor_location)
if operator: if operator:
operator.properties.location = location.to_translation() properties.location = location.to_translation()
# rotation # rotation
view_align = (context.user_preferences.edit.object_align == 'VIEW') view_align = (context.user_preferences.edit.object_align == 'VIEW')
view_align_force = False view_align_force = False
if operator: if operator:
if operator.properties.is_property_set("view_align"): if properties.is_property_set("view_align"):
view_align = view_align_force = operator.view_align view_align = view_align_force = operator.view_align
else: else:
operator.properties.view_align = view_align properties.view_align = view_align
if operator and operator.properties.is_property_set("rotation") and not view_align_force: if operator and (properties.is_property_set("rotation") and
rotation = mathutils.Euler(operator.properties.rotation).to_matrix().to_4x4() not view_align_force):
rotation = Euler(properties.rotation).to_matrix().to_4x4()
else: else:
if view_align and space_data: if view_align and space_data:
rotation = space_data.region_3d.view_matrix.to_3x3().inverted().to_4x4() rotation = space_data.region_3d.view_matrix.to_3x3().inverted()
rotation.resize_4x4()
else: else:
rotation = mathutils.Matrix() rotation = mathutils.Matrix()
# set the operator properties # set the operator properties
if operator: if operator:
operator.properties.rotation = rotation.to_euler() properties.rotation = rotation.to_euler()
return location * rotation return location * rotation
@@ -114,14 +121,18 @@ def object_data_add(context, obdata, operator=None):
# XXX # XXX
# caused because entering editmodedoes not add a empty undo slot! # caused because entering editmodedoes not add a empty undo slot!
if context.user_preferences.edit.use_enter_edit_mode: if context.user_preferences.edit.use_enter_edit_mode:
if not (obj_act and obj_act.mode == 'EDIT' and obj_act.type == obj_new.type): if not (obj_act and
obj_act.mode == 'EDIT' and
obj_act.type == obj_new.type):
_obdata = bpy.data.meshes.new(obdata.name) _obdata = bpy.data.meshes.new(obdata.name)
obj_act = bpy.data.objects.new(_obdata.name, _obdata) obj_act = bpy.data.objects.new(_obdata.name, _obdata)
obj_act.matrix_world = obj_new.matrix_world obj_act.matrix_world = obj_new.matrix_world
scene.objects.link(obj_act) scene.objects.link(obj_act)
scene.objects.active = obj_act scene.objects.active = obj_act
bpy.ops.object.mode_set(mode='EDIT') bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.ed.undo_push(message="Enter Editmode") # need empty undo step # need empty undo step
bpy.ops.ed.undo_push(message="Enter Editmode")
# XXX # XXX
if obj_act and obj_act.mode == 'EDIT' and obj_act.type == obj_new.type: if obj_act and obj_act.mode == 'EDIT' and obj_act.type == obj_new.type:

View File

@@ -16,13 +16,13 @@
# #
# ##### END GPL LICENSE BLOCK ##### # ##### END GPL LICENSE BLOCK #####
# <pep8 compliant> # <pep8-80 compliant>
__all__ = ( __all__ = (
"region_2d_to_vector_3d", "region_2d_to_vector_3d",
"region_2d_to_location_3d", "region_2d_to_location_3d",
"location_3d_to_region_2d", "location_3d_to_region_2d",
) )
def region_2d_to_vector_3d(region, rv3d, coord): def region_2d_to_vector_3d(region, rv3d, coord):
@@ -90,15 +90,23 @@ def region_2d_to_location_3d(region, rv3d, coord, depth_location):
origin_start = rv3d.view_matrix.inverted()[3].to_3d() origin_start = rv3d.view_matrix.inverted()[3].to_3d()
origin_end = origin_start + coord_vec origin_end = origin_start + coord_vec
view_vec = rv3d.view_matrix.inverted()[2] view_vec = rv3d.view_matrix.inverted()[2]
return intersect_line_plane(origin_start, origin_end, depth_location, view_vec, 1) return intersect_line_plane(origin_start,
origin_end,
depth_location,
view_vec, 1,
)
else: else:
dx = (2.0 * coord[0] / region.width) - 1.0 dx = (2.0 * coord[0] / region.width) - 1.0
dy = (2.0 * coord[1] / region.height) - 1.0 dy = (2.0 * coord[1] / region.height) - 1.0
persinv = persmat.inverted() persinv = persmat.inverted()
viewinv = rv3d.view_matrix.inverted() viewinv = rv3d.view_matrix.inverted()
origin_start = (persinv[0].xyz * dx) + (persinv[1].xyz * dy) + viewinv[3].xyz origin_start = ((persinv[0].xyz * dx) +
(persinv[1].xyz * dy) + viewinv[3].xyz)
origin_end = origin_start + coord_vec origin_end = origin_start + coord_vec
return intersect_point_line(depth_location, origin_start, origin_end)[0] return intersect_point_line(depth_location,
origin_start,
origin_end,
)[0]
def location_3d_to_region_2d(region, rv3d, coord): def location_3d_to_region_2d(region, rv3d, coord):

View File

@@ -120,7 +120,7 @@ def fromxml(data):
py_item = (xml_node.tagName, _fromxml_kwargs(xml_node), []) py_item = (xml_node.tagName, _fromxml_kwargs(xml_node), [])
#_fromxml_iter(py_item, xml_node.childNodes) #_fromxml_iter(py_item, xml_node.childNodes)
for xml_node_child in xml_node.childNodes: for xml_node_child in xml_node.childNodes:
if xml_node_child.nodeType not in (xml_node_child.TEXT_NODE, xml_node_child.COMMENT_NODE): if xml_node_child.nodeType not in {xml_node_child.TEXT_NODE, xml_node_child.COMMENT_NODE}:
py_item[CHILDREN].append(_fromxml(xml_node_child)) py_item[CHILDREN].append(_fromxml(xml_node_child))
return py_item return py_item

View File

@@ -40,13 +40,13 @@ def _parse_rna(prop, value):
elif prop.type == 'INT': elif prop.type == 'INT':
value = int(value) value = int(value)
elif prop.type == 'BOOLEAN': elif prop.type == 'BOOLEAN':
if value in (True, False): if value in {True, False}:
pass pass
else: else:
if value not in ("True", "False"): if value not in {"True", "False"}:
raise Exception("invalid bool value: %s" % value) raise Exception("invalid bool value: %s" % value)
value = bool(value == "True") value = bool(value == "True")
elif prop.type in ('STRING', 'ENUM'): elif prop.type in {'STRING', 'ENUM'}:
pass pass
elif prop.type == 'POINTER': elif prop.type == 'POINTER':
value = eval("_bpy." + value) value = eval("_bpy." + value)

View File

@@ -16,14 +16,14 @@
# #
# ##### END GPL LICENSE BLOCK ##### # ##### END GPL LICENSE BLOCK #####
# <pep8 compliant> # <pep8-80 compliant>
# This file defines a set of methods that are useful for various # This file defines a set of methods that are useful for various
# Relative Keying Set (RKS) related operations, such as: callbacks # Relative Keying Set (RKS) related operations, such as: callbacks
# for polling, iterator callbacks, and also generate callbacks. # for polling, iterator callbacks, and also generate callbacks.
# All of these can be used in conjunction with the others. # All of these can be used in conjunction with the others.
__all__ = [ __all__ = (
"path_add_property", "path_add_property",
"RKS_POLL_selected_objects", "RKS_POLL_selected_objects",
"RKS_POLL_selected_bones", "RKS_POLL_selected_bones",
@@ -33,7 +33,7 @@ __all__ = [
"RKS_GEN_location", "RKS_GEN_location",
"RKS_GEN_rotation", "RKS_GEN_rotation",
"RKS_GEN_scaling", "RKS_GEN_scaling",
] )
import bpy import bpy
@@ -75,7 +75,8 @@ def RKS_POLL_selected_bones(ksi, context):
# selected bones or objects # selected bones or objects
def RKS_POLL_selected_items(ksi, context): def RKS_POLL_selected_items(ksi, context):
return RKS_POLL_selected_bones(ksi, context) or RKS_POLL_selected_objects(ksi, context) return (RKS_POLL_selected_bones(ksi, context) or
RKS_POLL_selected_objects(ksi, context))
########################### ###########################
# Iterator Callbacks # Iterator Callbacks

View File

@@ -148,7 +148,7 @@ class InfoStructRNA:
import types import types
functions = [] functions = []
for identifier, attr in self._get_py_visible_attrs(): for identifier, attr in self._get_py_visible_attrs():
if type(attr) in (types.FunctionType, types.MethodType): if type(attr) in {types.FunctionType, types.MethodType}:
functions.append((identifier, attr)) functions.append((identifier, attr))
return functions return functions
@@ -156,7 +156,7 @@ class InfoStructRNA:
import types import types
functions = [] functions = []
for identifier, attr in self._get_py_visible_attrs(): for identifier, attr in self._get_py_visible_attrs():
if type(attr) in (types.BuiltinMethodType, types.BuiltinFunctionType): if type(attr) in {types.BuiltinMethodType, types.BuiltinFunctionType}:
functions.append((identifier, attr)) functions.append((identifier, attr))
return functions return functions
@@ -260,7 +260,7 @@ class InfoPropertyRNA:
if self.array_length: if self.array_length:
type_str += " array of %d items" % (self.array_length) type_str += " array of %d items" % (self.array_length)
if self.type in ("float", "int"): if self.type in {"float", "int"}:
type_str += " in [%s, %s]" % (range_str(self.min), range_str(self.max)) type_str += " in [%s, %s]" % (range_str(self.min), range_str(self.max))
elif self.type == "enum": elif self.type == "enum":
if self.is_enum_flag: if self.is_enum_flag:
@@ -595,7 +595,7 @@ def BuildRNAInfo():
for prop in rna_info.properties: for prop in rna_info.properties:
# ERROR CHECK # ERROR CHECK
default = prop.default default = prop.default
if type(default) in (float, int): if type(default) in {float, int}:
if default < prop.min or default > prop.max: if default < prop.min or default > prop.max:
print("\t %s.%s, %s not in [%s - %s]" % (rna_info.identifier, prop.identifier, default, prop.min, prop.max)) print("\t %s.%s, %s not in [%s - %s]" % (rna_info.identifier, prop.identifier, default, prop.min, prop.max))

View File

@@ -1,8 +1,7 @@
import bpy import bpy
is_ntsc = (bpy.context.scene.render.fps != 25) is_ntsc = (bpy.context.scene.render.fps != 25)
bpy.context.scene.render.ffmpeg_format = "AVI" bpy.context.scene.render.ffmpeg_format = "XVID"
bpy.context.scene.render.ffmpeg_codec = "XVID"
if is_ntsc: if is_ntsc:
bpy.context.scene.render.ffmpeg_gopsize = 18 bpy.context.scene.render.ffmpeg_gopsize = 18

View File

@@ -61,13 +61,19 @@ class EditExternally(bpy.types.Operator):
def execute(self, context): def execute(self, context):
import os import os
import subprocess import subprocess
filepath = os.path.normpath(bpy.path.abspath(self.filepath))
filepath = self.filepath
if not filepath:
self.report({'ERROR'}, "Image path not set")
return {'CANCELLED'}
filepath = os.path.normpath(bpy.path.abspath(filepath))
if not os.path.exists(filepath): if not os.path.exists(filepath):
self.report({'ERROR'}, self.report({'ERROR'},
"Image path %r not found, image may be packed or " "Image path %r not found, image may be packed or "
"unsaved." % filepath) "unsaved." % filepath)
return {'CANCELLED'} return {'CANCELLED'}
cmd = self._editor_guess(context) + [filepath] cmd = self._editor_guess(context) + [filepath]

View File

@@ -22,6 +22,7 @@ import bpy
from mathutils import Vector from mathutils import Vector
from blf import gettext as _ from blf import gettext as _
def GlobalBB_LQ(bb_world): def GlobalBB_LQ(bb_world):
# Initialize the variables with the 8th vertex # Initialize the variables with the 8th vertex
@@ -34,7 +35,7 @@ def GlobalBB_LQ(bb_world):
) )
# Test against the other 7 verts # Test against the other 7 verts
for i in range (7): for i in range(7):
# X Range # X Range
val = bb_world[i][0] val = bb_world[i][0]
@@ -62,6 +63,7 @@ def GlobalBB_LQ(bb_world):
return (Vector((left, front, up)), Vector((right, back, down))) return (Vector((left, front, up)), Vector((right, back, down)))
def GlobalBB_HQ(obj): def GlobalBB_HQ(obj):
matrix_world = obj.matrix_world.copy() matrix_world = obj.matrix_world.copy()
@@ -81,7 +83,7 @@ def GlobalBB_HQ(obj):
) )
# Test against all other verts # Test against all other verts
for i in range (len(verts)-1): for i in range(len(verts) - 1):
vco = matrix_world * verts[i].co vco = matrix_world * verts[i].co

View File

@@ -520,7 +520,7 @@ def unwrap(operator, context, **kwargs):
if obj and obj.type == 'MESH': if obj and obj.type == 'MESH':
meshes = [obj.data] meshes = [obj.data]
else: else:
meshes = {me.name: me for obj in context.selected_objects if obj.type == 'MESH' for me in (obj.data,) if not me.library if len(me.faces)}.values() meshes = list({me for obj in context.selected_objects if obj.type == 'MESH' for me in (obj.data,) if me.faces and me.library is None})
if not meshes: if not meshes:
operator.report({'ERROR'}, "No mesh object.") operator.report({'ERROR'}, "No mesh object.")

View File

@@ -587,7 +587,7 @@ class WM_OT_context_modal_mouse(bpy.types.Operator):
self._values_clear() self._values_clear()
return {'FINISHED'} return {'FINISHED'}
elif event_type in ('RIGHTMOUSE', 'ESC'): elif event_type in {'RIGHTMOUSE', 'ESC'}:
self._values_restore() self._values_restore()
return {'FINISHED'} return {'FINISHED'}
@@ -841,7 +841,7 @@ class WM_OT_properties_edit(bpy.types.Operator):
prop_ui = rna_idprop_ui_prop_get(item, prop) prop_ui = rna_idprop_ui_prop_get(item, prop)
if prop_type in (float, int): if prop_type in {float, int}:
prop_ui['soft_min'] = prop_ui['min'] = prop_type(self.min) prop_ui['soft_min'] = prop_ui['min'] = prop_type(self.min)
prop_ui['soft_max'] = prop_ui['max'] = prop_type(self.max) prop_ui['soft_max'] = prop_ui['max'] = prop_type(self.max)

View File

@@ -361,7 +361,7 @@ class DATA_PT_paragraph(CurveButtonsPanel, bpy.types.Panel):
col.prop(text, "offset_y", text="Y") col.prop(text, "offset_y", text="Y")
class DATA_PT_textboxes(CurveButtonsPanel, bpy.types.Panel): class DATA_PT_text_boxes(CurveButtonsPanel, bpy.types.Panel):
bl_label = _("Text Boxes") bl_label = _("Text Boxes")
@classmethod @classmethod

View File

@@ -41,11 +41,9 @@ class DATA_PT_empty(DataButtonsPanel, bpy.types.Panel):
layout.prop(ob, "empty_draw_type", text=_("Display")) layout.prop(ob, "empty_draw_type", text=_("Display"))
if ob.empty_draw_type == 'IMAGE': if ob.empty_draw_type == 'IMAGE':
# layout.template_image(ob, "data", None)
layout.template_ID(ob, "data", open="image.open", unlink="image.unlink") layout.template_ID(ob, "data", open="image.open", unlink="image.unlink")
row = layout.row(align=True) layout.prop(ob, "color", text=_("Transparency"), index=3, slider=True)
row.prop(ob, "color", text=_("Transparency"), index=3, slider=True)
row = layout.row(align=True) row = layout.row(align=True)
row.prop(ob, "empty_image_offset", text=_("Offset X"), index=0) row.prop(ob, "empty_image_offset", text=_("Offset X"), index=0)
row.prop(ob, "empty_image_offset", text=_("Offset Y"), index=1) row.prop(ob, "empty_image_offset", text=_("Offset Y"), index=1)

View File

@@ -247,15 +247,17 @@ class MATERIAL_PT_diffuse(MaterialButtonsPanel, bpy.types.Panel):
row.prop(mat, "diffuse_fresnel_factor", text=_("Factor")) row.prop(mat, "diffuse_fresnel_factor", text=_("Factor"))
if mat.use_diffuse_ramp: if mat.use_diffuse_ramp:
layout.separator() col = layout.column()
layout.template_color_ramp(mat, "diffuse_ramp", expand=True) col.active = (not mat.use_shadeless)
layout.separator() col.separator()
col.template_color_ramp(mat, "diffuse_ramp", expand=True)
col.separator()
row = layout.row() row = col.row()
row.prop(mat, "diffuse_ramp_input", text=_("Input")) row.prop(mat, "diffuse_ramp_input", text=_("Input"))
row.prop(mat, "diffuse_ramp_blend", text=_("Blend")) row.prop(mat, "diffuse_ramp_blend", text=_("Blend"))
layout.prop(mat, "diffuse_ramp_factor", text=_("Factor")) col.prop(mat, "diffuse_ramp_factor", text=_("Factor"))
class MATERIAL_PT_specular(MaterialButtonsPanel, bpy.types.Panel): class MATERIAL_PT_specular(MaterialButtonsPanel, bpy.types.Panel):

View File

@@ -463,7 +463,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
col.prop(part, "mass") col.prop(part, "mass")
col.prop(part, "use_multiply_size_mass", text=_("Multiply mass with size")) col.prop(part, "use_multiply_size_mass", text=_("Multiply mass with size"))
if part.physics_type in ('NEWTON', 'FLUID'): if part.physics_type in {'NEWTON', 'FLUID'}:
split = layout.split() split = layout.split()
col = split.column() col = split.column()
@@ -922,7 +922,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel, bpy.types.Panel):
col = row.column() col = row.column()
col.label(text="") col.label(text="")
if part.render_type in ('OBJECT', 'GROUP') and not part.use_advanced_hair: if part.render_type in {'OBJECT', 'GROUP'} and not part.use_advanced_hair:
row = layout.row(align=True) row = layout.row(align=True)
row.prop(part, "particle_size") row.prop(part, "particle_size")
row.prop(part, "size_random", slider=True) row.prop(part, "size_random", slider=True)

View File

@@ -353,7 +353,7 @@ class INFO_MT_help(bpy.types.Menu):
layout = self.layout layout = self.layout
layout.operator("wm.url_open", text=_("Manual"), icon='HELP').url = 'http://wiki.blender.org/index.php/Doc:Manual' layout.operator("wm.url_open", text=_("Manual"), icon='HELP').url = 'http://wiki.blender.org/index.php/Doc:Manual'
layout.operator("wm.url_open", text=_("Release Log"), icon='URL').url = 'http://www.blender.org/development/release-logs/blender-257/' layout.operator("wm.url_open", text=_("Release Log"), icon='URL').url = 'http://www.blender.org/development/release-logs/blender-259/'
layout.separator() layout.separator()

View File

@@ -755,6 +755,31 @@ class USERPREF_PT_file(bpy.types.Panel):
from bl_ui.space_userpref_keymap import InputKeyMapPanel from bl_ui.space_userpref_keymap import InputKeyMapPanel
class USERPREF_MT_ndof_settings(bpy.types.Menu):
# accessed from the window keybindings in C (only)
bl_label = _("3D Mouse Settings")
def draw(self, context):
layout = self.layout
input_prefs = context.user_preferences.inputs
layout.separator()
layout.prop(input_prefs, "ndof_sensitivity")
if context.space_data.type == 'VIEW_3D':
layout.separator()
layout.prop(input_prefs, "ndof_show_guide")
layout.separator()
layout.label(text="orbit options")
layout.prop(input_prefs, "ndof_orbit_invert_axes")
layout.separator()
layout.label(text="fly options")
layout.prop(input_prefs, "ndof_fly_helicopter", icon='NDOF_FLY')
layout.prop(input_prefs, "ndof_lock_horizon", icon='NDOF_DOM')
class USERPREF_PT_input(bpy.types.Panel, InputKeyMapPanel): class USERPREF_PT_input(bpy.types.Panel, InputKeyMapPanel):
bl_space_type = 'USER_PREFERENCES' bl_space_type = 'USER_PREFERENCES'
bl_label = _("Input") bl_label = _("Input")
@@ -817,12 +842,9 @@ class USERPREF_PT_input(bpy.types.Panel, InputKeyMapPanel):
#sub.prop(view, "wheel_scroll_lines", text="Scroll Lines") #sub.prop(view, "wheel_scroll_lines", text="Scroll Lines")
col.separator() col.separator()
''' not implemented yet
sub = col.column() sub = col.column()
sub.label(text="NDOF Device:") sub.label(text="NDOF Device:")
sub.prop(inputs, "ndof_pan_speed", text="Pan Speed") sub.prop(inputs, "ndof_sensitivity", text="NDOF Sensitivity")
sub.prop(inputs, "ndof_rotate_speed", text="Orbit Speed")
'''
row.separator() row.separator()
@@ -881,7 +903,7 @@ class USERPREF_PT_addons(bpy.types.Panel):
if not user_addon_paths: if not user_addon_paths:
user_script_path = bpy.utils.user_script_path() user_script_path = bpy.utils.user_script_path()
if user_script_path is not None: if user_script_path is not None:
user_addon_paths.append(os.path.join(user_script_path(), "addons")) user_addon_paths.append(os.path.join(user_script_path, "addons"))
user_addon_paths.append(os.path.join(bpy.utils.resource_path('USER'), "scripts", "addons")) user_addon_paths.append(os.path.join(bpy.utils.resource_path('USER'), "scripts", "addons"))
for path in user_addon_paths: for path in user_addon_paths:
@@ -927,6 +949,12 @@ class USERPREF_PT_addons(bpy.types.Panel):
"(see console for details)", "(see console for details)",
) )
if addon_utils.error_encoding:
self.draw_error(col,
"One or more addons do not have UTF-8 encoding\n"
"(see console for details)",
)
filter = context.window_manager.addon_filter filter = context.window_manager.addon_filter
search = context.window_manager.addon_search.lower() search = context.window_manager.addon_search.lower()
support = context.window_manager.addon_support support = context.window_manager.addon_support
@@ -1020,7 +1048,6 @@ class USERPREF_PT_addons(bpy.types.Panel):
for i in range(4 - tot_row): for i in range(4 - tot_row):
split.separator() split.separator()
# Append missing scripts # Append missing scripts
# First collect scripts that are used but have no script file. # First collect scripts that are used but have no script file.
module_names = {mod.__name__ for mod, info in addons} module_names = {mod.__name__ for mod, info in addons}
@@ -1049,17 +1076,25 @@ class WM_OT_addon_enable(bpy.types.Operator):
bl_idname = "wm.addon_enable" bl_idname = "wm.addon_enable"
bl_label = _("Enable Add-On") bl_label = _("Enable Add-On")
module = StringProperty(name=_("Module"), description=_("Module name of the addon to enable")) module = StringProperty(
name=_("Module"),
description=_("Module name of the addon to enable"),
)
def execute(self, context): def execute(self, context):
mod = addon_utils.enable(self.module) mod = addon_utils.enable(self.module)
if mod: if mod:
# check if add-on is written for current blender version, or raise a warning
info = addon_utils.module_bl_info(mod) info = addon_utils.module_bl_info(mod)
if info.get("blender", (0, 0, 0)) > bpy.app.version: info_ver = info.get("blender", (0, 0, 0))
self.report("WARNING','This script was written for a newer version of Blender and might not function (correctly).\nThe script is enabled though.")
if info_ver > bpy.app.version:
self.report({'WARNING'}, ("This script was written Blender "
"version %d.%d.%d and might not "
"function (correctly).\n"
"The script is enabled though.") %
info_ver)
return {'FINISHED'} return {'FINISHED'}
else: else:
return {'CANCELLED'} return {'CANCELLED'}

View File

@@ -190,10 +190,10 @@ class InputKeyMapPanel:
if km.is_modal: if km.is_modal:
row.label(text="", icon='LINKED') row.label(text="", icon='LINKED')
if km.is_user_defined: if km.is_user_modified:
row.operator("wm.keymap_restore", text=_("Restore")) row.operator("wm.keymap_restore", text=_("Restore"))
else: else:
row.operator("wm.keymap_edit", text=_("Edit")) row.label()
if km.show_expanded_children: if km.show_expanded_children:
if children: if children:
@@ -214,7 +214,6 @@ class InputKeyMapPanel:
# "Add New" at end of keymap item list # "Add New" at end of keymap item list
col = self.indented_layout(col, level + 1) col = self.indented_layout(col, level + 1)
subcol = col.split(percentage=0.2).column() subcol = col.split(percentage=0.2).column()
subcol.enabled = km.is_user_defined
subcol.operator("wm.keyitem_add", text=_("Add New"), icon='ZOOMIN') subcol.operator("wm.keyitem_add", text=_("Add New"), icon='ZOOMIN')
col.separator() col.separator()
@@ -245,7 +244,7 @@ class InputKeyMapPanel:
col = self.indented_layout(layout, level) col = self.indented_layout(layout, level)
if km.is_user_defined: if kmi.show_expanded:
col = col.column(align=True) col = col.column(align=True)
box = col.box() box = col.box()
else: else:
@@ -258,7 +257,6 @@ class InputKeyMapPanel:
row.prop(kmi, "show_expanded", text="", emboss=False) row.prop(kmi, "show_expanded", text="", emboss=False)
row = split.row() row = split.row()
row.enabled = km.is_user_defined
row.prop(kmi, "active", text="", emboss=False) row.prop(kmi, "active", text="", emboss=False)
if km.is_modal: if km.is_modal:
@@ -267,12 +265,13 @@ class InputKeyMapPanel:
row.label(text=kmi.name) row.label(text=kmi.name)
row = split.row() row = split.row()
row.enabled = km.is_user_defined
row.prop(kmi, "map_type", text="") row.prop(kmi, "map_type", text="")
if map_type == 'KEYBOARD': if map_type == 'KEYBOARD':
row.prop(kmi, "type", text="", full_event=True) row.prop(kmi, "type", text="", full_event=True)
elif map_type == 'MOUSE': elif map_type == 'MOUSE':
row.prop(kmi, "type", text="", full_event=True) row.prop(kmi, "type", text="", full_event=True)
elif map_type == 'NDOF':
row.prop(kmi, "type", text="", full_event=True)
elif map_type == 'TWEAK': elif map_type == 'TWEAK':
subrow = row.row() subrow = row.row()
subrow.prop(kmi, "type", text="") subrow.prop(kmi, "type", text="")
@@ -282,9 +281,10 @@ class InputKeyMapPanel:
else: else:
row.label() row.label()
if not kmi.is_user_defined: if (not kmi.is_user_defined) and kmi.is_user_modified:
op = row.operator("wm.keyitem_restore", text="", icon='BACK') op = row.operator("wm.keyitem_restore", text="", icon='BACK')
op.item_id = kmi.id op.item_id = kmi.id
else:
op = row.operator("wm.keyitem_remove", text="", icon='X') op = row.operator("wm.keyitem_remove", text="", icon='X')
op.item_id = kmi.id op.item_id = kmi.id
@@ -292,8 +292,6 @@ class InputKeyMapPanel:
if kmi.show_expanded: if kmi.show_expanded:
box = col.box() box = col.box()
box.enabled = km.is_user_defined
if map_type not in {'TEXTINPUT', 'TIMER'}: if map_type not in {'TEXTINPUT', 'TIMER'}:
split = box.split(percentage=0.4) split = box.split(percentage=0.4)
sub = split.row() sub = split.row()
@@ -308,7 +306,7 @@ class InputKeyMapPanel:
sub = split.column() sub = split.column()
subrow = sub.row(align=True) subrow = sub.row(align=True)
if map_type == 'KEYBOARD': if map_type in {'KEYBOARD', 'NDOF'}:
subrow.prop(kmi, "type", text="", event=True) subrow.prop(kmi, "type", text="", event=True)
subrow.prop(kmi, "value", text="") subrow.prop(kmi, "value", text="")
elif map_type == 'MOUSE': elif map_type == 'MOUSE':
@@ -352,10 +350,10 @@ class InputKeyMapPanel:
row.label() row.label()
row.label() row.label()
if km.is_user_defined: if km.is_user_modified:
row.operator("wm.keymap_restore", text=_("Restore")) row.operator("wm.keymap_restore", text=_("Restore"))
else: else:
row.operator("wm.keymap_edit", text=_("Edit")) row.label()
for kmi in filtered_items: for kmi in filtered_items:
self.draw_kmi(display_keymaps, kc, km, kmi, col, 1) self.draw_kmi(display_keymaps, kc, km, kmi, col, 1)
@@ -363,7 +361,6 @@ class InputKeyMapPanel:
# "Add New" at end of keymap item list # "Add New" at end of keymap item list
col = self.indented_layout(layout, 1) col = self.indented_layout(layout, 1)
subcol = col.split(percentage=0.2).column() subcol = col.split(percentage=0.2).column()
subcol.enabled = km.is_user_defined
subcol.operator("wm.keyitem_add", text=_("Add New"), icon='ZOOMIN') subcol.operator("wm.keyitem_add", text=_("Add New"), icon='ZOOMIN')
def draw_hierarchy(self, display_keymaps, layout): def draw_hierarchy(self, display_keymaps, layout):
@@ -372,8 +369,7 @@ class InputKeyMapPanel:
def draw_keymaps(self, context, layout): def draw_keymaps(self, context, layout):
wm = context.window_manager wm = context.window_manager
kc = wm.keyconfigs.active kc = wm.keyconfigs.user
defkc = wm.keyconfigs.default
col = layout.column() col = layout.column()
sub = col.column() sub = col.column()
@@ -398,7 +394,7 @@ class InputKeyMapPanel:
col.separator() col.separator()
display_keymaps = _merge_keymaps(kc, defkc) display_keymaps = _merge_keymaps(kc, kc)
if context.space_data.filter_text != "": if context.space_data.filter_text != "":
filter_text = context.space_data.filter_text.lower() filter_text = context.space_data.filter_text.lower()
self.draw_filtered(display_keymaps, filter_text, col) self.draw_filtered(display_keymaps, filter_text, col)
@@ -550,22 +546,24 @@ class WM_OT_keyconfig_import(bpy.types.Operator):
def execute(self, context): def execute(self, context):
from os.path import basename from os.path import basename
import shutil import shutil
if not self.filepath:
raise Exception("Filepath not set")
f = open(self.filepath, "r") if not self.filepath:
if not f: self.report({'ERROR'}, "Filepath not set")
raise Exception("Could not open file") return {'CANCELLED'}
config_name = basename(self.filepath) config_name = basename(self.filepath)
path = bpy.utils.user_resource('SCRIPTS', os.path.join("presets", "keyconfig"), create=True) path = bpy.utils.user_resource('SCRIPTS', os.path.join("presets", "keyconfig"), create=True)
path = os.path.join(path, config_name) path = os.path.join(path, config_name)
try:
if self.keep_original: if self.keep_original:
shutil.copy(self.filepath, path) shutil.copy(self.filepath, path)
else: else:
shutil.move(self.filepath, path) shutil.move(self.filepath, path)
except Exception as e:
self.report({'ERROR'}, "Installing keymap failed: %s" % e)
return {'CANCELLED'}
# sneaky way to check we're actually running the code. # sneaky way to check we're actually running the code.
bpy.utils.keyconfig_set(path) bpy.utils.keyconfig_set(path)
@@ -595,6 +593,9 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
if not self.filepath: if not self.filepath:
raise Exception("Filepath not set") raise Exception("Filepath not set")
if not self.filepath.endswith('.py'):
self.filepath += '.py'
f = open(self.filepath, "w") f = open(self.filepath, "w")
if not f: if not f:
raise Exception("Could not open file") raise Exception("Could not open file")
@@ -609,7 +610,7 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
# Generate a list of keymaps to export: # Generate a list of keymaps to export:
# #
# First add all user_defined keymaps (found in inputs.edited_keymaps list), # First add all user_modified keymaps (found in keyconfigs.user.keymaps list),
# then add all remaining keymaps from the currently active custom keyconfig. # then add all remaining keymaps from the currently active custom keyconfig.
# #
# This will create a final list of keymaps that can be used as a 'diff' against # This will create a final list of keymaps that can be used as a 'diff' against
@@ -619,7 +620,9 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
class FakeKeyConfig(): class FakeKeyConfig():
keymaps = [] keymaps = []
edited_kc = FakeKeyConfig() edited_kc = FakeKeyConfig()
edited_kc.keymaps.extend(context.user_preferences.inputs.edited_keymaps) for km in wm.keyconfigs.user.keymaps:
if km.is_user_modified:
edited_kc.keymaps.append(km)
# merge edited keymaps with non-default keyconfig, if it exists # merge edited keymaps with non-default keyconfig, if it exists
if kc != wm.keyconfigs.default: if kc != wm.keyconfigs.default:
export_keymaps = _merge_keymaps(edited_kc, kc) export_keymaps = _merge_keymaps(edited_kc, kc)
@@ -669,18 +672,6 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
class WM_OT_keymap_edit(bpy.types.Operator):
"Edit stored key map"
bl_idname = "wm.keymap_edit"
bl_label = _("Edit Key Map")
__doc__ = _("Edit stored key map")
def execute(self, context):
km = context.keymap
km.copy_to_user()
return {'FINISHED'}
class WM_OT_keymap_restore(bpy.types.Operator): class WM_OT_keymap_restore(bpy.types.Operator):
"Restore key map(s)" "Restore key map(s)"
bl_idname = "wm.keymap_restore" bl_idname = "wm.keymap_restore"
@@ -693,7 +684,7 @@ class WM_OT_keymap_restore(bpy.types.Operator):
wm = context.window_manager wm = context.window_manager
if self.all: if self.all:
for km in wm.keyconfigs.default.keymaps: for km in wm.keyconfigs.user.keymaps:
km.restore_to_default() km.restore_to_default()
else: else:
km = context.keymap km = context.keymap
@@ -713,13 +704,13 @@ class WM_OT_keyitem_restore(bpy.types.Operator):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
keymap = getattr(context, "keymap", None) keymap = getattr(context, "keymap", None)
return keymap and keymap.is_user_defined return keymap
def execute(self, context): def execute(self, context):
km = context.keymap km = context.keymap
kmi = km.keymap_items.from_id(self.item_id) kmi = km.keymap_items.from_id(self.item_id)
if not kmi.is_user_defined: if (not kmi.is_user_defined) and kmi.is_user_modified:
km.restore_item_to_default(kmi) km.restore_item_to_default(kmi)
return {'FINISHED'} return {'FINISHED'}
@@ -758,7 +749,7 @@ class WM_OT_keyitem_remove(bpy.types.Operator):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
return hasattr(context, "keymap") and context.keymap.is_user_defined return hasattr(context, "keymap")
def execute(self, context): def execute(self, context):
km = context.keymap km = context.keymap

View File

@@ -59,6 +59,7 @@ def draw_gpencil_tools(context, layout):
row = col.row() row = col.row()
row.prop(context.tool_settings, "use_grease_pencil_sessions") row.prop(context.tool_settings, "use_grease_pencil_sessions")
# ********** default tools for objectmode **************** # ********** default tools for objectmode ****************
class VIEW3D_PT_tools_objectmode(View3DPanel, bpy.types.Panel): class VIEW3D_PT_tools_objectmode(View3DPanel, bpy.types.Panel):
@@ -88,8 +89,9 @@ class VIEW3D_PT_tools_objectmode(View3DPanel, bpy.types.Panel):
col = layout.column(align=True) col = layout.column(align=True)
col.label(text=_("Shading:")) col.label(text=_("Shading:"))
col.operator("object.shade_smooth", text=_("Smooth")) row = col.row(align=True)
col.operator("object.shade_flat", text=_("Flat")) row.operator("object.shade_smooth", text=_("Smooth"))
row.operator("object.shade_flat", text=_("Flat"))
draw_keyframing_tools(context, layout) draw_keyframing_tools(context, layout)
@@ -155,8 +157,9 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, bpy.types.Panel):
col = layout.column(align=True) col = layout.column(align=True)
col.label(text="Shading:") col.label(text="Shading:")
col.operator("mesh.faces_shade_smooth", text="Smooth") row = col.row(align=True)
col.operator("mesh.faces_shade_flat", text="Flat") row.operator("mesh.faces_shade_smooth", text="Smooth")
row.operator("mesh.faces_shade_flat", text="Flat")
draw_repeat_tools(context, layout) draw_repeat_tools(context, layout)

View File

@@ -35,7 +35,7 @@ def add_object(self, context):
mesh.from_pydata(verts, edges, faces) mesh.from_pydata(verts, edges, faces)
# useful for development when the mesh may be invalid. # useful for development when the mesh may be invalid.
# mesh.validate(verbose=True) # mesh.validate(verbose=True)
add_object_data(context, mesh_data, operator=self) add_object_data(context, mesh, operator=self)
class OBJECT_OT_add_object(bpy.types.Operator, AddObjectHelper): class OBJECT_OT_add_object(bpy.types.Operator, AddObjectHelper):

0
release/scripts/templates/batch_export.py Executable file → Normal file
View File

View File

@@ -18,7 +18,7 @@ class ModalOperator(bpy.types.Operator):
elif event.type == 'LEFTMOUSE': elif event.type == 'LEFTMOUSE':
return {'FINISHED'} return {'FINISHED'}
elif event.type in ('RIGHTMOUSE', 'ESC'): elif event.type in {'RIGHTMOUSE', 'ESC'}:
context.object.location.x = self.first_value context.object.location.x = self.first_value
return {'CANCELLED'} return {'CANCELLED'}

View File

@@ -45,7 +45,7 @@ class ModalDrawOperator(bpy.types.Operator):
context.region.callback_remove(self._handle) context.region.callback_remove(self._handle)
return {'FINISHED'} return {'FINISHED'}
elif event.type in ('RIGHTMOUSE', 'ESC'): elif event.type in {'RIGHTMOUSE', 'ESC'}:
context.region.callback_remove(self._handle) context.region.callback_remove(self._handle)
return {'CANCELLED'} return {'CANCELLED'}

View File

@@ -29,7 +29,7 @@ class ViewOperator(bpy.types.Operator):
context.area.header_text_set() context.area.header_text_set()
return {'FINISHED'} return {'FINISHED'}
elif event.type in ('RIGHTMOUSE', 'ESC'): elif event.type in {'RIGHTMOUSE', 'ESC'}:
rv3d.view_location = self._initial_location rv3d.view_location = self._initial_location
context.area.header_text_set() context.area.header_text_set()
return {'CANCELLED'} return {'CANCELLED'}

0
release/scripts/templates/ui_menu.py Executable file → Normal file
View File

View File

@@ -12,22 +12,22 @@
</style> </style>
</head> </head>
<body> <body>
<p class="title"><b>Blender 2.58</b></p> <p class="title"><b>Blender 2.59</b></p>
<p><br></p> <p><br></p>
<p class="header"><b>About</b></p> <p class="header"><b>About</b></p>
<p class="body">Welcome to Blender, the free, open source 3D application for modeling, animation, rendering, compositing, video editing and game creation. Blender is available for Linux, Mac OS X, Windows, Solaris and FreeBSD and has a large world-wide community.</p> <p class="body">Welcome to Blender, the free, open source 3D application for modeling, animation, rendering, compositing, video editing and game creation. Blender is available for Linux, Mac OS X, Windows, Solaris and FreeBSD and has a large world-wide community.</p>
<p class="body">Blender can be used freely for any purpose, including commercial use and distribution. It's free and open-source software, released under the GNU GPL licence. The entire source code is available on our website.</p> <p class="body">Blender can be used freely for any purpose, including commercial use and distribution. It's free and open-source software, released under the GNU GPL licence. The entire source code is available on our website.</p>
<p class="body">For more information, visit <a href="http://www.blender.org">blender.org</a>.</p> <p class="body">For more information, visit <a href="http://www.blender.org">blender.org</a>.</p>
<p><br></p> <p><br></p>
<p class="header"><b>2.58</b></p> <p class="header"><b>2.59</b></p>
<p class="body">The Blender Foundation and online developer community is proud to present Blender 2.58. This release is the second official stable release of the Blender 2.5 series, and represents the culmination of many years of redesign and development work. <a href="http://www.blender.org/development/release-logs/blender-258/">More information about this release</a>.</p> <p class="body">The Blender Foundation and online developer community is proud to present Blender 2.59. This release is the third official stable release of the Blender 2.5 series, and represents the culmination of many years of redesign and development work. <a href="http://www.blender.org/development/release-logs/blender-259/">More information about this release</a>.</p>
<p class="body">What to Expect:</p> <p class="body">What to Expect:</p>
<p class="body"> • Big improvements - This is our most exciting version to date, already a significant improvement in many ways over 2.49</p> <p class="body"> • Big improvements - This is our most exciting version to date, already a significant improvement in many ways over 2.49</p>
<p class="body"> • Missing/Incomplete Features - Although most of it is there, not all functionality from pre-2.5 versions has been restored yet. Some functionality may be re-implemented a different way.</p> <p class="body"> • Missing/Incomplete Features - Although most of it is there, not all functionality from pre-2.5 versions has been restored yet. Some functionality may be re-implemented a different way.</p>
<p class="body"> • Changes - If you're used to the old Blenders, Blender 2.5 may seem quite different at first, but it won't be long before it grows on you even more than before.</p> <p class="body"> • Changes - If you're used to the old Blenders, Blender 2.5 may seem quite different at first, but it won't be long before it grows on you even more than before.</p>
<p><br></p> <p><br></p>
<p class="header"><b>Bugs</b></p> <p class="header"><b>Bugs</b></p>
<p class="body">Although Blender 2.58 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender 2.58. If it wasnt reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.</p> <p class="body">Although Blender 2.59 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender 2.59. If it wasnt reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.</p>
<p><br></p> <p><br></p>
<p class="header"><b>Package Contents</b></p> <p class="header"><b>Package Contents</b></p>
<p class="body">The downloaded Blender package includes:</p> <p class="body">The downloaded Blender package includes:</p>
@@ -51,11 +51,11 @@
<p class="header"><b>Links</b></p> <p class="header"><b>Links</b></p>
<p class="body">Users:</p> <p class="body">Users:</p>
<p class="body"> General information <a href="http://www.blender.org">www.blender.org</a> <br> <p class="body"> General information <a href="http://www.blender.org">www.blender.org</a> <br>
Full release log <a href="http://www.blender.org/development/release-logs/blender-258/">www.blender.org/development/release-logs/blender-258/</a><br> Full release log <a href="http://www.blender.org/development/release-logs/blender-259/">www.blender.org/development/release-logs/blender-259/</a><br>
Tutorials <a href="http://www.blender.org/education-help/">www.blender.org/education-help/</a> <br> Tutorials <a href="http://www.blender.org/education-help/">www.blender.org/education-help/</a> <br>
Manual <a href="http://wiki.blender.org/index.php/Doc:Manual">wiki.blender.org/index.php/Doc:Manual</a><br> Manual <a href="http://wiki.blender.org/index.php/Doc:Manual">wiki.blender.org/index.php/Doc:Manual</a><br>
User Forum <a href="http://www.blenderartists.org">www.blenderartists.org</a><br> User Forum <a href="http://www.blenderartists.org">www.blenderartists.org</a><br>
IRC <a href="irc://irc.freenode.net/#blender">#blender on irc.freenode.net</a><br> IRC <a href="irc://irc.freenode.net/#blenderchat">#blenderchat on irc.freenode.net</a><br>
</p> </p>
<p class="body">Developers:</p> <p class="body">Developers:</p>
<p class="body"> Development <a href="http://www.blender.org/development/">www.blender.org/development/</a><br> <p class="body"> Development <a href="http://www.blender.org/development/">www.blender.org/development/</a><br>

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