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)
# 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)
if(UNIX AND NOT APPLE)
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()
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
set(PLATFORM_LINKLIBS "-lutil -lc -lm -lpthread -lstdc++")
@@ -896,28 +910,15 @@ elseif(APPLE)
endif()
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
# 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_BINARY "${LIBDIR}/python/bin/python${PYTHON_VERSION}") # not used yet
set(PYTHON_LIBRARY python${PYTHON_VERSION})
set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}")
# 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
set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
@@ -972,7 +973,17 @@ elseif(APPLE)
set(SAMPLERATE_LIBPATH ${SAMPLERATE}/lib)
endif()
find_library(SYSTEMSTUBS_LIBRARY
NAMES
SystemStubs
PATHS
)
mark_as_advanced(SYSTEMSTUBS_LIBRARY)
if(SYSTEMSTUBS_LIBRARY)
set(PLATFORM_LINKLIBS stdc++ SystemStubs)
else()
set(PLATFORM_LINKLIBS stdc++)
endif()
if(WITH_COCOA)
set(PLATFORM_CFLAGS "-pipe -funsigned-char -DGHOST_COCOA")
@@ -987,9 +998,28 @@ elseif(APPLE)
elseif(WITH_CODEC_QUICKTIME)
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -framework QuickTime")
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()
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(WITH_INPUT_NDOF OFF) # unsupported
endif()
if(WITH_OPENCOLLADA)
@@ -1029,6 +1059,10 @@ elseif(APPLE)
set(TIFF_LIBPATH ${TIFF}/lib)
endif()
if (WITH_INPUT_NDOF)
# linker needs "-weak_framework 3DconnexionClient"
endif()
set(EXETYPE MACOSX_BUNDLE)
set(CMAKE_C_FLAGS_DEBUG "-fno-strict-aliasing -g")
@@ -1054,20 +1088,34 @@ if(APPLE OR WIN32)
endif()
endif()
# See TEST_SSE_SUPPORT() for how this is defined.
if(WITH_RAYOPTIMIZATION)
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)
set(PLATFORM_CFLAGS " -msse ${PLATFORM_CFLAGS}")
set(PLATFORM_CFLAGS " ${_sse} ${PLATFORM_CFLAGS}")
add_definitions(-D__SSE__ -D__MMX__)
endif()
if(SUPPORT_SSE2_BUILD)
set(PLATFORM_CFLAGS " -msse2 ${PLATFORM_CFLAGS}")
set(PLATFORM_CFLAGS " ${_sse2} ${PLATFORM_CFLAGS}")
add_definitions(-D__SSE2__)
if(NOT SUPPORT_SSE_BUILD) # dont double up
add_definitions(-D__MMX__)
endif()
endif()
endif()
unset(_sse)
unset(_sse2)
endif()
if(WITH_IMAGE_OPENJPEG)
@@ -1306,6 +1354,7 @@ if(FIRST_RUN)
info_cfg_option(WITH_OPENCOLLADA)
info_cfg_option(WITH_FFTW3)
info_cfg_option(WITH_INTERNATIONAL)
info_cfg_option(WITH_INPUT_NDOF)
info_cfg_text("Compiler Options:")
info_cfg_option(WITH_BUILDINFO)

View File

@@ -111,6 +111,11 @@ btools.print_targets(B.targets, B.bc)
# 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
quickie = B.arguments.get('BF_QUICK', 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_NO_ELBEEM'] = True
target_env_defs['WITH_BF_PYTHON'] = False
target_env_defs['WITH_BF_3DMOUSE'] = False
# Merge blenderlite, let command line to override
for k,v in target_env_defs.iteritems():
if k not in B.arguments:
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['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')
if env['WITH_BF_FFMPEG']:
dllsources += ['${BF_FFMPEG_LIBPATH}/avcodec-52.dll',
'${BF_FFMPEG_LIBPATH}/avformat-52.dll',
'${BF_FFMPEG_LIBPATH}/avdevice-52.dll',
'${BF_FFMPEG_LIBPATH}/avutil-50.dll',
'${BF_FFMPEG_LIBPATH}/swscale-0.dll']
dllsources += env['BF_FFMPEG_DLL'].split()
# Since the thumb handler is loaded by Explorer, architecture is
# 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_STATICFFMPEG = True
BF_FFMPEG = '/home/sources/staticlibs/ffmpeg'
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 ' + \
@@ -81,6 +81,12 @@ WITH_BF_STATICJEMALLOC = True
BF_JEMALLOC = '/home/sources/staticlibs/jemalloc'
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
BF_DEBUG = False
REL_CFLAGS = ['-O2']

View File

@@ -13,7 +13,18 @@ WITH_BF_STATICPYTHON = True
WITH_BF_COLLADA = False
# 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++
WITH_BF_STATICCXX = True
@@ -65,6 +76,12 @@ WITH_BF_STATICJEMALLOC = True
BF_JEMALLOC = '/home/sources/staticlibs/jemalloc'
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
BF_DEBUG = False
REL_CFLAGS = ['-O2']

View File

@@ -13,7 +13,18 @@ WITH_BF_STATICPYTHON = True
WITH_BF_COLLADA = False
# 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++
WITH_BF_STATICCXX = True
@@ -65,6 +76,12 @@ WITH_BF_STATICJEMALLOC = True
BF_JEMALLOC = '/home/sources/staticlibs/jemalloc'
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
BF_DEBUG = False
REL_CFLAGS = ['-O2']

View File

@@ -22,7 +22,7 @@ BF_EXPAT_LIB = ''
WITH_BF_FFMPEG = 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_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 ' + \
@@ -81,6 +81,12 @@ WITH_BF_STATICJEMALLOC = True
BF_JEMALLOC = '/home/sources/staticlibs/jemalloc'
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
BF_DEBUG = False
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, 'win32_scons', 'windows', generic_builder)
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_x86_64_cmake', '', generic_builder)

View File

@@ -108,5 +108,33 @@ else:
sys.exit(0)
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)
sys.exit(retcode)

View File

@@ -72,6 +72,34 @@ if builder.find('scons') != -1:
retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options)
sys.exit(retcode)
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)
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
"""
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
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
"""
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 sys

View File

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

View File

@@ -21,14 +21,23 @@ cmd = 'uname -p'
MAC_PROC=commands.getoutput(cmd)
cmd = 'uname -r'
cmd_res=commands.getoutput(cmd)
if cmd_res[0]=='7':
if cmd_res[:1]=='7':
MAC_CUR_VER='10.3'
elif cmd_res[0]=='8':
elif cmd_res[:1]=='8':
MAC_CUR_VER='10.4'
elif cmd_res[0]=='9':
elif cmd_res[:1]=='9':
MAC_CUR_VER='10.5'
elif cmd_res[0]=='10':
elif cmd_res[:2]=='10':
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':
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
# Can be customized
if MACOSX_ARCHITECTURE == 'ppc':
# ppc release are now made for 10.4
if MACOSX_ARCHITECTURE == 'ppc' and MAC_CUR_VER == '10.4':
# all releases are now made for 10.5 !
# MAC_MIN_VERS = '10.3'
# MACOSX_SDK='/Developer/SDKs/MacOSX10.3.9.sdk'
# LCGDIR = '#../lib/darwin-6.1-powerpc'
@@ -50,7 +59,7 @@ if MACOSX_ARCHITECTURE == 'ppc':
LCGDIR = '#../lib/darwin-8.0.0-powerpc'
CC = 'gcc-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'
MACOSX_DEPLOYMENT_TARGET = '10.4'
MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
@@ -58,12 +67,22 @@ elif MACOSX_ARCHITECTURE == 'i386':
CC = 'gcc-4.0'
CXX = 'g++-4.0'
else :
if 'Mac OS X 10.5' in MACOSX_SDK_CHECK:
# OSX 10.5/6 with Xcode 3.x
MAC_MIN_VERS = '10.5'
MACOSX_DEPLOYMENT_TARGET = '10.5'
MACOSX_SDK='/Developer/SDKs/MacOSX10.5.sdk'
LCGDIR = '#../lib/darwin-9.x.universal'
CC = 'gcc-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}'
@@ -71,8 +90,8 @@ LIBDIR = '${LCGDIR}'
################### Dependency settings ##################
#############################################################################
#Defaults openMP to true if compiler (currently only gcc 4.2) handles it
if CC == 'gcc-4.2':
#Defaults openMP to true if compiler handles it
if CC == 'gcc-4.2' or CC == 'llvm-gcc-4.2':
WITH_BF_OPENMP = True # multithreading for fluids, cloth and smoke
else:
WITH_BF_OPENMP = False
@@ -189,7 +208,7 @@ BF_GETTEXT_LIB = 'intl'
BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = False
WITH_BF_PLAYER = True
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'
@@ -240,7 +259,7 @@ BF_OPENGL_LIBPATH = '/System/Library/Frameworks/OpenGL.framework/Libraries'
BF_OPENGL_LINKFLAGS = ['-framework', 'OpenGL']
#OpenCollada flags
WITH_BF_COLLADA = False
WITH_BF_COLLADA = True
BF_COLLADA = '#source/blender/collada'
BF_COLLADA_INC = '${BF_COLLADA}'
BF_COLLADA_LIB = 'bf_collada'
@@ -265,6 +284,8 @@ if MACOSX_ARCHITECTURE == 'i386':
elif MACOSX_ARCHITECTURE == 'x86_64':
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-msse2']
# SpaceNavigator and related 3D mice
WITH_BF_3DMOUSE = True
#############################################################################
################### various compile settings and flags ##################
@@ -283,28 +304,31 @@ CPPFLAGS = []+ARCH_FLAGS
CCFLAGS = ['-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
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
if WITH_BF_QUICKTIME == True:
if USE_QTKIT == True:
if WITH_BF_QUICKTIME:
if USE_QTKIT:
PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QTKit']
else:
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
LLIBS = ['stdc++', 'SystemStubs']
# some flags shuffling for different Os versions
# some flags shuffling for different OS versions
if MAC_MIN_VERS == '10.3':
CFLAGS = ['-fuse-cxa-atexit']+CFLAGS
CXXFLAGS = ['-fuse-cxa-atexit']+CXXFLAGS
PLATFORM_LINKFLAGS = ['-fuse-cxa-atexit']+PLATFORM_LINKFLAGS
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]
PLATFORM_LINKFLAGS = ['-mmacosx-version-min='+MAC_MIN_VERS,'-Wl','-isysroot',MACOSX_SDK,'-arch',MACOSX_ARCHITECTURE]+PLATFORM_LINKFLAGS
CCFLAGS=SDK_FLAGS+CCFLAGS

View File

@@ -192,6 +192,14 @@ WITH_BF_OPENMP = True
WITH_BF_RAYOPTIMIZATION = True
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'
CXX = 'g++'

View File

@@ -7,6 +7,7 @@ BF_FFMPEG = LIBDIR +'/ffmpeg'
BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}/include/msvc'
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_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_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_LIBPATH = '${BF_OPENCOLLADA}/lib'
WITH_BF_3DMOUSE = True
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
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_LIBPATH='${BF_FFMPEG}/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_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_LIBPATH = '${BF_OPENCOLLADA}/lib'
WITH_BF_3DMOUSE = True
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE','/arch:SSE2']

View File

@@ -206,6 +206,12 @@ def setup_staticlibs(lenv):
if lenv['WITH_BF_STATICJEMALLOC']:
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
def setup_syslibs(lenv):
@@ -271,6 +277,11 @@ def setup_syslibs(lenv):
if not lenv['WITH_BF_STATICJEMALLOC']:
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']
return syslibs

View File

