Merge with trunk r39000

This commit is contained in:
Miika Hamalainen 2011-08-03 18:47:20 +00:00
commit daea8a28ae
204 changed files with 5287 additions and 2375 deletions

@ -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
# we use precompiled libraries for py 3.2 and up by default
# normally cached but not since we include them with blender
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()
# 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
# uncached vars
set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
@ -972,7 +973,17 @@ elseif(APPLE)
set(SAMPLERATE_LIBPATH ${SAMPLERATE}/lib)
endif()
set(PLATFORM_LINKLIBS stdc++ SystemStubs)
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,24 @@ 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()
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 +1055,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 +1084,34 @@ if(APPLE OR WIN32)
endif()
endif()
# See TEST_SSE_SUPPORT() for how this is defined.
if(WITH_RAYOPTIMIZATION)
if(CMAKE_COMPILER_IS_GNUCC)
if(SUPPORT_SSE_BUILD)
set(PLATFORM_CFLAGS " -msse ${PLATFORM_CFLAGS}")
add_definitions(-D__SSE__ -D__MMX__)
endif()
if(SUPPORT_SSE2_BUILD)
set(PLATFORM_CFLAGS " -msse2 ${PLATFORM_CFLAGS}")
add_definitions(-D__SSE2__)
if(NOT SUPPORT_SSE_BUILD) # dont double up
add_definitions(-D__MMX__)
endif()
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 " ${_sse} ${PLATFORM_CFLAGS}")
add_definitions(-D__SSE__ -D__MMX__)
endif()
if(SUPPORT_SSE2_BUILD)
set(PLATFORM_CFLAGS " ${_sse2} ${PLATFORM_CFLAGS}")
add_definitions(-D__SSE2__)
if(NOT SUPPORT_SSE_BUILD) # dont double up
add_definitions(-D__MMX__)
endif()
endif()
unset(_sse)
unset(_sse2)
endif()
if(WITH_IMAGE_OPENJPEG)
@ -1306,6 +1350,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)

@ -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,6 +246,7 @@ 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():
@ -658,11 +664,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

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

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

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

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

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

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

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

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

