* Merged changes in the trunk up to revision 31789.

* Made a local fix for a compilation error with VC++ 2008 and
CMake, reported to the bf-committers mailing list:
http://lists.blender.org/pipermail/bf-committers/2010-September/028643.html
This commit is contained in:
2010-09-06 23:26:36 +00:00
279 changed files with 5648 additions and 5317 deletions

View File

@@ -300,7 +300,7 @@ IF(UNIX AND NOT APPLE)
IF(CMAKE_SYSTEM_NAME MATCHES "Linux") IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
# BSD's dont use libdl.so # BSD's dont use libdl.so
SET(LLIBS "${LLIBS} -ldl") LIST(APPEND LLIBS -ldl)
# binreloc is linux only # binreloc is linux only
SET(BINRELOC ${CMAKE_SOURCE_DIR}/extern/binreloc) SET(BINRELOC ${CMAKE_SOURCE_DIR}/extern/binreloc)
@@ -308,9 +308,9 @@ IF(UNIX AND NOT APPLE)
ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux") ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
IF(WITH_OPENMP) IF(WITH_OPENMP)
SET(LLIBS "${LLIBS} -lgomp") LIST(APPEND LLIBS -lgomp)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp") LIST(APPEND CMAKE_C_FLAGS -fopenmp)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp") LIST(APPEND CMAKE_CXX_FLAGS -fopenmp)
ENDIF(WITH_OPENMP) ENDIF(WITH_OPENMP)
@@ -415,11 +415,19 @@ IF(WIN32)
SET(CMAKE_CXX_FLAGS "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305" CACHE STRING "MSVC MT C++ flags " FORCE) SET(CMAKE_CXX_FLAGS "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305" CACHE STRING "MSVC MT C++ flags " FORCE)
SET(CMAKE_C_FLAGS "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305" CACHE STRING "MSVC MT C++ flags " FORCE) SET(CMAKE_C_FLAGS "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305" CACHE STRING "MSVC MT C++ flags " FORCE)
SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /Od /Gm /EHsc /RTC1 /MTd /W3 /nologo /ZI /J" CACHE STRING "MSVC MT flags " FORCE) IF(CMAKE_CL_64)
SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /Od /Gm /EHsc /RTC1 /MTd /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE)
ELSE(CMAKE_CL_64)
SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /Od /Gm /EHsc /RTC1 /MTd /W3 /nologo /ZI /J" CACHE STRING "MSVC MT flags " FORCE)
ENDIF(CMAKE_CL_64)
SET(CMAKE_CXX_FLAGS_RELEASE "/O2 /Ob2 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE) SET(CMAKE_CXX_FLAGS_RELEASE "/O2 /Ob2 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE)
SET(CMAKE_CXX_FLAGS_MINSIZEREL "/O1 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE) SET(CMAKE_CXX_FLAGS_MINSIZEREL "/O1 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE)
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/O2 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE) SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/O2 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE)
SET(CMAKE_C_FLAGS_DEBUG "/D_DEBUG /Od /Gm /EHsc /RTC1 /MTd /W3 /nologo /ZI /J" CACHE STRING "MSVC MT flags " FORCE) IF(CMAKE_CL_64)
SET(CMAKE_C_FLAGS_DEBUG "/D_DEBUG /Od /Gm /EHsc /RTC1 /MTd /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE)
ELSE(CMAKE_CL_64)
SET(CMAKE_C_FLAGS_DEBUG "/D_DEBUG /Od /Gm /EHsc /RTC1 /MTd /W3 /nologo /ZI /J" CACHE STRING "MSVC MT flags " FORCE)
ENDIF(CMAKE_CL_64)
SET(CMAKE_C_FLAGS_RELEASE "/O2 /Ob2 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE) SET(CMAKE_C_FLAGS_RELEASE "/O2 /Ob2 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE)
SET(CMAKE_C_FLAGS_MINSIZEREL "/O1 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE) SET(CMAKE_C_FLAGS_MINSIZEREL "/O1 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE)
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "/O2 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE) SET(CMAKE_C_FLAGS_RELWITHDEBINFO "/O2 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE)

View File

@@ -33,9 +33,9 @@ import platform as pltfrm
# Need a better way to do this. Automagical maybe is not the best thing, maybe it is. # Need a better way to do this. Automagical maybe is not the best thing, maybe it is.
if pltfrm.architecture()[0] == '64bit': if pltfrm.architecture()[0] == '64bit':
bitness = 64 bitness = 64
else: else:
bitness = 32 bitness = 32
import sys import sys
import os import os
@@ -79,15 +79,15 @@ B.binarykind = ['blender' , 'blenderplayer']
# XX cheating for BF_FANCY, we check for BF_FANCY before args are validated # XX cheating for BF_FANCY, we check for BF_FANCY before args are validated
use_color = ARGUMENTS.get('BF_FANCY', '1') use_color = ARGUMENTS.get('BF_FANCY', '1')
if platform=='win32': if platform=='win32':
use_color = None use_color = None
if not use_color=='1': if not use_color=='1':
B.bc.disable() B.bc.disable()
#on defaut white Os X terminal, some colors are totally unlegible #on defaut white Os X terminal, some colors are totally unlegible
if platform=='darwin': if platform=='darwin':
B.bc.OKGREEN = '\033[34m' B.bc.OKGREEN = '\033[34m'
B.bc.WARNING = '\033[36m' B.bc.WARNING = '\033[36m'
# arguments # arguments
print B.bc.HEADER+'Command-line arguments'+B.bc.ENDC print B.bc.HEADER+'Command-line arguments'+B.bc.ENDC
@@ -110,100 +110,100 @@ quickie = B.arguments.get('BF_QUICK', None)
quickdebug = B.arguments.get('BF_QUICKDEBUG', None) quickdebug = B.arguments.get('BF_QUICKDEBUG', None)
if quickdebug: if quickdebug:
B.quickdebug=string.split(quickdebug, ',') B.quickdebug=string.split(quickdebug, ',')
else: else:
B.quickdebug=[] B.quickdebug=[]
if quickie: if quickie:
B.quickie=string.split(quickie,',') B.quickie=string.split(quickie,',')
else: else:
B.quickie=[] B.quickie=[]
toolset = B.arguments.get('BF_TOOLSET', None) toolset = B.arguments.get('BF_TOOLSET', None)
if toolset: if toolset:
print "Using " + toolset print "Using " + toolset
if toolset=='mstoolkit': if toolset=='mstoolkit':
env = BlenderEnvironment(ENV = os.environ) env = BlenderEnvironment(ENV = os.environ)
env.Tool('mstoolkit', [toolpath]) env.Tool('mstoolkit', [toolpath])
else: else:
env = BlenderEnvironment(tools=[toolset], ENV = os.environ) env = BlenderEnvironment(tools=[toolset], ENV = os.environ)
# xxx commented out, as was supressing warnings under mingw.. # xxx commented out, as was supressing warnings under mingw..
#if env: #if env:
# btools.SetupSpawn(env) # btools.SetupSpawn(env)
else: else:
if bitness==64 and platform=='win32': if bitness==64 and platform=='win32':
env = BlenderEnvironment(ENV = os.environ, MSVS_ARCH='amd64') env = BlenderEnvironment(ENV = os.environ, MSVS_ARCH='amd64')
else: else:
env = BlenderEnvironment(ENV = os.environ) env = BlenderEnvironment(ENV = os.environ)
if not env: if not env:
print "Could not create a build environment" print "Could not create a build environment"
Exit() Exit()
cc = B.arguments.get('CC', None) cc = B.arguments.get('CC', None)
cxx = B.arguments.get('CXX', None) cxx = B.arguments.get('CXX', None)
if cc: if cc:
env['CC'] = cc env['CC'] = cc
if cxx: if cxx:
env['CXX'] = cxx env['CXX'] = cxx
if env['CC'] in ['cl', 'cl.exe'] and sys.platform=='win32': if env['CC'] in ['cl', 'cl.exe'] and sys.platform=='win32':
if bitness == 64: if bitness == 64:
platform = 'win64-vc' platform = 'win64-vc'
else: else:
platform = 'win32-vc' platform = 'win32-vc'
elif env['CC'] in ['gcc'] and sys.platform=='win32': elif env['CC'] in ['gcc'] and sys.platform=='win32':
platform = 'win32-mingw' platform = 'win32-mingw'
env.SConscriptChdir(0) env.SConscriptChdir(0)
crossbuild = B.arguments.get('BF_CROSS', None) crossbuild = B.arguments.get('BF_CROSS', None)
if crossbuild and platform not in ('win32-vc', 'win64-vc'): if crossbuild and platform not in ('win32-vc', 'win64-vc'):
platform = 'linuxcross' platform = 'linuxcross'
env['OURPLATFORM'] = platform env['OURPLATFORM'] = platform
configfile = os.path.join("build_files", "scons", "config", platform + "-config.py") configfile = os.path.join("build_files", "scons", "config", platform + "-config.py")
if os.path.exists(configfile): if os.path.exists(configfile):
print B.bc.OKGREEN + "Using config file: " + B.bc.ENDC + configfile print B.bc.OKGREEN + "Using config file: " + B.bc.ENDC + configfile
else: else:
print B.bc.FAIL + configfile + " doesn't exist" + B.bc.ENDC print B.bc.FAIL + configfile + " doesn't exist" + B.bc.ENDC
if crossbuild and env['PLATFORM'] != 'win32': if crossbuild and env['PLATFORM'] != 'win32':
print B.bc.HEADER+"Preparing for crossbuild"+B.bc.ENDC print B.bc.HEADER+"Preparing for crossbuild"+B.bc.ENDC
env.Tool('crossmingw', [toolpath]) env.Tool('crossmingw', [toolpath])
# todo: determine proper libs/includes etc. # todo: determine proper libs/includes etc.
# Needed for gui programs, console programs should do without it # Needed for gui programs, console programs should do without it
# Now we don't need this option to have console window # Now we don't need this option to have console window
# env.Append(LINKFLAGS=['-mwindows']) # env.Append(LINKFLAGS=['-mwindows'])
userconfig = B.arguments.get('BF_CONFIG', 'user-config.py') userconfig = B.arguments.get('BF_CONFIG', 'user-config.py')
# first read platform config. B.arguments will override # first read platform config. B.arguments will override
optfiles = [configfile] optfiles = [configfile]
if os.path.exists(userconfig): if os.path.exists(userconfig):
print B.bc.OKGREEN + "Using user-config file: " + B.bc.ENDC + userconfig print B.bc.OKGREEN + "Using user-config file: " + B.bc.ENDC + userconfig
optfiles += [userconfig] optfiles += [userconfig]
else: else:
print B.bc.WARNING + userconfig + " not found, no user overrides" + B.bc.ENDC print B.bc.WARNING + userconfig + " not found, no user overrides" + B.bc.ENDC
opts = btools.read_opts(env, optfiles, B.arguments) opts = btools.read_opts(env, optfiles, B.arguments)
opts.Update(env) opts.Update(env)
if not env['BF_FANCY']: if not env['BF_FANCY']:
B.bc.disable() B.bc.disable()
# remove install dir so old and new files are not mixed. # remove install dir so old and new files are not mixed.
# NOTE: only do the scripts directory for now, otherwise is too disruptive for developers # NOTE: only do the scripts directory for now, otherwise is too disruptive for developers
# TODO: perhaps we need an option (off by default) to not do this altogether... # TODO: perhaps we need an option (off by default) to not do this altogether...
if not env['WITHOUT_BF_INSTALL'] and not env['WITHOUT_BF_OVERWRITE_INSTALL']: if not env['WITHOUT_BF_INSTALL'] and not env['WITHOUT_BF_OVERWRITE_INSTALL']:
scriptsDir = os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts') scriptsDir = os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts')
if os.path.isdir(scriptsDir): if os.path.isdir(scriptsDir):
print B.bc.OKGREEN + "Clearing installation directory%s: %s" % (B.bc.ENDC, os.path.abspath(scriptsDir)) print B.bc.OKGREEN + "Clearing installation directory%s: %s" % (B.bc.ENDC, os.path.abspath(scriptsDir))
shutil.rmtree(scriptsDir) shutil.rmtree(scriptsDir)
SetOption('num_jobs', int(env['BF_NUMJOBS'])) SetOption('num_jobs', int(env['BF_NUMJOBS']))
@@ -211,158 +211,158 @@ print B.bc.OKGREEN + "Build with parallel jobs%s: %s" % (B.bc.ENDC, GetOption('n
print B.bc.OKGREEN + "Build with debug symbols%s: %s" % (B.bc.ENDC, env['BF_DEBUG']) print B.bc.OKGREEN + "Build with debug symbols%s: %s" % (B.bc.ENDC, env['BF_DEBUG'])
if 'blenderlite' in B.targets: if 'blenderlite' in B.targets:
target_env_defs = {} target_env_defs = {}
target_env_defs['WITH_BF_GAMEENGINE'] = False target_env_defs['WITH_BF_GAMEENGINE'] = False
target_env_defs['WITH_BF_OPENAL'] = False target_env_defs['WITH_BF_OPENAL'] = False
target_env_defs['WITH_BF_OPENEXR'] = False target_env_defs['WITH_BF_OPENEXR'] = False
target_env_defs['WITH_BF_OPENMP'] = False target_env_defs['WITH_BF_OPENMP'] = False
target_env_defs['WITH_BF_ICONV'] = False target_env_defs['WITH_BF_ICONV'] = False
target_env_defs['WITH_BF_INTERNATIONAL'] = False target_env_defs['WITH_BF_INTERNATIONAL'] = False
target_env_defs['WITH_BF_OPENJPEG'] = False target_env_defs['WITH_BF_OPENJPEG'] = False
target_env_defs['WITH_BF_FFMPEG'] = False target_env_defs['WITH_BF_FFMPEG'] = False
target_env_defs['WITH_BF_QUICKTIME'] = False target_env_defs['WITH_BF_QUICKTIME'] = False
target_env_defs['WITH_BF_REDCODE'] = False target_env_defs['WITH_BF_REDCODE'] = False
target_env_defs['WITH_BF_DDS'] = False target_env_defs['WITH_BF_DDS'] = False
target_env_defs['WITH_BF_CINEON'] = False target_env_defs['WITH_BF_CINEON'] = False
target_env_defs['WITH_BF_HDR'] = False target_env_defs['WITH_BF_HDR'] = False
target_env_defs['WITH_BF_ZLIB'] = False target_env_defs['WITH_BF_ZLIB'] = False
target_env_defs['WITH_BF_SDL'] = False target_env_defs['WITH_BF_SDL'] = False
target_env_defs['WITH_BF_JPEG'] = False target_env_defs['WITH_BF_JPEG'] = False
target_env_defs['WITH_BF_PNG'] = False target_env_defs['WITH_BF_PNG'] = False
target_env_defs['WITH_BF_BULLET'] = False target_env_defs['WITH_BF_BULLET'] = False
target_env_defs['WITH_BF_BINRELOC'] = False target_env_defs['WITH_BF_BINRELOC'] = False
target_env_defs['BF_BUILDINFO'] = False target_env_defs['BF_BUILDINFO'] = False
target_env_defs['BF_NO_ELBEEM'] = True target_env_defs['BF_NO_ELBEEM'] = True
target_env_defs['WITH_BF_PYTHON'] = False target_env_defs['WITH_BF_PYTHON'] = False
# Merge blenderlite, let command line to override # Merge blenderlite, let command line to override
for k,v in target_env_defs.iteritems(): for k,v in target_env_defs.iteritems():
if k not in B.arguments: if k not in B.arguments:
env[k] = v env[k] = v
if env['WITH_BF_OPENMP'] == 1: if env['WITH_BF_OPENMP'] == 1:
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
env['CCFLAGS'].append('/openmp') env['CCFLAGS'].append('/openmp')
env['CPPFLAGS'].append('/openmp') env['CPPFLAGS'].append('/openmp')
env['CXXFLAGS'].append('/openmp') env['CXXFLAGS'].append('/openmp')
else: else:
if env['CC'].endswith('icc'): # to be able to handle CC=/opt/bla/icc case if env['CC'].endswith('icc'): # to be able to handle CC=/opt/bla/icc case
env.Append(LINKFLAGS=['-openmp', '-static-intel']) env.Append(LINKFLAGS=['-openmp', '-static-intel'])
env['CCFLAGS'].append('-openmp') env['CCFLAGS'].append('-openmp')
env['CPPFLAGS'].append('-openmp') env['CPPFLAGS'].append('-openmp')
env['CXXFLAGS'].append('-openmp') env['CXXFLAGS'].append('-openmp')
else: else:
env.Append(CCFLAGS=['-fopenmp']) env.Append(CCFLAGS=['-fopenmp'])
env.Append(CPPFLAGS=['-fopenmp']) env.Append(CPPFLAGS=['-fopenmp'])
env.Append(CXXFLAGS=['-fopenmp']) env.Append(CXXFLAGS=['-fopenmp'])
if env['WITH_GHOST_COCOA'] == True: if env['WITH_GHOST_COCOA'] == True:
env.Append(CFLAGS=['-DGHOST_COCOA']) env.Append(CFLAGS=['-DGHOST_COCOA'])
env.Append(CXXFLAGS=['-DGHOST_COCOA']) env.Append(CXXFLAGS=['-DGHOST_COCOA'])
env.Append(CPPFLAGS=['-DGHOST_COCOA']) env.Append(CPPFLAGS=['-DGHOST_COCOA'])
if env['USE_QTKIT'] == True: if env['USE_QTKIT'] == True:
env.Append(CFLAGS=['-DUSE_QTKIT']) env.Append(CFLAGS=['-DUSE_QTKIT'])
env.Append(CXXFLAGS=['-DUSE_QTKIT']) env.Append(CXXFLAGS=['-DUSE_QTKIT'])
env.Append(CPPFLAGS=['-DUSE_QTKIT']) env.Append(CPPFLAGS=['-DUSE_QTKIT'])
#check for additional debug libnames #check for additional debug libnames
if env.has_key('BF_DEBUG_LIBS'): if env.has_key('BF_DEBUG_LIBS'):
B.quickdebug += env['BF_DEBUG_LIBS'] B.quickdebug += env['BF_DEBUG_LIBS']
printdebug = B.arguments.get('BF_LISTDEBUG', 0) printdebug = B.arguments.get('BF_LISTDEBUG', 0)
if len(B.quickdebug) > 0 and printdebug != 0: if len(B.quickdebug) > 0 and printdebug != 0:
print B.bc.OKGREEN + "Buildings these libs with debug symbols:" + B.bc.ENDC print B.bc.OKGREEN + "Buildings these libs with debug symbols:" + B.bc.ENDC
for l in B.quickdebug: for l in B.quickdebug:
print "\t" + l print "\t" + l
# remove stdc++ from LLIBS if we are building a statc linked CXXFLAGS # remove stdc++ from LLIBS if we are building a statc linked CXXFLAGS
if env['WITH_BF_STATICCXX']: if env['WITH_BF_STATICCXX']:
if 'stdc++' in env['LLIBS']: if 'stdc++' in env['LLIBS']:
env['LLIBS'].remove('stdc++') env['LLIBS'].remove('stdc++')
else: else:
print '\tcould not remove stdc++ library from LLIBS, WITH_BF_STATICCXX may not work for your platform' print '\tcould not remove stdc++ library from LLIBS, WITH_BF_STATICCXX may not work for your platform'
# check target for blenderplayer. Set WITH_BF_PLAYER if found on cmdline # check target for blenderplayer. Set WITH_BF_PLAYER if found on cmdline
if 'blenderplayer' in B.targets: if 'blenderplayer' in B.targets:
env['WITH_BF_PLAYER'] = True env['WITH_BF_PLAYER'] = True
if 'blendernogame' in B.targets: if 'blendernogame' in B.targets:
env['WITH_BF_GAMEENGINE'] = False env['WITH_BF_GAMEENGINE'] = False
# disable elbeem (fluidsim) compilation? # disable elbeem (fluidsim) compilation?
if env['BF_NO_ELBEEM'] == 1: if env['BF_NO_ELBEEM'] == 1:
env['CPPFLAGS'].append('-DDISABLE_ELBEEM') env['CPPFLAGS'].append('-DDISABLE_ELBEEM')
env['CXXFLAGS'].append('-DDISABLE_ELBEEM') env['CXXFLAGS'].append('-DDISABLE_ELBEEM')
env['CCFLAGS'].append('-DDISABLE_ELBEEM') env['CCFLAGS'].append('-DDISABLE_ELBEEM')
if env['WITH_BF_SDL'] == False and env['OURPLATFORM'] in ('win32-vc', 'win32-ming', 'win64-vc'): if env['WITH_BF_SDL'] == False and env['OURPLATFORM'] in ('win32-vc', 'win32-ming', 'win64-vc'):
env['PLATFORM_LINKFLAGS'].remove('/ENTRY:mainCRTStartup') env['PLATFORM_LINKFLAGS'].remove('/ENTRY:mainCRTStartup')
env['PLATFORM_LINKFLAGS'].append('/ENTRY:main') env['PLATFORM_LINKFLAGS'].append('/ENTRY:main')
# lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir # lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir
B.root_build_dir = env['BF_BUILDDIR'] B.root_build_dir = env['BF_BUILDDIR']
B.doc_build_dir = os.path.join(env['BF_INSTALLDIR'], 'doc') B.doc_build_dir = os.path.join(env['BF_INSTALLDIR'], 'doc')
if not B.root_build_dir[-1]==os.sep: if not B.root_build_dir[-1]==os.sep:
B.root_build_dir += os.sep B.root_build_dir += os.sep
if not B.doc_build_dir[-1]==os.sep: if not B.doc_build_dir[-1]==os.sep:
B.doc_build_dir += os.sep B.doc_build_dir += os.sep
# We do a shortcut for clean when no quicklist is given: just delete # We do a shortcut for clean when no quicklist is given: just delete
# builddir without reading in SConscripts # builddir without reading in SConscripts
do_clean = None do_clean = None
if 'clean' in B.targets: if 'clean' in B.targets:
do_clean = True do_clean = True
if not quickie and do_clean: if not quickie and do_clean:
if os.path.exists(B.doc_build_dir): if os.path.exists(B.doc_build_dir):
print B.bc.HEADER+'Cleaning doc dir...'+B.bc.ENDC print B.bc.HEADER+'Cleaning doc dir...'+B.bc.ENDC
dirs = os.listdir(B.doc_build_dir) dirs = os.listdir(B.doc_build_dir)
for entry in dirs: for entry in dirs:
if os.path.isdir(B.doc_build_dir + entry) == 1: if os.path.isdir(B.doc_build_dir + entry) == 1:
print "clean dir %s"%(B.doc_build_dir+entry) print "clean dir %s"%(B.doc_build_dir+entry)
shutil.rmtree(B.doc_build_dir+entry) shutil.rmtree(B.doc_build_dir+entry)
else: # remove file else: # remove file
print "remove file %s"%(B.doc_build_dir+entry) print "remove file %s"%(B.doc_build_dir+entry)
os.remove(B.root_build_dir+entry) os.remove(B.root_build_dir+entry)
if os.path.exists(B.root_build_dir): if os.path.exists(B.root_build_dir):
print B.bc.HEADER+'Cleaning build dir...'+B.bc.ENDC print B.bc.HEADER+'Cleaning build dir...'+B.bc.ENDC
dirs = os.listdir(B.root_build_dir) dirs = os.listdir(B.root_build_dir)
for entry in dirs: for entry in dirs:
if os.path.isdir(B.root_build_dir + entry) == 1: if os.path.isdir(B.root_build_dir + entry) == 1:
print "clean dir %s"%(B.root_build_dir+entry) print "clean dir %s"%(B.root_build_dir+entry)
shutil.rmtree(B.root_build_dir+entry) shutil.rmtree(B.root_build_dir+entry)
else: # remove file else: # remove file
print "remove file %s"%(B.root_build_dir+entry) print "remove file %s"%(B.root_build_dir+entry)
os.remove(B.root_build_dir+entry) os.remove(B.root_build_dir+entry)
for confile in ['extern/ffmpeg/config.mak', 'extern/x264/config.mak', for confile in ['extern/ffmpeg/config.mak', 'extern/x264/config.mak',
'extern/xvidcore/build/generic/platform.inc', 'extern/ffmpeg/include']: 'extern/xvidcore/build/generic/platform.inc', 'extern/ffmpeg/include']:
if os.path.exists(confile): if os.path.exists(confile):
print "clean file %s"%confile print "clean file %s"%confile
if os.path.isdir(confile): if os.path.isdir(confile):
for root, dirs, files in os.walk(confile): for root, dirs, files in os.walk(confile):
for name in files: for name in files:
os.remove(os.path.join(root, name)) os.remove(os.path.join(root, name))
else: else:
os.remove(confile) os.remove(confile)
print B.bc.OKGREEN+'...done'+B.bc.ENDC print B.bc.OKGREEN+'...done'+B.bc.ENDC
else: else:
print B.bc.HEADER+'Already Clean, nothing to do.'+B.bc.ENDC print B.bc.HEADER+'Already Clean, nothing to do.'+B.bc.ENDC
Exit() Exit()
if not os.path.isdir ( B.root_build_dir): if not os.path.isdir ( B.root_build_dir):
os.makedirs ( B.root_build_dir ) os.makedirs ( B.root_build_dir )
os.makedirs ( B.root_build_dir + 'source' ) os.makedirs ( B.root_build_dir + 'source' )
os.makedirs ( B.root_build_dir + 'intern' ) os.makedirs ( B.root_build_dir + 'intern' )
os.makedirs ( B.root_build_dir + 'extern' ) os.makedirs ( B.root_build_dir + 'extern' )
os.makedirs ( B.root_build_dir + 'lib' ) os.makedirs ( B.root_build_dir + 'lib' )
os.makedirs ( B.root_build_dir + 'bin' ) os.makedirs ( B.root_build_dir + 'bin' )
# # Docs not working with epy anymore # # Docs not working with epy anymore
# if not os.path.isdir(B.doc_build_dir) and env['WITH_BF_DOCS']: # if not os.path.isdir(B.doc_build_dir) and env['WITH_BF_DOCS']:
# os.makedirs ( B.doc_build_dir ) # os.makedirs ( B.doc_build_dir )
Help(opts.GenerateHelpText(env)) Help(opts.GenerateHelpText(env))
@@ -370,10 +370,10 @@ Help(opts.GenerateHelpText(env))
# commands, do 'scons BF_QUIET=0' # commands, do 'scons BF_QUIET=0'
bf_quietoutput = B.arguments.get('BF_QUIET', '1') bf_quietoutput = B.arguments.get('BF_QUIET', '1')
if env['BF_QUIET']: if env['BF_QUIET']:
B.set_quiet_output(env) B.set_quiet_output(env)
else: else:
if toolset=='msvc': if toolset=='msvc':
B.msvc_hack(env) B.msvc_hack(env)
print B.bc.HEADER+'Building in: ' + B.bc.ENDC + os.path.abspath(B.root_build_dir) print B.bc.HEADER+'Building in: ' + B.bc.ENDC + os.path.abspath(B.root_build_dir)
env.SConsignFile(B.root_build_dir+'scons-signatures') env.SConsignFile(B.root_build_dir+'scons-signatures')
@@ -395,23 +395,23 @@ SConscript(B.root_build_dir+'/source/SConscript')
# libraries to give as objects to linking phase # libraries to give as objects to linking phase
mainlist = [] mainlist = []
for tp in B.possible_types: for tp in B.possible_types:
if not tp == 'player': if not tp == 'player':
mainlist += B.create_blender_liblist(env, tp) mainlist += B.create_blender_liblist(env, tp)
if B.arguments.get('BF_PRIORITYLIST', '0')=='1': if B.arguments.get('BF_PRIORITYLIST', '0')=='1':
B.propose_priorities() B.propose_priorities()
dobj = B.buildinfo(env, "dynamic") + B.resources dobj = B.buildinfo(env, "dynamic") + B.resources
thestatlibs, thelibincs = B.setup_staticlibs(env) thestatlibs, thelibincs = B.setup_staticlibs(env)
thesyslibs = B.setup_syslibs(env) thesyslibs = B.setup_syslibs(env)
if 'blender' in B.targets or not env['WITH_BF_NOBLENDER']: if 'blender' in B.targets or not env['WITH_BF_NOBLENDER']:
env.BlenderProg(B.root_build_dir, "blender", mainlist + thestatlibs + dobj, thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blender') env.BlenderProg(B.root_build_dir, "blender", mainlist + thestatlibs + dobj, thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blender')
if env['WITH_BF_PLAYER']: if env['WITH_BF_PLAYER']:
playerlist = B.create_blender_liblist(env, 'player') playerlist = B.create_blender_liblist(env, 'player')
playerlist += B.create_blender_liblist(env, 'intern') playerlist += B.create_blender_liblist(env, 'intern')
playerlist += B.create_blender_liblist(env, 'extern') playerlist += B.create_blender_liblist(env, 'extern')
env.BlenderProg(B.root_build_dir, "blenderplayer", playerlist, thestatlibs + dobj + thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blenderplayer') env.BlenderProg(B.root_build_dir, "blenderplayer", playerlist, thestatlibs + dobj + thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blenderplayer')
##### Now define some targets ##### Now define some targets
@@ -421,19 +421,19 @@ if env['WITH_BF_PLAYER']:
#-- binaries #-- binaries
blenderinstall = [] blenderinstall = []
if env['OURPLATFORM']=='darwin': if env['OURPLATFORM']=='darwin':
for prg in B.program_list: for prg in B.program_list:
bundle = '%s.app' % prg[0] bundle = '%s.app' % prg[0]
bundledir = os.path.dirname(bundle) bundledir = os.path.dirname(bundle)
for dp, dn, df in os.walk(bundle): for dp, dn, df in os.walk(bundle):
if '.svn' in dn: if '.svn' in dn:
dn.remove('.svn') dn.remove('.svn')
if '_svn' in dn: if '_svn' in dn:
dn.remove('_svn') dn.remove('_svn')
dir=env['BF_INSTALLDIR']+dp[len(bundledir):] dir=env['BF_INSTALLDIR']+dp[len(bundledir):]
source=[dp+os.sep+f for f in df] source=[dp+os.sep+f for f in df]
blenderinstall.append(env.Install(dir=dir,source=source)) blenderinstall.append(env.Install(dir=dir,source=source))
else: else:
blenderinstall = env.Install(dir=env['BF_INSTALLDIR'], source=B.program_list) blenderinstall = env.Install(dir=env['BF_INSTALLDIR'], source=B.program_list)
#-- local path = config files in install dir: installdir\VERSION #-- local path = config files in install dir: installdir\VERSION
#- dont do config and scripts for darwin, it is already in the bundle #- dont do config and scripts for darwin, it is already in the bundle
@@ -444,98 +444,98 @@ dottargetlist = []
scriptinstall = [] scriptinstall = []
if env['OURPLATFORM']!='darwin': if env['OURPLATFORM']!='darwin':
for dp, dn, df in os.walk('bin/.blender'): for dp, dn, df in os.walk('bin/.blender'):
if '.svn' in dn: if '.svn' in dn:
dn.remove('.svn') dn.remove('.svn')
if '_svn' in dn: if '_svn' in dn:
dn.remove('_svn') dn.remove('_svn')
for f in df: for f in df:
if not env['WITH_BF_INTERNATIONAL']: if not env['WITH_BF_INTERNATIONAL']:
if 'locale' in dp: if 'locale' in dp:
continue continue
if f == '.Blanguages': if f == '.Blanguages':
continue continue
if not env['WITH_BF_FREETYPE']: if not env['WITH_BF_FREETYPE']:
if f.endswith('.ttf'): if f.endswith('.ttf'):
continue continue
if 'locale' in dp: if 'locale' in dp:
datafileslist.append(os.path.join(dp,f)) datafileslist.append(os.path.join(dp,f))
dir= os.path.join(*([env['BF_INSTALLDIR']] + [VERSION] + ['datafiles'] + dp.split(os.sep)[1:])) # skip bin dir= os.path.join(*([env['BF_INSTALLDIR']] + [VERSION] + ['datafiles'] + dp.split(os.sep)[1:])) # skip bin
datafilestargetlist.append(dir + os.sep + f) datafilestargetlist.append(dir + os.sep + f)
else: else:
dotblendlist.append(os.path.join(dp, f)) dotblendlist.append(os.path.join(dp, f))
dir= os.path.join(*([env['BF_INSTALLDIR']] + [VERSION] + ['config'] + dp.split(os.sep)[1:])) # skip bin dir= os.path.join(*([env['BF_INSTALLDIR']] + [VERSION] + ['config'] + dp.split(os.sep)[1:])) # skip bin
dottargetlist.append(dir + os.sep + f) dottargetlist.append(dir + os.sep + f)
dotblenderinstall = [] dotblenderinstall = []
for targetdir,srcfile in zip(dottargetlist, dotblendlist): for targetdir,srcfile in zip(dottargetlist, dotblendlist):
td, tf = os.path.split(targetdir) td, tf = os.path.split(targetdir)
dotblenderinstall.append(env.Install(dir=td, source=srcfile)) dotblenderinstall.append(env.Install(dir=td, source=srcfile))
for targetdir,srcfile in zip(datafilestargetlist, datafileslist): for targetdir,srcfile in zip(datafilestargetlist, datafileslist):
td, tf = os.path.split(targetdir) td, tf = os.path.split(targetdir)
dotblenderinstall.append(env.Install(dir=td, source=srcfile)) dotblenderinstall.append(env.Install(dir=td, source=srcfile))
if env['WITH_BF_PYTHON']: if env['WITH_BF_PYTHON']:
#-- local/VERSION/scripts #-- local/VERSION/scripts
scriptpaths=['release/scripts'] scriptpaths=['release/scripts']
for scriptpath in scriptpaths: for scriptpath in scriptpaths:
for dp, dn, df in os.walk(scriptpath): for dp, dn, df in os.walk(scriptpath):
if '.svn' in dn: if '.svn' in dn:
dn.remove('.svn') dn.remove('.svn')
if '_svn' in dn: if '_svn' in dn:
dn.remove('_svn') dn.remove('_svn')
dir = os.path.join(env['BF_INSTALLDIR'], VERSION) dir = os.path.join(env['BF_INSTALLDIR'], VERSION)
dir += os.sep + os.path.basename(scriptpath) + dp[len(scriptpath):] dir += os.sep + os.path.basename(scriptpath) + dp[len(scriptpath):]
source=[os.path.join(dp, f) for f in df if f[-3:]!='pyc'] source=[os.path.join(dp, f) for f in df if f[-3:]!='pyc']
scriptinstall.append(env.Install(dir=dir,source=source)) scriptinstall.append(env.Install(dir=dir,source=source))
#-- icons #-- icons
if env['OURPLATFORM']=='linux2': if env['OURPLATFORM']=='linux2':
iconlist = [] iconlist = []
icontargetlist = [] icontargetlist = []
for tp, tn, tf in os.walk('release/freedesktop/icons'): for tp, tn, tf in os.walk('release/freedesktop/icons'):
if '.svn' in tn: if '.svn' in tn:
tn.remove('.svn') tn.remove('.svn')
if '_svn' in tn: if '_svn' in tn:
tn.remove('_svn') tn.remove('_svn')
for f in tf: for f in tf:
iconlist.append(os.path.join(tp, f)) iconlist.append(os.path.join(tp, f))
icontargetlist.append( os.path.join(*([env['BF_INSTALLDIR']] + tp.split(os.sep)[2:] + [f])) ) icontargetlist.append( os.path.join(*([env['BF_INSTALLDIR']] + tp.split(os.sep)[2:] + [f])) )
iconinstall = [] iconinstall = []
for targetdir,srcfile in zip(icontargetlist, iconlist): for targetdir,srcfile in zip(icontargetlist, iconlist):
td, tf = os.path.split(targetdir) td, tf = os.path.split(targetdir)
iconinstall.append(env.Install(dir=td, source=srcfile)) iconinstall.append(env.Install(dir=td, source=srcfile))
# dlls for linuxcross # dlls for linuxcross
# TODO - add more libs, for now this lets blenderlite run # TODO - add more libs, for now this lets blenderlite run
if env['OURPLATFORM']=='linuxcross': if env['OURPLATFORM']=='linuxcross':
dir=env['BF_INSTALLDIR'] dir=env['BF_INSTALLDIR']
source = [] source = []
if env['WITH_BF_OPENMP']: if env['WITH_BF_OPENMP']:
source += ['../lib/windows/pthreads/lib/pthreadGC2.dll'] source += ['../lib/windows/pthreads/lib/pthreadGC2.dll']
scriptinstall.append(env.Install(dir=dir, source=source)) scriptinstall.append(env.Install(dir=dir, source=source))
#-- plugins #-- plugins
pluglist = [] pluglist = []
plugtargetlist = [] plugtargetlist = []
for tp, tn, tf in os.walk('release/plugins'): for tp, tn, tf in os.walk('release/plugins'):
if '.svn' in tn: if '.svn' in tn:
tn.remove('.svn') tn.remove('.svn')
if '_svn' in tn: if '_svn' in tn:
tn.remove('_svn') tn.remove('_svn')
df = tp[8:] # remove 'release/' df = tp[8:] # remove 'release/'
for f in tf: for f in tf:
pluglist.append(os.path.join(tp, f)) pluglist.append(os.path.join(tp, f))
plugtargetlist.append( os.path.join(env['BF_INSTALLDIR'], df, f) ) plugtargetlist.append( os.path.join(env['BF_INSTALLDIR'], df, f) )
# header files for plugins # header files for plugins
@@ -556,82 +556,82 @@ plugtargetlist.append(os.path.join(env['BF_INSTALLDIR'], 'plugins', 'include', '
plugininstall = [] plugininstall = []
for targetdir,srcfile in zip(plugtargetlist, pluglist): for targetdir,srcfile in zip(plugtargetlist, pluglist):
td, tf = os.path.split(targetdir) td, tf = os.path.split(targetdir)
plugininstall.append(env.Install(dir=td, source=srcfile)) plugininstall.append(env.Install(dir=td, source=srcfile))
textlist = [] textlist = []
texttargetlist = [] texttargetlist = []
for tp, tn, tf in os.walk('release/text'): for tp, tn, tf in os.walk('release/text'):
if '.svn' in tn: if '.svn' in tn:
tn.remove('.svn') tn.remove('.svn')
if '_svn' in tn: if '_svn' in tn:
tn.remove('_svn') tn.remove('_svn')
for f in tf: for f in tf:
textlist.append(tp+os.sep+f) textlist.append(tp+os.sep+f)
textinstall = env.Install(dir=env['BF_INSTALLDIR'], source=textlist) textinstall = env.Install(dir=env['BF_INSTALLDIR'], source=textlist)
if env['OURPLATFORM']=='darwin': if env['OURPLATFORM']=='darwin':
allinstall = [blenderinstall, plugininstall, textinstall] allinstall = [blenderinstall, plugininstall, textinstall]
elif env['OURPLATFORM']=='linux2': elif env['OURPLATFORM']=='linux2':
allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall, iconinstall] allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall, iconinstall]
else: else:
allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall] allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall]
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'): if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
dllsources = [] dllsources = []
if not env['OURPLATFORM'] in ('win32-mingw', 'win64-vc', 'linuxcross'): if not env['OURPLATFORM'] in ('win32-mingw', 'win64-vc', 'linuxcross'):
# For MinGW and linuxcross static linking will be used # For MinGW and linuxcross static linking will be used
dllsources += ['${LCGDIR}/gettext/lib/gnu_gettext.dll'] dllsources += ['${LCGDIR}/gettext/lib/gnu_gettext.dll']
#currently win64-vc doesn't appear to have libpng.dll #currently win64-vc doesn't appear to have libpng.dll
if env['OURPLATFORM'] != 'win64-vc': if env['OURPLATFORM'] != 'win64-vc':
dllsources += ['${BF_PNG_LIBPATH}/libpng.dll'] dllsources += ['${BF_PNG_LIBPATH}/libpng.dll']
dllsources += ['${BF_ZLIB_LIBPATH}/zlib.dll'] dllsources += ['${BF_ZLIB_LIBPATH}/zlib.dll']
# Used when linking to libtiff was dynamic # Used when linking to libtiff was dynamic
# keep it here until compilation on all platform would be ok # keep it here until compilation on all platform would be ok
# dllsources += ['${BF_TIFF_LIBPATH}/${BF_TIFF_LIB}.dll'] # dllsources += ['${BF_TIFF_LIBPATH}/${BF_TIFF_LIB}.dll']
if env['OURPLATFORM'] != 'linuxcross': if env['OURPLATFORM'] != 'linuxcross':
# pthreads library is already added # pthreads library is already added
dllsources += ['${BF_PTHREADS_LIBPATH}/${BF_PTHREADS_LIB}.dll'] dllsources += ['${BF_PTHREADS_LIBPATH}/${BF_PTHREADS_LIB}.dll']
if env['WITH_BF_SDL']: if env['WITH_BF_SDL']:
if env['OURPLATFORM'] == 'win64-vc': if env['OURPLATFORM'] == 'win64-vc':
pass # we link statically already to SDL on win64 pass # we link statically already to SDL on win64
else: else:
dllsources.append('${BF_SDL_LIBPATH}/SDL.dll') dllsources.append('${BF_SDL_LIBPATH}/SDL.dll')
if env['WITH_BF_PYTHON']: if env['WITH_BF_PYTHON']:
if env['BF_DEBUG']: if env['BF_DEBUG']:
dllsources.append('${BF_PYTHON_LIBPATH}/${BF_PYTHON_DLL}_d.dll') dllsources.append('${BF_PYTHON_LIBPATH}/${BF_PYTHON_DLL}_d.dll')
else: else:
dllsources.append('${BF_PYTHON_LIBPATH}/${BF_PYTHON_DLL}.dll') dllsources.append('${BF_PYTHON_LIBPATH}/${BF_PYTHON_DLL}.dll')
if env['WITH_BF_ICONV']: if env['WITH_BF_ICONV']:
if env['OURPLATFORM'] == 'win64-vc': if env['OURPLATFORM'] == 'win64-vc':
pass # we link statically to iconv on win64 pass # we link statically to iconv on win64
elif not env['OURPLATFORM'] in ('win32-mingw', 'linuxcross'): elif not env['OURPLATFORM'] in ('win32-mingw', 'linuxcross'):
#gettext for MinGW and cross-compilation is compiled staticly #gettext for MinGW and cross-compilation is compiled staticly
dllsources += ['${BF_ICONV_LIBPATH}/iconv.dll'] dllsources += ['${BF_ICONV_LIBPATH}/iconv.dll']
if env['WITH_BF_OPENAL']: if env['WITH_BF_OPENAL']:
dllsources.append('${LCGDIR}/openal/lib/OpenAL32.dll') dllsources.append('${LCGDIR}/openal/lib/OpenAL32.dll')
dllsources.append('${LCGDIR}/openal/lib/wrap_oal.dll') dllsources.append('${LCGDIR}/openal/lib/wrap_oal.dll')
if env['WITH_BF_SNDFILE']: if env['WITH_BF_SNDFILE']:
dllsources.append('${LCGDIR}/sndfile/lib/libsndfile-1.dll') dllsources.append('${LCGDIR}/sndfile/lib/libsndfile-1.dll')
if env['WITH_BF_FFMPEG']: if env['WITH_BF_FFMPEG']:
dllsources += ['${BF_FFMPEG_LIBPATH}/avcodec-52.dll', dllsources += ['${BF_FFMPEG_LIBPATH}/avcodec-52.dll',
'${BF_FFMPEG_LIBPATH}/avformat-52.dll', '${BF_FFMPEG_LIBPATH}/avformat-52.dll',
'${BF_FFMPEG_LIBPATH}/avdevice-52.dll', '${BF_FFMPEG_LIBPATH}/avdevice-52.dll',
'${BF_FFMPEG_LIBPATH}/avutil-50.dll', '${BF_FFMPEG_LIBPATH}/avutil-50.dll',
'${BF_FFMPEG_LIBPATH}/swscale-0.dll'] '${BF_FFMPEG_LIBPATH}/swscale-0.dll']
windlls = env.Install(dir=env['BF_INSTALLDIR'], source = dllsources) windlls = env.Install(dir=env['BF_INSTALLDIR'], source = dllsources)
allinstall += windlls allinstall += windlls
installtarget = env.Alias('install', allinstall) installtarget = env.Alias('install', allinstall)
bininstalltarget = env.Alias('install-bin', blenderinstall) bininstalltarget = env.Alias('install-bin', blenderinstall)
@@ -641,24 +641,24 @@ nsiscmd = env.Command('nsisinstaller', None, nsisaction)
nsisalias = env.Alias('nsis', nsiscmd) nsisalias = env.Alias('nsis', nsiscmd)
if 'blender' in B.targets: if 'blender' in B.targets:
blenderexe= env.Alias('blender', B.program_list) blenderexe= env.Alias('blender', B.program_list)
Depends(blenderexe,installtarget) Depends(blenderexe,installtarget)
if env['WITH_BF_PLAYER']: if env['WITH_BF_PLAYER']:
blenderplayer = env.Alias('blenderplayer', B.program_list) blenderplayer = env.Alias('blenderplayer', B.program_list)
Depends(blenderplayer,installtarget) Depends(blenderplayer,installtarget)
if not env['WITH_BF_GAMEENGINE']: if not env['WITH_BF_GAMEENGINE']:
blendernogame = env.Alias('blendernogame', B.program_list) blendernogame = env.Alias('blendernogame', B.program_list)
Depends(blendernogame,installtarget) Depends(blendernogame,installtarget)
if 'blenderlite' in B.targets: if 'blenderlite' in B.targets:
blenderlite = env.Alias('blenderlite', B.program_list) blenderlite = env.Alias('blenderlite', B.program_list)
Depends(blenderlite,installtarget) Depends(blenderlite,installtarget)
Depends(nsiscmd, allinstall) Depends(nsiscmd, allinstall)
Default(B.program_list) Default(B.program_list)
if not env['WITHOUT_BF_INSTALL']: if not env['WITHOUT_BF_INSTALL']:
Default(installtarget) Default(installtarget)

File diff suppressed because it is too large Load Diff

View File

@@ -32,4 +32,4 @@ license@blender.org for further information.
Ton Roosendaal Ton Roosendaal
Chairman Blender Foundation. Chairman Blender Foundation.
June 2005 June 2005

View File

@@ -1390,4 +1390,4 @@ Radoslav Dejanovic
James H. Cloos, Jr. James H. Cloos, Jr.
Karl Erlandsen (LethalSideParting) Karl Erlandsen (LethalSideParting)
Kari Pulli Kari Pulli
Dave Shemano Dave Shemano

4
extern/SConscript vendored
View File

@@ -17,7 +17,7 @@ if env['OURPLATFORM'] == 'linux2':
SConscript(['binreloc/SConscript']); SConscript(['binreloc/SConscript']);
if env['WITH_BF_LZO']: if env['WITH_BF_LZO']:
SConscript(['lzo/SConscript']) SConscript(['lzo/SConscript'])
if env['WITH_BF_LZMA']: if env['WITH_BF_LZMA']:
SConscript(['lzma/SConscript']) SConscript(['lzma/SConscript'])

View File

@@ -23,4 +23,3 @@ ADD_DEFINITIONS(-DENABLE_BINRELOC)
FILE(GLOB SRC *.c) FILE(GLOB SRC *.c)
BLENDERLIB(extern_binreloc "${SRC}" "${INC}") BLENDERLIB(extern_binreloc "${SRC}" "${INC}")
#, libtype=['core','player'], priority = [25,15] )

View File

@@ -24,12 +24,13 @@ btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int
m_shapeType = CONVEX_HULL_SHAPE_PROXYTYPE; m_shapeType = CONVEX_HULL_SHAPE_PROXYTYPE;
m_unscaledPoints.resize(numPoints); m_unscaledPoints.resize(numPoints);
unsigned char* pointsBaseAddress = (unsigned char*)points; unsigned char* pointsAddress = (unsigned char*)points;
for (int i=0;i<numPoints;i++) for (int i=0;i<numPoints;i++)
{ {
btVector3* point = (btVector3*)(pointsBaseAddress + i*stride); btScalar* point = (btScalar*)pointsAddress;
m_unscaledPoints[i] = point[0]; m_unscaledPoints[i] = btVector3(point[0], point[1], point[2]);
pointsAddress += stride;
} }
recalcLocalAabb(); recalcLocalAabb();

View File

@@ -11,15 +11,15 @@ flags = []
defs = [] defs = []
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
flags = [] flags = []
defs.append('OPJ_STATIC') defs.append('OPJ_STATIC')
else: else:
flags = ['-Wall', '-O3', '-ffast-math', '-std=c99'] flags = ['-Wall', '-O3', '-ffast-math', '-std=c99']
oj_env = env.Clone() oj_env = env.Clone()
if not env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): if not env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
oj_env.Replace(CCFLAGS = '') oj_env.Replace(CCFLAGS = '')
oj_env.Replace(BF_DEBUG_FLAGS = '') oj_env.Replace(BF_DEBUG_FLAGS = '')
oj_env.BlenderLib ( libname='extern_openjpeg', oj_env.BlenderLib ( libname='extern_openjpeg',
sources=sources, includes=Split(incs), sources=sources, includes=Split(incs),

View File

@@ -20,36 +20,52 @@
# #
# ***** END LGPL LICENSE BLOCK ***** # ***** END LGPL LICENSE BLOCK *****
SET(INC . intern FX SRC ${PTHREADS_INC} ${LIBSAMPLERATE_INC}) SET(INC
.
intern
FX SRC
${PTHREADS_INC}
${LIBSAMPLERATE_INC}
)
FILE(GLOB SRC intern/*.cpp intern/*.h FX/*.cpp SRC/*.cpp) FILE(GLOB SRC
intern/*.cpp
intern/*.h
FX/*.cpp
SRC/*.cpp
)
IF(WITH_FFMPEG) IF(WITH_FFMPEG)
SET(INC ${INC} ffmpeg ${FFMPEG_INC}) LIST(APPEND INC ffmpeg)
LIST(APPEND INC ${FFMPEG_INC})
FILE(GLOB FFMPEGSRC ffmpeg/*.cpp) FILE(GLOB FFMPEGSRC ffmpeg/*.cpp)
ADD_DEFINITIONS(-DWITH_FFMPEG) ADD_DEFINITIONS(-DWITH_FFMPEG)
ENDIF(WITH_FFMPEG) ENDIF(WITH_FFMPEG)
IF(WITH_SDL) IF(WITH_SDL)
SET(INC ${INC} SDL ${SDL_INCLUDE_DIR}) LIST(APPEND INC SDL)
LIST(APPEND INC ${SDL_INCLUDE_DIR})
FILE(GLOB SDLSRC SDL/*.cpp) FILE(GLOB SDLSRC SDL/*.cpp)
ADD_DEFINITIONS(-DWITH_SDL) ADD_DEFINITIONS(-DWITH_SDL)
ENDIF(WITH_SDL) ENDIF(WITH_SDL)
IF(WITH_OPENAL) IF(WITH_OPENAL)
SET(INC ${INC} OpenAL ${OPENAL_INCLUDE_DIR}) LIST(APPEND INC OpenAL)
LIST(APPEND INC ${OPENAL_INCLUDE_DIR})
FILE(GLOB OPENALSRC OpenAL/*.cpp) FILE(GLOB OPENALSRC OpenAL/*.cpp)
ADD_DEFINITIONS(-DWITH_OPENAL) ADD_DEFINITIONS(-DWITH_OPENAL)
ENDIF(WITH_OPENAL) ENDIF(WITH_OPENAL)
IF(WITH_JACK) IF(WITH_JACK)
SET(INC ${INC} jack ${JACK_INC}) LIST(APPEND INC jack)
LIST(APPEND INC ${JACK_INC})
FILE(GLOB JACKSRC jack/*.cpp) FILE(GLOB JACKSRC jack/*.cpp)
ADD_DEFINITIONS(-DWITH_JACK) ADD_DEFINITIONS(-DWITH_JACK)
ENDIF(WITH_JACK) ENDIF(WITH_JACK)
IF(WITH_SNDFILE) IF(WITH_SNDFILE)
SET(INC ${INC} sndfile ${SNDFILE_INC}) LIST(APPEND INC sndfile)
LIST(APPEND INC ${SNDFILE_INC})
FILE(GLOB SNDFILESRC sndfile/*.cpp) FILE(GLOB SNDFILESRC sndfile/*.cpp)
ADD_DEFINITIONS(-DWITH_SNDFILE) ADD_DEFINITIONS(-DWITH_SNDFILE)
ENDIF(WITH_SNDFILE) ENDIF(WITH_SNDFILE)
@@ -61,7 +77,8 @@ ENDIF(WITH_SNDFILE)
#ENDIF(WITH_FFTW3) #ENDIF(WITH_FFTW3)
IF(WITH_PYTHON) IF(WITH_PYTHON)
SET(INC ${INC} Python ${PYTHON_INC}) LIST(APPEND INC Python)
LIST(APPEND INC ${PYTHON_INC})
FILE(GLOB PYTHONSRC Python/*.cpp) FILE(GLOB PYTHONSRC Python/*.cpp)
ELSE(WITH_PYTHON) ELSE(WITH_PYTHON)
ADD_DEFINITIONS(-DDISABLE_PYTHON) ADD_DEFINITIONS(-DDISABLE_PYTHON)

View File

@@ -243,7 +243,10 @@ void AUD_OpenALDevice::updateStreams()
stop(sound); stop(sound);
// decrement again, so that we get the next sound in the // decrement again, so that we get the next sound in the
// next loop run // next loop run
--it; if(m_playingSounds->empty())
break;
else
--it;
} }
// continue playing // continue playing
else else

View File

@@ -7,40 +7,40 @@ incs = '. intern FX SRC ' + env['BF_PTHREADS_INC'] + ' ' + env['BF_LIBSAMPLERATE
defs = [] defs = []
if env['WITH_BF_FFMPEG']: if env['WITH_BF_FFMPEG']:
sources += env.Glob('ffmpeg/*.cpp') sources += env.Glob('ffmpeg/*.cpp')
incs += ' ffmpeg ' + env['BF_FFMPEG_INC'] incs += ' ffmpeg ' + env['BF_FFMPEG_INC']
defs.append('WITH_FFMPEG') defs.append('WITH_FFMPEG')
if env['WITH_BF_SDL']: if env['WITH_BF_SDL']:
sources += env.Glob('SDL/*.cpp') sources += env.Glob('SDL/*.cpp')
incs += ' SDL ' + env['BF_SDL_INC'] incs += ' SDL ' + env['BF_SDL_INC']
defs.append('WITH_SDL') defs.append('WITH_SDL')
if env['WITH_BF_OPENAL']: if env['WITH_BF_OPENAL']:
sources += env.Glob('OpenAL/*.cpp') sources += env.Glob('OpenAL/*.cpp')
incs += ' OpenAL ' + env['BF_OPENAL_INC'] incs += ' OpenAL ' + env['BF_OPENAL_INC']
defs.append('WITH_OPENAL') defs.append('WITH_OPENAL')
if env['WITH_BF_JACK']: if env['WITH_BF_JACK']:
sources += env.Glob('jack/*.cpp') sources += env.Glob('jack/*.cpp')
incs += ' jack ' + env['BF_JACK_INC'] incs += ' jack ' + env['BF_JACK_INC']
defs.append('WITH_JACK') defs.append('WITH_JACK')
if env['WITH_BF_SNDFILE']: if env['WITH_BF_SNDFILE']:
sources += env.Glob('sndfile/*.cpp') sources += env.Glob('sndfile/*.cpp')
incs += ' sndfile ' + env['BF_SNDFILE_INC'] incs += ' sndfile ' + env['BF_SNDFILE_INC']
defs.append('WITH_SNDFILE') defs.append('WITH_SNDFILE')
#if env['WITH_BF_FFTW3']: #if env['WITH_BF_FFTW3']:
# sources += env.Glob('fftw/*.cpp') # sources += env.Glob('fftw/*.cpp')
# incs += ' fftw ' + env['BF_FFTW3_INC'] # incs += ' fftw ' + env['BF_FFTW3_INC']
# defs.append('WITH_FFTW3') # defs.append('WITH_FFTW3')
if env['WITH_BF_PYTHON']: if env['WITH_BF_PYTHON']:
sources += env.Glob('Python/*.cpp') sources += env.Glob('Python/*.cpp')
incs += ' Python ' + env['BF_PYTHON_INC'] incs += ' Python ' + env['BF_PYTHON_INC']
else: else:
defs.append('DISABLE_PYTHON') defs.append('DISABLE_PYTHON')
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'): if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
incs += ' ' + env['BF_PTHREADS_INC'] incs += ' ' + env['BF_PTHREADS_INC']

View File

@@ -96,7 +96,6 @@ typedef AUD_Handle AUD_Channel;
#endif #endif
static AUD_IDevice* AUD_device = NULL; static AUD_IDevice* AUD_device = NULL;
static int AUD_available_devices[4];
static AUD_I3DDevice* AUD_3ddevice = NULL; static AUD_I3DDevice* AUD_3ddevice = NULL;
void AUD_initOnce() void AUD_initOnce()
@@ -161,22 +160,6 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize)
} }
} }
int* AUD_enumDevices()
{
int i = 0;
#ifdef WITH_SDL
AUD_available_devices[i++] = AUD_SDL_DEVICE;
#endif
#ifdef WITH_OPENAL
AUD_available_devices[i++] = AUD_OPENAL_DEVICE;
#endif
#ifdef WITH_JACK
AUD_available_devices[i++] = AUD_JACK_DEVICE;
#endif
AUD_available_devices[i++] = AUD_NULL_DEVICE;
return AUD_available_devices;
}
void AUD_exit() void AUD_exit()
{ {
#ifndef DISABLE_PYTHON #ifndef DISABLE_PYTHON

View File

@@ -69,12 +69,6 @@ extern void AUD_initOnce();
*/ */
extern int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize); extern int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize);
/**
* Returns a integer list with available sound devices. The last one is always
* AUD_NULL_DEVICE.
*/
extern int* AUD_enumDevices();
/** /**
* Unitinitializes an audio device. * Unitinitializes an audio device.
*/ */

View File

@@ -8,56 +8,56 @@ window_system = env['OURPLATFORM']
sources = env.Glob('intern/*.cpp') sources = env.Glob('intern/*.cpp')
if window_system == 'darwin': if window_system == 'darwin':
sources += env.Glob('intern/*.mm') sources += env.Glob('intern/*.mm')
pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_Window', 'GHOST_DropTarget'] pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_Window', 'GHOST_DropTarget']
defs=['_USE_MATH_DEFINES'] defs=['_USE_MATH_DEFINES']
if window_system in ('linux2', 'openbsd3', 'sunos5', 'freebsd7', 'freebsd8', 'freebsd9', 'irix6', 'aix4', 'aix5'): if window_system in ('linux2', 'openbsd3', 'sunos5', 'freebsd7', 'freebsd8', 'freebsd9', 'irix6', 'aix4', 'aix5'):
for f in pf: for f in pf:
try: try:
sources.remove('intern' + os.sep + f + 'Win32.cpp') sources.remove('intern' + os.sep + f + 'Win32.cpp')
sources.remove('intern' + os.sep + f + 'Carbon.cpp') sources.remove('intern' + os.sep + f + 'Carbon.cpp')
except ValueError: except ValueError:
pass pass
elif window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'): elif window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
for f in pf: for f in pf:
try: try:
sources.remove('intern' + os.sep + f + 'X11.cpp') sources.remove('intern' + os.sep + f + 'X11.cpp')
sources.remove('intern' + os.sep + f + 'Carbon.cpp') sources.remove('intern' + os.sep + f + 'Carbon.cpp')
except ValueError: except ValueError:
pass pass
elif window_system == 'darwin': elif window_system == 'darwin':
if env['WITH_GHOST_COCOA']: if env['WITH_GHOST_COCOA']:
if env['WITH_BF_QUICKTIME']: if env['WITH_BF_QUICKTIME']:
defs.append('WITH_QUICKTIME') defs.append('WITH_QUICKTIME')
if env['USE_QTKIT']: if env['USE_QTKIT']:
defs.append('USE_QTKIT') defs.append('USE_QTKIT')
for f in pf: for f in pf:
try: try:
sources.remove('intern' + os.sep + f + 'Win32.cpp') sources.remove('intern' + os.sep + f + 'Win32.cpp')
sources.remove('intern' + os.sep + f + 'X11.cpp') sources.remove('intern' + os.sep + f + 'X11.cpp')
sources.remove('intern' + os.sep + f + 'Carbon.cpp') sources.remove('intern' + os.sep + f + 'Carbon.cpp')
except ValueError: except ValueError:
pass pass
else: else:
for f in pf: for f in pf:
try: try:
sources.remove('intern' + os.sep + f + 'Win32.cpp') sources.remove('intern' + os.sep + f + 'Win32.cpp')
sources.remove('intern' + os.sep + f + 'X11.cpp') sources.remove('intern' + os.sep + f + 'X11.cpp')
sources.remove('intern' + os.sep + f + 'Cocoa.mm') sources.remove('intern' + os.sep + f + 'Cocoa.mm')
except ValueError: except ValueError:
pass pass
else: else:
print "Unknown window system specified." print "Unknown window system specified."
Exit() Exit()
if env['BF_GHOST_DEBUG']: if env['BF_GHOST_DEBUG']:
defs.append('BF_GHOST_DEBUG') defs.append('BF_GHOST_DEBUG')
incs = '. ../string #extern/glew/include #source/blender/imbuf #source/blender/makesdna ' + env['BF_OPENGL_INC'] incs = '. ../string #extern/glew/include #source/blender/imbuf #source/blender/makesdna ' + env['BF_OPENGL_INC']
if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'): if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
incs = env['BF_WINTAB_INC'] + ' ' + incs incs = env['BF_WINTAB_INC'] + ' ' + incs
env.BlenderLib ('bf_intern_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15] ) env.BlenderLib ('bf_intern_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15] )

View File

@@ -212,4 +212,4 @@ bool GHOST_WindowManager::getAnyModifiedState()
} }
return isAnyModified; return isAnyModified;
} }

View File

@@ -117,7 +117,7 @@ SOURCE=..\..\..\..\source\blender\blenkernel\bad_level_call_stubs\stubs.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\..\..\source\icons\winplayer.rc SOURCE=..\..\..\..\source\icons\winblender.rc
# End Source File # End Source File
# End Group # End Group
# Begin Group "Header Files" # Begin Group "Header Files"
@@ -145,7 +145,7 @@ SOURCE=..\..\..\..\source\gameengine\GamePlayer\ghost\GPG_System.h
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# Begin Source File # Begin Source File
SOURCE=..\..\..\..\source\icons\winplayer.ico SOURCE=..\..\..\..\source\icons\winblender.ico
# End Source File # End Source File
# End Group # End Group
# Begin Source File # Begin Source File

View File

@@ -189,7 +189,7 @@ ECHO Done
RelativePath="..\..\..\..\source\blender\blenkernel\bad_level_call_stubs\stubs.c"> RelativePath="..\..\..\..\source\blender\blenkernel\bad_level_call_stubs\stubs.c">
</File> </File>
<File <File
RelativePath="..\..\..\..\source\icons\winplayer.rc"> RelativePath="..\..\..\..\source\icons\winblender.rc">
<FileConfiguration <FileConfiguration
Name="BlenderPlayer Debug|Win32"> Name="BlenderPlayer Debug|Win32">
<Tool <Tool
@@ -224,7 +224,7 @@ ECHO Done
Name="Resource Files" Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"> Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
<File <File
RelativePath="..\..\..\..\source\icons\winplayer.ico"> RelativePath="..\..\..\..\source\icons\winblender.ico">
</File> </File>
</Filter> </Filter>
<File <File

View File

@@ -239,7 +239,7 @@
> >
</File> </File>
<File <File
RelativePath="..\..\..\..\source\icons\winplayer.rc" RelativePath="..\..\..\..\source\icons\winblender.rc"
> >
<FileConfiguration <FileConfiguration
Name="BlenderPlayer Debug|Win32" Name="BlenderPlayer Debug|Win32"
@@ -285,7 +285,7 @@
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
> >
<File <File
RelativePath="..\..\..\..\source\icons\winplayer.ico" RelativePath="..\..\..\..\source\icons\winblender.ico"
> >
</File> </File>
</Filter> </Filter>

View File

@@ -1,7 +1,12 @@
[Desktop Entry] [Desktop Entry]
Encoding=UTF-8
Name=Blender Name=Blender
GenericName=3D modeller
GenericName[es]=modelador 3D
GenericName[de]=3D Modellierer
GenericName[fr]=modeleur 3D
GenericName[ru]=Редактор 3D-моделей
Comment=3D modeling, animation, rendering and post-production Comment=3D modeling, animation, rendering and post-production
Comment[es]=modelado 3D, animación, renderizado y post-producción
Exec=blender Exec=blender
Icon=blender.svg Icon=blender.svg
Terminal=false Terminal=false

View File

@@ -1,208 +0,0 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
__author__ = "Bill L.Nieuwendorp"
__bpydoc__ = """\
This script Exports Lightwaves MotionDesigner format.
The .mdd format has become quite a popular Pipeline format<br>
for moving animations from package to package.
Be sure not to use modifiers that change the number or order of verts in the mesh
"""
#Please send any fixes,updates,bugs to Slow67_at_Gmail.com or cbarton_at_metavr.com
#Bill Niewuendorp
# ***** 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.
#
# ***** END GPL LICENCE BLOCK *****
import bpy
import mathutils
from struct import pack
def zero_file(filepath):
'''
If a file fails, this replaces it with 1 char, better not remove it?
'''
file = open(filepath, 'w')
file.write('\n') # apparently macosx needs some data in a blank file?
file.close()
def check_vertcount(mesh, vertcount):
'''
check and make sure the vertcount is consistent throughout the frame range
'''
if len(mesh.vertices) != vertcount:
raise Exception('Error, number of verts has changed during animation, cannot export')
f.close()
zero_file(filepath)
return
def write(filename, sce, ob, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS):
"""
Blender.Window.WaitCursor(1)
mesh_orig = Mesh.New()
mesh_orig.getFromObject(ob.name)
"""
bpy.ops.object.mode_set(mode='OBJECT')
orig_frame = sce.frame_current
sce.set_frame(PREF_STARTFRAME)
me = ob.create_mesh(sce, True, 'PREVIEW')
#Flip y and z
mat_flip = mathutils.Matrix(\
[1.0, 0.0, 0.0, 0.0],\
[0.0, 0.0, 1.0, 0.0],\
[0.0, 1.0, 0.0, 0.0],\
[0.0, 0.0, 0.0, 1.0],\
)
numverts = len(me.vertices)
numframes = PREF_ENDFRAME - PREF_STARTFRAME + 1
PREF_FPS = float(PREF_FPS)
f = open(filename, 'wb') #no Errors yet:Safe to create file
# Write the header
f.write(pack(">2i", numframes, numverts))
# Write the frame times (should we use the time IPO??)
f.write(pack(">%df" % (numframes), *[frame / PREF_FPS for frame in range(numframes)])) # seconds
#rest frame needed to keep frames in sync
"""
Blender.Set('curframe', PREF_STARTFRAME)
me_tmp.getFromObject(ob.name)
"""
check_vertcount(me, numverts)
me.transform(mat_flip * ob.matrix_world)
f.write(pack(">%df" % (numverts * 3), *[axis for v in me.vertices for axis in v.co]))
for frame in range(PREF_STARTFRAME, PREF_ENDFRAME + 1):#in order to start at desired frame
"""
Blender.Set('curframe', frame)
me_tmp.getFromObject(ob.name)
"""
sce.set_frame(frame)
me = ob.create_mesh(sce, True, 'PREVIEW')
check_vertcount(me, numverts)
me.transform(mat_flip * ob.matrix_world)
# Write the vertex data
f.write(pack(">%df" % (numverts * 3), *[axis for v in me.vertices for axis in v.co]))
"""
me_tmp.vertices= None
"""
f.close()
print('MDD Exported: %s frames:%d\n' % (filename, numframes - 1))
"""
Blender.Window.WaitCursor(0)
Blender.Set('curframe', orig_frame)
"""
sce.set_frame(orig_frame)
from bpy.props import *
class ExportMDD(bpy.types.Operator):
'''Animated mesh to MDD vertex keyframe file'''
bl_idname = "export.mdd"
bl_label = "Export MDD"
# get first scene to get min and max properties for frames, fps
minframe = 1
maxframe = 300000
minfps = 1
maxfps = 120
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
filepath = StringProperty(name="File Path", description="Filepath used for exporting the MDD file", maxlen=1024)
check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'})
fps = IntProperty(name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default=25)
frame_start = IntProperty(name="Start Frame", description="Start frame for baking", min=minframe, max=maxframe, default=1)
frame_end = IntProperty(name="End Frame", description="End frame for baking", min=minframe, max=maxframe, default=250)
@classmethod
def poll(cls, context):
ob = context.active_object
return (ob and ob.type == 'MESH')
def execute(self, context):
filepath = self.properties.filepath
filepath = bpy.path.ensure_ext(filepath, ".mdd")
write(filepath,
context.scene,
context.active_object,
self.properties.frame_start,
self.properties.frame_end,
self.properties.fps,
)
return {'FINISHED'}
def invoke(self, context, event):
import os
if not self.properties.is_property_set("filepath"):
self.properties.filepath = os.path.splitext(bpy.data.filepath)[0] + ".mdd"
context.manager.add_fileselect(self)
return {'RUNNING_MODAL'}
def menu_func(self, context):
self.layout.operator(ExportMDD.bl_idname, text="Lightwave Point Cache (.mdd)")
def register():
bpy.types.INFO_MT_file_export.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_export.remove(menu_func)
if __name__ == "__main__":
register()

View File

@@ -1,327 +0,0 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
__author__ = "Bruce Merry"
__version__ = "0.93"
__bpydoc__ = """\
This script exports Stanford PLY files from Blender. It supports normals,
colours, and texture coordinates per face or per vertex.
Only one mesh can be exported at a time.
"""
# Copyright (C) 2004, 2005: Bruce Merry, bmerry@cs.uct.ac.za
#
# 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.
# Vector rounding se we can use as keys
#
# Updated on Aug 11, 2008 by Campbell Barton
# - added 'comment' prefix to comments - Needed to comply with the PLY spec.
#
# Updated on Jan 1, 2007 by Gabe Ghearing
# - fixed normals so they are correctly smooth/flat
# - fixed crash when the model doesn't have uv coords or vertex colors
# - fixed crash when the model has vertex colors but doesn't have uv coords
# - changed float32 to float and uint8 to uchar for compatibility
# Errata/Notes as of Jan 1, 2007
# - script exports texture coords if they exist even if TexFace isn't selected (not a big deal to me)
# - ST(R) should probably be renamed UV(T) like in most PLY files (importer needs to be updated to take either)
#
# Updated on Jan 3, 2007 by Gabe Ghearing
# - fixed "sticky" vertex UV exporting
# - added pupmenu to enable/disable exporting normals, uv coords, and colors
# Errata/Notes as of Jan 3, 2007
# - ST(R) coords should probably be renamed UV(T) like in most PLY files (importer needs to be updated to take either)
# - edges should be exported since PLY files support them
# - code is getting spaghettish, it should be refactored...
#
def rvec3d(v):
return round(v[0], 6), round(v[1], 6), round(v[2], 6)
def rvec2d(v):
return round(v[0], 6), round(v[1], 6)
def write(filename, scene, ob, \
EXPORT_APPLY_MODIFIERS=True,\
EXPORT_NORMALS=True,\
EXPORT_UV=True,\
EXPORT_COLORS=True):
if not filename.lower().endswith('.ply'):
filename += '.ply'
if not ob:
raise Exception("Error, Select 1 active object")
return
file = open(filename, 'w')
#EXPORT_EDGES = Draw.Create(0)
"""
is_editmode = Blender.Window.EditMode()
if is_editmode:
Blender.Window.EditMode(0, '', 0)
Window.WaitCursor(1)
"""
if scene.objects.active:
bpy.ops.object.mode_set(mode='OBJECT')
#mesh = BPyMesh.getMeshFromObject(ob, None, EXPORT_APPLY_MODIFIERS, False, scn) # XXX
if EXPORT_APPLY_MODIFIERS:
mesh = ob.create_mesh(scene, True, 'PREVIEW')
else:
mesh = ob.data
if not mesh:
raise ("Error, could not get mesh data from active object")
return
# mesh.transform(ob.matrix_world) # XXX
faceUV = (len(mesh.uv_textures) > 0)
vertexUV = (len(mesh.sticky) > 0)
vertexColors = len(mesh.vertex_colors) > 0
if (not faceUV) and (not vertexUV):
EXPORT_UV = False
if not vertexColors:
EXPORT_COLORS = False
if not EXPORT_UV:
faceUV = vertexUV = False
if not EXPORT_COLORS:
vertexColors = False
if faceUV:
active_uv_layer = mesh.uv_textures.active
if not active_uv_layer:
EXPORT_UV = False
faceUV = None
else:
active_uv_layer = active_uv_layer.data
if vertexColors:
active_col_layer = mesh.vertex_colors.active
if not active_col_layer:
EXPORT_COLORS = False
vertexColors = None
else:
active_col_layer = active_col_layer.data
# incase
color = uvcoord = uvcoord_key = normal = normal_key = None
mesh_verts = mesh.vertices # save a lookup
ply_verts = [] # list of dictionaries
# vdict = {} # (index, normal, uv) -> new index
vdict = [{} for i in range(len(mesh_verts))]
ply_faces = [[] for f in range(len(mesh.faces))]
vert_count = 0
for i, f in enumerate(mesh.faces):
smooth = f.use_smooth
if not smooth:
normal = tuple(f.normal)
normal_key = rvec3d(normal)
if faceUV:
uv = active_uv_layer[i]
uv = uv.uv1, uv.uv2, uv.uv3, uv.uv4 # XXX - crufty :/
if vertexColors:
col = active_col_layer[i]
col = col.color1, col.color2, col.color3, col.color4
f_verts = f.vertices
pf = ply_faces[i]
for j, vidx in enumerate(f_verts):
v = mesh_verts[vidx]
if smooth:
normal = tuple(v.normal)
normal_key = rvec3d(normal)
if faceUV:
uvcoord = uv[j][0], 1.0 - uv[j][1]
uvcoord_key = rvec2d(uvcoord)
elif vertexUV:
uvcoord = v.uvco[0], 1.0 - v.uvco[1]
uvcoord_key = rvec2d(uvcoord)
if vertexColors:
color = col[j]
color = int(color[0] * 255.0), int(color[1] * 255.0), int(color[2] * 255.0)
key = normal_key, uvcoord_key, color
vdict_local = vdict[vidx]
pf_vidx = vdict_local.get(key) # Will be None initially
if pf_vidx == None: # same as vdict_local.has_key(key)
pf_vidx = vdict_local[key] = vert_count
ply_verts.append((vidx, normal, uvcoord, color))
vert_count += 1
pf.append(pf_vidx)
file.write('ply\n')
file.write('format ascii 1.0\n')
file.write('comment Created by Blender %s - www.blender.org, source file: %s\n' % (bpy.app.version_string, bpy.data.filepath.split('/')[-1].split('\\')[-1]))
file.write('element vertex %d\n' % len(ply_verts))
file.write('property float x\n')
file.write('property float y\n')
file.write('property float z\n')
if EXPORT_NORMALS:
file.write('property float nx\n')
file.write('property float ny\n')
file.write('property float nz\n')
if EXPORT_UV:
file.write('property float s\n')
file.write('property float t\n')
if EXPORT_COLORS:
file.write('property uchar red\n')
file.write('property uchar green\n')
file.write('property uchar blue\n')
file.write('element face %d\n' % len(mesh.faces))
file.write('property list uchar uint vertex_indices\n')
file.write('end_header\n')
for i, v in enumerate(ply_verts):
file.write('%.6f %.6f %.6f ' % tuple(mesh_verts[v[0]].co)) # co
if EXPORT_NORMALS:
file.write('%.6f %.6f %.6f ' % v[1]) # no
if EXPORT_UV:
file.write('%.6f %.6f ' % v[2]) # uv
if EXPORT_COLORS:
file.write('%u %u %u' % v[3]) # col
file.write('\n')
for pf in ply_faces:
if len(pf) == 3:
file.write('3 %d %d %d\n' % tuple(pf))
else:
file.write('4 %d %d %d %d\n' % tuple(pf))
file.close()
print("writing", filename, "done")
if EXPORT_APPLY_MODIFIERS:
bpy.data.meshes.remove(mesh)
# XXX
"""
if is_editmode:
Blender.Window.EditMode(1, '', 0)
"""
from bpy.props import *
class ExportPLY(bpy.types.Operator):
'''Export a single object as a stanford PLY with normals, colours and texture coordinates.'''
bl_idname = "export.ply"
bl_label = "Export PLY"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
filepath = StringProperty(name="File Path", description="Filepath used for exporting the PLY file", maxlen=1024, default="")
check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'})
use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default=True)
use_normals = BoolProperty(name="Normals", description="Export Normals for smooth and hard shaded faces", default=True)
use_uvs = BoolProperty(name="UVs", description="Exort the active UV layer", default=True)
use_colors = BoolProperty(name="Vertex Colors", description="Exort the active vertex color layer", default=True)
@classmethod
def poll(cls, context):
return context.active_object != None
def execute(self, context):
filepath = self.properties.filepath
filepath = bpy.path.ensure_ext(filepath, ".ply")
write(filepath, context.scene, context.active_object,\
EXPORT_APPLY_MODIFIERS=self.properties.use_modifiers,
EXPORT_NORMALS=self.properties.use_normals,
EXPORT_UV=self.properties.use_uvs,
EXPORT_COLORS=self.properties.use_colors,
)
return {'FINISHED'}
def invoke(self, context, event):
import os
if not self.properties.is_property_set("filepath"):
self.properties.filepath = os.path.splitext(bpy.data.filepath)[0] + ".ply"
context.manager.add_fileselect(self)
return {'RUNNING_MODAL'}
def draw(self, context):
layout = self.layout
props = self.properties
row = layout.row()
row.prop(props, "use_modifiers")
row.prop(props, "use_normals")
row = layout.row()
row.prop(props, "use_uvs")
row.prop(props, "use_colors")
def menu_func(self, context):
self.layout.operator(ExportPLY.bl_idname, text="Stanford (.ply)")
def register():
bpy.types.INFO_MT_file_export.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_export.remove(menu_func)
if __name__ == "__main__":
register()

View File

@@ -1,154 +0,0 @@
# ***** 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.
#
# ***** END GPL LICENCE BLOCK *****
# <pep8 compliant>
# mdd importer by Bill L.Nieuwendorp
# conversion to blender 2.5: Ivo Grigull (loolarge)
#
# Warning if the vertex order or vertex count differs from the
# origonal model the mdd was Baked out from their will be Strange
# behavior
#
# vertex animation to ShapeKeys with ipo and gives the frame a value of 1.0
# A modifier to read mdd files would be Ideal but thats for another day :)
#
# Please send any fixes,updates,bugs to Slow67_at_Gmail.com
# Bill Niewuendorp
import bpy
from struct import unpack
def mdd_import(filepath, ob, scene, PREF_START_FRAME=0, PREF_JUMP=1):
print('\n\nimporting mdd "%s"' % filepath)
bpy.ops.object.mode_set(mode='OBJECT')
file = open(filepath, 'rb')
frames, points = unpack(">2i", file.read(8))
time = unpack((">%df" % frames), file.read(frames * 4))
print('\tpoints:%d frames:%d' % (points, frames))
# If target object doesn't have Basis shape key, create it.
try:
num_keys = len(ob.data.shape_keys.keys)
except:
basis = ob.add_shape_key()
basis.name = "Basis"
ob.data.update()
scene.frame_current = PREF_START_FRAME
def UpdateMesh(ob, fr):
# Insert new shape key
new_shapekey = ob.add_shape_key()
new_shapekey.name = ("frame_%.4d" % fr)
new_shapekey_name = new_shapekey.name
ob.active_shape_key_index = len(ob.data.shape_keys.keys)-1
index = len(ob.data.shape_keys.keys)-1
ob.show_shape_key = True
verts = ob.data.shape_keys.keys[len(ob.data.shape_keys.keys)-1].data
for v in verts: # 12 is the size of 3 floats
v.co[:] = unpack('>3f', file.read(12))
#me.update()
ob.show_shape_key = False
# insert keyframes
shape_keys = ob.data.shape_keys
scene.frame_current -= 1
ob.data.shape_keys.keys[index].value = 0.0
shape_keys.keys[len(ob.data.shape_keys.keys)-1].keyframe_insert("value")
scene.frame_current += 1
ob.data.shape_keys.keys[index].value = 1.0
shape_keys.keys[len(ob.data.shape_keys.keys)-1].keyframe_insert("value")
scene.frame_current += 1
ob.data.shape_keys.keys[index].value = 0.0
shape_keys.keys[len(ob.data.shape_keys.keys)-1].keyframe_insert("value")
ob.data.update()
for i in range(frames):
UpdateMesh(ob, i)
from bpy.props import *
class importMDD(bpy.types.Operator):
'''Import MDD vertex keyframe file to shape keys'''
bl_idname = "import_shape.mdd"
bl_label = "Import MDD"
# get first scene to get min and max properties for frames, fps
minframe = 1
maxframe = 300000
minfps = 1
maxfps = 120
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
filepath = StringProperty(name="File Path", description="Filepath used for importing the MDD file", maxlen=1024)
#fps = IntProperty(name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default=25)
frame_start = IntProperty(name="Start Frame", description="Start frame for inserting animation", min=minframe, max=maxframe, default=0)
@classmethod
def poll(cls, context):
ob = context.active_object
return (ob and ob.type == 'MESH')
def execute(self, context):
if not self.properties.filepath:
raise Exception("filename not set")
mdd_import(self.properties.filepath, bpy.context.active_object, context.scene, self.properties.frame_start, 1)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return {'RUNNING_MODAL'}
def menu_func(self, context):
self.layout.operator(importMDD.bl_idname, text="Lightwave Point Cache (.mdd)")
def register():
bpy.types.INFO_MT_file_import.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_import.remove(menu_func)
if __name__ == "__main__":
register()

View File

@@ -19,9 +19,7 @@
# This directory is a Python package. # This directory is a Python package.
# To support reload properly, try to access a package var, if it's there, reload everything # To support reload properly, try to access a package var, if it's there, reload everything
try: if "bpy" in locals():
init_data
reload(model) reload(model)
reload(operators) reload(operators)
reload(client) reload(client)
@@ -32,7 +30,7 @@ try:
reload(balancing) reload(balancing)
reload(ui) reload(ui)
reload(repath) reload(repath)
except: else:
from netrender import model from netrender import model
from netrender import operators from netrender import operators
from netrender import client from netrender import client
@@ -49,7 +47,6 @@ slaves = []
blacklist = [] blacklist = []
init_file = "" init_file = ""
init_data = True
init_address = True init_address = True
def register(): def register():

View File

@@ -23,6 +23,7 @@ from _bpy import ops as ops_module
# op_add = ops_module.add # op_add = ops_module.add
op_dir = ops_module.dir op_dir = ops_module.dir
op_poll = ops_module.poll
op_call = ops_module.call op_call = ops_module.call
op_as_string = ops_module.as_string op_as_string = ops_module.as_string
op_get_rna = ops_module.get_rna op_get_rna = ops_module.get_rna
@@ -120,6 +121,9 @@ class bpy_ops_submodule_op(object):
self.module = module self.module = module
self.func = func self.func = func
def poll(self, context=None):
return op_poll(self.idname_py(), context)
def idname(self): def idname(self):
# submod.foo -> SUBMOD_OT_foo # submod.foo -> SUBMOD_OT_foo
return self.module.upper() + "_OT_" + self.func return self.module.upper() + "_OT_" + self.func

View File

@@ -0,0 +1,102 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from bpy.props import *
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'})
def invoke(self, context, event):
import os
if not self.properties.is_property_set("filepath"):
self.properties.filepath = os.path.splitext(context.blend_data.filepath)[0] + self.filename_ext
context.window_manager.add_fileselect(self)
return {'RUNNING_MODAL'}
class ImportHelper:
filepath = StringProperty(name="File Path", description="Filepath used for importing the file", maxlen= 1024, default= "", subtype='FILE_PATH')
def invoke(self, context, event):
context.window_manager.add_fileselect(self)
return {'RUNNING_MODAL'}
# limited replacement for BPyImage.comprehensiveImageLoad
def load_image(imagepath, dirname):
import os
if os.path.exists(imagepath):
return bpy.data.images.load(imagepath)
variants = [imagepath, os.path.join(dirname, imagepath), os.path.join(dirname, os.path.basename(imagepath))]
for filepath in variants:
for nfilepath in (filepath, bpy.path.resolve_ncase(filepath)):
if os.path.exists(nfilepath):
return bpy.data.images.load(nfilepath)
# TODO comprehensiveImageLoad also searched in bpy.config.textureDir
return None
# 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':
return False, None
if ob.dupli_type != 'NONE':
ob.create_dupli_list(scene)
return True, [(dob.object, dob.matrix) for dob in ob.dupli_list]
else:
return False, [(ob, ob.matrix_world)]
def free_derived_objects(ob):
ob.free_dupli_list()
def unpack_list(list_of_tuples):
flat_list = []
flat_list_extend = flat_list.extend # a tich faster
for t in list_of_tuples:
flat_list_extend(t)
return flat_list
# same as above except that it adds 0 for triangle faces
def unpack_face_list(list_of_tuples):
# allocate the entire list
flat_ls = [0] * (len(list_of_tuples) * 4)
i = 0
for t in list_of_tuples:
if len(t) == 3:
if t[2] == 0:
t = t[1], t[2], t[0]
else: # assuem quad
if t[3] == 0 or t[2] == 0:
t = t[2], t[3], t[0], t[1]
flat_ls[i:i + len(t)] = t
i += 4
return flat_ls

View File

@@ -84,6 +84,8 @@ def draw(layout, context, context_member, use_edit=True):
props.data_path = context_member props.data_path = context_member
del row del row
rna_properties = {prop.identifier for prop in rna_item.bl_rna.properties if prop.is_runtime} if items else None
for key, val in items: for key, val in items:
if key == '_RNA_UI': if key == '_RNA_UI':
@@ -113,7 +115,10 @@ def draw(layout, context, context_member, use_edit=True):
if convert_to_pyobject and not hasattr(val_orig, "len"): if convert_to_pyobject and not hasattr(val_orig, "len"):
row.label(text=val_draw) row.label(text=val_draw)
else: else:
row.prop(rna_item, '["%s"]' % key, text="") if key in rna_properties:
row.prop(rna_item, key, text="")
else:
row.prop(rna_item, '["%s"]' % key, text="")
if use_edit: if use_edit:
row = split.row(align=True) row = split.row(align=True)

View File

@@ -135,7 +135,7 @@ class AddTorus(bpy.types.Operator):
def menu_func(self, context): def menu_func(self, context):
self.layout.operator(AddTorus.bl_idname, text="Torus", icon='MESH_DONUT') self.layout.operator(AddTorus.bl_idname, text="Torus", icon='MESH_TORUS')
def register(): def register():

View File

@@ -681,7 +681,7 @@ import bpy
class UpdateAnimData(bpy.types.Operator): class UpdateAnimData(bpy.types.Operator):
'''''' '''Update data paths from 2.53 to edited data paths of drivers and fcurves'''
bl_idname = "anim.update_data_paths" bl_idname = "anim.update_data_paths"
bl_label = "Update Animation Data" bl_label = "Update Animation Data"
@@ -696,4 +696,4 @@ if __name__ == "__main__":
bpy.ops.anim.update_data_paths() bpy.ops.anim.update_data_paths()
def register(): def register():
pass pass

View File

@@ -44,7 +44,7 @@ def get_console(console_id):
from code import InteractiveConsole from code import InteractiveConsole
consoles = getattr(get_console, "consoles", None) consoles = getattr(get_console, "consoles", None)
hash_next = hash(bpy.context.manager) hash_next = hash(bpy.context.window_manager)
if consoles is None: if consoles is None:
consoles = get_console.consoles = {} consoles = get_console.consoles = {}

View File

@@ -0,0 +1,74 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# To support reload properly, try to access a package var, if it's there, reload everything
if "bpy" in locals():
# only reload if we alredy loaded, highly annoying
import sys
reload(sys.modules.get("io_mesh_ply.export_ply", sys))
import bpy
from bpy.props import *
from io_utils import ImportHelper
class BvhImporter(bpy.types.Operator, ImportHelper):
'''Load a OBJ Motion Capture File'''
bl_idname = "import_anim.bvh"
bl_label = "Import BVH"
filename_ext = ".bvh"
scale = FloatProperty(name="Scale", description="Scale the BVH by this value", min=0.0001, max=1000000.0, soft_min=0.001, soft_max=100.0, default=0.1)
frame_start = IntProperty(name="Start Frame", description="Starting frame for the animation", default=1)
loop = BoolProperty(name="Loop", description="Loop the animation playback", default=False)
rotate_mode = EnumProperty(items=(
('QUATERNION', "Quaternion", "Convert rotations to quaternions"),
('NATIVE', "Euler (Native)", "Use the rotation order defined in the BVH file"),
('XYZ', "Euler (XYZ)", "Convert rotations to euler XYZ"),
('XZY', "Euler (XZY)", "Convert rotations to euler XZY"),
('YXZ', "Euler (YXZ)", "Convert rotations to euler YXZ"),
('YZX', "Euler (YZX)", "Convert rotations to euler YZX"),
('ZXY', "Euler (ZXY)", "Convert rotations to euler ZXY"),
('ZYX', "Euler (ZYX)", "Convert rotations to euler ZYX"),
),
name="Rotation",
description="Rotation conversion.",
default='NATIVE')
def execute(self, context):
import io_anim_bvh.import_bvh
return io_anim_bvh.import_bvh.load(self, context, **self.properties)
def menu_func(self, context):
self.layout.operator(BvhImporter.bl_idname, text="Motion Capture (.bvh)")
def register():
bpy.types.INFO_MT_file_import.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_import.remove(menu_func)
if __name__ == "__main__":
register()

View File

@@ -18,6 +18,8 @@
# <pep8 compliant> # <pep8 compliant>
# Script copyright (C) Campbell Barton
import math import math
from math import radians from math import radians
@@ -349,7 +351,7 @@ def bvh_node_dict2armature(context, bvh_nodes, ROT_MODE='XYZ', IMPORT_START_FRAM
for ob in scn.objects: for ob in scn.objects:
ob.select = False ob.select = False
scn.set_frame(IMPORT_START_FRAME) scn.frame_set(IMPORT_START_FRAME)
arm_data = bpy.data.armatures.new("MyBVH") arm_data = bpy.data.armatures.new("MyBVH")
arm_ob = bpy.data.objects.new("MyBVH", arm_data) arm_ob = bpy.data.objects.new("MyBVH", arm_data)
@@ -553,70 +555,24 @@ def bvh_node_dict2armature(context, bvh_nodes, ROT_MODE='XYZ', IMPORT_START_FRAM
return arm_ob return arm_ob
from bpy.props import * def load(operator, context, filepath="", rotate_mode='NATIVE', scale=1.0, use_cyclic=False, frame_start=1):
import time
t1 = time.time()
print('\tparsing bvh %r...' % filepath, end="")
bvh_nodes = read_bvh(context, filepath,
ROT_MODE=rotate_mode,
GLOBAL_SCALE=scale)
class BvhImporter(bpy.types.Operator): print('%.4f' % (time.time() - t1))
'''Load a OBJ Motion Capture File''' t1 = time.time()
bl_idname = "import_anim.bvh" print('\timporting to blender...', end="")
bl_label = "Import BVH"
filepath = StringProperty(name="File Path", description="Filepath used for importing the OBJ file", maxlen=1024, default="") bvh_node_dict2armature(context, bvh_nodes,
scale = FloatProperty(name="Scale", description="Scale the BVH by this value", min=0.0001, max=1000000.0, soft_min=0.001, soft_max=100.0, default=0.1) ROT_MODE=rotate_mode,
frame_start = IntProperty(name="Start Frame", description="Starting frame for the animation", default=1) IMPORT_START_FRAME=frame_start,
loop = BoolProperty(name="Loop", description="Loop the animation playback", default=False) IMPORT_LOOP=use_cyclic)
rotate_mode = EnumProperty(items=(
('QUATERNION', "Quaternion", "Convert rotations to quaternions"),
('NATIVE', "Euler (Native)", "Use the rotation order defined in the BVH file"),
('XYZ', "Euler (XYZ)", "Convert rotations to euler XYZ"),
('XZY', "Euler (XZY)", "Convert rotations to euler XZY"),
('YXZ', "Euler (YXZ)", "Convert rotations to euler YXZ"),
('YZX', "Euler (YZX)", "Convert rotations to euler YZX"),
('ZXY', "Euler (ZXY)", "Convert rotations to euler ZXY"),
('ZYX', "Euler (ZYX)", "Convert rotations to euler ZYX"),
),
name="Rotation",
description="Rotation conversion.",
default='NATIVE')
def execute(self, context): print('Done in %.4f\n' % (time.time() - t1))
# print("Selected: " + context.active_object.name)
import time return {'FINISHED'}
t1 = time.time()
print('\tparsing bvh...', end="")
bvh_nodes = read_bvh(context, self.properties.filepath,
ROT_MODE=self.properties.rotate_mode,
GLOBAL_SCALE=self.properties.scale)
print('%.4f' % (time.time() - t1))
t1 = time.time()
print('\timporting to blender...', end="")
bvh_node_dict2armature(context, bvh_nodes,
ROT_MODE=self.properties.rotate_mode,
IMPORT_START_FRAME=self.properties.frame_start,
IMPORT_LOOP=self.properties.loop)
print('Done in %.4f\n' % (time.time() - t1))
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return {'RUNNING_MODAL'}
def menu_func(self, context):
self.layout.operator(BvhImporter.bl_idname, text="Motion Capture (.bvh)")
def register():
bpy.types.INFO_MT_file_import.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_import.remove(menu_func)
if __name__ == "__main__":
register()

View File

@@ -0,0 +1,76 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# To support reload properly, try to access a package var, if it's there, reload everything
if "bpy" in locals():
import sys
reload(sys.modules.get("io_mesh_ply.export_ply", sys))
import bpy
from bpy.props import *
from io_utils import ExportHelper
class ExportPLY(bpy.types.Operator, ExportHelper):
'''Export a single object as a stanford PLY with normals, colours and texture coordinates.'''
bl_idname = "export.ply"
bl_label = "Export PLY"
filename_ext = ".ply"
use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default=True)
use_normals = BoolProperty(name="Normals", description="Export Normals for smooth and hard shaded faces", default=True)
use_uv_coords = BoolProperty(name="UVs", description="Exort the active UV layer", default=True)
use_colors = BoolProperty(name="Vertex Colors", description="Exort the active vertex color layer", default=True)
@classmethod
def poll(cls, context):
return context.active_object != None
def execute(self, context):
filepath = self.properties.filepath
filepath = bpy.path.ensure_ext(filepath, self.filename_ext)
import io_mesh_ply.export_ply
return io_mesh_ply.export_ply.save(self, context, **self.properties)
def draw(self, context):
layout = self.layout
props = self.properties
row = layout.row()
row.prop(props, "use_modifiers")
row.prop(props, "use_normals")
row = layout.row()
row.prop(props, "use_uv_coords")
row.prop(props, "use_colors")
def menu_func(self, context):
self.layout.operator(ExportPLY.bl_idname, text="Stanford (.ply)")
def register():
bpy.types.INFO_MT_file_export.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_export.remove(menu_func)
if __name__ == "__main__":
register()

View File

@@ -0,0 +1,206 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# Copyright (C) 2004, 2005: Bruce Merry, bmerry@cs.uct.ac.za
# Contributors: Bruce Merry, Campbell Barton
"""
This script exports Stanford PLY files from Blender. It supports normals,
colours, and texture coordinates per face or per vertex.
Only one mesh can be exported at a time.
"""
import bpy
import os
def save(operator, context, filepath="", use_modifiers=True, use_normals=True, use_uv_coords=True, use_colors=True):
def rvec3d(v):
return round(v[0], 6), round(v[1], 6), round(v[2], 6)
def rvec2d(v):
return round(v[0], 6), round(v[1], 6)
scene = context.scene
obj = context.object
if not obj:
raise Exception("Error, Select 1 active object")
file = open(filepath, 'w')
if scene.objects.active:
bpy.ops.object.mode_set(mode='OBJECT')
if use_modifiers:
mesh = obj.create_mesh(scene, True, 'PREVIEW')
else:
mesh = obj.data
if not mesh:
raise Exception("Error, could not get mesh data from active object")
# mesh.transform(obj.matrix_world) # XXX
faceUV = (len(mesh.uv_textures) > 0)
vertexUV = (len(mesh.sticky) > 0)
vertexColors = len(mesh.vertex_colors) > 0
if (not faceUV) and (not vertexUV):
use_uv_coords = False
if not vertexColors:
use_colors = False
if not use_uv_coords:
faceUV = vertexUV = False
if not use_colors:
vertexColors = False
if faceUV:
active_uv_layer = mesh.uv_textures.active
if not active_uv_layer:
use_uv_coords = False
faceUV = None
else:
active_uv_layer = active_uv_layer.data
if vertexColors:
active_col_layer = mesh.vertex_colors.active
if not active_col_layer:
use_colors = False
vertexColors = None
else:
active_col_layer = active_col_layer.data
# incase
color = uvcoord = uvcoord_key = normal = normal_key = None
mesh_verts = mesh.vertices # save a lookup
ply_verts = [] # list of dictionaries
# vdict = {} # (index, normal, uv) -> new index
vdict = [{} for i in range(len(mesh_verts))]
ply_faces = [[] for f in range(len(mesh.faces))]
vert_count = 0
for i, f in enumerate(mesh.faces):
smooth = f.use_smooth
if not smooth:
normal = tuple(f.normal)
normal_key = rvec3d(normal)
if faceUV:
uv = active_uv_layer[i]
uv = uv.uv1, uv.uv2, uv.uv3, uv.uv4 # XXX - crufty :/
if vertexColors:
col = active_col_layer[i]
col = col.color1, col.color2, col.color3, col.color4
f_verts = f.vertices
pf = ply_faces[i]
for j, vidx in enumerate(f_verts):
v = mesh_verts[vidx]
if smooth:
normal = tuple(v.normal)
normal_key = rvec3d(normal)
if faceUV:
uvcoord = uv[j][0], 1.0 - uv[j][1]
uvcoord_key = rvec2d(uvcoord)
elif vertexUV:
uvcoord = v.uvco[0], 1.0 - v.uvco[1]
uvcoord_key = rvec2d(uvcoord)
if vertexColors:
color = col[j]
color = int(color[0] * 255.0), int(color[1] * 255.0), int(color[2] * 255.0)
key = normal_key, uvcoord_key, color
vdict_local = vdict[vidx]
pf_vidx = vdict_local.get(key) # Will be None initially
if pf_vidx == None: # same as vdict_local.has_key(key)
pf_vidx = vdict_local[key] = vert_count
ply_verts.append((vidx, normal, uvcoord, color))
vert_count += 1
pf.append(pf_vidx)
file.write('ply\n')
file.write('format ascii 1.0\n')
file.write('comment Created by Blender %s - www.blender.org, source file: %r\n' % (bpy.app.version_string, os.path.basename(bpy.data.filepath)))
file.write('element vertex %d\n' % len(ply_verts))
file.write('property float x\n')
file.write('property float y\n')
file.write('property float z\n')
if use_normals:
file.write('property float nx\n')
file.write('property float ny\n')
file.write('property float nz\n')
if use_uv_coords:
file.write('property float s\n')
file.write('property float t\n')
if use_colors:
file.write('property uchar red\n')
file.write('property uchar green\n')
file.write('property uchar blue\n')
file.write('element face %d\n' % len(mesh.faces))
file.write('property list uchar uint vertex_indices\n')
file.write('end_header\n')
for i, v in enumerate(ply_verts):
file.write('%.6f %.6f %.6f ' % tuple(mesh_verts[v[0]].co)) # co
if use_normals:
file.write('%.6f %.6f %.6f ' % v[1]) # no
if use_uv_coords:
file.write('%.6f %.6f ' % v[2]) # uv
if use_colors:
file.write('%u %u %u' % v[3]) # col
file.write('\n')
for pf in ply_faces:
if len(pf) == 3:
file.write('3 %d %d %d\n' % tuple(pf))
else:
file.write('4 %d %d %d %d\n' % tuple(pf))
file.close()
print("writing %r done" % filepath)
if use_modifiers:
bpy.data.meshes.remove(mesh)
# XXX
"""
if is_editmode:
Blender.Window.EditMode(1, '', 0)
"""
return {'FINISHED'}

View File

@@ -0,0 +1,86 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# To support reload properly, try to access a package var, if it's there, reload everything
if "bpy" in locals():
import sys
reload(sys.modules.get("io_scene_3ds.import_3ds", sys))
reload(sys.modules.get("io_scene_3ds.export_3ds", sys))
import bpy
from bpy.props import *
from io_utils import ImportHelper, ExportHelper
class Import3DS(bpy.types.Operator, ImportHelper):
'''Import from 3DS file format (.3ds)'''
bl_idname = "import_scene.autodesk_3ds"
bl_label = 'Import 3DS'
filename_ext = ".3ds"
constrain_size = FloatProperty(name="Size Constraint", description="Scale the model by 10 until it reacehs the size constraint. Zero Disables.", min=0.0, max=1000.0, soft_min=0.0, soft_max=1000.0, default=10.0)
use_image_search = BoolProperty(name="Image Search", description="Search subdirectories for any assosiated images (Warning, may be slow)", default=True)
use_apply_transform = BoolProperty(name="Apply Transform", description="Workaround for object transformations importing incorrectly", default=False)
def execute(self, context):
import io_scene_3ds.import_3ds
return io_scene_3ds.import_3ds.load(self, context, **self.properties)
class Export3DS(bpy.types.Operator, ExportHelper):
'''Export to 3DS file format (.3ds)'''
bl_idname = "export_scene.autodesk_3ds"
bl_label = 'Export 3DS'
filename_ext = ".3ds"
def execute(self, context):
import io_scene_3ds.export_3ds
return io_scene_3ds.export_3ds.save(self, context, **self.properties)
# Add to a menu
def menu_func_export(self, context):
self.layout.operator(Export3DS.bl_idname, text="3D Studio (.3ds)")
def menu_func_import(self, context):
self.layout.operator(Import3DS.bl_idname, text="3D Studio (.3ds)")
def register():
bpy.types.INFO_MT_file_import.append(menu_func_import)
bpy.types.INFO_MT_file_export.append(menu_func_export)
def unregister():
bpy.types.INFO_MT_file_import.remove(menu_func_import)
bpy.types.INFO_MT_file_export.remove(menu_func_export)
if __name__ == "__main__":
register()
# NOTES:
# why add 1 extra vertex? and remove it when done? - "Answer - eekadoodle - would need to re-order UV's without this since face order isnt always what we give blender, BMesh will solve :D"
# disabled scaling to size, this requires exposing bb (easy) and understanding how it works (needs some time)
if __name__ == "__main__":
register()

View File

@@ -1,4 +1,3 @@
# coding: utf-8
# ##### BEGIN GPL LICENSE BLOCK ##### # ##### BEGIN GPL LICENSE BLOCK #####
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
@@ -19,74 +18,74 @@
# <pep8 compliant> # <pep8 compliant>
__author__ = ["Campbell Barton", "Bob Holcomb", "Richard Lärkäng", "Damien McGinnes", "Mark Stijnman"] # Script copyright (C) Bob Holcomb
__url__ = ("blenderartists.org", "www.blender.org", "www.gametutorials.com", "lib3ds.sourceforge.net/") # Contributors: Campbell Barton, Bob Holcomb, Richard Lärkäng, Damien McGinnes, Mark Stijnman
__version__ = "0.90a"
__bpydoc__ = """\
3ds Exporter
This script Exports a 3ds file.
"""
Exporting is based on 3ds loader from www.gametutorials.com(Thanks DigiBen) and using information Exporting is based on 3ds loader from www.gametutorials.com(Thanks DigiBen) and using information
from the lib3ds project (http://lib3ds.sourceforge.net/) sourcecode. from the lib3ds project (http://lib3ds.sourceforge.net/) sourcecode.
""" """
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Bob Holcomb
#
# 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.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
###################################################### ######################################################
# Importing modules # Data Structures
###################################################### ######################################################
#Some of the chunks that we will export
#----- Primary Chunk, at the beginning of each file
PRIMARY= 0x4D4D
#------ Main Chunks
OBJECTINFO = 0x3D3D #This gives the version of the mesh and is found right before the material and object information
VERSION = 0x0002 #This gives the version of the .3ds file
KFDATA = 0xB000 #This is the header for all of the key frame info
#------ sub defines of OBJECTINFO
MATERIAL=45055 #0xAFFF // This stored the texture info
OBJECT=16384 #0x4000 // This stores the faces, vertices, etc...
#>------ sub defines of MATERIAL
MATNAME = 0xA000 # This holds the material name
MATAMBIENT = 0xA010 # Ambient color of the object/material
MATDIFFUSE = 0xA020 # This holds the color of the object/material
MATSPECULAR = 0xA030 # SPecular color of the object/material
MATSHINESS = 0xA040 # ??
MATMAP = 0xA200 # This is a header for a new material
MATMAPFILE = 0xA300 # This holds the file name of the texture
RGB1= 0x0011
RGB2= 0x0012
#>------ sub defines of OBJECT
OBJECT_MESH = 0x4100 # This lets us know that we are reading a new object
OBJECT_LIGHT = 0x4600 # This lets un know we are reading a light object
OBJECT_CAMERA= 0x4700 # This lets un know we are reading a camera object
#>------ sub defines of CAMERA
OBJECT_CAM_RANGES= 0x4720 # The camera range values
#>------ sub defines of OBJECT_MESH
OBJECT_VERTICES = 0x4110 # The objects vertices
OBJECT_FACES = 0x4120 # The objects faces
OBJECT_MATERIAL = 0x4130 # This is found if the object has a material, either texture map or color
OBJECT_UV = 0x4140 # The UV texture coordinates
OBJECT_TRANS_MATRIX = 0x4160 # The Object Matrix
#>------ sub defines of KFDATA
KFDATA_KFHDR = 0xB00A
KFDATA_KFSEG = 0xB008
KFDATA_KFCURTIME = 0xB009
KFDATA_OBJECT_NODE_TAG = 0xB002
#>------ sub defines of OBJECT_NODE_TAG
OBJECT_NODE_ID = 0xB030
OBJECT_NODE_HDR = 0xB010
OBJECT_PIVOT = 0xB013
OBJECT_INSTANCE_NAME = 0xB011
POS_TRACK_TAG = 0xB020
ROT_TRACK_TAG = 0xB021
SCL_TRACK_TAG = 0xB022
import struct import struct
import os
import time
import bpy
# import Blender
# from BPyMesh import getMeshFromObject
# from BPyObject import getDerivedObjects
# try:
# import struct
# except:
# struct = None
# also used by X3D exporter
# 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':
return False, None
if ob.dupli_type != 'NONE':
ob.create_dupli_list(scene)
return True, [(dob.object, dob.matrix) for dob in ob.dupli_list]
else:
return False, [(ob, ob.matrix_world)]
# also used by X3D exporter
def free_derived_objects(ob):
ob.free_dupli_list()
# So 3ds max can open files, limit names to 12 in length # So 3ds max can open files, limit names to 12 in length
# this is verry annoying for filenames! # this is verry annoying for filenames!
@@ -94,13 +93,10 @@ name_unique = []
name_mapping = {} name_mapping = {}
def sane_name(name): def sane_name(name):
name_fixed = name_mapping.get(name) name_fixed = name_mapping.get(name)
if name_fixed != None: if name_fixed is not None:
return name_fixed return name_fixed
if len(name) > 12: new_name = name[:12]
new_name = name[:12]
else:
new_name = name
i = 0 i = 0
@@ -112,65 +108,6 @@ def sane_name(name):
name_mapping[name] = new_name name_mapping[name] = new_name
return new_name return new_name
######################################################
# Data Structures
######################################################
#Some of the chunks that we will export
#----- Primary Chunk, at the beginning of each file
PRIMARY= int("0x4D4D",16)
#------ Main Chunks
OBJECTINFO = int("0x3D3D",16); #This gives the version of the mesh and is found right before the material and object information
VERSION = int("0x0002",16); #This gives the version of the .3ds file
KFDATA = int("0xB000",16); #This is the header for all of the key frame info
#------ sub defines of OBJECTINFO
MATERIAL=45055 #0xAFFF // This stored the texture info
OBJECT=16384 #0x4000 // This stores the faces, vertices, etc...
#>------ sub defines of MATERIAL
MATNAME = int("0xA000",16); # This holds the material name
MATAMBIENT = int("0xA010",16); # Ambient color of the object/material
MATDIFFUSE = int("0xA020",16); # This holds the color of the object/material
MATSPECULAR = int("0xA030",16); # SPecular color of the object/material
MATSHINESS = int("0xA040",16); # ??
MATMAP = int("0xA200",16); # This is a header for a new material
MATMAPFILE = int("0xA300",16); # This holds the file name of the texture
RGB1= int("0x0011",16)
RGB2= int("0x0012",16)
#>------ sub defines of OBJECT
OBJECT_MESH = int("0x4100",16); # This lets us know that we are reading a new object
OBJECT_LIGHT = int("0x4600",16); # This lets un know we are reading a light object
OBJECT_CAMERA= int("0x4700",16); # This lets un know we are reading a camera object
#>------ sub defines of CAMERA
OBJECT_CAM_RANGES= int("0x4720",16); # The camera range values
#>------ sub defines of OBJECT_MESH
OBJECT_VERTICES = int("0x4110",16); # The objects vertices
OBJECT_FACES = int("0x4120",16); # The objects faces
OBJECT_MATERIAL = int("0x4130",16); # This is found if the object has a material, either texture map or color
OBJECT_UV = int("0x4140",16); # The UV texture coordinates
OBJECT_TRANS_MATRIX = int("0x4160",16); # The Object Matrix
#>------ sub defines of KFDATA
KFDATA_KFHDR = int("0xB00A",16);
KFDATA_KFSEG = int("0xB008",16);
KFDATA_KFCURTIME = int("0xB009",16);
KFDATA_OBJECT_NODE_TAG = int("0xB002",16);
#>------ sub defines of OBJECT_NODE_TAG
OBJECT_NODE_ID = int("0xB030",16);
OBJECT_NODE_HDR = int("0xB010",16);
OBJECT_PIVOT = int("0xB013",16);
OBJECT_INSTANCE_NAME = int("0xB011",16);
POS_TRACK_TAG = int("0xB020",16);
ROT_TRACK_TAG = int("0xB021",16);
SCL_TRACK_TAG = int("0xB022",16);
def uv_key(uv): def uv_key(uv):
return round(uv[0], 6), round(uv[1], 6) return round(uv[0], 6), round(uv[1], 6)
# return round(uv.x, 6), round(uv.y, 6) # return round(uv.x, 6), round(uv.y, 6)
@@ -379,7 +316,7 @@ class _3ds_named_variable(object):
if (self.value!=None): if (self.value!=None):
spaces="" spaces=""
for i in range(indent): for i in range(indent):
spaces+=" "; spaces += " "
if (self.name!=""): if (self.name!=""):
print(spaces, self.name, " = ", self.value) print(spaces, self.name, " = ", self.value)
else: else:
@@ -444,7 +381,7 @@ class _3ds_chunk(object):
Uses the dump function of the named variables and the subchunks to do the actual work.''' Uses the dump function of the named variables and the subchunks to do the actual work.'''
spaces="" spaces=""
for i in range(indent): for i in range(indent):
spaces+=" "; spaces += " "
print(spaces, "ID=", hex(self.ID.value), "size=", self.get_size()) print(spaces, "ID=", hex(self.ID.value), "size=", self.get_size())
for variable in self.variables: for variable in self.variables:
variable.dump(indent+1) variable.dump(indent+1)
@@ -479,11 +416,11 @@ def make_material_subchunk(id, color):
Used for color subchunks, such as diffuse color or ambient color subchunks.''' Used for color subchunks, such as diffuse color or ambient color subchunks.'''
mat_sub = _3ds_chunk(id) mat_sub = _3ds_chunk(id)
col1 = _3ds_chunk(RGB1) col1 = _3ds_chunk(RGB1)
col1.add_variable("color1", _3ds_rgb_color(color)); col1.add_variable("color1", _3ds_rgb_color(color))
mat_sub.add_subchunk(col1) mat_sub.add_subchunk(col1)
# optional: # optional:
# col2 = _3ds_chunk(RGB1) # col2 = _3ds_chunk(RGB1)
# col2.add_variable("color2", _3ds_rgb_color(color)); # col2.add_variable("color2", _3ds_rgb_color(color))
# mat_sub.add_subchunk(col2) # mat_sub.add_subchunk(col2)
return mat_sub return mat_sub
@@ -921,27 +858,21 @@ def make_kf_obj_node(obj, name_to_id):
return kf_obj_node return kf_obj_node
""" """
# import BPyMessages
def write(filename, context): def save(operator, context, filepath=""):
import bpy
import time
from io_utils import create_derived_objects, free_derived_objects
'''Save the Blender scene to a 3ds file.''' '''Save the Blender scene to a 3ds file.'''
# Time the export # Time the export
if not filename.lower().endswith('.3ds'):
filename += '.3ds'
# XXX
# if not BPyMessages.Warning_SaveOver(filename):
# return
# XXX
time1 = time.clock() time1 = time.clock()
# time1= Blender.sys.time()
# Blender.Window.WaitCursor(1) # Blender.Window.WaitCursor(1)
sce = context.scene sce = context.scene
# sce= bpy.data.scenes.active
if context.object: if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='OBJECT')
# Initialize the main chunk (primary): # Initialize the main chunk (primary):
@@ -1090,7 +1021,7 @@ def write(filename, context):
# Check the size: # Check the size:
primary.get_size() primary.get_size()
# Open the file for writing: # Open the file for writing:
file = open( filename, 'wb' ) file = open(filepath, 'wb')
# Recursively write the chunks to file: # Recursively write the chunks to file:
primary.write(file) primary.write(file)
@@ -1098,56 +1029,15 @@ def write(filename, context):
# Close the file: # Close the file:
file.close() file.close()
# Clear name mapping vars, could make locals too
name_unique[:] = []
name_mapping.clear()
# Debugging only: report the exporting time: # Debugging only: report the exporting time:
# Blender.Window.WaitCursor(0) # Blender.Window.WaitCursor(0)
print("3ds export time: %.2f" % (time.clock() - time1)) print("3ds export time: %.2f" % (time.clock() - time1))
# print("3ds export time: %.2f" % (Blender.sys.time() - time1))
# Debugging only: dump the chunk hierarchy: # Debugging only: dump the chunk hierarchy:
#primary.dump() #primary.dump()
return {'FINISHED'}
# # write('/test_b.3ds')
from bpy.props import *
class Export3DS(bpy.types.Operator):
'''Export to 3DS file format (.3ds)'''
bl_idname = "export.autodesk_3ds"
bl_label = 'Export 3DS'
filepath = StringProperty(name="File Path", description="Filepath used for exporting the 3DS file", maxlen= 1024, default= "")
check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'})
@classmethod
def poll(cls, context): # Poll isnt working yet
return context.active_object != None
def execute(self, context):
filepath = self.properties.filepath
filepath = bpy.path.ensure_ext(filepath, ".3ds")
write(filepath, context)
return {'FINISHED'}
def invoke(self, context, event):
import os
if not self.properties.is_property_set("filepath"):
self.properties.filepath = os.path.splitext(bpy.data.filepath)[0] + ".3ds"
context.manager.add_fileselect(self)
return {'RUNNING_MODAL'}
# Add to a menu
def menu_func(self, context):
self.layout.operator(Export3DS.bl_idname, text="3D Studio (.3ds)")
def register():
bpy.types.INFO_MT_file_export.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_export.remove(menu_func)
if __name__ == "__main__":
register()

View File

@@ -18,130 +18,14 @@
# <pep8 compliant> # <pep8 compliant>
__author__= ['Bob Holcomb', 'Richard L?rk?ng', 'Damien McGinnes', 'Campbell Barton', 'Mario Lapin']
__url__ = ("blenderartists.org", "www.blender.org", "www.gametutorials.com", "lib3ds.sourceforge.net/")
__version__= '0.996'
__bpydoc__= '''\
3ds Importer
This script imports a 3ds file and the materials into Blender for editing.
Loader is based on 3ds loader from www.gametutorials.com (Thanks DigiBen).
0.996 by Mario Lapin (mario.lapin@gmail.com) 13/04/200 <br>
- Implemented workaround to correct association between name, geometry and materials of
imported meshes.
Without this patch, version 0.995 of this importer would associate to each mesh object the
geometry and the materials of the previously parsed mesh object. By so, the name of the
first mesh object would be thrown away, and the name of the last mesh object would be
automatically merged with a '.001' at the end. No object would desappear, however object's
names and materials would be completely jumbled.
0.995 by Campbell Barton<br>
- workaround for buggy mesh vert delete
- minor tweaks
0.99 by Bob Holcomb<br>
- added support for floating point color values that previously broke on import.
0.98 by Campbell Barton<br>
- import faces and verts to lists instead of a mesh, convert to a mesh later
- use new index mapping feature of mesh to re-map faces that were not added.
0.97 by Campbell Barton<br>
- Strip material names of spaces
- Added import as instance to import the 3ds into its own
scene and add a group instance to the current scene
- New option to scale down imported objects so they are within a limited bounding area.
0.96 by Campbell Barton<br>
- Added workaround for bug in setting UV's for Zero vert index UV faces.
- Removed unique name function, let blender make the names unique.
0.95 by Campbell Barton<br>
- Removed workarounds for Blender 2.41
- Mesh objects split by material- many 3ds objects used more then 16 per mesh.
- Removed a lot of unneeded variable creation.
0.94 by Campbell Barton<br>
- Face import tested to be about overall 16x speedup over 0.93.
- Material importing speedup.
- Tested with more models.
- Support some corrupt models.
0.93 by Campbell Barton<br>
- Tested with 400 3ds files from turbosquid and samples.
- Tactfully ignore faces that used the same verts twice.
- Rollback to 0.83 sloppy un-reorganized code, this broke UV coord loading.
- Converted from NMesh to Mesh.
- Faster and cleaner new names.
- Use external comprehensive image loader.
- Re intergrated 0.92 and 0.9 changes
- Fixes for 2.41 compat.
- Non textured faces do not use a texture flag.
0.92<br>
- Added support for diffuse, alpha, spec, bump maps in a single material
0.9<br>
- Reorganized code into object/material block functions<br>
- Use of Matrix() to copy matrix data<br>
- added support for material transparency<br>
0.83 2005-08-07: Campell Barton
- Aggressive image finding and case insensitivy for posisx systems.
0.82a 2005-07-22
- image texture loading (both for face uv and renderer)
0.82 - image texture loading (for face uv)
0.81a (fork- not 0.9) Campbell Barton 2005-06-08
- Simplified import code
- Never overwrite data
- Faster list handling
- Leaves import selected
0.81 Damien McGinnes 2005-01-09
- handle missing images better
0.8 Damien McGinnes 2005-01-08
- copies sticky UV coords to face ones
- handles images better
- Recommend that you run 'RemoveDoubles' on each imported mesh after using this script
'''
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Bob Holcomb # Script copyright (C) Bob Holcomb
# # Contributors: Bob Holcomb, Richard L?rk?ng, Damien McGinnes, Campbell Barton, Mario Lapin
# 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.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
# Importing modules
import os import os
import time import time
import struct import struct
from import_scene_obj import load_image from io_utils import load_image
import bpy import bpy
import mathutils import mathutils
@@ -158,9 +42,9 @@ BOUNDS_3DS = []
PRIMARY = int('0x4D4D',16) PRIMARY = int('0x4D4D',16)
#------ Main Chunks #------ Main Chunks
OBJECTINFO = int('0x3D3D',16); #This gives the version of the mesh and is found right before the material and object information OBJECTINFO = 0x3D3D #This gives the version of the mesh and is found right before the material and object information
VERSION = int('0x0002',16); #This gives the version of the .3ds file VERSION = 0x0002 #This gives the version of the .3ds file
EDITKEYFRAME= int('0xB000',16); #This is the header for all of the key frame info EDITKEYFRAME= 0xB000 #This is the header for all of the key frame info
#------ sub defines of OBJECTINFO #------ sub defines of OBJECTINFO
MATERIAL = 45055 #0xAFFF // This stored the texture info MATERIAL = 45055 #0xAFFF // This stored the texture info
@@ -168,62 +52,62 @@ OBJECT = 16384 #0x4000 // This stores the faces, vertices, etc...
#>------ sub defines of MATERIAL #>------ sub defines of MATERIAL
#------ sub defines of MATERIAL_BLOCK #------ sub defines of MATERIAL_BLOCK
MAT_NAME = int('0xA000',16) # This holds the material name MAT_NAME = 0xA000 # This holds the material name
MAT_AMBIENT = int('0xA010',16) # Ambient color of the object/material MAT_AMBIENT = 0xA010 # Ambient color of the object/material
MAT_DIFFUSE = int('0xA020',16) # This holds the color of the object/material MAT_DIFFUSE = 0xA020 # This holds the color of the object/material
MAT_SPECULAR = int('0xA030',16) # SPecular color of the object/material MAT_SPECULAR = 0xA030 # SPecular color of the object/material
MAT_SHINESS = int('0xA040',16) # ?? MAT_SHINESS = 0xA040 # ??
MAT_TRANSPARENCY= int('0xA050',16) # Transparency value of material MAT_TRANSPARENCY= 0xA050 # Transparency value of material
MAT_SELF_ILLUM = int('0xA080',16) # Self Illumination value of material MAT_SELF_ILLUM = 0xA080 # Self Illumination value of material
MAT_WIRE = int('0xA085',16) # Only render's wireframe MAT_WIRE = 0xA085 # Only render's wireframe
MAT_TEXTURE_MAP = int('0xA200',16) # This is a header for a new texture map MAT_TEXTURE_MAP = 0xA200 # This is a header for a new texture map
MAT_SPECULAR_MAP= int('0xA204',16) # This is a header for a new specular map MAT_SPECULAR_MAP= 0xA204 # This is a header for a new specular map
MAT_OPACITY_MAP = int('0xA210',16) # This is a header for a new opacity map MAT_OPACITY_MAP = 0xA210 # This is a header for a new opacity map
MAT_REFLECTION_MAP= int('0xA220',16) # This is a header for a new reflection map MAT_REFLECTION_MAP= 0xA220 # This is a header for a new reflection map
MAT_BUMP_MAP = int('0xA230',16) # This is a header for a new bump map MAT_BUMP_MAP = 0xA230 # This is a header for a new bump map
MAT_MAP_FILENAME = int('0xA300',16) # This holds the file name of the texture MAT_MAP_FILEPATH = 0xA300 # This holds the file name of the texture
MAT_FLOAT_COLOR = int ('0x0010', 16) #color defined as 3 floats MAT_FLOAT_COLOR = 0x0010 #color defined as 3 floats
MAT_24BIT_COLOR = int ('0x0011', 16) #color defined as 3 bytes MAT_24BIT_COLOR = 0x0011 #color defined as 3 bytes
#>------ sub defines of OBJECT #>------ sub defines of OBJECT
OBJECT_MESH = int('0x4100',16); # This lets us know that we are reading a new object OBJECT_MESH = 0x4100 # This lets us know that we are reading a new object
OBJECT_LAMP = int('0x4600',16); # This lets un know we are reading a light object OBJECT_LAMP = 0x4600 # This lets un know we are reading a light object
OBJECT_LAMP_SPOT = int('0x4610',16); # The light is a spotloght. OBJECT_LAMP_SPOT = 0x4610 # The light is a spotloght.
OBJECT_LAMP_OFF = int('0x4620',16); # The light off. OBJECT_LAMP_OFF = 0x4620 # The light off.
OBJECT_LAMP_ATTENUATE = int('0x4625',16); OBJECT_LAMP_ATTENUATE = 0x4625
OBJECT_LAMP_RAYSHADE = int('0x4627',16); OBJECT_LAMP_RAYSHADE = 0x4627
OBJECT_LAMP_SHADOWED = int('0x4630',16); OBJECT_LAMP_SHADOWED = 0x4630
OBJECT_LAMP_LOCAL_SHADOW = int('0x4640',16); OBJECT_LAMP_LOCAL_SHADOW = 0x4640
OBJECT_LAMP_LOCAL_SHADOW2 = int('0x4641',16); OBJECT_LAMP_LOCAL_SHADOW2 = 0x4641
OBJECT_LAMP_SEE_CONE = int('0x4650',16); OBJECT_LAMP_SEE_CONE = 0x4650
OBJECT_LAMP_SPOT_RECTANGULAR = int('0x4651',16); OBJECT_LAMP_SPOT_RECTANGULAR = 0x4651
OBJECT_LAMP_SPOT_OVERSHOOT = int('0x4652',16); OBJECT_LAMP_SPOT_OVERSHOOT = 0x4652
OBJECT_LAMP_SPOT_PROJECTOR = int('0x4653',16); OBJECT_LAMP_SPOT_PROJECTOR = 0x4653
OBJECT_LAMP_EXCLUDE = int('0x4654',16); OBJECT_LAMP_EXCLUDE = 0x4654
OBJECT_LAMP_RANGE = int('0x4655',16); OBJECT_LAMP_RANGE = 0x4655
OBJECT_LAMP_ROLL = int('0x4656',16); OBJECT_LAMP_ROLL = 0x4656
OBJECT_LAMP_SPOT_ASPECT = int('0x4657',16); OBJECT_LAMP_SPOT_ASPECT = 0x4657
OBJECT_LAMP_RAY_BIAS = int('0x4658',16); OBJECT_LAMP_RAY_BIAS = 0x4658
OBJECT_LAMP_INNER_RANGE = int('0x4659',16); OBJECT_LAMP_INNER_RANGE = 0x4659
OBJECT_LAMP_OUTER_RANGE = int('0x465A',16); OBJECT_LAMP_OUTER_RANGE = 0x465A
OBJECT_LAMP_MULTIPLIER = int('0x465B',16); OBJECT_LAMP_MULTIPLIER = 0x465B
OBJECT_LAMP_AMBIENT_LIGHT = int('0x4680',16); OBJECT_LAMP_AMBIENT_LIGHT = 0x4680
OBJECT_CAMERA= int('0x4700',16); # This lets un know we are reading a camera object OBJECT_CAMERA= 0x4700 # This lets un know we are reading a camera object
#>------ sub defines of CAMERA #>------ sub defines of CAMERA
OBJECT_CAM_RANGES= int('0x4720',16); # The camera range values OBJECT_CAM_RANGES= 0x4720 # The camera range values
#>------ sub defines of OBJECT_MESH #>------ sub defines of OBJECT_MESH
OBJECT_VERTICES = int('0x4110',16); # The objects vertices OBJECT_VERTICES = 0x4110 # The objects vertices
OBJECT_FACES = int('0x4120',16); # The objects faces OBJECT_FACES = 0x4120 # The objects faces
OBJECT_MATERIAL = int('0x4130',16); # This is found if the object has a material, either texture map or color OBJECT_MATERIAL = 0x4130 # This is found if the object has a material, either texture map or color
OBJECT_UV = int('0x4140',16); # The UV texture coordinates OBJECT_UV = 0x4140 # The UV texture coordinates
OBJECT_TRANS_MATRIX = int('0x4160',16); # The Object Matrix OBJECT_TRANS_MATRIX = 0x4160 # The Object Matrix
global scn global scn
scn = None scn = None
@@ -299,7 +183,19 @@ def add_texture_to_material(image, texture, material, mapto):
if image: if image:
texture.image = image texture.image = image
material.add_texture(texture, "UV", mapto) mtex = material.texture_slots.add()
mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use_map_color_diffuse = False
if mapto == 'COLOR':
mtex.use_map_color_diffuse = True
elif mapto == 'SPECULARITY':
mtex.use_map_specular = True
elif mapto == 'ALPHA':
mtex.use_map_alpha = True
elif mapto == 'NORMAL':
mtex.use_map_normal = True
def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH): def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
@@ -356,7 +252,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
bmat = MATDICT[matName][1] bmat = MATDICT[matName][1]
img = TEXTURE_DICT.get(bmat.name) img = TEXTURE_DICT.get(bmat.name)
bmesh.materials.link(bmat) # can be None bmesh.materials.append(bmat) # can be None
if uv_faces and img: if uv_faces and img:
for fidx in faces: for fidx in faces:
@@ -420,7 +316,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
#print 'MAT_TEXTURE_MAP..while', new_chunk.bytes_read, new_chunk.length #print 'MAT_TEXTURE_MAP..while', new_chunk.bytes_read, new_chunk.length
read_chunk(file, temp_chunk) read_chunk(file, temp_chunk)
if (temp_chunk.ID == MAT_MAP_FILENAME): if (temp_chunk.ID == MAT_MAP_FILEPATH):
texture_name = read_string(file) texture_name = read_string(file)
img = TEXTURE_DICT[contextMaterial.name] = load_image(texture_name, dirname) img = TEXTURE_DICT[contextMaterial.name] = load_image(texture_name, dirname)
new_chunk.bytes_read += (len(texture_name)+1) #plus one for the null character that gets removed new_chunk.bytes_read += (len(texture_name)+1) #plus one for the null character that gets removed
@@ -434,7 +330,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
if img: if img:
add_texture_to_material(img, new_texture, contextMaterial, mapto) add_texture_to_material(img, new_texture, contextMaterial, mapto)
dirname = os.path.dirname(FILENAME) dirname = os.path.dirname(file.name)
#loop through all the data for this chunk (previous chunk) and see what it is #loop through all the data for this chunk (previous chunk) and see what it is
while (previous_chunk.bytes_read < previous_chunk.length): while (previous_chunk.bytes_read < previous_chunk.length):
@@ -720,14 +616,14 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
#contextMatrix = contextMatrix * tx #contextMatrix = contextMatrix * tx
#contextMatrix = contextMatrix *tx #contextMatrix = contextMatrix *tx
elif (new_chunk.ID == MAT_MAP_FILENAME): elif (new_chunk.ID == MAT_MAP_FILEPATH):
texture_name = read_string(file) texture_name = read_string(file)
try: try:
TEXTURE_DICT[contextMaterial.name] TEXTURE_DICT[contextMaterial.name]
except: except:
#img = TEXTURE_DICT[contextMaterial.name]= BPyImage.comprehensiveImageLoad(texture_name, FILENAME) #img = TEXTURE_DICT[contextMaterial.name]= BPyImage.comprehensiveImageLoad(texture_name, FILEPATH)
img = TEXTURE_DICT[contextMaterial.name] = load_image(texture_name, dirname) img = TEXTURE_DICT[contextMaterial.name] = load_image(texture_name, dirname)
# img = TEXTURE_DICT[contextMaterial.name]= BPyImage.comprehensiveImageLoad(texture_name, FILENAME, PLACE_HOLDER=False, RECURSIVE=IMAGE_SEARCH) # img = TEXTURE_DICT[contextMaterial.name]= BPyImage.comprehensiveImageLoad(texture_name, FILEPATH, PLACE_HOLDER=False, RECURSIVE=IMAGE_SEARCH)
new_chunk.bytes_read += len(texture_name)+1 #plus one for the null character that gets removed new_chunk.bytes_read += len(texture_name)+1 #plus one for the null character that gets removed
@@ -750,30 +646,27 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
if CreateBlenderObject: if CreateBlenderObject:
putContextMesh(contextMesh_vertls, contextMesh_facels, contextMeshMaterials) putContextMesh(contextMesh_vertls, contextMesh_facels, contextMeshMaterials)
def load_3ds(filename, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True, APPLY_MATRIX=False): def load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True, APPLY_MATRIX=False):
global FILENAME, SCN global SCN
# global FILENAME, SCN_OBJECTS
# XXX # XXX
# if BPyMessages.Error_NoFile(filename): # if BPyMessages.Error_NoFile(filepath):
# return # return
print('\n\nImporting 3DS: "%s"' % (filename)) print('\n\nImporting 3DS: %r' % (filepath))
# print('\n\nImporting 3DS: "%s"' % (Blender.sys.expandpath(filename)))
time1 = time.clock() time1 = time.clock()
# time1 = Blender.sys.time() # time1 = Blender.sys.time()
FILENAME = filename
current_chunk = chunk() current_chunk = chunk()
file = open(filename,'rb') file = open(filepath, 'rb')
#here we go! #here we go!
# print 'reading the first chunk' # print 'reading the first chunk'
read_chunk(file, current_chunk) read_chunk(file, current_chunk)
if (current_chunk.ID!=PRIMARY): if (current_chunk.ID!=PRIMARY):
print('\tFatal Error: Not a valid 3ds file: ', filename) print('\tFatal Error: Not a valid 3ds file: %r' % filepath)
file.close() file.close()
return return
@@ -834,7 +727,7 @@ def load_3ds(filename, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True,
# Done DUMMYVERT # Done DUMMYVERT
""" """
if IMPORT_AS_INSTANCE: if IMPORT_AS_INSTANCE:
name = filename.split('\\')[-1].split('/')[-1] name = filepath.split('\\')[-1].split('/')[-1]
# Create a group for this import. # Create a group for this import.
group_scn = Scene.New(name) group_scn = Scene.New(name)
for ob in importedObjects: for ob in importedObjects:
@@ -892,96 +785,10 @@ def load_3ds(filename, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True,
# Done constraining to bounds. # Done constraining to bounds.
# Select all new objects. # Select all new objects.
print('finished importing: "%s" in %.4f sec.' % (filename, (time.clock()-time1))) print('finished importing: %r in %.4f sec.' % (filepath, (time.clock()-time1)))
# print('finished importing: "%s" in %.4f sec.' % (filename, (Blender.sys.time()-time1)))
file.close() file.close()
DEBUG = False def load(operator, context, filepath="", constrain_size=0.0, use_image_search=True, use_apply_transform=True):
# For testing compatibility load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=constrain_size, IMAGE_SEARCH=use_image_search, APPLY_MATRIX=use_apply_transform)
#load_3ds('/metavr/convert/vehicle/truck_002/TruckTanker1.3DS', False) return {'FINISHED'}
#load_3ds('/metavr/archive/convert/old/arranged_3ds_to_hpx-2/only-need-engine-trains/Engine2.3DS', False)
'''
else:
import os
# DEBUG ONLY
TIME = Blender.sys.time()
import os
print 'Searching for files'
os.system('find /metavr/ -iname "*.3ds" > /tmp/temp3ds_list')
# os.system('find /storage/ -iname "*.3ds" > /tmp/temp3ds_list')
print '...Done'
file = open('/tmp/temp3ds_list', 'r')
lines = file.readlines()
file.close()
# sort by filesize for faster testing
lines_size = [(os.path.getsize(f[:-1]), f[:-1]) for f in lines]
lines_size.sort()
lines = [f[1] for f in lines_size]
def between(v,a,b):
if v <= max(a,b) and v >= min(a,b):
return True
return False
for i, _3ds in enumerate(lines):
if between(i, 650,800):
#_3ds= _3ds[:-1]
print 'Importing', _3ds, '\nNUMBER', i, 'of', len(lines)
_3ds_file= _3ds.split('/')[-1].split('\\')[-1]
newScn = Blender.Scene.New(_3ds_file)
newScn.makeCurrent()
load_3ds(_3ds, False)
print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME)
'''
from bpy.props import *
class IMPORT_OT_autodesk_3ds(bpy.types.Operator):
'''Import from 3DS file format (.3ds)'''
bl_idname = "import_scene.autodesk_3ds"
bl_label = 'Import 3DS'
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
filepath = StringProperty(name="File Path", description="Filepath used for importing the 3DS file", maxlen= 1024, default= "")
constrain_size = FloatProperty(name="Size Constraint", description="Scale the model by 10 until it reacehs the size constraint. Zero Disables.", min=0.0, max=1000.0, soft_min=0.0, soft_max=1000.0, default=10.0)
search_images = BoolProperty(name="Image Search", description="Search subdirectories for any assosiated images (Warning, may be slow)", default=True)
apply_transform = BoolProperty(name="Apply Transform", description="Workaround for object transformations importing incorrectly", default=False)
def execute(self, context):
load_3ds(self.properties.filepath,
context,
IMPORT_CONSTRAIN_BOUNDS=self.properties.constrain_size,
IMAGE_SEARCH=self.properties.search_images,
APPLY_MATRIX=self.properties.apply_transform)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return {'RUNNING_MODAL'}
def menu_func(self, context):
self.layout.operator(IMPORT_OT_autodesk_3ds.bl_idname, text="3D Studio (.3ds)")
def register():
bpy.types.INFO_MT_file_import.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_import.remove(menu_func)
# NOTES:
# why add 1 extra vertex? and remove it when done? - "Answer - eekadoodle - would need to re-order UV's without this since face order isnt always what we give blender, BMesh will solve :D"
# disabled scaling to size, this requires exposing bb (easy) and understanding how it works (needs some time)
if __name__ == "__main__":
register()

View File

@@ -0,0 +1,102 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# To support reload properly, try to access a package var, if it's there, reload everything
if "bpy" in locals():
# only reload if we alredy loaded, highly annoying
import sys
reload(sys.modules.get("io_scene_fbx.export_fbx", sys))
import bpy
from bpy.props import *
from io_utils import ExportHelper
class ExportFBX(bpy.types.Operator, ExportHelper):
'''Selection to an ASCII Autodesk FBX'''
bl_idname = "export_scene.fbx"
bl_label = "Export FBX"
filename_ext = ".fbx"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
EXP_OBS_SELECTED = BoolProperty(name="Selected Objects", description="Export selected objects on visible layers", default=True)
# EXP_OBS_SCENE = BoolProperty(name="Scene Objects", description="Export all objects in this scene", default=True)
TX_SCALE = FloatProperty(name="Scale", description="Scale all data, (Note! some imports dont support scaled armatures)", min=0.01, max=1000.0, soft_min=0.01, soft_max=1000.0, default=1.0)
TX_XROT90 = BoolProperty(name="Rot X90", description="Rotate all objects 90 degrees about the X axis", default=True)
TX_YROT90 = BoolProperty(name="Rot Y90", description="Rotate all objects 90 degrees about the Y axis", default=False)
TX_ZROT90 = BoolProperty(name="Rot Z90", description="Rotate all objects 90 degrees about the Z axis", default=False)
EXP_EMPTY = BoolProperty(name="Empties", description="Export empty objects", default=True)
EXP_CAMERA = BoolProperty(name="Cameras", description="Export camera objects", default=True)
EXP_LAMP = BoolProperty(name="Lamps", description="Export lamp objects", default=True)
EXP_ARMATURE = BoolProperty(name="Armatures", description="Export armature objects", default=True)
EXP_MESH = BoolProperty(name="Meshes", description="Export mesh objects", default=True)
EXP_MESH_APPLY_MOD = BoolProperty(name="Modifiers", description="Apply modifiers to mesh objects", default=True)
EXP_MESH_HQ_NORMALS = BoolProperty(name="HQ Normals", description="Generate high quality normals", default=True)
EXP_IMAGE_COPY = BoolProperty(name="Copy Image Files", description="Copy image files to the destination path", default=False)
# armature animation
ANIM_ENABLE = BoolProperty(name="Enable Animation", description="Export keyframe animation", default=True)
ANIM_OPTIMIZE = BoolProperty(name="Optimize Keyframes", description="Remove double keyframes", default=True)
ANIM_OPTIMIZE_PRECISSION = FloatProperty(name="Precision", description="Tolerence for comparing double keyframes (higher for greater accuracy)", min=1, max=16, soft_min=1, soft_max=16, default=6.0)
# ANIM_ACTION_ALL = BoolProperty(name="Current Action", description="Use actions currently applied to the armatures (use scene start/end frame)", default=True)
ANIM_ACTION_ALL = BoolProperty(name="All Actions", description="Use all actions for armatures, if false, use current action", default=False)
# batch
BATCH_ENABLE = BoolProperty(name="Enable Batch", description="Automate exporting multiple scenes or groups to files", default=False)
BATCH_GROUP = BoolProperty(name="Group > File", description="Export each group as an FBX file, if false, export each scene as an FBX file", default=False)
BATCH_OWN_DIR = BoolProperty(name="Own Dir", description="Create a dir for each exported file", default=True)
BATCH_FILE_PREFIX = StringProperty(name="Prefix", description="Prefix each file with this name", maxlen=1024, default="")
def execute(self, context):
import math
from mathutils import Matrix
if not self.properties.filepath:
raise Exception("filepath not set")
mtx4_x90n = Matrix.Rotation(-math.pi/2.0, 4, 'X')
mtx4_y90n = Matrix.Rotation(-math.pi/2.0, 4, 'Y')
mtx4_z90n = Matrix.Rotation(-math.pi/2.0, 4, 'Z')
GLOBAL_MATRIX = Matrix()
GLOBAL_MATRIX[0][0] = GLOBAL_MATRIX[1][1] = GLOBAL_MATRIX[2][2] = self.properties.TX_SCALE
if self.properties.TX_XROT90: GLOBAL_MATRIX = mtx4_x90n * GLOBAL_MATRIX
if self.properties.TX_YROT90: GLOBAL_MATRIX = mtx4_y90n * GLOBAL_MATRIX
if self.properties.TX_ZROT90: GLOBAL_MATRIX = mtx4_z90n * GLOBAL_MATRIX
import io_scene_fbx.export_fbx
return io_scene_fbx.export_fbx.save(self, context, GLOBAL_MATRIX=GLOBAL_MATRIX, **self.properties)
def menu_func(self, context):
self.layout.operator(ExportFBX.bl_idname, text="Autodesk FBX (.fbx)")
def register():
bpy.types.INFO_MT_file_export.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_export.remove(menu_func)
if __name__ == "__main__":
register()

View File

@@ -18,36 +18,13 @@
# <pep8 compliant> # <pep8 compliant>
__author__ = "Campbell Barton" # Script copyright (C) Campbell Barton
__url__ = ['www.blender.org', 'blenderartists.org']
__version__ = "1.2"
__bpydoc__ = """\ """
This script is an exporter to the FBX file format. This script is an exporter to the FBX file format.
http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_fbx http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_fbx
""" """
# --------------------------------------------------------------------------
# FBX Export v0.1 by Campbell Barton (AKA Ideasman)
# --------------------------------------------------------------------------
# ***** 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.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import os import os
import time import time
@@ -57,19 +34,10 @@ import shutil # for file copying
import bpy import bpy
from mathutils import Vector, Euler, Matrix from mathutils import Vector, Euler, Matrix
def copy_file(source, dest):
# XXX - remove, can use shutil
file = open(source, 'rb')
data = file.read()
file.close()
file = open(dest, 'wb')
file.write(data)
file.close()
# XXX not used anymore, images are copied one at a time # XXX not used anymore, images are copied one at a time
def copy_images(dest_dir, textures): def copy_images(dest_dir, textures):
import shutil
if not dest_dir.endswith(os.sep): if not dest_dir.endswith(os.sep):
dest_dir += os.sep dest_dir += os.sep
@@ -84,12 +52,12 @@ def copy_images(dest_dir, textures):
# Make a name for the target path. # Make a name for the target path.
dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1] dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1]
if not Blender.sys.exists(dest_image_path): # Image isnt already there if not Blender.sys.exists(dest_image_path): # Image isnt already there
print('\tCopying "%s" > "%s"' % (image_path, dest_image_path)) print("\tCopying %r > %r" % (image_path, dest_image_path))
try: try:
copy_file(image_path, dest_image_path) shutil.copy(image_path, dest_image_path)
copyCount+=1 copyCount+=1
except: except:
print('\t\tWarning, file failed to copy, skipping.') print("\t\tWarning, file failed to copy, skipping.")
print('\tCopied %d images' % copyCount) print('\tCopied %d images' % copyCount)
@@ -104,27 +72,11 @@ def eulerRadToDeg(eul):
return ret return ret
mtx4_identity = Matrix()
# testing
mtx_x90 = Matrix.Rotation( math.pi/2, 3, 'X') # used
#mtx_x90n = Matrix.Rotation(-90, 3, 'x')
#mtx_y90 = Matrix.Rotation( 90, 3, 'y')
#mtx_y90n = Matrix.Rotation(-90, 3, 'y')
#mtx_z90 = Matrix.Rotation( 90, 3, 'z')
#mtx_z90n = Matrix.Rotation(-90, 3, 'z')
#mtx4_x90 = Matrix.Rotation( 90, 4, 'x')
mtx4_x90n = Matrix.Rotation(-math.pi/2, 4, 'X') # used
#mtx4_y90 = Matrix.Rotation( 90, 4, 'y')
mtx4_y90n = Matrix.Rotation(-math.pi/2, 4, 'Y') # used
mtx4_z90 = Matrix.Rotation( math.pi/2, 4, 'Z') # used
mtx4_z90n = Matrix.Rotation(-math.pi/2, 4, 'Z') # used
# def strip_path(p): # def strip_path(p):
# return p.split('\\')[-1].split('/')[-1] # return p.split('\\')[-1].split('/')[-1]
# Used to add the scene name into the filename without using odd chars # Used to add the scene name into the filepath without using odd chars
sane_name_mapping_ob = {} sane_name_mapping_ob = {}
sane_name_mapping_mat = {} sane_name_mapping_mat = {}
sane_name_mapping_tex = {} sane_name_mapping_tex = {}
@@ -197,7 +149,7 @@ def sane_groupname(data): return sane_name(data, sane_name_mapping_group)
# ''' # '''
# fname_orig - blender path, can be relative # fname_orig - blender path, can be relative
# basepath - fname_rel will be relative to this # basepath - fname_rel will be relative to this
# FORCE_CWD - dont use the basepath, just add a ./ to the filename. # FORCE_CWD - dont use the basepath, just add a ./ to the filepath.
# use when we know the file will be in the basepath. # use when we know the file will be in the basepath.
# ''' # '''
# fname = bpy.path.abspath(fname_orig) # fname = bpy.path.abspath(fname_orig)
@@ -282,19 +234,17 @@ header_comment = \
''' '''
# This func can be called with just the filename # This func can be called with just the filepath
def write(filename, batch_objects = None, \ def save(operator, context, filepath="", \
context = None,
EXP_OBS_SELECTED = True, EXP_OBS_SELECTED = True,
EXP_MESH = True, EXP_MESH = True,
EXP_MESH_APPLY_MOD = True, EXP_MESH_APPLY_MOD = True,
# EXP_MESH_HQ_NORMALS = False,
EXP_ARMATURE = True, EXP_ARMATURE = True,
EXP_LAMP = True, EXP_LAMP = True,
EXP_CAMERA = True, EXP_CAMERA = True,
EXP_EMPTY = True, EXP_EMPTY = True,
EXP_IMAGE_COPY = False, EXP_IMAGE_COPY = False,
GLOBAL_MATRIX = Matrix(), GLOBAL_MATRIX = None,
ANIM_ENABLE = True, ANIM_ENABLE = True,
ANIM_OPTIMIZE = True, ANIM_OPTIMIZE = True,
ANIM_OPTIMIZE_PRECISSION = 6, ANIM_OPTIMIZE_PRECISSION = 6,
@@ -305,16 +255,26 @@ def write(filename, batch_objects = None, \
BATCH_OWN_DIR = False BATCH_OWN_DIR = False
): ):
if bpy.context.object: #XXX, missing arg
batch_objects = None
# testing
mtx_x90 = Matrix.Rotation( math.pi/2.0, 3, 'X') # used
mtx4_z90 = Matrix.Rotation( math.pi/2.0, 4, 'Z')
if GLOBAL_MATRIX is None:
GLOBAL_MATRIX = Matrix()
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='OBJECT')
# ----------------- Batch support! # ----------------- Batch support!
if BATCH_ENABLE: if BATCH_ENABLE:
if os == None: BATCH_OWN_DIR = False if os == None: BATCH_OWN_DIR = False
fbxpath = filename fbxpath = filepath
# get the path component of filename # get the path component of filepath
tmp_exists = bpy.utils.exists(fbxpath) tmp_exists = bpy.utils.exists(fbxpath)
# tmp_exists = Blender.sys.exists(fbxpath) # tmp_exists = Blender.sys.exists(fbxpath)
@@ -323,7 +283,7 @@ def write(filename, batch_objects = None, \
# while fbxpath and fbxpath[-1] not in ('/', '\\'): # while fbxpath and fbxpath[-1] not in ('/', '\\'):
# fbxpath = fbxpath[:-1] # fbxpath = fbxpath[:-1]
if not fbxpath: if not fbxpath:
# if not filename: # if not filepath:
# XXX # XXX
print('Error%t|Directory does not exist!') print('Error%t|Directory does not exist!')
# Draw.PupMenu('Error%t|Directory does not exist!') # Draw.PupMenu('Error%t|Directory does not exist!')
@@ -368,9 +328,9 @@ def write(filename, batch_objects = None, \
os.mkdir(new_fbxpath) os.mkdir(new_fbxpath)
filename = new_fbxpath + newname + '.fbx' filepath = new_fbxpath + newname + '.fbx'
print('\nBatch exporting %s as...\n\t"%s"' % (data, filename)) print('\nBatch exporting %s as...\n\t%r' % (data, filepath))
# XXX don't know what to do with this, probably do the same? (Arystan) # XXX don't know what to do with this, probably do the same? (Arystan)
if BATCH_GROUP: #group if BATCH_GROUP: #group
@@ -393,12 +353,11 @@ def write(filename, batch_objects = None, \
# Call self with modified args # Call self with modified args
# Dont pass batch options since we already usedt them # Dont pass batch options since we already usedt them
write(filename, data.objects, write(filepath, data.objects,
context, context,
False, False,
EXP_MESH, EXP_MESH,
EXP_MESH_APPLY_MOD, EXP_MESH_APPLY_MOD,
# EXP_MESH_HQ_NORMALS,
EXP_ARMATURE, EXP_ARMATURE,
EXP_LAMP, EXP_LAMP,
EXP_CAMERA, EXP_CAMERA,
@@ -423,9 +382,9 @@ def write(filename, batch_objects = None, \
# end batch support # end batch support
# Use this for working out paths relative to the export location # Use this for working out paths relative to the export location
basepath = os.path.dirname(filename) or '.' basepath = os.path.dirname(filepath) or '.'
basepath += os.sep basepath += os.sep
# basepath = Blender.sys.dirname(filename) # basepath = Blender.sys.dirname(filepath)
# ---------------------------------------------- # ----------------------------------------------
# storage classes # storage classes
@@ -572,11 +531,11 @@ def write(filename, batch_objects = None, \
print('\nFBX export starting...', filename) print('\nFBX export starting... %r' % filepath)
start_time = time.clock() start_time = time.clock()
# start_time = Blender.sys.time() # start_time = Blender.sys.time()
try: try:
file = open(filename, 'w') file = open(filepath, 'w')
except: except:
return False return False
@@ -2006,7 +1965,7 @@ def write(filename, batch_objects = None, \
ob_base.update(scene) ob_base.update(scene)
# This causes the makeDisplayList command to effect the mesh # This causes the makeDisplayList command to effect the mesh
scene.set_frame(scene.frame_current) scene.frame_set(scene.frame_current)
# Blender.Set('curframe', Blender.Get('curframe')) # Blender.Set('curframe', Blender.Get('curframe'))
@@ -2179,7 +2138,7 @@ def write(filename, batch_objects = None, \
if ob_base.type == 'ARMATURE': if ob_base.type == 'ARMATURE':
ob_base.update(scene) ob_base.update(scene)
# This causes the makeDisplayList command to effect the mesh # This causes the makeDisplayList command to effect the mesh
scene.set_frame(scene.frame_current) scene.frame_set(scene.frame_current)
# Blender.Set('curframe', Blender.Get('curframe')) # Blender.Set('curframe', Blender.Get('curframe'))
del tmp_ob_type, tmp_objects del tmp_ob_type, tmp_objects
@@ -2472,7 +2431,7 @@ Objects: {''')
file.write('\n\t\tPoseNode: {') file.write('\n\t\tPoseNode: {')
file.write('\n\t\t\tNode: "Model::%s"' % fbxName ) file.write('\n\t\t\tNode: "Model::%s"' % fbxName )
if matrix: file.write('\n\t\t\tMatrix: %s' % mat4x4str(matrix)) if matrix: file.write('\n\t\t\tMatrix: %s' % mat4x4str(matrix))
else: file.write('\n\t\t\tMatrix: %s' % mat4x4str(mtx4_identity)) else: file.write('\n\t\t\tMatrix: %s' % mat4x4str(Matrix()))
file.write('\n\t\t}') file.write('\n\t\t}')
file.write('\n\t}') file.write('\n\t}')
@@ -2760,7 +2719,9 @@ Takes: {''')
else: else:
file.write('\n\tTake: "%s" {' % sane_takename(blenAction)) file.write('\n\tTake: "%s" {' % sane_takename(blenAction))
act_start, act_end = blenAction.get_frame_range() act_start, act_end = blenAction.frame_range
act_start = int(act_start)
act_end = int(act_end)
# tmp = blenAction.getFrameNumbers() # tmp = blenAction.getFrameNumbers()
# if tmp: # if tmp:
# act_start = min(tmp) # act_start = min(tmp)
@@ -2797,7 +2758,7 @@ Takes: {''')
''' '''
i = act_start i = act_start
while i <= act_end: while i <= act_end:
scene.set_frame(i) scene.frame_set(i)
# Blender.Set('curframe', i) # Blender.Set('curframe', i)
for ob_generic in ob_anim_lists: for ob_generic in ob_anim_lists:
for my_ob in ob_generic: for my_ob in ob_generic:
@@ -2937,8 +2898,7 @@ Takes: {''')
file.write('\n}') file.write('\n}')
scene.set_frame(frame_orig) scene.frame_set(frame_orig)
# Blender.Set('curframe', frame_orig)
else: else:
# no animation # no animation
@@ -2967,12 +2927,10 @@ Takes: {''')
mist_start = m.start mist_start = m.start
mist_end = m.depth mist_end = m.depth
mist_height = m.height mist_height = m.height
# mist_intense, mist_start, mist_end, mist_height = world.mist
world_hor = world.horizon_color world_hor = world.horizon_color
# world_hor = world.hor
else: else:
has_mist = mist_intense = mist_start = mist_end = mist_height = 0 has_mist = mist_intense = mist_start = mist_end = mist_height = 0
world_hor = 0,0,0 world_hor = 0, 0, 0
file.write('\n;Version 5 settings') file.write('\n;Version 5 settings')
file.write('\n;------------------------------------------------------------------') file.write('\n;------------------------------------------------------------------')
@@ -3024,394 +2982,7 @@ Takes: {''')
# bpy.util.copy_images( [ tex[1] for tex in textures if tex[1] != None ], basepath) # bpy.util.copy_images( [ tex[1] for tex in textures if tex[1] != None ], basepath)
print('export finished in %.4f sec.' % (time.clock() - start_time)) print('export finished in %.4f sec.' % (time.clock() - start_time))
# print 'export finished in %.4f sec.' % (Blender.sys.time() - start_time) return {'FINISHED'}
return True
# --------------------------------------------
# UI Function - not a part of the exporter.
# this is to separate the user interface from the rest of the exporter.
# from Blender import Draw, Window
EVENT_NONE = 0
EVENT_EXIT = 1
EVENT_REDRAW = 2
EVENT_FILESEL = 3
GLOBALS = {}
# export opts
def do_redraw(e,v): GLOBALS['EVENT'] = e
# toggle between these 2, only allow one on at once
def do_obs_sel(e,v):
GLOBALS['EVENT'] = e
GLOBALS['EXP_OBS_SCENE'].val = 0
GLOBALS['EXP_OBS_SELECTED'].val = 1
def do_obs_sce(e,v):
GLOBALS['EVENT'] = e
GLOBALS['EXP_OBS_SCENE'].val = 1
GLOBALS['EXP_OBS_SELECTED'].val = 0
def do_batch_type_grp(e,v):
GLOBALS['EVENT'] = e
GLOBALS['BATCH_GROUP'].val = 1
GLOBALS['BATCH_SCENE'].val = 0
def do_batch_type_sce(e,v):
GLOBALS['EVENT'] = e
GLOBALS['BATCH_GROUP'].val = 0
GLOBALS['BATCH_SCENE'].val = 1
def do_anim_act_all(e,v):
GLOBALS['EVENT'] = e
GLOBALS['ANIM_ACTION_ALL'][0].val = 1
GLOBALS['ANIM_ACTION_ALL'][1].val = 0
def do_anim_act_cur(e,v):
if GLOBALS['BATCH_ENABLE'].val and GLOBALS['BATCH_GROUP'].val:
Draw.PupMenu('Warning%t|Cant use this with batch export group option')
else:
GLOBALS['EVENT'] = e
GLOBALS['ANIM_ACTION_ALL'][0].val = 0
GLOBALS['ANIM_ACTION_ALL'][1].val = 1
def fbx_ui_exit(e,v):
GLOBALS['EVENT'] = e
def do_help(e,v):
url = 'http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_fbx'
print('Trying to open web browser with documentation at this address...')
print('\t' + url)
try:
import webbrowser
webbrowser.open(url)
except:
Blender.Draw.PupMenu("Error%t|Opening a webbrowser requires a full python installation")
print('...could not open a browser window.')
# run when export is pressed
#def fbx_ui_write(e,v):
def fbx_ui_write(filename, context):
# Dont allow overwriting files when saving normally
if not GLOBALS['BATCH_ENABLE'].val:
if not BPyMessages.Warning_SaveOver(filename):
return
GLOBALS['EVENT'] = EVENT_EXIT
# Keep the order the same as above for simplicity
# the [] is a dummy arg used for objects
Blender.Window.WaitCursor(1)
# Make the matrix
GLOBAL_MATRIX = mtx4_identity
GLOBAL_MATRIX[0][0] = GLOBAL_MATRIX[1][1] = GLOBAL_MATRIX[2][2] = GLOBALS['_SCALE'].val
if GLOBALS['_XROT90'].val: GLOBAL_MATRIX = mtx4_x90n * GLOBAL_MATRIX
if GLOBALS['_YROT90'].val: GLOBAL_MATRIX = mtx4_y90n * GLOBAL_MATRIX
if GLOBALS['_ZROT90'].val: GLOBAL_MATRIX = mtx4_z90n * GLOBAL_MATRIX
ret = write(\
filename, None,\
context,
GLOBALS['EXP_OBS_SELECTED'].val,\
GLOBALS['EXP_MESH'].val,\
GLOBALS['EXP_MESH_APPLY_MOD'].val,\
GLOBALS['EXP_MESH_HQ_NORMALS'].val,\
GLOBALS['EXP_ARMATURE'].val,\
GLOBALS['EXP_LAMP'].val,\
GLOBALS['EXP_CAMERA'].val,\
GLOBALS['EXP_EMPTY'].val,\
GLOBALS['EXP_IMAGE_COPY'].val,\
GLOBAL_MATRIX,\
GLOBALS['ANIM_ENABLE'].val,\
GLOBALS['ANIM_OPTIMIZE'].val,\
GLOBALS['ANIM_OPTIMIZE_PRECISSION'].val,\
GLOBALS['ANIM_ACTION_ALL'][0].val,\
GLOBALS['BATCH_ENABLE'].val,\
GLOBALS['BATCH_GROUP'].val,\
GLOBALS['BATCH_SCENE'].val,\
GLOBALS['BATCH_FILE_PREFIX'].val,\
GLOBALS['BATCH_OWN_DIR'].val,\
)
Blender.Window.WaitCursor(0)
GLOBALS.clear()
if ret == False:
Draw.PupMenu('Error%t|Path cannot be written to!')
def fbx_ui():
# Only to center the UI
x,y = GLOBALS['MOUSE']
x-=180; y-=0 # offset... just to get it centered
Draw.Label('Export Objects...', x+20,y+165, 200, 20)
if not GLOBALS['BATCH_ENABLE'].val:
Draw.BeginAlign()
GLOBALS['EXP_OBS_SELECTED'] = Draw.Toggle('Selected Objects', EVENT_REDRAW, x+20, y+145, 160, 20, GLOBALS['EXP_OBS_SELECTED'].val, 'Export selected objects on visible layers', do_obs_sel)
GLOBALS['EXP_OBS_SCENE'] = Draw.Toggle('Scene Objects', EVENT_REDRAW, x+180, y+145, 160, 20, GLOBALS['EXP_OBS_SCENE'].val, 'Export all objects in this scene', do_obs_sce)
Draw.EndAlign()
Draw.BeginAlign()
GLOBALS['_SCALE'] = Draw.Number('Scale:', EVENT_NONE, x+20, y+120, 140, 20, GLOBALS['_SCALE'].val, 0.01, 1000.0, 'Scale all data, (Note! some imports dont support scaled armatures)')
GLOBALS['_XROT90'] = Draw.Toggle('Rot X90', EVENT_NONE, x+160, y+120, 60, 20, GLOBALS['_XROT90'].val, 'Rotate all objects 90 degrees about the X axis')
GLOBALS['_YROT90'] = Draw.Toggle('Rot Y90', EVENT_NONE, x+220, y+120, 60, 20, GLOBALS['_YROT90'].val, 'Rotate all objects 90 degrees about the Y axis')
GLOBALS['_ZROT90'] = Draw.Toggle('Rot Z90', EVENT_NONE, x+280, y+120, 60, 20, GLOBALS['_ZROT90'].val, 'Rotate all objects 90 degrees about the Z axis')
Draw.EndAlign()
y -= 35
Draw.BeginAlign()
GLOBALS['EXP_EMPTY'] = Draw.Toggle('Empty', EVENT_NONE, x+20, y+120, 60, 20, GLOBALS['EXP_EMPTY'].val, 'Export empty objects')
GLOBALS['EXP_CAMERA'] = Draw.Toggle('Camera', EVENT_NONE, x+80, y+120, 60, 20, GLOBALS['EXP_CAMERA'].val, 'Export camera objects')
GLOBALS['EXP_LAMP'] = Draw.Toggle('Lamp', EVENT_NONE, x+140, y+120, 60, 20, GLOBALS['EXP_LAMP'].val, 'Export lamp objects')
GLOBALS['EXP_ARMATURE'] = Draw.Toggle('Armature', EVENT_NONE, x+200, y+120, 60, 20, GLOBALS['EXP_ARMATURE'].val, 'Export armature objects')
GLOBALS['EXP_MESH'] = Draw.Toggle('Mesh', EVENT_REDRAW, x+260, y+120, 80, 20, GLOBALS['EXP_MESH'].val, 'Export mesh objects', do_redraw) #, do_axis_z)
Draw.EndAlign()
if GLOBALS['EXP_MESH'].val:
# below mesh but
Draw.BeginAlign()
GLOBALS['EXP_MESH_APPLY_MOD'] = Draw.Toggle('Modifiers', EVENT_NONE, x+260, y+100, 80, 20, GLOBALS['EXP_MESH_APPLY_MOD'].val, 'Apply modifiers to mesh objects') #, do_axis_z)
GLOBALS['EXP_MESH_HQ_NORMALS'] = Draw.Toggle('HQ Normals', EVENT_NONE, x+260, y+80, 80, 20, GLOBALS['EXP_MESH_HQ_NORMALS'].val, 'Generate high quality normals') #, do_axis_z)
Draw.EndAlign()
GLOBALS['EXP_IMAGE_COPY'] = Draw.Toggle('Copy Image Files', EVENT_NONE, x+20, y+80, 160, 20, GLOBALS['EXP_IMAGE_COPY'].val, 'Copy image files to the destination path') #, do_axis_z)
Draw.Label('Export Armature Animation...', x+20,y+45, 300, 20)
GLOBALS['ANIM_ENABLE'] = Draw.Toggle('Enable Animation', EVENT_REDRAW, x+20, y+25, 160, 20, GLOBALS['ANIM_ENABLE'].val, 'Export keyframe animation', do_redraw)
if GLOBALS['ANIM_ENABLE'].val:
Draw.BeginAlign()
GLOBALS['ANIM_OPTIMIZE'] = Draw.Toggle('Optimize Keyframes', EVENT_REDRAW, x+20, y+0, 160, 20, GLOBALS['ANIM_OPTIMIZE'].val, 'Remove double keyframes', do_redraw)
if GLOBALS['ANIM_OPTIMIZE'].val:
GLOBALS['ANIM_OPTIMIZE_PRECISSION'] = Draw.Number('Precission: ', EVENT_NONE, x+180, y+0, 160, 20, GLOBALS['ANIM_OPTIMIZE_PRECISSION'].val, 1, 16, 'Tolerence for comparing double keyframes (higher for greater accuracy)')
Draw.EndAlign()
Draw.BeginAlign()
GLOBALS['ANIM_ACTION_ALL'][1] = Draw.Toggle('Current Action', EVENT_REDRAW, x+20, y-25, 160, 20, GLOBALS['ANIM_ACTION_ALL'][1].val, 'Use actions currently applied to the armatures (use scene start/end frame)', do_anim_act_cur)
GLOBALS['ANIM_ACTION_ALL'][0] = Draw.Toggle('All Actions', EVENT_REDRAW, x+180,y-25, 160, 20, GLOBALS['ANIM_ACTION_ALL'][0].val, 'Use all actions for armatures', do_anim_act_all)
Draw.EndAlign()
Draw.Label('Export Batch...', x+20,y-60, 300, 20)
GLOBALS['BATCH_ENABLE'] = Draw.Toggle('Enable Batch', EVENT_REDRAW, x+20, y-80, 160, 20, GLOBALS['BATCH_ENABLE'].val, 'Automate exporting multiple scenes or groups to files', do_redraw)
if GLOBALS['BATCH_ENABLE'].val:
Draw.BeginAlign()
GLOBALS['BATCH_GROUP'] = Draw.Toggle('Group > File', EVENT_REDRAW, x+20, y-105, 160, 20, GLOBALS['BATCH_GROUP'].val, 'Export each group as an FBX file', do_batch_type_grp)
GLOBALS['BATCH_SCENE'] = Draw.Toggle('Scene > File', EVENT_REDRAW, x+180, y-105, 160, 20, GLOBALS['BATCH_SCENE'].val, 'Export each scene as an FBX file', do_batch_type_sce)
# Own dir requires OS module
if os:
GLOBALS['BATCH_OWN_DIR'] = Draw.Toggle('Own Dir', EVENT_NONE, x+20, y-125, 80, 20, GLOBALS['BATCH_OWN_DIR'].val, 'Create a dir for each exported file')
GLOBALS['BATCH_FILE_PREFIX'] = Draw.String('Prefix: ', EVENT_NONE, x+100, y-125, 240, 20, GLOBALS['BATCH_FILE_PREFIX'].val, 64, 'Prefix each file with this name ')
else:
GLOBALS['BATCH_FILE_PREFIX'] = Draw.String('Prefix: ', EVENT_NONE, x+20, y-125, 320, 20, GLOBALS['BATCH_FILE_PREFIX'].val, 64, 'Prefix each file with this name ')
Draw.EndAlign()
#y+=80
'''
Draw.BeginAlign()
GLOBALS['FILENAME'] = Draw.String('path: ', EVENT_NONE, x+20, y-170, 300, 20, GLOBALS['FILENAME'].val, 64, 'Prefix each file with this name ')
Draw.PushButton('..', EVENT_FILESEL, x+320, y-170, 20, 20, 'Select the path', do_redraw)
'''
# Until batch is added
#
#Draw.BeginAlign()
Draw.PushButton('Online Help', EVENT_REDRAW, x+20, y-160, 100, 20, 'Open online help in a browser window', do_help)
Draw.PushButton('Cancel', EVENT_EXIT, x+130, y-160, 100, 20, 'Exit the exporter', fbx_ui_exit)
Draw.PushButton('Export', EVENT_FILESEL, x+240, y-160, 100, 20, 'Export the fbx file', do_redraw)
#Draw.PushButton('Export', EVENT_EXIT, x+180, y-160, 160, 20, 'Export the fbx file', fbx_ui_write)
#Draw.EndAlign()
# exit when mouse out of the view?
# GLOBALS['EVENT'] = EVENT_EXIT
#def write_ui(filename):
def write_ui():
# globals
GLOBALS['EVENT'] = EVENT_REDRAW
#GLOBALS['MOUSE'] = Window.GetMouseCoords()
GLOBALS['MOUSE'] = [i/2 for i in Window.GetScreenSize()]
GLOBALS['FILENAME'] = ''
'''
# IF called from the fileselector
if filename == None:
GLOBALS['FILENAME'] = filename # Draw.Create(Blender.sys.makename(ext='.fbx'))
else:
GLOBALS['FILENAME'].val = filename
'''
GLOBALS['EXP_OBS_SELECTED'] = Draw.Create(1) # dont need 2 variables but just do this for clarity
GLOBALS['EXP_OBS_SCENE'] = Draw.Create(0)
GLOBALS['EXP_MESH'] = Draw.Create(1)
GLOBALS['EXP_MESH_APPLY_MOD'] = Draw.Create(1)
GLOBALS['EXP_MESH_HQ_NORMALS'] = Draw.Create(0)
GLOBALS['EXP_ARMATURE'] = Draw.Create(1)
GLOBALS['EXP_LAMP'] = Draw.Create(1)
GLOBALS['EXP_CAMERA'] = Draw.Create(1)
GLOBALS['EXP_EMPTY'] = Draw.Create(1)
GLOBALS['EXP_IMAGE_COPY'] = Draw.Create(0)
# animation opts
GLOBALS['ANIM_ENABLE'] = Draw.Create(1)
GLOBALS['ANIM_OPTIMIZE'] = Draw.Create(1)
GLOBALS['ANIM_OPTIMIZE_PRECISSION'] = Draw.Create(4) # decimal places
GLOBALS['ANIM_ACTION_ALL'] = [Draw.Create(0), Draw.Create(1)] # not just the current action
# batch export options
GLOBALS['BATCH_ENABLE'] = Draw.Create(0)
GLOBALS['BATCH_GROUP'] = Draw.Create(1) # cant have both of these enabled at once.
GLOBALS['BATCH_SCENE'] = Draw.Create(0) # see above
GLOBALS['BATCH_FILE_PREFIX'] = Draw.Create(Blender.sys.makename(ext='_').split('\\')[-1].split('/')[-1])
GLOBALS['BATCH_OWN_DIR'] = Draw.Create(0)
# done setting globals
# Used by the user interface
GLOBALS['_SCALE'] = Draw.Create(1.0)
GLOBALS['_XROT90'] = Draw.Create(True)
GLOBALS['_YROT90'] = Draw.Create(False)
GLOBALS['_ZROT90'] = Draw.Create(False)
# best not do move the cursor
# Window.SetMouseCoords(*[i/2 for i in Window.GetScreenSize()])
# hack so the toggle buttons redraw. this is not nice at all
while GLOBALS['EVENT'] != EVENT_EXIT:
if GLOBALS['BATCH_ENABLE'].val and GLOBALS['BATCH_GROUP'].val and GLOBALS['ANIM_ACTION_ALL'][1].val:
#Draw.PupMenu("Warning%t|Cant batch export groups with 'Current Action' ")
GLOBALS['ANIM_ACTION_ALL'][0].val = 1
GLOBALS['ANIM_ACTION_ALL'][1].val = 0
if GLOBALS['EVENT'] == EVENT_FILESEL:
if GLOBALS['BATCH_ENABLE'].val:
txt = 'Batch FBX Dir'
name = Blender.sys.expandpath('//')
else:
txt = 'Export FBX'
name = Blender.sys.makename(ext='.fbx')
Blender.Window.FileSelector(fbx_ui_write, txt, name)
#fbx_ui_write('/test.fbx')
break
Draw.UIBlock(fbx_ui, 0)
# GLOBALS.clear()
from bpy.props import *
class ExportFBX(bpy.types.Operator):
'''Selection to an ASCII Autodesk FBX'''
bl_idname = "export.fbx"
bl_label = "Export FBX"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
filepath = StringProperty(name="File Path", description="Filepath used for exporting the FBX file", maxlen= 1024, default="")
check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'})
EXP_OBS_SELECTED = BoolProperty(name="Selected Objects", description="Export selected objects on visible layers", default=True)
# EXP_OBS_SCENE = BoolProperty(name="Scene Objects", description="Export all objects in this scene", default=True)
TX_SCALE = FloatProperty(name="Scale", description="Scale all data, (Note! some imports dont support scaled armatures)", min=0.01, max=1000.0, soft_min=0.01, soft_max=1000.0, default=1.0)
TX_XROT90 = BoolProperty(name="Rot X90", description="Rotate all objects 90 degrees about the X axis", default=True)
TX_YROT90 = BoolProperty(name="Rot Y90", description="Rotate all objects 90 degrees about the Y axis", default=False)
TX_ZROT90 = BoolProperty(name="Rot Z90", description="Rotate all objects 90 degrees about the Z axis", default=False)
EXP_EMPTY = BoolProperty(name="Empties", description="Export empty objects", default=True)
EXP_CAMERA = BoolProperty(name="Cameras", description="Export camera objects", default=True)
EXP_LAMP = BoolProperty(name="Lamps", description="Export lamp objects", default=True)
EXP_ARMATURE = BoolProperty(name="Armatures", description="Export armature objects", default=True)
EXP_MESH = BoolProperty(name="Meshes", description="Export mesh objects", default=True)
EXP_MESH_APPLY_MOD = BoolProperty(name="Modifiers", description="Apply modifiers to mesh objects", default=True)
EXP_MESH_HQ_NORMALS = BoolProperty(name="HQ Normals", description="Generate high quality normals", default=True)
EXP_IMAGE_COPY = BoolProperty(name="Copy Image Files", description="Copy image files to the destination path", default=False)
# armature animation
ANIM_ENABLE = BoolProperty(name="Enable Animation", description="Export keyframe animation", default=True)
ANIM_OPTIMIZE = BoolProperty(name="Optimize Keyframes", description="Remove double keyframes", default=True)
ANIM_OPTIMIZE_PRECISSION = FloatProperty(name="Precision", description="Tolerence for comparing double keyframes (higher for greater accuracy)", min=1, max=16, soft_min=1, soft_max=16, default=6.0)
# ANIM_ACTION_ALL = BoolProperty(name="Current Action", description="Use actions currently applied to the armatures (use scene start/end frame)", default=True)
ANIM_ACTION_ALL = BoolProperty(name="All Actions", description="Use all actions for armatures, if false, use current action", default=False)
# batch
BATCH_ENABLE = BoolProperty(name="Enable Batch", description="Automate exporting multiple scenes or groups to files", default=False)
BATCH_GROUP = BoolProperty(name="Group > File", description="Export each group as an FBX file, if false, export each scene as an FBX file", default=False)
BATCH_OWN_DIR = BoolProperty(name="Own Dir", description="Create a dir for each exported file", default=True)
BATCH_FILE_PREFIX = StringProperty(name="Prefix", description="Prefix each file with this name", maxlen=1024, default="")
@classmethod
def poll(cls, context):
return context.active_object
def execute(self, context):
if not self.properties.filepath:
raise Exception("filepath not set")
filepath = self.properties.filepath
filepath = bpy.path.ensure_ext(filepath, ".fbx")
GLOBAL_MATRIX = mtx4_identity
GLOBAL_MATRIX[0][0] = GLOBAL_MATRIX[1][1] = GLOBAL_MATRIX[2][2] = self.properties.TX_SCALE
if self.properties.TX_XROT90: GLOBAL_MATRIX = mtx4_x90n * GLOBAL_MATRIX
if self.properties.TX_YROT90: GLOBAL_MATRIX = mtx4_y90n * GLOBAL_MATRIX
if self.properties.TX_ZROT90: GLOBAL_MATRIX = mtx4_z90n * GLOBAL_MATRIX
write(filepath,
None, # XXX
context,
self.properties.EXP_OBS_SELECTED,
self.properties.EXP_MESH,
self.properties.EXP_MESH_APPLY_MOD,
# self.properties.EXP_MESH_HQ_NORMALS,
self.properties.EXP_ARMATURE,
self.properties.EXP_LAMP,
self.properties.EXP_CAMERA,
self.properties.EXP_EMPTY,
self.properties.EXP_IMAGE_COPY,
GLOBAL_MATRIX,
self.properties.ANIM_ENABLE,
self.properties.ANIM_OPTIMIZE,
self.properties.ANIM_OPTIMIZE_PRECISSION,
self.properties.ANIM_ACTION_ALL,
self.properties.BATCH_ENABLE,
self.properties.BATCH_GROUP,
self.properties.BATCH_FILE_PREFIX,
self.properties.BATCH_OWN_DIR,
)
return {'FINISHED'}
def invoke(self, context, event):
import os
if not self.properties.is_property_set("filepath"):
self.properties.filepath = os.path.splitext(bpy.data.filepath)[0] + ".fbx"
context.manager.add_fileselect(self)
return {'RUNNING_MODAL'}
# if __name__ == "__main__":
# bpy.ops.EXPORT_OT_ply(filepath="/tmp/test.ply")
# NOTES (all line numbers correspond to original export_fbx.py (under release/scripts) # NOTES (all line numbers correspond to original export_fbx.py (under release/scripts)
@@ -3432,21 +3003,3 @@ class ExportFBX(bpy.types.Operator):
# - bpy.sys.time move to bpy.sys.util? # - bpy.sys.time move to bpy.sys.util?
# - new scene creation, activation: lines 327-342, 368 # - new scene creation, activation: lines 327-342, 368
# - uses bpy.path.abspath, *.relpath - replace at least relpath # - uses bpy.path.abspath, *.relpath - replace at least relpath
# SMALL or COSMETICAL
# - find a way to get blender version, and put it in bpy.util?, old was Blender.Get('version')
def menu_func(self, context):
self.layout.operator(ExportFBX.bl_idname, text="Autodesk FBX (.fbx)")
def register():
bpy.types.INFO_MT_file_export.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_export.remove(menu_func)
if __name__ == "__main__":
register()

View File

@@ -0,0 +1,144 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# To support reload properly, try to access a package var, if it's there, reload everything
if "bpy" in locals():
# only reload if we alredy loaded, highly annoying
import sys
reload(sys.modules.get("io_scene_obj.import_obj", sys))
reload(sys.modules.get("io_scene_obj.export_obj", sys))
import bpy
from bpy.props import *
from io_utils import ExportHelper, ImportHelper
class ImportOBJ(bpy.types.Operator, ImportHelper):
'''Load a Wavefront OBJ File'''
bl_idname = "import_scene.obj"
bl_label = "Import OBJ"
filename_ext = ".obj"
CREATE_SMOOTH_GROUPS = BoolProperty(name="Smooth Groups", description="Surround smooth groups by sharp edges", default= True)
CREATE_FGONS = BoolProperty(name="NGons as FGons", description="Import faces with more then 4 verts as fgons", default= True)
CREATE_EDGES = BoolProperty(name="Lines as Edges", description="Import lines and faces with 2 verts as edge", default= True)
SPLIT_OBJECTS = BoolProperty(name="Object", description="Import OBJ Objects into Blender Objects", default= True)
SPLIT_GROUPS = BoolProperty(name="Group", description="Import OBJ Groups into Blender Objects", default= True)
# old comment: only used for user feedback
# disabled this option because in old code a handler for it disabled SPLIT* params, it's not passed to load_obj
# KEEP_VERT_ORDER = BoolProperty(name="Keep Vert Order", description="Keep vert and face order, disables split options, enable for morph targets", default= True)
ROTATE_X90 = BoolProperty(name="-X90", description="Rotate X 90.", default= True)
CLAMP_SIZE = FloatProperty(name="Clamp Scale", description="Clamp the size to this maximum (Zero to Disable)", min=0.0, max=1000.0, soft_min=0.0, soft_max=1000.0, default=0.0)
POLYGROUPS = BoolProperty(name="Poly Groups", description="Import OBJ groups as vertex groups.", default= True)
IMAGE_SEARCH = BoolProperty(name="Image Search", description="Search subdirs for any assosiated images (Warning, may be slow)", default= True)
def execute(self, context):
# print("Selected: " + context.active_object.name)
import io_scene_obj.import_obj
return io_scene_obj.import_obj.load(self, context, **self.properties)
'''
load_obj(self.properties.filepath,
context,
self.properties.CLAMP_SIZE,
self.properties.CREATE_FGONS,
self.properties.CREATE_SMOOTH_GROUPS,
self.properties.CREATE_EDGES,
self.properties.SPLIT_OBJECTS,
self.properties.SPLIT_GROUPS,
self.properties.ROTATE_X90,
self.properties.IMAGE_SEARCH,
self.properties.POLYGROUPS)
'''
return {'FINISHED'}
class ExportOBJ(bpy.types.Operator, ExportHelper):
'''Save a Wavefront OBJ File'''
bl_idname = "export_scene.obj"
bl_label = 'Export OBJ'
filename_ext = ".obj"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
# context group
use_selection = BoolProperty(name="Selection Only", description="Export selected objects only", default= False)
use_all_scenes = BoolProperty(name="All Scenes", description="", default= False)
use_animation = BoolProperty(name="Animation", description="", default= False)
# object group
use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply modifiers (preview resolution)", default= True)
use_rotate_x90 = BoolProperty(name="Rotate X90", description="", default= True)
# extra data group
use_edges = BoolProperty(name="Edges", description="", default=True)
use_normals = BoolProperty(name="Normals", description="", default=False)
use_hq_normals = BoolProperty(name="High Quality Normals", description="", default=True)
use_uvs = BoolProperty(name="UVs", description="", default= True)
use_materials = BoolProperty(name="Materials", description="", default=True)
copy_images = BoolProperty(name="Copy Images", description="", default=False)
use_triangles = BoolProperty(name="Triangulate", description="", default=False)
use_vertex_groups = BoolProperty(name="Polygroups", description="", default=False)
use_nurbs = BoolProperty(name="Nurbs", description="", default=False)
# grouping group
use_blen_objects = BoolProperty(name="Objects as OBJ Objects", description="", default= True)
group_by_object = BoolProperty(name="Objects as OBJ Groups ", description="", default= False)
group_by_material = BoolProperty(name="Material Groups", description="", default= False)
keep_vertex_order = BoolProperty(name="Keep Vertex Order", description="", default= False)
def execute(self, context):
import io_scene_obj.export_obj
print(self.properties.keys())
return io_scene_obj.export_obj.save(self, context, **self.properties)
def menu_func_import(self, context):
self.layout.operator(ImportOBJ.bl_idname, text="Wavefront (.obj)")
def menu_func_export(self, context):
self.layout.operator(ExportOBJ.bl_idname, text="Wavefront (.obj)")
def register():
bpy.types.INFO_MT_file_import.append(menu_func_import)
bpy.types.INFO_MT_file_export.append(menu_func_export)
def unregister():
bpy.types.INFO_MT_file_import.remove(menu_func_import)
bpy.types.INFO_MT_file_export.remove(menu_func_export)
# CONVERSION ISSUES
# - matrix problem
# - duplis - only tested dupliverts
# - all scenes export
# + normals calculation
if __name__ == "__main__":
register()

View File

@@ -18,23 +18,6 @@
# <pep8 compliant> # <pep8 compliant>
__author__ = "Campbell Barton, Jiri Hnidek, Paolo Ciccone"
__url__ = ['http://wiki.blender.org/index.php/Scripts/Manual/Export/wavefront_obj', 'www.blender.org', 'blenderartists.org']
__version__ = "1.21"
__bpydoc__ = """\
This script is an exporter to OBJ file format.
Usage:
Select the objects you wish to export and run this script from "File->Export" menu.
Selecting the default options from the popup box will be good in most cases.
All objects that can be represented as a mesh (mesh, curve, metaball, surface, text3d)
will be exported as mesh data.
"""
# import math and other in functions that use them for the sake of fast Blender startup
# import math
import os import os
import time import time
import shutil import shutil
@@ -122,7 +105,7 @@ def write_mtl(scene, filepath, copy_images, mtl_dict):
try: try:
filepath = copy_image(mtex.texture.image) filepath = copy_image(mtex.texture.image)
# filepath = mtex.texture.image.filepath.split('\\')[-1].split('/')[-1] # filepath = mtex.texture.image.filepath.split('\\')[-1].split('/')[-1]
file.write('map_Kd %s\n' % filepath) # Diffuse mapping image file.write('map_Kd %s\n' % repr(filepath)[1:-1]) # Diffuse mapping image
break break
except: except:
# Texture has no image though its an image type, best ignore. # Texture has no image though its an image type, best ignore.
@@ -332,7 +315,7 @@ def write_file(filepath, objects, scene,
return ret return ret
print('OBJ Export path: "%s"' % filepath) print('OBJ Export path: %r' % filepath)
temp_mesh_name = '~tmp-mesh' temp_mesh_name = '~tmp-mesh'
time1 = time.clock() time1 = time.clock()
@@ -342,13 +325,13 @@ def write_file(filepath, objects, scene,
file = open(filepath, "w") file = open(filepath, "w")
# Write Header # Write Header
file.write('# Blender v%s OBJ File: %s\n' % (bpy.app.version_string, bpy.data.filepath.split('/')[-1].split('\\')[-1] )) file.write('# Blender v%s OBJ File: %r\n' % (bpy.app.version_string, os.path.basename(bpy.data.filepath)))
file.write('# www.blender.org\n') file.write('# www.blender.org\n')
# Tell the obj file what material file to use. # Tell the obj file what material file to use.
if EXPORT_MTL: if EXPORT_MTL:
mtlfilepath = '%s.mtl' % '.'.join(filepath.split('.')[:-1]) mtlfilepath = os.path.splitext(filepath)[0] + ".mtl"
file.write('mtllib %s\n' % ( mtlfilepath.split('\\')[-1].split('/')[-1] )) file.write('mtllib %s\n' % repr(os.path.basename(mtlfilepath))[1:-1]) # filepath can contain non utf8 chars, use repr
if EXPORT_ROTX90: if EXPORT_ROTX90:
mat_xrot90= mathutils.Matrix.Rotation(-math.pi/2, 4, 'X') mat_xrot90= mathutils.Matrix.Rotation(-math.pi/2, 4, 'X')
@@ -751,7 +734,8 @@ def write_file(filepath, objects, scene,
print("OBJ Export time: %.2f" % (time.clock() - time1)) print("OBJ Export time: %.2f" % (time.clock() - time1))
def write(filepath, context, #
def _write(context, filepath,
EXPORT_TRI, # ok EXPORT_TRI, # ok
EXPORT_EDGES, EXPORT_EDGES,
EXPORT_NORMALS, # not yet EXPORT_NORMALS, # not yet
@@ -777,7 +761,7 @@ def write(filepath, context,
orig_scene = context.scene orig_scene = context.scene
# Exit edit mode before exporting, so current object states are exported properly. # Exit edit mode before exporting, so current object states are exported properly.
if context.object: if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='OBJECT')
# if EXPORT_ALL_SCENES: # if EXPORT_ALL_SCENES:
@@ -848,105 +832,51 @@ def write(filepath, context,
''' '''
Currently the exporter lacks these features: Currently the exporter lacks these features:
* nurbs
* multiple scene export (only active scene is written) * multiple scene export (only active scene is written)
* particles * particles
''' '''
from bpy.props import *
class ExportOBJ(bpy.types.Operator): def save(operator, context, filepath="",
'''Save a Wavefront OBJ File''' use_triangles=False,
use_edges=False,
use_normals=False,
use_hq_normals=False,
use_uvs=True,
use_materials=True,
copy_images=False,
use_modifiers=True,
use_rotate_x90=True,
use_blen_objects=True,
group_by_object=False,
group_by_material=False,
keep_vertex_order=False,
use_vertex_groups=False,
use_nurbs=True,
use_selection=True,
use_all_scenes=False,
use_animation=False,
):
bl_idname = "export.obj" _write(context, filepath,
bl_label = 'Export OBJ' EXPORT_TRI=use_triangles,
EXPORT_EDGES=use_edges,
EXPORT_NORMALS=use_normals,
EXPORT_NORMALS_HQ=use_hq_normals,
EXPORT_UV=use_uvs,
EXPORT_MTL=use_materials,
EXPORT_COPY_IMAGES=copy_images,
EXPORT_APPLY_MODIFIERS=use_modifiers,
EXPORT_ROTX90=use_rotate_x90,
EXPORT_BLEN_OBS=use_blen_objects,
EXPORT_GROUP_BY_OB=group_by_object,
EXPORT_GROUP_BY_MAT=group_by_material,
EXPORT_KEEP_VERT_ORDER=keep_vertex_order,
EXPORT_POLYGROUPS=use_vertex_groups,
EXPORT_CURVE_AS_NURBS=use_nurbs,
EXPORT_SEL_ONLY=use_selection,
EXPORT_ALL_SCENES=use_all_scenes,
EXPORT_ANIMATION=use_animation,
)
# List of operator properties, the attributes will be assigned return {'FINISHED'}
# to the class instance from the operator settings before calling.
filepath = StringProperty(name="File Path", description="Filepath used for exporting the OBJ file", maxlen= 1024, default= "")
check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'})
# context group
use_selection = BoolProperty(name="Selection Only", description="Export selected objects only", default= False)
use_all_scenes = BoolProperty(name="All Scenes", description="", default= False)
use_animation = BoolProperty(name="Animation", description="", default= False)
# object group
use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply modifiers (preview resolution)", default= True)
use_rotate90 = BoolProperty(name="Rotate X90", description="", default= True)
# extra data group
use_edges = BoolProperty(name="Edges", description="", default=True)
use_normals = BoolProperty(name="Normals", description="", default=False)
use_hq_normals = BoolProperty(name="High Quality Normals", description="", default=True)
use_uvs = BoolProperty(name="UVs", description="", default= True)
use_materials = BoolProperty(name="Materials", description="", default=True)
copy_images = BoolProperty(name="Copy Images", description="", default=False)
use_triangles = BoolProperty(name="Triangulate", description="", default=False)
use_vertex_groups = BoolProperty(name="Polygroups", description="", default=False)
use_nurbs = BoolProperty(name="Nurbs", description="", default=False)
# grouping group
use_blen_objects = BoolProperty(name="Objects as OBJ Objects", description="", default= True)
group_by_object = BoolProperty(name="Objects as OBJ Groups ", description="", default= False)
group_by_material = BoolProperty(name="Material Groups", description="", default= False)
keep_vertex_order = BoolProperty(name="Keep Vertex Order", description="", default= False)
def execute(self, context):
filepath = self.properties.filepath
filepath = bpy.path.ensure_ext(filepath, ".obj")
write(filepath, context,
EXPORT_TRI=self.properties.use_triangles,
EXPORT_EDGES=self.properties.use_edges,
EXPORT_NORMALS=self.properties.use_normals,
EXPORT_NORMALS_HQ=self.properties.use_hq_normals,
EXPORT_UV=self.properties.use_uvs,
EXPORT_MTL=self.properties.use_materials,
EXPORT_COPY_IMAGES=self.properties.copy_images,
EXPORT_APPLY_MODIFIERS=self.properties.use_modifiers,
EXPORT_ROTX90=self.properties.use_rotate90,
EXPORT_BLEN_OBS=self.properties.use_blen_objects,
EXPORT_GROUP_BY_OB=self.properties.group_by_object,
EXPORT_GROUP_BY_MAT=self.properties.group_by_material,
EXPORT_KEEP_VERT_ORDER=self.properties.keep_vertex_order,
EXPORT_POLYGROUPS=self.properties.use_vertex_groups,
EXPORT_CURVE_AS_NURBS=self.properties.use_nurbs,
EXPORT_SEL_ONLY=self.properties.use_selection,
EXPORT_ALL_SCENES=self.properties.use_all_scenes,
EXPORT_ANIMATION=self.properties.use_animation)
return {'FINISHED'}
def invoke(self, context, event):
import os
if not self.properties.is_property_set("filepath"):
self.properties.filepath = os.path.splitext(bpy.data.filepath)[0] + ".obj"
context.manager.add_fileselect(self)
return {'RUNNING_MODAL'}
def menu_func(self, context):
self.layout.operator(ExportOBJ.bl_idname, text="Wavefront (.obj)")
def register():
bpy.types.INFO_MT_file_export.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_export.remove(menu_func)
# CONVERSION ISSUES
# - matrix problem
# - duplis - only tested dupliverts
# - NURBS - needs API additions
# - all scenes export
# + normals calculation
if __name__ == "__main__":
register()

View File

@@ -18,16 +18,17 @@
# <pep8 compliant> # <pep8 compliant>
__author__= "Campbell Barton", "Jiri Hnidek", "Paolo Ciccone" # Script copyright (C) Campbell Barton
__url__= ['http://wiki.blender.org/index.php/Scripts/Manual/Import/wavefront_obj', 'blender.org', 'blenderartists.org'] # Contributors: Campbell Barton, Jiri Hnidek, Paolo Ciccone
__version__= "2.11"
__bpydoc__= """\ """
This script imports a Wavefront OBJ files to Blender. This script imports a Wavefront OBJ files to Blender.
Usage: Usage:
Run this script from "File->Import" menu and then load the desired OBJ file. Run this script from "File->Import" menu and then load the desired OBJ file.
Note, This loads mesh objects and materials only, nurbs and curves are not supported. Note, This loads mesh objects and materials only, nurbs and curves are not supported.
http://wiki.blender.org/index.php/Scripts/Manual/Import/wavefront_obj
""" """
import os import os
@@ -35,30 +36,8 @@ import time
import bpy import bpy
import mathutils import mathutils
from geometry import PolyFill from geometry import PolyFill
from io_utils import load_image, unpack_list, unpack_face_list
def unpack_list(list_of_tuples):
l = []
for t in list_of_tuples:
l.extend(t)
return l
# same as above except that it adds 0 for triangle faces
def unpack_face_list(list_of_tuples):
# allocate the entire list
flat_ls = [0] * (len(list_of_tuples) * 4)
i = 0
for t in list_of_tuples:
if len(t) == 3:
if t[2] == 0:
t = t[1], t[2], t[0]
else: # assuem quad
if t[3] == 0 or t[2] == 0:
t = t[2], t[3], t[0], t[1]
flat_ls[i:i + len(t)] = t
i += 4
return flat_ls
def BPyMesh_ngon(from_data, indices, PREF_FIX_LOOPS= True): def BPyMesh_ngon(from_data, indices, PREF_FIX_LOOPS= True):
''' '''
@@ -78,7 +57,7 @@ def BPyMesh_ngon(from_data, indices, PREF_FIX_LOOPS= True):
if not indices: if not indices:
return [] return []
# return [] # return []
def rvec(co): return round(co.x, 6), round(co.y, 6), round(co.z, 6) def rvec(co): return round(co.x, 6), round(co.y, 6), round(co.z, 6)
def mlen(co): return abs(co[0])+abs(co[1])+abs(co[2]) # manhatten length of a vector, faster then length def mlen(co): return abs(co[0])+abs(co[1])+abs(co[2]) # manhatten length of a vector, faster then length
@@ -259,21 +238,6 @@ def line_value(line_split):
elif length > 2: elif length > 2:
return ' '.join( line_split[1:] ) return ' '.join( line_split[1:] )
# limited replacement for BPyImage.comprehensiveImageLoad
def load_image(imagepath, dirname):
if os.path.exists(imagepath):
return bpy.data.images.load(imagepath)
variants = [imagepath, os.path.join(dirname, imagepath), os.path.join(dirname, os.path.basename(imagepath))]
for filepath in variants:
for nfilepath in (filepath, bpy.path.resolve_ncase(filepath)):
if os.path.exists(nfilepath):
return bpy.data.images.load(nfilepath)
# TODO comprehensiveImageLoad also searched in bpy.config.textureDir
return None
def obj_image_load(imagepath, DIR, IMAGE_SEARCH): def obj_image_load(imagepath, DIR, IMAGE_SEARCH):
if '_' in imagepath: if '_' in imagepath:
@@ -289,21 +253,21 @@ def obj_image_load(imagepath, DIR, IMAGE_SEARCH):
return None return None
# def obj_image_load(imagepath, DIR, IMAGE_SEARCH): # def obj_image_load(imagepath, DIR, IMAGE_SEARCH):
# ''' # '''
# Mainly uses comprehensiveImageLoad # Mainly uses comprehensiveImageLoad
# but tries to replace '_' with ' ' for Max's exporter replaces spaces with underscores. # but tries to replace '_' with ' ' for Max's exporter replaces spaces with underscores.
# ''' # '''
# if '_' in imagepath: # if '_' in imagepath:
# image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH) # image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH)
# if image: return image # if image: return image
# # Did the exporter rename the image? # # Did the exporter rename the image?
# image= BPyImage.comprehensiveImageLoad(imagepath.replace('_', ' '), DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH) # image= BPyImage.comprehensiveImageLoad(imagepath.replace('_', ' '), DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH)
# if image: return image # if image: return image
# # Return an image, placeholder if it dosnt exist # # Return an image, placeholder if it dosnt exist
# image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= True, RECURSIVE= IMAGE_SEARCH) # image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= True, RECURSIVE= IMAGE_SEARCH)
# return image # return image
def create_materials(filepath, material_libs, unique_materials, unique_material_images, IMAGE_SEARCH): def create_materials(filepath, material_libs, unique_materials, unique_material_images, IMAGE_SEARCH):
@@ -334,42 +298,65 @@ def create_materials(filepath, material_libs, unique_materials, unique_material_
# Image has alpha # Image has alpha
# XXX bitmask won't work? # XXX bitmask won't work?
blender_material.add_texture(texture, 'UV', {'COLOR', 'ALPHA'}) mtex = blender_material.texture_slots.add()
mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use_map_color_diffuse = True
mtex.use_map_alpha = True
texture.mipmap = True texture.mipmap = True
texture.interpolation = True texture.interpolation = True
texture.use_alpha = True texture.use_alpha = True
blender_material.use_transparency = True blender_material.use_transparency = True
blender_material.alpha = 0.0 blender_material.alpha = 0.0
else: else:
blender_material.add_texture(texture, 'UV', 'COLOR') mtex = blender_material.texture_slots.add()
mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use_map_color_diffuse = True
# adds textures to faces (Textured/Alt-Z mode) # adds textures to faces (Textured/Alt-Z mode)
# Only apply the diffuse texture to the face if the image has not been set with the inline usemat func. # Only apply the diffuse texture to the face if the image has not been set with the inline usemat func.
unique_material_images[context_material_name]= image, has_data # set the texface image unique_material_images[context_material_name]= image, has_data # set the texface image
elif type == 'Ka': elif type == 'Ka':
blender_material.add_texture(texture, 'UV', 'AMBIENT') mtex = blender_material.texture_slots.add()
# blender_material.setTexture(1, texture, Texture.TexCo.UV, Texture.MapTo.CMIR) # TODO- Add AMB to BPY API mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use_map_ambient = True
# blender_material.setTexture(1, texture, Texture.TexCo.UV, Texture.MapTo.CMIR) # TODO- Add AMB to BPY API
elif type == 'Ks': elif type == 'Ks':
blender_material.add_texture(texture, 'UV', 'SPECULARITY') mtex = blender_material.texture_slots.add()
# blender_material.setTexture(2, texture, Texture.TexCo.UV, Texture.MapTo.SPEC) mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use_map_specular = True
# blender_material.setTexture(2, texture, Texture.TexCo.UV, Texture.MapTo.SPEC)
elif type == 'Bump': elif type == 'Bump':
blender_material.add_texture(texture, 'UV', 'NORMAL') mtex = blender_material.texture_slots.add()
# blender_material.setTexture(3, texture, Texture.TexCo.UV, Texture.MapTo.NOR) mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use_map_normal = True
# blender_material.setTexture(3, texture, Texture.TexCo.UV, Texture.MapTo.NOR)
elif type == 'D': elif type == 'D':
blender_material.add_texture(texture, 'UV', 'ALPHA') mtex = blender_material.texture_slots.add()
mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use_map_alpha = True
blender_material.z_transparency = True blender_material.z_transparency = True
blender_material.alpha = 0.0 blender_material.alpha = 0.0
# blender_material.setTexture(4, texture, Texture.TexCo.UV, Texture.MapTo.ALPHA) # blender_material.setTexture(4, texture, Texture.TexCo.UV, Texture.MapTo.ALPHA)
# blender_material.mode |= Material.Modes.ZTRANSP # blender_material.mode |= Material.Modes.ZTRANSP
# blender_material.alpha = 0.0 # blender_material.alpha = 0.0
# Todo, unset deffuse material alpha if it has an alpha channel # Todo, unset deffuse material alpha if it has an alpha channel
elif type == 'refl': elif type == 'refl':
blender_material.add_texture(texture, 'UV', 'REFLECTION') mtex = blender_material.texture_slots.add()
# blender_material.setTexture(5, texture, Texture.TexCo.UV, Texture.MapTo.REF) mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use_map_reflect = True
# blender_material.setTexture(5, texture, Texture.TexCo.UV, Texture.MapTo.REF)
# Add an MTL with the same name as the obj if no MTLs are spesified. # Add an MTL with the same name as the obj if no MTLs are spesified.
@@ -629,7 +616,7 @@ def create_mesh(new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, v
# make sure the list isnt too big # make sure the list isnt too big
for material in materials: for material in materials:
me.materials.link(material) me.materials.append(material)
me.vertices.add(len(verts_loc)) me.vertices.add(len(verts_loc))
me.faces.add(len(faces)) me.faces.add(len(faces))
@@ -676,7 +663,7 @@ def create_mesh(new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, v
context_material_old= context_material context_material_old= context_material
blender_face.material_index= mat blender_face.material_index= mat
# blender_face.mat= mat # blender_face.mat= mat
if verts_tex: if verts_tex:
@@ -708,10 +695,10 @@ def create_mesh(new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, v
if len(face_vert_loc_indicies)==4: if len(face_vert_loc_indicies)==4:
blender_tface.uv4= verts_tex[face_vert_tex_indicies[3]] blender_tface.uv4= verts_tex[face_vert_tex_indicies[3]]
# for ii, uv in enumerate(blender_face.uv): # for ii, uv in enumerate(blender_face.uv):
# uv.x, uv.y= verts_tex[face_vert_tex_indicies[ii]] # uv.x, uv.y= verts_tex[face_vert_tex_indicies[ii]]
del me_faces del me_faces
# del ALPHA # del ALPHA
if CREATE_EDGES: if CREATE_EDGES:
@@ -719,46 +706,46 @@ def create_mesh(new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, v
# edges should be a list of (a, b) tuples # edges should be a list of (a, b) tuples
me.edges.foreach_set("vertices", unpack_list(edges)) me.edges.foreach_set("vertices", unpack_list(edges))
# me_edges.extend( edges ) # me_edges.extend( edges )
# del me_edges # del me_edges
# Add edge faces. # Add edge faces.
# me_edges= me.edges # me_edges= me.edges
def edges_match(e1, e2): def edges_match(e1, e2):
return (e1[0] == e2[0] and e1[1] == e2[1]) or (e1[0] == e2[1] and e1[1] == e2[0]) return (e1[0] == e2[0] and e1[1] == e2[1]) or (e1[0] == e2[1] and e1[1] == e2[0])
# XXX slow # XXX slow
# if CREATE_FGONS and fgon_edges: # if CREATE_FGONS and fgon_edges:
# for fgon_edge in fgon_edges.keys(): # for fgon_edge in fgon_edges.keys():
# for ed in me.edges: # for ed in me.edges:
# if edges_match(fgon_edge, ed.vertices): # if edges_match(fgon_edge, ed.vertices):
# ed.is_fgon = True # ed.is_fgon = True
# if CREATE_FGONS and fgon_edges: # if CREATE_FGONS and fgon_edges:
# FGON= Mesh.EdgeFlags.FGON # FGON= Mesh.EdgeFlags.FGON
# for ed in me.findEdges( fgon_edges.keys() ): # for ed in me.findEdges( fgon_edges.keys() ):
# if ed!=None: # if ed!=None:
# me_edges[ed].flag |= FGON # me_edges[ed].flag |= FGON
# del FGON # del FGON
# XXX slow # XXX slow
# if unique_smooth_groups and sharp_edges: # if unique_smooth_groups and sharp_edges:
# for sharp_edge in sharp_edges.keys(): # for sharp_edge in sharp_edges.keys():
# for ed in me.edges: # for ed in me.edges:
# if edges_match(sharp_edge, ed.vertices): # if edges_match(sharp_edge, ed.vertices):
# ed.use_edge_sharp = True # ed.use_edge_sharp = True
# if unique_smooth_groups and sharp_edges: # if unique_smooth_groups and sharp_edges:
# SHARP= Mesh.EdgeFlags.SHARP # SHARP= Mesh.EdgeFlags.SHARP
# for ed in me.findEdges( sharp_edges.keys() ): # for ed in me.findEdges( sharp_edges.keys() ):
# if ed!=None: # if ed!=None:
# me_edges[ed].flag |= SHARP # me_edges[ed].flag |= SHARP
# del SHARP # del SHARP
me.update() me.update()
# me.calcNormals() # me.calcNormals()
ob= bpy.data.objects.new("Mesh", me) ob= bpy.data.objects.new("Mesh", me)
new_objects.append(ob) new_objects.append(ob)
@@ -768,8 +755,7 @@ def create_mesh(new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, v
# the following test will never run # the following test will never run
for group_name, group_indicies in vertex_groups.items(): for group_name, group_indicies in vertex_groups.items():
group= ob.vertex_groups.new(group_name) group= ob.vertex_groups.new(group_name)
for vertex_index in group_indicies: ob.vertex_groups.assign(group_indicies, group, 1.0, 'REPLACE')
ob.vertex_groups.assign(vertex_index, group, 1.0, 'REPLACE')
def create_nurbs(context_nurbs, vert_loc, new_objects): def create_nurbs(context_nurbs, vert_loc, new_objects):
@@ -860,7 +846,7 @@ def strip_slash(line_split):
def get_float_func(filepath): def get_float_func(filepath):
''' '''
find the float function for this obj file find the float function for this obj file
- weather to replace commas or not - whether to replace commas or not
''' '''
file= open(filepath, 'rU') file= open(filepath, 'rU')
for line in file: #.xreadlines(): for line in file: #.xreadlines():
@@ -874,31 +860,29 @@ def get_float_func(filepath):
# incase all vert values were ints # incase all vert values were ints
return float return float
def load_obj(filepath, def load(operator, context, filepath,
context, CLAMP_SIZE= 0.0,
CLAMP_SIZE= 0.0, CREATE_FGONS= True,
CREATE_FGONS= True, CREATE_SMOOTH_GROUPS= True,
CREATE_SMOOTH_GROUPS= True, CREATE_EDGES= True,
CREATE_EDGES= True, SPLIT_OBJECTS= True,
SPLIT_OBJECTS= True, SPLIT_GROUPS= True,
SPLIT_GROUPS= True, ROTATE_X90= True,
SPLIT_MATERIALS= True, IMAGE_SEARCH=True,
ROTATE_X90= True, POLYGROUPS=False):
IMAGE_SEARCH=True,
POLYGROUPS=False):
''' '''
Called by the user interface or another script. Called by the user interface or another script.
load_obj(path) - should give acceptable results. load_obj(path) - should give acceptable results.
This function passes the file and sends the data off This function passes the file and sends the data off
to be split into objects and then converted into mesh objects to be split into objects and then converted into mesh objects
''' '''
print('\nimporting obj "%s"' % filepath) print('\nimporting obj %r' % filepath)
if SPLIT_OBJECTS or SPLIT_GROUPS or SPLIT_MATERIALS: if SPLIT_OBJECTS or SPLIT_GROUPS:
POLYGROUPS = False POLYGROUPS = False
time_main= time.time() time_main= time.time()
# time_main= sys.time() # time_main= sys.time()
verts_loc= [] verts_loc= []
verts_tex= [] verts_tex= []
@@ -932,12 +916,12 @@ def load_obj(filepath,
# when there are faces that end with \ # when there are faces that end with \
# it means they are multiline- # it means they are multiline-
# since we use xreadline we cant skip to the next line # since we use xreadline we cant skip to the next line
# so we need to know weather # so we need to know whether
context_multi_line= '' context_multi_line= ''
print('\tparsing obj file "%s"...' % filepath) print("\tparsing obj file...")
time_sub= time.time() time_sub= time.time()
# time_sub= sys.time() # time_sub= sys.time()
file= open(filepath, 'rU') file= open(filepath, 'rU')
for line in file: #.xreadlines(): for line in file: #.xreadlines():
@@ -988,7 +972,7 @@ def load_obj(filepath,
vert_loc_index= int(obj_vert[0])-1 vert_loc_index= int(obj_vert[0])-1
# Add the vertex to the current group # Add the vertex to the current group
# *warning*, this wont work for files that have groups defined around verts # *warning*, this wont work for files that have groups defined around verts
if POLYGROUPS and context_vgroup: if POLYGROUPS and context_vgroup:
vertex_groups[context_vgroup].append(vert_loc_index) vertex_groups[context_vgroup].append(vert_loc_index)
# Make relative negative vert indicies absolute # Make relative negative vert indicies absolute
@@ -1080,8 +1064,7 @@ def load_obj(filepath,
context_material= line_value(line.split()) context_material= line_value(line.split())
unique_materials[context_material]= None unique_materials[context_material]= None
elif line.startswith('mtllib'): # usemap or usemat elif line.startswith('mtllib'): # usemap or usemat
material_libs.extend( line.split()[1:] ) # can have multiple mtllib filenames per line material_libs = list(set(material_libs) | set(line.split()[1:])) # can have multiple mtllib filenames per line, mtllib can appear more than once, so make sure only occurance of material exists
# Nurbs support # Nurbs support
elif line.startswith('cstype '): elif line.startswith('cstype '):
@@ -1146,7 +1129,7 @@ def load_obj(filepath,
file.close() file.close()
time_new= time.time() time_new= time.time()
# time_new= sys.time() # time_new= sys.time()
print('%.4f sec' % (time_new-time_sub)) print('%.4f sec' % (time_new-time_sub))
time_sub= time_new time_sub= time_new
@@ -1155,7 +1138,7 @@ def load_obj(filepath,
create_materials(filepath, material_libs, unique_materials, unique_material_images, IMAGE_SEARCH) create_materials(filepath, material_libs, unique_materials, unique_material_images, IMAGE_SEARCH)
time_new= time.time() time_new= time.time()
# time_new= sys.time() # time_new= sys.time()
print('%.4f sec' % (time_new-time_sub)) print('%.4f sec' % (time_new-time_sub))
time_sub= time_new time_sub= time_new
@@ -1166,13 +1149,13 @@ def load_obj(filepath,
bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_all(action='DESELECT')
scene = context.scene scene = context.scene
# scn.objects.selected = [] # scn.objects.selected = []
new_objects= [] # put new objects here new_objects= [] # put new objects here
print('\tbuilding geometry...\n\tverts:%i faces:%i materials: %i smoothgroups:%i ...' % ( len(verts_loc), len(faces), len(unique_materials), len(unique_smooth_groups) )) print('\tbuilding geometry...\n\tverts:%i faces:%i materials: %i smoothgroups:%i ...' % ( len(verts_loc), len(faces), len(unique_materials), len(unique_smooth_groups) ))
# Split the mesh by objects/materials, may # Split the mesh by objects/materials, may
if SPLIT_OBJECTS or SPLIT_GROUPS: SPLIT_OB_OR_GROUP = True if SPLIT_OBJECTS or SPLIT_GROUPS: SPLIT_OB_OR_GROUP = True
else: SPLIT_OB_OR_GROUP = False else: SPLIT_OB_OR_GROUP = False
for verts_loc_split, faces_split, unique_materials_split, dataname in split_mesh(verts_loc, faces, unique_materials, filepath, SPLIT_OB_OR_GROUP): for verts_loc_split, faces_split, unique_materials_split, dataname in split_mesh(verts_loc, faces, unique_materials, filepath, SPLIT_OB_OR_GROUP):
# Create meshes from the data, warning 'vertex_groups' wont support splitting # Create meshes from the data, warning 'vertex_groups' wont support splitting
@@ -1193,327 +1176,34 @@ def load_obj(filepath,
axis_min= [ 1000000000]*3 axis_min= [ 1000000000]*3
axis_max= [-1000000000]*3 axis_max= [-1000000000]*3
# if CLAMP_SIZE: # if CLAMP_SIZE:
# # Get all object bounds # # Get all object bounds
# for ob in new_objects: # for ob in new_objects:
# for v in ob.getBoundBox(): # for v in ob.getBoundBox():
# for axis, value in enumerate(v): # for axis, value in enumerate(v):
# if axis_min[axis] > value: axis_min[axis]= value # if axis_min[axis] > value: axis_min[axis]= value
# if axis_max[axis] < value: axis_max[axis]= value # if axis_max[axis] < value: axis_max[axis]= value
# # Scale objects # # Scale objects
# max_axis= max(axis_max[0]-axis_min[0], axis_max[1]-axis_min[1], axis_max[2]-axis_min[2]) # max_axis= max(axis_max[0]-axis_min[0], axis_max[1]-axis_min[1], axis_max[2]-axis_min[2])
# scale= 1.0 # scale= 1.0
# while CLAMP_SIZE < max_axis * scale: # while CLAMP_SIZE < max_axis * scale:
# scale= scale/10.0 # scale= scale/10.0
# for ob in new_objects: # for ob in new_objects:
# ob.setSize(scale, scale, scale) # ob.setSize(scale, scale, scale)
# Better rotate the vert locations # Better rotate the vert locations
#if not ROTATE_X90: #if not ROTATE_X90:
# for ob in new_objects: # for ob in new_objects:
# ob.RotX = -1.570796326794896558 # ob.RotX = -1.570796326794896558
time_new= time.time() time_new= time.time()
# time_new= sys.time() # time_new= sys.time()
print('%.4f sec' % (time_new-time_sub)) print('finished importing: %r in %.4f sec.' % (filepath, (time_new-time_main)))
print('finished importing: "%s" in %.4f sec.' % (filepath, (time_new-time_main))) return {'FINISHED'}
DEBUG= True
def load_obj_ui(filepath, BATCH_LOAD= False):
if BPyMessages.Error_NoFile(filepath):
return
global CREATE_SMOOTH_GROUPS, CREATE_FGONS, CREATE_EDGES, SPLIT_OBJECTS, SPLIT_GROUPS, CLAMP_SIZE, IMAGE_SEARCH, POLYGROUPS, KEEP_VERT_ORDER, ROTATE_X90
CREATE_SMOOTH_GROUPS= Draw.Create(0)
CREATE_FGONS= Draw.Create(1)
CREATE_EDGES= Draw.Create(1)
SPLIT_OBJECTS= Draw.Create(0)
SPLIT_GROUPS= Draw.Create(0)
CLAMP_SIZE= Draw.Create(10.0)
IMAGE_SEARCH= Draw.Create(1)
POLYGROUPS= Draw.Create(0)
KEEP_VERT_ORDER= Draw.Create(1)
ROTATE_X90= Draw.Create(1)
# Get USER Options
# Note, Works but not pretty, instead use a more complicated GUI
'''
pup_block= [\
'Import...',\
('Smooth Groups', CREATE_SMOOTH_GROUPS, 'Surround smooth groups by sharp edges'),\
('Create FGons', CREATE_FGONS, 'Import faces with more then 4 verts as fgons.'),\
('Lines', CREATE_EDGES, 'Import lines and faces with 2 verts as edges'),\
'Separate objects from obj...',\
('Object', SPLIT_OBJECTS, 'Import OBJ Objects into Blender Objects'),\
('Group', SPLIT_GROUPS, 'Import OBJ Groups into Blender Objects'),\
'Options...',\
('Keep Vert Order', KEEP_VERT_ORDER, 'Keep vert and face order, disables some other options.'),\
('Clamp Scale:', CLAMP_SIZE, 0.0, 1000.0, 'Clamp the size to this maximum (Zero to Disable)'),\
('Image Search', IMAGE_SEARCH, 'Search subdirs for any assosiated images (Warning, may be slow)'),\
]
if not Draw.PupBlock('Import OBJ...', pup_block):
return
if KEEP_VERT_ORDER.val:
SPLIT_OBJECTS.val = False
SPLIT_GROUPS.val = False
'''
# BEGIN ALTERNATIVE UI *******************
if True:
EVENT_NONE = 0
EVENT_EXIT = 1
EVENT_REDRAW = 2
EVENT_IMPORT = 3
GLOBALS = {}
GLOBALS['EVENT'] = EVENT_REDRAW
#GLOBALS['MOUSE'] = Window.GetMouseCoords()
GLOBALS['MOUSE'] = [i/2 for i in Window.GetScreenSize()]
def obj_ui_set_event(e,v):
GLOBALS['EVENT'] = e
def do_split(e,v):
global SPLIT_OBJECTS, SPLIT_GROUPS, KEEP_VERT_ORDER, POLYGROUPS
if SPLIT_OBJECTS.val or SPLIT_GROUPS.val:
KEEP_VERT_ORDER.val = 0
POLYGROUPS.val = 0
else:
KEEP_VERT_ORDER.val = 1
def do_vertorder(e,v):
global SPLIT_OBJECTS, SPLIT_GROUPS, KEEP_VERT_ORDER
if KEEP_VERT_ORDER.val:
SPLIT_OBJECTS.val = SPLIT_GROUPS.val = 0
else:
if not (SPLIT_OBJECTS.val or SPLIT_GROUPS.val):
KEEP_VERT_ORDER.val = 1
def do_polygroups(e,v):
global SPLIT_OBJECTS, SPLIT_GROUPS, KEEP_VERT_ORDER, POLYGROUPS
if POLYGROUPS.val:
SPLIT_OBJECTS.val = SPLIT_GROUPS.val = 0
def do_help(e,v):
url = __url__[0]
print('Trying to open web browser with documentation at this address...')
print('\t' + url)
try:
import webbrowser
webbrowser.open(url)
except:
print('...could not open a browser window.')
def obj_ui():
ui_x, ui_y = GLOBALS['MOUSE']
# Center based on overall pup size
ui_x -= 165
ui_y -= 90
global CREATE_SMOOTH_GROUPS, CREATE_FGONS, CREATE_EDGES, SPLIT_OBJECTS, SPLIT_GROUPS, CLAMP_SIZE, IMAGE_SEARCH, POLYGROUPS, KEEP_VERT_ORDER, ROTATE_X90
Draw.Label('Import...', ui_x+9, ui_y+159, 220, 21)
Draw.BeginAlign()
CREATE_SMOOTH_GROUPS = Draw.Toggle('Smooth Groups', EVENT_NONE, ui_x+9, ui_y+139, 110, 20, CREATE_SMOOTH_GROUPS.val, 'Surround smooth groups by sharp edges')
CREATE_FGONS = Draw.Toggle('NGons as FGons', EVENT_NONE, ui_x+119, ui_y+139, 110, 20, CREATE_FGONS.val, 'Import faces with more then 4 verts as fgons')
CREATE_EDGES = Draw.Toggle('Lines as Edges', EVENT_NONE, ui_x+229, ui_y+139, 110, 20, CREATE_EDGES.val, 'Import lines and faces with 2 verts as edges')
Draw.EndAlign()
Draw.Label('Separate objects by OBJ...', ui_x+9, ui_y+110, 220, 20)
Draw.BeginAlign()
SPLIT_OBJECTS = Draw.Toggle('Object', EVENT_REDRAW, ui_x+9, ui_y+89, 55, 21, SPLIT_OBJECTS.val, 'Import OBJ Objects into Blender Objects', do_split)
SPLIT_GROUPS = Draw.Toggle('Group', EVENT_REDRAW, ui_x+64, ui_y+89, 55, 21, SPLIT_GROUPS.val, 'Import OBJ Groups into Blender Objects', do_split)
Draw.EndAlign()
# Only used for user feedback
KEEP_VERT_ORDER = Draw.Toggle('Keep Vert Order', EVENT_REDRAW, ui_x+184, ui_y+89, 113, 21, KEEP_VERT_ORDER.val, 'Keep vert and face order, disables split options, enable for morph targets', do_vertorder)
ROTATE_X90 = Draw.Toggle('-X90', EVENT_REDRAW, ui_x+302, ui_y+89, 38, 21, ROTATE_X90.val, 'Rotate X 90.')
Draw.Label('Options...', ui_x+9, ui_y+60, 211, 20)
CLAMP_SIZE = Draw.Number('Clamp Scale: ', EVENT_NONE, ui_x+9, ui_y+39, 130, 21, CLAMP_SIZE.val, 0.0, 1000.0, 'Clamp the size to this maximum (Zero to Disable)')
POLYGROUPS = Draw.Toggle('Poly Groups', EVENT_REDRAW, ui_x+144, ui_y+39, 90, 21, POLYGROUPS.val, 'Import OBJ groups as vertex groups.', do_polygroups)
IMAGE_SEARCH = Draw.Toggle('Image Search', EVENT_NONE, ui_x+239, ui_y+39, 100, 21, IMAGE_SEARCH.val, 'Search subdirs for any assosiated images (Warning, may be slow)')
Draw.BeginAlign()
Draw.PushButton('Online Help', EVENT_REDRAW, ui_x+9, ui_y+9, 110, 21, 'Load the wiki page for this script', do_help)
Draw.PushButton('Cancel', EVENT_EXIT, ui_x+119, ui_y+9, 110, 21, '', obj_ui_set_event)
Draw.PushButton('Import', EVENT_IMPORT, ui_x+229, ui_y+9, 110, 21, 'Import with these settings', obj_ui_set_event)
Draw.EndAlign()
# hack so the toggle buttons redraw. this is not nice at all
while GLOBALS['EVENT'] not in (EVENT_EXIT, EVENT_IMPORT):
Draw.UIBlock(obj_ui, 0)
if GLOBALS['EVENT'] != EVENT_IMPORT:
return
# END ALTERNATIVE UI *********************
Window.WaitCursor(1)
if BATCH_LOAD: # load the dir
try:
files= [ f for f in os.listdir(filepath) if f.lower().endswith('.obj') ]
except:
Window.WaitCursor(0)
Draw.PupMenu('Error%t|Could not open path ' + filepath)
return
if not files:
Window.WaitCursor(0)
Draw.PupMenu('Error%t|No files at path ' + filepath)
return
for f in files:
scn= bpy.data.scenes.new(os.path.splitext(f)[0])
scn.makeCurrent()
load_obj(sys.join(filepath, f),\
CLAMP_SIZE.val,\
CREATE_FGONS.val,\
CREATE_SMOOTH_GROUPS.val,\
CREATE_EDGES.val,\
SPLIT_OBJECTS.val,\
SPLIT_GROUPS.val,\
ROTATE_X90.val,\
IMAGE_SEARCH.val,\
POLYGROUPS.val
)
else: # Normal load
load_obj(filepath,\
CLAMP_SIZE.val,\
CREATE_FGONS.val,\
CREATE_SMOOTH_GROUPS.val,\
CREATE_EDGES.val,\
SPLIT_OBJECTS.val,\
SPLIT_GROUPS.val,\
ROTATE_X90.val,\
IMAGE_SEARCH.val,\
POLYGROUPS.val
)
Window.WaitCursor(0)
def load_obj_ui_batch(file):
load_obj_ui(file, True)
DEBUG= False
# if __name__=='__main__' and not DEBUG:
# if os and Window.GetKeyQualifiers() & Window.Qual.SHIFT:
# Window.FileSelector(load_obj_ui_batch, 'Import OBJ Dir', '')
# else:
# Window.FileSelector(load_obj_ui, 'Import a Wavefront OBJ', '*.obj')
# For testing compatibility
'''
else:
# DEBUG ONLY
TIME= sys.time()
DIR = '/fe/obj'
import os
print 'Searching for files'
def fileList(path):
for dirpath, dirnames, filenames in os.walk(path):
for filename in filenames:
yield os.path.join(dirpath, filename)
files = [f for f in fileList(DIR) if f.lower().endswith('.obj')]
files.sort()
for i, obj_file in enumerate(files):
if 0 < i < 20:
print 'Importing', obj_file, '\nNUMBER', i, 'of', len(files)
newScn= bpy.data.scenes.new(os.path.basename(obj_file))
newScn.makeCurrent()
load_obj(obj_file, False, IMAGE_SEARCH=0)
print 'TOTAL TIME: %.6f' % (sys.time() - TIME)
'''
from bpy.props import *
class IMPORT_OT_obj(bpy.types.Operator):
'''Load a Wavefront OBJ File'''
bl_idname = "import_scene.obj"
bl_label = "Import OBJ"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
filepath = StringProperty(name="File Path", description="Filepath used for importing the OBJ file", maxlen= 1024, default= "")
CREATE_SMOOTH_GROUPS = BoolProperty(name="Smooth Groups", description="Surround smooth groups by sharp edges", default= True)
CREATE_FGONS = BoolProperty(name="NGons as FGons", description="Import faces with more then 4 verts as fgons", default= True)
CREATE_EDGES = BoolProperty(name="Lines as Edges", description="Import lines and faces with 2 verts as edge", default= True)
SPLIT_OBJECTS = BoolProperty(name="Object", description="Import OBJ Objects into Blender Objects", default= True)
SPLIT_GROUPS = BoolProperty(name="Group", description="Import OBJ Groups into Blender Objects", default= True)
# old comment: only used for user feedback
# disabled this option because in old code a handler for it disabled SPLIT* params, it's not passed to load_obj
# KEEP_VERT_ORDER = BoolProperty(name="Keep Vert Order", description="Keep vert and face order, disables split options, enable for morph targets", default= True)
ROTATE_X90 = BoolProperty(name="-X90", description="Rotate X 90.", default= True)
CLAMP_SIZE = FloatProperty(name="Clamp Scale", description="Clamp the size to this maximum (Zero to Disable)", min=0.0, max=1000.0, soft_min=0.0, soft_max=1000.0, default=0.0)
POLYGROUPS = BoolProperty(name="Poly Groups", description="Import OBJ groups as vertex groups.", default= True)
IMAGE_SEARCH = BoolProperty(name="Image Search", description="Search subdirs for any assosiated images (Warning, may be slow)", default= True)
def execute(self, context):
# print("Selected: " + context.active_object.name)
load_obj(self.properties.filepath,
context,
self.properties.CLAMP_SIZE,
self.properties.CREATE_FGONS,
self.properties.CREATE_SMOOTH_GROUPS,
self.properties.CREATE_EDGES,
self.properties.SPLIT_OBJECTS,
self.properties.SPLIT_GROUPS,
self.properties.ROTATE_X90,
self.properties.IMAGE_SEARCH,
self.properties.POLYGROUPS)
return {'FINISHED'}
def invoke(self, context, event):
context.manager.add_fileselect(self)
return {'RUNNING_MODAL'}
def menu_func(self, context):
self.layout.operator(IMPORT_OT_obj.bl_idname, text="Wavefront (.obj)")
def register():
bpy.types.INFO_MT_file_import.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_import.remove(menu_func)
# NOTES (all line numbers refer to 2.4x import_obj.py, not this file) # NOTES (all line numbers refer to 2.4x import_obj.py, not this file)

View File

@@ -0,0 +1,61 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# To support reload properly, try to access a package var, if it's there, reload everything
if "bpy" in locals():
# only reload if we alredy loaded, highly annoying
import sys
reload(sys.modules.get("io_scene_x3d.export_x3d", sys))
import bpy
from bpy.props import *
from io_utils import ExportHelper
class ExportX3D(bpy.types.Operator, ExportHelper):
'''Export selection to Extensible 3D file (.x3d)'''
bl_idname = "export_scene.x3d"
bl_label = 'Export X3D'
filename_ext = ".x3d"
use_apply_modifiers = BoolProperty(name="Apply Modifiers", description="Use transformed mesh data from each object", default=True)
use_triangulate = BoolProperty(name="Triangulate", description="Triangulate quads.", default=False)
use_compress = BoolProperty(name="Compress", description="GZip the resulting file, requires a full python install", default=False)
def execute(self, context):
import io_scene_x3d.export_x3d
return io_scene_x3d.export_x3d.save(self, context, **self.properties)
def menu_func(self, context):
self.layout.operator(ExportX3D.bl_idname, text="X3D Extensible 3D (.x3d)")
def register():
bpy.types.INFO_MT_file_export.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_export.remove(menu_func)
# NOTES
# - blender version is hardcoded
if __name__ == "__main__":
register()

View File

@@ -18,68 +18,29 @@
# <pep8 compliant> # <pep8 compliant>
__author__ = ("Bart", "Campbell Barton") # Contributors: bart:neeneenee*de, http://www.neeneenee.de/vrml, Campbell Barton
__email__ = ["Bart, bart:neeneenee*de"]
__url__ = ["Author's (Bart) homepage, http://www.neeneenee.de/vrml"] """
__version__ = "2006/01/17"
__bpydoc__ = """\
This script exports to X3D format. This script exports to X3D format.
Usage: Usage:
Run this script from "File->Export" menu. A pop-up will ask whether you Run this script from "File->Export" menu. A pop-up will ask whether you
want to export only selected or all relevant objects. want to export only selected or all relevant objects.
Known issues:<br> Known issues:
Doesn't handle multiple materials (don't use material indices);<br> Doesn't handle multiple materials (don't use material indices);<br>
Doesn't handle multiple UV textures on a single mesh (create a mesh for each texture);<br> Doesn't handle multiple UV textures on a single mesh (create a mesh for each texture);<br>
Can't get the texture array associated with material * not the UV ones; Can't get the texture array associated with material * not the UV ones;
""" """
# $Id$
#
#------------------------------------------------------------------------
# X3D exporter for blender 2.36 or above
#
# ***** 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.
#
# ***** END GPL LICENCE BLOCK *****
#
####################################
# Library dependancies
####################################
import math import math
import os import os
import bpy import bpy
import mathutils import mathutils
from export_3ds import create_derived_objects, free_derived_objects from io_utils import create_derived_objects, free_derived_objects
# import Blender
# from Blender import Object, Lamp, Draw, Image, Text, sys, Mesh
# from Blender.Scene import Render
# import BPyObject
# import BPyMesh
#
DEG2RAD=0.017453292519943295 DEG2RAD=0.017453292519943295
MATWORLD= mathutils.Matrix.Rotation(-90, 4, 'X') MATWORLD= mathutils.Matrix.Rotation(-90, 4, 'X')
@@ -87,8 +48,7 @@ MATWORLD= mathutils.Matrix.Rotation(-90, 4, 'X')
# Global Variables # Global Variables
#################################### ####################################
filename = "" filepath = ""
# filename = Blender.Get('filename')
_safeOverwrite = True _safeOverwrite = True
extension = '' extension = ''
@@ -99,7 +59,7 @@ extension = ''
class x3d_class: class x3d_class:
def __init__(self, filename): def __init__(self, filepath):
#--- public you can change these --- #--- public you can change these ---
self.writingcolor = 0 self.writingcolor = 0
self.writingtexture = 0 self.writingtexture = 0
@@ -122,18 +82,18 @@ class x3d_class:
self.matNames={} # dictionary of materiaNames self.matNames={} # dictionary of materiaNames
self.meshNames={} # dictionary of meshNames self.meshNames={} # dictionary of meshNames
self.indentLevel=0 # keeps track of current indenting self.indentLevel=0 # keeps track of current indenting
self.filename=filename self.filepath=filepath
self.file = None self.file = None
if filename.lower().endswith('.x3dz'): if filepath.lower().endswith('.x3dz'):
try: try:
import gzip import gzip
self.file = gzip.open(filename, "w") self.file = gzip.open(filepath, "w")
except: except:
print("failed to import compression modules, exporting uncompressed") print("failed to import compression modules, exporting uncompressed")
self.filename = filename[:-1] # remove trailing z self.filepath = filepath[:-1] # remove trailing z
if self.file == None: if self.file == None:
self.file = open(self.filename, "w") self.file = open(self.filepath, "w")
self.bNav=0 self.bNav=0
self.nodeID=0 self.nodeID=0
@@ -175,13 +135,13 @@ class x3d_class:
########################################################## ##########################################################
def writeHeader(self): def writeHeader(self):
#bfile = sys.expandpath( Blender.Get('filename') ).replace('<', '&lt').replace('>', '&gt') #bfile = sys.expandpath( Blender.Get('filepath') ).replace('<', '&lt').replace('>', '&gt')
bfile = self.filename.replace('<', '&lt').replace('>', '&gt') # use outfile name bfile = repr(os.path.basename(self.filepath).replace('<', '&lt').replace('>', '&gt'))[1:-1] # use outfile name
self.file.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") self.file.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
self.file.write("<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.0//EN\" \"http://www.web3d.org/specifications/x3d-3.0.dtd\">\n") self.file.write("<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.0//EN\" \"http://www.web3d.org/specifications/x3d-3.0.dtd\">\n")
self.file.write("<X3D version=\"3.0\" profile=\"Immersive\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema-instance\" xsd:noNamespaceSchemaLocation=\"http://www.web3d.org/specifications/x3d-3.0.xsd\">\n") self.file.write("<X3D version=\"3.0\" profile=\"Immersive\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema-instance\" xsd:noNamespaceSchemaLocation=\"http://www.web3d.org/specifications/x3d-3.0.xsd\">\n")
self.file.write("<head>\n") self.file.write("<head>\n")
self.file.write("\t<meta name=\"filename\" content=\"%s\" />\n" % os.path.basename(bfile)) self.file.write("\t<meta name=\"filename\" content=\"%s\" />\n" % bfile)
# self.file.write("\t<meta name=\"filename\" content=\"%s\" />\n" % sys.basename(bfile)) # self.file.write("\t<meta name=\"filename\" content=\"%s\" />\n" % sys.basename(bfile))
self.file.write("\t<meta name=\"generator\" content=\"Blender %s\" />\n" % bpy.app.version_string) self.file.write("\t<meta name=\"generator\" content=\"Blender %s\" />\n" % bpy.app.version_string)
# self.file.write("\t<meta name=\"generator\" content=\"Blender %s\" />\n" % Blender.Get('version')) # self.file.write("\t<meta name=\"generator\" content=\"Blender %s\" />\n" % Blender.Get('version'))
@@ -465,6 +425,7 @@ class x3d_class:
self.writeIndented("<Appearance>\n", 1) self.writeIndented("<Appearance>\n", 1)
# right now this script can only handle a single material per mesh. # right now this script can only handle a single material per mesh.
if len(maters) >= 1 and maters[0].use_face_texture == False: if len(maters) >= 1 and maters[0].use_face_texture == False:
mat = maters[0]
self.writeMaterial(mat, self.cleanStr(mat.name,''), world) self.writeMaterial(mat, self.cleanStr(mat.name,''), world)
if len(maters) > 1: if len(maters) > 1:
print("Warning: mesh named %s has multiple materials" % meshName) print("Warning: mesh named %s has multiple materials" % meshName)
@@ -711,13 +672,13 @@ class x3d_class:
def writeImageTexture(self, image): def writeImageTexture(self, image):
name = image.name name = image.name
filename = os.path.basename(image.filepath) filepath = os.path.basename(image.filepath)
if name in self.texNames: if name in self.texNames:
self.writeIndented("<ImageTexture USE=\"%s\" />\n" % self.cleanStr(name)) self.writeIndented("<ImageTexture USE=\"%s\" />\n" % self.cleanStr(name))
self.texNames[name] += 1 self.texNames[name] += 1
else: else:
self.writeIndented("<ImageTexture DEF=\"%s\" " % self.cleanStr(name), 1) self.writeIndented("<ImageTexture DEF=\"%s\" " % self.cleanStr(name), 1)
self.file.write("url=\"%s\" />" % filename) self.file.write("url=\"%s\" />" % filepath)
self.writeIndented("\n",-1) self.writeIndented("\n",-1)
self.texNames[name] = 1 self.texNames[name] = 1
@@ -820,7 +781,7 @@ class x3d_class:
EXPORT_TRI= False,\ EXPORT_TRI= False,\
): ):
print("Info: starting X3D export to " + self.filename + "...") print("Info: starting X3D export to %r..." % self.filepath)
self.writeHeader() self.writeHeader()
# self.writeScript() # self.writeScript()
self.writeNavigationInfo(scene) self.writeNavigationInfo(scene)
@@ -918,7 +879,7 @@ class x3d_class:
self.texNames={} self.texNames={}
self.matNames={} self.matNames={}
self.indentLevel=0 self.indentLevel=0
print("Info: finished X3D export to %s\n" % self.filename) print("Info: finished X3D export to %r" % self.filepath)
def cleanStr(self, name, prefix='rsvd_'): def cleanStr(self, name, prefix='rsvd_'):
"""cleanStr(name,prefix) - try to create a valid VRML DEF name from object name""" """cleanStr(name,prefix) - try to create a valid VRML DEF name from object name"""
@@ -1128,91 +1089,35 @@ class x3d_class:
# Callbacks, needed before Main # Callbacks, needed before Main
########################################################## ##########################################################
def write(filename, def save(operator, context, filepath="",
context, use_apply_modifiers=False,
EXPORT_APPLY_MODIFIERS=False, use_triangulate=False,
EXPORT_TRI=False, use_compress=False):
EXPORT_GZIP=False):
if EXPORT_GZIP: if use_compress:
if not filename.lower().endswith('.x3dz'): if not filepath.lower().endswith('.x3dz'):
filename = '.'.join(filename.split('.')[:-1]) + '.x3dz' filepath = '.'.join(filepath.split('.')[:-1]) + '.x3dz'
else: else:
if not filename.lower().endswith('.x3d'): if not filepath.lower().endswith('.x3d'):
filename = '.'.join(filename.split('.')[:-1]) + '.x3d' filepath = '.'.join(filepath.split('.')[:-1]) + '.x3d'
scene = context.scene scene = context.scene
world = scene.world world = scene.world
if scene.objects.active: if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='OBJECT')
# XXX these are global textures while .Get() returned only scene's? # XXX these are global textures while .Get() returned only scene's?
alltextures = bpy.data.textures alltextures = bpy.data.textures
# alltextures = Blender.Texture.Get() # alltextures = Blender.Texture.Get()
wrlexport=x3d_class(filename) wrlexport = x3d_class(filepath)
wrlexport.export(\ wrlexport.export(scene,
scene,\ world,
world,\ alltextures,
alltextures,\ EXPORT_APPLY_MODIFIERS=use_apply_modifiers,
\ EXPORT_TRI=use_triangulate,
EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS,\ )
EXPORT_TRI = EXPORT_TRI,\
)
return {'FINISHED'}
from bpy.props import *
class ExportX3D(bpy.types.Operator):
'''Export selection to Extensible 3D file (.x3d)'''
bl_idname = "export.x3d"
bl_label = 'Export X3D'
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
filepath = StringProperty(name="File Path", description="Filepath used for exporting the X3D file", maxlen= 1024, default= "")
check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'})
apply_modifiers = BoolProperty(name="Apply Modifiers", description="Use transformed mesh data from each object", default=True)
triangulate = BoolProperty(name="Triangulate", description="Triangulate quads.", default=False)
compress = BoolProperty(name="Compress", description="GZip the resulting file, requires a full python install", default=False)
def execute(self, context):
filepath = self.properties.filepath
filepath = bpy.path.ensure_ext(filepath, ".x3d")
write(filepath,
context,
self.properties.apply_modifiers,
self.properties.triangulate,
self.properties.compress,
)
return {'FINISHED'}
def invoke(self, context, event):
import os
if not self.properties.is_property_set("filepath"):
self.properties.filepath = os.path.splitext(bpy.data.filepath)[0] + ".x3d"
context.manager.add_fileselect(self)
return {'RUNNING_MODAL'}
def menu_func(self, context):
self.layout.operator(ExportX3D.bl_idname, text="X3D Extensible 3D (.x3d)")
def register():
bpy.types.INFO_MT_file_export.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_export.remove(menu_func)
# NOTES
# - blender version is hardcoded
if __name__ == "__main__":
register()

View File

@@ -0,0 +1,115 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# To support reload properly, try to access a package var, if it's there, reload everything
if "bpy" in locals():
# only reload if we alredy loaded, highly annoying
import sys
reload(sys.modules.get("io_shape_mdd.import_mdd", sys))
reload(sys.modules.get("io_shape_mdd.export_mdd", sys))
import bpy
from bpy.props import *
from io_utils import ExportHelper, ImportHelper
class ImportMDD(bpy.types.Operator, ImportHelper):
'''Import MDD vertex keyframe file to shape keys'''
bl_idname = "import_shape.mdd"
bl_label = "Import MDD"
filename_ext = ".mdd"
frame_start = IntProperty(name="Start Frame", description="Start frame for inserting animation", min=-300000, max=300000, default=0)
frame_step = IntProperty(name="Step", min=1, max=1000, default=1)
@classmethod
def poll(cls, context):
ob = context.active_object
return (ob and ob.type == 'MESH')
def execute(self, context):
# initialize from scene if unset
scene = context.scene
if not self.properties.is_property_set("frame_start"):
self.properties.frame_start = scene.frame_current
import io_shape_mdd.import_mdd
return io_shape_mdd.import_mdd.load(self, context, **self.properties)
class ExportMDD(bpy.types.Operator, ExportHelper):
'''Animated mesh to MDD vertex keyframe file'''
bl_idname = "export_shape.mdd"
bl_label = "Export MDD"
filename_ext = ".mdd"
# get first scene to get min and max properties for frames, fps
minframe = 1
maxframe = 300000
minfps = 1
maxfps = 120
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
fps = IntProperty(name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default=25)
frame_start = IntProperty(name="Start Frame", description="Start frame for baking", min=minframe, max=maxframe, default=1)
frame_end = IntProperty(name="End Frame", description="End frame for baking", min=minframe, max=maxframe, default=250)
@classmethod
def poll(cls, context):
obj = context.active_object
return (obj and obj.type == 'MESH')
def execute(self, context):
# initialize from scene if unset
scene = context.scene
if not self.properties.is_property_set("frame_start"):
self.properties.frame_start = scene.frame_start
if not self.properties.is_property_set("frame_end"):
self.properties.frame_end = scene.frame_end
if not self.properties.is_property_set("fps"):
self.properties.fps = scene.render.fps
import io_shape_mdd.export_mdd
return io_shape_mdd.export_mdd.save(self, context, **self.properties)
def menu_func_import(self, context):
self.layout.operator(ImportMDD.bl_idname, text="Lightwave Point Cache (.mdd)")
def menu_func_export(self, context):
self.layout.operator(ExportMDD.bl_idname, text="Lightwave Point Cache (.mdd)")
def register():
bpy.types.INFO_MT_file_import.append(menu_func_import)
bpy.types.INFO_MT_file_export.append(menu_func_export)
def unregister():
bpy.types.INFO_MT_file_import.remove(menu_func_import)
bpy.types.INFO_MT_file_export.remove(menu_func_export)
if __name__ == "__main__":
register()

View File

@@ -0,0 +1,131 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# Contributors: Bill L.Nieuwendorp
"""
This script Exports Lightwaves MotionDesigner format.
The .mdd format has become quite a popular Pipeline format<br>
for moving animations from package to package.
Be sure not to use modifiers that change the number or order of verts in the mesh
"""
import bpy
import mathutils
from struct import pack
def zero_file(filepath):
'''
If a file fails, this replaces it with 1 char, better not remove it?
'''
file = open(filepath, 'w')
file.write('\n') # apparently macosx needs some data in a blank file?
file.close()
def check_vertcount(mesh, vertcount):
'''
check and make sure the vertcount is consistent throughout the frame range
'''
if len(mesh.vertices) != vertcount:
raise Exception('Error, number of verts has changed during animation, cannot export')
f.close()
zero_file(filepath)
return
def save(operator, context, filepath="", frame_start=1, frame_end=300, fps=25):
"""
Blender.Window.WaitCursor(1)
mesh_orig = Mesh.New()
mesh_orig.getFromObject(obj.name)
"""
scene = context.scene
obj = context.object
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
orig_frame = scene.frame_current
scene.frame_set(frame_start)
me = obj.create_mesh(scene, True, 'PREVIEW')
#Flip y and z
mat_flip = mathutils.Matrix(\
[1.0, 0.0, 0.0, 0.0],\
[0.0, 0.0, 1.0, 0.0],\
[0.0, 1.0, 0.0, 0.0],\
[0.0, 0.0, 0.0, 1.0],\
)
numverts = len(me.vertices)
numframes = frame_end - frame_start + 1
fps = float(fps)
f = open(filepath, 'wb') #no Errors yet:Safe to create file
# Write the header
f.write(pack(">2i", numframes, numverts))
# Write the frame times (should we use the time IPO??)
f.write(pack(">%df" % (numframes), *[frame / fps for frame in range(numframes)])) # seconds
#rest frame needed to keep frames in sync
"""
Blender.Set('curframe', frame_start)
me_tmp.getFromObject(obj.name)
"""
check_vertcount(me, numverts)
me.transform(mat_flip * obj.matrix_world)
f.write(pack(">%df" % (numverts * 3), *[axis for v in me.vertices for axis in v.co]))
for frame in range(frame_start, frame_end + 1):#in order to start at desired frame
"""
Blender.Set('curframe', frame)
me_tmp.getFromObject(obj.name)
"""
scene.frame_set(frame)
me = obj.create_mesh(scene, True, 'PREVIEW')
check_vertcount(me, numverts)
me.transform(mat_flip * obj.matrix_world)
# Write the vertex data
f.write(pack(">%df" % (numverts * 3), *[axis for v in me.vertices for axis in v.co]))
"""
me_tmp.vertices= None
"""
f.close()
print('MDD Exported: %r frames:%d\n' % (filepath, numframes - 1))
"""
Blender.Window.WaitCursor(0)
Blender.Set('curframe', orig_frame)
"""
scene.frame_set(orig_frame)
return {'FINISHED'}

View File

@@ -0,0 +1,105 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# mdd importer by Bill L.Nieuwendorp
# conversion to blender 2.5: Ivo Grigull (loolarge)
#
# Warning if the vertex order or vertex count differs from the
# origonal model the mdd was Baked out from their will be Strange
# behavior
#
# vertex animation to ShapeKeys with ipo and gives the frame a value of 1.0
# A modifier to read mdd files would be Ideal but thats for another day :)
#
# Please send any fixes,updates,bugs to Slow67_at_Gmail.com
# Bill Niewuendorp
import bpy
from struct import unpack
def load(operator, context, filepath, frame_start=0, frame_step=1):
scene = context.scene
obj = context.object
print('\n\nimporting mdd %r' % filepath)
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
file = open(filepath, 'rb')
frames, points = unpack(">2i", file.read(8))
time = unpack((">%df" % frames), file.read(frames * 4))
print('\tpoints:%d frames:%d' % (points, frames))
# If target object doesn't have Basis shape key, create it.
try:
num_keys = len(obj.data.shape_keys.keys)
except:
basis = obj.add_shape_key()
basis.name = "Basis"
obj.data.update()
scene.frame_current = frame_start
def UpdateMesh(ob, fr):
# Insert new shape key
new_shapekey = obj.add_shape_key()
new_shapekey.name = ("frame_%.4d" % fr)
new_shapekey_name = new_shapekey.name
obj.active_shape_key_index = len(obj.data.shape_keys.keys)-1
index = len(obj.data.shape_keys.keys)-1
obj.show_shape_key = True
verts = obj.data.shape_keys.keys[len(obj.data.shape_keys.keys)-1].data
for v in verts: # 12 is the size of 3 floats
v.co[:] = unpack('>3f', file.read(12))
#me.update()
obj.show_shape_key = False
# insert keyframes
shape_keys = obj.data.shape_keys
scene.frame_current -= 1
obj.data.shape_keys.keys[index].value = 0.0
shape_keys.keys[len(obj.data.shape_keys.keys)-1].keyframe_insert("value")
scene.frame_current += 1
obj.data.shape_keys.keys[index].value = 1.0
shape_keys.keys[len(obj.data.shape_keys.keys)-1].keyframe_insert("value")
scene.frame_current += 1
obj.data.shape_keys.keys[index].value = 0.0
shape_keys.keys[len(obj.data.shape_keys.keys)-1].keyframe_insert("value")
obj.data.update()
for i in range(frames):
UpdateMesh(obj, i)
return {'FINISHED'}

View File

@@ -87,7 +87,7 @@ def bake(frame_start, frame_end, step=1, only_selected=False):
# could spped this up by applying steps here too... # could spped this up by applying steps here too...
for f in frame_range: for f in frame_range:
scene.set_frame(f) scene.frame_set(f)
info = pose_info() info = pose_info()
info_ls.append(info) info_ls.append(info)
@@ -169,7 +169,7 @@ class BakeAction(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
def invoke(self, context, event): def invoke(self, context, event):
wm = context.manager wm = context.window_manager
return wm.invoke_props_dialog(self) return wm.invoke_props_dialog(self)

View File

@@ -59,7 +59,7 @@ class SelectPattern(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
def invoke(self, context, event): def invoke(self, context, event):
wm = context.manager wm = context.window_manager
# return wm.invoke_props_popup(self, event) # return wm.invoke_props_popup(self, event)
wm.invoke_props_popup(self, event) wm.invoke_props_popup(self, event)
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
@@ -573,4 +573,4 @@ def unregister():
pass pass
if __name__ == "__main__": if __name__ == "__main__":
register() register()

View File

@@ -64,7 +64,7 @@ class AddPresetBase():
return {'FINISHED'} return {'FINISHED'}
def invoke(self, context, event): def invoke(self, context, event):
wm = context.manager wm = context.window_manager
#crashes, TODO - fix #crashes, TODO - fix
#return wm.invoke_props_popup(self, event) #return wm.invoke_props_popup(self, event)

View File

@@ -207,7 +207,7 @@ class ExportUVLayout(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
def invoke(self, context, event): def invoke(self, context, event):
wm = context.manager wm = context.window_manager
wm.add_fileselect(self) wm.add_fileselect(self)
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}

View File

@@ -449,7 +449,7 @@ class WM_OT_context_modal_mouse(bpy.types.Operator):
else: else:
self.properties.initial_x = event.mouse_x self.properties.initial_x = event.mouse_x
context.manager.add_modal_handler(self) context.window_manager.add_modal_handler(self)
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
@@ -505,7 +505,7 @@ class WM_OT_doc_view(bpy.types.Operator):
bl_label = "View Documentation" bl_label = "View Documentation"
doc_id = doc_id doc_id = doc_id
_prefix = 'http://www.blender.org/documentation/250PythonDoc' _prefix = "http://www.blender.org/documentation/blender_python_api_%s" % "_".join(str(v) for v in bpy.app.version)
def _nested_class_string(self, class_string): def _nested_class_string(self, class_string):
ls = [] ls = []
@@ -608,7 +608,7 @@ class WM_OT_doc_edit(bpy.types.Operator):
layout.prop(props, "doc_new", text="") layout.prop(props, "doc_new", text="")
def invoke(self, context, event): def invoke(self, context, event):
wm = context.manager wm = context.window_manager
return wm.invoke_props_dialog(self, width=600) return wm.invoke_props_dialog(self, width=600)
@@ -692,7 +692,7 @@ class WM_OT_properties_edit(bpy.types.Operator):
self.properties.max = prop_ui.get("max", 1000000000) self.properties.max = prop_ui.get("max", 1000000000)
self.properties.description = prop_ui.get("description", "") self.properties.description = prop_ui.get("description", "")
wm = context.manager wm = context.window_manager
# This crashes, TODO - fix # This crashes, TODO - fix
#return wm.invoke_props_popup(self, event) #return wm.invoke_props_popup(self, event)

View File

@@ -1,7 +1,7 @@
# Configuration Blender # Configuration Blender
import bpy import bpy
wm = bpy.context.manager wm = bpy.context.window_manager
wm.keyconfigs.active = wm.keyconfigs['Blender'] wm.keyconfigs.active = wm.keyconfigs['Blender']
bpy.context.user_preferences.view.use_mouse_auto_depth = False bpy.context.user_preferences.view.use_mouse_auto_depth = False

View File

@@ -1,378 +1,378 @@
# Configuration Maya # Configuration Maya
import bpy import bpy
wm = bpy.context.manager wm = bpy.context.window_manager
kc = wm.add_keyconfig('Maya') kc = wm.keyconfigs.new('Maya')
# Map 3D View # Map 3D View
km = kc.add_keymap('3D View', space_type='VIEW_3D', region_type='WINDOW', modal=False) km = kc.keymaps.new('3D View', space_type='VIEW_3D', region_type='WINDOW', modal=False)
kmi = km.items.add('view3d.manipulator', 'LEFTMOUSE', 'PRESS', any=True) kmi = km.items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', any=True)
kmi.properties.release_confirm = True kmi.properties.release_confirm = True
kmi = km.items.add('view3d.cursor3d', 'ACTIONMOUSE', 'PRESS') kmi = km.items.new('view3d.cursor3d', 'ACTIONMOUSE', 'PRESS')
kmi = km.items.add('view3d.rotate', 'LEFTMOUSE', 'PRESS', alt=True) kmi = km.items.new('view3d.rotate', 'LEFTMOUSE', 'PRESS', alt=True)
kmi = km.items.add('view3d.move', 'MIDDLEMOUSE', 'PRESS', alt=True) kmi = km.items.new('view3d.move', 'MIDDLEMOUSE', 'PRESS', alt=True)
kmi = km.items.add('view3d.zoom', 'RIGHTMOUSE', 'PRESS', alt=True) kmi = km.items.new('view3d.zoom', 'RIGHTMOUSE', 'PRESS', alt=True)
kmi = km.items.add('view3d.view_selected', 'NUMPAD_PERIOD', 'PRESS') kmi = km.items.new('view3d.view_selected', 'NUMPAD_PERIOD', 'PRESS')
kmi = km.items.add('view3d.view_center_cursor', 'NUMPAD_PERIOD', 'PRESS', ctrl=True) kmi = km.items.new('view3d.view_center_cursor', 'NUMPAD_PERIOD', 'PRESS', ctrl=True)
kmi = km.items.add('view3d.fly', 'F', 'PRESS', shift=True) kmi = km.items.new('view3d.fly', 'F', 'PRESS', shift=True)
kmi = km.items.add('view3d.smoothview', 'TIMER1', 'ANY', any=True) kmi = km.items.new('view3d.smoothview', 'TIMER1', 'ANY', any=True)
kmi = km.items.add('view3d.rotate', 'TRACKPADPAN', 'ANY', alt=True) kmi = km.items.new('view3d.rotate', 'TRACKPADPAN', 'ANY', alt=True)
kmi = km.items.add('view3d.rotate', 'MOUSEROTATE', 'ANY') kmi = km.items.new('view3d.rotate', 'MOUSEROTATE', 'ANY')
kmi = km.items.add('view3d.move', 'TRACKPADPAN', 'ANY') kmi = km.items.new('view3d.move', 'TRACKPADPAN', 'ANY')
kmi = km.items.add('view3d.zoom', 'TRACKPADZOOM', 'ANY') kmi = km.items.new('view3d.zoom', 'TRACKPADZOOM', 'ANY')
kmi = km.items.add('view3d.zoom', 'NUMPAD_PLUS', 'PRESS') kmi = km.items.new('view3d.zoom', 'NUMPAD_PLUS', 'PRESS')
kmi.properties.delta = 1 kmi.properties.delta = 1
kmi = km.items.add('view3d.zoom', 'NUMPAD_MINUS', 'PRESS') kmi = km.items.new('view3d.zoom', 'NUMPAD_MINUS', 'PRESS')
kmi.properties.delta = -1 kmi.properties.delta = -1
kmi = km.items.add('view3d.zoom', 'EQUAL', 'PRESS', ctrl=True) kmi = km.items.new('view3d.zoom', 'EQUAL', 'PRESS', ctrl=True)
kmi.properties.delta = 1 kmi.properties.delta = 1
kmi = km.items.add('view3d.zoom', 'MINUS', 'PRESS', ctrl=True) kmi = km.items.new('view3d.zoom', 'MINUS', 'PRESS', ctrl=True)
kmi.properties.delta = -1 kmi.properties.delta = -1
kmi = km.items.add('view3d.zoom', 'WHEELINMOUSE', 'PRESS') kmi = km.items.new('view3d.zoom', 'WHEELINMOUSE', 'PRESS')
kmi.properties.delta = 1 kmi.properties.delta = 1
kmi = km.items.add('view3d.zoom', 'WHEELOUTMOUSE', 'PRESS') kmi = km.items.new('view3d.zoom', 'WHEELOUTMOUSE', 'PRESS')
kmi.properties.delta = -1 kmi.properties.delta = -1
kmi = km.items.add('view3d.view_all', 'HOME', 'PRESS') kmi = km.items.new('view3d.view_all', 'HOME', 'PRESS')
kmi.properties.center = False kmi.properties.center = False
kmi = km.items.add('view3d.view_all', 'C', 'PRESS', shift=True) kmi = km.items.new('view3d.view_all', 'C', 'PRESS', shift=True)
kmi.properties.center = True kmi.properties.center = True
kmi = km.items.add('view3d.viewnumpad', 'NUMPAD_0', 'PRESS') kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_0', 'PRESS')
kmi.properties.type = 'CAMERA' kmi.properties.type = 'CAMERA'
kmi = km.items.add('view3d.viewnumpad', 'NUMPAD_1', 'PRESS') kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS')
kmi.properties.type = 'FRONT' kmi.properties.type = 'FRONT'
kmi = km.items.add('view3d.view_orbit', 'NUMPAD_2', 'PRESS') kmi = km.items.new('view3d.view_orbit', 'NUMPAD_2', 'PRESS')
kmi.properties.type = 'ORBITDOWN' kmi.properties.type = 'ORBITDOWN'
kmi = km.items.add('view3d.viewnumpad', 'NUMPAD_3', 'PRESS') kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS')
kmi.properties.type = 'RIGHT' kmi.properties.type = 'RIGHT'
kmi = km.items.add('view3d.view_orbit', 'NUMPAD_4', 'PRESS') kmi = km.items.new('view3d.view_orbit', 'NUMPAD_4', 'PRESS')
kmi.properties.type = 'ORBITLEFT' kmi.properties.type = 'ORBITLEFT'
kmi = km.items.add('view3d.view_persportho', 'NUMPAD_5', 'PRESS') kmi = km.items.new('view3d.view_persportho', 'NUMPAD_5', 'PRESS')
kmi = km.items.add('view3d.view_orbit', 'NUMPAD_6', 'PRESS') kmi = km.items.new('view3d.view_orbit', 'NUMPAD_6', 'PRESS')
kmi.properties.type = 'ORBITRIGHT' kmi.properties.type = 'ORBITRIGHT'
kmi = km.items.add('view3d.viewnumpad', 'NUMPAD_7', 'PRESS') kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_7', 'PRESS')
kmi.properties.type = 'TOP' kmi.properties.type = 'TOP'
kmi = km.items.add('view3d.view_orbit', 'NUMPAD_8', 'PRESS') kmi = km.items.new('view3d.view_orbit', 'NUMPAD_8', 'PRESS')
kmi.properties.type = 'ORBITUP' kmi.properties.type = 'ORBITUP'
kmi = km.items.add('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', ctrl=True) kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', ctrl=True)
kmi.properties.type = 'BACK' kmi.properties.type = 'BACK'
kmi = km.items.add('view3d.viewnumpad', 'NUMPAD_3', 'PRESS', ctrl=True) kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS', ctrl=True)
kmi.properties.type = 'LEFT' kmi.properties.type = 'LEFT'
kmi = km.items.add('view3d.viewnumpad', 'NUMPAD_7', 'PRESS', ctrl=True) kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_7', 'PRESS', ctrl=True)
kmi.properties.type = 'BOTTOM' kmi.properties.type = 'BOTTOM'
kmi = km.items.add('view3d.view_pan', 'NUMPAD_2', 'PRESS', ctrl=True) kmi = km.items.new('view3d.view_pan', 'NUMPAD_2', 'PRESS', ctrl=True)
kmi.properties.type = 'PANDOWN' kmi.properties.type = 'PANDOWN'
kmi = km.items.add('view3d.view_pan', 'NUMPAD_4', 'PRESS', ctrl=True) kmi = km.items.new('view3d.view_pan', 'NUMPAD_4', 'PRESS', ctrl=True)
kmi.properties.type = 'PANLEFT' kmi.properties.type = 'PANLEFT'
kmi = km.items.add('view3d.view_pan', 'NUMPAD_6', 'PRESS', ctrl=True) kmi = km.items.new('view3d.view_pan', 'NUMPAD_6', 'PRESS', ctrl=True)
kmi.properties.type = 'PANRIGHT' kmi.properties.type = 'PANRIGHT'
kmi = km.items.add('view3d.view_pan', 'NUMPAD_8', 'PRESS', ctrl=True) kmi = km.items.new('view3d.view_pan', 'NUMPAD_8', 'PRESS', ctrl=True)
kmi.properties.type = 'PANUP' kmi.properties.type = 'PANUP'
kmi = km.items.add('view3d.view_pan', 'WHEELUPMOUSE', 'PRESS', ctrl=True) kmi = km.items.new('view3d.view_pan', 'WHEELUPMOUSE', 'PRESS', ctrl=True)
kmi.properties.type = 'PANRIGHT' kmi.properties.type = 'PANRIGHT'
kmi = km.items.add('view3d.view_pan', 'WHEELDOWNMOUSE', 'PRESS', ctrl=True) kmi = km.items.new('view3d.view_pan', 'WHEELDOWNMOUSE', 'PRESS', ctrl=True)
kmi.properties.type = 'PANLEFT' kmi.properties.type = 'PANLEFT'
kmi = km.items.add('view3d.view_pan', 'WHEELUPMOUSE', 'PRESS', shift=True) kmi = km.items.new('view3d.view_pan', 'WHEELUPMOUSE', 'PRESS', shift=True)
kmi.properties.type = 'PANUP' kmi.properties.type = 'PANUP'
kmi = km.items.add('view3d.view_pan', 'WHEELDOWNMOUSE', 'PRESS', shift=True) kmi = km.items.new('view3d.view_pan', 'WHEELDOWNMOUSE', 'PRESS', shift=True)
kmi.properties.type = 'PANDOWN' kmi.properties.type = 'PANDOWN'
kmi = km.items.add('view3d.view_orbit', 'WHEELUPMOUSE', 'PRESS', ctrl=True, alt=True) kmi = km.items.new('view3d.view_orbit', 'WHEELUPMOUSE', 'PRESS', ctrl=True, alt=True)
kmi.properties.type = 'ORBITLEFT' kmi.properties.type = 'ORBITLEFT'
kmi = km.items.add('view3d.view_orbit', 'WHEELDOWNMOUSE', 'PRESS', ctrl=True, alt=True) kmi = km.items.new('view3d.view_orbit', 'WHEELDOWNMOUSE', 'PRESS', ctrl=True, alt=True)
kmi.properties.type = 'ORBITRIGHT' kmi.properties.type = 'ORBITRIGHT'
kmi = km.items.add('view3d.view_orbit', 'WHEELUPMOUSE', 'PRESS', shift=True, alt=True) kmi = km.items.new('view3d.view_orbit', 'WHEELUPMOUSE', 'PRESS', shift=True, alt=True)
kmi.properties.type = 'ORBITUP' kmi.properties.type = 'ORBITUP'
kmi = km.items.add('view3d.view_orbit', 'WHEELDOWNMOUSE', 'PRESS', shift=True, alt=True) kmi = km.items.new('view3d.view_orbit', 'WHEELDOWNMOUSE', 'PRESS', shift=True, alt=True)
kmi.properties.type = 'ORBITDOWN' kmi.properties.type = 'ORBITDOWN'
kmi = km.items.add('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', shift=True) kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', shift=True)
kmi.properties.align_active = True kmi.properties.align_active = True
kmi.properties.type = 'FRONT' kmi.properties.type = 'FRONT'
kmi = km.items.add('view3d.viewnumpad', 'NUMPAD_3', 'PRESS', shift=True) kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS', shift=True)
kmi.properties.align_active = True kmi.properties.align_active = True
kmi.properties.type = 'RIGHT' kmi.properties.type = 'RIGHT'
kmi = km.items.add('view3d.viewnumpad', 'NUMPAD_7', 'PRESS', shift=True) kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_7', 'PRESS', shift=True)
kmi.properties.align_active = True kmi.properties.align_active = True
kmi.properties.type = 'TOP' kmi.properties.type = 'TOP'
kmi = km.items.add('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', shift=True, ctrl=True) kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', shift=True, ctrl=True)
kmi.properties.align_active = True kmi.properties.align_active = True
kmi.properties.type = 'BACK' kmi.properties.type = 'BACK'
kmi = km.items.add('view3d.viewnumpad', 'NUMPAD_3', 'PRESS', shift=True, ctrl=True) kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS', shift=True, ctrl=True)
kmi.properties.align_active = True kmi.properties.align_active = True
kmi.properties.type = 'LEFT' kmi.properties.type = 'LEFT'
kmi = km.items.add('view3d.viewnumpad', 'NUMPAD_7', 'PRESS', shift=True, ctrl=True) kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_7', 'PRESS', shift=True, ctrl=True)
kmi.properties.align_active = True kmi.properties.align_active = True
kmi.properties.type = 'BOTTOM' kmi.properties.type = 'BOTTOM'
kmi = km.items.add('view3d.localview', 'NUMPAD_SLASH', 'PRESS') kmi = km.items.new('view3d.localview', 'NUMPAD_SLASH', 'PRESS')
kmi = km.items.add('view3d.layers', 'ACCENT_GRAVE', 'PRESS') kmi = km.items.new('view3d.layers', 'ACCENT_GRAVE', 'PRESS')
kmi.properties.nr = 0 kmi.properties.nr = 0
kmi = km.items.add('view3d.layers', 'ONE', 'PRESS', any=True) kmi = km.items.new('view3d.layers', 'ONE', 'PRESS', any=True)
kmi.properties.nr = 1 kmi.properties.nr = 1
kmi = km.items.add('view3d.layers', 'TWO', 'PRESS', any=True) kmi = km.items.new('view3d.layers', 'TWO', 'PRESS', any=True)
kmi.properties.nr = 2 kmi.properties.nr = 2
kmi = km.items.add('view3d.layers', 'THREE', 'PRESS', any=True) kmi = km.items.new('view3d.layers', 'THREE', 'PRESS', any=True)
kmi.properties.nr = 3 kmi.properties.nr = 3
kmi = km.items.add('view3d.layers', 'FOUR', 'PRESS', any=True) kmi = km.items.new('view3d.layers', 'FOUR', 'PRESS', any=True)
kmi.properties.nr = 4 kmi.properties.nr = 4
kmi = km.items.add('view3d.layers', 'FIVE', 'PRESS', any=True) kmi = km.items.new('view3d.layers', 'FIVE', 'PRESS', any=True)
kmi.properties.nr = 5 kmi.properties.nr = 5
kmi = km.items.add('view3d.layers', 'SIX', 'PRESS', any=True) kmi = km.items.new('view3d.layers', 'SIX', 'PRESS', any=True)
kmi.properties.nr = 6 kmi.properties.nr = 6
kmi = km.items.add('view3d.layers', 'SEVEN', 'PRESS', any=True) kmi = km.items.new('view3d.layers', 'SEVEN', 'PRESS', any=True)
kmi.properties.nr = 7 kmi.properties.nr = 7
kmi = km.items.add('view3d.layers', 'EIGHT', 'PRESS', any=True) kmi = km.items.new('view3d.layers', 'EIGHT', 'PRESS', any=True)
kmi.properties.nr = 8 kmi.properties.nr = 8
kmi = km.items.add('view3d.layers', 'NINE', 'PRESS', any=True) kmi = km.items.new('view3d.layers', 'NINE', 'PRESS', any=True)
kmi.properties.nr = 9 kmi.properties.nr = 9
kmi = km.items.add('view3d.layers', 'ZERO', 'PRESS', any=True) kmi = km.items.new('view3d.layers', 'ZERO', 'PRESS', any=True)
kmi.properties.nr = 10 kmi.properties.nr = 10
kmi = km.items.add('wm.context_toggle_enum', 'Z', 'PRESS') kmi = km.items.new('wm.context_toggle_enum', 'Z', 'PRESS')
kmi.properties.data_path = 'space_data.viewport_shade' kmi.properties.data_path = 'space_data.viewport_shade'
kmi.properties.value_1 = 'SOLID' kmi.properties.value_1 = 'SOLID'
kmi.properties.value_2 = 'WIREFRAME' kmi.properties.value_2 = 'WIREFRAME'
kmi = km.items.add('wm.context_toggle_enum', 'Z', 'PRESS', alt=True) kmi = km.items.new('wm.context_toggle_enum', 'Z', 'PRESS', alt=True)
kmi.properties.data_path = 'space_data.viewport_shade' kmi.properties.data_path = 'space_data.viewport_shade'
kmi.properties.value_1 = 'TEXTURED' kmi.properties.value_1 = 'TEXTURED'
kmi.properties.value_2 = 'SOLID' kmi.properties.value_2 = 'SOLID'
kmi = km.items.add('view3d.select', 'SELECTMOUSE', 'PRESS') kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS')
kmi = km.items.add('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True) kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True)
kmi.properties.extend = True kmi.properties.extend = True
kmi = km.items.add('view3d.select', 'SELECTMOUSE', 'PRESS', ctrl=True) kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', ctrl=True)
kmi.properties.center = True kmi.properties.center = True
kmi = km.items.add('view3d.select', 'SELECTMOUSE', 'PRESS', alt=True) kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', alt=True)
kmi.properties.enumerate = True kmi.properties.enumerate = True
kmi = km.items.add('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True) kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True)
kmi.properties.center = True kmi.properties.center = True
kmi.properties.extend = True kmi.properties.extend = True
kmi = km.items.add('view3d.select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True) kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True)
kmi.properties.center = True kmi.properties.center = True
kmi.properties.enumerate = True kmi.properties.enumerate = True
kmi = km.items.add('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, alt=True) kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, alt=True)
kmi.properties.enumerate = True kmi.properties.enumerate = True
kmi.properties.extend = True kmi.properties.extend = True
kmi = km.items.add('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True) kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True)
kmi.properties.center = True kmi.properties.center = True
kmi.properties.enumerate = True kmi.properties.enumerate = True
kmi.properties.extend = True kmi.properties.extend = True
kmi = km.items.add('view3d.select_border', 'EVT_TWEAK_S', 'ANY') kmi = km.items.new('view3d.select_border', 'EVT_TWEAK_S', 'ANY')
kmi.properties.extend = False kmi.properties.extend = False
kmi = km.items.add('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', ctrl=True) kmi = km.items.new('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', ctrl=True)
kmi = km.items.add('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', shift=True, ctrl=True) kmi = km.items.new('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', shift=True, ctrl=True)
kmi.properties.deselect = True kmi.properties.deselect = True
kmi = km.items.add('view3d.select_circle', 'C', 'PRESS') kmi = km.items.new('view3d.select_circle', 'C', 'PRESS')
kmi = km.items.add('view3d.clip_border', 'B', 'PRESS', alt=True) kmi = km.items.new('view3d.clip_border', 'B', 'PRESS', alt=True)
kmi = km.items.add('view3d.zoom_border', 'B', 'PRESS', shift=True) kmi = km.items.new('view3d.zoom_border', 'B', 'PRESS', shift=True)
kmi = km.items.add('view3d.render_border', 'B', 'PRESS', shift=True) kmi = km.items.new('view3d.render_border', 'B', 'PRESS', shift=True)
kmi = km.items.add('view3d.camera_to_view', 'NUMPAD_0', 'PRESS', ctrl=True, alt=True) kmi = km.items.new('view3d.camera_to_view', 'NUMPAD_0', 'PRESS', ctrl=True, alt=True)
kmi = km.items.add('view3d.object_as_camera', 'NUMPAD_0', 'PRESS', ctrl=True) kmi = km.items.new('view3d.object_as_camera', 'NUMPAD_0', 'PRESS', ctrl=True)
kmi = km.items.add('wm.call_menu', 'S', 'PRESS', shift=True) kmi = km.items.new('wm.call_menu', 'S', 'PRESS', shift=True)
kmi.properties.name = 'VIEW3D_MT_snap' kmi.properties.name = 'VIEW3D_MT_snap'
kmi = km.items.add('wm.context_set_enum', 'COMMA', 'PRESS') kmi = km.items.new('wm.context_set_enum', 'COMMA', 'PRESS')
kmi.properties.data_path = 'space_data.pivot_point' kmi.properties.data_path = 'space_data.pivot_point'
kmi.properties.value = 'BOUNDING_BOX_CENTER' kmi.properties.value = 'BOUNDING_BOX_CENTER'
kmi = km.items.add('wm.context_set_enum', 'COMMA', 'PRESS', ctrl=True) kmi = km.items.new('wm.context_set_enum', 'COMMA', 'PRESS', ctrl=True)
kmi.properties.data_path = 'space_data.pivot_point' kmi.properties.data_path = 'space_data.pivot_point'
kmi.properties.value = 'MEDIAN_POINT' kmi.properties.value = 'MEDIAN_POINT'
kmi = km.items.add('wm.context_toggle', 'COMMA', 'PRESS', alt=True) kmi = km.items.new('wm.context_toggle', 'COMMA', 'PRESS', alt=True)
kmi.properties.data_path = 'space_data.use_pivot_point_align' kmi.properties.data_path = 'space_data.use_pivot_point_align'
kmi = km.items.add('wm.context_toggle', 'Q', 'PRESS') kmi = km.items.new('wm.context_toggle', 'Q', 'PRESS')
kmi.properties.data_path = 'space_data.show_manipulator' kmi.properties.data_path = 'space_data.show_manipulator'
kmi = km.items.add('wm.context_set_enum', 'PERIOD', 'PRESS') kmi = km.items.new('wm.context_set_enum', 'PERIOD', 'PRESS')
kmi.properties.data_path = 'space_data.pivot_point' kmi.properties.data_path = 'space_data.pivot_point'
kmi.properties.value = 'CURSOR' kmi.properties.value = 'CURSOR'
kmi = km.items.add('wm.context_set_enum', 'PERIOD', 'PRESS', ctrl=True) kmi = km.items.new('wm.context_set_enum', 'PERIOD', 'PRESS', ctrl=True)
kmi.properties.data_path = 'space_data.pivot_point' kmi.properties.data_path = 'space_data.pivot_point'
kmi.properties.value = 'INDIVIDUAL_ORIGINS' kmi.properties.value = 'INDIVIDUAL_ORIGINS'
kmi = km.items.add('wm.context_set_enum', 'PERIOD', 'PRESS', alt=True) kmi = km.items.new('wm.context_set_enum', 'PERIOD', 'PRESS', alt=True)
kmi.properties.data_path = 'space_data.pivot_point' kmi.properties.data_path = 'space_data.pivot_point'
kmi.properties.value = 'ACTIVE_ELEMENT' kmi.properties.value = 'ACTIVE_ELEMENT'
kmi = km.items.add('transform.translate', 'G', 'PRESS', shift=True) kmi = km.items.new('transform.translate', 'G', 'PRESS', shift=True)
kmi = km.items.add('transform.translate', 'EVT_TWEAK_S', 'ANY') kmi = km.items.new('transform.translate', 'EVT_TWEAK_S', 'ANY')
kmi = km.items.add('transform.rotate', 'R', 'PRESS', shift=True) kmi = km.items.new('transform.rotate', 'R', 'PRESS', shift=True)
kmi = km.items.add('transform.resize', 'S', 'PRESS', shift=True) kmi = km.items.new('transform.resize', 'S', 'PRESS', shift=True)
kmi = km.items.add('transform.warp', 'W', 'PRESS', shift=True) kmi = km.items.new('transform.warp', 'W', 'PRESS', shift=True)
kmi = km.items.add('transform.tosphere', 'S', 'PRESS', shift=True, alt=True) kmi = km.items.new('transform.tosphere', 'S', 'PRESS', shift=True, alt=True)
kmi = km.items.add('transform.shear', 'S', 'PRESS', shift=True, ctrl=True, alt=True) kmi = km.items.new('transform.shear', 'S', 'PRESS', shift=True, ctrl=True, alt=True)
kmi = km.items.add('transform.select_orientation', 'SPACE', 'PRESS', alt=True) kmi = km.items.new('transform.select_orientation', 'SPACE', 'PRESS', alt=True)
kmi = km.items.add('transform.create_orientation', 'SPACE', 'PRESS', ctrl=True, alt=True) kmi = km.items.new('transform.create_orientation', 'SPACE', 'PRESS', ctrl=True, alt=True)
kmi.properties.use = True kmi.properties.use = True
kmi = km.items.add('transform.mirror', 'M', 'PRESS', ctrl=True) kmi = km.items.new('transform.mirror', 'M', 'PRESS', ctrl=True)
kmi = km.items.add('wm.context_toggle', 'TAB', 'PRESS', shift=True) kmi = km.items.new('wm.context_toggle', 'TAB', 'PRESS', shift=True)
kmi.properties.data_path = 'tool_settings.snap' kmi.properties.data_path = 'tool_settings.use_snap'
kmi = km.items.add('transform.snap_type', 'TAB', 'PRESS', shift=True, ctrl=True) kmi = km.items.new('transform.snap_type', 'TAB', 'PRESS', shift=True, ctrl=True)
kmi = km.items.add('view3d.enable_manipulator', 'W', 'PRESS') kmi = km.items.new('view3d.enable_manipulator', 'W', 'PRESS')
kmi.properties.translate = True kmi.properties.translate = True
kmi = km.items.add('view3d.enable_manipulator', 'E', 'PRESS') kmi = km.items.new('view3d.enable_manipulator', 'E', 'PRESS')
kmi.properties.rotate = True kmi.properties.rotate = True
kmi = km.items.add('view3d.enable_manipulator', 'R', 'PRESS') kmi = km.items.new('view3d.enable_manipulator', 'R', 'PRESS')
kmi.properties.scale = True kmi.properties.scale = True
kmi = km.items.add('view3d.select_border', 'EVT_TWEAK_S', 'ANY', shift=True) kmi = km.items.new('view3d.select_border', 'EVT_TWEAK_S', 'ANY', shift=True)
kmi.properties.extend = True kmi.properties.extend = True
# Map Object Mode # Map Object Mode
km = kc.add_keymap('Object Mode', space_type='EMPTY', region_type='WINDOW', modal=False) km = kc.keymaps.new('Object Mode', space_type='EMPTY', region_type='WINDOW', modal=False)
kmi = km.items.add('wm.context_cycle_enum', 'O', 'PRESS', shift=True) kmi = km.items.new('wm.context_cycle_enum', 'O', 'PRESS', shift=True)
kmi.properties.data_path = 'tool_settings.proportional_edit_falloff' kmi.properties.data_path = 'tool_settings.proportional_edit_falloff'
kmi = km.items.add('wm.context_toggle_enum', 'O', 'PRESS') kmi = km.items.new('wm.context_toggle_enum', 'O', 'PRESS')
kmi.properties.data_path = 'tool_settings.proportional_edit' kmi.properties.data_path = 'tool_settings.proportional_edit'
kmi.properties.value_1 = 'DISABLED' kmi.properties.value_1 = 'DISABLED'
kmi.properties.value_2 = 'ENABLED' kmi.properties.value_2 = 'ENABLED'
kmi = km.items.add('view3d.game_start', 'P', 'PRESS') kmi = km.items.new('view3d.game_start', 'P', 'PRESS')
kmi = km.items.add('object.select_all', 'A', 'PRESS') kmi = km.items.new('object.select_all', 'A', 'PRESS')
kmi = km.items.add('object.select_inverse', 'I', 'PRESS', ctrl=True) kmi = km.items.new('object.select_inverse', 'I', 'PRESS', ctrl=True)
kmi = km.items.add('object.select_linked', 'L', 'PRESS', shift=True) kmi = km.items.new('object.select_linked', 'L', 'PRESS', shift=True)
kmi = km.items.add('object.select_grouped', 'G', 'PRESS', shift=True) kmi = km.items.new('object.select_grouped', 'G', 'PRESS', shift=True)
kmi = km.items.add('object.select_mirror', 'M', 'PRESS', shift=True, ctrl=True) kmi = km.items.new('object.select_mirror', 'M', 'PRESS', shift=True, ctrl=True)
kmi = km.items.add('object.select_hierarchy', 'LEFT_BRACKET', 'PRESS') kmi = km.items.new('object.select_hierarchy', 'LEFT_BRACKET', 'PRESS')
kmi.properties.direction = 'PARENT' kmi.properties.direction = 'PARENT'
kmi = km.items.add('object.select_hierarchy', 'LEFT_BRACKET', 'PRESS', shift=True) kmi = km.items.new('object.select_hierarchy', 'LEFT_BRACKET', 'PRESS', shift=True)
kmi.properties.direction = 'PARENT' kmi.properties.direction = 'PARENT'
kmi.properties.extend = True kmi.properties.extend = True
kmi = km.items.add('object.select_hierarchy', 'RIGHT_BRACKET', 'PRESS') kmi = km.items.new('object.select_hierarchy', 'RIGHT_BRACKET', 'PRESS')
kmi.properties.direction = 'CHILD' kmi.properties.direction = 'CHILD'
kmi = km.items.add('object.select_hierarchy', 'RIGHT_BRACKET', 'PRESS', shift=True) kmi = km.items.new('object.select_hierarchy', 'RIGHT_BRACKET', 'PRESS', shift=True)
kmi.properties.direction = 'CHILD' kmi.properties.direction = 'CHILD'
kmi.properties.extend = True kmi.properties.extend = True
kmi = km.items.add('object.parent_set', 'P', 'PRESS', ctrl=True) kmi = km.items.new('object.parent_set', 'P', 'PRESS', ctrl=True)
kmi = km.items.add('object.parent_no_inverse_set', 'P', 'PRESS', shift=True, ctrl=True) kmi = km.items.new('object.parent_no_inverse_set', 'P', 'PRESS', shift=True, ctrl=True)
kmi = km.items.add('object.parent_clear', 'P', 'PRESS', alt=True) kmi = km.items.new('object.parent_clear', 'P', 'PRESS', alt=True)
kmi = km.items.add('object.track_set', 'T', 'PRESS', ctrl=True) kmi = km.items.new('object.track_set', 'T', 'PRESS', ctrl=True)
kmi = km.items.add('object.track_clear', 'T', 'PRESS', alt=True) kmi = km.items.new('object.track_clear', 'T', 'PRESS', alt=True)
kmi = km.items.add('object.constraint_add_with_targets', 'C', 'PRESS', shift=True, ctrl=True) kmi = km.items.new('object.constraint_add_with_targets', 'C', 'PRESS', shift=True, ctrl=True)
kmi = km.items.add('object.constraints_clear', 'C', 'PRESS', ctrl=True, alt=True) kmi = km.items.new('object.constraints_clear', 'C', 'PRESS', ctrl=True, alt=True)
kmi = km.items.add('object.location_clear', 'G', 'PRESS', alt=True) kmi = km.items.new('object.location_clear', 'G', 'PRESS', alt=True)
kmi = km.items.add('object.rotation_clear', 'R', 'PRESS', alt=True) kmi = km.items.new('object.rotation_clear', 'R', 'PRESS', alt=True)
kmi = km.items.add('object.scale_clear', 'S', 'PRESS', alt=True) kmi = km.items.new('object.scale_clear', 'S', 'PRESS', alt=True)
kmi = km.items.add('object.origin_clear', 'O', 'PRESS', alt=True) kmi = km.items.new('object.origin_clear', 'O', 'PRESS', alt=True)
kmi = km.items.add('object.hide_view_clear', 'H', 'PRESS', alt=True) kmi = km.items.new('object.hide_view_clear', 'H', 'PRESS', alt=True)
kmi = km.items.add('object.hide_view_set', 'H', 'PRESS') kmi = km.items.new('object.hide_view_set', 'H', 'PRESS')
kmi = km.items.add('object.hide_view_set', 'H', 'PRESS', shift=True) kmi = km.items.new('object.hide_view_set', 'H', 'PRESS', shift=True)
kmi.properties.unselected = True kmi.properties.unselected = True
kmi = km.items.add('object.move_to_layer', 'M', 'PRESS') kmi = km.items.new('object.move_to_layer', 'M', 'PRESS')
kmi = km.items.add('object.delete', 'X', 'PRESS') kmi = km.items.new('object.delete', 'X', 'PRESS')
kmi = km.items.add('object.delete', 'DEL', 'PRESS') kmi = km.items.new('object.delete', 'DEL', 'PRESS')
kmi = km.items.add('wm.call_menu', 'A', 'PRESS', shift=True) kmi = km.items.new('wm.call_menu', 'A', 'PRESS', shift=True)
kmi.properties.name = 'INFO_MT_add' kmi.properties.name = 'INFO_MT_add'
kmi = km.items.add('object.duplicates_make_real', 'A', 'PRESS', shift=True, ctrl=True) kmi = km.items.new('object.duplicates_make_real', 'A', 'PRESS', shift=True, ctrl=True)
kmi = km.items.add('wm.call_menu', 'A', 'PRESS', ctrl=True) kmi = km.items.new('wm.call_menu', 'A', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_object_apply' kmi.properties.name = 'VIEW3D_MT_object_apply'
kmi = km.items.add('wm.call_menu', 'U', 'PRESS') kmi = km.items.new('wm.call_menu', 'U', 'PRESS')
kmi.properties.name = 'VIEW3D_MT_make_single_user' kmi.properties.name = 'VIEW3D_MT_make_single_user'
kmi = km.items.add('wm.call_menu', 'L', 'PRESS', ctrl=True) kmi = km.items.new('wm.call_menu', 'L', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_make_links' kmi.properties.name = 'VIEW3D_MT_make_links'
kmi = km.items.add('object.duplicate_move', 'D', 'PRESS', shift=True) kmi = km.items.new('object.duplicate_move', 'D', 'PRESS', shift=True)
kmi = km.items.add('object.duplicate_move_linked', 'D', 'PRESS', alt=True) kmi = km.items.new('object.duplicate_move_linked', 'D', 'PRESS', alt=True)
kmi = km.items.add('object.join', 'J', 'PRESS', ctrl=True) kmi = km.items.new('object.join', 'J', 'PRESS', ctrl=True)
kmi = km.items.add('object.convert', 'C', 'PRESS', alt=True) kmi = km.items.new('object.convert', 'C', 'PRESS', alt=True)
kmi = km.items.add('object.proxy_make', 'P', 'PRESS', ctrl=True, alt=True) kmi = km.items.new('object.proxy_make', 'P', 'PRESS', ctrl=True, alt=True)
kmi = km.items.add('object.make_local', 'L', 'PRESS') kmi = km.items.new('object.make_local', 'L', 'PRESS')
kmi = km.items.add('anim.keyframe_insert_menu', 'I', 'PRESS') kmi = km.items.new('anim.keyframe_insert_menu', 'I', 'PRESS')
kmi = km.items.add('anim.keyframe_delete_v3d', 'I', 'PRESS', alt=True) kmi = km.items.new('anim.keyframe_delete_v3d', 'I', 'PRESS', alt=True)
kmi = km.items.add('anim.keying_set_active_set', 'I', 'PRESS', shift=True, ctrl=True, alt=True) kmi = km.items.new('anim.keying_set_active_set', 'I', 'PRESS', shift=True, ctrl=True, alt=True)
kmi = km.items.add('group.create', 'G', 'PRESS', ctrl=True) kmi = km.items.new('group.create', 'G', 'PRESS', ctrl=True)
kmi = km.items.add('group.objects_remove', 'G', 'PRESS', ctrl=True, alt=True) kmi = km.items.new('group.objects_remove', 'G', 'PRESS', ctrl=True, alt=True)
kmi = km.items.add('group.objects_add_active', 'G', 'PRESS', shift=True, ctrl=True) kmi = km.items.new('group.objects_add_active', 'G', 'PRESS', shift=True, ctrl=True)
kmi = km.items.add('group.objects_remove_active', 'G', 'PRESS', shift=True, alt=True) kmi = km.items.new('group.objects_remove_active', 'G', 'PRESS', shift=True, alt=True)
kmi = km.items.add('wm.call_menu', 'W', 'PRESS', ctrl=True) kmi = km.items.new('wm.call_menu', 'W', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_object_specials' kmi.properties.name = 'VIEW3D_MT_object_specials'
kmi = km.items.add('object.subdivision_set', 'ZERO', 'PRESS', ctrl=True) kmi = km.items.new('object.subdivision_set', 'ZERO', 'PRESS', ctrl=True)
kmi.properties.level = 0 kmi.properties.level = 0
kmi = km.items.add('object.subdivision_set', 'ONE', 'PRESS', ctrl=True) kmi = km.items.new('object.subdivision_set', 'ONE', 'PRESS', ctrl=True)
kmi.properties.level = 1 kmi.properties.level = 1
kmi = km.items.add('object.subdivision_set', 'TWO', 'PRESS', ctrl=True) kmi = km.items.new('object.subdivision_set', 'TWO', 'PRESS', ctrl=True)
kmi.properties.level = 2 kmi.properties.level = 2
kmi = km.items.add('object.subdivision_set', 'THREE', 'PRESS', ctrl=True) kmi = km.items.new('object.subdivision_set', 'THREE', 'PRESS', ctrl=True)
kmi.properties.level = 3 kmi.properties.level = 3
kmi = km.items.add('object.subdivision_set', 'FOUR', 'PRESS', ctrl=True) kmi = km.items.new('object.subdivision_set', 'FOUR', 'PRESS', ctrl=True)
kmi.properties.level = 4 kmi.properties.level = 4
kmi = km.items.add('object.subdivision_set', 'FIVE', 'PRESS', ctrl=True) kmi = km.items.new('object.subdivision_set', 'FIVE', 'PRESS', ctrl=True)
kmi.properties.level = 5 kmi.properties.level = 5
kmi = km.items.add('object.select_all', 'SELECTMOUSE', 'CLICK') kmi = km.items.new('object.select_all', 'SELECTMOUSE', 'CLICK')
kmi.properties.action = 'DESELECT' kmi.properties.action = 'DESELECT'
# Map Mesh # Map Mesh
km = kc.add_keymap('Mesh', space_type='EMPTY', region_type='WINDOW', modal=False) km = kc.keymaps.new('Mesh', space_type='EMPTY', region_type='WINDOW', modal=False)
kmi = km.items.add('mesh.loopcut_slide', 'R', 'PRESS', ctrl=True) kmi = km.items.new('mesh.loopcut_slide', 'R', 'PRESS', ctrl=True)
kmi = km.items.add('mesh.loop_select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True) kmi = km.items.new('mesh.loop_select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True)
kmi = km.items.add('mesh.loop_select', 'SELECTMOUSE', 'PRESS', shift=True, alt=True) kmi = km.items.new('mesh.loop_select', 'SELECTMOUSE', 'PRESS', shift=True, alt=True)
kmi.properties.extend = True kmi.properties.extend = True
kmi = km.items.add('mesh.edgering_select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True) kmi = km.items.new('mesh.edgering_select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True)
kmi = km.items.add('mesh.edgering_select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True) kmi = km.items.new('mesh.edgering_select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True)
kmi.properties.extend = True kmi.properties.extend = True
kmi = km.items.add('mesh.select_shortest_path', 'SELECTMOUSE', 'PRESS', ctrl=True) kmi = km.items.new('mesh.select_shortest_path', 'SELECTMOUSE', 'PRESS', ctrl=True)
kmi = km.items.add('mesh.select_all', 'A', 'PRESS') kmi = km.items.new('mesh.select_all', 'A', 'PRESS')
kmi = km.items.add('mesh.select_more', 'NUMPAD_PLUS', 'PRESS', ctrl=True) kmi = km.items.new('mesh.select_more', 'NUMPAD_PLUS', 'PRESS', ctrl=True)
kmi = km.items.add('mesh.select_less', 'NUMPAD_MINUS', 'PRESS', ctrl=True) kmi = km.items.new('mesh.select_less', 'NUMPAD_MINUS', 'PRESS', ctrl=True)
kmi = km.items.add('mesh.select_inverse', 'I', 'PRESS', ctrl=True) kmi = km.items.new('mesh.select_inverse', 'I', 'PRESS', ctrl=True)
kmi = km.items.add('mesh.select_non_manifold', 'M', 'PRESS', shift=True, ctrl=True, alt=True) kmi = km.items.new('mesh.select_non_manifold', 'M', 'PRESS', shift=True, ctrl=True, alt=True)
kmi = km.items.add('mesh.select_linked', 'L', 'PRESS', ctrl=True) kmi = km.items.new('mesh.select_linked', 'L', 'PRESS', ctrl=True)
kmi = km.items.add('mesh.select_linked_pick', 'L', 'PRESS') kmi = km.items.new('mesh.select_linked_pick', 'L', 'PRESS')
kmi = km.items.add('mesh.select_linked_pick', 'L', 'PRESS', shift=True) kmi = km.items.new('mesh.select_linked_pick', 'L', 'PRESS', shift=True)
kmi.properties.deselect = True kmi.properties.deselect = True
kmi = km.items.add('mesh.faces_select_linked_flat', 'F', 'PRESS', shift=True, ctrl=True, alt=True) kmi = km.items.new('mesh.faces_select_linked_flat', 'F', 'PRESS', shift=True, ctrl=True, alt=True)
kmi.properties.sharpness = 135.0 kmi.properties.sharpness = 135.0
kmi = km.items.add('mesh.select_similar', 'G', 'PRESS', shift=True) kmi = km.items.new('mesh.select_similar', 'G', 'PRESS', shift=True)
kmi = km.items.add('wm.call_menu', 'TAB', 'PRESS', ctrl=True) kmi = km.items.new('wm.call_menu', 'TAB', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_selection_mode' kmi.properties.name = 'VIEW3D_MT_edit_mesh_selection_mode'
kmi = km.items.add('mesh.hide', 'H', 'PRESS') kmi = km.items.new('mesh.hide', 'H', 'PRESS')
kmi = km.items.add('mesh.hide', 'H', 'PRESS', shift=True) kmi = km.items.new('mesh.hide', 'H', 'PRESS', shift=True)
kmi.properties.unselected = True kmi.properties.unselected = True
kmi = km.items.add('mesh.reveal', 'H', 'PRESS', alt=True) kmi = km.items.new('mesh.reveal', 'H', 'PRESS', alt=True)
kmi = km.items.add('mesh.normals_make_consistent', 'N', 'PRESS', ctrl=True) kmi = km.items.new('mesh.normals_make_consistent', 'N', 'PRESS', ctrl=True)
kmi = km.items.add('mesh.normals_make_consistent', 'N', 'PRESS', shift=True, ctrl=True) kmi = km.items.new('mesh.normals_make_consistent', 'N', 'PRESS', shift=True, ctrl=True)
kmi.properties.inside = True kmi.properties.inside = True
kmi = km.items.add('view3d.edit_mesh_extrude_move_normal', 'E', 'PRESS', ctrl=True) kmi = km.items.new('view3d.edit_mesh_extrude_move_normal', 'E', 'PRESS', ctrl=True)
kmi = km.items.add('view3d.edit_mesh_extrude_individual_move', 'E', 'PRESS', shift=True) kmi = km.items.new('view3d.edit_mesh_extrude_individual_move', 'E', 'PRESS', shift=True)
kmi = km.items.add('wm.call_menu', 'E', 'PRESS', alt=True) kmi = km.items.new('wm.call_menu', 'E', 'PRESS', alt=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_extrude' kmi.properties.name = 'VIEW3D_MT_edit_mesh_extrude'
kmi = km.items.add('mesh.spin', 'R', 'PRESS', alt=True) kmi = km.items.new('mesh.spin', 'R', 'PRESS', alt=True)
kmi = km.items.add('mesh.fill', 'F', 'PRESS', alt=True) kmi = km.items.new('mesh.fill', 'F', 'PRESS', alt=True)
kmi = km.items.add('mesh.beautify_fill', 'F', 'PRESS', shift=True, alt=True) kmi = km.items.new('mesh.beautify_fill', 'F', 'PRESS', shift=True, alt=True)
kmi = km.items.add('mesh.quads_convert_to_tris', 'T', 'PRESS', ctrl=True) kmi = km.items.new('mesh.quads_convert_to_tris', 'T', 'PRESS', ctrl=True)
kmi = km.items.add('mesh.tris_convert_to_quads', 'J', 'PRESS', alt=True) kmi = km.items.new('mesh.tris_convert_to_quads', 'J', 'PRESS', alt=True)
kmi = km.items.add('mesh.edge_flip', 'F', 'PRESS', shift=True, ctrl=True) kmi = km.items.new('mesh.edge_flip', 'F', 'PRESS', shift=True, ctrl=True)
kmi = km.items.add('mesh.rip_move', 'V', 'PRESS') kmi = km.items.new('mesh.rip_move', 'V', 'PRESS')
kmi = km.items.add('mesh.merge', 'M', 'PRESS', alt=True) kmi = km.items.new('mesh.merge', 'M', 'PRESS', alt=True)
kmi = km.items.add('transform.shrink_fatten', 'S', 'PRESS', ctrl=True, alt=True) kmi = km.items.new('transform.shrink_fatten', 'S', 'PRESS', ctrl=True, alt=True)
kmi = km.items.add('mesh.edge_face_add', 'F', 'PRESS') kmi = km.items.new('mesh.edge_face_add', 'F', 'PRESS')
kmi = km.items.add('mesh.duplicate_move', 'D', 'PRESS', shift=True) kmi = km.items.new('mesh.duplicate_move', 'D', 'PRESS', shift=True)
kmi = km.items.add('wm.call_menu', 'A', 'PRESS', shift=True) kmi = km.items.new('wm.call_menu', 'A', 'PRESS', shift=True)
kmi.properties.name = 'INFO_MT_mesh_add' kmi.properties.name = 'INFO_MT_mesh_add'
kmi = km.items.add('mesh.separate', 'P', 'PRESS') kmi = km.items.new('mesh.separate', 'P', 'PRESS')
kmi = km.items.add('mesh.split', 'Y', 'PRESS') kmi = km.items.new('mesh.split', 'Y', 'PRESS')
kmi = km.items.add('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', ctrl=True) kmi = km.items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', ctrl=True)
kmi = km.items.add('mesh.delete', 'X', 'PRESS') kmi = km.items.new('mesh.delete', 'X', 'PRESS')
kmi = km.items.add('mesh.delete', 'DEL', 'PRESS') kmi = km.items.new('mesh.delete', 'DEL', 'PRESS')
kmi = km.items.add('mesh.knife_cut', 'LEFTMOUSE', 'PRESS', key_modifier='K') kmi = km.items.new('mesh.knife_cut', 'LEFTMOUSE', 'PRESS', key_modifier='K')
kmi = km.items.add('mesh.knife_cut', 'LEFTMOUSE', 'PRESS', shift=True, key_modifier='K') kmi = km.items.new('mesh.knife_cut', 'LEFTMOUSE', 'PRESS', shift=True, key_modifier='K')
kmi.properties.type = 'MIDPOINTS' kmi.properties.type = 'MIDPOINTS'
kmi = km.items.add('object.vertex_parent_set', 'P', 'PRESS', ctrl=True) kmi = km.items.new('object.vertex_parent_set', 'P', 'PRESS', ctrl=True)
kmi = km.items.add('wm.call_menu', 'W', 'PRESS', ctrl=True) kmi = km.items.new('wm.call_menu', 'W', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_specials' kmi.properties.name = 'VIEW3D_MT_edit_mesh_specials'
kmi = km.items.add('wm.call_menu', 'F', 'PRESS', ctrl=True) kmi = km.items.new('wm.call_menu', 'F', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_faces' kmi.properties.name = 'VIEW3D_MT_edit_mesh_faces'
kmi = km.items.add('wm.call_menu', 'E', 'PRESS', ctrl=True) kmi = km.items.new('wm.call_menu', 'E', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_edges' kmi.properties.name = 'VIEW3D_MT_edit_mesh_edges'
kmi = km.items.add('wm.call_menu', 'V', 'PRESS', ctrl=True) kmi = km.items.new('wm.call_menu', 'V', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_vertices' kmi.properties.name = 'VIEW3D_MT_edit_mesh_vertices'
kmi = km.items.add('wm.call_menu', 'H', 'PRESS', ctrl=True) kmi = km.items.new('wm.call_menu', 'H', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_hook' kmi.properties.name = 'VIEW3D_MT_hook'
kmi = km.items.add('wm.call_menu', 'U', 'PRESS') kmi = km.items.new('wm.call_menu', 'U', 'PRESS')
kmi.properties.name = 'VIEW3D_MT_uv_map' kmi.properties.name = 'VIEW3D_MT_uv_map'
kmi = km.items.add('wm.call_menu', 'G', 'PRESS', ctrl=True) kmi = km.items.new('wm.call_menu', 'G', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_vertex_group' kmi.properties.name = 'VIEW3D_MT_vertex_group'
kmi = km.items.add('wm.context_cycle_enum', 'O', 'PRESS', shift=True) kmi = km.items.new('wm.context_cycle_enum', 'O', 'PRESS', shift=True)
kmi.properties.data_path = 'tool_settings.proportional_edit_falloff' kmi.properties.data_path = 'tool_settings.proportional_edit_falloff'
kmi = km.items.add('wm.context_toggle_enum', 'O', 'PRESS') kmi = km.items.new('wm.context_toggle_enum', 'O', 'PRESS')
kmi.properties.data_path = 'tool_settings.proportional_edit' kmi.properties.data_path = 'tool_settings.proportional_edit'
kmi.properties.value_1 = 'DISABLED' kmi.properties.value_1 = 'DISABLED'
kmi.properties.value_2 = 'ENABLED' kmi.properties.value_2 = 'ENABLED'
kmi = km.items.add('wm.context_toggle_enum', 'O', 'PRESS', alt=True) kmi = km.items.new('wm.context_toggle_enum', 'O', 'PRESS', alt=True)
kmi.properties.data_path = 'tool_settings.proportional_edit' kmi.properties.data_path = 'tool_settings.proportional_edit'
kmi.properties.value_1 = 'DISABLED' kmi.properties.value_1 = 'DISABLED'
kmi.properties.value_2 = 'CONNECTED' kmi.properties.value_2 = 'CONNECTED'
kmi = km.items.add('mesh.select_all', 'SELECTMOUSE', 'CLICK') kmi = km.items.new('mesh.select_all', 'SELECTMOUSE', 'CLICK')
kmi.properties.action = 'DESELECT' kmi.properties.action = 'DESELECT'
wm.keyconfigs.active = kc wm.keyconfigs.active = kc

View File

@@ -38,7 +38,7 @@ class ExportSomeData(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
def invoke(self, context, event): def invoke(self, context, event):
wm = context.manager wm = context.window_manager
if True: if True:
# File selector # File selector

View File

@@ -25,7 +25,7 @@ class ModalOperator(bpy.types.Operator):
def invoke(self, context, event): def invoke(self, context, event):
if context.object: if context.object:
context.manager.add_modal_handler(self) context.window_manager.add_modal_handler(self)
self.properties.first_mouse_x = event.mouse_x self.properties.first_mouse_x = event.mouse_x
self.properties.first_value = context.object.location.x self.properties.first_value = context.object.location.x
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}

View File

@@ -52,7 +52,7 @@ class ModalDrawOperator(bpy.types.Operator):
def invoke(self, context, event): def invoke(self, context, event):
if context.area.type == 'VIEW_3D': if context.area.type == 'VIEW_3D':
context.manager.add_modal_handler(self) context.window_manager.add_modal_handler(self)
# Add the region OpenGL drawing callback # Add the region OpenGL drawing callback
# draw in view space with 'POST_VIEW' and 'PRE_VIEW' # draw in view space with 'POST_VIEW' and 'PRE_VIEW'

View File

@@ -39,7 +39,7 @@ class ViewOperator(bpy.types.Operator):
v3d = context.space_data v3d = context.space_data
rv3d = v3d.region_3d rv3d = v3d.region_3d
context.manager.add_modal_handler(self) context.window_manager.add_modal_handler(self)
if rv3d.view_perspective == 'CAMERA': if rv3d.view_perspective == 'CAMERA':
rv3d.view_perspective = 'PERSP' rv3d.view_perspective = 'PERSP'

View File

@@ -250,7 +250,7 @@ class AsScript(bpy.types.Operator):
import os import os
obj = context.object obj = context.object
self.properties.filepath = os.path.splitext(bpy.data.filepath)[0] + "-" + bpy.path.clean_name(obj.name) + ".py" self.properties.filepath = os.path.splitext(bpy.data.filepath)[0] + "-" + bpy.path.clean_name(obj.name) + ".py"
wm = context.manager wm = context.window_manager
wm.add_fileselect(self) wm.add_fileselect(self)
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}

View File

@@ -54,13 +54,15 @@ class DATA_PT_context_lamp(DataButtonsPanel, bpy.types.Panel):
split = layout.split(percentage=0.65) split = layout.split(percentage=0.65)
texture_count = len(lamp.texture_slots.keys())
if ob: if ob:
split.template_ID(ob, "data") split.template_ID(ob, "data")
split.separator()
elif lamp: elif lamp:
split.template_ID(space, "pin_id") split.template_ID(space, "pin_id")
split.separator()
if texture_count != 0:
split.label(text=str(texture_count), icon='TEXTURE')
class DATA_PT_preview(DataButtonsPanel, bpy.types.Panel): class DATA_PT_preview(DataButtonsPanel, bpy.types.Panel):
bl_label = "Preview" bl_label = "Preview"

View File

@@ -755,7 +755,6 @@ class VolumeButtonsPanel():
class MATERIAL_PT_volume_density(VolumeButtonsPanel, bpy.types.Panel): class MATERIAL_PT_volume_density(VolumeButtonsPanel, bpy.types.Panel):
bl_label = "Density" bl_label = "Density"
bl_default_closed = False
COMPAT_ENGINES = {'BLENDER_RENDER'} COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw(self, context): def draw(self, context):
@@ -773,7 +772,6 @@ class MATERIAL_PT_volume_density(VolumeButtonsPanel, bpy.types.Panel):
class MATERIAL_PT_volume_shading(VolumeButtonsPanel, bpy.types.Panel): class MATERIAL_PT_volume_shading(VolumeButtonsPanel, bpy.types.Panel):
bl_label = "Shading" bl_label = "Shading"
bl_default_closed = False
COMPAT_ENGINES = {'BLENDER_RENDER'} COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw(self, context): def draw(self, context):
@@ -799,7 +797,6 @@ class MATERIAL_PT_volume_shading(VolumeButtonsPanel, bpy.types.Panel):
class MATERIAL_PT_volume_lighting(VolumeButtonsPanel, bpy.types.Panel): class MATERIAL_PT_volume_lighting(VolumeButtonsPanel, bpy.types.Panel):
bl_label = "Lighting" bl_label = "Lighting"
bl_default_closed = False
COMPAT_ENGINES = {'BLENDER_RENDER'} COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw(self, context): def draw(self, context):
@@ -847,7 +844,6 @@ class MATERIAL_PT_volume_transp(VolumeButtonsPanel, bpy.types.Panel):
class MATERIAL_PT_volume_integration(VolumeButtonsPanel, bpy.types.Panel): class MATERIAL_PT_volume_integration(VolumeButtonsPanel, bpy.types.Panel):
bl_label = "Integration" bl_label = "Integration"
bl_default_closed = False
COMPAT_ENGINES = {'BLENDER_RENDER'} COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw(self, context): def draw(self, context):

View File

@@ -142,7 +142,7 @@ class OBJECT_PT_groups(ObjectButtonsPanel, bpy.types.Panel):
if ob.name in group.objects: if ob.name in group.objects:
col = layout.column(align=True) col = layout.column(align=True)
col.set_context_pointer("group", group) col.context_pointer_set("group", group)
row = col.box().row() row = col.box().row()
row.prop(group, "name", text="") row.prop(group, "name", text="")

View File

@@ -487,12 +487,12 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
col.prop(boids, "air_ave_max", slider=True) col.prop(boids, "air_ave_max", slider=True)
col.prop(boids, "air_personal_space") col.prop(boids, "air_personal_space")
row = col.row() row = col.row()
row.active = (boids.use_land or boids.allow_climb) and boids.allow_flight row.active = (boids.use_land or boids.use_climb) and boids.use_flight
row.prop(boids, "land_smooth") row.prop(boids, "land_smooth")
sub = split.column() sub = split.column()
col = sub.column(align=True) col = sub.column(align=True)
col.active = boids.use_land or boids.allow_climb col.active = boids.use_land or boids.use_climb
col.prop(boids, "land_speed_max") col.prop(boids, "land_speed_max")
col.prop(boids, "land_jump_speed") col.prop(boids, "land_jump_speed")
col.prop(boids, "land_acc_max", slider=True) col.prop(boids, "land_acc_max", slider=True)
@@ -862,6 +862,15 @@ class PARTICLE_PT_draw(ParticleButtonsPanel, bpy.types.Panel):
else: else:
row.label(text="") row.label(text="")
if part.draw_percentage != 100:
if part.type == 'HAIR':
if psys.hair_dynamics and psys.point_cache.is_baked == False:
layout.row().label(text="Display percentage makes dynamics inaccurate without baking!")
else:
phystype = part.physics_type
if phystype != 'NO' and phystype != 'KEYED' and psys.point_cache.is_baked == False:
layout.row().label(text="Display percentage makes dynamics inaccurate without baking!")
row = layout.row() row = layout.row()
col = row.column() col = row.column()
col.prop(part, "show_size") col.prop(part, "show_size")
@@ -1028,9 +1037,10 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, bpy.types.Panel):
row.prop_search(psys, "vertex_group_density", ob, "vertex_groups", text="Density") row.prop_search(psys, "vertex_group_density", ob, "vertex_groups", text="Density")
row.prop(psys, "invert_vertex_group_density", text="") row.prop(psys, "invert_vertex_group_density", text="")
row = layout.row() # Commented out vertex groups don't work and are still waiting for better implementation
row.prop_search(psys, "vertex_group_velocity", ob, "vertex_groups", text="Velocity") # row = layout.row()
row.prop(psys, "invert_vertex_group_velocity", text="") # row.prop_search(psys, "vertex_group_velocity", ob, "vertex_groups", text="Velocity")
# row.prop(psys, "invert_vertex_group_velocity", text="")
row = layout.row() row = layout.row()
row.prop_search(psys, "vertex_group_length", ob, "vertex_groups", text="Length") row.prop_search(psys, "vertex_group_length", ob, "vertex_groups", text="Length")
@@ -1056,21 +1066,21 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, bpy.types.Panel):
row.prop_search(psys, "vertex_group_roughness_end", ob, "vertex_groups", text="Roughness End") row.prop_search(psys, "vertex_group_roughness_end", ob, "vertex_groups", text="Roughness End")
row.prop(psys, "invert_vertex_group_roughness_end", text="") row.prop(psys, "invert_vertex_group_roughness_end", text="")
row = layout.row() # row = layout.row()
row.prop_search(psys, "vertex_group_size", ob, "vertex_groups", text="Size") # row.prop_search(psys, "vertex_group_size", ob, "vertex_groups", text="Size")
row.prop(psys, "invert_vertex_group_size", text="") # row.prop(psys, "invert_vertex_group_size", text="")
row = layout.row() # row = layout.row()
row.prop_search(psys, "vertex_group_tangent", ob, "vertex_groups", text="Tangent") # row.prop_search(psys, "vertex_group_tangent", ob, "vertex_groups", text="Tangent")
row.prop(psys, "invert_vertex_group_tangent", text="") # row.prop(psys, "invert_vertex_group_tangent", text="")
row = layout.row() # row = layout.row()
row.prop_search(psys, "vertex_group_rotation", ob, "vertex_groups", text="Rotation") # row.prop_search(psys, "vertex_group_rotation", ob, "vertex_groups", text="Rotation")
row.prop(psys, "invert_vertex_group_rotation", text="") # row.prop(psys, "invert_vertex_group_rotation", text="")
row = layout.row() # row = layout.row()
row.prop_search(psys, "vertex_group_field", ob, "vertex_groups", text="Field") # row.prop_search(psys, "vertex_group_field", ob, "vertex_groups", text="Field")
row.prop(psys, "invert_vertex_group_field", text="") # row.prop(psys, "invert_vertex_group_field", text="")
class PARTICLE_PT_custom_props(ParticleButtonsPanel, PropertyPanel, bpy.types.Panel): class PARTICLE_PT_custom_props(ParticleButtonsPanel, PropertyPanel, bpy.types.Panel):

View File

@@ -63,7 +63,7 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, bpy.types.Panel):
if md: if md:
# remove modifier + settings # remove modifier + settings
split.set_context_pointer("modifier", md) split.context_pointer_set("modifier", md)
split.operator("object.modifier_remove", text="Remove") split.operator("object.modifier_remove", text="Remove")
row = split.row(align=True) row = split.row(align=True)
@@ -105,7 +105,7 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, bpy.types.Panel):
col.prop(cloth, "use_pin_cloth", text="Pinning") col.prop(cloth, "use_pin_cloth", text="Pinning")
sub = col.column() sub = col.column()
sub.active = cloth.use_pin_cloth sub.active = cloth.use_pin_cloth
sub.prop_search(cloth, "mass_vertex_group", ob, "vertex_groups", text="") sub.prop_search(cloth, "vertex_group_mass", ob, "vertex_groups", text="")
sub.prop(cloth, "pin_stiffness", text="Stiffness") sub.prop(cloth, "pin_stiffness", text="Stiffness")
col.label(text="Pre roll:") col.label(text="Pre roll:")
@@ -113,7 +113,7 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, bpy.types.Panel):
# Disabled for now # Disabled for now
""" """
if cloth.mass_vertex_group: if cloth.vertex_group_mass:
layout.label(text="Goal:") layout.label(text="Goal:")
col = layout.column_flow() col = layout.column_flow()
@@ -208,12 +208,12 @@ class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, bpy.types.Panel):
col = split.column() col = split.column()
col.label(text="Structural Stiffness:") col.label(text="Structural Stiffness:")
col.prop_search(cloth, "structural_stiffness_vertex_group", ob, "vertex_groups", text="") col.prop_search(cloth, "vertex_group_structural_stiffness", ob, "vertex_groups", text="")
col.prop(cloth, "structural_stiffness_max", text="Max") col.prop(cloth, "structural_stiffness_max", text="Max")
col = split.column() col = split.column()
col.label(text="Bending Stiffness:") col.label(text="Bending Stiffness:")
col.prop_search(cloth, "bending_vertex_group", ob, "vertex_groups", text="") col.prop_search(cloth, "vertex_group_bending", ob, "vertex_groups", text="")
col.prop(cloth, "bending_stiffness_max", text="Max") col.prop(cloth, "bending_stiffness_max", text="Max")

View File

@@ -26,7 +26,7 @@ import bpy
def point_cache_ui(self, context, cache, enabled, cachetype): def point_cache_ui(self, context, cache, enabled, cachetype):
layout = self.layout layout = self.layout
layout.set_context_pointer("point_cache", cache) layout.context_pointer_set("point_cache", cache)
row = layout.row() row = layout.row()
row.template_list(cache, "point_caches", cache.point_caches, "active_index", rows=2) row.template_list(cache, "point_caches", cache.point_caches, "active_index", rows=2)

View File

@@ -175,7 +175,7 @@ class PHYSICS_PT_collision(PhysicButtonsPanel, bpy.types.Panel):
if md: if md:
# remove modifier + settings # remove modifier + settings
split.set_context_pointer("modifier", md) split.context_pointer_set("modifier", md)
split.operator("object.modifier_remove", text="Remove") split.operator("object.modifier_remove", text="Remove")
col = split.column() col = split.column()

View File

@@ -44,7 +44,7 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, bpy.types.Panel):
if md: if md:
# remove modifier + settings # remove modifier + settings
split.set_context_pointer("modifier", md) split.context_pointer_set("modifier", md)
split.operator("object.modifier_remove", text="Remove") split.operator("object.modifier_remove", text="Remove")
row = split.row(align=True) row = split.row(align=True)
@@ -58,10 +58,8 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, bpy.types.Panel):
split.operator("object.modifier_add", text="Add").type = 'FLUID_SIMULATION' split.operator("object.modifier_add", text="Add").type = 'FLUID_SIMULATION'
split.label() split.label()
fluid = None
if md:
if fluid:
row = layout.row() row = layout.row()
row.prop(fluid, "type") row.prop(fluid, "type")
if fluid.type not in ('NONE', 'DOMAIN', 'PARTICLE'): if fluid.type not in ('NONE', 'DOMAIN', 'PARTICLE'):
@@ -72,7 +70,7 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, bpy.types.Panel):
layout.active = fluid.use layout.active = fluid.use
if fluid.type == 'DOMAIN': if fluid.type == 'DOMAIN':
layout.operator("fluid.bake", text="Bake Fluid Simulation", icon='MOD_FLUIDSIM') layout.operator("fluid.bake", text="Bake (Req. Memory: %s)" % fluid.memory_estimate, icon='MOD_FLUIDSIM')
split = layout.split() split = layout.split()
col = split.column() col = split.column()
@@ -82,7 +80,7 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, bpy.types.Panel):
col.prop(fluid, "render_display_mode", text="") col.prop(fluid, "render_display_mode", text="")
col = split.column() col = split.column()
col.label(text="Required Memory: " + fluid.memory_estimate) col.label()
col.prop(fluid, "preview_resolution", text="Preview") col.prop(fluid, "preview_resolution", text="Preview")
col.label(text="Viewport Display:") col.label(text="Viewport Display:")
col.prop(fluid, "viewport_display_mode", text="") col.prop(fluid, "viewport_display_mode", text="")

View File

@@ -49,7 +49,7 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, bpy.types.Panel):
if md: if md:
# remove modifier + settings # remove modifier + settings
split.set_context_pointer("modifier", md) split.context_pointer_set("modifier", md)
split.operator("object.modifier_remove", text="Remove") split.operator("object.modifier_remove", text="Remove")
row = split.row(align=True) row = split.row(align=True)

View File

@@ -55,7 +55,7 @@ class PHYSICS_PT_softbody(PhysicButtonsPanel, bpy.types.Panel):
if md: if md:
# remove modifier + settings # remove modifier + settings
split.set_context_pointer("modifier", md) split.context_pointer_set("modifier", md)
split.operator("object.modifier_remove", text="Remove") split.operator("object.modifier_remove", text="Remove")
row = split.row(align=True) row = split.row(align=True)
@@ -77,7 +77,7 @@ class PHYSICS_PT_softbody(PhysicButtonsPanel, bpy.types.Panel):
col.label(text="Object:") col.label(text="Object:")
col.prop(softbody, "friction") col.prop(softbody, "friction")
col.prop(softbody, "mass") col.prop(softbody, "mass")
col.prop_search(softbody, "mass_vertex_group", ob, "vertex_groups", text="Mass:") col.prop_search(softbody, "vertex_group_mass", ob, "vertex_groups", text="Mass:")
col = split.column() col = split.column()
col.label(text="Simulation:") col.label(text="Simulation:")
@@ -137,7 +137,7 @@ class PHYSICS_PT_softbody_goal(PhysicButtonsPanel, bpy.types.Panel):
col.prop(softbody, "goal_spring", text="Stiffness") col.prop(softbody, "goal_spring", text="Stiffness")
col.prop(softbody, "goal_friction", text="Damping") col.prop(softbody, "goal_friction", text="Damping")
layout.prop_search(softbody, "goal_vertex_group", ob, "vertex_groups", text="Vertex Group") layout.prop_search(softbody, "vertex_group_goal", ob, "vertex_groups", text="Vertex Group")
class PHYSICS_PT_softbody_edge(PhysicButtonsPanel, bpy.types.Panel): class PHYSICS_PT_softbody_edge(PhysicButtonsPanel, bpy.types.Panel):
@@ -173,7 +173,7 @@ class PHYSICS_PT_softbody_edge(PhysicButtonsPanel, bpy.types.Panel):
col.prop(softbody, "plastic") col.prop(softbody, "plastic")
col.prop(softbody, "bend") col.prop(softbody, "bend")
col.prop(softbody, "spring_length", text="Length") col.prop(softbody, "spring_length", text="Length")
col.prop_search(softbody, "spring_vertex_group", ob, "vertex_groups", text="Springs:") col.prop_search(softbody, "vertex_group_spring", ob, "vertex_groups", text="Springs:")
col = split.column() col = split.column()
col.prop(softbody, "use_stiff_quads") col.prop(softbody, "use_stiff_quads")

View File

@@ -238,7 +238,7 @@ class ANIM_OT_keying_set_export(bpy.types.Operator):
# Add KeyingSet and set general settings # Add KeyingSet and set general settings
f.write("# Keying Set Level declarations\n") f.write("# Keying Set Level declarations\n")
f.write("ks= scene.add_keying_set(name=\"%s\")\n" % ks.name) f.write("ks= scene.keying_sets.new(name=\"%s\")\n" % ks.name)
if not ks.is_path_absolute: if not ks.is_path_absolute:
f.write("ks.is_path_absolute = False\n") f.write("ks.is_path_absolute = False\n")
@@ -314,7 +314,7 @@ class ANIM_OT_keying_set_export(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
def invoke(self, context, event): def invoke(self, context, event):
wm = context.manager wm = context.window_manager
wm.add_fileselect(self) wm.add_fileselect(self)
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}

View File

@@ -362,8 +362,8 @@ class TEXTURE_PT_influence(TextureSlotPanel, bpy.types.Panel):
col = split.column() col = split.column()
factor_but(col, tex.use_map_density, "use_map_density", "density_factor", "Density") factor_but(col, tex.use_map_density, "use_map_density", "density_factor", "Density")
factor_but(col, tex.use_map_emission, "use_map_emission", "emission_factor", "Emission") factor_but(col, tex.use_map_emission, "use_map_emission", "emission_factor", "Emission")
factor_but(col, tex.use_map_scatter, "use_map_scattering", "scattering_factor", "Scattering") factor_but(col, tex.use_map_scatter, "use_map_scatter", "scattering_factor", "Scattering")
factor_but(col, tex.use_map_reflect, "use_map_reflection", "reflection_factor", "Reflection") factor_but(col, tex.use_map_reflect, "use_map_reflect", "reflection_factor", "Reflection")
col = split.column() col = split.column()
col.label(text=" ") col.label(text=" ")

View File

@@ -50,6 +50,8 @@ class WORLD_PT_context_world(WorldButtonsPanel, bpy.types.Panel):
scene = context.scene scene = context.scene
world = context.world world = context.world
space = context.space_data space = context.space_data
texture_count = world and len(world.texture_slots.keys())
split = layout.split(percentage=0.65) split = layout.split(percentage=0.65)
if scene: if scene:
@@ -57,6 +59,8 @@ class WORLD_PT_context_world(WorldButtonsPanel, bpy.types.Panel):
elif world: elif world:
split.template_ID(space, "pin_id") split.template_ID(space, "pin_id")
if texture_count:
split.label(text=str(texture_count), icon='TEXTURE')
class WORLD_PT_preview(WorldButtonsPanel, bpy.types.Panel): class WORLD_PT_preview(WorldButtonsPanel, bpy.types.Panel):
bl_label = "Preview" bl_label = "Preview"

View File

@@ -27,7 +27,6 @@ class FILEBROWSER_HT_header(bpy.types.Header):
layout = self.layout layout = self.layout
st = context.space_data st = context.space_data
params = st.params
layout.template_header(menus=False) layout.template_header(menus=False)
@@ -45,24 +44,28 @@ class FILEBROWSER_HT_header(bpy.types.Header):
row = layout.row(align=True) row = layout.row(align=True)
row.operator("file.directory_new", text="", icon='NEWFOLDER') row.operator("file.directory_new", text="", icon='NEWFOLDER')
params = st.params
layout.prop(params, "display_type", expand=True, text="") # can be None when save/reload with a file selector open
layout.prop(params, "sort_method", expand=True, text="") if params:
layout.prop(params, "display_type", expand=True, text="")
layout.prop(params, "sort_method", expand=True, text="")
layout.prop(params, "show_hidden") layout.prop(params, "show_hidden")
layout.prop(params, "use_filter", text="", icon='FILTER') layout.prop(params, "use_filter", text="", icon='FILTER')
row = layout.row(align=True) row = layout.row(align=True)
row.active = params.use_filter row.active = params.use_filter
row.prop(params, "use_filter_folder", text="") row.prop(params, "use_filter_folder", text="")
row.prop(params, "use_filter_blender", text="") row.prop(params, "use_filter_blender", text="")
row.prop(params, "use_filter_image", text="") row.prop(params, "use_filter_image", text="")
row.prop(params, "use_filter_movie", text="") row.prop(params, "use_filter_movie", text="")
row.prop(params, "use_filter_script", text="") row.prop(params, "use_filter_script", text="")
row.prop(params, "use_filter_font", text="") row.prop(params, "use_filter_font", text="")
row.prop(params, "use_filter_sound", text="") row.prop(params, "use_filter_sound", text="")
row.prop(params, "use_filter_text", text="") row.prop(params, "use_filter_text", text="")
def register(): def register():

View File

@@ -26,7 +26,7 @@ class INFO_HT_header(bpy.types.Header):
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
wm = context.manager wm = context.window_manager
window = context.window window = context.window
scene = context.scene scene = context.scene
rd = scene.render rd = scene.render
@@ -169,7 +169,7 @@ class INFO_MT_mesh_add(bpy.types.Menu):
layout.operator("mesh.primitive_circle_add", icon='MESH_CIRCLE', text="Circle") layout.operator("mesh.primitive_circle_add", icon='MESH_CIRCLE', text="Circle")
layout.operator("mesh.primitive_uv_sphere_add", icon='MESH_UVSPHERE', text="UV Sphere") layout.operator("mesh.primitive_uv_sphere_add", icon='MESH_UVSPHERE', text="UV Sphere")
layout.operator("mesh.primitive_ico_sphere_add", icon='MESH_ICOSPHERE', text="Icosphere") layout.operator("mesh.primitive_ico_sphere_add", icon='MESH_ICOSPHERE', text="Icosphere")
layout.operator("mesh.primitive_tube_add", icon='MESH_TUBE', text="Tube") layout.operator("mesh.primitive_cylinder_add", icon='MESH_CYLINDER', text="Cylinder")
layout.operator("mesh.primitive_cone_add", icon='MESH_CONE', text="Cone") layout.operator("mesh.primitive_cone_add", icon='MESH_CONE', text="Cone")
layout.separator() layout.separator()
layout.operator("mesh.primitive_grid_add", icon='MESH_GRID', text="Grid") layout.operator("mesh.primitive_grid_add", icon='MESH_GRID', text="Grid")
@@ -200,9 +200,9 @@ class INFO_MT_surface_add(bpy.types.Menu):
layout.operator("surface.primitive_nurbs_surface_curve_add", icon='SURFACE_NCURVE', text="NURBS Curve") layout.operator("surface.primitive_nurbs_surface_curve_add", icon='SURFACE_NCURVE', text="NURBS Curve")
layout.operator("surface.primitive_nurbs_surface_circle_add", icon='SURFACE_NCIRCLE', text="NURBS Circle") layout.operator("surface.primitive_nurbs_surface_circle_add", icon='SURFACE_NCIRCLE', text="NURBS Circle")
layout.operator("surface.primitive_nurbs_surface_surface_add", icon='SURFACE_NSURFACE', text="NURBS Surface") layout.operator("surface.primitive_nurbs_surface_surface_add", icon='SURFACE_NSURFACE', text="NURBS Surface")
layout.operator("surface.primitive_nurbs_surface_tube_add", icon='SURFACE_NTUBE', text="NURBS Tube") layout.operator("surface.primitive_nurbs_surface_cylinder_add", icon='SURFACE_NCYLINDER', text="NURBS Cylinder")
layout.operator("surface.primitive_nurbs_surface_sphere_add", icon='SURFACE_NSPHERE', text="NURBS Sphere") layout.operator("surface.primitive_nurbs_surface_sphere_add", icon='SURFACE_NSPHERE', text="NURBS Sphere")
layout.operator("surface.primitive_nurbs_surface_donut_add", icon='SURFACE_NDONUT', text="NURBS Torus") layout.operator("surface.primitive_nurbs_surface_torus_add", icon='SURFACE_NTORUS', text="NURBS Torus")
class INFO_MT_armature_add(bpy.types.Menu): class INFO_MT_armature_add(bpy.types.Menu):
@@ -316,8 +316,10 @@ class INFO_MT_help(bpy.types.Menu):
layout.separator() layout.separator()
layout.operator("wm.url_open", text="Report a Bug", icon='URL').url = 'http://projects.blender.org/tracker/?atid=498&group_id=9&func=browse' layout.operator("wm.url_open", text="Report a Bug", icon='URL').url = 'http://projects.blender.org/tracker/?atid=498&group_id=9&func=browse'
layout.separator() layout.separator()
layout.operator("wm.url_open", text="Python API Reference", icon='URL').url = 'http://www.blender.org/documentation/250PythonDoc/contents.html' layout.operator("wm.url_open", text="Python API Reference", icon='URL').url = "http://www.blender.org/documentation/blender_python_api_%s/contents.html" % "_".join(str(v) for v in bpy.app.version)
layout.operator("help.operator_cheat_sheet") layout.operator("help.operator_cheat_sheet", icon='TEXT')
layout.separator()
layout.operator("anim.update_data_paths", text="FCurve/Driver 2.54 fix", icon='HELP')
layout.separator() layout.separator()
layout.operator("wm.splash") layout.operator("wm.splash")

View File

@@ -796,7 +796,7 @@ class USERPREF_PT_input(InputKeyMapPanel):
#start = time.time() #start = time.time()
userpref = context.user_preferences userpref = context.user_preferences
wm = context.manager wm = context.window_manager
inputs = userpref.inputs inputs = userpref.inputs
@@ -980,7 +980,8 @@ class USERPREF_PT_addons(bpy.types.Panel):
rowsub = row.row() rowsub = row.row()
rowsub.active = is_enabled rowsub.active = is_enabled
rowsub.label(text=info["name"], icon='ERROR' if info["warning"] else 'BLENDER') rowsub.label(text='%s: %s' % (info['category'], info["name"]))
if info["warning"]: rowsub.label(icon='ERROR')
if is_enabled: if is_enabled:
row.operator("wm.addon_disable", icon='CHECKBOX_HLT', text="", emboss=False).module = module_name row.operator("wm.addon_disable", icon='CHECKBOX_HLT', text="", emboss=False).module = module_name
@@ -1004,7 +1005,7 @@ class USERPREF_PT_addons(bpy.types.Panel):
if info["version"]: if info["version"]:
split = colsub.row().split(percentage=0.15) split = colsub.row().split(percentage=0.15)
split.label(text='Version:') split.label(text='Version:')
split.label(text=info["version"]) split.label(text='.'.join([str(x) for x in info["version"]]))
if info["warning"]: if info["warning"]:
split = colsub.row().split(percentage=0.15) split = colsub.row().split(percentage=0.15)
split.label(text="Warning:") split.label(text="Warning:")
@@ -1045,7 +1046,7 @@ class USERPREF_PT_addons(bpy.types.Panel):
from bpy.props import * from bpy.props import *
def addon_info_get(mod, info_basis={"name": "", "author": "", "version": "", "blender": "", "location": "", "description": "", "wiki_url": "", "tracker_url": "", "category": "", "warning": "", "show_expanded": False}): def addon_info_get(mod, info_basis={"name": "", "author": "", "version": (), "blender": (), "api": 0, "location": "", "description": "", "wiki_url": "", "tracker_url": "", "category": "", "warning": "", "show_expanded": False}):
addon_info = getattr(mod, "bl_addon_info", {}) addon_info = getattr(mod, "bl_addon_info", {})
# avoid re-initializing # avoid re-initializing
@@ -1189,7 +1190,7 @@ class WM_OT_addon_install(bpy.types.Operator):
self.report({'ERROR'}, "No 'addons' path could be found in " + str(bpy.utils.script_paths())) self.report({'ERROR'}, "No 'addons' path could be found in " + str(bpy.utils.script_paths()))
return {'CANCELLED'} return {'CANCELLED'}
wm = context.manager wm = context.window_manager
wm.add_fileselect(self) wm.add_fileselect(self)
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
@@ -1225,4 +1226,4 @@ def unregister():
pass pass
if __name__ == "__main__": if __name__ == "__main__":
register() register()

View File

@@ -138,10 +138,10 @@ class InputKeyMapPanel(bpy.types.Panel):
self.draw_km(display_keymaps, kc, km, children, col, level) self.draw_km(display_keymaps, kc, km, children, col, level)
''' '''
km = kc.find_keymap(idname, space_type=spaceid, region_type=regionid) km = kc.keymaps.find(idname, space_type=spaceid, region_type=regionid)
if not km: if not km:
kc = defkc kc = defkc
km = kc.find_keymap(idname, space_type=spaceid, region_type=regionid) km = kc.keymaps.find(idname, space_type=spaceid, region_type=regionid)
if km: if km:
self.draw_km(kc, km, children, col, level) self.draw_km(kc, km, children, col, level)
@@ -161,7 +161,7 @@ class InputKeyMapPanel(bpy.types.Panel):
def draw_km(self, display_keymaps, kc, km, children, layout, level): def draw_km(self, display_keymaps, kc, km, children, layout, level):
km = km.active() km = km.active()
layout.set_context_pointer("keymap", km) layout.context_pointer_set("keymap", km)
col = self.indented_layout(layout, level) col = self.indented_layout(layout, level)
@@ -211,6 +211,19 @@ class InputKeyMapPanel(bpy.types.Panel):
for entry in children: for entry in children:
self.draw_entry(display_keymaps, entry, col, level + 1) self.draw_entry(display_keymaps, entry, col, level + 1)
@staticmethod
def draw_kmi_properties(box, properties, title=None):
box.separator()
if title:
box.label(text=title)
flow = box.column_flow(columns=2)
for pname, value in properties.bl_rna.properties.items():
if pname != "rna_type" and not properties.is_property_hidden(pname):
if isinstance(value, bpy.types.OperatorProperties):
__class__.draw_kmi_properties(box, value, title=pname)
else:
flow.prop(properties, pname)
def draw_kmi(self, display_keymaps, kc, km, kmi, layout, level): def draw_kmi(self, display_keymaps, kc, km, kmi, layout, level):
map_type = kmi.map_type map_type = kmi.map_type
@@ -293,34 +306,22 @@ class InputKeyMapPanel(bpy.types.Panel):
subrow.prop(kmi, "oskey", text="Cmd") subrow.prop(kmi, "oskey", text="Cmd")
subrow.prop(kmi, "key_modifier", text="", event=True) subrow.prop(kmi, "key_modifier", text="", event=True)
def display_properties(properties, title=None):
box.separator()
if title:
box.label(text=title)
flow = box.column_flow(columns=2)
for pname, value in properties.items():
if not properties.is_property_hidden(pname):
if isinstance(value, bpy.types.OperatorProperties):
display_properties(value, title=pname)
else:
flow.prop(properties, pname)
# Operator properties # Operator properties
props = kmi.properties props = kmi.properties
if props is not None: if props is not None:
display_properties(props) __class__.draw_kmi_properties(box, props)
# Modal key maps attached to this operator # Modal key maps attached to this operator
if not km.is_modal: if not km.is_modal:
kmm = kc.find_keymap_modal(kmi.idname) kmm = kc.keymaps.find_modal(kmi.idname)
if kmm: if kmm:
self.draw_km(display_keymaps, kc, kmm, None, layout, level + 1) self.draw_km(display_keymaps, kc, kmm, None, layout, level + 1)
layout.set_context_pointer("keymap", km) layout.context_pointer_set("keymap", km)
def draw_filtered(self, display_keymaps, filter_text, layout): def draw_filtered(self, display_keymaps, filter_text, layout):
for km, kc in display_keymaps: for km, kc in display_keymaps:
km = km.active() km = km.active()
layout.set_context_pointer("keymap", km) layout.context_pointer_set("keymap", km)
filtered_items = [kmi for kmi in km.items if filter_text in kmi.name.lower()] filtered_items = [kmi for kmi in km.items if filter_text in kmi.name.lower()]
@@ -352,7 +353,7 @@ class InputKeyMapPanel(bpy.types.Panel):
self.draw_entry(display_keymaps, entry, layout) self.draw_entry(display_keymaps, entry, layout)
def draw_keymaps(self, context, layout): def draw_keymaps(self, context, layout):
wm = context.manager wm = context.window_manager
kc = wm.keyconfigs.active kc = wm.keyconfigs.active
defkc = wm.keyconfigs.default defkc = wm.keyconfigs.default
@@ -364,7 +365,7 @@ class InputKeyMapPanel(bpy.types.Panel):
row = subcol.row() row = subcol.row()
row.prop_search(wm.keyconfigs, "active", wm, "keyconfigs", text="Key Config:") row.prop_search(wm.keyconfigs, "active", wm, "keyconfigs", text="Key Config:")
layout.set_context_pointer("keyconfig", wm.keyconfigs.active) layout.context_pointer_set("keyconfig", wm.keyconfigs.active)
row.operator("wm.keyconfig_remove", text="", icon='X') row.operator("wm.keyconfig_remove", text="", icon='X')
row.prop(context.space_data, "filter_text", icon="VIEWZOOM") row.prop(context.space_data, "filter_text", icon="VIEWZOOM")
@@ -386,7 +387,7 @@ def export_properties(prefix, properties, lines=None):
if lines is None: if lines is None:
lines = [] lines = []
for value, pname in properties.items(): for pname, value in properties.items():
if not properties.is_property_hidden(pname): if not properties.is_property_hidden(pname):
if isinstance(value, bpy.types.OperatorProperties): if isinstance(value, bpy.types.OperatorProperties):
export_properties(prefix + "." + pname, value, lines) export_properties(prefix + "." + pname, value, lines)
@@ -407,9 +408,9 @@ class WM_OT_keyconfig_test(bpy.types.Operator):
def kmistr(kmi): def kmistr(kmi):
if km.is_modal: if km.is_modal:
s = ["kmi = km.items.add_modal(\'%s\', \'%s\', \'%s\'" % (kmi.propvalue, kmi.type, kmi.value)] s = ["kmi = km.items.new_modal(\'%s\', \'%s\', \'%s\'" % (kmi.propvalue, kmi.type, kmi.value)]
else: else:
s = ["kmi = km.items.add(\'%s\', \'%s\', \'%s\'" % (kmi.idname, kmi.type, kmi.value)] s = ["kmi = km.items.new(\'%s\', \'%s\', \'%s\'" % (kmi.idname, kmi.type, kmi.value)]
if kmi.any: if kmi.any:
s.append(", any=True") s.append(", any=True")
@@ -436,7 +437,7 @@ class WM_OT_keyconfig_test(bpy.types.Operator):
idname, spaceid, regionid, children = entry idname, spaceid, regionid, children = entry
km = kc.find_keymap(idname, space_type=spaceid, region_type=regionid) km = kc.keymaps.find(idname, space_type=spaceid, region_type=regionid)
if km: if km:
km = km.active() km = km.active()
@@ -485,7 +486,7 @@ class WM_OT_keyconfig_test(bpy.types.Operator):
return result return result
def execute(self, context): def execute(self, context):
wm = context.manager wm = context.window_manager
kc = wm.keyconfigs.default kc = wm.keyconfigs.default
if self.testConfig(kc): if self.testConfig(kc):
@@ -528,8 +529,8 @@ class WM_OT_keyconfig_import(bpy.types.Operator):
config_name = None config_name = None
for line in f: for line in f:
if line.startswith("kc = wm.add_keyconfig("): if line.startswith("kc = wm.keyconfigs.new("):
config_name = line[23:-3] config_name = line[24:-3]
break break
if config_name is None: if config_name is None:
@@ -551,23 +552,23 @@ class WM_OT_keyconfig_import(bpy.types.Operator):
shutil.move(self.properties.filepath, path) shutil.move(self.properties.filepath, path)
# sneaky way to check we're actually running the code. # sneaky way to check we're actually running the code.
wm = context.manager wm = context.window_manager
while config_name in wm.keyconfigs: while config_name in wm.keyconfigs:
wm.remove_keyconfig(wm.keyconfigs[config_name]) wm.keyconfigs.remove(wm.keyconfigs[config_name])
wm = context.manager wm = context.window_manager
totmap = len(wm.keyconfigs) totmap = len(wm.keyconfigs)
mod = __import__(config_name) mod = __import__(config_name)
if totmap == len(wm.keyconfigs): if totmap == len(wm.keyconfigs):
reload(mod) reload(mod)
wm = bpy.context.manager wm = bpy.context.window_manager
wm.keyconfigs.active = wm.keyconfigs[config_name] wm.keyconfigs.active = wm.keyconfigs[config_name]
return {'FINISHED'} return {'FINISHED'}
def invoke(self, context, event): def invoke(self, context, event):
wm = context.manager wm = context.window_manager
wm.add_fileselect(self) wm.add_fileselect(self)
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
@@ -593,7 +594,7 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
if not f: if not f:
raise Exception("Could not open file") raise Exception("Could not open file")
wm = context.manager wm = context.window_manager
kc = wm.keyconfigs.active kc = wm.keyconfigs.active
if self.properties.kc_name != '': if self.properties.kc_name != '':
@@ -606,8 +607,8 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
f.write("# Configuration %s\n" % name) f.write("# Configuration %s\n" % name)
f.write("import bpy\n\n") f.write("import bpy\n\n")
f.write("wm = bpy.context.manager\n") f.write("wm = bpy.context.window_manager\n")
f.write("kc = wm.add_keyconfig('%s')\n\n" % name) f.write("kc = wm.keyconfigs.new('%s')\n\n" % name)
# Generate a list of keymaps to export: # Generate a list of keymaps to export:
# #
@@ -633,12 +634,12 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
km = km.active() km = km.active()
f.write("# Map %s\n" % km.name) f.write("# Map %s\n" % km.name)
f.write("km = kc.add_keymap('%s', space_type='%s', region_type='%s', modal=%s)\n\n" % (km.name, km.space_type, km.region_type, km.is_modal)) f.write("km = kc.keymaps.new('%s', space_type='%s', region_type='%s', modal=%s)\n\n" % (km.name, km.space_type, km.region_type, km.is_modal))
for kmi in km.items: for kmi in km.items:
if km.is_modal: if km.is_modal:
f.write("kmi = km.items.add_modal('%s', '%s', '%s'" % (kmi.propvalue, kmi.type, kmi.value)) f.write("kmi = km.items.new_modal('%s', '%s', '%s'" % (kmi.propvalue, kmi.type, kmi.value))
else: else:
f.write("kmi = km.items.add('%s', '%s', '%s'" % (kmi.idname, kmi.type, kmi.value)) f.write("kmi = km.items.new('%s', '%s', '%s'" % (kmi.idname, kmi.type, kmi.value))
if kmi.any: if kmi.any:
f.write(", any=True") f.write(", any=True")
else: else:
@@ -666,7 +667,7 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
def invoke(self, context, event): def invoke(self, context, event):
wm = context.manager wm = context.window_manager
wm.add_fileselect(self) wm.add_fileselect(self)
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
@@ -677,7 +678,7 @@ class WM_OT_keymap_edit(bpy.types.Operator):
bl_label = "Edit Key Map" bl_label = "Edit Key Map"
def execute(self, context): def execute(self, context):
wm = context.manager wm = context.window_manager
km = context.keymap km = context.keymap
km.copy_to_user() km.copy_to_user()
return {'FINISHED'} return {'FINISHED'}
@@ -691,7 +692,7 @@ class WM_OT_keymap_restore(bpy.types.Operator):
all = BoolProperty(attr="all", name="All Keymaps", description="Restore all keymaps to default") all = BoolProperty(attr="all", name="All Keymaps", description="Restore all keymaps to default")
def execute(self, context): def execute(self, context):
wm = context.manager wm = context.window_manager
if self.properties.all: if self.properties.all:
for km in wm.keyconfigs.default.keymaps: for km in wm.keyconfigs.default.keymaps:
@@ -711,9 +712,9 @@ class WM_OT_keyitem_restore(bpy.types.Operator):
item_id = IntProperty(attr="item_id", name="Item Identifier", description="Identifier of the item to remove") item_id = IntProperty(attr="item_id", name="Item Identifier", description="Identifier of the item to remove")
def execute(self, context): def execute(self, context):
wm = context.manager wm = context.window_manager
km = context.keymap km = context.keymap
kmi = km.item_from_id(self.properties.item_id) kmi = km.items.from_id(self.properties.item_id)
km.restore_item_to_default(kmi) km.restore_item_to_default(kmi)
@@ -726,14 +727,14 @@ class WM_OT_keyitem_add(bpy.types.Operator):
bl_label = "Add Key Map Item" bl_label = "Add Key Map Item"
def execute(self, context): def execute(self, context):
wm = context.manager wm = context.window_manager
km = context.keymap km = context.keymap
kc = wm.keyconfigs.default kc = wm.keyconfigs.default
if km.is_modal: if km.is_modal:
km.items.add_modal("", 'A', 'PRESS') # kmi km.items.new_modal("", 'A', 'PRESS') # kmi
else: else:
km.items.add("none", 'A', 'PRESS') # kmi km.items.new("none", 'A', 'PRESS') # kmi
# clear filter and expand keymap so we can see the newly added item # clear filter and expand keymap so we can see the newly added item
if context.space_data.filter_text != "": if context.space_data.filter_text != "":
@@ -752,10 +753,10 @@ class WM_OT_keyitem_remove(bpy.types.Operator):
item_id = IntProperty(attr="item_id", name="Item Identifier", description="Identifier of the item to remove") item_id = IntProperty(attr="item_id", name="Item Identifier", description="Identifier of the item to remove")
def execute(self, context): def execute(self, context):
wm = context.manager wm = context.window_manager
km = context.keymap km = context.keymap
kmi = km.item_from_id(self.properties.item_id) kmi = km.items.from_id(self.properties.item_id)
km.remove_item(kmi) km.items.remove(kmi)
return {'FINISHED'} return {'FINISHED'}
@@ -766,12 +767,12 @@ class WM_OT_keyconfig_remove(bpy.types.Operator):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
wm = context.manager wm = context.window_manager
return wm.keyconfigs.active.is_user_defined return wm.keyconfigs.active.is_user_defined
def execute(self, context): def execute(self, context):
import sys import sys
wm = context.manager wm = context.window_manager
keyconfig = wm.keyconfigs.active keyconfig = wm.keyconfigs.active
@@ -787,7 +788,7 @@ class WM_OT_keyconfig_remove(bpy.types.Operator):
if os.path.exists(path): if os.path.exists(path):
os.remove(path) os.remove(path)
wm.remove_keyconfig(keyconfig) wm.keyconfigs.remove(keyconfig)
return {'FINISHED'} return {'FINISHED'}
def register(): def register():

View File

@@ -0,0 +1,133 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# Used for generating API diff's between releases
# ./blender.bin --background --python release/test/rna_info_dump.py
import bpy
def api_dump(use_properties=True, use_functions=True):
def prop_type(prop):
if prop.type == "pointer":
return prop.fixed_type.identifier
else:
return prop.type
def func_to_str(struct_id_str, func_id, func):
args = []
for prop in func.args:
data_str = "%s %s" % (prop_type(prop), prop.identifier)
if prop.array_length:
data_str += "[%d]" % prop.array_length
if not prop.is_required:
data_str += "=%s" % prop.default_str
args.append(data_str)
data_str = "%s.%s(%s)" % (struct_id_str, func_id, ", ".join(args))
if func.return_values:
return_args = ", ".join([prop_type(arg) for arg in func.return_values])
if len(func.return_values) > 1:
data_str += " --> (%s)" % return_args
else:
data_str += " --> %s" % return_args
return data_str
def prop_to_str(struct_id_str, prop_id, prop):
prop_str = " <-- %s" % prop_type(prop)
if prop.array_length:
prop_str += "[%d]" % prop.array_length
data_str = "%s.%s %s" % (struct_id_str, prop_id, prop_str)
return data_str
def struct_full_id(v):
struct_id_str = v.identifier # "".join(sid for sid in struct_id if struct_id)
for base in v.get_bases():
struct_id_str = base.identifier + "|" + struct_id_str
return struct_id_str
def dump_funcs():
data = []
for struct_id, v in sorted(struct.items()):
struct_id_str = struct_full_id(v)
funcs = [(func.identifier, func) for func in v.functions]
for func_id, func in funcs:
data.append(func_to_str(struct_id_str, func_id, func))
for prop in v.properties:
if prop.collection_type:
funcs = [(prop.identifier + "." + func.identifier, func) for func in prop.collection_type.functions]
for func_id, func in funcs:
data.append(func_to_str(struct_id_str, func_id, func))
data.sort()
data.append("# * functions *")
return data
def dump_props():
data = []
for struct_id, v in sorted(struct.items()):
struct_id_str = struct_full_id(v)
props = [(prop.identifier, prop) for prop in v.properties]
for prop_id, prop in props:
data.append(prop_to_str(struct_id_str, prop_id, prop))
for prop in v.properties:
if prop.collection_type:
props = [(prop.identifier + "." + prop_sub.identifier, prop_sub) for prop_sub in prop.collection_type.properties]
for prop_sub_id, prop_sub in props:
data.append(prop_to_str(struct_id_str, prop_sub_id, prop_sub))
data.sort()
data.insert(0, "# * properties *")
return data
import rna_info
struct = rna_info.BuildRNAInfo()[0]
data = []
if use_functions:
data.extend(dump_funcs())
if use_properties:
data.extend(dump_props())
if bpy.app.background:
import sys
sys.stderr.write("\n".join(data))
sys.stderr.write("\n\nEOF\n")
else:
text = bpy.data.texts.new(name="api.py")
text.from_string(data)
print("END")
if __name__ == "__main__":
api_dump()

View File

@@ -2,13 +2,13 @@
Import ('env') Import ('env')
SConscript(['blender/SConscript', SConscript(['blender/SConscript',
'kernel/SConscript', 'kernel/SConscript',
'creator/SConscript']) 'creator/SConscript'])
if env['WITH_BF_GAMEENGINE']: if env['WITH_BF_GAMEENGINE']:
SConscript (['gameengine/SConscript']) SConscript (['gameengine/SConscript'])
if env['WITH_BF_PLAYER']: if env['WITH_BF_PLAYER']:
SConscript (['blenderplayer/bad_level_call_stubs/SConscript']) SConscript (['blenderplayer/bad_level_call_stubs/SConscript'])
if env['OURPLATFORM'] in ('win64-vc', 'win32-vc', 'win32-mingw', 'linuxcross'): if env['OURPLATFORM'] in ('win64-vc', 'win32-vc', 'win32-mingw', 'linuxcross'):
SConscript (['icons/SConscript']) SConscript (['icons/SConscript'])

View File

@@ -27,7 +27,8 @@
FILE(GLOB SRC intern/*.c) FILE(GLOB SRC intern/*.c)
SET(INC SET(INC
. ../../../intern/guardedalloc .
../../../intern/guardedalloc
${JPEG_INC} ${JPEG_INC}
) )

View File

@@ -24,14 +24,19 @@
FILE(GLOB SRC intern/*.c) FILE(GLOB SRC intern/*.c)
SET(INC SET(INC
../../../intern/guardedalloc ../blenlib ../makesdna ../editors/include .
../blenkernel ../../../extern/glew/include . ../blenlib
../makesdna
../editors/include
../blenkernel
../../../intern/guardedalloc
../../../extern/glew/include
${FREETYPE_INCLUDE_DIRS} ${FREETYPE_INCLUDE_DIRS}
) )
IF(WITH_INTERNATIONAL) IF(WITH_INTERNATIONAL)
SET(INC ${INC} ${GETTEXT_INC}) LIST(APPEND INC ${GETTEXT_INC})
ADD_DEFINITIONS(-DINTERNATIONAL) ADD_DEFINITIONS(-DINTERNATIONAL)
ENDIF(WITH_INTERNATIONAL) ENDIF(WITH_INTERNATIONAL)

View File

@@ -12,8 +12,8 @@ incs += ' ' + env['BF_GETTEXT_INC']
defs = [] defs = []
if sys.platform == 'win32' or env['OURPLATFORM'] == 'linuxcross': if sys.platform == 'win32' or env['OURPLATFORM'] == 'linuxcross':
defs.append('_WIN32') defs.append('_WIN32')
defs.append('USE_GETTEXT_DLL') defs.append('USE_GETTEXT_DLL')
if env['WITH_BF_INTERNATIONAL']: if env['WITH_BF_INTERNATIONAL']:
defs.append('INTERNATIONAL') defs.append('INTERNATIONAL')

View File

@@ -57,6 +57,9 @@ void automatname(struct Material *);
struct Material ***give_matarar(struct Object *ob); struct Material ***give_matarar(struct Object *ob);
short *give_totcolp(struct Object *ob); short *give_totcolp(struct Object *ob);
struct Material ***give_matarar_id(struct ID *id); /* same but for ID's */
short *give_totcolp_id(struct ID *id);
struct Material *give_current_material(struct Object *ob, int act); struct Material *give_current_material(struct Object *ob, int act);
struct ID *material_from(struct Object *ob, int act); struct ID *material_from(struct Object *ob, int act);
void assign_material(struct Object *ob, struct Material *ma, int act); void assign_material(struct Object *ob, struct Material *ma, int act);
@@ -67,6 +70,10 @@ int find_material_index(struct Object *ob, struct Material *ma);
int object_add_material_slot(struct Object *ob); int object_add_material_slot(struct Object *ob);
int object_remove_material_slot(struct Object *ob); int object_remove_material_slot(struct Object *ob);
/* rna api */
void material_append_id(struct ID *id, struct Material *ma);
struct Material *material_pop_id(struct ID *id, int index);
/* rendering */ /* rendering */
void init_render_material(struct Material *, int, float *); void init_render_material(struct Material *, int, float *);

View File

@@ -253,6 +253,7 @@ ParticleThread *psys_threads_create(struct ParticleSimulationData *sim);
void psys_threads_free(ParticleThread *threads); void psys_threads_free(ParticleThread *threads);
void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]); void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]);
void psys_apply_hair_lattice(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
/* particle_system.c */ /* particle_system.c */
struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt); struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt);
@@ -282,6 +283,8 @@ void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short fr
void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]);
void psys_mat_hair_to_orco(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); void psys_mat_hair_to_orco(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]);
float psys_get_dietime_from_cache(struct PointCache *cache, int index);
void psys_free_pdd(struct ParticleSystem *psys); void psys_free_pdd(struct ParticleSystem *psys);
float *psys_cache_vgroup(struct DerivedMesh *dm, struct ParticleSystem *psys, int vgroup); float *psys_cache_vgroup(struct DerivedMesh *dm, struct ParticleSystem *psys, int vgroup);

View File

@@ -70,6 +70,7 @@ struct Tex *add_texture(const char *name);
void tex_set_type(struct Tex *tex, int type); void tex_set_type(struct Tex *tex, int type);
void default_mtex(struct MTex *mtex); void default_mtex(struct MTex *mtex);
struct MTex *add_mtex(void); struct MTex *add_mtex(void);
struct MTex *add_mtex_id(struct ID *id, int slot);
struct Tex *copy_texture(struct Tex *tex); struct Tex *copy_texture(struct Tex *tex);
void make_local_texture(struct Tex *tex); void make_local_texture(struct Tex *tex);
void autotexname(struct Tex *tex); void autotexname(struct Tex *tex);

View File

@@ -27,13 +27,30 @@
FILE(GLOB SRC intern/*.c) FILE(GLOB SRC intern/*.c)
SET(INC SET(INC
. ../../../intern/guardedalloc ../../../intern/memutil ../editors/include ../blenlib ../makesdna ../modifiers .
../render/extern/include ../../../intern/decimation/extern ../avi
../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern ../blenlib
../../../intern/iksolver/extern ../blenloader ../ikplugin ../freestyle ../blenloader
../nodes ../../../extern/glew/include ../gpu ../makesrna ../../../intern/smoke/extern ../editors/include
../../../intern/bsp/extern ../blenfont ../freestyle
../gpu
../ikplugin
../imbuf
../makesdna
../makesrna
../modifiers
../nodes
../render/extern/include
../../../extern/glew/include
../../../intern/audaspace/intern ../../../intern/audaspace/intern
../../../intern/bsp/extern ../blenfont
../../../intern/decimation/extern
../../../intern/elbeem/extern
../../../intern/guardedalloc
../../../intern/iksolver/extern
../../../intern/memutil
../../../intern/opennl/extern
../../../intern/smoke/extern
../../../source/blender/windowmanager # XXX - BAD LEVEL CALL WM_api.h ../../../source/blender/windowmanager # XXX - BAD LEVEL CALL WM_api.h
${ZLIB_INC} ${ZLIB_INC}
) )
@@ -42,7 +59,7 @@ SET(INC
ADD_DEFINITIONS(-DGLEW_STATIC) ADD_DEFINITIONS(-DGLEW_STATIC)
IF(WITH_BULLET) IF(WITH_BULLET)
SET(INC ${INC} ../../../extern/bullet2/src) LIST(APPEND INC ../../../extern/bullet2/src)
ADD_DEFINITIONS(-DUSE_BULLET) ADD_DEFINITIONS(-DUSE_BULLET)
ENDIF(WITH_BULLET) ENDIF(WITH_BULLET)
@@ -71,22 +88,24 @@ IF(WITH_IMAGE_HDR)
ENDIF(WITH_IMAGE_HDR) ENDIF(WITH_IMAGE_HDR)
IF(WITH_QUICKTIME) IF(WITH_QUICKTIME)
SET(INC ${INC} ../quicktime ${QUICKTIME_INC}) LIST(APPEND INC ../quicktime)
LIST(APPEND INC ${QUICKTIME_INC})
ADD_DEFINITIONS(-DWITH_QUICKTIME) ADD_DEFINITIONS(-DWITH_QUICKTIME)
ENDIF(WITH_QUICKTIME) ENDIF(WITH_QUICKTIME)
IF(WITH_FFMPEG) IF(WITH_FFMPEG)
SET(INC ${INC} ${FFMPEG_INC}) LIST(APPEND INC ${FFMPEG_INC})
ADD_DEFINITIONS(-DWITH_FFMPEG) ADD_DEFINITIONS(-DWITH_FFMPEG)
ENDIF(WITH_FFMPEG) ENDIF(WITH_FFMPEG)
IF(WITH_LCMS) IF(WITH_LCMS)
SET(INC ${INC} ${LCMS_INCLUDE_DIR}) LIST(APPEND INC ${LCMS_INCLUDE_DIR})
ADD_DEFINITIONS(-DWITH_LCMS) ADD_DEFINITIONS(-DWITH_LCMS)
ENDIF(WITH_LCMS) ENDIF(WITH_LCMS)
IF(WITH_PYTHON) IF(WITH_PYTHON)
SET(INC ${INC} ../python ${PYTHON_INC}) LIST(APPEND INC ../python)
LIST(APPEND INC ${PYTHON_INC})
ELSE(WITH_PYTHON) ELSE(WITH_PYTHON)
ADD_DEFINITIONS(-DDISABLE_PYTHON) ADD_DEFINITIONS(-DDISABLE_PYTHON)
ENDIF(WITH_PYTHON) ENDIF(WITH_PYTHON)
@@ -100,18 +119,17 @@ IF(NOT WITH_FLUID)
ENDIF(NOT WITH_FLUID) ENDIF(NOT WITH_FLUID)
IF(WITH_LZO) IF(WITH_LZO)
SET(INC ${INC} ../../../extern/lzo/minilzo) LIST(APPEND INC ../../../extern/lzo/minilzo)
ADD_DEFINITIONS(-DWITH_LZO) ADD_DEFINITIONS(-DWITH_LZO)
ENDIF(WITH_LZO) ENDIF(WITH_LZO)
IF(WITH_LZMA) IF(WITH_LZMA)
SET(INC ${INC} ../../../extern/lzma) LIST(APPEND INC ../../../extern/lzma)
ADD_DEFINITIONS(-DWITH_LZMA) ADD_DEFINITIONS(-DWITH_LZMA)
ENDIF(WITH_LZMA) ENDIF(WITH_LZMA)
IF(WIN32) IF(WIN32)
SET(INC ${INC} ${PTHREADS_INC}) LIST(APPEND INC ${PTHREADS_INC})
ENDIF(WIN32) ENDIF(WIN32)
BLENDERLIB(bf_blenkernel "${SRC}" "${INC}") BLENDERLIB(bf_blenkernel "${SRC}" "${INC}")

View File

@@ -20,68 +20,68 @@ incs += ' ' + env['BF_ZLIB_INC']
defs = [ 'GLEW_STATIC' ] defs = [ 'GLEW_STATIC' ]
if not env['WITH_BF_PYTHON']: if not env['WITH_BF_PYTHON']:
defs.append('DISABLE_PYTHON') defs.append('DISABLE_PYTHON')
else: else:
incs += ' ../python' incs += ' ../python'
incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_PYTHON_INC']
if env['BF_DEBUG']: if env['BF_DEBUG']:
defs.append('_DEBUG') defs.append('_DEBUG')
if env['WITH_BF_QUICKTIME']: if env['WITH_BF_QUICKTIME']:
incs += ' ../quicktime' incs += ' ../quicktime'
if env['WITH_BF_SDL']: if env['WITH_BF_SDL']:
incs += ' ' + env['BF_SDL_INC'] incs += ' ' + env['BF_SDL_INC']
else: else:
defs.append('DISABLE_SDL') defs.append('DISABLE_SDL')
if env['WITH_BF_OPENEXR']: if env['WITH_BF_OPENEXR']:
defs.append('WITH_OPENEXR') defs.append('WITH_OPENEXR')
if env['WITH_BF_TIFF']: if env['WITH_BF_TIFF']:
defs.append('WITH_TIFF') defs.append('WITH_TIFF')
if env['WITH_BF_OPENJPEG']: if env['WITH_BF_OPENJPEG']:
defs.append('WITH_OPENJPEG') defs.append('WITH_OPENJPEG')
if env['WITH_BF_DDS']: if env['WITH_BF_DDS']:
defs.append('WITH_DDS') defs.append('WITH_DDS')
if env['WITH_BF_CINEON']: if env['WITH_BF_CINEON']:
defs.append('WITH_CINEON') defs.append('WITH_CINEON')
if env['WITH_BF_HDR']: if env['WITH_BF_HDR']:
defs.append('WITH_HDR') defs.append('WITH_HDR')
if env['WITH_BF_FFMPEG']: if env['WITH_BF_FFMPEG']:
defs.append('WITH_FFMPEG') defs.append('WITH_FFMPEG')
incs += ' ' + env['BF_FFMPEG_INC'] incs += ' ' + env['BF_FFMPEG_INC']
if env['WITH_BF_QUICKTIME']: if env['WITH_BF_QUICKTIME']:
defs.append('WITH_QUICKTIME') defs.append('WITH_QUICKTIME')
incs += ' ' + env['BF_QUICKTIME_INC'] incs += ' ' + env['BF_QUICKTIME_INC']
if env['WITH_BF_BULLET']: if env['WITH_BF_BULLET']:
defs.append('USE_BULLET') defs.append('USE_BULLET')
if env['OURPLATFORM'] == 'darwin': if env['OURPLATFORM'] == 'darwin':
if env['WITH_BF_OPENMP']: if env['WITH_BF_OPENMP']:
defs.append('PARALLEL=1') defs.append('PARALLEL=1')
if env['BF_NO_ELBEEM']: if env['BF_NO_ELBEEM']:
defs.append('DISABLE_ELBEEM') defs.append('DISABLE_ELBEEM')
if env['WITH_BF_LCMS']: if env['WITH_BF_LCMS']:
defs.append('WITH_LCMS') defs.append('WITH_LCMS')
incs += ' ' + env['BF_LCMS_INC'] incs += ' ' + env['BF_LCMS_INC']
if env['WITH_BF_LZO']: if env['WITH_BF_LZO']:
incs += ' #/extern/lzo/minilzo' incs += ' #/extern/lzo/minilzo'
defs.append('WITH_LZO') defs.append('WITH_LZO')
if env['WITH_BF_LZMA']: if env['WITH_BF_LZMA']:
incs += ' #/extern/lzma' incs += ' #/extern/lzma'
defs.append('WITH_LZMA') defs.append('WITH_LZMA')
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'): if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
incs += ' ' + env['BF_PTHREADS_INC'] incs += ' ' + env['BF_PTHREADS_INC']

View File

@@ -1285,6 +1285,12 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
size = psys_get_child_size(psys, cpa, ctime, 0); size = psys_get_child_size(psys, cpa, ctime, 0);
} }
/* some hair paths might be non-existent so they can't be used for duplication */
if(hair &&
((a < totpart && psys->pathcache[a]->steps < 0) ||
(a >= totpart && psys->childcache[a-totpart]->steps < 0)))
continue;
if(part->ren_as==PART_DRAW_GR) { if(part->ren_as==PART_DRAW_GR) {
/* for groups, pick the object based on settings */ /* for groups, pick the object based on settings */
if(part->draw&PART_DRAW_RAND_GR) if(part->draw&PART_DRAW_RAND_GR)

View File

@@ -231,7 +231,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
curscene= bfd->curscene; curscene= bfd->curscene;
if(curscene==NULL) curscene= bfd->main->scene.first; if(curscene==NULL) curscene= bfd->main->scene.first;
/* and we enforce curscene to be in current screen */ /* and we enforce curscene to be in current screen */
curscreen->scene= curscene; if(curscreen) curscreen->scene= curscene; /* can run in bgmode */
/* clear_global will free G.main, here we can still restore pointers */ /* clear_global will free G.main, here we can still restore pointers */
lib_link_screen_restore(bfd->main, curscreen, curscene); lib_link_screen_restore(bfd->main, curscreen, curscene);

View File

@@ -910,6 +910,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa)
if(bpa->data.health <= 0.0f) { if(bpa->data.health <= 0.0f) {
pa->alive = PARS_DYING; pa->alive = PARS_DYING;
pa->dietime = bbd->cfra;
return; return;
} }

View File

@@ -701,7 +701,7 @@ Main *CTX_data_main(const bContext *C)
{ {
Main *bmain; Main *bmain;
if(ctx_data_pointer_verify(C, "main", (void*)&bmain)) if(ctx_data_pointer_verify(C, "blend_data", (void*)&bmain))
return bmain; return bmain;
else else
return C->data.main; return C->data.main;

View File

@@ -265,13 +265,11 @@ static PackedFile *get_builtin_packedfile(void)
void free_ttfont(void) void free_ttfont(void)
{ {
struct TmpFont *tf; struct TmpFont *tf;
tf= ttfdata.first; for(tf= ttfdata.first; tf; tf= tf->next) {
while(tf) { if(tf->pf) freePackedFile(tf->pf); /* NULL when the font file can't be found on disk */
freePackedFile(tf->pf);
tf->pf= NULL; tf->pf= NULL;
tf->vfont= NULL; tf->vfont= NULL;
tf= tf->next;
} }
BLI_freelistN(&ttfdata); BLI_freelistN(&ttfdata);
} }

View File

@@ -1301,13 +1301,14 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
/* correct times for rotation drivers /* correct times for rotation drivers
* - need to go from degrees to radians... * - need to go from degrees to radians...
* - there's only really 1 target to worry about * - there's only really 1 target to worry about
* - were also degrees/10
*/ */
if (fcu->driver && fcu->driver->variables.first) { if (fcu->driver && fcu->driver->variables.first) {
DriverVar *dvar= fcu->driver->variables.first; DriverVar *dvar= fcu->driver->variables.first;
DriverTarget *dtar= &dvar->targets[0]; DriverTarget *dtar= &dvar->targets[0];
if (ELEM3(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) { if (ELEM3(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) {
const float fac= (float)M_PI / 180.0f; const float fac= (float)M_PI / 18.0f;
dst->vec[0][0] *= fac; dst->vec[0][0] *= fac;
dst->vec[1][0] *= fac; dst->vec[1][0] *= fac;

View File

@@ -1160,7 +1160,7 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name)
/* this would overflow name buffer */ /* this would overflow name buffer */
left[16] = 0; left[16] = 0;
/* left_len = 16; */ /* for now this isnt used again */ /* left_len = 16; */ /* for now this isnt used again */
memcpy(name, left, sizeof(char) * 16); memcpy(name, left, sizeof(char) * 17);
continue; continue;
} }
/* this format specifier is from hell... */ /* this format specifier is from hell... */
@@ -1199,8 +1199,15 @@ int new_id(ListBase *lb, ID *id, const char *tname)
* easier to assign each time then to check if its needed */ * easier to assign each time then to check if its needed */
name[sizeof(name)-1]= 0; name[sizeof(name)-1]= 0;
if(name[0] == '\0') if(name[0] == '\0') {
/* disallow empty names */
strcpy(name, ID_FALLBACK_NAME); strcpy(name, ID_FALLBACK_NAME);
}
else {
/* disallow non utf8 chars,
* the interface checks for this but new ID's based on file names dont */
BLI_utf8_invalid_strip(name, strlen(name));
}
result = check_for_dupid(lb, id, name); result = check_for_dupid(lb, id, name);
strcpy(id->name+2, name); strcpy(id->name+2, name);
@@ -1391,8 +1398,9 @@ void text_idbutton(struct ID *id, char *text)
text[4]= 0; text[4]= 0;
} }
} }
else else {
strcpy(text, ""); text[0]= '\0';
}
} }
void rename_id(ID *id, char *name) void rename_id(ID *id, char *name)

View File

@@ -435,6 +435,90 @@ short *give_totcolp(Object *ob)
return NULL; return NULL;
} }
/* same as above but for ID's */
Material ***give_matarar_id(ID *id)
{
switch(GS(id->name)) {
case ID_ME:
return &(((Mesh *)id)->mat);
break;
case ID_CU:
return &(((Curve *)id)->mat);
break;
case ID_MB:
return &(((Curve *)id)->mat);
break;
}
return NULL;
}
short *give_totcolp_id(ID *id)
{
switch(GS(id->name)) {
case ID_ME:
return &(((Mesh *)id)->totcol);
break;
case ID_CU:
return &(((Curve *)id)->totcol);
break;
case ID_MB:
return &(((Curve *)id)->totcol);
break;
}
return NULL;
}
void material_append_id(ID *id, Material *ma)
{
Material ***matar;
if((matar= give_matarar_id(id))) {
short *totcol= give_totcolp_id(id);
Material **mat= MEM_callocN(sizeof(void *) * ((*totcol) + 1), "newmatar");
if(*totcol) memcpy(mat, *matar, sizeof(void *) * (*totcol));
if(*matar) MEM_freeN(*matar);
*matar= mat;
(*matar)[(*totcol)++]= ma;
id_us_plus((ID *)ma);
test_object_materials(id);
}
}
Material *material_pop_id(ID *id, int index)
{
Material *ret= NULL;
Material ***matar;
if((matar= give_matarar_id(id))) {
short *totcol= give_totcolp_id(id);
if(index >= 0 && index < (*totcol)) {
ret= (*matar)[index];
if(*totcol <= 1) {
*totcol= 0;
MEM_freeN(*matar);
*matar= NULL;
}
else {
Material **mat;
if(index + 1 != (*totcol))
memmove((*matar), (*matar) + 1, (*totcol) - (index + 1));
(*totcol)--;
mat= MEM_callocN(sizeof(void *) * (*totcol), "newmatar");
memcpy(mat, *matar, sizeof(void *) * (*totcol));
MEM_freeN(*matar);
*matar= mat;
test_object_materials(id);
}
}
}
return ret;
}
Material *give_current_material(Object *ob, int act) Material *give_current_material(Object *ob, int act)
{ {
Material ***matarar, *ma; Material ***matarar, *ma;
@@ -454,7 +538,7 @@ Material *give_current_material(Object *ob, int act)
} }
else { /* in data */ else { /* in data */
/* check for inconsistancy */ /* check for inconsistency */
if(*totcolp < ob->totcol) if(*totcolp < ob->totcol)
ob->totcol= *totcolp; ob->totcol= *totcolp;
if(act>ob->totcol) act= ob->totcol; if(act>ob->totcol) act= ob->totcol;

View File

@@ -2553,7 +2553,7 @@ void object_handle_update(Scene *scene, Object *ob)
while(psys) { while(psys) {
if(psys_check_enabled(ob, psys)) { if(psys_check_enabled(ob, psys)) {
/* check use of dupli objects here */ /* check use of dupli objects here */
if(psys->part && psys->part->draw_as == PART_DRAW_REND && if(psys->part && (psys->part->draw_as == PART_DRAW_REND || G.rendering) &&
((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob) ((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob)
|| (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group))) || (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group)))
ob->transflag |= OB_DUPLIPARTS; ob->transflag |= OB_DUPLIPARTS;

View File

@@ -709,6 +709,10 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float
data->timeoffset= timeoffset; data->timeoffset= timeoffset;
psys->renderdata= data; psys->renderdata= data;
/* Hair can and has to be recalculated if everything isn't displayed. */
if(psys->part->disp != 100 && psys->part->type == PART_HAIR)
psys->recalc |= PSYS_RECALC_RESET;
} }
void psys_render_restore(Object *ob, ParticleSystem *psys) void psys_render_restore(Object *ob, ParticleSystem *psys)
@@ -1117,6 +1121,24 @@ static int get_pointcache_times_for_particle(PointCache *cache, int index, float
return ret == 2; return ret == 2;
} }
float psys_get_dietime_from_cache(PointCache *cache, int index) {
PTCacheMem *pm;
int dietime = 10000000; /* some max value so that we can default to pa->time+lifetime */
for(pm=cache->mem_cache.last; pm; pm=pm->prev) {
if(pm->index_array) {
if(pm->index_array[index])
return (float)pm->frame;
}
else {
return (float)pm->frame;
}
}
return (float)dietime;
}
static void init_particle_interpolation(Object *ob, ParticleSystem *psys, ParticleData *pa, ParticleInterpolationData *pind) static void init_particle_interpolation(Object *ob, ParticleSystem *psys, ParticleData *pa, ParticleInterpolationData *pind)
{ {
@@ -2009,6 +2031,10 @@ void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
LOOP_PARTICLES { LOOP_PARTICLES {
psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,state.co,0,0,0,0,0); psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,state.co,0,0,0,0,0);
mul_m4_v3(sim->ob->obmat, state.co);
mul_mat3_m4_v3(sim->ob->obmat, state.vel);
pd_point_from_particle(sim, pa, &state, &point); pd_point_from_particle(sim, pa, &state, &point);
for(eff = effectors->first; eff; eff=eff->next) { for(eff = effectors->first; eff; eff=eff->next) {
@@ -3164,7 +3190,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
/* at the moment this is only used for weight painting. /* at the moment this is only used for weight painting.
* will need to move out of this check if its used elsewhere. */ * will need to move out of this check if its used elsewhere. */
t2 = birthtime + ((float)(k+1)/(float)steps) * (dietime - birthtime); t2 = birthtime + ((float)k/(float)steps) * (dietime - birthtime);
while (pind.hkey[1]->time < t2) pind.hkey[1]++; while (pind.hkey[1]->time < t2) pind.hkey[1]++;
pind.hkey[0] = pind.hkey[1] - 1; pind.hkey[0] = pind.hkey[1] - 1;
@@ -4423,3 +4449,34 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3]
VECADDFAC(center, center, yvec, bb->offset[1]); VECADDFAC(center, center, yvec, bb->offset[1]);
} }
void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys) {
ParticleSimulationData sim = {scene, ob, psys, psys_get_modifier(ob, psys)};
psys->lattice = psys_get_lattice(&sim);
if(psys->lattice) {
ParticleData *pa = psys->particles;
HairKey *hkey;
int p, h;
float hairmat[4][4], imat[4][4];
for(p=0; p<psys->totpart; p++, pa++) {
psys_mat_hair_to_global(sim.ob, sim.psmd->dm, psys->part->from, pa, hairmat);
invert_m4_m4(imat, hairmat);
hkey = pa->hair;
for(h=0; h<pa->totkey; h++, hkey++) {
mul_m4_v3(hairmat, hkey->co);
calc_latt_deform(psys->lattice, hkey->co, 1.0f);
mul_m4_v3(imat, hkey->co);
}
}
end_latt_deform(psys->lattice);
psys->lattice= NULL;
/* protect the applied shape */
psys->flag |= PSYS_EDITED;
}
}

View File

@@ -106,19 +106,25 @@
/* Reacting to system events */ /* Reacting to system events */
/************************************************/ /************************************************/
static int get_current_display_percentage(ParticleSystem *psys) static int particles_are_dynamic(ParticleSystem *psys) {
if(psys->pointcache->flag & PTCACHE_BAKED)
return 0;
if(psys->part->type == PART_HAIR)
return psys->flag & PSYS_HAIR_DYNAMICS;
else
return ELEM3(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID);
}
int psys_get_current_display_percentage(ParticleSystem *psys)
{ {
ParticleSettings *part=psys->part; ParticleSettings *part=psys->part;
if(psys->renderdata || (part->child_nbr && part->childtype) if((psys->renderdata && !particles_are_dynamic(psys)) /* non-dynamic particles can be rendered fully */
|| (psys->pointcache->flag & PTCACHE_BAKING)) || (part->child_nbr && part->childtype) /* display percentage applies to children */
|| (psys->pointcache->flag & PTCACHE_BAKING)) /* baking is always done with full amount */
return 100; return 100;
if(part->phystype==PART_PHYS_KEYED){ return psys->part->disp;
return psys->part->disp;
}
else
return psys->part->disp;
} }
void psys_reset(ParticleSystem *psys, int mode) void psys_reset(ParticleSystem *psys, int mode)
@@ -1567,8 +1573,6 @@ void initialize_particle(ParticleSimulationData *sim, ParticleData *pa, int p)
/* TODO: needs some work to make most blendtypes generally usefull */ /* TODO: needs some work to make most blendtypes generally usefull */
psys_get_texture(sim,ma,pa,&ptex,MAP_PA_INIT); psys_get_texture(sim,ma,pa,&ptex,MAP_PA_INIT);
} }
pa->lifetime= part->lifetime*ptex.life;
if(part->type==PART_HAIR) if(part->type==PART_HAIR)
pa->time= 0.0f; pa->time= 0.0f;
@@ -1584,25 +1588,6 @@ void initialize_particle(ParticleSimulationData *sim, ParticleData *pa, int p)
pa->time= part->sta + (part->end - part->sta)*ptex.time; pa->time= part->sta + (part->end - part->sta)*ptex.time;
} }
if(part->type==PART_HAIR){
pa->lifetime=100.0f;
}
else{
#if 0 // XXX old animation system
icu=find_ipocurve(psys->part->ipo,PART_EMIT_LIFE);
if(icu){
calc_icu(icu,100*ptex.time);
pa->lifetime*=icu->curval;
}
#endif // XXX old animation system
if(part->randlife!=0.0)
pa->lifetime*= 1.0f - part->randlife * BLI_frand();
}
pa->dietime= pa->time+pa->lifetime;
if(part->type!=PART_HAIR && part->distr!=PART_DISTR_GRID && part->from != PART_FROM_VERT){ if(part->type!=PART_HAIR && part->distr!=PART_DISTR_GRID && part->from != PART_FROM_VERT){
if(ptex.exist < BLI_frand()) if(ptex.exist < BLI_frand())
pa->flag |= PARS_UNEXIST; pa->flag |= PARS_UNEXIST;
@@ -1695,6 +1680,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
part=psys->part; part=psys->part;
ptex.ivel=1.0; ptex.ivel=1.0;
ptex.life=1.0;
/* we need to get every random even if they're not used so that they don't effect eachother */ /* we need to get every random even if they're not used so that they don't effect eachother */
r_vel[0] = 2.0f * (PSYS_FRAND(p + 10) - 0.5f); r_vel[0] = 2.0f * (PSYS_FRAND(p + 10) - 0.5f);
@@ -1752,7 +1738,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0);
/* get possible textural influence */ /* get possible textural influence */
psys_get_texture(sim, give_current_material(sim->ob,part->omat), pa, &ptex, MAP_PA_IVEL); psys_get_texture(sim, give_current_material(sim->ob,part->omat), pa, &ptex, MAP_PA_IVEL|MAP_PA_LIFE);
//if(vg_vel && pa->num != -1) //if(vg_vel && pa->num != -1)
// ptex.ivel*=psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_vel); // ptex.ivel*=psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_vel);
@@ -1975,8 +1961,25 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
} }
} }
if(part->type == PART_HAIR){
pa->lifetime = 100.0f;
}
else{
pa->lifetime = part->lifetime*ptex.life;
if(part->randlife != 0.0)
pa->lifetime *= 1.0f - part->randlife * PSYS_FRAND(p + 21);
}
pa->dietime = pa->time + pa->lifetime; pa->dietime = pa->time + pa->lifetime;
if(sim->psys->pointcache && sim->psys->pointcache->flag & PTCACHE_BAKED &&
sim->psys->pointcache->mem_cache.first) {
float dietime = psys_get_dietime_from_cache(sim->psys->pointcache, p);
pa->dietime = MIN2(pa->dietime, dietime);
}
if(pa->time > cfra) if(pa->time > cfra)
pa->alive = PARS_UNBORN; pa->alive = PARS_UNBORN;
else if(pa->dietime <= cfra) else if(pa->dietime <= cfra)
@@ -3052,7 +3055,7 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo
/* Stickness to surface */ /* Stickness to surface */
normalize_v3(nor_vec); normalize_v3(nor_vec);
madd_v3_v3fl(pa->state.vel, nor_vec, -pd->pdef_stickness); madd_v3_v3fl(pa->state.vel, col.nor, -pd->pdef_stickness);
} }
col.t = dt; col.t = dt;
@@ -3250,7 +3253,7 @@ static void hair_step(ParticleSimulationData *sim, float cfra)
ParticleSystem *psys = sim->psys; ParticleSystem *psys = sim->psys;
/* ParticleSettings *part = psys->part; */ /* ParticleSettings *part = psys->part; */
PARTICLE_P; PARTICLE_P;
float disp = (float)get_current_display_percentage(psys)/100.0f; float disp = (float)psys_get_current_display_percentage(psys)/100.0f;
BLI_srandom(psys->seed); BLI_srandom(psys->seed);
@@ -3518,7 +3521,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra)
psys_update_effectors(sim); psys_update_effectors(sim);
disp= (float)get_current_display_percentage(psys)/100.0f; disp= (float)psys_get_current_display_percentage(psys)/100.0f;
LOOP_PARTICLES { LOOP_PARTICLES {
pa->size = part->size; pa->size = part->size;
@@ -3785,7 +3788,7 @@ static void system_step(ParticleSimulationData *sim, float cfra)
/* 3. do dynamics */ /* 3. do dynamics */
/* set particles to be not calculated TODO: can't work with pointcache */ /* set particles to be not calculated TODO: can't work with pointcache */
disp= (float)get_current_display_percentage(psys)/100.0f; disp= (float)psys_get_current_display_percentage(psys)/100.0f;
BLI_srandom(psys->seed); BLI_srandom(psys->seed);
LOOP_PARTICLES { LOOP_PARTICLES {
@@ -4035,6 +4038,10 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
{ {
PARTICLE_P; PARTICLE_P;
/* Particles without dynamics haven't been reset yet because they don't use pointcache */
if(psys->recalc & PSYS_RECALC_RESET)
psys_reset(psys, PSYS_RESET_ALL);
if(emit_particles(&sim, NULL, cfra)) { if(emit_particles(&sim, NULL, cfra)) {
free_keyed_keys(psys); free_keyed_keys(psys);
distribute_particles(&sim, part->from); distribute_particles(&sim, part->from);

View File

@@ -273,4 +273,4 @@ Report *BKE_reports_last_displayable(ReportList *reports)
} }
return NULL; return NULL;
} }

View File

@@ -572,9 +572,22 @@ void set_sca_new_poins_ob(Object *ob)
bObjectActuator *oa= act->data; bObjectActuator *oa= act->data;
ID_NEW(oa->reference); ID_NEW(oa->reference);
} }
else if(act->type==ACT_SCENE) { else if(act->type==ACT_MESSAGE) {
bSceneActuator *sca= act->data; bMessageActuator *ma= act->data;
ID_NEW(sca->camera); ID_NEW(ma->toObject);
}
else if(act->type==ACT_PARENT) {
bParentActuator *para = act->data;
ID_NEW(para->ob);
}
else if(act->type==ACT_ARMATURE) {
bArmatureActuator *aa = act->data;
ID_NEW(aa->target);
ID_NEW(aa->subtarget);
}
else if(act->type==ACT_PROPERTY) {
bPropertyActuator *pa= act->data;
ID_NEW(pa->ob);
} }
} }
act= act->next; act= act->next;

View File

@@ -689,6 +689,49 @@ MTex *add_mtex()
return mtex; return mtex;
} }
/* slot -1 for first free ID */
MTex *add_mtex_id(ID *id, int slot)
{
MTex **mtex_ar;
short act;
give_active_mtex(id, &mtex_ar, &act);
if(mtex_ar==NULL) {
return NULL;
}
if(slot==-1) {
/* find first free */
int i;
for (i= 0; i < MAX_MTEX; i++) {
if (!mtex_ar[i]) {
slot= i;
break;
}
}
if(slot == -1) {
return NULL;
}
}
else {
/* make sure slot is valid */
if(slot < 0 || slot >= MAX_MTEX) {
return NULL;
}
}
if (mtex_ar[slot]) {
id_us_min((ID *)mtex_ar[slot]->tex);
MEM_freeN(mtex_ar[slot]);
mtex_ar[slot]= NULL;
}
mtex_ar[slot]= add_mtex();
return mtex_ar[slot];
}
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
Tex *copy_texture(Tex *tex) Tex *copy_texture(Tex *tex)

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