@@ -87,7 +87,7 @@ def validate_arguments(args, bc):
'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_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_OGG', 'BF_OGG', 'BF_OGG_LIB',
'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',
'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',
'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
@@ -149,7 +149,7 @@ def validate_arguments(args, bc):
'BF_PROFILE_CFLAGS', 'BF_PROFILE_CCFLAGS', 'BF_PROFILE_CXXFLAGS', 'BF_PROFILE_LINKFLAGS',
'BF_DEBUG_CFLAGS', 'BF_DEBUG_CCFLAGS', 'BF_DEBUG_CXXFLAGS',
'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_PRIORITYLIST', 'BF_BUILDINFO','CC', 'CXX', 'BF_QUICKDEBUG',
'BF_LISTDEBUG', 'LCGDIR', 'BF_X264_CONFIG', 'BF_XVIDCORE_CONFIG',
'BF_UNIT_TEST']
'BF_UNIT_TEST', 'BF_BITNESS']
okdict = {}
@@ -291,6 +291,7 @@ def read_opts(env, cfg, args):
(BoolVariable('WITH_BF_FFMPEG', 'Use FFMPEG if true', False)),
('BF_FFMPEG', 'FFMPEG base path', ''),
('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_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_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', []),
('CCFLAGS', 'Generic C and C++ flags', []),
('CXXFLAGS', 'C++ only flags', []),
@@ -453,6 +463,8 @@ def read_opts(env, cfg, args):
('LLIBS', 'Platform libs', []),
('PLATFORM_LINKFLAGS', 'Platform linkflags', []),
('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)),
('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
# 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
# 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 %}
/* 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 */
/*
div.related {

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

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 texture
def createTexture(cont):
"""Create a new Dynamic Texture"""
object = cont.owner
@@ -29,6 +30,7 @@ def createTexture(cont):
logic.texture.source = new_source
logic.texture.refresh(False)
def removeTexture(cont):
"""Delete the Dynamic Texture, reversing back the final to its original state."""
try:

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

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

@@ -1,6 +1,7 @@
"""
Hello World Text Example
++++++++++++++++++++++++
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.
"""
@@ -11,6 +12,7 @@ from bge import logic
import bgl
import blf
def init():
"""init function - runs once"""
# create a new font object, use external ttf file
@@ -22,6 +24,7 @@ def init():
scene = logic.getCurrentScene()
scene.post_draw = [write]
def write():
"""write on screen"""
width = render.getWindowWidth()

234
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::
This documentation is still very weak, and needs some help!
.. module:: bge.constraints
.. 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.
:arg obj1: first object on Constraint
:type obj1: :class:'bge.types.KX_GameObject' #I think, there is no error when I use one
:arg physicsid: the physics id of the first object in constraint
:type physicsid: int
:arg obj2: second object on Constraint
:type obj2: :class:'bge.types.KX_GameObject' #too
:arg physicsid2: the physics id of the second object in constraint
:type physicsid2: int
:arg restLength: #to be filled
:type restLength: float
:arg constrainttype: the type of the constraint. The constraint types are:
:arg restitution: #to be filled
:type restitution: float
- :class:`POINTTOPOINT_CONSTRAINT`
- :class:`LINEHINGE_CONSTRAINT`
- :class:`ANGULAR_CONSTRAINT`
- :class:`CONETWIST_CONSTRAINT`
- :class:`VEHICLE_CONSTRAINT`
:arg damping: #to be filled
:type damping: float
:type constrainttype: int
: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
@@ -49,7 +72,7 @@ Game Engine bge.constraints Module
:type constraintId: int
:return: a vehicle constraint object.
:rtype: :class:'KX_VehicleWrapper'
:rtype: :class:`bge.types.KX_VehicleWrapper`
.. function:: removeConstraint(constraintId)
@@ -63,7 +86,7 @@ Game Engine bge.constraints Module
.. note::
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.
:type ccdMode: int
@@ -73,21 +96,21 @@ Game Engine bge.constraints Module
.. note::
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.
:type breakingTreshold: float
.. function:: setDeactivationAngularTreshold(angularTreshold)
Sets the deactivation angular treshold.
Sets the angular velocity treshold.
:arg angularTreshold: New deactivation angular treshold.
:type angularTreshold: float
.. function:: setDeactivationLinearTreshold(linearTreshold)
Sets the deactivation linear treshold.
Sets the linear velocity treshold.
:arg linearTreshold: New deactivation linear treshold.
:type linearTreshold: float
@@ -104,21 +127,20 @@ Game Engine bge.constraints Module
Sets the debug mode.
Debug modes:
- No debug: 0
- Draw wireframe: 1
- Draw Aabb: 2 #What's Aabb?
- Draw freatures text: 4
- Draw contact points: 8
- No deactivation: 16
- No help text: 32
- Draw text: 64
- Profile timings: 128
- Enable sat comparision: 256
- Disable Bullet LCP: 512
- Enable CCD: 1024
- Draw Constraints: #(1 << 11) = ?
- Draw Constraint Limits: #(1 << 12) = ?
- Fast Wireframe: #(1 << 13) = ?
- :class:`DBG_NODEBUG`
- :class:`DBG_DRAWWIREFRAME`
- :class:`DBG_DRAWAABB`
- :class:`DBG_DRAWFREATURESTEXT`
- :class:`DBG_DRAWCONTACTPOINTS`
- :class:`DBG_NOHELPTEXT`
- :class:`DBG_DRAWTEXT`
- :class:`DBG_PROFILETIMINGS`
- :class:`DBG_ENABLESATCOMPARISION`
- :class:`DBG_DISABLEBULLETLCP`
- :class:`DBG_ENABLECCD`
- :class:`DBG_DRAWCONSTRAINTS`
- :class:`DBG_DRAWCONSTRAINTLIMITS`
- :class:`DBG_FASTWIREFRAME`
:arg mode: The new debug mode.
:type mode: int
@@ -138,8 +160,11 @@ Game Engine bge.constraints Module
.. function:: setLinearAirDamping(damping)
.. note::
Not implemented.
Sets the linear air damping for rigidbodies.
.. function:: setNumIterations(numiter)
Sets the number of iterations for an iterative constraint solver.
@@ -159,7 +184,7 @@ Game Engine bge.constraints Module
.. note::
Very experimental, not recommended
Sets the solver damping.
Sets the damper constant of a penalty based solver.
:arg damping: New damping for the solver.
:type damping: float
@@ -169,7 +194,7 @@ Game Engine bge.constraints Module
.. note::
Very experimental, not recommended
Sets the solver tau.
Sets the spring constant of a penalty based solver.
:arg tau: New tau for the solver.
:type tau: float
@@ -189,7 +214,7 @@ Game Engine bge.constraints Module
.. note::
Very experimental, not recommended
Sets the sor constant.
Sets the successive overrelaxation constant.
:arg sor: New sor value.
:type sor: float
@@ -197,3 +222,136 @@ Game Engine bge.constraints Module
.. function:: setUseEpa(epa)
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

View File

@@ -1,6 +1,7 @@
Game Engine bge.logic Module
============================
Game Logic (bge.logic)
======================
*****
Intro
*****
@@ -216,6 +217,12 @@ General functions
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
:type name: string
:arg overlay: Overlay or underlay (optional)

View File

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

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

@@ -1,10 +1,6 @@
Game Engine bge.texture Module
==============================
.. 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.
Video Texture (bge.texture)
===========================
*****
Intro
@@ -40,6 +36,10 @@ When the texture object is deleted, the new texture is deleted and the old textu
.. 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])
FFmpeg video source

View File

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

12
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
@@ -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>`_
:type mode: Enumerated constant
:arg mode: Specifies the primitive that will be create from vertices between glBegin and
glEnd.
:arg mode: Specifies the primitive that will be create from vertices between
glBegin and glEnd.
.. function:: glBindTexture(target, texture):
@@ -1848,10 +1848,13 @@ class Buffer:
.. code-block:: python
import bgl
myByteBuffer = bgl.Buffer(bgl.GL_BYTE, [32, 32])
bgl.glGetPolygonStipple(myByteBuffer)
print(myByteBuffer.dimensions)
print(myByteBuffer.to_list())
sliceBuffer = myByteBuffer[0:16]
print(sliceBuffer)
@@ -1886,4 +1889,3 @@ class Buffer:
the Buffer. If a template is not passed in all fields will be initialized to 0.
:rtype: Buffer object
:return: The newly created buffer as a PyObject.

View File

@@ -416,6 +416,7 @@ def pymodule2sphinx(BASEPATH, module_name, module, title):
del key, descr
classes = []
submodules = []
for attribute in module_dir:
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)
elif value_type == type:
classes.append((attribute, value))
elif issubclass(value_type, types.ModuleType):
submodules.append((attribute, value))
elif value_type in (bool, int, float, str, tuple):
# constant, not much fun we can do here except to list it.
# 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)
fw("\n")
else:
print("\tnot documenting %s.%s" % (module_name, attribute))
print("\tnot documenting %s.%s of %r type" % (module_name, attribute, value_type.__name__))
continue
attribute_set.add(attribute)
# 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
for (type_name, value) in classes:
# May need to be its own function

View File

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

View File

@@ -289,21 +289,6 @@ extern GHOST_TSuccess GHOST_SetProgressBar(GHOST_WindowHandle windowhandle, floa
*/
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
***************************************************************************************/

View File

@@ -298,22 +298,6 @@ public:
*/
virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer* consumer) = 0;
/***************************************************************************************
** N-degree of freedom device management functionality
***************************************************************************************/
/**
* Starts the N-degree of freedom device manager
*/
virtual int openNDOF(GHOST_IWindow*,
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen
// original patch only
// GHOST_NDOFEventHandler_fp setNdofEventHandler
) = 0;
/***************************************************************************************
** Cursor management functionality
***************************************************************************************/

View File

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

View File

@@ -11,7 +11,7 @@ if window_system == 'darwin':
sources += env.Glob('intern/*.mm')
pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_SystemPaths', 'GHOST_Window', 'GHOST_DropTarget']
pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_SystemPaths', 'GHOST_Window', 'GHOST_DropTarget', 'GHOST_NDOFManager']
defs=['_USE_MATH_DEFINES']
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:
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'):
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_IWindow* window = (GHOST_IWindow*) windowhandle;

View File

@@ -35,8 +35,11 @@
#include "GHOST_DisplayManagerWin32.h"
#include "GHOST_Debug.h"
// We do not support multiple monitors at the moment
#define _WIN32_WINNT 0x501 // require Windows XP or newer
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// We do not support multiple monitors at the moment
#define COMPILE_MULTIMON_STUBS
#ifndef FREE_WINDOWS
#include <multimon.h>

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,6 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): none yet.
* Contributor(s):
* Mike Erwin
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file ghost/intern/GHOST_NDOFManager.cpp
* \ingroup GHOST
*/
#include <stdio.h> /* just for printf */
#include "GHOST_Debug.h"
#include "GHOST_NDOFManager.h"
#include "GHOST_EventNDOF.h"
#include "GHOST_EventKey.h"
#include "GHOST_WindowManager.h"
#include <string.h> // for memory functions
#include <stdio.h> // for error/info reporting
#include <math.h>
// the variable is outside the class because it must be accessed from plugin
static volatile GHOST_TEventNDOFData currentNdofValues = {0,0,0,0,0,0,0,0,0,0,0};
#if !defined(_WIN32) && !defined(__APPLE__)
#include "GHOST_SystemX11.h"
#ifdef DEBUG_NDOF_MOTION
// printable version of each GHOST_TProgress value
static const char* progress_string[] =
{"not started","starting","in progress","finishing","finished"};
#endif
namespace
{
GHOST_NDOFLibraryInit_fp ndofLibraryInit = 0;
GHOST_NDOFLibraryShutdown_fp ndofLibraryShutdown = 0;
GHOST_NDOFDeviceOpen_fp ndofDeviceOpen = 0;
}
GHOST_NDOFManager::GHOST_NDOFManager()
{
m_DeviceHandle = 0;
// discover the API from the plugin
ndofLibraryInit = 0;
ndofLibraryShutdown = 0;
ndofDeviceOpen = 0;
}
GHOST_NDOFManager::~GHOST_NDOFManager()
{
if (ndofLibraryShutdown)
ndofLibraryShutdown(m_DeviceHandle);
m_DeviceHandle = 0;
}
int
GHOST_NDOFManager::deviceOpen(GHOST_IWindow* window,
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen)
{
int Pid;
ndofLibraryInit = setNdofLibraryInit;
ndofLibraryShutdown = setNdofLibraryShutdown;
ndofDeviceOpen = setNdofDeviceOpen;
if (ndofLibraryInit && ndofDeviceOpen)
{
Pid= ndofLibraryInit();
#if 0
printf("%i client \n", Pid);
#ifdef DEBUG_NDOF_BUTTONS
static const char* ndof_button_names[] = {
// used internally, never sent
"NDOF_BUTTON_NONE",
// these two are available from any 3Dconnexion device
"NDOF_BUTTON_MENU",
"NDOF_BUTTON_FIT",
// standard views
"NDOF_BUTTON_TOP",
"NDOF_BUTTON_BOTTOM",
"NDOF_BUTTON_LEFT",
"NDOF_BUTTON_RIGHT",
"NDOF_BUTTON_FRONT",
"NDOF_BUTTON_BACK",
// more views
"NDOF_BUTTON_ISO1",
"NDOF_BUTTON_ISO2",
// 90 degree rotations
"NDOF_BUTTON_ROLL_CW",
"NDOF_BUTTON_ROLL_CCW",
"NDOF_BUTTON_SPIN_CW",
"NDOF_BUTTON_SPIN_CCW",
"NDOF_BUTTON_TILT_CW",
"NDOF_BUTTON_TILT_CCW",
// device control
"NDOF_BUTTON_ROTATE",
"NDOF_BUTTON_PANZOOM",
"NDOF_BUTTON_DOMINANT",
"NDOF_BUTTON_PLUS",
"NDOF_BUTTON_MINUS",
// general-purpose buttons
"NDOF_BUTTON_1",
"NDOF_BUTTON_2",
"NDOF_BUTTON_3",
"NDOF_BUTTON_4",
"NDOF_BUTTON_5",
"NDOF_BUTTON_6",
"NDOF_BUTTON_7",
"NDOF_BUTTON_8",
"NDOF_BUTTON_9",
"NDOF_BUTTON_10",
};
#endif
#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);
static const NDOF_ButtonT SpaceNavigator_HID_map[] = {
NDOF_BUTTON_MENU,
NDOF_BUTTON_FIT
};
static const NDOF_ButtonT SpaceExplorer_HID_map[] = {
NDOF_BUTTON_1,
NDOF_BUTTON_2,
NDOF_BUTTON_TOP,
NDOF_BUTTON_LEFT,
NDOF_BUTTON_RIGHT,
NDOF_BUTTON_FRONT,
NDOF_BUTTON_NONE, // esc key
NDOF_BUTTON_NONE, // alt key
NDOF_BUTTON_NONE, // shift key
NDOF_BUTTON_NONE, // ctrl key
NDOF_BUTTON_FIT,
NDOF_BUTTON_MENU,
NDOF_BUTTON_PLUS,
NDOF_BUTTON_MINUS,
NDOF_BUTTON_ROTATE
};
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)
{
// 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
return (Pid > 0) ? 0 : 1;
} else
return 1;
}
bool
GHOST_NDOFManager::available() const
{
return m_DeviceHandle != 0;
}
bool
GHOST_NDOFManager::event_present() const
{
if( currentNdofValues.changed >0) {
printf("time %llu but%u x%i y%i z%i rx%i ry%i rz%i \n" ,
currentNdofValues.time, currentNdofValues.buttons,
currentNdofValues.tx,currentNdofValues.ty,currentNdofValues.tz,
currentNdofValues.rx,currentNdofValues.ry,currentNdofValues.rz);
return true;
}else
}
}
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;
m_motionEventPending = false; // any pending motion is handled right now
GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow();
if (window == NULL) {
return false; // delivery will fail, so don't bother sending
}
void GHOST_NDOFManager::GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const
{
datas.tx = currentNdofValues.tx;
datas.ty = currentNdofValues.ty;
datas.tz = currentNdofValues.tz;
datas.rx = currentNdofValues.rx;
datas.ry = currentNdofValues.ry;
datas.rz = currentNdofValues.rz;
datas.buttons = currentNdofValues.buttons;
datas.client = currentNdofValues.client;
datas.address = currentNdofValues.address;
datas.time = currentNdofValues.time;
datas.delta = currentNdofValues.delta;
GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, window);
GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData();
// scale axis values here to normalize them to around +/- 1
// they are scaled again for overall sensitivity in the WM based on user prefs
const float scale = 1.f / 350.f; // 3Dconnexion devices send +/- 350 usually
data->tx = scale * m_translation[0];
data->ty = scale * m_translation[1];
data->tz = scale * m_translation[2];
data->rx = scale * m_rotation[0];
data->ry = scale * m_rotation[1];
data->rz = scale * m_rotation[2];
data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds
bool 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 *****
*
* 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,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): none yet.
* Contributor(s):
* Mike Erwin
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file ghost/intern/GHOST_NDOFManager.h
* \ingroup GHOST
*/
#ifndef _GHOST_NDOFMANAGER_H_
#define _GHOST_NDOFMANAGER_H_
#include "GHOST_System.h"
#include "GHOST_IWindow.h"
typedef enum {
NDOF_UnknownDevice, // <-- motion will work fine, buttons are ignored
// current devices
NDOF_SpaceNavigator,
NDOF_SpaceExplorer,
NDOF_SpacePilotPro,
// older devices
NDOF_SpacePilot
} NDOF_DeviceT;
// NDOF device button event types
typedef enum {
// used internally, never sent
NDOF_BUTTON_NONE,
// these two are available from any 3Dconnexion device
NDOF_BUTTON_MENU,
NDOF_BUTTON_FIT,
// standard views
NDOF_BUTTON_TOP,
NDOF_BUTTON_BOTTOM,
NDOF_BUTTON_LEFT,
NDOF_BUTTON_RIGHT,
NDOF_BUTTON_FRONT,
NDOF_BUTTON_BACK,
// more views
NDOF_BUTTON_ISO1,
NDOF_BUTTON_ISO2,
// 90 degree rotations
// these don't all correspond to physical buttons
NDOF_BUTTON_ROLL_CW,
NDOF_BUTTON_ROLL_CCW,
NDOF_BUTTON_SPIN_CW,
NDOF_BUTTON_SPIN_CCW,
NDOF_BUTTON_TILT_CW,
NDOF_BUTTON_TILT_CCW,
// device control
NDOF_BUTTON_ROTATE,
NDOF_BUTTON_PANZOOM,
NDOF_BUTTON_DOMINANT,
NDOF_BUTTON_PLUS,
NDOF_BUTTON_MINUS,
// general-purpose buttons
// users can assign functions via keymap editor
NDOF_BUTTON_1,
NDOF_BUTTON_2,
NDOF_BUTTON_3,
NDOF_BUTTON_4,
NDOF_BUTTON_5,
NDOF_BUTTON_6,
NDOF_BUTTON_7,
NDOF_BUTTON_8,
NDOF_BUTTON_9,
NDOF_BUTTON_10,
} NDOF_ButtonT;
class GHOST_NDOFManager
{
public:
GHOST_NDOFManager();
virtual ~GHOST_NDOFManager();
GHOST_NDOFManager(GHOST_System&);
int deviceOpen(GHOST_IWindow* window,
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen);
virtual ~GHOST_NDOFManager() {};
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;
bool event_present() const;
// each platform's device detection should call this
// use standard USB/HID identifiers
bool setDevice(unsigned short vendor_id, unsigned short product_id);
// filter out small/accidental/uncalibrated motions by
// setting up a "dead zone" around home position
// set to 0 to disable
// 0.1 is a safe and reasonable value
void setDeadZone(float);
// the latest raw axis data from the device
// NOTE: axis data should be in blender view coordinates
// +X is to the right
// +Y is up
// +Z is out of the screen
// for rotations, look from origin to each +axis
// rotations are + when CCW, - when CW
// each platform is responsible for getting axis data into this form
// these values should not be scaled (just shuffled or flipped)
void updateTranslation(short t[3], GHOST_TUns64 time);
void updateRotation(short r[3], GHOST_TUns64 time);
// the latest raw button data from the device
// use HID button encoding (not NDOF_ButtonT)
void updateButton(int button_number, bool press, GHOST_TUns64 time);
void updateButtons(int button_bits, GHOST_TUns64 time);
// NDOFButton events are sent immediately
// processes and sends most recent raw data as an NDOFMotion event
// returns whether an event was sent
bool sendMotionEvent();
protected:
void* m_DeviceHandle;
GHOST_System& m_system;
private:
void sendButtonEvent(NDOF_ButtonT, bool press, GHOST_TUns64 time, GHOST_IWindow*);
void sendKeyEvent(GHOST_TKey, bool press, GHOST_TUns64 time, GHOST_IWindow*);
NDOF_DeviceT m_deviceType;
int m_buttonCount;
int m_buttonMask;
short m_translation[3];
short m_rotation[3];
int m_buttons; // bit field
GHOST_TUns64 m_motionTime; // in milliseconds
GHOST_TUns64 m_prevMotionTime; // time of most recent Motion event sent
GHOST_TProgress m_motionState;
bool m_motionEventPending;
float m_deadZone; // discard motion with each component < this
};
#endif

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()
: m_displayManager(0), m_timerManager(0), m_windowManager(0), m_eventManager(0), m_ndofManager(0)
: m_displayManager(0),
m_timerManager(0),
m_windowManager(0),
m_eventManager(0)
#ifdef WITH_INPUT_NDOF
, m_ndofManager(0)
#endif
{
}
@@ -194,12 +200,17 @@ bool GHOST_System::getFullScreen(void)
bool GHOST_System::dispatchEvents()
{
bool handled;
if (m_eventManager) {
handled = m_eventManager->dispatchEvents();
bool handled = false;
#ifdef WITH_INPUT_NDOF
// NDOF Motion event is sent only once per dispatch, so do it now:
if (m_ndofManager) {
handled |= m_ndofManager->sendMotionEvent();
}
else {
handled = false;
#endif
if (m_eventManager) {
handled |= m_eventManager->dispatchEvents();
}
m_timerManager->fireTimers(getMilliSeconds());
@@ -243,18 +254,6 @@ GHOST_TSuccess GHOST_System::pushEvent(GHOST_IEvent* event)
return success;
}
int GHOST_System::openNDOF(GHOST_IWindow* w,
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen)
{
return m_ndofManager->deviceOpen(w,
setNdofLibraryInit,
setNdofLibraryShutdown,
setNdofDeviceOpen);
}
GHOST_TSuccess GHOST_System::getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const
{
GHOST_ModifierKeys keys;
@@ -285,12 +284,6 @@ GHOST_TSuccess GHOST_System::init()
m_timerManager = new GHOST_TimerManager ();
m_windowManager = new GHOST_WindowManager ();
m_eventManager = new GHOST_EventManager ();
m_ndofManager = new GHOST_NDOFManager();
#if 0
if(m_ndofManager)
printf("ndof manager \n");
#endif
#ifdef GHOST_DEBUG
if (m_eventManager) {
@@ -328,10 +321,12 @@ GHOST_TSuccess GHOST_System::exit()
delete m_eventManager;
m_eventManager = 0;
}
#ifdef WITH_INPUT_NDOF
if (m_ndofManager) {
delete m_ndofManager;
m_ndofManager = 0;
}
#endif
return GHOST_kSuccess;
}

View File

@@ -190,25 +190,6 @@ public:
*/
virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer* consumer);
/***************************************************************************************
** N-degree of freedom devcice management functionality
***************************************************************************************/
/** Inherited from GHOST_ISystem
* Opens the N-degree of freedom device manager
* return 0 if device found, 1 otherwise
*/
virtual int openNDOF(GHOST_IWindow* w,
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen);
// original patch only
// GHOST_NDOFEventHandler_fp setNdofEventHandler);
/***************************************************************************************
** Cursor management functionality
***************************************************************************************/
@@ -268,11 +249,13 @@ public:
*/
virtual inline GHOST_WindowManager* getWindowManager() const;
#ifdef WITH_INPUT_NDOF
/**
* Returns a pointer to our n-degree of freedeom manager.
* @return A pointer to our n-degree of freedeom manager.
*/
virtual inline GHOST_NDOFManager* getNDOFManager() const;
#endif
/**
* Returns the state of all modifier keys.
@@ -337,8 +320,10 @@ protected:
/** The event manager. */
GHOST_EventManager* m_eventManager;
#ifdef WITH_INPUT_NDOF
/** The N-degree of freedom device manager */
GHOST_NDOFManager* m_ndofManager;
#endif
/** Prints all the events. */
#ifdef GHOST_DEBUG
@@ -364,10 +349,12 @@ inline GHOST_WindowManager* GHOST_System::getWindowManager() const
return m_windowManager;
}
#ifdef WITH_INPUT_NDOF
inline GHOST_NDOFManager* GHOST_System::getNDOFManager() const
{
return m_ndofManager;
}
#endif
#endif // _GHOST_SYSTEM_H_