@ -39,12 +39,12 @@ def replace_line(f, i, text, keep_indent=True):
file_handle = open(f, 'r')
data = file_handle.readlines()
file_handle.close()
l = data[i]
ws = l[:len(l) - len(l.lstrip())]
data[i] = "%s%s\n" % (ws, text)
file_handle = open(f, 'w')
file_handle.writelines(data)
file_handle.close()
@ -182,13 +182,13 @@ def cmake_get_src(f):
if new_path_rel != l:
print("overly relative path:\n %s:%d\n %s\n %s" % (f, i, l, new_path_rel))
## Save time. just replace the line
# replace_line(f, i - 1, new_path_rel)
else:
raise Exception("non existant include %s:%d -> %s" % (f, i, new_file))
# print(new_file)
global_h.update(set(sources_h))
@ -206,7 +206,7 @@ def cmake_get_src(f):
if ff not in sources_c:
print(" missing: " + ff)
'''
# reset
sources_h[:] = []
sources_c[:] = []

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

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

@ -314,6 +314,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()

@ -264,7 +264,9 @@ if MACOSX_ARCHITECTURE == 'i386':
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse']
elif MACOSX_ARCHITECTURE == 'x86_64':
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-msse2']
# SpaceNavigator and related 3D mice
WITH_BF_3DMOUSE = False
#############################################################################
################### various compile settings and flags ##################
@ -294,6 +296,9 @@ if WITH_BF_QUICKTIME == True:
else:
PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QuickTime']
if WITH_BF_3DMOUSE:
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']

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

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

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

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

@ -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', '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
@ -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,14 @@ 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('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', []),

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

@ -8,11 +8,11 @@ from bge import constraints
# get object list
objects = logic.getCurrentScene().objects
# get object named Object1 and Object 2
object_1 = objects["Object1"]
object_2 = objects["Object2"]
# want to use Edge constraint type
constraint_type = 2
@ -31,7 +31,7 @@ edge_angle_y = 1.0
edge_angle_z = 0.0
# create an edge constraint
constraints.createConstraint( physics_id_1, physics_id_2,
constraint_type,
edge_position_x, edge_position_y, edge_position_z,
edge_angle_x, edge_angle_y, edge_angle_z )
constraints.createConstraint(physics_id_1, physics_id_2,
constraint_type,
edge_position_x, edge_position_y, edge_position_z,
edge_angle_x, edge_angle_y, edge_angle_z)

@ -6,29 +6,31 @@ createTexture() and removeTexture() are to be called from a module Python
Controller.
"""
from bge import logic
from bge import texture
from bge import texture
def createTexture(cont):
"""Create a new Dynamic Texture"""
object = cont.owner
# get the reference pointer (ID) of the internal texture
ID = texture.materialID(obj, 'IMoriginal.png')
# create a texture object
# create a texture object
object_texture = texture.Texture(object, ID)
# create a new source with an external image
url = logic.expandPath("//newtexture.jpg")
new_source = texture.ImageFFmpeg(url)
# the texture has to be stored in a permanent Python object
logic.texture = object_texture
# update/replace the texture
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:

@ -9,14 +9,14 @@ from bge import logic
cont = logic.getCurrentController()
obj = cont.owner
# the creation of the texture must be done once: save the
# the creation of the texture must be done once: save the
# texture object in an attribute of bge.logic module makes it persistent
if not hasattr(logic, 'video'):
# identify a static texture by name
matID = texture.materialID(obj, 'IMvideo.png')
# create a dynamic texture that will replace the static texture
logic.video = texture.Texture(obj, matID)
@ -24,7 +24,7 @@ if not hasattr(logic, 'video'):
movie = logic.expandPath('//trailer_400p.ogg')
logic.video.source = texture.VideoFFmpeg(movie)
logic.video.source.scale = True
# quick off the movie, but it wont play in the background
logic.video.source.play()

@ -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,31 +12,33 @@ from bge import logic
import bgl
import blf
def init():
"""init function - runs once"""
# create a new font object, use external ttf file
font_path = logic.expandPath('//Zeyada.ttf')
# store the font indice - to use later
# store the font indice - to use later
logic.font_id = blf.load(font_path)
# set the font drawing routine to run every frame
# set the font drawing routine to run every frame
scene = logic.getCurrentScene()
scene.post_draw=[write]
scene.post_draw = [write]
def write():
"""write on screen"""
width = render.getWindowWidth()
height = render.getWindowHeight()
# OpenGL setup
bgl.glMatrixMode(bgl.GL_PROJECTION)
bgl.glLoadIdentity()
bgl.gluOrtho2D(0, width, 0, height)
bgl.glMatrixMode(bgl.GL_MODELVIEW)
bgl.glLoadIdentity()
# BLF drawing routine
font_id = logic.font_id
blf.position(font_id, (width*0.2), (height*0.3), 0)
blf.position(font_id, (width * 0.2), (height * 0.3), 0)
blf.size(font_id, 50, 72)
blf.draw(font_id, "Hello World")

@ -1,15 +1,15 @@
import mathutils
# zero length vector
vec = mathutils.Vector((0, 0, 1))
vec = mathutils.Vector((0.0, 0.0, 1.0))
# unit length vector
vec_a = vec.copy().normalize()
vec_b = mathutils.Vector((0, 1, 2))
vec_b = mathutils.Vector((0.0, 1.0, 2.0))
vec2d = mathutils.Vector((1, 2))
vec3d = mathutils.Vector((1, 0, 0))
vec2d = mathutils.Vector((1.0, 2.0))
vec3d = mathutils.Vector((1.0, 0.0, 0.0))
vec4d = vec_a.to_4d()
# other mathutuls types
@ -34,9 +34,9 @@ vec_a + vec_b
vec_a - vec_b
vec_a * vec_b
vec_a * 10.0
vec_a * matrix
matrix * vec_a
quat * vec_a
vec_a * vec_b
vec_a * quat
-vec_a
@ -44,6 +44,7 @@ vec_a * quat
x = vec_a[0]
len(vec)
vec_a[:] = vec_b
vec_a[:] = 1.0, 2.0, 3.0
vec2d[:] = vec3d[:2]

@ -1,28 +1,47 @@
Game Engine bge.constraints Module
==================================
Physics Constraints (bge.constraints)
=====================================
.. note::
This documentation is still very weak, and needs some help!
.. function:: createConstraint([obj1, [obj2, [restLength, [restitution, [damping]]]]])
.. 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 +68,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)
@ -60,10 +79,10 @@ Game Engine bge.constraints Module
.. function:: setCcdMode(ccdMode)
..note::
.. 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 +92,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 +123,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,7 +156,10 @@ Game Engine bge.constraints Module
.. function:: setLinearAirDamping(damping)
Not implemented.
.. note::
Not implemented.
Sets the linear air damping for rigidbodies.
.. function:: setNumIterations(numiter)
@ -156,10 +177,10 @@ Game Engine bge.constraints Module
.. function:: setSolverDamping(damping)
..note::
.. 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 +190,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 +210,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 +218,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

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

@ -1,6 +1,7 @@
Game Engine bge.logic Module
============================
Game Logic (bge.logic)
======================
*****
Intro
*****

@ -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()
@ -43,7 +43,7 @@ Intro
bge.logic.addActiveActuator(wmotion, True)
# Centre the mouse
bge.render.setMousePosition(bge.render.getWindowWidth()/2, bge.render.getWindowHeight()/2)
bge.render.setMousePosition(bge.render.getWindowWidth() / 2, bge.render.getWindowHeight() / 2)
*********
Constants

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

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

@ -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):
@ -1886,4 +1886,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.

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

@ -38,8 +38,11 @@ cp $SPHINXBASE/sphinx-out/contents.html $SPHINXBASE/sphinx-out/index.html
ssh $SSH_USER@emo.blender.org 'rm -rf '$SSH_UPLOAD_FULL'/*'
rsync --progress -avze "ssh -p 22" $SPHINXBASE/sphinx-out/* $SSH_HOST:$SSH_UPLOAD_FULL/
# symlink the dir to a static URL
ssh $SSH_USER@emo.blender.org 'rm '$SSH_UPLOAD'/250PythonDoc && ln -s '$SSH_UPLOAD_FULL' '$SSH_UPLOAD'/250PythonDoc'
## symlink the dir to a static URL
#ssh $SSH_USER@emo.blender.org 'rm '$SSH_UPLOAD'/250PythonDoc && ln -s '$SSH_UPLOAD_FULL' '$SSH_UPLOAD'/250PythonDoc'
# better redirect
ssh $SSH_USER@emo.blender.org 'echo "<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\" content=\"0;url=../blender_python_api_'$BLENDER_VERSION'/\"></head><body>Redirecting...</body></html>" > '$SSH_UPLOAD'/250PythonDoc/index.html'
# pdf
sphinx-build -b latex $SPHINXBASE/sphinx-in $SPHINXBASE/sphinx-out

@ -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)
@ -158,12 +169,21 @@ elseif(APPLE)
intern/GHOST_SystemCocoa.mm
intern/GHOST_SystemPathsCocoa.mm
intern/GHOST_WindowCocoa.mm
intern/GHOST_DisplayManagerCocoa.h
intern/GHOST_SystemCocoa.h
intern/GHOST_SystemPathsCocoa.h
intern/GHOST_WindowCocoa.h
)
if(WITH_INPUT_NDOF)
list(APPEND SRC
intern/GHOST_NDOFManagerCocoa.mm
intern/GHOST_NDOFManagerCocoa.h
)
endif()
else()
list(APPEND SRC
intern/GHOST_DisplayManagerCarbon.cpp
@ -215,6 +235,14 @@ elseif(UNIX)
)
endif()
if(WITH_INPUT_NDOF)
list(APPEND SRC
intern/GHOST_NDOFManagerX11.cpp
intern/GHOST_NDOFManagerX11.h
)
endif()
elseif(WIN32)
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX")
@ -238,6 +266,15 @@ elseif(WIN32)
intern/GHOST_WindowWin32.h
intern/GHOST_TaskbarWin32.h
)
if(WITH_INPUT_NDOF)
list(APPEND SRC
intern/GHOST_NDOFManagerWin32.cpp
intern/GHOST_NDOFManagerWin32.h
)
endif()
endif()
blender_add_lib(bf_intern_ghost "${SRC}" "${INC}" "${INC_SYS}")

@ -288,21 +288,6 @@ extern GHOST_TSuccess GHOST_SetProgressBar(GHOST_WindowHandle windowhandle, floa
* @param windowhandle The handle to the window
*/
extern GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle);
/***************************************************************************************
** N-degree of freedom device management functionality
***************************************************************************************/
/**
* Open N-degree of freedom devices
*/
extern int GHOST_OpenNDOF(GHOST_SystemHandle systemhandle,
GHOST_WindowHandle windowhandle,
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen
);
/***************************************************************************************
** Cursor management functionality

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

@ -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. */

@ -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']
@ -76,7 +76,25 @@ else:
if env['BF_GHOST_DEBUG']:
defs.append('WITH_GHOST_DEBUG')
else:
sources.remove('intern' + os.sep + 'GHOST_EventPrinter.cpp')
sources.remove('intern' + os.sep + 'GHOST_EventPrinter.cpp')
if env['WITH_BF_3DMOUSE']:
defs.append('WITH_INPUT_NDOF')
if env['OURPLATFORM']=='linux2':
incs += ' ' + env['BF_3DMOUSE_INC']
else:
sources.remove('intern' + os.sep + 'GHOST_NDOFManager.cpp')
try:
if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
sources.remove('intern' + os.sep + 'GHOST_NDOFManagerWin32.cpp')
elif window_system=='darwin':
sources.remove('intern' + os.sep + 'GHOST_NDOFManagerCocoa.mm')
else:
sources.remove('intern' + os.sep + 'GHOST_NDOFManagerX11.cpp')
except ValueError:
pass
if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
incs = env['BF_WINTAB_INC'] + ' ' + incs

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

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

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

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

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

@ -19,11 +19,6 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file ghost/intern/GHOST_EventNDOF.h
* \ingroup GHOST
*/
#ifndef _GHOST_EVENT_NDOF_H_
@ -31,32 +26,33 @@
#include "GHOST_Event.h"
/**
* N-degree of freedom device event.
*/
class GHOST_EventNDOF : public GHOST_Event
{
public:
/**
* Constructor.
* @param msec The time this event was generated.
* @param type The type of this event.
* @param x The x-coordinate of the location the cursor was at at the time of the event.
* @param y The y-coordinate of the location the cursor was at at the time of the event.
*/
GHOST_EventNDOF(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window,
GHOST_TEventNDOFData data)
: GHOST_Event(msec, type, window)
{
m_ndofEventData = data;
m_data = &m_ndofEventData;
}
protected:
/** translation & rotation from the device. */
GHOST_TEventNDOFData m_ndofEventData;
};
class GHOST_EventNDOFMotion : public GHOST_Event
{
protected:
GHOST_TEventNDOFMotionData m_axisData;
public:
GHOST_EventNDOFMotion(GHOST_TUns64 time, GHOST_IWindow* window)
: GHOST_Event(time, GHOST_kEventNDOFMotion, window)
{
m_data = &m_axisData;
}
};
class GHOST_EventNDOFButton : public GHOST_Event
{
protected:
GHOST_TEventNDOFButtonData m_buttonData;
public:
GHOST_EventNDOFButton(GHOST_TUns64 time, GHOST_IWindow* window)
: GHOST_Event(time, GHOST_kEventNDOFButton, window)
{
m_data = &m_buttonData;
}
};
#endif // _GHOST_EVENT_NDOF_H_

@ -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);
#endif
return (Pid > 0) ? 0 : 1;
} else
return 1;
}
static const NDOF_ButtonT SpaceNavigator_HID_map[] = {
NDOF_BUTTON_MENU,
NDOF_BUTTON_FIT
};
bool
GHOST_NDOFManager::available() const
{
return m_DeviceHandle != 0;
}
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
};
bool
GHOST_NDOFManager::event_present() const
{
if( currentNdofValues.changed >0) {
printf("time %llu but%u x%i y%i z%i rx%i ry%i rz%i \n" ,
currentNdofValues.time, currentNdofValues.buttons,
currentNdofValues.tx,currentNdofValues.ty,currentNdofValues.tz,
currentNdofValues.rx,currentNdofValues.ry,currentNdofValues.rz);
return true;
}else
return false;
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?
};
void GHOST_NDOFManager::GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const
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)
{
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;
// 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 true;
}
}
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)
return HOME(tx) && HOME(ty) && HOME(tz) && HOME(rx) && HOME(ry) && HOME(rz);
#undef HOME
}
static bool nearHomePosition(GHOST_TEventNDOFMotionData* ndof, float threshold)
{
if (threshold == 0.f) {
return atHomePosition(ndof);
}
else {
#define HOME1(foo) (fabsf(ndof->foo) < threshold)
return HOME1(tx) && HOME1(ty) && HOME1(tz) && HOME1(rx) && HOME1(ry) && HOME1(rz);
#undef HOME1
}
}
bool GHOST_NDOFManager::sendMotionEvent()
{
if (!m_motionEventPending)
return false;
m_motionEventPending = false; // any pending motion is handled right now
GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow();
if (window == NULL) {
return false; // delivery will fail, so don't bother sending
}
GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, window);
GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData();
// scale axis values here to normalize them to around +/- 1
// they are scaled again for overall sensitivity in the WM based on user prefs
const float scale = 1.f / 350.f; // 3Dconnexion devices send +/- 350 usually
data->tx = scale * m_translation[0];
data->ty = scale * m_translation[1];
data->tz = scale * m_translation[2];
data->rx = scale * m_rotation[0];
data->ry = scale * m_rotation[1];
data->rz = scale * m_rotation[2];
data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds
bool handMotion = !nearHomePosition(data, m_deadZone);
// determine what kind of motion event to send (Starting, InProgress, Finishing)
// and where that leaves this NDOF manager (NotStarted, InProgress, Finished)
switch (m_motionState) {
case GHOST_kNotStarted:
case GHOST_kFinished:
if (handMotion) {
data->progress = GHOST_kStarting;
m_motionState = GHOST_kInProgress;
// prev motion time will be ancient, so just make up something reasonable
data->dt = 0.0125f;
}
else {
// send no event and keep current state
delete event;
return false;
}
break;
case GHOST_kInProgress:
if (handMotion) {
data->progress = GHOST_kInProgress;
// keep InProgress state
}
else {
data->progress = GHOST_kFinishing;
m_motionState = GHOST_kFinished;
}
break;
default:
break;
}
#ifdef DEBUG_NDOF_MOTION
printf("ndof motion sent -- %s\n", progress_string[data->progress]);
// show details about this motion event
printf(" T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n",
data->tx, data->ty, data->tz,
data->rx, data->ry, data->rz,
data->dt);
#endif
m_system.pushEvent(event);
m_prevMotionTime = m_motionTime;
return true;
}

@ -1,4 +1,6 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@ -15,43 +17,144 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): none yet.
* Contributor(s):
* Mike Erwin
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file ghost/intern/GHOST_NDOFManager.h
* \ingroup GHOST
*/
#ifndef _GHOST_NDOFMANAGER_H_
#define _GHOST_NDOFMANAGER_H_
#include "GHOST_System.h"
#include "GHOST_IWindow.h"
// #define DEBUG_NDOF_MOTION
// #define DEBUG_NDOF_BUTTONS
typedef enum {
NDOF_UnknownDevice, // <-- motion will work fine, buttons are ignored
// current devices
NDOF_SpaceNavigator,
NDOF_SpaceExplorer,
NDOF_SpacePilotPro,
// older devices
NDOF_SpacePilot
} NDOF_DeviceT;
// NDOF device button event types
typedef enum {
// used internally, never sent
NDOF_BUTTON_NONE,
// these two are available from any 3Dconnexion device
NDOF_BUTTON_MENU,
NDOF_BUTTON_FIT,
// standard views
NDOF_BUTTON_TOP,
NDOF_BUTTON_BOTTOM,
NDOF_BUTTON_LEFT,
NDOF_BUTTON_RIGHT,
NDOF_BUTTON_FRONT,
NDOF_BUTTON_BACK,
// more views
NDOF_BUTTON_ISO1,
NDOF_BUTTON_ISO2,
// 90 degree rotations
// these don't all correspond to physical buttons
NDOF_BUTTON_ROLL_CW,
NDOF_BUTTON_ROLL_CCW,
NDOF_BUTTON_SPIN_CW,
NDOF_BUTTON_SPIN_CCW,
NDOF_BUTTON_TILT_CW,
NDOF_BUTTON_TILT_CCW,
// device control
NDOF_BUTTON_ROTATE,
NDOF_BUTTON_PANZOOM,
NDOF_BUTTON_DOMINANT,
NDOF_BUTTON_PLUS,
NDOF_BUTTON_MINUS,
// general-purpose buttons
// users can assign functions via keymap editor
NDOF_BUTTON_1,
NDOF_BUTTON_2,
NDOF_BUTTON_3,
NDOF_BUTTON_4,
NDOF_BUTTON_5,
NDOF_BUTTON_6,
NDOF_BUTTON_7,
NDOF_BUTTON_8,
NDOF_BUTTON_9,
NDOF_BUTTON_10,
} NDOF_ButtonT;
class GHOST_NDOFManager
{
public:
GHOST_NDOFManager();
virtual ~GHOST_NDOFManager();
GHOST_NDOFManager(GHOST_System&);
int deviceOpen(GHOST_IWindow* window,
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen);
void GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const;
bool available() const;
bool event_present() const;
virtual ~GHOST_NDOFManager() {};
// whether multi-axis functionality is available (via the OS or driver)
// does not imply that a device is plugged in or being used
virtual bool available() = 0;
// each platform's device detection should call this
// use standard USB/HID identifiers
bool setDevice(unsigned short vendor_id, unsigned short product_id);
// filter out small/accidental/uncalibrated motions by
// setting up a "dead zone" around home position
// set to 0 to disable
// 0.1 is a safe and reasonable value
void setDeadZone(float);
// the latest raw axis data from the device
// NOTE: axis data should be in blender view coordinates
// +X is to the right
// +Y is up
// +Z is out of the screen
// for rotations, look from origin to each +axis
// rotations are + when CCW, - when CW
// each platform is responsible for getting axis data into this form
// these values should not be scaled (just shuffled or flipped)
void updateTranslation(short t[3], GHOST_TUns64 time);
void updateRotation(short r[3], GHOST_TUns64 time);
// the latest raw button data from the device
// use HID button encoding (not NDOF_ButtonT)
void updateButton(int button_number, bool press, GHOST_TUns64 time);
void updateButtons(int button_bits, GHOST_TUns64 time);
// NDOFButton events are sent immediately
// processes and sends most recent raw data as an NDOFMotion event
// returns whether an event was sent
bool sendMotionEvent();
protected:
void* m_DeviceHandle;
GHOST_System& m_system;
private:
void sendButtonEvent(NDOF_ButtonT, bool press, GHOST_TUns64 time, GHOST_IWindow*);
void sendKeyEvent(GHOST_TKey, bool press, GHOST_TUns64 time, GHOST_IWindow*);
NDOF_DeviceT m_deviceType;
int m_buttonCount;
int m_buttonMask;
short m_translation[3];
short m_rotation[3];
int m_buttons; // bit field
GHOST_TUns64 m_motionTime; // in milliseconds
GHOST_TUns64 m_prevMotionTime; // time of most recent Motion event sent
GHOST_TProgress m_motionState;
bool m_motionEventPending;
float m_deadZone; // discard motion with each component < this
};
#endif

@ -0,0 +1,50 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s):
* Mike Erwin
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef _GHOST_NDOFMANAGERCOCOA_H_
#define _GHOST_NDOFMANAGERCOCOA_H_
#include "GHOST_NDOFManager.h"
// Event capture is handled within the NDOF manager on Macintosh,
// so there's no need for SystemCocoa to look for them.
class GHOST_NDOFManagerCocoa : public GHOST_NDOFManager
{
public:
GHOST_NDOFManagerCocoa(GHOST_System&);
~GHOST_NDOFManagerCocoa();
// whether multi-axis functionality is available (via the OS or driver)
// does not imply that a device is plugged in or being used
bool available();
private:
unsigned short m_clientID;
};
#endif

@ -0,0 +1,172 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s):
* Mike Erwin
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "GHOST_NDOFManagerCocoa.h"
#include "GHOST_SystemCocoa.h"
extern "C" {
#include <3DconnexionClient/ConnexionClientAPI.h>
#include <stdio.h>
}
// static functions need to talk to these objects:
static GHOST_SystemCocoa* ghost_system = NULL;
static GHOST_NDOFManager* ndof_manager = NULL;
// 3Dconnexion drivers before 10.x are "old"
// not all buttons will work
static bool has_old_driver = true;
static void NDOF_DeviceAdded(io_connect_t connection)
{
printf("ndof: device added\n"); // change these: printf --> informational reports
#if 0 // device preferences will be useful some day
ConnexionDevicePrefs p;
ConnexionGetCurrentDevicePrefs(kDevID_AnyDevice, &p);
#endif
// determine exactly which device is plugged in
SInt32 result = 0;
ConnexionControl(kConnexionCtlGetDeviceID, 0, &result);
unsigned short vendorID = result >> 16;
unsigned short productID = result & 0xffff;
ndof_manager->setDevice(vendorID, productID);
}
static void NDOF_DeviceRemoved(io_connect_t connection)
{
printf("ndof: device removed\n");
}
static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, void* messageArgument)
{
switch (messageType)
{
case kConnexionMsgDeviceState:
{
ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument;
GHOST_TUns64 now = ghost_system->getMilliSeconds();
switch (s->command)
{
case kConnexionCmdHandleAxis:
{
// convert to blender view coordinates
short t[3] = {s->axis[0], -(s->axis[2]), s->axis[1]};
short r[3] = {-(s->axis[3]), s->axis[5], -(s->axis[4])};
ndof_manager->updateTranslation(t, now);
ndof_manager->updateRotation(r, now);
ghost_system->notifyExternalEventProcessed();
break;
}
case kConnexionCmdHandleButtons:
{
int button_bits = has_old_driver ? s->buttons8 : s->buttons;
ndof_manager->updateButtons(button_bits, now);
ghost_system->notifyExternalEventProcessed();
break;
}
case kConnexionCmdAppSpecific:
printf("ndof: app-specific command, param = %hd, value = %d\n", s->param, s->value);
break;
default:
printf("ndof: mystery device command %d\n", s->command);
}
break;
}
case kConnexionMsgPrefsChanged:
// printf("ndof: prefs changed\n"); // this includes app switches
// TODO: look through updated prefs for things blender cares about
break;
case kConnexionMsgCalibrateDevice:
printf("ndof: calibrate\n"); // but what should blender do?
break;
case kConnexionMsgDoMapping:
// printf("ndof: driver did something\n");
// sent when the driver itself consumes an NDOF event
// and performs whatever action is set in user prefs
// 3Dx header file says to ignore these
break;
default:
printf("ndof: mystery event %d\n", messageType);
}
}
GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys)
: GHOST_NDOFManager(sys)
{
if (available())
{
// give static functions something to talk to:
ghost_system = dynamic_cast<GHOST_SystemCocoa*>(&sys);
ndof_manager = this;
OSErr error = InstallConnexionHandlers(NDOF_DeviceEvent, NDOF_DeviceAdded, NDOF_DeviceRemoved);
if (error) {
printf("ndof: error %d while installing handlers\n", error);
return;
}
// Pascal string *and* a four-letter constant. How old-skool.
m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\007blender",
kConnexionClientModeTakeOver, kConnexionMaskAll);
// printf("ndof: client id = %d\n", m_clientID);
if (SetConnexionClientButtonMask != NULL) {
has_old_driver = false;
SetConnexionClientButtonMask(m_clientID, kConnexionMaskAllButtons);
}
else {
printf("ndof: old 3Dx driver installed, some buttons may not work\n");
}
}
else {
printf("ndof: 3Dx driver not found\n");
// This isn't a hard error, just means the user doesn't have a 3D mouse.
}
}
GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa()
{
UnregisterConnexionClient(m_clientID);
CleanupConnexionHandlers();
ghost_system = NULL;
ndof_manager = NULL;
}
bool GHOST_NDOFManagerCocoa::available()
{
// extern OSErr InstallConnexionHandlers() __attribute__((weak_import));
// ^^ not needed since the entire framework is weak-linked
return InstallConnexionHandlers != NULL;
// this means that the driver is installed and dynamically linked to blender
}

@ -0,0 +1,41 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s):
* Mike Erwin
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "GHOST_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;
}

@ -0,0 +1,40 @@
/*
* $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_
#include "GHOST_NDOFManager.h"
class GHOST_NDOFManagerWin32 : public GHOST_NDOFManager
{
public:
GHOST_NDOFManagerWin32(GHOST_System&);
bool available();
};
#endif

@ -0,0 +1,106 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s):
* Mike Erwin
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "GHOST_NDOFManagerX11.h"
#include "GHOST_SystemX11.h"
#include <spnav.h>
#include <stdio.h>
GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys)
:
GHOST_NDOFManager(sys),
m_available(false)
{
setDeadZone(0.1f); // how to calibrate on Linux? throw away slight motion!
if (spnav_open() != -1) {
// determine exactly which device (if any) is plugged in
#define MAX_LINE_LENGTH 100
// look for USB devices with Logitech's vendor ID
FILE* command_output = popen("lsusb -d 046d:","r");
if (command_output) {
char line[MAX_LINE_LENGTH] = {0};
while (fgets(line, MAX_LINE_LENGTH, command_output)) {
unsigned short vendor_id = 0, product_id = 0;
if (sscanf(line, "Bus %*d Device %*d: ID %hx:%hx", &vendor_id, &product_id) == 2)
if (setDevice(vendor_id, product_id)) {
m_available = true;
break; // stop looking once the first 3D mouse is found
}
}
pclose(command_output);
}
}
else {
printf("ndof: spacenavd not found\n");
// This isn't a hard error, just means the user doesn't have a 3D mouse.
}
}
GHOST_NDOFManagerX11::~GHOST_NDOFManagerX11()
{
if (m_available)
spnav_close();
}
bool GHOST_NDOFManagerX11::available()
{
return m_available;
}
//bool GHOST_NDOFManagerX11::identifyDevice()
//{
//
//}
bool GHOST_NDOFManagerX11::processEvents()
{
GHOST_TUns64 now = m_system.getMilliSeconds();
bool anyProcessed = false;
spnav_event e;
while (spnav_poll_event(&e)) {
switch (e.type) {
case SPNAV_EVENT_MOTION:
{
// convert to blender view coords
short t[3] = {e.motion.x, e.motion.y, -e.motion.z};
short r[3] = {-e.motion.rx, -e.motion.ry, e.motion.rz};
updateTranslation(t, now);
updateRotation(r, now);
break;
}
case SPNAV_EVENT_BUTTON:
updateButton(e.button.bnum, e.button.press, now);
break;
}
anyProcessed = true;
}
return anyProcessed;
}

@ -0,0 +1,49 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s):
* Mike Erwin
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef _GHOST_NDOFMANAGERX11_H_
#define _GHOST_NDOFMANAGERX11_H_
#include "GHOST_NDOFManager.h"
/* Event capture is handled within the NDOF manager on Linux,
* so there's no need for SystemX11 to look for them. */
class GHOST_NDOFManagerX11 : public GHOST_NDOFManager
{
public:
GHOST_NDOFManagerX11(GHOST_System&);
~GHOST_NDOFManagerX11();
bool available();
bool processEvents();
private:
// bool identifyDevice();
bool m_available;
};
#endif

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

@ -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;
/** The N-degree of freedom device manager */
GHOST_NDOFManager* m_ndofManager;
#ifdef WITH_INPUT_NDOF
/** The N-degree of freedom device manager */
GHOST_NDOFManager* m_ndofManager;
#endif
/** Prints all the events. */
#ifdef GHOST_DEBUG
@ -364,10 +349,12 @@ inline GHOST_WindowManager* GHOST_System::getWindowManager() const
return m_windowManager;
}
#ifdef WITH_INPUT_NDOF
inline GHOST_NDOFManager* GHOST_System::getNDOFManager() const
{
return m_ndofManager;
}
#endif
#endif // _GHOST_SYSTEM_H_

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

@ -52,7 +52,7 @@
#include "GHOST_TimerTask.h"
#include "GHOST_WindowManager.h"
#include "GHOST_WindowCocoa.h"
#include "GHOST_NDOFManager.h"
#include "GHOST_NDOFManagerCocoa.h"
#include "AssertMacros.h"
#pragma mark KeyMap, mouse converters
@ -596,6 +596,11 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
GHOST_TSuccess success = GHOST_System::init();
if (success) {
#ifdef WITH_INPUT_NDOF
m_ndofManager = new GHOST_NDOFManagerCocoa(*this);
#endif
//ProcessSerialNumber psn;
//Carbon stuff to move window & menu to foreground
@ -1007,6 +1012,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
return GHOST_kSuccess;
}
void GHOST_SystemCocoa::notifyExternalEventProcessed()
{
m_outsideLoopEventProcessed = true;
}
//Note: called from NSWindow delegate
GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window)
{
@ -1560,6 +1570,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
GHOST_TInt32 delta;
double deltaF = [event deltaY];
if (deltaF == 0.0) deltaF = [event deltaX]; // make blender decide if it's horizontal scroll
if (deltaF == 0.0) break; //discard trackpad delta=0 events
delta = deltaF > 0.0 ? 1 : -1;

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

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

@ -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,17 @@
#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"
#include "GHOST_NDOFManagerWin32.h"
// Key code values not found in winuser.h
#ifndef VK_MINUS
@ -158,18 +125,25 @@
#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 */
RAWINPUTDEVICE devices[2];
memset(devices, 0, 2 * sizeof(RAWINPUTDEVICE));
return RegisterRawInputDevices(&device, 1, sizeof(device));
};
// multi-axis mouse (SpaceNavigator, etc.)
devices[0].usUsagePage = 0x01;
devices[0].usUsage = 0x08;
// Initiates WM_INPUT messages from keyboard
// That way GHOST can retrieve true keys
devices[1].usUsagePage = 0x01;
devices[1].usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
if (RegisterRawInputDevices(devices, 2, sizeof(RAWINPUTDEVICE)))
puts("registered for RawInput (spacenav & keyboard)");
else
printf("could not register for RawInput: %d\n", (int)GetLastError());
}
GHOST_SystemWin32::GHOST_SystemWin32()
: m_hasPerformanceCounter(false), m_freq(0), m_start(0)
@ -186,6 +160,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 +222,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 +363,15 @@ GHOST_TSuccess GHOST_SystemWin32::init()
GHOST_TSuccess success = GHOST_System::init();
/* Disable scaling on high DPI displays on Vista */
HMODULE
user32 = ::LoadLibraryA("user32.dll");
typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)();
LPFNSETPROCESSDPIAWARE SetProcessDPIAware =
(LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware");
if (SetProcessDPIAware)
SetProcessDPIAware();
#ifdef NEED_RAW_PROC
pRegisterRawInputDevices = (LPFNDLLRRID)GetProcAddress(user32, "RegisterRawInputDevices");
pGetRawInputData = (LPFNDLLGRID)GetProcAddress(user32, "GetRawInputData");
#else
FreeLibrary(user32);
#endif
/* Initiates WM_INPUT messages from keyboard */
initKeyboardRawInput();
FreeLibrary(user32);
initRawInput();
// Determine whether this system has a high frequency performance counter. */
m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE;
@ -440,104 +412,84 @@ GHOST_TSuccess GHOST_SystemWin32::init()
GHOST_TSuccess GHOST_SystemWin32::exit()
{
#ifdef NEED_RAW_PROC
FreeLibrary(user32);
#endif
return GHOST_System::exit();
}
GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, int * keyDown, char * vk)
GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int * keyDown, char * vk)
{
unsigned int size = 0;
char * data;
GHOST_TKey key = GHOST_kKeyUnknown;
if(!keyDown)
return GHOST_kKeyUnknown;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, 0, &size, sizeof(RAWINPUTHEADER));
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
if((data = (char*)malloc(size)) &&
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER)))
{
RAWINPUT ri;
memcpy(&ri,data,(size < sizeof(ri)) ? size : sizeof(ri));
if (ri.header.dwType == RIM_TYPEKEYBOARD)
{
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
GHOST_ModifierKeys modifiers;
system->retrieveModifierKeys(modifiers);
*keyDown = !(ri.data.keyboard.Flags & RI_KEY_BREAK);
key = this->convertKey(window, ri.data.keyboard.VKey, ri.data.keyboard.MakeCode, (ri.data.keyboard.Flags&(RI_KEY_E1|RI_KEY_E0)));
// extra handling of modifier keys: don't send repeats out from GHOST
if(key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt)
{
bool changed = false;
GHOST_TModifierKeyMask modifier;
switch(key) {
case GHOST_kKeyLeftShift:
{
changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != (bool)*keyDown);
modifier = GHOST_kModifierKeyLeftShift;
}
break;
case GHOST_kKeyRightShift:
{
changed = (modifiers.get(GHOST_kModifierKeyRightShift) != (bool)*keyDown);
modifier = GHOST_kModifierKeyRightShift;
}
break;
case GHOST_kKeyLeftControl:
{
changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != (bool)*keyDown);
modifier = GHOST_kModifierKeyLeftControl;
}
break;
case GHOST_kKeyRightControl:
{
changed = (modifiers.get(GHOST_kModifierKeyRightControl) != (bool)*keyDown);
modifier = GHOST_kModifierKeyRightControl;
}
break;
case GHOST_kKeyLeftAlt:
{
changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != (bool)*keyDown);
modifier = GHOST_kModifierKeyLeftAlt;
}
break;
case GHOST_kKeyRightAlt:
{
changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != (bool)*keyDown);
modifier = GHOST_kModifierKeyRightAlt;
}
break;
default: break;
}
if(changed)
{
modifiers.set(modifier, (bool)*keyDown);
system->storeModifierKeys(modifiers);
}
else
{
key = GHOST_kKeyUnknown;
}
}
GHOST_ModifierKeys modifiers;
system->retrieveModifierKeys(modifiers);
*keyDown = !(raw.data.keyboard.Flags & RI_KEY_BREAK);
key = this->convertKey(window, raw.data.keyboard.VKey, raw.data.keyboard.MakeCode, (raw.data.keyboard.Flags&(RI_KEY_E1|RI_KEY_E0)));
// extra handling of modifier keys: don't send repeats out from GHOST
if(key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt)
{
bool changed = false;
GHOST_TModifierKeyMask modifier;
switch(key) {
case GHOST_kKeyLeftShift:
{
changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != (bool)*keyDown);
modifier = GHOST_kModifierKeyLeftShift;
}
break;
case GHOST_kKeyRightShift:
{
changed = (modifiers.get(GHOST_kModifierKeyRightShift) != (bool)*keyDown);
modifier = GHOST_kModifierKeyRightShift;
}
break;
case GHOST_kKeyLeftControl:
{
changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != (bool)*keyDown);
modifier = GHOST_kModifierKeyLeftControl;
}
break;
case GHOST_kKeyRightControl:
{
changed = (modifiers.get(GHOST_kModifierKeyRightControl) != (bool)*keyDown);
modifier = GHOST_kModifierKeyRightControl;
}
break;
case GHOST_kKeyLeftAlt:
{
changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != (bool)*keyDown);
modifier = GHOST_kModifierKeyLeftAlt;
}
break;
case GHOST_kKeyRightAlt:
{
changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != (bool)*keyDown);
modifier = GHOST_kModifierKeyRightAlt;
}
break;
default: break;
}
if(changed)
{
modifiers.set(modifier, (bool)*keyDown);
system->storeModifierKeys(modifiers);
}
else
{
key = GHOST_kKeyUnknown;
}
}
if(vk) *vk = ri.data.keyboard.VKey;
};
};
free(data);
if(vk) *vk = raw.data.keyboard.VKey;
return key;
}
@ -741,12 +693,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 +728,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 +757,102 @@ 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);
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
{
#if 0
// I'm getting garbage bits -- examine whole report:
printf("ndof: HID report for buttons [");
for (int i = 0; i < raw.data.hid.dwSizeHid; ++i)
printf(" %02X", data[i]);
printf(" ]\n");
#endif
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 +869,38 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
// Keyboard events, processed
////////////////////////////////////////////////////////////////////////
case WM_INPUT:
{
// check WM_INPUT from input sink when ghost window is not in the foreground
if (wParam == RIM_INPUTSINK) {
if (GetFocus() != hwnd) // WM_INPUT message not for this window
return 0;
} //else wPAram == RIM_INPUT
event = processKeyEvent(window, wParam, lParam);
if (!event) {
GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
GHOST_PRINT(msg)
GHOST_PRINT(" key ignored\n")
} //else wParam == RIM_INPUT
RAWINPUT raw;
RAWINPUT* raw_ptr = &raw;
UINT rawSize = sizeof(RAWINPUT);
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER));
switch (raw.header.dwType)
{
case RIM_TYPEKEYBOARD:
event = processKeyEvent(window, raw);
if (!event) {
GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
GHOST_PRINT(msg)
GHOST_PRINT(" key ignored\n")
}
break;
case RIM_TYPEHID:
#ifdef WITH_INPUT_NDOF
if (system->processNDOF(raw))
eventHandled = true;
#endif
break;
}
break;
break;
}
////////////////////////////////////////////////////////////////////////
// Keyboard events, ignored
////////////////////////////////////////////////////////////////////////
@ -839,9 +910,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
case WM_SYSKEYUP:
/* These functions were replaced by WM_INPUT*/
case WM_CHAR:
/* The WM_CHAR message is posted to the window with the keyboard focus when
* a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR
* contains the character code of the key that was pressed.
/* The WM_CHAR message is posted to the window with the keyboard focus when
* a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR
* contains the character code of the key that was pressed.
*/
case WM_DEADCHAR:
/* The WM_DEADCHAR message is posted to the window with the keyboard focus when a
@ -989,11 +1060,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 +1198,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 +1219,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 +1293,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

@ -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,22 @@ 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);
/**
* 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);
/**
* Returns the local state of the modifier keys (from the message queue).
* @param keys The state of the keys.
@ -412,11 +334,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 +362,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 +395,3 @@ inline void GHOST_SystemWin32::handleKeyboardChange(void)
}
}
#endif // _GHOST_SYSTEM_WIN32_H_

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

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

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

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

@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
__all__ = (
"paths",
@ -26,13 +26,14 @@ __all__ = (
"disable",
"reset_all",
"module_bl_info",
)
)
import bpy as _bpy
error_duplicates = False
def paths():
# RELEASE SCRIPTS: official scripts distributed in Blender releases
paths = _bpy.utils.script_paths("addons")
@ -128,7 +129,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 +149,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 +171,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 +216,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 +264,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 +321,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

@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
"""
Give access to blender data and utility functions.
@ -31,7 +31,7 @@ __all__ = (
"props",
"types",
"utils",
)
)
# internal blender C module
@ -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:

@ -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
@ -239,4 +267,4 @@ def basename(path):
Use for Windows compatibility.
"""
return _os.path.basename(path[2:] if path.startswith("//") else path)
return _os.path.basename(path[2:] if path[:2] in {"//", b"//"} else path)

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

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

@ -16,11 +16,11 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
__all__ = (
"load_image",
)
)
# limited replacement for BPyImage.comprehensiveImageLoad
@ -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, )

@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
__all__ = (
"ExportHelper",
@ -31,15 +31,34 @@ __all__ = (
"path_reference_copy",
"path_reference_mode",
"unique_name"
)
)
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
if check_extension is not None:
filepath = bpy.path.ensure_ext(self.filepath,
self.filename_ext
if check_extension
else "")
filepath = bpy.path.ensure_ext(self.filepath, self.filename_ext if check_extension else "")
if filepath != self.filepath:
self.filepath = filepath
change_ext = True
if filepath != self.filepath:
self.filepath = filepath
return 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,14 +236,19 @@ 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:
return Matrix(_axis_convert_matrix[i])
assert(0)
def axis_conversion_ensure(operator, forward_attr, up_attr):
"""
Function to ensure an operator has valid axis conversion settings, intended
@ -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
@ -184,9 +266,9 @@ def axis_conversion_ensure(operator, forward_attr, up_attr):
def validate(axis_forward, axis_up):
if axis_forward[-1] == axis_up[-1]:
axis_up = axis_up[0:-1] + 'XYZ'[('XYZ'.index(axis_up[-1]) + 1) % 3]
return axis_forward, axis_up
change = False
axis = getattr(operator, forward_attr), getattr(operator, up_attr)
@ -201,9 +283,10 @@ 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 != 'NONE':
if ob.parent and ob.parent.dupli_type in {'VERTS', 'FACES'}:
return False, None
if ob.dupli_type != '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
@ -287,7 +384,9 @@ def path_reference(filepath, base_src, base_dst, mode='AUTO', copy_subdir="", co
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

@ -26,7 +26,7 @@ __all__ = (
"edge_loops_from_edges",
"ngon_tesselate",
"face_random_points",
)
)
def mesh_linked_faces(mesh):
@ -170,8 +170,8 @@ def edge_loops_from_faces(mesh, faces=None, seams=()):
# from knowing the last 2, look for th next.
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)
@ -296,7 +299,8 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
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)]
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:

@ -16,12 +16,12 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
__all__ = (
"add_object_align_init",
"object_data_add",
)
)
import bpy
@ -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:

@ -16,13 +16,13 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
__all__ = (
"region_2d_to_vector_3d",
"region_2d_to_location_3d",
"location_3d_to_region_2d",
)
)
def region_2d_to_vector_3d(region, rv3d, coord):
@ -50,11 +50,11 @@ def region_2d_to_vector_3d(region, rv3d, coord):
-0.5
))
w = (out[0] * persinv[0][3]) + \
(out[1] * persinv[1][3]) + \
(out[2] * persinv[2][3]) + persinv[3][3]
w = ((out[0] * persinv[0][3]) +
(out[1] * persinv[1][3]) +
(out[2] * persinv[2][3]) + persinv[3][3])
return ((out * persinv) / w) - rv3d.view_matrix.inverted()[3].xyz
return ((persinv * out) / w) - rv3d.view_matrix.inverted()[3].xyz
else:
return rv3d.view_matrix.inverted()[2].xyz.normalized()
@ -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):
@ -116,7 +124,7 @@ def location_3d_to_region_2d(region, rv3d, coord):
"""
from mathutils import Vector
prj = Vector((coord[0], coord[1], coord[2], 1.0)) * rv3d.perspective_matrix
prj = rv3d.perspective_matrix * Vector((coord[0], coord[1], coord[2], 1.0))
if prj.w > 0.0:
width_half = region.width / 2.0
height_half = region.height / 2.0

@ -144,21 +144,21 @@ class _GenericBone:
""" Vector pointing down the x-axis of the bone.
"""
from mathutils import Vector
return Vector((1.0, 0.0, 0.0)) * self.matrix.to_3x3()
return self.matrix.to_3x3() * Vector((1.0, 0.0, 0.0))
@property
def y_axis(self):
""" Vector pointing down the x-axis of the bone.
"""
from mathutils import Vector
return Vector((0.0, 1.0, 0.0)) * self.matrix.to_3x3()
return self.matrix.to_3x3() * Vector((0.0, 1.0, 0.0))
@property
def z_axis(self):
""" Vector pointing down the x-axis of the bone.
"""
from mathutils import Vector
return Vector((0.0, 0.0, 1.0)) * self.matrix.to_3x3()
return self.matrix.to_3x3() * Vector((0.0, 0.0, 1.0))
@property
def basename(self):
@ -294,9 +294,9 @@ class EditBone(StructRNA, _GenericBone, metaclass=StructMetaPropGroup):
:type roll: bool
"""
from mathutils import Vector
z_vec = Vector((0.0, 0.0, 1.0)) * self.matrix.to_3x3()
self.tail = self.tail * matrix
self.head = self.head * matrix
z_vec = self.matrix.to_3x3() * Vector((0.0, 0.0, 1.0))
self.tail = matrix * self.tail
self.head = matrix * self.head
if scale:
scalar = matrix.median_scale
@ -304,7 +304,7 @@ class EditBone(StructRNA, _GenericBone, metaclass=StructMetaPropGroup):
self.tail_radius *= scalar
if roll:
self.align_roll(z_vec * matrix)
self.align_roll(matrix * z_vec)
def ord_ind(i1, i2):

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

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

@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
import bpy
import mathutils
@ -40,8 +40,10 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
for minor_index in range(minor_seg):
angle = 2 * pi * minor_index / minor_seg
vec = Vector((major_rad + (cos(angle) * minor_rad), 0.0,
(sin(angle) * minor_rad))) * quat
vec = quat * Vector((major_rad + (cos(angle) * minor_rad),
0.0,
(sin(angle) * minor_rad),
))
verts.extend(vec[:])
@ -72,7 +74,11 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
return verts, faces
from bpy.props import FloatProperty, IntProperty, BoolProperty, FloatVectorProperty
from bpy.props import (FloatProperty,
IntProperty,
BoolProperty,
FloatVectorProperty,
)
class AddTorus(bpy.types.Operator):
@ -82,7 +88,8 @@ class AddTorus(bpy.types.Operator):
bl_options = {'REGISTER', 'UNDO'}
major_radius = FloatProperty(name="Major Radius",
description="Radius from the origin to the center of the cross sections",
description=("Radius from the origin to the "
"center of the cross sections"),
default=1.0, min=0.01, max=100.0)
minor_radius = FloatProperty(name="Minor Radius",
description="Radius of the torus' cross section",

@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
import bpy
from bpy.props import StringProperty
@ -28,7 +28,11 @@ class EditExternally(bpy.types.Operator):
bl_label = "Image Edit Externally"
bl_options = {'REGISTER'}
filepath = StringProperty(name="File Path", description="Path to an image file", maxlen=1024, default="")
filepath = StringProperty(
name="File Path",
description="Path to an image file",
maxlen=1024,
)
def _editor_guess(self, context):
import sys
@ -57,10 +61,13 @@ class EditExternally(bpy.types.Operator):
def execute(self, context):
import os
import subprocess
filepath = bpy.path.abspath(self.filepath)
filepath = os.path.normpath(bpy.path.abspath(self.filepath))
if not os.path.exists(filepath):
self.report({'ERROR'}, "Image path %r not found, image may be packed or unsaved." % filepath)
self.report({'ERROR'},
"Image path %r not found, image may be packed or "
"unsaved." % filepath)
return {'CANCELLED'}
cmd = self._editor_guess(context) + [filepath]
@ -70,7 +77,10 @@ class EditExternally(bpy.types.Operator):
except:
import traceback
traceback.print_exc()
self.report({'ERROR'}, "Image editor not found, please specify in User Preferences > File")
self.report({'ERROR'},
"Image editor not found, "
"please specify in User Preferences > File")
return {'CANCELLED'}
return {'FINISHED'}
@ -104,7 +114,9 @@ class SaveDirty(bpy.types.Operator):
if "\\" not in filepath and "/" not in filepath:
self.report({'WARNING'}, "Invalid path: " + filepath)
elif filepath in unique_paths:
self.report({'WARNING'}, "Path used by more then one image: " + filepath)
self.report({'WARNING'},
"Path used by more then one image: %r" %
filepath)
else:
unique_paths.add(filepath)
image.save()
@ -142,14 +154,14 @@ class ProjectEdit(bpy.types.Operator):
filepath = os.path.basename(bpy.data.filepath)
filepath = os.path.splitext(filepath)[0]
# filepath = bpy.path.clean_name(filepath) # fixes <memory> rubbish, needs checking
# fixes <memory> rubbish, needs checking
# filepath = bpy.path.clean_name(filepath)
if filepath.startswith(".") or filepath == "":
# TODO, have a way to check if the file is saved, assume startup.blend
if bpy.data.is_saved:
filepath = "//" + filepath
else:
tmpdir = context.user_preferences.filepaths.temporary_directory
filepath = os.path.join(tmpdir, "project_edit")
else:
filepath = "//" + filepath
obj = context.object

@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
import bpy
@ -111,7 +111,8 @@ class MeshMirrorUV(bpy.types.Operator):
#for i, v in enumerate(mesh.vertices):
vmap = {}
for mirror_a, mirror_b in (mirror_gt, mirror_lt), (mirror_lt, mirror_gt):
for mirror_a, mirror_b in ((mirror_gt, mirror_lt),
(mirror_lt, mirror_gt)):
for co, i in mirror_a.items():
nco = (-co[0], co[1], co[2])
j = mirror_b.get(nco)
@ -120,7 +121,8 @@ class MeshMirrorUV(bpy.types.Operator):
active_uv_layer = mesh.uv_textures.active.data
fuvs = [(uv.uv1, uv.uv2, uv.uv3, uv.uv4) for uv in active_uv_layer]
fuvs_cpy = [(uv[0].copy(), uv[1].copy(), uv[2].copy(), uv[3].copy()) for uv in fuvs]
fuvs_cpy = [(uv[0].copy(), uv[1].copy(), uv[2].copy(), uv[3].copy())
for uv in fuvs]
# as a list
faces = mesh.faces[:]

@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
import bpy
from bpy.props import StringProperty, BoolProperty, EnumProperty, IntProperty
@ -28,9 +28,22 @@ class SelectPattern(bpy.types.Operator):
bl_label = "Select Pattern"
bl_options = {'REGISTER', 'UNDO'}
pattern = StringProperty(name="Pattern", description="Name filter using '*' and '?' wildcard chars", maxlen=32, default="*")
case_sensitive = BoolProperty(name="Case Sensitive", description="Do a case sensitive compare", default=False)
extend = BoolProperty(name="Extend", description="Extend the existing selection", default=True)
pattern = StringProperty(
name="Pattern",
description="Name filter using '*' and '?' wildcard chars",
maxlen=32,
default="*",
)
case_sensitive = BoolProperty(
name="Case Sensitive",
description="Do a case sensitive compare",
default=False,
)
extend = BoolProperty(
name="Extend",
description="Extend the existing selection",
default=True,
)
def execute(self, context):
@ -39,22 +52,37 @@ class SelectPattern(bpy.types.Operator):
if self.case_sensitive:
pattern_match = fnmatch.fnmatchcase
else:
pattern_match = lambda a, b: fnmatch.fnmatchcase(a.upper(), b.upper())
pattern_match = (lambda a, b:
fnmatch.fnmatchcase(a.upper(), b.upper()))
is_ebone = False
obj = context.object
if obj and obj.mode == 'POSE':
items = obj.data.bones
if not self.extend:
bpy.ops.pose.select_all(action='DESELECT')
elif obj and obj.type == 'ARMATURE' and obj.mode == 'EDIT':
items = obj.data.edit_bones
if not self.extend:
bpy.ops.armature.select_all(action='DESELECT')
is_ebone = True
else:
items = context.visible_objects
if not self.extend:
bpy.ops.object.select_all(action='DESELECT')
# Can be pose bones or objects
for item in items:
if pattern_match(item.name, self.pattern):
item.select = True
elif not self.extend:
item.select = False
# hrmf, perhaps there should be a utility function for this.
if is_ebone:
item.select_head = True
item.select_tail = True
if item.use_connect:
item_parent = item.parent
if item_parent is not None:
item_parent.select_tail = True
return {'FINISHED'}
@ -93,19 +121,25 @@ class SelectCamera(bpy.types.Operator):
class SelectHierarchy(bpy.types.Operator):
'''Select object relative to the active objects position in the hierarchy'''
'''Select object relative to the active objects position''' \
'''in the hierarchy'''
bl_idname = "object.select_hierarchy"
bl_label = "Select Hierarchy"
bl_options = {'REGISTER', 'UNDO'}
direction = EnumProperty(items=(
('PARENT', "Parent", ""),
('CHILD', "Child", "")),
name="Direction",
description="Direction to select in the hierarchy",
default='PARENT')
direction = EnumProperty(
items=(('PARENT', "Parent", ""),
('CHILD', "Child", ""),
),
name="Direction",
description="Direction to select in the hierarchy",
default='PARENT')
extend = BoolProperty(name="Extend", description="Extend the existing selection", default=False)
extend = BoolProperty(
name="Extend",
description="Extend the existing selection",
default=False,
)
@classmethod
def poll(cls, context):
@ -163,7 +197,12 @@ class SubdivisionSet(bpy.types.Operator):
level = IntProperty(name="Level",
default=1, min=-100, max=100, soft_min=-6, soft_max=6)
relative = BoolProperty(name="Relative", description="Apply the subsurf level as an offset relative to the current level", default=False)
relative = BoolProperty(
name="Relative",
description=("Apply the subsurf level as an offset "
"relative to the current level"),
default=False,
)
@classmethod
def poll(cls, context):
@ -215,7 +254,8 @@ class SubdivisionSet(bpy.types.Operator):
mod = obj.modifiers.new("Subsurf", 'SUBSURF')
mod.levels = level
except:
self.report({'WARNING'}, "Modifiers cannot be added to object: " + obj.name)
self.report({'WARNING'},
"Modifiers cannot be added to object: " + obj.name)
for obj in context.selected_editable_objects:
set_object_subd(obj)
@ -224,23 +264,37 @@ class SubdivisionSet(bpy.types.Operator):
class ShapeTransfer(bpy.types.Operator):
'''Copy another selected objects active shape to this one by applying the relative offsets'''
'''Copy another selected objects active shape to this one by ''' \
'''applying the relative offsets'''
bl_idname = "object.shape_key_transfer"
bl_label = "Transfer Shape Key"
bl_options = {'REGISTER', 'UNDO'}
mode = EnumProperty(items=(
('OFFSET', "Offset", "Apply the relative positional offset"),
('RELATIVE_FACE', "Relative Face", "Calculate the geometricly relative position (using faces)."),
('RELATIVE_EDGE', "Relative Edge", "Calculate the geometricly relative position (using edges).")),
name="Transformation Mode",
description="Method to apply relative shape positions to the new shape",
default='OFFSET')
use_clamp = BoolProperty(name="Clamp Offset",
description="Clamp the transformation to the distance each vertex moves in the original shape.",
default=False)
mode = EnumProperty(
items=(('OFFSET',
"Offset",
"Apply the relative positional offset",
),
('RELATIVE_FACE',
"Relative Face",
"Calculate relative position (using faces).",
),
('RELATIVE_EDGE',
"Relative Edge",
"Calculate relative position (using edges).",
),
),
name="Transformation Mode",
description="Relative shape positions to the new shape method",
default='OFFSET',
)
use_clamp = BoolProperty(
name="Clamp Offset",
description=("Clamp the transformation to the distance each "
"vertex moves in the original shape."),
default=False,
)
def _main(self, ob_act, objects, mode='OFFSET', use_clamp=False):
@ -272,13 +326,16 @@ class ShapeTransfer(bpy.types.Operator):
orig_shape_coords = me_cos(ob_act.active_shape_key.data)
orig_normals = me_nos(me.vertices)
# orig_coords = me_cos(me.vertices) # the actual mverts location isnt as relyable as the base shape :S
# the actual mverts location isnt as relyable as the base shape :S
# orig_coords = me_cos(me.vertices)
orig_coords = me_cos(me.shape_keys.key_blocks[0].data)
for ob_other in objects:
me_other = ob_other.data
if len(me_other.vertices) != len(me.vertices):
self.report({'WARNING'}, "Skipping '%s', vertex count differs" % ob_other.name)
self.report({'WARNING'},
("Skipping '%s', "
"vertex count differs") % ob_other.name)
continue
target_normals = me_nos(me_other.vertices)
@ -290,53 +347,90 @@ class ShapeTransfer(bpy.types.Operator):
ob_add_shape(ob_other, orig_key_name)
# editing the final coords, only list that stores wrapped coords
target_shape_coords = [v.co for v in ob_other.active_shape_key.data]
target_shape_coords = [v.co for v in
ob_other.active_shape_key.data]
median_coords = [[] for i in range(len(me.vertices))]
# Method 1, edge
if mode == 'OFFSET':
for i, vert_cos in enumerate(median_coords):
vert_cos.append(target_coords[i] + (orig_shape_coords[i] - orig_coords[i]))
vert_cos.append(target_coords[i] +
(orig_shape_coords[i] - orig_coords[i]))
elif mode == 'RELATIVE_FACE':
for face in me.faces:
i1, i2, i3, i4 = face.vertices_raw
if i4 != 0:
pt = barycentric_transform(orig_shape_coords[i1],
orig_coords[i4], orig_coords[i1], orig_coords[i2],
target_coords[i4], target_coords[i1], target_coords[i2])
orig_coords[i4],
orig_coords[i1],
orig_coords[i2],
target_coords[i4],
target_coords[i1],
target_coords[i2],
)
median_coords[i1].append(pt)
pt = barycentric_transform(orig_shape_coords[i2],
orig_coords[i1], orig_coords[i2], orig_coords[i3],
target_coords[i1], target_coords[i2], target_coords[i3])
orig_coords[i1],
orig_coords[i2],
orig_coords[i3],
target_coords[i1],
target_coords[i2],
target_coords[i3],
)
median_coords[i2].append(pt)
pt = barycentric_transform(orig_shape_coords[i3],
orig_coords[i2], orig_coords[i3], orig_coords[i4],
target_coords[i2], target_coords[i3], target_coords[i4])
orig_coords[i2],
orig_coords[i3],
orig_coords[i4],
target_coords[i2],
target_coords[i3],
target_coords[i4],
)
median_coords[i3].append(pt)
pt = barycentric_transform(orig_shape_coords[i4],
orig_coords[i3], orig_coords[i4], orig_coords[i1],
target_coords[i3], target_coords[i4], target_coords[i1])
orig_coords[i3],
orig_coords[i4],
orig_coords[i1],
target_coords[i3],
target_coords[i4],
target_coords[i1],
)
median_coords[i4].append(pt)
else:
pt = barycentric_transform(orig_shape_coords[i1],
orig_coords[i3], orig_coords[i1], orig_coords[i2],
target_coords[i3], target_coords[i1], target_coords[i2])
orig_coords[i3],
orig_coords[i1],
orig_coords[i2],
target_coords[i3],
target_coords[i1],
target_coords[i2],
)
median_coords[i1].append(pt)
pt = barycentric_transform(orig_shape_coords[i2],
orig_coords[i1], orig_coords[i2], orig_coords[i3],
target_coords[i1], target_coords[i2], target_coords[i3])
orig_coords[i1],
orig_coords[i2],
orig_coords[i3],
target_coords[i1],
target_coords[i2],
target_coords[i3],
)
median_coords[i2].append(pt)
pt = barycentric_transform(orig_shape_coords[i3],
orig_coords[i2], orig_coords[i3], orig_coords[i1],
target_coords[i2], target_coords[i3], target_coords[i1])
orig_coords[i2],
orig_coords[i3],
orig_coords[i1],
target_coords[i2],
target_coords[i3],
target_coords[i1],
)
median_coords[i3].append(pt)
elif mode == 'RELATIVE_EDGE':
@ -374,7 +468,8 @@ class ShapeTransfer(bpy.types.Operator):
if use_clamp:
# clamp to the same movement as the original
# breaks copy between different scaled meshes.
len_from = (orig_shape_coords[i] - orig_coords[i]).length
len_from = (orig_shape_coords[i] -
orig_coords[i]).length
ofs = co - target_coords[i]
ofs.length = len_from
co = target_coords[i] + ofs
@ -395,7 +490,10 @@ class ShapeTransfer(bpy.types.Operator):
if 1: # swap from/to, means we cant copy to many at once.
if len(objects) != 1:
self.report({'ERROR'}, "Expected one other selected mesh object to copy from")
self.report({'ERROR'},
("Expected one other selected "
"mesh object to copy from"))
return {'CANCELLED'}
ob_act, objects = objects[0], [ob_act]
@ -429,11 +527,14 @@ class JoinUVs(bpy.types.Operator):
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
if not mesh.uv_textures:
self.report({'WARNING'}, "Object: %s, Mesh: '%s' has no UVs\n" % (obj.name, mesh.name))
self.report({'WARNING'},
"Object: %s, Mesh: '%s' has no UVs"
% (obj.name, mesh.name))
else:
len_faces = len(mesh.faces)
uv_array = array.array('f', [0.0] * 8) * len_faces # seems to be the fastest way to create an array
# seems to be the fastest way to create an array
uv_array = array.array('f', [0.0] * 8) * len_faces
mesh.uv_textures.active.data.foreach_get("uv_raw", uv_array)
objects = context.selected_editable_objects[:]
@ -450,11 +551,18 @@ class JoinUVs(bpy.types.Operator):
mesh_other.tag = True
if len(mesh_other.faces) != len_faces:
self.report({'WARNING'}, "Object: %s, Mesh: '%s' has %d faces, expected %d\n" % (obj_other.name, mesh_other.name, len(mesh_other.faces), len_faces))
self.report({'WARNING'}, "Object: %s, Mesh: "
"'%s' has %d faces, expected %d\n"
% (obj_other.name,
mesh_other.name,
len(mesh_other.faces),
len_faces),
)
else:
uv_other = mesh_other.uv_textures.active
if not uv_other:
uv_other = mesh_other.uv_textures.new() # should return the texture it adds
# should return the texture it adds
uv_other = mesh_other.uv_textures.new()
# finally do the copy
uv_other.data.foreach_set("uv_raw", uv_array)
@ -482,14 +590,18 @@ class MakeDupliFace(bpy.types.Operator):
SCALE_FAC = 0.01
offset = 0.5 * SCALE_FAC
base_tri = Vector((-offset, -offset, 0.0)), Vector((offset, -offset, 0.0)), Vector((offset, offset, 0.0)), Vector((-offset, offset, 0.0))
base_tri = (Vector((-offset, -offset, 0.0)),
Vector((+offset, -offset, 0.0)),
Vector((+offset, +offset, 0.0)),
Vector((-offset, +offset, 0.0)),
)
def matrix_to_quat(matrix):
# scale = matrix.median_scale
trans = matrix.to_translation()
rot = matrix.to_3x3() # also contains scale
return [(b * rot) + trans for b in base_tri]
return [(rot * b) + trans for b in base_tri]
scene = bpy.context.scene
linked = {}
for obj in bpy.context.selected_objects:
@ -498,7 +610,10 @@ class MakeDupliFace(bpy.types.Operator):
linked.setdefault(data, []).append(obj)
for data, objects in linked.items():
face_verts = [axis for obj in objects for v in matrix_to_quat(obj.matrix_world) for axis in v]
face_verts = [axis for obj in objects
for v in matrix_to_quat(obj.matrix_world)
for axis in v]
faces = list(range(len(face_verts) // 3))
mesh = bpy.data.meshes.new(data.name + "_dupli")
@ -535,7 +650,8 @@ class MakeDupliFace(bpy.types.Operator):
class IsolateTypeRender(bpy.types.Operator):
'''Hide unselected render objects of same type as active by setting the hide render flag'''
'''Hide unselected render objects of same type as active ''' \
'''by setting the hide render flag'''
bl_idname = "object.isolate_type_render"
bl_label = "Restrict Render Unselected"
bl_options = {'REGISTER', 'UNDO'}

@ -16,102 +16,109 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
import bpy
from mathutils import Vector
def GlobalBB_LQ(bb_world):
# Initialize the variables with the 8th vertex
left, right, front, back, down, up =\
bb_world[7][0],\
bb_world[7][0],\
bb_world[7][1],\
bb_world[7][1],\
bb_world[7][2],\
bb_world[7][2]
left, right, front, back, down, up = (bb_world[7][0],
bb_world[7][0],
bb_world[7][1],
bb_world[7][1],
bb_world[7][2],
bb_world[7][2],
)
# Test against the other 7 verts
for i in range (7):
for i in range(7):
# X Range
val = bb_world[i][0]
if val < left:
left = val
if val > right:
right = val
# Y Range
val = bb_world[i][1]
if val < front:
front = val
if val > back:
back = val
# Z Range
val = bb_world[i][2]
if val < down:
down = val
if val > up:
up = val
return (Vector((left, front, up)), Vector((right, back, down)))
def GlobalBB_HQ(obj):
matrix_world = obj.matrix_world.copy()
# Initialize the variables with the last vertex
verts = obj.data.vertices
val = verts[-1].co * matrix_world
left, right, front, back, down, up =\
val[0],\
val[0],\
val[1],\
val[1],\
val[2],\
val[2]
val = matrix_world * verts[-1].co
left, right, front, back, down, up = (val[0],
val[0],
val[1],
val[1],
val[2],
val[2],
)
# Test against all other verts
for i in range (len(verts)-1):
vco = verts[i].co * matrix_world
for i in range(len(verts) - 1):
vco = matrix_world * verts[i].co
# X Range
val = vco[0]
if val < left:
left = val
if val > right:
right = val
# Y Range
val = vco[1]
if val < front:
front = val
if val > back:
back = val
# Z Range
val = vco[2]
if val < down:
down = val
if val > up:
up = val
return (Vector((left, front, up)), Vector((right, back, down)))
return Vector((left, front, up)), Vector((right, back, down))
def align_objects(align_x, align_y, align_z, align_mode, relative_to, bb_quality):
def align_objects(align_x,
align_y,
align_z,
align_mode,
relative_to,
bb_quality):
cursor = bpy.context.scene.cursor_location
@ -123,20 +130,20 @@ def align_objects(align_x, align_y, align_z, align_mode, relative_to, bb_quality
objs = []
for obj in bpy.context.selected_objects:
matrix_world = obj.matrix_world
bb_world = [Vector(v[:]) * matrix_world for v in obj.bound_box]
matrix_world = obj.matrix_world.copy()
bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box]
objs.append((obj, bb_world))
if not objs:
return False
for obj, bb_world in objs:
if bb_quality:
GBB = GlobalBB_HQ(obj)
else:
GBB = GlobalBB_LQ(bb_world)
Left_Front_Up = GBB[0]
Right_Back_Down = GBB[1]
@ -193,13 +200,14 @@ def align_objects(align_x, align_y, align_z, align_mode, relative_to, bb_quality
# Main Loop
for obj, bb_world in objs:
bb_world = [Vector(v[:]) * obj.matrix_world for v in obj.bound_box]
matrix_world = obj.matrix_world.copy()
bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box]
if bb_quality:
GBB = GlobalBB_HQ(obj)
else:
GBB = GlobalBB_LQ(bb_world)
Left_Front_Up = GBB[0]
Right_Back_Down = GBB[1]
@ -339,7 +347,9 @@ class AlignObjects(bpy.types.Operator):
bb_quality = BoolProperty(
name="High Quality",
description="Enables high quality calculation of the bounding box for perfect results on complex shape meshes with rotation/scale (Slow)",
description=("Enables high quality calculation of the "
"bounding box for perfect results on complex "
"shape meshes with rotation/scale (Slow)"),
default=True)
align_mode = EnumProperty(items=(
@ -374,7 +384,12 @@ class AlignObjects(bpy.types.Operator):
def execute(self, context):
align_axis = self.align_axis
ret = align_objects('X' in align_axis, 'Y' in align_axis, 'Z' in align_axis, self.align_mode, self.relative_to, self.bb_quality)
ret = align_objects('X' in align_axis,
'Y' in align_axis,
'Z' in align_axis,
self.align_mode,
self.relative_to,
self.bb_quality)
if not ret:
self.report({'WARNING'}, "No objects with bound-box selected")

@ -16,11 +16,16 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
from mathutils import Vector
import bpy
from bpy.props import BoolProperty, EnumProperty, IntProperty, FloatProperty, FloatVectorProperty
from bpy.props import (BoolProperty,
EnumProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
)
def object_ensure_material(obj, mat_name):
@ -61,7 +66,8 @@ class QuickFur(bpy.types.Operator):
def execute(self, context):
fake_context = bpy.context.copy()
mesh_objects = [obj for obj in context.selected_objects if obj.type == 'MESH']
mesh_objects = [obj for obj in context.selected_objects
if obj.type == 'MESH']
if not mesh_objects:
self.report({'ERROR'}, "Select at least one mesh object.")
@ -92,7 +98,8 @@ class QuickFur(bpy.types.Operator):
psys.settings.child_type = 'INTERPOLATED'
obj.data.materials.append(mat)
obj.particle_systems[-1].settings.material = len(obj.data.materials)
obj.particle_systems[-1].settings.material = \
len(obj.data.materials)
return {'FINISHED'}
@ -149,7 +156,10 @@ class QuickExplode(bpy.types.Operator):
for obj in mesh_objects:
if obj.particle_systems:
self.report({'ERROR'}, "Object %r already has a particle system" % obj.name)
self.report({'ERROR'},
"Object %r already has a "
"particle system" % obj.name)
return {'CANCELLED'}
if self.fade:
@ -184,9 +194,7 @@ class QuickExplode(bpy.types.Operator):
if self.fade:
explode.show_dead = False
bpy.ops.mesh.uv_texture_add(fake_context)
uv = obj.data.uv_textures[-1]
uv.name = "Explode fade"
uv = obj.data.uv_textures.new("Explode fade")
explode.particle_uv = uv.name
mat = object_ensure_material(obj, "Explode Fade")
@ -247,7 +255,7 @@ class QuickExplode(bpy.types.Operator):
def obj_bb_minmax(obj, min_co, max_co):
for i in range(0, 8):
bb_vec = Vector(obj.bound_box[i]) * obj.matrix_world
bb_vec = obj.matrix_world * Vector(obj.bound_box[i])
min_co[0] = min(bb_vec[0], min_co[0])
min_co[1] = min(bb_vec[1], min_co[1])
@ -262,21 +270,26 @@ class QuickSmoke(bpy.types.Operator):
bl_label = "Quick Smoke"
bl_options = {'REGISTER', 'UNDO'}
style = EnumProperty(items=(
('STREAM', "Stream", ""),
('PUFF', "Puff", ""),
('FIRE', "Fire", "")),
name="Smoke Style",
description="",
default='STREAM')
style = EnumProperty(
items=(('STREAM', "Stream", ""),
('PUFF', "Puff", ""),
('FIRE', "Fire", ""),
),
name="Smoke Style",
description="",
default='STREAM',
)
show_flows = BoolProperty(name="Render Smoke Objects",
description="Keep the smoke objects visible during rendering.",
default=False)
show_flows = BoolProperty(
name="Render Smoke Objects",
description="Keep the smoke objects visible during rendering.",
default=False,
)
def execute(self, context):
fake_context = bpy.context.copy()
mesh_objects = [obj for obj in context.selected_objects if obj.type == 'MESH']
mesh_objects = [obj for obj in context.selected_objects
if obj.type == 'MESH']
min_co = Vector((100000.0, 100000.0, 100000.0))
max_co = -min_co
@ -336,21 +349,25 @@ class QuickSmoke(bpy.types.Operator):
mat.volume.density = 0
mat.volume.density_scale = 5
mat.texture_slots.add()
mat.texture_slots[0].texture = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA')
mat.texture_slots[0].texture.voxel_data.domain_object = obj
mat.texture_slots[0].use_map_color_emission = False
mat.texture_slots[0].use_map_density = True
tex = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA')
tex.voxel_data.domain_object = obj
tex_slot = mat.texture_slots.add()
tex_slot.texture = tex
tex_slot.use_map_color_emission = False
tex_slot.use_map_density = True
# for fire add a second texture for emission and emission color
if self.style == 'FIRE':
mat.volume.emission = 5
mat.texture_slots.add()
mat.texture_slots[1].texture = bpy.data.textures.new("Smoke Heat", 'VOXEL_DATA')
mat.texture_slots[1].texture.voxel_data.domain_object = obj
mat.texture_slots[1].texture.use_color_ramp = True
tex = bpy.data.textures.new("Smoke Heat", 'VOXEL_DATA')
tex.voxel_data.domain_object = obj
tex.use_color_ramp = True
ramp = mat.texture_slots[1].texture.color_ramp
tex_slot = mat.texture_slots.add()
tex_slot.texture = tex
ramp = tex.color_ramp
elem = ramp.elements.new(0.333)
elem.color[0] = elem.color[3] = 1
@ -371,28 +388,38 @@ class QuickFluid(bpy.types.Operator):
bl_label = "Quick Fluid"
bl_options = {'REGISTER', 'UNDO'}
style = EnumProperty(items=(
('INFLOW', "Inflow", ""),
('BASIC', "Basic", "")),
style = EnumProperty(
items=(('INFLOW', "Inflow", ""),
('BASIC', "Basic", ""),
),
name="Fluid Style",
description="",
default='BASIC')
initial_velocity = FloatVectorProperty(name="Initial Velocity",
description="Initial velocity of the fluid",
default=(0.0, 0.0, 0.0), min=-100.0, max=100.0, subtype='VELOCITY')
show_flows = BoolProperty(name="Render Fluid Objects",
description="Keep the fluid objects visible during rendering.",
default=False)
start_baking = BoolProperty(name="Start Fluid Bake",
description="Start baking the fluid immediately after creating the domain object.",
default=False)
default='BASIC',
)
initial_velocity = FloatVectorProperty(
name="Initial Velocity",
description="Initial velocity of the fluid",
default=(0.0, 0.0, 0.0),
min=-100.0,
max=100.0,
subtype='VELOCITY',
)
show_flows = BoolProperty(
name="Render Fluid Objects",
description="Keep the fluid objects visible during rendering.",
default=False,
)
start_baking = BoolProperty(
name="Start Fluid Bake",
description=("Start baking the fluid immediately "
"after creating the domain object"),
default=False,
)
def execute(self, context):
fake_context = bpy.context.copy()
mesh_objects = [obj for obj in context.selected_objects if (obj.type == 'MESH' and not 0 in obj.dimensions)]
mesh_objects = [obj for obj in context.selected_objects
if (obj.type == 'MESH' and not 0.0 in obj.dimensions)]
min_co = Vector((100000, 100000, 100000))
max_co = Vector((-100000, -100000, -100000))
@ -405,7 +432,8 @@ class QuickFluid(bpy.types.Operator):
# make each selected object a fluid
bpy.ops.object.modifier_add(fake_context, type='FLUID_SIMULATION')
# fluid has to be before constructive modifiers, so it might not be the last modifier
# fluid has to be before constructive modifiers,
# so it might not be the last modifier
for mod in obj.modifiers:
if mod.type == 'FLUID_SIMULATION':
break
@ -429,10 +457,14 @@ class QuickFluid(bpy.types.Operator):
obj = context.active_object
obj.name = "Fluid Domain"
# give the fluid some room below the flows and scale with initial velocity
# give the fluid some room below the flows
# and scale with initial velocity
v = 0.5 * self.initial_velocity
obj.location = 0.5 * (max_co + min_co) + Vector((0.0, 0.0, -1.0)) + v
obj.scale = 0.5 * (max_co - min_co) + Vector((1.0, 1.0, 2.0)) + Vector((abs(v[0]), abs(v[1]), abs(v[2])))
obj.scale = (0.5 * (max_co - min_co) +
Vector((1.0, 1.0, 2.0)) +
Vector((abs(v[0]), abs(v[1]), abs(v[2])))
)
# setup smoke domain
bpy.ops.object.modifier_add(type='FLUID_SIMULATION')

@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
import bpy
@ -93,40 +93,69 @@ class RandomizeLocRotSize(bpy.types.Operator):
bl_label = "Randomize Transform"
bl_options = {'REGISTER', 'UNDO'}
random_seed = IntProperty(name="Random Seed",
description="Seed value for the random generator",
default=0, min=0, max=1000)
use_delta = BoolProperty(name="Transform Delta",
description="Randomize delta transform values instead of regular transform", default=False)
use_loc = BoolProperty(name="Randomize Location",
description="Randomize the location values", default=True)
loc = FloatVectorProperty(name="Location",
description="Maximun distance the objects can spread over each axis",
default=(0.0, 0.0, 0.0), min=-100.0, max=100.0, subtype='TRANSLATION')
use_rot = BoolProperty(name="Randomize Rotation",
description="Randomize the rotation values", default=True)
rot = FloatVectorProperty(name="Rotation",
description="Maximun rotation over each axis",
default=(0.0, 0.0, 0.0), min=-180.0, max=180.0, subtype='TRANSLATION')
use_scale = BoolProperty(name="Randomize Scale",
description="Randomize the scale values", default=True)
scale_even = BoolProperty(name="Scale Even",
description="Use the same scale value for all axis", default=False)
random_seed = IntProperty(
name="Random Seed",
description="Seed value for the random generator",
min=0,
max=1000,
default=0,
)
use_delta = BoolProperty(
name="Transform Delta",
description=("Randomize delta transform values "
"instead of regular transform"),
default=False,
)
use_loc = BoolProperty(
name="Randomize Location",
description="Randomize the location values",
default=True,
)
loc = FloatVectorProperty(
name="Location",
description=("Maximun distance the objects "
"can spread over each axis"),
min=-100.0,
max=100.0,
default=(0.0, 0.0, 0.0),
subtype='TRANSLATION',
)
use_rot = BoolProperty(
name="Randomize Rotation",
description="Randomize the rotation values",
default=True,
)
rot = FloatVectorProperty(
name="Rotation",
description="Maximun rotation over each axis",
min=-180.0,
max=180.0,
default=(0.0, 0.0, 0.0),
subtype='TRANSLATION',
)
use_scale = BoolProperty(
name="Randomize Scale",
description="Randomize the scale values",
default=True,
)
scale_even = BoolProperty(
name="Scale Even",
description="Use the same scale value for all axis",
default=False,
)
'''scale_min = FloatProperty(name="Minimun Scale Factor",
description="Lowest scale percentage possible",
default=0.15, min=-1.0, max=1.0, precision=3)'''
scale = FloatVectorProperty(name="Scale",
description="Maximum scale randomization over each axis",
default=(0.0, 0.0, 0.0), min=-100.0, max=100.0, subtype='TRANSLATION')
scale = FloatVectorProperty(
name="Scale",
description="Maximum scale randomization over each axis",
min=-100.0,
max=100.0,
default=(0.0, 0.0, 0.0),
subtype='TRANSLATION',
)
def execute(self, context):
from math import radians

@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
import bpy
@ -30,8 +30,15 @@ class AddPresetBase():
# bl_label = "Add a Python Preset"
bl_options = {'REGISTER'} # only because invoke_props_popup requires.
name = bpy.props.StringProperty(name="Name", description="Name of the preset, used to make the path name", maxlen=64, default="")
remove_active = bpy.props.BoolProperty(default=False, options={'HIDDEN'})
name = bpy.props.StringProperty(
name="Name",
description="Name of the preset, used to make the path name",
maxlen=64,
)
remove_active = bpy.props.BoolProperty(
default=False,
options={'HIDDEN'},
)
@staticmethod
def as_filename(name): # could reuse for other presets
@ -54,7 +61,10 @@ class AddPresetBase():
filename = self.as_filename(name)
target_path = bpy.utils.user_resource('SCRIPTS', os.path.join("presets", self.preset_subdir), create=True)
target_path = os.path.join("presets", self.preset_subdir)
target_path = bpy.utils.user_resource('SCRIPTS',
target_path,
create=True)
if not target_path:
self.report({'WARNING'}, "Failed to create presets path")
@ -95,7 +105,9 @@ class AddPresetBase():
filepath = bpy.utils.preset_find(preset_active, self.preset_subdir)
if not filepath:
filepath = bpy.utils.preset_find(preset_active, self.preset_subdir, display_name=True)
filepath = bpy.utils.preset_find(preset_active,
self.preset_subdir,
display_name=True)
if not filepath:
return {'CANCELLED'}
@ -133,8 +145,15 @@ class ExecutePreset(bpy.types.Operator):
bl_idname = "script.execute_preset"
bl_label = "Execute a Python Preset"
filepath = bpy.props.StringProperty(name="Path", description="Path of the Python file to execute", maxlen=512, default="")
menu_idname = bpy.props.StringProperty(name="Menu ID Name", description="ID name of the menu this was called from", default="")
filepath = bpy.props.StringProperty(
name="Path",
description="Path of the Python file to execute",
maxlen=512,
)
menu_idname = bpy.props.StringProperty(
name="Menu ID Name",
description="ID name of the menu this was called from",
)
def execute(self, context):
from os.path import basename
@ -182,7 +201,10 @@ class AddPresetSSS(AddPresetBase, bpy.types.Operator):
preset_menu = "MATERIAL_MT_sss_presets"
preset_defines = [
"material = (bpy.context.material.active_node_material if bpy.context.material.active_node_material else bpy.context.material)"
("material = "
"bpy.context.material.active_node_material "
"if bpy.context.material.active_node_material "
"else bpy.context.material")
]
preset_values = [
@ -306,7 +328,11 @@ class AddPresetOperator(AddPresetBase, bpy.types.Operator):
bl_label = "Operator Preset"
preset_menu = "WM_MT_operator_presets"
operator = bpy.props.StringProperty(name="Operator", maxlen=64, options={'HIDDEN'})
operator = bpy.props.StringProperty(
name="Operator",
maxlen=64,
options={'HIDDEN'},
)
# XXX, not ideal
preset_defines = [
@ -322,12 +348,15 @@ class AddPresetOperator(AddPresetBase, bpy.types.Operator):
properties_blacklist = bpy.types.Operator.bl_rna.properties.keys()
prefix, suffix = self.operator.split("_OT_", 1)
operator_rna = getattr(getattr(bpy.ops, prefix.lower()), suffix).get_rna().bl_rna
op = getattr(getattr(bpy.ops, prefix.lower()), suffix)
operator_rna = op.get_rna().bl_rna
del op
ret = []
for prop_id, prop in operator_rna.properties.items():
if (not (prop.is_hidden or prop.is_skip_save)) and prop_id not in properties_blacklist:
ret.append("op.%s" % prop_id)
if not (prop.is_hidden or prop.is_skip_save):
if prop_id not in properties_blacklist:
ret.append("op.%s" % prop_id)
return ret

@ -1,27 +1,23 @@
# ***** BEGIN GPL LICENSE BLOCK *****
# ##### BEGIN GPL LICENSE BLOCK #####
#
# Script copyright (C) Campbell J Barton
# 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 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.
#
# 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.
#
# 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.
#
# ***** END GPL LICENCE BLOCK *****
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
# History
#
# Originally written by Matt Ebb
import bpy
@ -46,8 +42,10 @@ def guess_player_path(preset):
player_path = "djv_view"
if sys.platform == "darwin":
# TODO, crummy supporting only 1 version, could find the newest installed version
test_path = '/Applications/djv-0.8.2.app/Contents/Resources/bin/djv_view'
# TODO, crummy supporting only 1 version,
# could find the newest installed version
test_path = ("/Applications/djv-0.8.2.app"
"/Contents/Resources/bin/djv_view")
if os.path.exists(test_path):
player_path = test_path
@ -59,7 +57,7 @@ def guess_player_path(preset):
elif preset == 'MPLAYER':
player_path = "mplayer"
else:
player_path = ""
@ -85,10 +83,10 @@ class PlayRenderedAnim(bpy.types.Operator):
is_movie = rd.is_movie_format
# try and guess a command line if it doesn't exist
if player_path == '':
if player_path == "":
player_path = guess_player_path(preset)
if is_movie == False and preset in ('FRAMECYCLER', 'RV', 'MPLAYER'):
if is_movie == False and preset in {'FRAMECYCLER', 'RV', 'MPLAYER'}:
# replace the number with '#'
file_a = rd.frame_path(frame=0)
@ -98,11 +96,11 @@ class PlayRenderedAnim(bpy.types.Operator):
while len(file_a) == len(file_b):
frame_tmp = (frame_tmp * 10) + 9
print(frame_tmp)
file_b = rd.frame_path(frame=frame_tmp)
file_b = rd.frame_path(frame=int(frame_tmp / 10))
file = "".join((c if file_b[i] == c else "#") for i, c in enumerate(file_a))
file = ("".join((c if file_b[i] == c else "#")
for i, c in enumerate(file_a)))
else:
# works for movies and images
file = rd.frame_path(frame=scene.frame_start)
@ -112,10 +110,35 @@ class PlayRenderedAnim(bpy.types.Operator):
cmd = [player_path]
# extra options, fps controls etc.
if preset == 'BLENDER24':
# -----------------------------------------------------------------
# Check blender is not 2.5x until it supports playback again
try:
process = subprocess.Popen([player_path, '--version'],
stdout=subprocess.PIPE,
)
except:
# ignore and allow the main execution to catch the problem.
process = None
if process is not None:
process.wait()
out = process.stdout.read()
process.stdout.close()
out_split = out.strip().split()
if out_split[0] == b'Blender':
if not out_split[1].startswith(b'2.4'):
self.report({'ERROR'},
"Blender %s doesn't support playback: %r" %
(out_split[1].decode(), player_path))
return {'CANCELLED'}
del out, out_split
del process
# -----------------------------------------------------------------
opts = ["-a", "-f", str(rd.fps), str(rd.fps_base), file]
cmd.extend(opts)
elif preset == 'DJV':
opts = [file, "-playback_speed", str(rd.fps)]
opts = [file, "-playback_speed", "%d" % int(rd.fps / rd.fps_base)]
cmd.extend(opts)
elif preset == 'FRAMECYCLER':
opts = [file, "%d-%d" % (scene.frame_start, scene.frame_end)]
@ -128,20 +151,26 @@ class PlayRenderedAnim(bpy.types.Operator):
if is_movie:
opts.append(file)
else:
opts.append("mf://%s" % file.replace("#", "?"))
opts += ["-mf", "fps=%.4f" % (rd.fps / rd.fps_base)]
opts += [("mf://%s" % file.replace("#", "?")),
"-mf",
"fps=%.4f" % (rd.fps / rd.fps_base),
]
opts += ["-loop", "0", "-really-quiet", "-fs"]
cmd.extend(opts)
else: # 'CUSTOM'
cmd.append(file)
if (player_path == "") or (os.path.exists(player_path)==False):
self.report({'ERROR'}, "Couldn't find an external animation player")
else:
# launch it
try:
process = subprocess.Popen(cmd)
except:
pass
# launch it
print("Executing command:\n %r" % " ".join(cmd))
try:
process = subprocess.Popen(cmd)
except Exception as e:
import traceback
self.report({'ERROR'},
"Couldn't run external animation player with command "
"%r\n%s" % (" ".join(cmd), str(e)))
return {'CANCELLED'}
return {'FINISHED'}

@ -243,7 +243,7 @@ def testNewVecLs2DRotIsBetter(vecs, mat=-1, bestAreaSoFar = -1):
# Do this allong the way
if mat != -1:
v = vecs[i] = v*mat
v = vecs[i] = mat * v
x= v.x
y= v.y
if x<minx: minx= x
@ -1064,7 +1064,7 @@ def main(context,
f_uv = f.uv
for j, v in enumerate(f.v):
# XXX - note, between mathutils in 2.4 and 2.5 the order changed.
f_uv[j][:] = (v.co * MatQuat).xy
f_uv[j][:] = (MatQuat * v.co).xy
if USER_SHARE_SPACE:

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

@ -397,6 +397,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.operator("object.multires_higher_levels_delete", text="Delete Higher")
col.operator("object.multires_reshape", text="Reshape")
col.operator("object.multires_base_apply", text="Apply Base")
col.prop(md, "use_subsurf_uv")
col.prop(md, "show_only_control_edges")
layout.separator()

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

@ -93,7 +93,7 @@ class WORLD_PT_world(WorldButtonsPanel, bpy.types.Panel):
col.prop(world, "zenith_color")
col.active = world.use_sky_blend
row.column().prop(world, "ambient_color")
row = layout.row()
row.prop(world, "exposure")
row.prop(world, "color_range")

@ -60,7 +60,7 @@ class INFO_HT_header(bpy.types.Header):
layout.template_running_jobs()
layout.template_reports_banner()
row = layout.row(align=True)
row.operator("wm.splash", text="", icon='BLENDER', emboss=False)
row.label(text=scene.statistics())

@ -135,7 +135,7 @@ class NODE_MT_node(bpy.types.Menu):
layout.operator("transform.resize")
layout.separator()
layout.operator("node.duplicate_move")
layout.operator("node.delete")
layout.operator("node.delete_reconnect")

@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# <pep8-80 compliant>
import bpy
@ -33,19 +33,21 @@ class TEXT_HT_header(bpy.types.Header):
row.template_header()
if context.area.show_menus:
sub = row.row(align=True)
sub.menu("TEXT_MT_view")
sub.menu("TEXT_MT_text")
row.menu("TEXT_MT_view")
row.menu("TEXT_MT_text")
if text:
sub.menu("TEXT_MT_edit")
sub.menu("TEXT_MT_format")
row.menu("TEXT_MT_edit")
row.menu("TEXT_MT_format")
row.menu("TEXT_MT_templates")
if text and text.is_modified:
row = layout.row()
row.alert = True
row.operator("text.resolve_conflict", text="", icon='HELP')
sub = row.row()
sub.alert = True
sub.operator("text.resolve_conflict", text="", icon='HELP')
layout.template_ID(st, "text", new="text.new", unlink="text.unlink")
row.template_ID(st, "text", new="text.new", unlink="text.unlink")
row = layout.row(align=True)
row.prop(st, "show_line_numbers", text="")
@ -63,11 +65,13 @@ class TEXT_HT_header(bpy.types.Header):
row = layout.row()
if text.filepath:
if text.is_dirty:
row.label(text="File: *%s (unsaved)" % text.filepath)
row.label(text="File: *%r (unsaved)" % text.filepath)
else:
row.label(text="File: %s" % text.filepath)
row.label(text="File: %r" % text.filepath)
else:
row.label(text="Text: External" if text.library else "Text: Internal")
row.label(text="Text: External"
if text.library
else "Text: Internal")
class TEXT_PT_properties(bpy.types.Panel):
@ -150,8 +154,12 @@ class TEXT_MT_view(bpy.types.Menu):
layout.separator()
layout.operator("text.move", text="Top of File").type = 'FILE_TOP'
layout.operator("text.move", text="Bottom of File").type = 'FILE_BOTTOM'
layout.operator("text.move",
text="Top of File",
).type = 'FILE_TOP'
layout.operator("text.move",
text="Bottom of File",
).type = 'FILE_BOTTOM'
class TEXT_MT_text(bpy.types.Menu):
@ -185,19 +193,15 @@ class TEXT_MT_text(bpy.types.Menu):
# XXX uiMenuItemO(head, 0, "text.refresh_pyconstraints");
#endif
layout.separator()
layout.menu("TEXT_MT_templates")
class TEXT_MT_templates(bpy.types.Menu):
'''
Creates the menu items by scanning scripts/templates
'''
bl_label = "Script Templates"
bl_label = "Templates"
def draw(self, context):
self.path_menu(bpy.utils.script_paths("templates"), "text.open", {"internal": True})
self.path_menu(bpy.utils.script_paths("templates"),
"text.open",
{"internal": True},
)
class TEXT_MT_edit_select(bpy.types.Menu):
@ -246,8 +250,12 @@ class TEXT_MT_edit_to3d(bpy.types.Menu):
def draw(self, context):
layout = self.layout
layout.operator("text.to_3d_object", text="One Object").split_lines = False
layout.operator("text.to_3d_object", text="One Object Per Line").split_lines = True
layout.operator("text.to_3d_object",
text="One Object",
).split_lines = False
layout.operator("text.to_3d_object",
text="One Object Per Line",
).split_lines = True
class TEXT_MT_edit(bpy.types.Menu):

@ -817,12 +817,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 +878,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:
@ -1020,7 +1017,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}

@ -271,6 +271,8 @@ class InputKeyMapPanel:
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="")
@ -306,7 +308,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':
@ -590,6 +592,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")

@ -55,7 +55,7 @@ class VIEW3D_HT_header(bpy.types.Header):
row = layout.row()
# Contains buttons like Mode, Pivot, Manipulator, Layer, Mesh Select Mode...
row.template_header_3D()
row.template_header_3D()
if obj:
# Particle edit
@ -79,19 +79,22 @@ class VIEW3D_HT_header(bpy.types.Header):
row.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True)
# Snap
snap_element = toolsettings.snap_element
row = layout.row(align=True)
row.prop(toolsettings, "use_snap", text="")
row.prop(toolsettings, "snap_element", text="", icon_only=True)
if toolsettings.snap_element != 'INCREMENT':
if snap_element != 'INCREMENT':
row.prop(toolsettings, "snap_target", text="")
if obj and obj.mode == 'OBJECT':
row.prop(toolsettings, "use_snap_align_rotation", text="")
if toolsettings.snap_element == 'VOLUME':
if obj:
if obj.mode == 'OBJECT':
row.prop(toolsettings, "use_snap_align_rotation", text="")
elif obj.mode == 'EDIT':
row.prop(toolsettings, "use_snap_self", text="")
if snap_element == 'VOLUME':
row.prop(toolsettings, "use_snap_peel_object", text="")
elif toolsettings.snap_element == 'FACE':
elif snap_element == 'FACE':
row.prop(toolsettings, "use_snap_project", text="")
if toolsettings.use_snap_project and obj.mode == 'EDIT':
row.prop(toolsettings, "use_snap_project_self", text="")
# OpenGL render
row = layout.row(align=True)
@ -346,6 +349,30 @@ class VIEW3D_MT_view_navigation(bpy.types.Menu):
layout.operator("view3d.fly")
class VIEW3D_MT_ndof_settings(bpy.types.Menu):
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 VIEW3D_MT_view_align(bpy.types.Menu):
bl_label = "Align View"

@ -58,6 +58,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):

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