View File

@@ -220,6 +220,11 @@ public:
*/
GHOST_TSuccess handleApplicationBecomeActiveEvent();
/**
* External objects should call this when they send an event outside processEvents.
*/
void notifyExternalEventProcessed();
/**
* @see GHOST_ISystem
*/
@@ -267,7 +272,7 @@ protected:
/** Start time at initialization. */
GHOST_TUns64 m_start_time;
/** Event has been processed directly by Cocoa and has sent a ghost event to be dispatched */
/** Event has been processed directly by Cocoa (or NDOF manager) and has sent a ghost event to be dispatched */
bool m_outsideLoopEventProcessed;
/** Raised window is not yet known by the window manager, so delay application become active event handling */

View File

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

View File

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

View File

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

View File

@@ -43,7 +43,11 @@
#include <stdio.h> // for fprintf only
#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()
{
@@ -56,21 +60,12 @@ GHOST_SystemPathsX11::~GHOST_SystemPathsX11()
const GHOST_TUns8* GHOST_SystemPathsX11::getSystemDir() const
{
/* no prefix assumes a portable build which only uses bundled scripts */
#ifdef PREFIX
return (GHOST_TUns8*) PREFIX "/share";
#else
return NULL;
#endif
return (const GHOST_TUns8 *)static_path;
}
const GHOST_TUns8* GHOST_SystemPathsX11::getUserDir() const
{
const char* env = getenv("HOME");
if(env) {
return (GHOST_TUns8*) env;
} else {
return NULL;
}
return (const GHOST_TUns8 *)getenv("HOME");
}
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)) {
type= GHOST_TKey( key - SDL_SCANCODE_A + int(GHOST_kKeyA));
} else if ((key >= SDL_SCANCODE_1) && (key <= SDL_SCANCODE_0)) {
type= GHOST_TKey(key - SDL_SCANCODE_1 + int(GHOST_kKey0));
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)) {
type= GHOST_TKey(key - SDL_SCANCODE_F1 + int(GHOST_kKeyF1));
} 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_GRAVE, GHOST_kKeyAccentGrave);
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_BACKSLASH, GHOST_kKeyBackslash);
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_LALT, GHOST_kKeyLeftAlt);
GXMAP(type,SDL_SCANCODE_RALT, GHOST_kKeyRightAlt);
GXMAP(type,SDL_SCANCODE_LGUI, GHOST_kKeyOS);
GXMAP(type,SDL_SCANCODE_RGUI, GHOST_kKeyOS);
GXMAP(type,SDL_SCANCODE_INSERT, GHOST_kKeyInsert);
@@ -197,6 +200,7 @@ convertSDLKey(SDL_Scancode key)
GXMAP(type,SDL_SCANCODE_CAPSLOCK, GHOST_kKeyCapsLock);
GXMAP(type,SDL_SCANCODE_SCROLLLOCK, GHOST_kKeyScrollLock);
GXMAP(type,SDL_SCANCODE_NUMLOCKCLEAR, GHOST_kKeyNumLock);
GXMAP(type,SDL_SCANCODE_PRINTSCREEN, GHOST_kKeyPrintScreen);
/* keypad events */
@@ -228,6 +232,7 @@ convertSDLKey(SDL_Scancode key)
GXMAP(type,SDL_SCANCODE_AUDIONEXT, GHOST_kKeyMediaLast);
default:
printf("Unknown\n");
type= GHOST_kKeyUnknown;
break;
}
@@ -372,6 +377,7 @@ GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
case SDL_KEYUP:
{
SDL_KeyboardEvent &sdl_sub_evt= sdl_event->key;
SDL_Keycode sym= sdl_sub_evt.keysym.sym;
GHOST_TEventType type= (sdl_sub_evt.state == SDL_PRESSED) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID));
@@ -379,7 +385,45 @@ GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
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 */
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;
}

View File

@@ -39,22 +39,20 @@
* @date May 7, 2001
*/
#ifdef BF_GHOST_DEBUG
#include <iostream>
#ifdef FREE_WINDOWS
# define WINVER 0x0501 /* GetConsoleWindow() for MinGW */
#endif
#include <stdio.h> // [mce] temporary debug, remove soon!
#include "GHOST_SystemWin32.h"
#include "GHOST_EventDragnDrop.h"
#define WIN32_LEAN_AND_MEAN
#ifdef _WIN32_IE
#undef _WIN32_IE
#ifndef _WIN32_IE
#define _WIN32_IE 0x0501 /* shipped before XP, so doesn't impose additional requirements */
#endif
#define _WIN32_IE 0x0501
#include <windows.h>
#include <shlobj.h>
#include <tlhelp32.h>
// win64 doesn't define GWL_USERDATA
#ifdef WIN32
@@ -64,48 +62,19 @@
#endif
#endif
/*
* According to the docs the mouse wheel message is supported from windows 98
* upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the
* wheel detent value are undefined.
*/
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x020A
#endif // WM_MOUSEWHEEL
#ifndef WHEEL_DELTA
#define WHEEL_DELTA 120 /* Value for rolling one detent, (old convention! MS changed it) */
#endif // WHEEL_DELTA
/*
* Defines for mouse buttons 4 and 5 aka xbutton1 and xbutton2.
* MSDN: Declared in Winuser.h, include Windows.h
* This does not seem to work with MinGW so we define our own here.
*/
#ifndef XBUTTON1
#define XBUTTON1 0x0001
#endif // XBUTTON1
#ifndef XBUTTON2
#define XBUTTON2 0x0002
#endif // XBUTTON2
#ifndef WM_XBUTTONUP
#define WM_XBUTTONUP 524
#endif // WM_XBUTTONUP
#ifndef WM_XBUTTONDOWN
#define WM_XBUTTONDOWN 523
#endif // WM_XBUTTONDOWN
#include "GHOST_Debug.h"
#include "GHOST_DisplayManagerWin32.h"
#include "GHOST_EventButton.h"
#include "GHOST_EventCursor.h"
#include "GHOST_EventKey.h"
#include "GHOST_EventWheel.h"
#include "GHOST_EventNDOF.h"
#include "GHOST_TimerTask.h"
#include "GHOST_TimerManager.h"
#include "GHOST_WindowManager.h"
#include "GHOST_WindowWin32.h"
#include "GHOST_NDOFManager.h"
#ifdef WITH_INPUT_NDOF
#include "GHOST_NDOFManagerWin32.h"
#endif
// Key code values not found in winuser.h
#ifndef VK_MINUS
@@ -158,18 +127,35 @@
#define VK_MEDIA_PLAY_PAUSE 0xB3
#endif // VK_MEDIA_PLAY_PAUSE
/*
Initiates WM_INPUT messages from keyboard
That way GHOST can retrieve true keys
*/
GHOST_TInt32 GHOST_SystemWin32::initKeyboardRawInput(void)
static void initRawInput()
{
RAWINPUTDEVICE device = {0};
device.usUsagePage = 0x01; /* usUsagePage & usUsage for keyboard*/
device.usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
#ifdef WITH_INPUT_NDOF
#define DEVICE_COUNT 2
#else
#define DEVICE_COUNT 1
#endif
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()
: m_hasPerformanceCounter(false), m_freq(0), m_start(0)
@@ -186,6 +172,10 @@ GHOST_SystemWin32::GHOST_SystemWin32()
this->handleKeyboardChange();
// Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32.
OleInitialize(0);
#ifdef WITH_INPUT_NDOF
m_ndofManager = new GHOST_NDOFManagerWin32(*this);
#endif
}
GHOST_SystemWin32::~GHOST_SystemWin32()
@@ -244,6 +234,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow(
// Store the pointer to the window
// if (state != GHOST_kWindowStateFullScreen) {
m_windowManager->addWindow(window);
m_windowManager->setActiveWindow(window);
// }
}
else {
@@ -384,22 +375,15 @@ GHOST_TSuccess GHOST_SystemWin32::init()
GHOST_TSuccess success = GHOST_System::init();
/* Disable scaling on high DPI displays on Vista */
HMODULE
user32 = ::LoadLibraryA("user32.dll");
typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)();
LPFNSETPROCESSDPIAWARE SetProcessDPIAware =
(LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware");
if (SetProcessDPIAware)
SetProcessDPIAware();
#ifdef NEED_RAW_PROC
pRegisterRawInputDevices = (LPFNDLLRRID)GetProcAddress(user32, "RegisterRawInputDevices");
pGetRawInputData = (LPFNDLLGRID)GetProcAddress(user32, "GetRawInputData");
#else
FreeLibrary(user32);
#endif
/* Initiates WM_INPUT messages from keyboard */
initKeyboardRawInput();
initRawInput();
// Determine whether this system has a high frequency performance counter. */
m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE;
@@ -440,41 +424,25 @@ GHOST_TSuccess GHOST_SystemWin32::init()
GHOST_TSuccess GHOST_SystemWin32::exit()
{
#ifdef NEED_RAW_PROC
FreeLibrary(user32);
#endif
return GHOST_System::exit();
}
GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, int * keyDown, char * vk)
GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int * keyDown, char * vk)
{
unsigned int size = 0;
char * data;
GHOST_TKey key = GHOST_kKeyUnknown;
if(!keyDown)
return GHOST_kKeyUnknown;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, 0, &size, sizeof(RAWINPUTHEADER));
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_ModifierKeys modifiers;
system->retrieveModifierKeys(modifiers);
*keyDown = !(ri.data.keyboard.Flags & RI_KEY_BREAK);
key = this->convertKey(window, ri.data.keyboard.VKey, ri.data.keyboard.MakeCode, (ri.data.keyboard.Flags&(RI_KEY_E1|RI_KEY_E0)));
*keyDown = !(raw.data.keyboard.Flags & RI_KEY_BREAK);
key = this->convertKey(window, raw.data.keyboard.VKey, raw.data.keyboard.MakeCode, (raw.data.keyboard.Flags&(RI_KEY_E1|RI_KEY_E0)));
// extra handling of modifier keys: don't send repeats out from GHOST
if(key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt)
@@ -533,11 +501,7 @@ GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, WPARAM wParam, LPAR
}
if(vk) *vk = ri.data.keyboard.VKey;
};
};
free(data);
if(vk) *vk = raw.data.keyboard.VKey;
return key;
}
@@ -741,12 +705,12 @@ GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WP
}
GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam)
GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINPUT const& raw)
{
int keyDown=0;
char vk;
GHOST_SystemWin32 * system = (GHOST_SystemWin32 *)getSystem();
GHOST_TKey key = system->hardKey(window, wParam, lParam, &keyDown, &vk);
GHOST_TKey key = system->hardKey(window, raw, &keyDown, &vk);
GHOST_EventKey* event;
if (key != GHOST_kKeyUnknown) {
char ascii = '\0';
@@ -776,7 +740,13 @@ GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, WPARAM
GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window)
{
return new GHOST_Event(getSystem()->getMilliSeconds(), type, window);
GHOST_System* system = (GHOST_System*)getSystem();
if (type == GHOST_kEventWindowActivate) {
system->getWindowManager()->setActiveWindow(window);
}
return new GHOST_Event(system->getMilliSeconds(), type, window);
}
GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType,
@@ -799,9 +769,95 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax)
minmax->ptMinTrackSize.y=240;
}
#ifdef WITH_INPUT_NDOF
bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw)
{
bool eventSent = false;
GHOST_TUns64 now = getMilliSeconds();
static bool firstEvent = true;
if (firstEvent) { // determine exactly which device is plugged in
RID_DEVICE_INFO info;
unsigned infoSize = sizeof(RID_DEVICE_INFO);
info.cbSize = infoSize;
GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize);
if (info.dwType == RIM_TYPEHID)
m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId);
else
puts("<!> not a HID device... mouse/kb perhaps?");
firstEvent = false;
}
// The NDOF manager sends button changes immediately, and *pretends* to
// send motion. Mark as 'sent' so motion will always get dispatched.
eventSent = true;
#ifdef _MSC_VER
// using Microsoft compiler & header files
// they invented the RawInput API, so this version is (probably) correct
BYTE const* data = raw.data.hid.bRawData;
// struct RAWHID {
// DWORD dwSizeHid;
// DWORD dwCount;
// BYTE bRawData[1];
// };
#else
// MinGW's definition (below) doesn't agree, so we need a slight
// workaround until it's fixed
BYTE const* data = &raw.data.hid.bRawData;
// struct RAWHID {
// DWORD dwSizeHid;
// DWORD dwCount;
// BYTE bRawData; // <== isn't this s'posed to be a BYTE*?
// };
#endif
BYTE packetType = data[0];
switch (packetType)
{
case 1: // translation
{
short* axis = (short*)(data + 1);
// massage into blender view coords (same goes for rotation)
short t[3] = {axis[0], -axis[2], axis[1]};
m_ndofManager->updateTranslation(t, now);
if (raw.data.hid.dwSizeHid == 13)
{ // this report also includes rotation
short r[3] = {-axis[3], axis[5], -axis[4]};
m_ndofManager->updateRotation(r, now);
// I've never gotten one of these, has anyone else?
puts("ndof: combined T + R");
}
break;
}
case 2: // rotation
{
short* axis = (short*)(data + 1);
short r[3] = {-axis[0], axis[2], -axis[1]};
m_ndofManager->updateRotation(r, now);
break;
}
case 3: // buttons
{
int button_bits;
memcpy(&button_bits, data + 1, sizeof(button_bits));
m_ndofManager->updateButtons(button_bits, now);
break;
}
}
return eventSent;
}
#endif // WITH_INPUT_NDOF
LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
GHOST_Event* event = 0;
bool eventHandled = false;
LRESULT lResult = 0;
GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized")
@@ -818,18 +874,38 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
// Keyboard events, processed
////////////////////////////////////////////////////////////////////////
case WM_INPUT:
{
// check WM_INPUT from input sink when ghost window is not in the foreground
if (wParam == RIM_INPUTSINK) {
if (GetFocus() != hwnd) // WM_INPUT message not for this window
return 0;
} //else wPAram == RIM_INPUT
event = processKeyEvent(window, wParam, lParam);
} //else wParam == RIM_INPUT
RAWINPUT raw;
RAWINPUT* raw_ptr = &raw;
UINT rawSize = sizeof(RAWINPUT);
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER));
switch (raw.header.dwType)
{
case RIM_TYPEKEYBOARD:
event = processKeyEvent(window, raw);
if (!event) {
GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
GHOST_PRINT(msg)
GHOST_PRINT(" key ignored\n")
}
break;
#ifdef WITH_INPUT_NDOF
case RIM_TYPEHID:
if (system->processNDOF(raw))
eventHandled = true;
break;
#endif
}
break;
}
////////////////////////////////////////////////////////////////////////
// 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,
* the message is sent asynchronously, so the window is activated immediately.
*/
{
GHOST_ModifierKeys modifiers;
modifiers.clear();
system->storeModifierKeys(modifiers);
event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window);
/* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
will not be dispatched to OUR active window if we minimize one of OUR windows. */
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
break;
}
case WM_PAINT:
/* An application sends the WM_PAINT message when the system or another application
* makes a request to paint a portion of an application's window. The message is sent
@@ -1122,28 +1203,6 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* In GHOST, we let DefWindowProc call the timer callback.
*/
break;
case WM_BLND_NDOF_AXIS:
{
GHOST_TEventNDOFData ndofdata;
system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
system->m_eventManager->
pushEvent(new GHOST_EventNDOF(
system->getMilliSeconds(),
GHOST_kEventNDOFMotion,
window, ndofdata));
}
break;
case WM_BLND_NDOF_BTN:
{
GHOST_TEventNDOFData ndofdata;
system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
system->m_eventManager->
pushEvent(new GHOST_EventNDOF(
system->getMilliSeconds(),
GHOST_kEventNDOFButton,
window, ndofdata));
}
break;
}
}
else {
@@ -1165,10 +1224,12 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
if (event) {
system->pushEvent(event);
eventHandled = true;
}
else {
if (!eventHandled)
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
}
return lResult;
}
@@ -1237,8 +1298,32 @@ int GHOST_SystemWin32::toggleConsole(int action)
{
case 3: //hide if no console
{
CONSOLE_SCREEN_BUFFER_INFO csbi = {{0}};
if(!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) || csbi.dwCursorPosition.X || csbi.dwCursorPosition.Y>1)
DWORD sp = GetCurrentProcessId();
HANDLE ptree = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 e = {0}; e.dwSize = sizeof(PROCESSENTRY32);
if( Process32First(ptree, &e)) {
do { //Searches for Blender's PROCESSENTRY32
if (e.th32ProcessID == sp) {
sp = e.th32ParentProcessID;
Process32First(ptree, &e);
do { //Got parent id, searches for its PROCESSENTRY32
if (e.th32ProcessID == sp) {
if(strcmp("explorer.exe",e.szExeFile)==0)
{ //If explorer, hide cmd
ShowWindow(GetConsoleWindow(),SW_HIDE);
m_consoleStatus = 0;
}
break;
}
} while( Process32Next(ptree, &e));
break;
}
} while( Process32Next(ptree, &e));
}
CloseHandle(ptree);
break;
}
case 0: //hide

View File

@@ -38,7 +38,10 @@
#error WIN32 only!
#endif // WIN32
#define _WIN32_WINNT 0x501 // require Windows XP or newer
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ole2.h> // for drag-n-drop
#include "GHOST_System.h"
@@ -46,95 +49,6 @@
# define __int64 long long
#endif
#ifndef WM_INPUT
#define WM_INPUT 0x00FF
#endif
#ifndef RID_INPUT
#define RID_INPUT 0x10000003
#endif
#ifndef RIM_INPUTSINK
#define RIM_INPUTSINK 0x1
#endif
#ifndef RI_KEY_BREAK
#define RI_KEY_BREAK 0x1
#endif
#ifndef RI_KEY_E0
#define RI_KEY_E0 0x2
#endif
#ifndef RI_KEY_E1
#define RI_KEY_E1 0x4
#endif
#ifndef RIM_TYPEMOUSE
#define RIM_TYPEMOUSE 0x0
#define RIM_TYPEKEYBOARD 0x1
#define RIM_TYPEHID 0x2
typedef struct tagRAWINPUTDEVICE {
USHORT usUsagePage;
USHORT usUsage;
DWORD dwFlags;
HWND hwndTarget;
} RAWINPUTDEVICE;
typedef struct tagRAWINPUTHEADER {
DWORD dwType;
DWORD dwSize;
HANDLE hDevice;
WPARAM wParam;
} RAWINPUTHEADER;
typedef struct tagRAWMOUSE {
USHORT usFlags;
union {
ULONG ulButtons;
struct {
USHORT usButtonFlags;
USHORT usButtonData;
};
};
ULONG ulRawButtons;
LONG lLastX;
LONG lLastY;
ULONG ulExtraInformation;
} RAWMOUSE;
typedef struct tagRAWKEYBOARD {
USHORT MakeCode;
USHORT Flags;
USHORT Reserved;
USHORT VKey;
UINT Message;
ULONG ExtraInformation;
} RAWKEYBOARD;
typedef struct tagRAWHID {
DWORD dwSizeHid;
DWORD dwCount;
BYTE bRawData[1];
} RAWHID;
typedef struct tagRAWINPUT {
RAWINPUTHEADER header;
union {
RAWMOUSE mouse;
RAWKEYBOARD keyboard;
RAWHID hid;
} data;
} RAWINPUT;
DECLARE_HANDLE(HRAWINPUT);
#endif
#ifdef FREE_WINDOWS
#define NEED_RAW_PROC
typedef BOOL (WINAPI * LPFNDLLRRID)(RAWINPUTDEVICE*,UINT, UINT);
typedef UINT (WINAPI * LPFNDLLGRID)(HRAWINPUT, UINT, LPVOID, PUINT, UINT);
#define GetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader) ((pGetRawInputData)?pGetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader):(UINT)-1)
#endif
class GHOST_EventButton;
class GHOST_EventCursor;
class GHOST_EventKey;
@@ -314,14 +228,13 @@ protected:
/**
* Catches raw WIN32 key codes from WM_INPUT in the wndproc.
* @param window-> The window for this handling
* @param wParam The wParam from the wndproc
* @param lParam The lParam from the wndproc
* @param window The window for this handling
* @param raw RawInput structure with detailed info about the key event
* @param keyDown Pointer flag that specify if a key is down
* @param vk Pointer to virtual key
* @return The GHOST key (GHOST_kKeyUnknown if no match).
*/
virtual GHOST_TKey hardKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, int * keyDown, char * vk);
virtual GHOST_TKey hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int * keyDown, char * vk);
/**
* Creates modifier key event(s) and updates the key data stored locally (m_modifierKeys).
@@ -362,10 +275,9 @@ protected:
* In most cases this is a straightforward conversion of key codes.
* For the modifier keys however, we want to distinguish left and right keys.
* @param window The window receiving the event (the active window).
* @param wParam The wParam from the wndproc
* @param lParam The lParam from the wndproc
* @param raw RawInput structure with detailed info about the key event
*/
static GHOST_EventKey* processKeyEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam);
static GHOST_EventKey* processKeyEvent(GHOST_IWindow *window, RAWINPUT const& raw);
/**
* Process special keys (VK_OEM_*), to see if current key layout
@@ -383,12 +295,24 @@ protected:
* @return The event created.
*/
static GHOST_Event* processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window);
/**
* Handles minimum window size.
* @param minmax The MINMAXINFO structure.
*/
static void processMinMaxInfo(MINMAXINFO * minmax);
#ifdef WITH_INPUT_NDOF
/**
* Handles Motion and Button events from a SpaceNavigator or related device.
* Instead of returning an event object, this function communicates directly
* with the GHOST_NDOFManager.
* @param raw RawInput structure with detailed info about the NDOF event
* @return Whether an event was generated and sent.
*/
bool processNDOF(RAWINPUT const& raw);
#endif
/**
* Returns the local state of the modifier keys (from the message queue).
* @param keys The state of the keys.
@@ -412,11 +336,6 @@ protected:
*/
static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
/**
* Initiates WM_INPUT messages from keyboard
*/
GHOST_TInt32 initKeyboardRawInput(void);
/**
* Toggles console
* @action 0 - Hides
@@ -445,15 +364,6 @@ protected:
/** Console status */
int m_consoleStatus;
/** handle for user32.dll*/
HMODULE user32;
#ifdef NEED_RAW_PROC
/* pointer to RegisterRawInputDevices function */
LPFNDLLRRID pRegisterRawInputDevices;
/* pointer to GetRawInputData function */
LPFNDLLGRID pGetRawInputData;
#endif
};
inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const
@@ -487,4 +397,3 @@ inline void GHOST_SystemWin32::handleKeyboardChange(void)
}
}
#endif // _GHOST_SYSTEM_WIN32_H_

View File

@@ -42,9 +42,10 @@
#include "GHOST_EventKey.h"
#include "GHOST_EventButton.h"
#include "GHOST_EventWheel.h"
#include "GHOST_EventNDOF.h"
#include "GHOST_NDOFManager.h"
#include "GHOST_DisplayManagerX11.h"
#ifdef WITH_INPUT_NDOF
#include "GHOST_NDOFManagerX11.h"
#endif
#include "GHOST_Debug.h"
@@ -79,19 +80,6 @@
static GHOST_TKey
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
static char *txt_cut_buffer= NULL;
static char *txt_select_buffer= NULL;
@@ -181,6 +169,9 @@ init(
GHOST_TSuccess success = GHOST_System::init();
if (success) {
#ifdef WITH_INPUT_NDOF
m_ndofManager = new GHOST_NDOFManagerX11(*this);
#endif
m_displayManager = new GHOST_DisplayManagerX11(this);
if (m_displayManager) {
@@ -275,7 +266,7 @@ createWindow(
if (window->getValid()) {
// Store the pointer to the window
m_windowManager->addWindow(window);
m_windowManager->setActiveWindow(window);
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
}
else {
@@ -386,8 +377,6 @@ lastEventTime(Time default_time) {
return data.timestamp;
}
bool
GHOST_SystemX11::
processEvents(
@@ -428,6 +417,13 @@ processEvents(
if (generateWindowExposeEvents()) {
anyProcessed = true;
}
#ifdef WITH_INPUT_NDOF
if (dynamic_cast<GHOST_NDOFManagerX11*>(m_ndofManager)->processEvents()) {
anyProcessed = true;
}
#endif
} while (waitForEvent && !anyProcessed);
return anyProcessed;
@@ -612,6 +608,9 @@ GHOST_SystemX11::processEvent(XEvent *xe)
{
XFocusChangeEvent &xfe = xe->xfocus;
// TODO: make sure this is the correct place for activate/deactivate
// printf("X: focus %s for window %d\n", xfe.type == FocusIn ? "in" : "out", (int) xfe.window);
// May have to look at the type of event and filter some
// out.
@@ -641,32 +640,8 @@ GHOST_SystemX11::processEvent(XEvent *xe)
);
} else
#endif
if (sNdofInfo.currValues) {
static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0};
if (xcme.message_type == sNdofInfo.motionAtom)
{
data.changed = 1;
data.delta = xcme.data.s[8] - data.time;
data.time = xcme.data.s[8];
data.tx = xcme.data.s[2] >> 2;
data.ty = xcme.data.s[3] >> 2;
data.tz = xcme.data.s[4] >> 2;
data.rx = xcme.data.s[5];
data.ry = xcme.data.s[6];
data.rz =-xcme.data.s[7];
g_event = new GHOST_EventNDOF(getMilliSeconds(),
GHOST_kEventNDOFMotion,
window, data);
} else if (xcme.message_type == sNdofInfo.btnPressAtom) {
data.changed = 2;
data.delta = xcme.data.s[8] - data.time;
data.time = xcme.data.s[8];
data.buttons = xcme.data.s[2];
g_event = new GHOST_EventNDOF(getMilliSeconds(),
GHOST_kEventNDOFButton,
window, data);
}
} else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) {
if (((Atom)xcme.data.l[0]) == m_wm_take_focus) {
XWindowAttributes attr;
Window fwin;
int revert_to;
@@ -723,6 +698,14 @@ GHOST_SystemX11::processEvent(XEvent *xe)
xce.y_root
);
}
// printf("X: %s window %d\n", xce.type == EnterNotify ? "entering" : "leaving", (int) xce.window);
if (xce.type == EnterNotify)
m_windowManager->setActiveWindow(window);
else
m_windowManager->setWindowInactive(window);
break;
}
case MapNotify:
@@ -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_SystemX11::
getModifierKeys(

View File

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

View File

@@ -3,20 +3,16 @@
*/
#ifndef GHOST_TASKBARWIN32_H_
#define GHOST_TASKBARWIN32_H_
#ifndef WIN32
#error WIN32 only!
#endif // WIN32
#define _WIN32_WINNT 0x501 // require Windows XP or newer
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shlobj.h>
/* MinGW needs it */
#ifdef FREE_WINDOWS
#ifdef WINVER
#undef WINVER
#endif
#define WINVER 0x0501
#endif /* FREE_WINDOWS */
// ITaskbarList, ITaskbarList2 and ITaskbarList3 might be missing, present here in that case.
// Note, ITaskbarList3 is supported only since Windows 7, though. Check for that is done in

View File

@@ -39,20 +39,12 @@
#endif // WIN32
#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"
#define _WIN32_WINNT 0x501 // require Windows XP or newer
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wintab.h>
#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR)

View File

@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
__all__ = (
"paths",
@@ -32,6 +32,8 @@ import bpy as _bpy
error_duplicates = False
error_encoding = False
def paths():
# RELEASE SCRIPTS: official scripts distributed in Blender releases
@@ -50,14 +52,18 @@ def paths():
def modules(module_cache):
global error_duplicates
global error_encoding
import os
error_duplicates = False
error_encoding = False
path_list = paths()
# fake module importing
def fake_module(mod_name, mod_path, speedy=True):
global error_encoding
if _bpy.app.debug:
print("fake_module", mod_path, mod_name)
import ast
@@ -68,12 +74,28 @@ def modules(module_cache):
line_iter = iter(file_mod)
l = ""
while not l.startswith("bl_info"):
try:
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:
break
while l.rstrip():
lines.append(l)
try:
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)
else:
@@ -128,7 +150,12 @@ def modules(module_cache):
error_duplicates = True
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]
mod = None
@@ -143,7 +170,9 @@ def modules(module_cache):
del modules_stale
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
@@ -163,8 +192,9 @@ def check(module_name):
loaded_state = mod and getattr(mod, "__addon_enabled__", Ellipsis)
if loaded_state is Ellipsis:
print("Warning: addon-module %r found module but without"
" __addon_enabled__ field, possible name collision from file: %r" %
print("Warning: addon-module %r found module "
"but without __addon_enabled__ field, "
"possible name collision from file: %r" %
(module_name, getattr(mod, "__file__", "<unknown>")))
loaded_state = False
@@ -207,7 +237,8 @@ def enable(module_name, default_set=True):
return None
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
try:
mod = __import__(module_name)
@@ -254,8 +285,9 @@ def disable(module_name, default_set=True):
import sys
mod = sys.modules.get(module_name)
# possible this addon is from a previous session and didnt load a module this time.
# so even if the module is not found, still disable the addon in the user prefs.
# possible this addon is from a previous session and didnt load a
# module this time. So even if the module is not found, still disable
# the addon in the user prefs.
if mod:
mod.__addon_enabled__ = False
@@ -310,7 +342,22 @@ def reset_all(reload_scripts=False):
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", {})
# avoid re-initializing

View File

@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
"""
Give access to blender data and utility functions.
@@ -43,12 +43,14 @@ from . import utils, path, ops
# fake operator module
ops = ops.ops_fake_module
def _main():
import sys as _sys
# Possibly temp. addons path
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 0:

View File

@@ -16,26 +16,44 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
"""
This module has a similar scope to os.path, containing utility
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 os as _os
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
"""
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
@@ -44,7 +62,8 @@ def relpath(path, start=None):
"""
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
"""
if not path.startswith("//"):
@@ -68,27 +87,28 @@ def is_subdir(path, directory):
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 "_"
or the replace argument if defined.
"""
unclean_chars = \
"\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\
\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\
\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\
\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\
\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\
\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\
\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe"
bad_chars = ("\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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)
return name
@@ -96,8 +116,9 @@ def clean_name(name, replace="_"):
def display_name(name):
"""
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.
Intended for use with filenames and module names.
Capitalize the first letter in all lowercase names,
mixed case names are kept as is. Intended for use with
filenames and module names.
"""
name_base = _os.path.splitext(name)[0]
@@ -115,9 +136,11 @@ def display_name(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):
@@ -132,7 +155,8 @@ def resolve_ncase(path):
if not path or os.path.exists(path):
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)
suffix = path[:0] # "" but ensure byte/str match
@@ -180,7 +204,7 @@ def resolve_ncase(path):
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.
:type ext: string
@@ -190,7 +214,9 @@ def ensure_ext(filepath, ext, case_sensitive=False):
import os
fn_base, fn_ext = os.path.splitext(filepath)
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
else:
return fn_base + ext
@@ -228,7 +254,9 @@ def module_names(path, recursive=False):
modules.append((filename, fullpath))
if recursive:
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

View File

@@ -16,13 +16,33 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
"""
This module contains utility functions specific to blender but
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 script_paths as _bpy_script_paths
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:
return None
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
if use_time:
@@ -74,7 +95,8 @@ def modules_from_path(path, loaded_modules):
:arg path: this path is scanned for scripts and packages.
: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
:return: all loaded modules.
:rtype: list
@@ -97,13 +119,17 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
"""
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
: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
"""
use_time = _bpy.app.debug
prefs = _bpy.context.user_preferences
if use_time:
import time
t_main = time.time()
@@ -116,10 +142,11 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
if reload_scripts:
_bpy_types.TypeMap.clear()
# just unload, dont change user defaults, this means we can sync to reload.
# note that they will only actually reload of the modification time changes.
# this `wont` work for packages so... its not perfect.
for module_name in [ext.module for ext in _bpy.context.user_preferences.addons]:
# just unload, dont change user defaults, this means we can sync
# to reload. note that they will only actually reload of the
# modification time changes. This `wont` work for packages so...
# its not perfect.
for module_name in [ext.module for ext in prefs.addons]:
_addon_utils.disable(module_name, default_set=False)
def register_module_call(mod):
@@ -131,7 +158,9 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
import traceback
traceback.print_exc()
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):
unregister = getattr(mod, "unregister", None)
@@ -172,7 +201,8 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
if reload_scripts:
# 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
_global_loaded_modules.reverse()
@@ -201,7 +231,8 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
_addon_utils.reset_all(reload_scripts)
# 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:
keyconfig_set(filepath)
@@ -214,12 +245,16 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
# 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), )
def user_script_path():
path = _bpy.context.user_preferences.filepaths.script_directory
prefs = _bpy.context.user_preferences
path = prefs.filepaths.script_directory
if path:
path = _os.path.normpath(path)
@@ -236,22 +271,25 @@ def script_paths(subdir=None, user_pref=True, all=False):
:type subdir: string
:arg user_pref: Include the user preference script path.
: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
:return: script paths.
:rtype: list
"""
scripts = list(_scripts)
prefs = _bpy.context.user_preferences
# add user scripts dir
if user_pref:
user_script_path = _bpy.context.user_preferences.filepaths.script_directory
user_script_path = prefs.filepaths.script_directory
else:
user_script_path = None
if all:
# 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:
# only paths blender uses
base_paths = _bpy_script_paths()
@@ -426,7 +464,8 @@ def user_resource(type, path="", create=False):
:type type: string
:arg subdir: Optional subdirectory.
: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
:return: a path.
:rtype: string
@@ -477,7 +516,8 @@ def register_module(module, verbose=False):
try:
register_class(cls)
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
traceback.print_exc()
if verbose:
@@ -495,7 +535,8 @@ def unregister_module(module, verbose=False):
try:
unregister_class(cls)
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
traceback.print_exc()
if verbose:

View File

@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
"""
Utility modules assosiated with the bpy module.

View File

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

View File

@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
__all__ = (
"ExportHelper",
@@ -37,9 +37,28 @@ import bpy
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:
filepath = StringProperty(name="File Path", description="Filepath used for exporting the file", maxlen=1024, default="", subtype='FILE_PATH')
check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'})
filepath = StringProperty(
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
# True == use ext, False == no ext, None == do nothing.
@@ -60,27 +79,39 @@ class ExportHelper:
return {'RUNNING_MODAL'}
def check(self, context):
change_ext = False
change_axis = _check_axis_conversion(self)
check_extension = self.check_extension
if check_extension is None:
return False
filepath = bpy.path.ensure_ext(self.filepath, self.filename_ext if check_extension else "")
if check_extension is not None:
filepath = bpy.path.ensure_ext(self.filepath,
self.filename_ext
if check_extension
else "")
if filepath != self.filepath:
self.filepath = filepath
return True
change_ext = True
return False
return (change_ext or change_axis)
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):
context.window_manager.fileselect_add(self)
return {'RUNNING_MODAL'}
def check(self, context):
return _check_axis_conversion(self)
# Axis conversion function, not pretty LUT
# 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...
# (i1<<0 | i1<<3 | i1<<6 | i1<<9)
_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},
{0xAC8, 0x8D0, 0x4E0, 0x2E8, 0x741, 0x951, 0x159, 0x369, 0x702, 0xB0A, 0x11A, 0x522, 0xA0B, 0x813, 0x423, 0x22B, 0x684, 0x894, 0x09C, 0x2AC, 0x645, 0xA4D, 0x05D, 0x465},
{0x4C8, 0x2D0, 0xAE0, 0x8E8, 0x681, 0x291, 0x099, 0x8A9, 0x642, 0x44A, 0x05A, 0xA62, 0x40B, 0x213, 0xA23, 0x82B, 0x744, 0x354, 0x15C, 0x96C, 0x705, 0x50D, 0x11D, 0xB25},
{0x2C8, 0xAD0, 0x8E0, 0x4E8, 0x641, 0xA51, 0x059, 0x469, 0x742, 0x34A, 0x15A, 0x962, 0x20B, 0xA13, 0x823, 0x42B, 0x704, 0xB14, 0x11C, 0x52C, 0x685, 0x28D, 0x09D, 0x8A5},
{0x708, 0xB10, 0x120, 0x528, 0x8C1, 0xAD1, 0x2D9, 0x4E9, 0x942, 0x74A, 0x35A, 0x162, 0x64B, 0xA53, 0x063, 0x46B, 0x804, 0xA14, 0x21C, 0x42C, 0x885, 0x68D, 0x29D, 0x0A5},
{0xB08, 0x110, 0x520, 0x728, 0x941, 0x151, 0x359, 0x769, 0x802, 0xA0A, 0x21A, 0x422, 0xA4B, 0x053, 0x463, 0x66B, 0x884, 0x094, 0x29C, 0x6AC, 0x8C5, 0xACD, 0x2DD, 0x4E5},
{0x508, 0x710, 0xB20, 0x128, 0x881, 0x691, 0x299, 0x0A9, 0x8C2, 0x4CA, 0x2DA, 0xAE2, 0x44B, 0x653, 0xA63, 0x06B, 0x944, 0x754, 0x35C, 0x16C, 0x805, 0x40D, 0x21D, 0xA25},
{0x108, 0x510, 0x720, 0xB28, 0x801, 0x411, 0x219, 0xA29, 0x882, 0x08A, 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},
{0x8C8, 0x4D0, 0x2E0, 0xAE8, 0x701, 0x511, 0x119, 0xB29, 0x682, 0x88A,
0x09A, 0x2A2, 0x80B, 0x413, 0x223, 0xA2B, 0x644, 0x454, 0x05C, 0xA6C,
0x745, 0x94D, 0x15D, 0x365},
{0xAC8, 0x8D0, 0x4E0, 0x2E8, 0x741, 0x951, 0x159, 0x369, 0x702, 0xB0A,
0x11A, 0x522, 0xA0B, 0x813, 0x423, 0x22B, 0x684, 0x894, 0x09C, 0x2AC,
0x645, 0xA4D, 0x05D, 0x465},
{0x4C8, 0x2D0, 0xAE0, 0x8E8, 0x681, 0x291, 0x099, 0x8A9, 0x642, 0x44A,
0x05A, 0xA62, 0x40B, 0x213, 0xA23, 0x82B, 0x744, 0x354, 0x15C, 0x96C,
0x705, 0x50D, 0x11D, 0xB25},
{0x2C8, 0xAD0, 0x8E0, 0x4E8, 0x641, 0xA51, 0x059, 0x469, 0x742, 0x34A,
0x15A, 0x962, 0x20B, 0xA13, 0x823, 0x42B, 0x704, 0xB14, 0x11C, 0x52C,
0x685, 0x28D, 0x09D, 0x8A5},
{0x708, 0xB10, 0x120, 0x528, 0x8C1, 0xAD1, 0x2D9, 0x4E9, 0x942, 0x74A,
0x35A, 0x162, 0x64B, 0xA53, 0x063, 0x46B, 0x804, 0xA14, 0x21C, 0x42C,
0x885, 0x68D, 0x29D, 0x0A5},
{0xB08, 0x110, 0x520, 0x728, 0x941, 0x151, 0x359, 0x769, 0x802, 0xA0A,
0x21A, 0x422, 0xA4B, 0x053, 0x463, 0x66B, 0x884, 0x094, 0x29C, 0x6AC,
0x8C5, 0xACD, 0x2DD, 0x4E5},
{0x508, 0x710, 0xB20, 0x128, 0x881, 0x691, 0x299, 0x0A9, 0x8C2, 0x4CA,
0x2DA, 0xAE2, 0x44B, 0x653, 0xA63, 0x06B, 0x944, 0x754, 0x35C, 0x16C,
0x805, 0x40D, 0x21D, 0xA25},
{0x108, 0x510, 0x720, 0xB28, 0x801, 0x411, 0x219, 0xA29, 0x882, 0x08A,
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}
@@ -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, "
"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):
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.
:type operator: :class:`Operator`
:arg forward_attr:
:arg forward_attr: attribute storing the forward axis
: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
:return: True if the value was modified.
:rtype: boolean
@@ -201,7 +283,8 @@ def axis_conversion_ensure(operator, forward_attr, up_attr):
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):
if ob.parent and ob.parent.dupli_type in {'VERTS', 'FACES'}:
return False, None
@@ -249,31 +332,45 @@ path_reference_mode = EnumProperty(
description="Method used to reference paths",
items=(('AUTO', "Auto", "Use Relative paths with subdirectories only"),
('ABSOLUTE', "Absolute", "Always write absolute paths"),
('RELATIVE', "Relative", "Always write relative patsh (where possible)"),
('MATCH', "Match", "Match Absolute/Relative setting with input path"),
('RELATIVE', "Relative", "Always write relative patsh "
"(where possible)"),
('MATCH', "Match", "Match Absolute/Relative "
"setting with input path"),
('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'
)
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
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
: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
: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
: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
:arg copy_subdir: the subdirectory of *base_dst* to use when mode='COPY'.
: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
:return: the new filepath.
:rtype: string
@@ -282,12 +379,14 @@ def path_reference(filepath, base_src, base_dst, mode='AUTO', copy_subdir="", co
is_relative = filepath.startswith("//")
filepath_abs = os.path.normpath(bpy.path.abspath(filepath, base_src))
if mode in ('ABSOLUTE', 'RELATIVE', 'STRIP'):
if mode in {'ABSOLUTE', 'RELATIVE', 'STRIP'}:
pass
elif mode == 'MATCH':
mode = 'RELATIVE' if is_relative else 'ABSOLUTE'
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':
if 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:
count = 1
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:
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]
while name_new in name_dict_values:
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
name_dict[key] = name_new

View File

@@ -170,8 +170,8 @@ def edge_loops_from_faces(mesh, faces=None, seams=()):
# from knowing the last 2, look for th next.
ed_adj = edges[context_loop[-1]]
if len(ed_adj) != 2:
if other_dir and flipped == False: # the original edge had 2 other edges
# the original edge had 2 other edges
if other_dir and flipped == False:
flipped = True # only flip the list once
context_loop.reverse()
ed_adj[:] = []
@@ -259,13 +259,15 @@ def edge_loops_from_edges(mesh, edges=None):
def ngon_tesselate(from_data, indices, fix_loops=True):
'''
Takes a polyline of indices (fgon)
and returns a list of face indicie lists.
Designed to be used for importers that need indices for an fgon to create from existing verts.
Takes a polyline of indices (fgon) and returns a list of face
indicie lists. Designed to be used for importers that need indices for an
fgon to create from existing verts.
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.
fix_loops: If this is enabled polylines that use loops to make multiple polylines are delt with correctly.
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.
fix_loops: If this is enabled polylines that use loops to make multiple
polylines are delt with correctly.
'''
from mathutils.geometry import tesselate_polygon
@@ -276,7 +278,8 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
return []
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):
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
'''
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)]
else:
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]:
verts.pop(i - 1)
@@ -304,14 +308,16 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
else:
'''
Seperate this loop into multiple loops be finding edges that are used twice
This is used by lightwave LWO files a lot
Seperate this loop into multiple loops be finding edges that are
used twice. This is used by lightwave LWO files a lot
'''
if type(from_data) in (tuple, list):
verts = [vert_treplet(Vector(from_data[i]), ii) for ii, i in enumerate(indices)]
if type(from_data) in {tuple, list}:
verts = [vert_treplet(Vector(from_data[i]), ii)
for ii, i in enumerate(indices)]
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))]
if edges:

View File

@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
__all__ = (
"add_object_align_init",
@@ -39,42 +39,49 @@ def add_object_align_init(context, operator):
:return: the matrix from the context and settings.
:rtype: :class:`Matrix`
"""
from mathutils import Matrix, Vector, Euler
properties = operator.properties if operator is not None else None
space_data = context.space_data
if space_data.type != 'VIEW_3D':
space_data = None
# location
if operator and operator.properties.is_property_set("location"):
location = mathutils.Matrix.Translation(mathutils.Vector(operator.properties.location))
if operator and properties.is_property_set("location"):
location = Matrix.Translation(Vector(properties.location))
else:
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:
location = mathutils.Matrix.Translation(context.scene.cursor_location)
location = Matrix.Translation(context.scene.cursor_location)
if operator:
operator.properties.location = location.to_translation()
properties.location = location.to_translation()
# rotation
view_align = (context.user_preferences.edit.object_align == 'VIEW')
view_align_force = False
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
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:
rotation = mathutils.Euler(operator.properties.rotation).to_matrix().to_4x4()
if operator and (properties.is_property_set("rotation") and
not view_align_force):
rotation = Euler(properties.rotation).to_matrix().to_4x4()
else:
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:
rotation = mathutils.Matrix()
# set the operator properties
if operator:
operator.properties.rotation = rotation.to_euler()
properties.rotation = rotation.to_euler()
return location * rotation
@@ -114,14 +121,18 @@ def object_data_add(context, obdata, operator=None):
# XXX
# caused because entering editmodedoes not add a empty undo slot!
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)
obj_act = bpy.data.objects.new(_obdata.name, _obdata)
obj_act.matrix_world = obj_new.matrix_world
scene.objects.link(obj_act)
scene.objects.active = obj_act
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
if obj_act and obj_act.mode == 'EDIT' and obj_act.type == obj_new.type:

View File

@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
__all__ = (
"region_2d_to_vector_3d",
@@ -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_end = origin_start + coord_vec
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:
dx = (2.0 * coord[0] / region.width) - 1.0
dy = (2.0 * coord[1] / region.height) - 1.0
persinv = persmat.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
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):

View File

@@ -120,7 +120,7 @@ def fromxml(data):
py_item = (xml_node.tagName, _fromxml_kwargs(xml_node), [])
#_fromxml_iter(py_item, 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))
return py_item

View File

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

View File

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

View File

@@ -148,7 +148,7 @@ class InfoStructRNA:
import types
functions = []
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))
return functions
@@ -156,7 +156,7 @@ class InfoStructRNA:
import types
functions = []
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))
return functions
@@ -260,7 +260,7 @@ class InfoPropertyRNA:
if 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))
elif self.type == "enum":
if self.is_enum_flag:
@@ -595,7 +595,7 @@ def BuildRNAInfo():
for prop in rna_info.properties:
# ERROR CHECK
default = prop.default
if type(default) in (float, int):
if type(default) in {float, int}:
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))

View File

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

View File

@@ -61,13 +61,19 @@ class EditExternally(bpy.types.Operator):
def execute(self, context):
import os
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):
self.report({'ERROR'},
"Image path %r not found, image may be packed or "
"unsaved." % filepath)
return {'CANCELLED'}
cmd = self._editor_guess(context) + [filepath]

View File

@@ -22,6 +22,7 @@ import bpy
from mathutils import Vector
from blf import gettext as _
def GlobalBB_LQ(bb_world):
# Initialize the variables with the 8th vertex
@@ -62,6 +63,7 @@ def GlobalBB_LQ(bb_world):
return (Vector((left, front, up)), Vector((right, back, down)))
def GlobalBB_HQ(obj):
matrix_world = obj.matrix_world.copy()

View File

@@ -520,7 +520,7 @@ def unwrap(operator, context, **kwargs):
if obj and obj.type == 'MESH':
meshes = [obj.data]
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:
operator.report({'ERROR'}, "No mesh object.")

View File

@@ -587,7 +587,7 @@ class WM_OT_context_modal_mouse(bpy.types.Operator):
self._values_clear()
return {'FINISHED'}
elif event_type in ('RIGHTMOUSE', 'ESC'):
elif event_type in {'RIGHTMOUSE', 'ESC'}:
self._values_restore()
return {'FINISHED'}
@@ -841,7 +841,7 @@ class WM_OT_properties_edit(bpy.types.Operator):
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_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")
class DATA_PT_textboxes(CurveButtonsPanel, bpy.types.Panel):
class DATA_PT_text_boxes(CurveButtonsPanel, bpy.types.Panel):
bl_label = _("Text Boxes")
@classmethod

View File

@@ -41,11 +41,9 @@ class DATA_PT_empty(DataButtonsPanel, bpy.types.Panel):
layout.prop(ob, "empty_draw_type", text=_("Display"))
if ob.empty_draw_type == 'IMAGE':
# layout.template_image(ob, "data", None)
layout.template_ID(ob, "data", open="image.open", unlink="image.unlink")
row = layout.row(align=True)
row.prop(ob, "color", text=_("Transparency"), index=3, slider=True)
layout.prop(ob, "color", text=_("Transparency"), index=3, slider=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 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"))
if mat.use_diffuse_ramp:
layout.separator()
layout.template_color_ramp(mat, "diffuse_ramp", expand=True)
layout.separator()
col = layout.column()
col.active = (not mat.use_shadeless)
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_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):

View File

@@ -463,7 +463,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
col.prop(part, "mass")
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()
col = split.column()
@@ -922,7 +922,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel, bpy.types.Panel):
col = row.column()
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.prop(part, "particle_size")
row.prop(part, "size_random", slider=True)

View File

@@ -353,7 +353,7 @@ class INFO_MT_help(bpy.types.Menu):
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=_("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()

View File

@@ -755,6 +755,31 @@ class USERPREF_PT_file(bpy.types.Panel):
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):
bl_space_type = 'USER_PREFERENCES'
bl_label = _("Input")
@@ -817,12 +842,9 @@ class USERPREF_PT_input(bpy.types.Panel, InputKeyMapPanel):
#sub.prop(view, "wheel_scroll_lines", text="Scroll Lines")
col.separator()
''' not implemented yet
sub = col.column()
sub.label(text="NDOF Device:")
sub.prop(inputs, "ndof_pan_speed", text="Pan Speed")
sub.prop(inputs, "ndof_rotate_speed", text="Orbit Speed")
'''
sub.prop(inputs, "ndof_sensitivity", text="NDOF Sensitivity")
row.separator()
@@ -881,7 +903,7 @@ class USERPREF_PT_addons(bpy.types.Panel):
if not user_addon_paths:
user_script_path = bpy.utils.user_script_path()
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"))
for path in user_addon_paths:
@@ -927,6 +949,12 @@ class USERPREF_PT_addons(bpy.types.Panel):
"(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
search = context.window_manager.addon_search.lower()
support = context.window_manager.addon_support
@@ -1020,7 +1048,6 @@ class USERPREF_PT_addons(bpy.types.Panel):
for i in range(4 - tot_row):
split.separator()
# Append missing scripts
# First collect scripts that are used but have no script file.
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_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):
mod = addon_utils.enable(self.module)
if mod:
# check if add-on is written for current blender version, or raise a warning
info = addon_utils.module_bl_info(mod)
if info.get("blender", (0, 0, 0)) > bpy.app.version:
self.report("WARNING','This script was written for a newer version of Blender and might not function (correctly).\nThe script is enabled though.")
info_ver = info.get("blender", (0, 0, 0))
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'}
else:
return {'CANCELLED'}

View File

@@ -190,10 +190,10 @@ class InputKeyMapPanel:
if km.is_modal:
row.label(text="", icon='LINKED')
if km.is_user_defined:
if km.is_user_modified:
row.operator("wm.keymap_restore", text=_("Restore"))
else:
row.operator("wm.keymap_edit", text=_("Edit"))
row.label()
if km.show_expanded_children:
if children:
@@ -214,7 +214,6 @@ class InputKeyMapPanel:
# "Add New" at end of keymap item list
col = self.indented_layout(col, level + 1)
subcol = col.split(percentage=0.2).column()
subcol.enabled = km.is_user_defined
subcol.operator("wm.keyitem_add", text=_("Add New"), icon='ZOOMIN')
col.separator()
@@ -245,7 +244,7 @@ class InputKeyMapPanel:
col = self.indented_layout(layout, level)
if km.is_user_defined:
if kmi.show_expanded:
col = col.column(align=True)
box = col.box()
else:
@@ -258,7 +257,6 @@ class InputKeyMapPanel:
row.prop(kmi, "show_expanded", text="", emboss=False)
row = split.row()
row.enabled = km.is_user_defined
row.prop(kmi, "active", text="", emboss=False)
if km.is_modal:
@@ -267,12 +265,13 @@ class InputKeyMapPanel:
row.label(text=kmi.name)
row = split.row()
row.enabled = km.is_user_defined
row.prop(kmi, "map_type", text="")
if map_type == 'KEYBOARD':
row.prop(kmi, "type", text="", full_event=True)
elif map_type == 'MOUSE':
row.prop(kmi, "type", text="", full_event=True)
elif map_type == 'NDOF':
row.prop(kmi, "type", text="", full_event=True)
elif map_type == 'TWEAK':
subrow = row.row()
subrow.prop(kmi, "type", text="")
@@ -282,9 +281,10 @@ class InputKeyMapPanel:
else:
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.item_id = kmi.id
else:
op = row.operator("wm.keyitem_remove", text="", icon='X')
op.item_id = kmi.id
@@ -292,8 +292,6 @@ class InputKeyMapPanel:
if kmi.show_expanded:
box = col.box()
box.enabled = km.is_user_defined
if map_type not in {'TEXTINPUT', 'TIMER'}:
split = box.split(percentage=0.4)
sub = split.row()
@@ -308,7 +306,7 @@ class InputKeyMapPanel:
sub = split.column()
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, "value", text="")
elif map_type == 'MOUSE':
@@ -352,10 +350,10 @@ class InputKeyMapPanel:
row.label()
row.label()
if km.is_user_defined:
if km.is_user_modified:
row.operator("wm.keymap_restore", text=_("Restore"))
else:
row.operator("wm.keymap_edit", text=_("Edit"))
row.label()
for kmi in filtered_items:
self.draw_kmi(display_keymaps, kc, km, kmi, col, 1)
@@ -363,7 +361,6 @@ class InputKeyMapPanel:
# "Add New" at end of keymap item list
col = self.indented_layout(layout, 1)
subcol = col.split(percentage=0.2).column()
subcol.enabled = km.is_user_defined
subcol.operator("wm.keyitem_add", text=_("Add New"), icon='ZOOMIN')
def draw_hierarchy(self, display_keymaps, layout):
@@ -372,8 +369,7 @@ class InputKeyMapPanel:
def draw_keymaps(self, context, layout):
wm = context.window_manager
kc = wm.keyconfigs.active
defkc = wm.keyconfigs.default
kc = wm.keyconfigs.user
col = layout.column()
sub = col.column()
@@ -398,7 +394,7 @@ class InputKeyMapPanel:
col.separator()
display_keymaps = _merge_keymaps(kc, defkc)
display_keymaps = _merge_keymaps(kc, kc)
if context.space_data.filter_text != "":
filter_text = context.space_data.filter_text.lower()
self.draw_filtered(display_keymaps, filter_text, col)
@@ -550,22 +546,24 @@ class WM_OT_keyconfig_import(bpy.types.Operator):
def execute(self, context):
from os.path import basename
import shutil
if not self.filepath:
raise Exception("Filepath not set")
f = open(self.filepath, "r")
if not f:
raise Exception("Could not open file")
if not self.filepath:
self.report({'ERROR'}, "Filepath not set")
return {'CANCELLED'}
config_name = basename(self.filepath)
path = bpy.utils.user_resource('SCRIPTS', os.path.join("presets", "keyconfig"), create=True)
path = os.path.join(path, config_name)
try:
if self.keep_original:
shutil.copy(self.filepath, path)
else:
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.
bpy.utils.keyconfig_set(path)
@@ -595,6 +593,9 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
if not self.filepath:
raise Exception("Filepath not set")
if not self.filepath.endswith('.py'):
self.filepath += '.py'
f = open(self.filepath, "w")
if not f:
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:
#
# 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.
#
# 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():
keymaps = []
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
if kc != wm.keyconfigs.default:
export_keymaps = _merge_keymaps(edited_kc, kc)
@@ -669,18 +672,6 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
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):
"Restore key map(s)"
bl_idname = "wm.keymap_restore"
@@ -693,7 +684,7 @@ class WM_OT_keymap_restore(bpy.types.Operator):
wm = context.window_manager
if self.all:
for km in wm.keyconfigs.default.keymaps:
for km in wm.keyconfigs.user.keymaps:
km.restore_to_default()
else:
km = context.keymap
@@ -713,13 +704,13 @@ class WM_OT_keyitem_restore(bpy.types.Operator):
@classmethod
def poll(cls, context):
keymap = getattr(context, "keymap", None)
return keymap and keymap.is_user_defined
return keymap
def execute(self, context):
km = context.keymap
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)
return {'FINISHED'}
@@ -758,7 +749,7 @@ class WM_OT_keyitem_remove(bpy.types.Operator):
@classmethod
def poll(cls, context):
return hasattr(context, "keymap") and context.keymap.is_user_defined
return hasattr(context, "keymap")
def execute(self, context):
km = context.keymap

View File

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

View File

@@ -35,7 +35,7 @@ def add_object(self, context):
mesh.from_pydata(verts, edges, faces)
# useful for development when the mesh may be invalid.
# 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):

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':
return {'FINISHED'}
elif event.type in ('RIGHTMOUSE', 'ESC'):
elif event.type in {'RIGHTMOUSE', 'ESC'}:
context.object.location.x = self.first_value
return {'CANCELLED'}

View File

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

View File

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

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

View File

@@ -12,22 +12,22 @@
</style>
</head>
<body>
<p class="title"><b>Blender 2.58</b></p>
<p class="title"><b>Blender 2.59</b></p>
<p><br></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">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><br></p>
<p class="header"><b>2.58</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="header"><b>2.59</b></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"> • 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"> • 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 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 class="header"><b>Package Contents</b></p>
<p class="body">The downloaded Blender package includes:</p>
@@ -51,11 +51,11 @@
<p class="header"><b>Links</b></p>
<p class="body">Users:</p>
<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>
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>
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 class="body">Developers:</p>
<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