merge from trunk at r31523

This commit is contained in:
Joseph Eagar 2010-09-07 05:47:34 +00:00
commit 82432d0d99
342 changed files with 6150 additions and 4824 deletions

@ -294,9 +294,9 @@ IF(UNIX AND NOT APPLE)
SET(EXPAT_LIB expat)
ENDIF (WITH_OPENCOLLADA)
FIND_PACKAGE(X11 REQUIRED)
# Could use ${X11_Xinput_LIB} ${X11_X11_LIB} too
SET(LLIBS "-lXi -lutil -lc -lm -lpthread -lstdc++ -lX11")
SET(LLIBS "-lutil -lc -lm -lpthread -lstdc++ ${X11_X11_LIB} ${X11_Xinput_LIB}")
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
# BSD's dont use libdl.so
@ -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_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)
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_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)
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_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)
@ -873,7 +881,7 @@ ENDIF(WITH_RAYOPTIMIZATION)
IF(WITH_IMAGE_OPENJPEG)
set(OPENJPEG ${CMAKE_SOURCE_DIR}/extern/libopenjpeg)
set(OPENJPEG_INC ${OPENJPEG})
set(OPENJPEG_LIb extern_libopenjpeg)
set(OPENJPEG_LIb extern_openjpeg)
ENDIF(WITH_IMAGE_OPENJPEG)
#-----------------------------------------------------------------------------

@ -406,12 +406,12 @@ thestatlibs, thelibincs = B.setup_staticlibs(env)
thesyslibs = B.setup_syslibs(env)
if 'blender' in B.targets or not env['WITH_BF_NOBLENDER']:
env.BlenderProg(B.root_build_dir, "blender", dobj + mainlist + thestatlibs, [], 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']:
playerlist = B.create_blender_liblist(env, 'player')
playerlist += B.create_blender_liblist(env, 'intern')
playerlist += B.create_blender_liblist(env, 'extern')
env.BlenderProg(B.root_build_dir, "blenderplayer", dobj + playerlist, [], thestatlibs + 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

@ -0,0 +1,119 @@
#! /usr/bin/env python
# ##### 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>
def print_help(targets):
print("CMake quicky wrapper, no valid targets given.")
print(" * targets can contain a subset of the full target name.")
print(" * arguments with a '-' prefix are passed onto make.")
print(" * this must run from the cmake build dir")
print(" * alias this with a short command for speedy access, in bash:")
print(" alias mk='../blender/build_files/cmake/example_scripts/make_quicky.py'")
print("")
print(" eg: make_quicky.py -j3 extern python")
print(" ...will execute")
print(" make -j3 extern_binreloc extern_glew bf_python bf_python_ext blender/fast")
print("")
print("Target List:")
for t in targets:
print(" %s" % t)
print("...exiting")
def main():
targets = set()
# collect targets
file = open("Makefile", "r")
for line in file:
line = line.rstrip()
if not line or line[0] in ". \t@$#":
continue
line = line.split("#", 1)[0]
if ":" not in line:
continue
line = line.split(":", 1)[0]
if "/" in line: # cmake terget options, dont need these
continue
targets.add(line)
file.close()
# remove cmake targets
bad = set([
"help",
"clean",
"all",
"preinstall",
"install",
"default_target",
"edit_cache",
"cmake_force",
"rebuild_cache",
"depend",
"cmake_check_build_system",
])
targets -= set(bad)
# parse args
targets = list(targets)
targets.sort()
import sys
if len(sys.argv) == 1:
print_help(targets)
return
targets_new = []
args = []
for arg in sys.argv[1:]:
if arg[0] in "/-":
args.append(arg)
else:
found = False
for t in targets:
if arg in t and t not in targets_new:
targets_new.append(t)
found = True
if not found:
print("Error '%s' not found in...")
for t in targets:
print(" %s" % t)
print("...aborting.")
return
# execute
cmd = "make %s %s blender/fast" % (" ".join(args), " ".join(targets_new))
print("cmake building with targets: %s" % " ".join(targets_new))
print("executing: %s" % cmd)
import os
os.system(cmd)
if __name__ == "__main__":
main()

@ -57,7 +57,6 @@ BF_OPENEXR_LIB = 'Half IlmImf Iex Imath '
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
# BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
WITH_BF_DDS = True
WITH_BF_JPEG = True
@ -87,7 +86,7 @@ BF_GETTEXT_INC = '${BF_GETTEXT}/include'
BF_GETTEXT_LIB = 'gettextlib'
BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = True
WITH_BF_GAMEENGINE = False
WITH_BF_PLAYER = True
WITH_BF_BULLET = True
@ -100,7 +99,8 @@ BF_FREETYPE = '/usr/local'
BF_FREETYPE_INC = '${BF_FREETYPE}/include ${BF_FREETYPE}/include/freetype2'
BF_FREETYPE_LIB = 'freetype'
WITH_BF_QUICKTIME = True # -DWITH_QUICKTIME
### XXX Find what this actually wants; it doesn't want libquicktime.
WITH_BF_QUICKTIME = False # -DWITH_QUICKTIME
BF_QUICKTIME = '/usr/local'
BF_QUICKTIME_INC = '${BF_QUICKTIME}/include'
@ -195,7 +195,7 @@ CXX_WARN = ['-Wno-invalid-offsetof', '-Wno-sign-compare']
##FIX_STUBS_WARNINGS = -Wno-unused
LLIBS = ['util', 'c', 'm', 'dl', 'pthread', 'stdc++']
LLIBS = ['util', 'c', 'm', 'pthread', 'stdc++']
##LOPTS = --dynamic
##DYNLDFLAGS = -shared $(LDFLAGS)

@ -57,7 +57,6 @@ BF_OPENEXR_LIB = 'Half IlmImf Iex Imath '
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
# BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
WITH_BF_DDS = True
WITH_BF_JPEG = True
@ -87,7 +86,7 @@ BF_GETTEXT_INC = '${BF_GETTEXT}/include'
BF_GETTEXT_LIB = 'gettextlib'
BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = True
WITH_BF_GAMEENGINE = False
WITH_BF_PLAYER = True
WITH_BF_BULLET = True
@ -100,7 +99,8 @@ BF_FREETYPE = '/usr/local'
BF_FREETYPE_INC = '${BF_FREETYPE}/include ${BF_FREETYPE}/include/freetype2'
BF_FREETYPE_LIB = 'freetype'
WITH_BF_QUICKTIME = True # -DWITH_QUICKTIME
### XXX Find what this actually wants; it doesn't want libquicktime.
WITH_BF_QUICKTIME = False # -DWITH_QUICKTIME
BF_QUICKTIME = '/usr/local'
BF_QUICKTIME_INC = '${BF_QUICKTIME}/include'
@ -195,7 +195,7 @@ CXX_WARN = ['-Wno-invalid-offsetof', '-Wno-sign-compare']
##FIX_STUBS_WARNINGS = -Wno-unused
LLIBS = ['util', 'c', 'm', 'dl', 'pthread', 'stdc++']
LLIBS = ['util', 'c', 'm', 'pthread', 'stdc++']
##LOPTS = --dynamic
##DYNLDFLAGS = -shared $(LDFLAGS)

@ -57,7 +57,6 @@ BF_OPENEXR_LIB = 'Half IlmImf Iex Imath '
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
# BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
WITH_BF_DDS = True
WITH_BF_JPEG = True
@ -87,7 +86,7 @@ BF_GETTEXT_INC = '${BF_GETTEXT}/include'
BF_GETTEXT_LIB = 'gettextlib'
BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = True
WITH_BF_GAMEENGINE = False
WITH_BF_PLAYER = True
WITH_BF_BULLET = True
@ -100,7 +99,8 @@ BF_FREETYPE = '/usr/local'
BF_FREETYPE_INC = '${BF_FREETYPE}/include ${BF_FREETYPE}/include/freetype2'
BF_FREETYPE_LIB = 'freetype'
WITH_BF_QUICKTIME = True # -DWITH_QUICKTIME
### XXX Find what this actually wants; it doesn't want libquicktime.
WITH_BF_QUICKTIME = False # -DWITH_QUICKTIME
BF_QUICKTIME = '/usr/local'
BF_QUICKTIME_INC = '${BF_QUICKTIME}/include'
@ -195,7 +195,7 @@ CXX_WARN = ['-Wno-invalid-offsetof', '-Wno-sign-compare']
##FIX_STUBS_WARNINGS = -Wno-unused
LLIBS = ['util', 'c', 'm', 'dl', 'pthread', 'stdc++']
LLIBS = ['util', 'c', 'm', 'pthread', 'stdc++']
##LOPTS = --dynamic
##DYNLDFLAGS = -shared $(LDFLAGS)

@ -84,6 +84,8 @@ BF_GETTEXT = '/usr'
BF_GETTEXT_INC = '${BF_GETTEXT}/include'
BF_GETTEXT_LIB = 'gettextlib'
BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
#WITH_BF_GETTEXT_STATIC = True
#BF_GETTEXT_LIB_STATIC = '${BF_GETTEXT}/lib/libgettextlib.a'
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = False
@ -97,6 +99,8 @@ BF_BULLET_LIB = 'extern_bullet'
BF_FREETYPE = '/usr'
BF_FREETYPE_INC = '${BF_FREETYPE}/include ${BF_FREETYPE}/include/freetype2'
BF_FREETYPE_LIB = 'freetype'
#WITH_BF_FREETYPE_STATIC = True
#BF_FREETYPE_LIB_STATIC = '${BF_FREETYPE}/lib/libfreetype.a'
WITH_BF_QUICKTIME = False # -DWITH_QUICKTIME
BF_QUICKTIME = '/usr/local'
@ -116,6 +120,8 @@ BF_FFMPEG = '/usr'
BF_FFMPEG_LIB = 'avformat avcodec swscale avutil avdevice'
BF_FFMPEG_INC = '${BF_FFMPEG}/include'
BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib'
#WITH_BF_STATICFFMPEG = True
#BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH/libavcodec.a ${BF_FFMPEG_LIBPATH}/libswscale.a ${BF_FFMPEG_LIBPATH}/libavutil.a ${BF_FFMPEG_LIBPATH}/libavdevice.a'
# enable ogg, vorbis and theora in ffmpeg
WITH_BF_OGG = False # -DWITH_OGG

@ -23,6 +23,7 @@ import sys
import zipfile
import shutil
import cStringIO
import platform
from SCons.Script.SConscript import SConsEnvironment
import SCons.Action
@ -153,8 +154,14 @@ def setup_staticlibs(lenv):
libincs += Split(lenv['BF_TIFF_LIBPATH'])
if lenv['WITH_BF_FFTW3']:
libincs += Split(lenv['BF_FFTW3_LIBPATH'])
if lenv['WITH_BF_FFMPEG'] and lenv['WITH_BF_STATICFFMPEG']:
statlibs += Split(lenv['BF_FFMPEG_LIB_STATIC'])
if lenv['WITH_BF_INTERNATIONAL']:
libincs += Split(lenv['BF_GETTEXT_LIBPATH'])
if lenv['WITH_BF_GETTEXT_STATIC']:
statlibs += Split(lenv['BF_GETTEXT_LIB_STATIC'])
if lenv['WITH_BF_FREETYPE_STATIC']:
statlibs += Split(lenv['BF_FREETYPE_LIB_STATIC'])
if lenv['WITH_BF_OPENAL']:
libincs += Split(lenv['BF_OPENAL_LIBPATH'])
if lenv['WITH_BF_STATICOPENAL']:
@ -195,13 +202,14 @@ def setup_syslibs(lenv):
lenv['BF_LIBSAMPLERATE_LIB']
]
if not lenv['WITH_BF_FREETYPE_STATIC']:
syslibs += Split(lenv['BF_FREETYPE_LIB'])
if lenv['WITH_BF_PYTHON'] and not lenv['WITH_BF_STATICPYTHON']:
if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc', 'win32-mingw'):
syslibs.append(lenv['BF_PYTHON_LIB']+'_d')
else:
syslibs.append(lenv['BF_PYTHON_LIB'])
if lenv['WITH_BF_INTERNATIONAL']:
if lenv['WITH_BF_INTERNATIONAL'] and not lenv['WITH_BF_GETTEXT_STATIC']:
syslibs += Split(lenv['BF_GETTEXT_LIB'])
if lenv['WITH_BF_OPENAL']:
if not lenv['WITH_BF_STATICOPENAL']:
@ -218,7 +226,7 @@ def setup_syslibs(lenv):
syslibs += Split(lenv['BF_OPENEXR_LIB'])
if lenv['WITH_BF_TIFF']:
syslibs += Split(lenv['BF_TIFF_LIB'])
if lenv['WITH_BF_FFMPEG']:
if lenv['WITH_BF_FFMPEG'] and not lenv['WITH_BF_STATICFFMPEG']:
syslibs += Split(lenv['BF_FFMPEG_LIB'])
if lenv['WITH_BF_OGG']:
syslibs += Split(lenv['BF_OGG_LIB'])
@ -269,15 +277,21 @@ def buildinfo(lenv, build_type):
build_date = time.strftime ("%Y-%m-%d")
build_time = time.strftime ("%H:%M:%S")
build_rev = os.popen('svnversion').read()[:-1] # remove \n
if build_rev == '':
build_rev = '<UNKNOWN>'
if lenv['BF_DEBUG']:
build_type = "Debug"
else:
build_type = "Release"
obj = []
if lenv['BF_BUILDINFO']:
lenv.Append (CPPDEFINES = ['BUILD_TIME=\'"%s"\''%(build_time),
'BUILD_DATE=\'"%s"\''%(build_date),
'BUILD_TYPE=\'"dynamic"\'',
'BUILD_REV=\'"%s"\''%(build_rev),
lenv.Append (CPPDEFINES = ['BUILD_TIME="%s"'%(build_time),
'BUILD_DATE="%s"'%(build_date),
'BUILD_TYPE="%s"'%(build_type),
'BUILD_REV="%s"'%(build_rev),
'NAN_BUILDINFO',
'BUILD_PLATFORM=\'"%s"\''%(sys.platform)])
'BUILD_PLATFORM="%s:%s"'%(platform.system(), platform.architecture()[0])])
obj = [lenv.Object (root_build_dir+'source/creator/%s_buildinfo'%build_type,
[root_build_dir+'source/creator/buildinfo.c'])]
return obj
@ -463,6 +477,9 @@ def WinPyBundle(target=None, source=None, env=None):
py_zip= env.subst( env['LCGDIR'] )
if py_zip[0]=='#':
py_zip= py_zip[1:]
if env['BF_DEBUG']:
py_zip+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '_d.zip'
else:
py_zip+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '.zip'
py_target = env.subst( env['BF_INSTALLDIR'] )
@ -722,7 +739,7 @@ class BlenderEnvironment(SConsEnvironment):
# note: libs is a global
add_lib_to_dict(self, libs, libtype, libname, priority)
def BlenderProg(self=None, builddir=None, progname=None, sources=None, includes=None, libs=None, libpath=None, binarykind=''):
def BlenderProg(self=None, builddir=None, progname=None, sources=None, libs=None, libpath=None, binarykind=''):
global vcp
print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
lenv = self.Clone()
@ -748,7 +765,6 @@ class BlenderEnvironment(SConsEnvironment):
lenv.Append(LINKFLAGS = lenv['BF_OPENGL_LINKFLAGS'])
if lenv['BF_PROFILE']:
lenv.Append(LINKFLAGS = lenv['BF_PROFILE_LINKFLAGS'])
lenv.Append(CPPPATH=includes)
if root_build_dir[0]==os.sep or root_build_dir[1]==':':
lenv.Append(LIBPATH=root_build_dir + '/lib')
lenv.Append(LIBPATH=libpath)

@ -38,6 +38,7 @@ def validate_arguments(args, bc):
'WITH_BF_OPENEXR', 'BF_OPENEXR', 'BF_OPENEXR_INC', 'BF_OPENEXR_LIB', 'BF_OPENEXR_LIBPATH', 'WITH_BF_STATICOPENEXR', 'BF_OPENEXR_LIB_STATIC',
'WITH_BF_DDS', 'WITH_BF_CINEON', 'WITH_BF_HDR',
'WITH_BF_FFMPEG', 'BF_FFMPEG_LIB','BF_FFMPEG_EXTRA', 'BF_FFMPEG', 'BF_FFMPEG_INC',
'WITH_BF_STATICFFMPEG', 'BF_FFMPEG_LIB_STATIC',
'WITH_BF_OGG', 'BF_OGG', 'BF_OGG_LIB',
'WITH_BF_JPEG', 'BF_JPEG', 'BF_JPEG_INC', 'BF_JPEG_LIB', 'BF_JPEG_LIBPATH',
'WITH_BF_OPENJPEG', 'BF_OPENJPEG', 'BF_OPENJPEG_INC', 'BF_OPENJPEG_LIB', 'BF_OPENJPEG_LIBPATH',
@ -46,11 +47,11 @@ def validate_arguments(args, bc):
'WITH_BF_TIFF', 'BF_TIFF', 'BF_TIFF_INC', 'BF_TIFF_LIB', 'BF_TIFF_LIBPATH',
'WITH_BF_ZLIB', 'BF_ZLIB', 'BF_ZLIB_INC', 'BF_ZLIB_LIB', 'BF_ZLIB_LIBPATH',
'WITH_BF_INTERNATIONAL',
'BF_GETTEXT', 'BF_GETTEXT_INC', 'BF_GETTEXT_LIB', 'BF_GETTEXT_LIBPATH',
'BF_GETTEXT', 'BF_GETTEXT_INC', 'BF_GETTEXT_LIB', 'WITH_BF_GETTEXT_STATIC', 'BF_GETTEXT_LIB_STATIC', 'BF_GETTEXT_LIBPATH',
'WITH_BF_ICONV', 'BF_ICONV', 'BF_ICONV_INC', 'BF_ICONV_LIB', 'BF_ICONV_LIBPATH',
'WITH_BF_GAMEENGINE', 'WITH_BF_BULLET', 'BF_BULLET', 'BF_BULLET_INC', 'BF_BULLET_LIB',
'BF_WINTAB', 'BF_WINTAB_INC',
'WITH_BF_FREETYPE', 'BF_FREETYPE', 'BF_FREETYPE_INC', 'BF_FREETYPE_LIB', 'BF_FREETYPE_LIBPATH',
'WITH_BF_FREETYPE', 'BF_FREETYPE', 'BF_FREETYPE_INC', 'BF_FREETYPE_LIB', 'BF_FREETYPE_LIBPATH', 'BF_FREETYPE_LIB_STATIC', 'WITH_BF_FREETYPE_STATIC',
'WITH_BF_QUICKTIME', 'BF_QUICKTIME', 'BF_QUICKTIME_INC', 'BF_QUICKTIME_LIB', 'BF_QUICKTIME_LIBPATH',
'WITH_BF_FFTW3', 'BF_FFTW3', 'BF_FFTW3_INC', 'BF_FFTW3_LIB', 'BF_FFTW3_LIBPATH',
'WITH_BF_STATICOPENGL', 'BF_OPENGL', 'BF_OPENGL_INC', 'BF_OPENGL_LIB', 'BF_OPENGL_LIBPATH', 'BF_OPENGL_LIB_STATIC',
@ -236,6 +237,8 @@ def read_opts(env, cfg, args):
('BF_FFMPEG_INC', 'FFMPEG includes', ''),
('BF_FFMPEG_LIBPATH', 'FFMPEG library path', ''),
(BoolVariable('WITH_BF_STATICFFMPEG', 'Use static FFMPEG if true', False)),
('BF_FFMPEG_LIB_STATIC', 'Static FFMPEG libraries', ''),
(BoolVariable('WITH_BF_OGG', 'Use OGG, THEORA, VORBIS in FFMPEG if true',
False)),
@ -289,6 +292,8 @@ def read_opts(env, cfg, args):
('BF_GETTEXT', 'gettext base path', ''),
('BF_GETTEXT_INC', 'gettext include path', ''),
('BF_GETTEXT_LIB', 'gettext library', ''),
(BoolVariable('WITH_BF_GETTEXT_STATIC', 'Use static gettext library if true', False)),
('BF_GETTEXT_LIB_STATIC', 'static gettext library', ''),
('BF_GETTEXT_LIBPATH', 'gettext library path', ''),
(BoolVariable('WITH_BF_ICONV', 'Use iconv if true', True)),
@ -309,29 +314,14 @@ def read_opts(env, cfg, args):
('BF_CXX', 'c++ base path for libstdc++, only used when static linking', ''),
(BoolVariable('WITH_BF_STATICCXX', 'static link to stdc++', False)),
('BF_CXX_LIB_STATIC', 'static library path for stdc++', ''),
##
##WITH_BF_NSPR = True
##BF_NSPR = $(LCGDIR)/nspr
##BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr
##BF_NSPR_LIB =
### Uncomment the following line to use Mozilla inplace of netscape
##CPPFLAGS += -DMOZ_NOT_NET
### Location of MOZILLA/Netscape header files...
##BF_MOZILLA = $(LCGDIR)/mozilla
##BF_MOZILLA_INC = -I$(BF_MOZILLA)/include/mozilla/nspr -I$(BF_MOZILLA)/include/mozilla -I$(BF_MOZILLA)/include/mozilla/xpcom -I$(BF_MOZILLA)/include/mozilla/idl
##BF_MOZILLA_LIB =
### Will fall back to look in BF_MOZILLA_INC/nspr and BF_MOZILLA_LIB
### if this is not set.
##
### Be paranoid regarding library creation (do not update archives)
##BF_PARANOID = True
##
### enable freetype2 support for text objects
(BoolVariable('WITH_BF_FREETYPE', 'Use FreeType2 if true', True)),
('BF_FREETYPE', 'Freetype base path', ''),
('BF_FREETYPE_INC', 'Freetype include path', ''),
('BF_FREETYPE_LIB', 'Freetype library', ''),
('BF_FREETYPE_LIBPATH', 'Freetype library path', ''),
(BoolVariable('WITH_BF_FREETYPE_STATIC', 'Use Static Freetype if true', False)),
('BF_FREETYPE_LIB_STATIC', 'Static Freetype library', ''),
(BoolVariable('WITH_BF_OPENMP', 'Use OpenMP if true', False)),
('BF_OPENMP', 'Base path to OpenMP (used when cross-compiling with older versions of WinGW)', ''),

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

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

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

@ -28,5 +28,5 @@ SET(INC . src)
FILE(GLOB SRC *.c except t1_generate_luts.c)
ADD_DEFINITIONS(-DWITH_OPENJPEG)
BLENDERLIB(extern_libopenjpeg "${SRC}" "${INC}")
BLENDERLIB(extern_openjpeg "${SRC}" "${INC}")
#, libtype=['international','player'], priority=[5, 210])

@ -28,7 +28,4 @@ SET(INC . )
FILE(GLOB SRC ./*.c)
BLENDERLIB(bf_lzma "${SRC}" "${INC}")
#, libtype='blender', priority = 0 )
BLENDERLIB(extern_lzma "${SRC}" "${INC}")

@ -6,4 +6,4 @@ sources = env.Glob('./*.c')
defs = ''
incs = ' . '
env.BlenderLib ('bf_lzma', sources, Split(incs), Split(defs), libtype=['intern'], priority=[40] )
env.BlenderLib ('extern_lzma', sources, Split(incs), Split(defs), libtype=['intern'], priority=[40] )

@ -30,5 +30,5 @@ FILE(GLOB SRC minilzo/*.c)
BLENDERLIB(bf_minilzo "${SRC}" "${INC}")
BLENDERLIB(extern_minilzo "${SRC}" "${INC}")
#, libtype='blender', priority = 0 )

@ -6,4 +6,4 @@ sources = env.Glob('minilzo/*.c')
defs = ''
incs = ' include '
env.BlenderLib ('bf_minilzo', sources, Split(incs), Split(defs), libtype=['intern'], priority=[40] )
env.BlenderLib ('extern_minilzo', sources, Split(incs), Split(defs), libtype=['intern'], priority=[40] )

@ -28,5 +28,5 @@ SET(INC . intern extern ../moto/include ../container ../memutil ../../source/ble
FILE(GLOB SRC intern/*.cpp)
BLENDERLIB(blender_bop "${SRC}" "${INC}")
BLENDERLIB(bf_intern_bop "${SRC}" "${INC}")
#, libtype='common', priority=5 )

@ -8,7 +8,7 @@ incs += ' ../../source/blender/makesdna ../../intern/guardedalloc'
incs += ' ../../source/blender/blenlib'
if (env['OURPLATFORM'] == 'win32-mingw'):
env.BlenderLib ('blender_bop', sources, Split(incs) , [], libtype='intern', priority = 5 )
env.BlenderLib ('bf_intern_bop', sources, Split(incs) , [], libtype='intern', priority = 5 )
else:
env.BlenderLib ('blender_bop', sources, Split(incs) , [], libtype='intern', priority = 5 )
env.BlenderLib ('bf_intern_bop', sources, Split(incs) , [], libtype='intern', priority = 5 )

@ -28,5 +28,5 @@ SET(INC intern ../container ../moto/include ../memutil)
FILE(GLOB SRC intern/*.cpp)
BLENDERLIB(blender_BSP "${SRC}" "${INC}")
BLENDERLIB(bf_intern_bsp "${SRC}" "${INC}")
#, libtype='core', priority=15 )

@ -5,5 +5,5 @@ sources = env.Glob('intern/*.cpp')
incs = 'intern ../container ../moto/include ../memutil'
env.BlenderLib ('blender_BSP', sources, Split(incs), [], libtype='core', priority=200 )
env.BlenderLib ('bf_intern_bsp', sources, Split(incs), [], libtype='core', priority=200 )

@ -28,5 +28,5 @@ SET(INC .)
FILE(GLOB SRC intern/*.cpp)
BLENDERLIB(blender_CTR "${SRC}" "${INC}")
BLENDERLIB(bf_intern_ctr "${SRC}" "${INC}")
#, libtype=['intern'], priority = 10 )

@ -4,4 +4,4 @@ Import ('env')
sources = env.Glob('intern/*.cpp')
incs = '.'
env.BlenderLib ('blender_CTR', sources, Split(incs) , [], libtype='intern', priority = 10 )
env.BlenderLib ('bf_intern_ctr', sources, Split(incs) , [], libtype='intern', priority = 10 )

@ -28,5 +28,5 @@ SET(INC . ../moto/include ../container ../memutil)
FILE(GLOB SRC intern/*.cpp)
BLENDERLIB(bf_decimation "${SRC}" "${INC}")
BLENDERLIB(bf_intern_decimate "${SRC}" "${INC}")
#, libtype=['core','common','player'], priority = [10, 20, 25] )

@ -5,4 +5,4 @@ sources = env.Glob('intern/*.cpp')
incs = '. ../moto/include ../container ../memutil'
env.BlenderLib ('bf_decimation', sources, Split(incs) , [], libtype=['core'], priority = [200] )
env.BlenderLib ('bf_intern_decimate', sources, Split(incs) , [], libtype=['core'], priority = [200] )

@ -37,5 +37,5 @@ IF(WITH_OPENMP)
ADD_DEFINITIONS(-DPARALLEL=1)
ENDIF(WITH_OPENMP)
BLENDERLIB_NOLIST(bf_elbeem "${SRC}" "${INC}")
BLENDERLIB_NOLIST(bf_intern_elbeem "${SRC}" "${INC}")
#, libtype='blender', priority=0 )

@ -19,4 +19,4 @@ if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
incs += ' ' + env['BF_PNG_INC'] + ' ' + env['BF_ZLIB_INC']
incs += ' extern '
env.BlenderLib ('bf_elbeem', sources, Split(incs), Split(defs), libtype='intern', priority=0 )
env.BlenderLib ('bf_intern_elbeem', sources, Split(incs), Split(defs), libtype='intern', priority=0 )

@ -90,5 +90,5 @@ ELSEIF(UNIX)
ENDIF(APPLE)
BLENDERLIB(bf_ghost "${SRC}" "${INC}")
BLENDERLIB(bf_intern_ghost "${SRC}" "${INC}")

@ -60,4 +60,4 @@ if env['BF_GHOST_DEBUG']:
incs = '. ../string #extern/glew/include #source/blender/imbuf #source/blender/makesdna ' + env['BF_OPENGL_INC']
if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
incs = env['BF_WINTAB_INC'] + ' ' + incs
env.BlenderLib ('bf_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] )

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

@ -28,10 +28,10 @@ SET(INC .)
FILE(GLOB SRC intern/*.c)
BLENDERLIB(bf_guardedalloc "${SRC}" "${INC}")
BLENDERLIB(bf_intern_guardedalloc "${SRC}" "${INC}")
# Override C++ alloc optional
IF(WITH_CXX_GUARDEDALLOC)
FILE(GLOB SRC cpp/*.cpp)
BLENDERLIB(bf_guardedalloc_cpp "${SRC}" "${INC}")
BLENDERLIB(bf_intern_guardedalloc_cpp "${SRC}" "${INC}")
ENDIF(WITH_CXX_GUARDEDALLOC)

@ -5,4 +5,4 @@ Import('env')
sources = env.Glob('intern/*.c')
incs = '.'
env.BlenderLib ('bf_guardedalloc', sources, Split(incs), defines=[], libtype=['intern','player'], priority = [5,150] )
env.BlenderLib ('bf_intern_guardedalloc', sources, Split(incs), defines=[], libtype=['intern','player'], priority = [5,150] )

@ -28,5 +28,5 @@ SET(INC intern ../moto/include ../memutil)
FILE(GLOB SRC intern/*.cpp)
BLENDERLIB(bf_IK "${SRC}" "${INC}")
BLENDERLIB(bf_intern_ik "${SRC}" "${INC}")
#, libtype=['blender'], priority = [10] )

@ -5,5 +5,5 @@ sources = env.Glob('intern/*.cpp')
incs = 'intern ../moto/include ../memutil'
env.BlenderLib ('bf_IK', sources, Split(incs), [], libtype=['intern','player'], priority=[100,90] )
env.BlenderLib ('bf_intern_ik', sources, Split(incs), [], libtype=['intern','player'], priority=[100,90] )

@ -28,5 +28,5 @@ SET(INC ../../extern/Eigen2)
FILE(GLOB SRC *.cpp kdl/*.cpp kdl/utilities/*.cpp)
BLENDERLIB(bf_ITASC "${SRC}" "${INC}")
BLENDERLIB(bf_intern_itasc "${SRC}" "${INC}")
#, libtype=['blender'], priority = [10] )

@ -7,5 +7,5 @@ sources += env.Glob('kdl/utilities/*.cpp')
incs = '. ../../extern/Eigen2'
env.BlenderLib ('bf_ITASC', sources, Split(incs), [], libtype=['intern','player'], priority=[20,100] )
env.BlenderLib ('bf_intern_itasc', sources, Split(incs), [], libtype=['intern','player'], priority=[20,100] )

@ -28,5 +28,5 @@ SET(INC . ..)
FILE(GLOB SRC intern/*.cpp)
BLENDERLIB(bf_memutil "${SRC}" "${INC}")
BLENDERLIB(bf_intern_memutil "${SRC}" "${INC}")
#, libtype=['intern', 'player'], priority = [0, 180] )

@ -5,4 +5,4 @@ sources = env.Glob('intern/*.cpp')
incs = '. ..'
env.BlenderLib ('bf_memutil', sources, Split(incs), [], libtype=['intern','player'], priority = [0,155] )
env.BlenderLib ('bf_intern_memutil', sources, Split(incs), [], libtype=['intern','player'], priority = [0,155] )

@ -28,5 +28,5 @@ SET(INC include)
FILE(GLOB SRC intern/*.cpp)
BLENDERLIB(bf_moto "${SRC}" "${INC}")
BLENDERLIB(bf_intern_moto "${SRC}" "${INC}")
#, libtype=['intern','game','game2','player'], priority = [15, 55, 100, 135] )

@ -5,4 +5,4 @@ sources = env.Glob('intern/*.cpp')
incs = 'include'
env.BlenderLib ('bf_moto', sources, Split(incs), [], libtype=['intern','player'], priority = [130,95] )
env.BlenderLib ('bf_intern_moto', sources, Split(incs), [], libtype=['intern','player'], priority = [130,95] )

@ -28,6 +28,6 @@ SET(INC extern superlu)
FILE(GLOB SRC intern/*.c superlu/*.c)
BLENDERLIB(blender_ONL "${SRC}" "${INC}")
BLENDERLIB(bf_intern_opennl "${SRC}" "${INC}")
#, libtype='core', priority=55 )

@ -6,7 +6,7 @@ sources = env.Glob('intern/*.c') + env.Glob('superlu/*.c')
incs = 'extern superlu'
if (env['OURPLATFORM'] == 'win32-mingw'):
env.BlenderLib ('blender_ONL', sources, Split(incs), [], libtype=['core','intern'], priority=[1,80] )
env.BlenderLib ('bf_intern_opennl', sources, Split(incs), [], libtype=['core','intern'], priority=[1,80] )
else:
env.BlenderLib ('blender_ONL', sources, Split(incs), [], libtype=['core'], priority=[55] )
env.BlenderLib ('bf_intern_opennl', sources, Split(incs), [], libtype=['core'], priority=[55] )

@ -38,5 +38,5 @@ IF(WITH_FFTW3)
ENDIF(WITH_FFTW3)
BLENDERLIB(bf_smoke "${SRC}" "${INC}")
BLENDERLIB(bf_intern_smoke "${SRC}" "${INC}")
#, libtype='blender', priority = 0 )

@ -19,4 +19,4 @@ if env['WITH_BF_FFTW3']:
defs += ' FFTW3=1'
incs += env['BF_FFTW3_INC']
env.BlenderLib ('bf_smoke', sources, Split(incs), Split(defs), libtype=['intern'], priority=[40] )
env.BlenderLib ('bf_intern_smoke', sources, Split(incs), Split(defs), libtype=['intern'], priority=[40] )

@ -28,5 +28,5 @@ SET(INC .)
FILE(GLOB SRC intern/*.cpp)
BLENDERLIB(bf_string "${SRC}" "${INC}")
BLENDERLIB(bf_intern_string "${SRC}" "${INC}")
#, libtype=['core', 'player'], priority = [30,10] )

@ -4,4 +4,4 @@ Import ('env')
sources = env.Glob('intern/*.cpp')
incs = '.'
env.BlenderLib ('bf_string', sources, Split(incs), [], libtype=['intern','player'], priority = [50,10] )
env.BlenderLib ('bf_intern_string', sources, Split(incs), [], libtype=['intern','player'], priority = [50,10] )

@ -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.active_uv_texture
if not active_uv_layer:
EXPORT_UV = False
faceUV = None
else:
active_uv_layer = active_uv_layer.data
if vertexColors:
active_col_layer = mesh.active_vertex_color
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()

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

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

@ -116,7 +116,7 @@ def RKS_GEN_rotation(ksi, context, ks, data):
# rotation mode affects the property used
if data.rotation_mode == 'QUATERNION':
path = path_add_property(base_path, "rotation_quaternion")
elif data.rotation_mode == 'AXISANGLE':
elif data.rotation_mode == 'AXIS_ANGLE':
path = path_add_property(base_path, "rotation_axis_angle")
else:
path = path_add_property(base_path, "rotation_euler")

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

@ -306,7 +306,9 @@ class Mesh(bpy_types.ID):
Make a mesh from a list of verts/edges/faces
Until we have a nicer way to make geometry, use this.
"""
self.add_geometry(len(verts), len(edges), len(faces))
self.vertices.add(len(verts))
self.edges.add(len(edges))
self.faces.add(len(faces))
verts_flat = [f for v in verts for f in v]
self.vertices.foreach_set("co", verts_flat)
@ -318,8 +320,11 @@ class Mesh(bpy_types.ID):
def treat_face(f):
if len(f) == 3:
return f[0], f[1], f[2], 0
elif f[3] == 0:
if f[2] == 0:
return f[2], f[0], f[1], 0
else:
return f[0], f[1], f[2], 0
elif f[2] == 0 or f[3] == 0:
return f[3], f[0], f[1], f[2]
return f

@ -262,7 +262,7 @@ def main(obj, bone_definition, base_names, options):
fcurve = ex.head_ctrl_p.driver_add('["bend_tot"]')
driver = fcurve.driver
driver.type = 'SUM'
fcurve.modifiers.remove(0) # grr dont need a modifier
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
for i in range(len(neck_chain)):
var = driver.variables.new()
@ -301,7 +301,7 @@ def main(obj, bone_definition, base_names, options):
driver.type = 'SCRIPTED'
driver.expression = "bend/bend_tot"
fcurve.modifiers.remove(0) # grr dont need a modifier
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
# add target

@ -194,7 +194,7 @@ def main(obj, bone_definition, base_names, options):
driver.expression = "(1.0-cos(x))-s"
for fcurve in driver_fcurves:
fcurve.modifiers.remove(0) # grr dont need a modifier
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
var = driver.variables.new()
var.name = "x"

@ -353,7 +353,7 @@ def main(obj, bone_definition, base_names, options):
fcurve = ex.ribcage_copy_p.driver_add('["bend_tot"]')
driver = fcurve.driver
driver.type = 'SUM'
fcurve.modifiers.remove(0) # grr dont need a modifier
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
for i in range(spine_chain_len - 1):
var = driver.variables.new()
@ -390,7 +390,7 @@ def main(obj, bone_definition, base_names, options):
driver.type = 'SCRIPTED'
driver.expression = "bend/bend_tot"
fcurve.modifiers.remove(0) # grr dont need a modifier
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
# add target

@ -266,7 +266,7 @@ def main(obj, bone_definition, base_names, options):
fcurve = ex.head_ctrl_p.driver_add('["bend_tot"]')
driver = fcurve.driver
driver.type = 'SUM'
fcurve.modifiers.remove(0) # grr dont need a modifier
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
for i in range(len(neck_chain)):
var = driver.variables.new()
@ -313,7 +313,7 @@ def main(obj, bone_definition, base_names, options):
driver.type = 'SCRIPTED'
driver.expression = "bend/bend_tot"
fcurve.modifiers.remove(0) # grr dont need a modifier
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
# add target

@ -157,7 +157,7 @@ def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, ta
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
fcurve.modifiers.remove(0) # grr dont need a modifier
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
blend_target(driver)

@ -84,6 +84,8 @@ def draw(layout, context, context_member, use_edit=True):
props.data_path = context_member
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:
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"):
row.label(text=val_draw)
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:
row = split.row(align=True)
@ -130,11 +135,11 @@ class PropertyPanel():
and the variable '_context_path' MUST be set.
"""
bl_label = "Custom Properties"
bl_default_closed = True
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
bool(eval("context.%s" % cls._context_path))
return bool(eval("context.%s" % cls._context_path))
def draw(self, context):
draw(self.layout, context, self._context_path)

@ -121,7 +121,9 @@ class AddTorus(bpy.types.Operator):
mesh = bpy.data.meshes.new("Torus")
mesh.add_geometry(int(len(verts_loc) / 3), 0, int(len(faces) / 4))
mesh.vertices.add(len(verts_loc) // 3)
mesh.faces.add(len(faces) // 4)
mesh.vertices.foreach_set("co", verts_loc)
mesh.faces.foreach_set("vertices_raw", faces)
mesh.update()
@ -133,7 +135,7 @@ class AddTorus(bpy.types.Operator):
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():

4
release/scripts/op/animsys_update.py Executable file → Normal file

@ -681,7 +681,7 @@ import bpy
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_label = "Update Animation Data"
@ -696,4 +696,4 @@ if __name__ == "__main__":
bpy.ops.anim.update_data_paths()
def register():
pass
pass

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

@ -18,6 +18,8 @@
# <pep8 compliant>
# Script copyright (C) Campbell Barton
import math
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:
ob.select = False
scn.set_frame(IMPORT_START_FRAME)
scn.frame_set(IMPORT_START_FRAME)
arm_data = bpy.data.armatures.new("MyBVH")
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
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):
'''Load a OBJ Motion Capture File'''
bl_idname = "import_anim.bvh"
bl_label = "Import BVH"
print('%.4f' % (time.time() - t1))
t1 = time.time()
print('\timporting to blender...', end="")
filepath = StringProperty(name="File Path", description="Filepath used for importing the OBJ file", maxlen=1024, default="")
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')
bvh_node_dict2armature(context, bvh_nodes,
ROT_MODE=rotate_mode,
IMPORT_START_FRAME=frame_start,
IMPORT_LOOP=use_cyclic)
def execute(self, context):
# print("Selected: " + context.active_object.name)
import time
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()
print('Done in %.4f\n' % (time.time() - t1))
return {'FINISHED'}

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

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

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

@ -1,4 +1,3 @@
# coding: utf-8
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
@ -19,74 +18,74 @@
# <pep8 compliant>
__author__ = ["Campbell Barton", "Bob Holcomb", "Richard Lärkäng", "Damien McGinnes", "Mark Stijnman"]
__url__ = ("blenderartists.org", "www.blender.org", "www.gametutorials.com", "lib3ds.sourceforge.net/")
__version__ = "0.90a"
__bpydoc__ = """\
3ds Exporter
This script Exports a 3ds file.
# Script copyright (C) Bob Holcomb
# Contributors: Campbell Barton, Bob Holcomb, Richard Lärkäng, Damien McGinnes, Mark Stijnman
"""
Exporting is based on 3ds loader from www.gametutorials.com(Thanks DigiBen) and using information
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 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
# this is verry annoying for filenames!
@ -94,13 +93,10 @@ name_unique = []
name_mapping = {}
def sane_name(name):
name_fixed = name_mapping.get(name)
if name_fixed != None:
if name_fixed is not None:
return name_fixed
if len(name) > 12:
new_name = name[:12]
else:
new_name = name
new_name = name[:12]
i = 0
@ -112,65 +108,6 @@ def sane_name(name):
name_mapping[name] = 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):
return round(uv[0], 6), round(uv[1], 6)
# return round(uv.x, 6), round(uv.y, 6)
@ -379,7 +316,7 @@ class _3ds_named_variable(object):
if (self.value!=None):
spaces=""
for i in range(indent):
spaces+=" ";
spaces += " "
if (self.name!=""):
print(spaces, self.name, " = ", self.value)
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.'''
spaces=""
for i in range(indent):
spaces+=" ";
spaces += " "
print(spaces, "ID=", hex(self.ID.value), "size=", self.get_size())
for variable in self.variables:
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.'''
mat_sub = _3ds_chunk(id)
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)
# optional:
# 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)
return mat_sub
@ -567,7 +504,7 @@ def extract_triangles(mesh):
f_v = face.vertices
# f_v = face.v
uf = mesh.active_uv_texture.data[i] if do_uv else None
uf = mesh.uv_textures.active.data[i] if do_uv else None
if do_uv:
f_uv = uf.uv
@ -921,27 +858,21 @@ def make_kf_obj_node(obj, name_to_id):
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.'''
# Time the export
if not filename.lower().endswith('.3ds'):
filename += '.3ds'
# XXX
# if not BPyMessages.Warning_SaveOver(filename):
# return
# XXX
time1 = time.clock()
# time1= Blender.sys.time()
# Blender.Window.WaitCursor(1)
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')
# Initialize the main chunk (primary):
@ -998,7 +929,7 @@ def write(filename, context):
if not mat_ls:
mat = mat_name = None
for f, uf in zip(data.faces, data.active_uv_texture.data):
for f, uf in zip(data.faces, data.uv_textures.active.data):
if mat_ls:
mat_index = f.material_index
# mat_index = f.mat
@ -1090,7 +1021,7 @@ def write(filename, context):
# Check the size:
primary.get_size()
# Open the file for writing:
file = open( filename, 'wb' )
file = open(filepath, 'wb')
# Recursively write the chunks to file:
primary.write(file)
@ -1098,56 +1029,15 @@ def write(filename, context):
# Close the file:
file.close()
# Clear name mapping vars, could make locals too
name_unique[:] = []
name_mapping.clear()
# Debugging only: report the exporting time:
# Blender.Window.WaitCursor(0)
print("3ds export time: %.2f" % (time.clock() - time1))
# print("3ds export time: %.2f" % (Blender.sys.time() - time1))
# Debugging only: dump the chunk hierarchy:
#primary.dump()
# # 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()
return {'FINISHED'}

@ -18,130 +18,14 @@
# <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
#
# 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
# Contributors: Bob Holcomb, Richard L?rk?ng, Damien McGinnes, Campbell Barton, Mario Lapin
import os
import time
import struct
from import_scene_obj import load_image
from io_utils import load_image
import bpy
import mathutils
@ -158,9 +42,9 @@ BOUNDS_3DS = []
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
EDITKEYFRAME= int('0xB000',16); #This is the header for all of the key frame info
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
EDITKEYFRAME= 0xB000 #This is the header for all of the key frame info
#------ sub defines of OBJECTINFO
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_BLOCK
MAT_NAME = int('0xA000',16) # This holds the material name
MAT_AMBIENT = int('0xA010',16) # Ambient color of the object/material
MAT_DIFFUSE = int('0xA020',16) # This holds the color of the object/material
MAT_SPECULAR = int('0xA030',16) # SPecular color of the object/material
MAT_SHINESS = int('0xA040',16) # ??
MAT_TRANSPARENCY= int('0xA050',16) # Transparency value of material
MAT_SELF_ILLUM = int('0xA080',16) # Self Illumination value of material
MAT_WIRE = int('0xA085',16) # Only render's wireframe
MAT_NAME = 0xA000 # This holds the material name
MAT_AMBIENT = 0xA010 # Ambient color of the object/material
MAT_DIFFUSE = 0xA020 # This holds the color of the object/material
MAT_SPECULAR = 0xA030 # SPecular color of the object/material
MAT_SHINESS = 0xA040 # ??
MAT_TRANSPARENCY= 0xA050 # Transparency value of material
MAT_SELF_ILLUM = 0xA080 # Self Illumination value of material
MAT_WIRE = 0xA085 # Only render's wireframe
MAT_TEXTURE_MAP = int('0xA200',16) # 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_OPACITY_MAP = int('0xA210',16) # 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_BUMP_MAP = int('0xA230',16) # This is a header for a new bump map
MAT_MAP_FILENAME = int('0xA300',16) # This holds the file name of the texture
MAT_TEXTURE_MAP = 0xA200 # This is a header for a new texture map
MAT_SPECULAR_MAP= 0xA204 # This is a header for a new specular map
MAT_OPACITY_MAP = 0xA210 # This is a header for a new opacity map
MAT_REFLECTION_MAP= 0xA220 # This is a header for a new reflection map
MAT_BUMP_MAP = 0xA230 # This is a header for a new bump map
MAT_MAP_FILEPATH = 0xA300 # This holds the file name of the texture
MAT_FLOAT_COLOR = int ('0x0010', 16) #color defined as 3 floats
MAT_24BIT_COLOR = int ('0x0011', 16) #color defined as 3 bytes
MAT_FLOAT_COLOR = 0x0010 #color defined as 3 floats
MAT_24BIT_COLOR = 0x0011 #color defined as 3 bytes
#>------ sub defines of OBJECT
OBJECT_MESH = int('0x4100',16); # 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_SPOT = int('0x4610',16); # The light is a spotloght.
OBJECT_LAMP_OFF = int('0x4620',16); # The light off.
OBJECT_LAMP_ATTENUATE = int('0x4625',16);
OBJECT_LAMP_RAYSHADE = int('0x4627',16);
OBJECT_LAMP_SHADOWED = int('0x4630',16);
OBJECT_LAMP_LOCAL_SHADOW = int('0x4640',16);
OBJECT_LAMP_LOCAL_SHADOW2 = int('0x4641',16);
OBJECT_LAMP_SEE_CONE = int('0x4650',16);
OBJECT_LAMP_SPOT_RECTANGULAR = int('0x4651',16);
OBJECT_LAMP_SPOT_OVERSHOOT = int('0x4652',16);
OBJECT_LAMP_SPOT_PROJECTOR = int('0x4653',16);
OBJECT_LAMP_EXCLUDE = int('0x4654',16);
OBJECT_LAMP_RANGE = int('0x4655',16);
OBJECT_LAMP_ROLL = int('0x4656',16);
OBJECT_LAMP_SPOT_ASPECT = int('0x4657',16);
OBJECT_LAMP_RAY_BIAS = int('0x4658',16);
OBJECT_LAMP_INNER_RANGE = int('0x4659',16);
OBJECT_LAMP_OUTER_RANGE = int('0x465A',16);
OBJECT_LAMP_MULTIPLIER = int('0x465B',16);
OBJECT_LAMP_AMBIENT_LIGHT = int('0x4680',16);
OBJECT_MESH = 0x4100 # This lets us know that we are reading a new object
OBJECT_LAMP = 0x4600 # This lets un know we are reading a light object
OBJECT_LAMP_SPOT = 0x4610 # The light is a spotloght.
OBJECT_LAMP_OFF = 0x4620 # The light off.
OBJECT_LAMP_ATTENUATE = 0x4625
OBJECT_LAMP_RAYSHADE = 0x4627
OBJECT_LAMP_SHADOWED = 0x4630
OBJECT_LAMP_LOCAL_SHADOW = 0x4640
OBJECT_LAMP_LOCAL_SHADOW2 = 0x4641
OBJECT_LAMP_SEE_CONE = 0x4650
OBJECT_LAMP_SPOT_RECTANGULAR = 0x4651
OBJECT_LAMP_SPOT_OVERSHOOT = 0x4652
OBJECT_LAMP_SPOT_PROJECTOR = 0x4653
OBJECT_LAMP_EXCLUDE = 0x4654
OBJECT_LAMP_RANGE = 0x4655
OBJECT_LAMP_ROLL = 0x4656
OBJECT_LAMP_SPOT_ASPECT = 0x4657
OBJECT_LAMP_RAY_BIAS = 0x4658
OBJECT_LAMP_INNER_RANGE = 0x4659
OBJECT_LAMP_OUTER_RANGE = 0x465A
OBJECT_LAMP_MULTIPLIER = 0x465B
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
OBJECT_CAM_RANGES= int('0x4720',16); # The camera range values
OBJECT_CAM_RANGES= 0x4720 # 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
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
global scn
scn = None
@ -266,12 +150,10 @@ def read_string(file):
s += struct.unpack('<c', file.read(1))[0]
#print 'string: ',s
#remove the null character from the string
s = str(s[:-1], 'ASCII')
# print("read string", s)
#remove the null character from the string
return s
# return s[:-1]
######################################################
# IMPORT
@ -300,9 +182,20 @@ def add_texture_to_material(image, texture, material, mapto):
if image:
texture.image = image
# if image: texture.setImage(image) # double check its an 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):
@ -337,7 +230,8 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
bmesh = bpy.data.meshes.new(contextObName)
if myContextMesh_vertls:
bmesh.add_geometry(len(myContextMesh_vertls)//3, 0, len(myContextMesh_facels))
bmesh.vertices.add(len(myContextMesh_vertls)//3)
bmesh.faces.add(len(myContextMesh_facels))
bmesh.vertices.foreach_set("co", myContextMesh_vertls)
eekadoodle_faces = []
@ -346,19 +240,20 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
bmesh.faces.foreach_set("vertices_raw", eekadoodle_faces)
if bmesh.faces and contextMeshUV:
bmesh.add_uv_texture()
uv_faces = bmesh.active_uv_texture.data[:]
bmesh.uv_textures.new()
uv_faces = bmesh.uv_textures.active.data[:]
else:
uv_faces = None
for mat_idx, (matName, faces) in enumerate(myContextMeshMaterials.items()):
if matName is None:
bmesh.add_material(None)
bmat = None
else:
bmat = MATDICT[matName][1]
bmesh.add_material(bmat) # can be None
img = TEXTURE_DICT.get(bmat.name)
bmesh.materials.append(bmat) # can be None
if uv_faces and img:
for fidx in faces:
bmesh.faces[fidx].material_index = mat_idx
@ -414,16 +309,14 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
return [float(col)/255 for col in struct.unpack('<3B', temp_data)] # data [0,1,2] == rgb
def read_texture(new_chunk, temp_chunk, name, mapto):
new_texture = bpy.data.textures.new(name)
new_texture.type = 'IMAGE'
new_texture = new_texture.recast_type()
new_texture = bpy.data.textures.new(name, type='IMAGE')
img = None
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)
if (temp_chunk.ID == MAT_MAP_FILENAME):
if (temp_chunk.ID == MAT_MAP_FILEPATH):
texture_name = read_string(file)
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
@ -437,7 +330,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
if img:
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
while (previous_chunk.bytes_read < previous_chunk.length):
@ -723,14 +616,14 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
#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)
try:
TEXTURE_DICT[contextMaterial.name]
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]= 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
@ -753,30 +646,27 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
if CreateBlenderObject:
putContextMesh(contextMesh_vertls, contextMesh_facels, contextMeshMaterials)
def load_3ds(filename, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True, APPLY_MATRIX=False):
global FILENAME, SCN
# global FILENAME, SCN_OBJECTS
def load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True, APPLY_MATRIX=False):
global SCN
# XXX
# if BPyMessages.Error_NoFile(filename):
# if BPyMessages.Error_NoFile(filepath):
# return
print('\n\nImporting 3DS: "%s"' % (filename))
# print('\n\nImporting 3DS: "%s"' % (Blender.sys.expandpath(filename)))
print('\n\nImporting 3DS: %r' % (filepath))
time1 = time.clock()
# time1 = Blender.sys.time()
FILENAME = filename
current_chunk = chunk()
file = open(filename,'rb')
file = open(filepath, 'rb')
#here we go!
# print 'reading the first chunk'
read_chunk(file, current_chunk)
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()
return
@ -837,7 +727,7 @@ def load_3ds(filename, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True,
# Done DUMMYVERT
"""
if IMPORT_AS_INSTANCE:
name = filename.split('\\')[-1].split('/')[-1]
name = filepath.split('\\')[-1].split('/')[-1]
# Create a group for this import.
group_scn = Scene.New(name)
for ob in importedObjects:
@ -895,96 +785,10 @@ def load_3ds(filename, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True,
# Done constraining to bounds.
# Select all new objects.
print('finished importing: "%s" in %.4f sec.' % (filename, (time.clock()-time1)))
# print('finished importing: "%s" in %.4f sec.' % (filename, (Blender.sys.time()-time1)))
print('finished importing: %r in %.4f sec.' % (filepath, (time.clock()-time1)))
file.close()
DEBUG = False
# For testing compatibility
#load_3ds('/metavr/convert/vehicle/truck_002/TruckTanker1.3DS', False)
#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()
def load(operator, context, filepath="", constrain_size=0.0, use_image_search=True, use_apply_transform=True):
load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=constrain_size, IMAGE_SEARCH=use_image_search, APPLY_MATRIX=use_apply_transform)
return {'FINISHED'}

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

@ -18,36 +18,13 @@
# <pep8 compliant>
__author__ = "Campbell Barton"
__url__ = ['www.blender.org', 'blenderartists.org']
__version__ = "1.2"
# Script copyright (C) Campbell Barton
__bpydoc__ = """\
"""
This script is an exporter to the FBX file format.
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 time
@ -57,19 +34,10 @@ import shutil # for file copying
import bpy
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
def copy_images(dest_dir, textures):
import shutil
if not dest_dir.endswith(os.sep):
dest_dir += os.sep
@ -84,12 +52,12 @@ def copy_images(dest_dir, textures):
# Make a name for the target path.
dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1]
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:
copy_file(image_path, dest_image_path)
shutil.copy(image_path, dest_image_path)
copyCount+=1
except:
print('\t\tWarning, file failed to copy, skipping.')
print("\t\tWarning, file failed to copy, skipping.")
print('\tCopied %d images' % copyCount)
@ -104,27 +72,11 @@ def eulerRadToDeg(eul):
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):
# 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_mat = {}
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
# 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.
# '''
# fname = bpy.path.abspath(fname_orig)
@ -282,19 +234,17 @@ header_comment = \
'''
# This func can be called with just the filename
def write(filename, batch_objects = None, \
context = None,
# This func can be called with just the filepath
def save(operator, context, filepath="", \
EXP_OBS_SELECTED = True,
EXP_MESH = True,
EXP_MESH_APPLY_MOD = True,
# EXP_MESH_HQ_NORMALS = False,
EXP_ARMATURE = True,
EXP_LAMP = True,
EXP_CAMERA = True,
EXP_EMPTY = True,
EXP_IMAGE_COPY = False,
GLOBAL_MATRIX = Matrix(),
GLOBAL_MATRIX = None,
ANIM_ENABLE = True,
ANIM_OPTIMIZE = True,
ANIM_OPTIMIZE_PRECISSION = 6,
@ -305,16 +255,26 @@ def write(filename, batch_objects = None, \
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')
# ----------------- Batch support!
if BATCH_ENABLE:
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 = Blender.sys.exists(fbxpath)
@ -323,7 +283,7 @@ def write(filename, batch_objects = None, \
# while fbxpath and fbxpath[-1] not in ('/', '\\'):
# fbxpath = fbxpath[:-1]
if not fbxpath:
# if not filename:
# if not filepath:
# XXX
print('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)
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)
if BATCH_GROUP: #group
@ -393,12 +353,11 @@ def write(filename, batch_objects = None, \
# Call self with modified args
# Dont pass batch options since we already usedt them
write(filename, data.objects,
write(filepath, data.objects,
context,
False,
EXP_MESH,
EXP_MESH_APPLY_MOD,
# EXP_MESH_HQ_NORMALS,
EXP_ARMATURE,
EXP_LAMP,
EXP_CAMERA,
@ -423,9 +382,9 @@ def write(filename, batch_objects = None, \
# end batch support
# 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 = Blender.sys.dirname(filename)
# basepath = Blender.sys.dirname(filepath)
# ----------------------------------------------
# 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 = Blender.sys.time()
try:
file = open(filename, 'w')
file = open(filepath, 'w')
except:
return False
@ -1630,7 +1589,7 @@ def write(filename, batch_objects = None, \
# if me.vertexColors:
collayers = me.vertex_colors
# collayers = me.getColorLayerNames()
collayer_orig = me.active_vertex_color
collayer_orig = me.vertex_colors.active
# collayer_orig = me.activeColorLayer
for colindex, collayer in enumerate(collayers):
# me.activeColorLayer = collayer
@ -1700,7 +1659,7 @@ def write(filename, batch_objects = None, \
if do_uvs:
uvlayers = me.uv_textures
# uvlayers = me.getUVLayerNames()
uvlayer_orig = me.active_uv_texture
uvlayer_orig = me.uv_textures.active
# uvlayer_orig = me.activeUVLayer
for uvindex, uvlayer in enumerate(me.uv_textures):
# for uvindex, uvlayer in enumerate(uvlayers):
@ -1834,8 +1793,8 @@ def write(filename, batch_objects = None, \
mats = my_mesh.blenMaterialList
if me.active_uv_texture:
uv_faces = me.active_uv_texture.data
if me.uv_textures.active:
uv_faces = me.uv_textures.active.data
else:
uv_faces = [None] * len(me.faces)
@ -2006,7 +1965,7 @@ def write(filename, batch_objects = None, \
ob_base.update(scene)
# 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'))
@ -2103,7 +2062,7 @@ def write(filename, batch_objects = None, \
material_mapping_local = {}
if len(me.uv_textures) > 0:
# if me.faceUV:
uvlayer_orig = me.active_uv_texture
uvlayer_orig = me.uv_textures.active
# uvlayer_orig = me.activeUVLayer
for uvlayer in me.uv_textures:
# for uvlayer in me.getUVLayerNames():
@ -2179,7 +2138,7 @@ def write(filename, batch_objects = None, \
if ob_base.type == 'ARMATURE':
ob_base.update(scene)
# 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'))
del tmp_ob_type, tmp_objects
@ -2472,7 +2431,7 @@ Objects: {''')
file.write('\n\t\tPoseNode: {')
file.write('\n\t\t\tNode: "Model::%s"' % fbxName )
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}')
@ -2760,7 +2719,9 @@ Takes: {''')
else:
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()
# if tmp:
# act_start = min(tmp)
@ -2797,7 +2758,7 @@ Takes: {''')
'''
i = act_start
while i <= act_end:
scene.set_frame(i)
scene.frame_set(i)
# Blender.Set('curframe', i)
for ob_generic in ob_anim_lists:
for my_ob in ob_generic:
@ -2937,8 +2898,7 @@ Takes: {''')
file.write('\n}')
scene.set_frame(frame_orig)
# Blender.Set('curframe', frame_orig)
scene.frame_set(frame_orig)
else:
# no animation
@ -2961,18 +2921,16 @@ Takes: {''')
# --------------------------- Footer
if world:
m = world.mist
m = world.mist_settings
has_mist = m.use_mist
mist_intense = m.intensity
mist_start = m.start
mist_end = m.depth
mist_height = m.height
# mist_intense, mist_start, mist_end, mist_height = world.mist
world_hor = world.horizon_color
# world_hor = world.hor
else:
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;------------------------------------------------------------------')
@ -3024,394 +2982,7 @@ Takes: {''')
# 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.' % (Blender.sys.time() - start_time)
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")
return {'FINISHED'}
# 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?
# - new scene creation, activation: lines 327-342, 368
# - 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()

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

@ -18,23 +18,6 @@
# <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 time
import shutil
@ -122,7 +105,7 @@ def write_mtl(scene, filepath, copy_images, mtl_dict):
try:
filepath = copy_image(mtex.texture.image)
# 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
except:
# Texture has no image though its an image type, best ignore.
@ -184,50 +167,48 @@ def copy_images(dest_dir):
# paths= bpy.util.copy_images(uniqueImages.values(), dest_dir)
print('\tCopied %d images' % copyCount)
# print('\tCopied %d images' % copyCount)
# XXX not converted
def test_nurbs_compat(ob):
if ob.type != 'Curve':
if ob.type != 'CURVE':
return False
for nu in ob.data:
if (not nu.knotsV) and nu.type != 1: # not a surface and not bezier
for nu in ob.data.splines:
if nu.point_count_v == 1 and nu.type != 'BEZIER': # not a surface and not bezier
return True
return False
# XXX not converted
def write_nurb(file, ob, ob_mat):
tot_verts = 0
cu = ob.data
# use negative indices
Vector = Blender.mathutils.Vector
for nu in cu:
for nu in cu.splines:
if nu.type == 'POLY':
DEG_ORDER_U = 1
else:
DEG_ORDER_U = nu.order_u - 1 # odd but tested to be correct
if nu.type==0: DEG_ORDER_U = 1
else: DEG_ORDER_U = nu.orderU-1 # Tested to be correct
if nu.type==1:
if nu.type == 'BEZIER':
print("\tWarning, bezier curve:", ob.name, "only poly and nurbs curves supported")
continue
if nu.knotsV:
if nu.point_count_v > 1:
print("\tWarning, surface:", ob.name, "only poly and nurbs curves supported")
continue
if len(nu) <= DEG_ORDER_U:
print("\tWarning, orderU is lower then vert count, skipping:", ob.name)
if len(nu.points) <= DEG_ORDER_U:
print("\tWarning, order_u is lower then vert count, skipping:", ob.name)
continue
pt_num = 0
do_closed = (nu.flagU & 1)
do_endpoints = (do_closed==0) and (nu.flagU & 2)
do_closed = nu.use_cyclic_u
do_endpoints = (do_closed == 0) and nu.use_endpoint_u
for pt in nu:
pt = Vector(pt[0], pt[1], pt[2]) * ob_mat
for pt in nu.points:
pt = ob_mat * pt.co.copy().resize3D()
file.write('v %.6f %.6f %.6f\n' % (pt[0], pt[1], pt[2]))
pt_num += 1
tot_verts += pt_num
@ -247,7 +228,7 @@ def write_nurb(file, ob, ob_mat):
pt_num += DEG_ORDER_U
curve_ls = curve_ls + curve_ls[0:DEG_ORDER_U]
file.write('curv 0.0 1.0 %s\n' % (' '.join( [str(i) for i in curve_ls] ))) # Blender has no U and V values for the curve
file.write('curv 0.0 1.0 %s\n' % (' '.join([str(i) for i in curve_ls]))) # Blender has no U and V values for the curve
# 'parm' keyword
tot_parm = (DEG_ORDER_U + 1) + pt_num
@ -334,7 +315,7 @@ def write_file(filepath, objects, scene,
return ret
print('OBJ Export path: "%s"' % filepath)
print('OBJ Export path: %r' % filepath)
temp_mesh_name = '~tmp-mesh'
time1 = time.clock()
@ -344,13 +325,13 @@ def write_file(filepath, objects, scene,
file = open(filepath, "w")
# 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')
# Tell the obj file what material file to use.
if EXPORT_MTL:
mtlfilepath = '%s.mtl' % '.'.join(filepath.split('.')[:-1])
file.write('mtllib %s\n' % ( mtlfilepath.split('\\')[-1].split('/')[-1] ))
mtlfilepath = os.path.splitext(filepath)[0] + ".mtl"
file.write('mtllib %s\n' % repr(os.path.basename(mtlfilepath))[1:-1]) # filepath can contain non utf8 chars, use repr
if EXPORT_ROTX90:
mat_xrot90= mathutils.Matrix.Rotation(-math.pi/2, 4, 'X')
@ -390,16 +371,13 @@ def write_file(filepath, objects, scene,
for ob, ob_mat in obs:
# XXX postponed
# # Nurbs curve support
# if EXPORT_CURVE_AS_NURBS and test_nurbs_compat(ob):
# if EXPORT_ROTX90:
# ob_mat = ob_mat * mat_xrot90
# totverts += write_nurb(file, ob, ob_mat)
# continue
# end nurbs
# Nurbs curve support
if EXPORT_CURVE_AS_NURBS and test_nurbs_compat(ob):
if EXPORT_ROTX90:
ob_mat = ob_mat * mat_xrot90
totverts += write_nurb(file, ob, ob_mat)
continue
# END NURBS
if ob.type != 'MESH':
continue
@ -418,7 +396,8 @@ def write_file(filepath, objects, scene,
if EXPORT_UV:
faceuv = len(me.uv_textures) > 0
uv_layer = me.active_uv_texture.data[:]
if faceuv:
uv_layer = me.uv_textures.active.data[:]
else:
faceuv = False
@ -542,7 +521,7 @@ def write_file(filepath, objects, scene,
uv_face_mapping = [[0,0,0,0] for i in range(len(face_index_pairs))] # a bit of a waste for tri's :/
uv_dict = {} # could use a set() here
uv_layer = me.active_uv_texture.data
uv_layer = me.uv_textures.active.data
for f, f_index in face_index_pairs:
for uv_index, uv in enumerate(uv_layer[f_index].uv):
uvkey = veckey2d(uv)
@ -755,7 +734,8 @@ def write_file(filepath, objects, scene,
print("OBJ Export time: %.2f" % (time.clock() - time1))
def write(filepath, context,
#
def _write(context, filepath,
EXPORT_TRI, # ok
EXPORT_EDGES,
EXPORT_NORMALS, # not yet
@ -781,7 +761,7 @@ def write(filepath, context,
orig_scene = context.scene
# 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')
# if EXPORT_ALL_SCENES:
@ -852,105 +832,51 @@ def write(filepath, context,
'''
Currently the exporter lacks these features:
* nurbs
* multiple scene export (only active scene is written)
* particles
'''
from bpy.props import *
class ExportOBJ(bpy.types.Operator):
'''Save a Wavefront OBJ File'''
def save(operator, context, filepath="",
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"
bl_label = 'Export OBJ'
_write(context, filepath,
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
# 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()
return {'FINISHED'}

@ -18,85 +18,26 @@
# <pep8 compliant>
__author__= "Campbell Barton", "Jiri Hnidek", "Paolo Ciccone"
__url__= ['http://wiki.blender.org/index.php/Scripts/Manual/Import/wavefront_obj', 'blender.org', 'blenderartists.org']
__version__= "2.11"
# Script copyright (C) Campbell Barton
# Contributors: Campbell Barton, Jiri Hnidek, Paolo Ciccone
__bpydoc__= """\
"""
This script imports a Wavefront OBJ files to Blender.
Usage:
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.
"""
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Campbell J Barton 2007
#
# 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 *****
# --------------------------------------------------------------------------
http://wiki.blender.org/index.php/Scripts/Manual/Import/wavefront_obj
"""
import os
import time
import bpy
import mathutils
from geometry import PolyFill
from io_utils import load_image, unpack_list, unpack_face_list
# from Blender import Mesh, Draw, Window, Texture, Material, sys
# # import BPyMesh
# import BPyImage
# import BPyMessages
# try: import os
# except: os= False
def stripExt(name): # name is a string
'''Strips the prefix off the name before writing'''
index= name.rfind('.')
if index != -1:
return name[ : index ]
else:
return name
# end path funcs
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):
'''
@ -116,7 +57,7 @@ def BPyMesh_ngon(from_data, indices, PREF_FIX_LOOPS= True):
if not indices:
return []
# return []
# return []
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
@ -297,21 +238,6 @@ def line_value(line_split):
elif length > 2:
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):
if '_' in imagepath:
@ -327,21 +253,21 @@ def obj_image_load(imagepath, DIR, IMAGE_SEARCH):
return None
# def obj_image_load(imagepath, DIR, IMAGE_SEARCH):
# '''
# Mainly uses comprehensiveImageLoad
# but tries to replace '_' with ' ' for Max's exporter replaces spaces with underscores.
# '''
# '''
# Mainly uses comprehensiveImageLoad
# but tries to replace '_' with ' ' for Max's exporter replaces spaces with underscores.
# '''
# if '_' in imagepath:
# image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH)
# if image: return image
# # Did the exporter rename the image?
# image= BPyImage.comprehensiveImageLoad(imagepath.replace('_', ' '), DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH)
# if image: return image
# if '_' in imagepath:
# image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH)
# if image: return image
# # Did the exporter rename the image?
# image= BPyImage.comprehensiveImageLoad(imagepath.replace('_', ' '), DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH)
# if image: return image
# # Return an image, placeholder if it dosnt exist
# image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= True, RECURSIVE= IMAGE_SEARCH)
# return image
# # Return an image, placeholder if it dosnt exist
# image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= True, RECURSIVE= IMAGE_SEARCH)
# return image
def create_materials(filepath, material_libs, unique_materials, unique_material_images, IMAGE_SEARCH):
@ -356,18 +282,15 @@ def create_materials(filepath, material_libs, unique_materials, unique_material_
#==================================================================================#
def load_material_image(blender_material, context_material_name, imagepath, type):
texture= bpy.data.textures.new(type)
texture.type= 'IMAGE'
texture = texture.recast_type() # Workaround for limitation in rna api.
# texture= bpy.data.textures.new(type)
# texture.setType('Image')
texture= bpy.data.textures.new(name=type, type='IMAGE')
# Absolute path - c:\.. etc would work here
image= obj_image_load(imagepath, DIR, IMAGE_SEARCH)
has_data = image.has_data if image else False
image = obj_image_load(imagepath, DIR, IMAGE_SEARCH)
has_data = False
if image:
texture.image = image
has_data = image.has_data
# Adds textures for materials (rendering)
if type == 'Kd':
@ -375,42 +298,65 @@ def create_materials(filepath, material_libs, unique_materials, unique_material_
# Image has alpha
# 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.interpolation = True
texture.use_alpha = True
blender_material.use_transparency = True
blender_material.alpha = 0.0
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)
# 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
elif type == 'Ka':
blender_material.add_texture(texture, 'UV', 'AMBIENT')
# blender_material.setTexture(1, texture, Texture.TexCo.UV, Texture.MapTo.CMIR) # TODO- Add AMB to BPY API
mtex = blender_material.texture_slots.add()
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':
blender_material.add_texture(texture, 'UV', 'SPECULARITY')
# blender_material.setTexture(2, texture, Texture.TexCo.UV, Texture.MapTo.SPEC)
mtex = blender_material.texture_slots.add()
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':
blender_material.add_texture(texture, 'UV', 'NORMAL')
# blender_material.setTexture(3, texture, Texture.TexCo.UV, Texture.MapTo.NOR)
mtex = blender_material.texture_slots.add()
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':
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.alpha = 0.0
# blender_material.setTexture(4, texture, Texture.TexCo.UV, Texture.MapTo.ALPHA)
# blender_material.mode |= Material.Modes.ZTRANSP
# blender_material.alpha = 0.0
# blender_material.setTexture(4, texture, Texture.TexCo.UV, Texture.MapTo.ALPHA)
# blender_material.mode |= Material.Modes.ZTRANSP
# blender_material.alpha = 0.0
# Todo, unset deffuse material alpha if it has an alpha channel
elif type == 'refl':
blender_material.add_texture(texture, 'UV', 'REFLECTION')
# blender_material.setTexture(5, texture, Texture.TexCo.UV, Texture.MapTo.REF)
mtex = blender_material.texture_slots.add()
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.
@ -451,22 +397,16 @@ def create_materials(filepath, material_libs, unique_materials, unique_material_
line_lower= line.lower().lstrip()
if line_lower.startswith('ka'):
context_material.mirror_color = (float(line_split[1]), float(line_split[2]), float(line_split[3]))
# context_material.setMirCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
elif line_lower.startswith('kd'):
context_material.diffuse_color = (float(line_split[1]), float(line_split[2]), float(line_split[3]))
# context_material.setRGBCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
elif line_lower.startswith('ks'):
context_material.specular_color = (float(line_split[1]), float(line_split[2]), float(line_split[3]))
# context_material.setSpecCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
elif line_lower.startswith('ns'):
context_material.specular_hardness = int((float(line_split[1])*0.51))
# context_material.setHardness( int((float(line_split[1])*0.51)) )
elif line_lower.startswith('ni'): # Refraction index
context_material.raytrace_transparency.ior = max(1, min(float(line_split[1]), 3))
# context_material.setIOR( max(1, min(float(line_split[1]), 3))) # Between 1 and 3
context_material.raytrace_transparency.ior = max(1, min(float(line_split[1]), 3)) # Between 1 and 3
elif line_lower.startswith('d') or line_lower.startswith('tr'):
context_material.alpha = float(line_split[1])
# context_material.setAlpha(float(line_split[1]))
elif line_lower.startswith('map_ka'):
img_filepath= line_value(line.split())
if img_filepath:
@ -624,14 +564,14 @@ def create_mesh(new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, v
if has_ngons and len_face_vert_loc_indicies > 4:
ngon_face_indices= BPyMesh_ngon(verts_loc, face_vert_loc_indicies)
faces.extend(\
[(\
[face_vert_loc_indicies[ngon[0]], face_vert_loc_indicies[ngon[1]], face_vert_loc_indicies[ngon[2]] ],\
[face_vert_tex_indicies[ngon[0]], face_vert_tex_indicies[ngon[1]], face_vert_tex_indicies[ngon[2]] ],\
context_material,\
context_smooth_group,\
context_object)\
for ngon in ngon_face_indices]\
faces.extend(
[(
[face_vert_loc_indicies[ngon[0]], face_vert_loc_indicies[ngon[1]], face_vert_loc_indicies[ngon[2]] ],
[face_vert_tex_indicies[ngon[0]], face_vert_tex_indicies[ngon[1]], face_vert_tex_indicies[ngon[2]] ],
context_material,
context_smooth_group,
context_object)
for ngon in ngon_face_indices]
)
# edges to make fgons
@ -676,30 +616,25 @@ def create_mesh(new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, v
# make sure the list isnt too big
for material in materials:
me.add_material(material)
#me.vertices.extend([(0,0,0)]) # dummy vert
me.materials.append(material)
me.add_geometry(len(verts_loc), 0, len(faces))
me.vertices.add(len(verts_loc))
me.faces.add(len(faces))
# verts_loc is a list of (x, y, z) tuples
me.vertices.foreach_set("co", unpack_list(verts_loc))
# me.vertices.extend(verts_loc)
# faces is a list of (vert_indices, texco_indices, ...) tuples
# XXX faces should contain either 3 or 4 verts
# XXX no check for valid face indices
me.faces.foreach_set("vertices_raw", unpack_face_list([f[0] for f in faces]))
# face_mapping= me.faces.extend([f[0] for f in faces], indexList=True)
if verts_tex and me.faces:
me.add_uv_texture()
# me.faceUV= 1
# TEXMODE= Mesh.FaceModes['TEX']
me.uv_textures.new()
context_material_old= -1 # avoid a dict lookup
mat= 0 # rare case it may be un-initialized.
me_faces= me.faces
# ALPHA= Mesh.FaceTranspModes.ALPHA
for i, face in enumerate(faces):
if len(face[0]) < 2:
@ -708,14 +643,8 @@ def create_mesh(new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, v
if CREATE_EDGES:
edges.append(face[0])
else:
# face_index_map= face_mapping[i]
# since we use foreach_set to add faces, all of them are added
if 1:
# if face_index_map!=None: # None means the face wasnt added
blender_face = me.faces[i]
# blender_face= me_faces[face_index_map]
face_vert_loc_indicies,\
face_vert_tex_indicies,\
@ -734,7 +663,7 @@ def create_mesh(new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, v
context_material_old= context_material
blender_face.material_index= mat
# blender_face.mat= mat
# blender_face.mat= mat
if verts_tex:
@ -766,57 +695,57 @@ def create_mesh(new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, v
if len(face_vert_loc_indicies)==4:
blender_tface.uv4= verts_tex[face_vert_tex_indicies[3]]
# for ii, uv in enumerate(blender_face.uv):
# uv.x, uv.y= verts_tex[face_vert_tex_indicies[ii]]
# for ii, uv in enumerate(blender_face.uv):
# uv.x, uv.y= verts_tex[face_vert_tex_indicies[ii]]
del me_faces
# del ALPHA
# del ALPHA
if CREATE_EDGES:
me.add_geometry(0, len(edges), 0)
me.edges.add(len(edges))
# edges should be a list of (a, b) tuples
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.
# me_edges= me.edges
# me_edges= me.edges
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])
# XXX slow
# if CREATE_FGONS and fgon_edges:
# for fgon_edge in fgon_edges.keys():
# for ed in me.edges:
# if edges_match(fgon_edge, ed.vertices):
# ed.is_fgon = True
# if CREATE_FGONS and fgon_edges:
# for fgon_edge in fgon_edges.keys():
# for ed in me.edges:
# if edges_match(fgon_edge, ed.vertices):
# ed.is_fgon = True
# if CREATE_FGONS and fgon_edges:
# FGON= Mesh.EdgeFlags.FGON
# for ed in me.findEdges( fgon_edges.keys() ):
# if ed!=None:
# me_edges[ed].flag |= FGON
# del FGON
# if CREATE_FGONS and fgon_edges:
# FGON= Mesh.EdgeFlags.FGON
# for ed in me.findEdges( fgon_edges.keys() ):
# if ed!=None:
# me_edges[ed].flag |= FGON
# del FGON
# XXX slow
# if unique_smooth_groups and sharp_edges:
# for sharp_edge in sharp_edges.keys():
# for ed in me.edges:
# if edges_match(sharp_edge, ed.vertices):
# ed.use_edge_sharp = True
# if unique_smooth_groups and sharp_edges:
# for sharp_edge in sharp_edges.keys():
# for ed in me.edges:
# if edges_match(sharp_edge, ed.vertices):
# ed.use_edge_sharp = True
# if unique_smooth_groups and sharp_edges:
# SHARP= Mesh.EdgeFlags.SHARP
# for ed in me.findEdges( sharp_edges.keys() ):
# if ed!=None:
# me_edges[ed].flag |= SHARP
# del SHARP
# if unique_smooth_groups and sharp_edges:
# SHARP= Mesh.EdgeFlags.SHARP
# for ed in me.findEdges( sharp_edges.keys() ):
# if ed!=None:
# me_edges[ed].flag |= SHARP
# del SHARP
me.update()
# me.calcNormals()
# me.calcNormals()
ob= bpy.data.objects.new("Mesh", me)
new_objects.append(ob)
@ -825,11 +754,8 @@ def create_mesh(new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, v
# content of the vertex_groups. If the user selects to NOT have vertex groups saved then
# the following test will never run
for group_name, group_indicies in vertex_groups.items():
group= ob.add_vertex_group(group_name)
# me.addVertGroup(group_name)
for vertex_index in group_indicies:
ob.add_vertex_to_group(vertex_index, group, 1.0, 'REPLACE')
# me.assignVertsToGroup(group_name, group_indicies, 1.00, Mesh.AssignModes.REPLACE)
group= ob.vertex_groups.new(group_name)
ob.vertex_groups.assign(group_indicies, group, 1.0, 'REPLACE')
def create_nurbs(context_nurbs, vert_loc, new_objects):
@ -857,21 +783,14 @@ def create_nurbs(context_nurbs, vert_loc, new_objects):
print('\tWarning, surfaces not supported')
return
cu = bpy.data.curves.new(name, 'Curve')
cu.flag |= 1 # 3D curve
cu = bpy.data.curves.new(name, 'CURVE')
cu.dimensions = '3D'
nu = None
for pt in curv_idx:
nu = cu.splines.new('NURBS')
nu.points.add(len(curv_idx) - 1) # a point is added to start with
nu.points.foreach_set("co", [co_axis for vt_idx in curv_idx for co_axis in (vert_loc[vt_idx] + (1.0,))])
pt = vert_loc[pt]
pt = (pt[0], pt[1], pt[2], 1.0)
if nu == None:
nu = cu.appendNurb(pt)
else:
nu.append(pt)
nu.orderU = deg[0]+1
nu.order_u = deg[0] + 1
# get for endpoint flag from the weighting
if curv_range and len(parm_u) > deg[0]+1:
@ -890,7 +809,7 @@ def create_nurbs(context_nurbs, vert_loc, new_objects):
do_endpoints = False
if do_endpoints:
nu.flagU |= 2
nu.use_endpoint_u = True
# close
@ -905,10 +824,10 @@ def create_nurbs(context_nurbs, vert_loc, new_objects):
break
if do_closed:
nu.flagU |= 1
nu.use_cyclic_u = True
'''
ob= bpy.data.objects.new("Mesh", me)
ob= bpy.data.objects.new("Nurb", cu)
new_objects.append(ob)
@ -927,7 +846,7 @@ def strip_slash(line_split):
def get_float_func(filepath):
'''
find the float function for this obj file
- weather to replace commas or not
- whether to replace commas or not
'''
file= open(filepath, 'rU')
for line in file: #.xreadlines():
@ -941,31 +860,29 @@ def get_float_func(filepath):
# incase all vert values were ints
return float
def load_obj(filepath,
context,
CLAMP_SIZE= 0.0,
CREATE_FGONS= True,
CREATE_SMOOTH_GROUPS= True,
CREATE_EDGES= True,
SPLIT_OBJECTS= True,
SPLIT_GROUPS= True,
SPLIT_MATERIALS= True,
ROTATE_X90= True,
IMAGE_SEARCH=True,
POLYGROUPS=False):
def load(operator, context, filepath,
CLAMP_SIZE= 0.0,
CREATE_FGONS= True,
CREATE_SMOOTH_GROUPS= True,
CREATE_EDGES= True,
SPLIT_OBJECTS= True,
SPLIT_GROUPS= True,
ROTATE_X90= True,
IMAGE_SEARCH=True,
POLYGROUPS=False):
'''
Called by the user interface or another script.
load_obj(path) - should give acceptable results.
This function passes the file and sends the data off
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
time_main= time.time()
# time_main= sys.time()
# time_main= sys.time()
verts_loc= []
verts_tex= []
@ -999,12 +916,12 @@ def load_obj(filepath,
# when there are faces that end with \
# it means they are multiline-
# 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= ''
print('\tparsing obj file "%s"...' % filepath)
print("\tparsing obj file...")
time_sub= time.time()
# time_sub= sys.time()
# time_sub= sys.time()
file= open(filepath, 'rU')
for line in file: #.xreadlines():
@ -1055,7 +972,7 @@ def load_obj(filepath,
vert_loc_index= int(obj_vert[0])-1
# Add the vertex to the current group
# *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)
# Make relative negative vert indicies absolute
@ -1147,8 +1064,7 @@ def load_obj(filepath,
context_material= line_value(line.split())
unique_materials[context_material]= None
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
elif line.startswith('cstype '):
@ -1213,7 +1129,7 @@ def load_obj(filepath,
file.close()
time_new= time.time()
# time_new= sys.time()
# time_new= sys.time()
print('%.4f sec' % (time_new-time_sub))
time_sub= time_new
@ -1222,7 +1138,7 @@ def load_obj(filepath,
create_materials(filepath, material_libs, unique_materials, unique_material_images, IMAGE_SEARCH)
time_new= time.time()
# time_new= sys.time()
# time_new= sys.time()
print('%.4f sec' % (time_new-time_sub))
time_sub= time_new
@ -1230,29 +1146,29 @@ def load_obj(filepath,
verts_loc[:] = [(v[0], v[2], -v[1]) for v in verts_loc]
# deselect all
# if context.selected_objects:
# bpy.ops.OBJECT_OT_select_all()
bpy.ops.object.select_all(action='DESELECT')
scene = context.scene
# scn.objects.selected = []
# scn.objects.selected = []
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) ))
# Split the mesh by objects/materials, may
if SPLIT_OBJECTS or SPLIT_GROUPS: SPLIT_OB_OR_GROUP = True
else: SPLIT_OB_OR_GROUP = False
if SPLIT_OBJECTS or SPLIT_GROUPS: SPLIT_OB_OR_GROUP = True
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):
# Create meshes from the data, warning 'vertex_groups' wont support splitting
create_mesh(new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc_split, verts_tex, faces_split, unique_materials_split, unique_material_images, unique_smooth_groups, vertex_groups, dataname)
# nurbs support
# for context_nurbs in nurbs:
# create_nurbs(scn, context_nurbs, verts_loc, new_objects)
for context_nurbs in nurbs:
create_nurbs(context_nurbs, verts_loc, new_objects)
# Create new obj
for obj in new_objects:
scene.objects.link(obj)
base = scene.objects.link(obj)
base.select = True
scene.update()
@ -1260,340 +1176,45 @@ def load_obj(filepath,
axis_min= [ 1000000000]*3
axis_max= [-1000000000]*3
# if CLAMP_SIZE:
# # Get all object bounds
# for ob in new_objects:
# for v in ob.getBoundBox():
# for axis, value in enumerate(v):
# if axis_min[axis] > value: axis_min[axis]= value
# if axis_max[axis] < value: axis_max[axis]= value
# if CLAMP_SIZE:
# # Get all object bounds
# for ob in new_objects:
# for v in ob.getBoundBox():
# for axis, value in enumerate(v):
# if axis_min[axis] > value: axis_min[axis]= value
# if axis_max[axis] < value: axis_max[axis]= value
# # Scale objects
# 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 objects
# max_axis= max(axis_max[0]-axis_min[0], axis_max[1]-axis_min[1], axis_max[2]-axis_min[2])
# scale= 1.0
# while CLAMP_SIZE < max_axis * scale:
# scale= scale/10.0
# while CLAMP_SIZE < max_axis * scale:
# scale= scale/10.0
# for ob in new_objects:
# ob.setSize(scale, scale, scale)
# for ob in new_objects:
# ob.setSize(scale, scale, scale)
# Better rotate the vert locations
#if not ROTATE_X90:
# for ob in new_objects:
# ob.RotX = -1.570796326794896558
# for ob in new_objects:
# ob.RotX = -1.570796326794896558
time_new= time.time()
# time_new= sys.time()
# time_new= sys.time()
print('%.4f sec' % (time_new-time_sub))
print('finished importing: "%s" in %.4f sec.' % (filepath, (time_new-time_main)))
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( stripExt(f) )
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)
print('finished importing: %r in %.4f sec.' % (filepath, (time_new-time_main)))
return {'FINISHED'}
# NOTES (all line numbers refer to 2.4x import_obj.py, not this file)
# check later: line 489
# can convert now: edge flags, edges: lines 508-528
# ngon (uses python module BPyMesh): 384-414
# nurbs: 947-
# NEXT clamp size: get bound box with RNA
# get back to l 140 (here)
# search image in bpy.config.textureDir - load_image
# replaced BPyImage.comprehensiveImageLoad with a simplified version that only checks additional directory specified, but doesn't search dirs recursively (obj_image_load)
# bitmask won't work? - 132
# uses operator bpy.ops.OBJECT_OT_select_all() to deselect all (not necessary?)
# uses bpy.sys.time()
if __name__ == "__main__":

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

@ -18,68 +18,29 @@
# <pep8 compliant>
__author__ = ("Bart", "Campbell Barton")
__email__ = ["Bart, bart:neeneenee*de"]
__url__ = ["Author's (Bart) homepage, http://www.neeneenee.de/vrml"]
__version__ = "2006/01/17"
__bpydoc__ = """\
# Contributors: bart:neeneenee*de, http://www.neeneenee.de/vrml, Campbell Barton
"""
This script exports to X3D format.
Usage:
Run this script from "File->Export" menu. A pop-up will ask whether you
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 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;
"""
# $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 os
import bpy
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
MATWORLD= mathutils.Matrix.Rotation(-90, 4, 'X')
@ -87,8 +48,7 @@ MATWORLD= mathutils.Matrix.Rotation(-90, 4, 'X')
# Global Variables
####################################
filename = ""
# filename = Blender.Get('filename')
filepath = ""
_safeOverwrite = True
extension = ''
@ -99,7 +59,7 @@ extension = ''
class x3d_class:
def __init__(self, filename):
def __init__(self, filepath):
#--- public you can change these ---
self.writingcolor = 0
self.writingtexture = 0
@ -122,18 +82,18 @@ class x3d_class:
self.matNames={} # dictionary of materiaNames
self.meshNames={} # dictionary of meshNames
self.indentLevel=0 # keeps track of current indenting
self.filename=filename
self.filepath=filepath
self.file = None
if filename.lower().endswith('.x3dz'):
if filepath.lower().endswith('.x3dz'):
try:
import gzip
self.file = gzip.open(filename, "w")
self.file = gzip.open(filepath, "w")
except:
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:
self.file = open(self.filename, "w")
self.file = open(self.filepath, "w")
self.bNav=0
self.nodeID=0
@ -175,15 +135,15 @@ class x3d_class:
##########################################################
def writeHeader(self):
#bfile = sys.expandpath( Blender.Get('filename') ).replace('<', '&lt').replace('>', '&gt')
bfile = self.filename.replace('<', '&lt').replace('>', '&gt') # use outfile name
#bfile = sys.expandpath( Blender.Get('filepath') ).replace('<', '&lt').replace('>', '&gt')
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("<!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("<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=\"generator\" content=\"Blender %s\" />\n" % '2.5')
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=\"translator\" content=\"X3D exporter v1.55 (2006/01/17)\" />\n")
self.file.write("</head>\n")
@ -258,12 +218,9 @@ class x3d_class:
def writeFog(self, world):
if world:
mtype = world.mist.falloff
# mtype = world.getMistype()
mparam = world.mist
# mparam = world.getMist()
mtype = world.mist_settings.falloff
mparam = world.mist_settings
grd = world.horizon_color
# grd = world.getHor()
grd0, grd1, grd2 = grd[0], grd[1], grd[2]
else:
return
@ -277,7 +234,7 @@ class x3d_class:
return
def writeNavigationInfo(self, scene):
self.file.write('<NavigationInfo headlight="FALSE" visibilityLimit="0.0" type=\'"EXAMINE","ANY"\' avatarSize="0.25, 1.75, 0.75" />\n')
self.file.write('<NavigationInfo headlight="false" visibilityLimit="0.0" type=\'"EXAMINE","ANY"\' avatarSize="0.25, 1.75, 0.75" />\n')
def writeSpotLight(self, ob, mtx, lamp, world):
safeName = self.cleanStr(ob.name)
@ -402,9 +359,9 @@ class x3d_class:
if len(mesh.faces) == 0: return
mode = []
# mode = 0
if mesh.active_uv_texture:
if mesh.uv_textures.active:
# if mesh.faceUV:
for face in mesh.active_uv_texture.data:
for face in mesh.uv_textures.active.data:
# for face in mesh.faces:
if face.use_halo and 'HALO' not in mode:
mode += ['HALO']
@ -460,40 +417,39 @@ class x3d_class:
self.writeIndented("<Shape>\n",1)
maters=mesh.materials
hasImageTexture=0
hasImageTexture = False
is_smooth = False
if len(maters) > 0 or mesh.active_uv_texture:
if len(maters) > 0 or mesh.uv_textures.active:
# if len(maters) > 0 or mesh.faceUV:
self.writeIndented("<Appearance>\n", 1)
# right now this script can only handle a single material per mesh.
if len(maters) >= 1:
mat=maters[0]
# matFlags = mat.getMode()
if not mat.use_face_texture:
# if not matFlags & Blender.Material.Modes['TEXFACE']:
self.writeMaterial(mat, self.cleanStr(mat.name,''), world)
# self.writeMaterial(mat, self.cleanStr(maters[0].name,''), world)
if len(maters) > 1:
print("Warning: mesh named %s has multiple materials" % meshName)
print("Warning: only one material per object handled")
if len(maters) >= 1 and maters[0].use_face_texture == False:
mat = maters[0]
self.writeMaterial(mat, self.cleanStr(mat.name,''), world)
if len(maters) > 1:
print("Warning: mesh named %s has multiple materials" % meshName)
print("Warning: only one material per object handled")
if not len(maters) or maters[0].use_face_texture:
#-- textures
face = None
if mesh.active_uv_texture:
# if mesh.faceUV:
for face in mesh.active_uv_texture.data:
# for face in mesh.faces:
if face.image:
# if (hasImageTexture == 0) and (face.image):
self.writeImageTexture(face.image)
# hasImageTexture=1 # keep track of face texture
break
if self.tilenode == 1 and face and face.image:
# if self.tilenode == 1:
self.writeIndented("<TextureTransform scale=\"%s %s\" />\n" % (face.image.xrep, face.image.yrep))
self.tilenode = 0
self.writeIndented("</Appearance>\n", -1)
image = None
if mesh.uv_textures.active:
for face in mesh.uv_textures.active.data:
if face.use_image:
image = face.image
if image:
self.writeImageTexture(image)
break
if image:
hasImageTexture = True
if self.tilenode == 1:
self.writeIndented("<TextureTransform scale=\"%s %s\" />\n" % (image.xrep, image.yrep))
self.tilenode = 0
self.writeIndented("</Appearance>\n", -1)
#-- IndexedFaceSet or IndexedLineSet
@ -525,11 +481,10 @@ class x3d_class:
self.file.write("creaseAngle=\"%s\" " % (round(creaseAngle,self.cp)))
#--- output textureCoordinates if UV texture used
if mesh.active_uv_texture:
# if mesh.faceUV:
if mesh.uv_textures.active:
if self.matonly == 1 and self.share == 1:
self.writeFaceColors(mesh)
elif hasImageTexture == 1:
elif hasImageTexture == True:
self.writeTextureCoordinates(mesh)
#--- output coordinates
self.writeCoordinates(ob, mesh, meshName, EXPORT_TRI)
@ -540,9 +495,9 @@ class x3d_class:
self.writeCoordinates(ob, mesh, meshName, EXPORT_TRI)
#--- output textureCoordinates if UV texture used
if mesh.active_uv_texture:
if mesh.uv_textures.active:
# if mesh.faceUV:
if hasImageTexture == 1:
if hasImageTexture == True:
self.writeTextureCoordinates(mesh)
elif self.matonly == 1 and self.share == 1:
self.writeFaceColors(mesh)
@ -614,7 +569,7 @@ class x3d_class:
texIndexList=[]
j=0
for face in mesh.active_uv_texture.data:
for face in mesh.uv_textures.active.data:
# for face in mesh.faces:
# workaround, since tface.uv iteration is wrong atm
uvs = face.uv
@ -646,10 +601,10 @@ class x3d_class:
def writeFaceColors(self, mesh):
if self.writingcolor == 0:
self.file.write("colorPerVertex=\"false\" ")
elif mesh.active_vertex_color:
elif mesh.vertex_colors.active:
# else:
self.writeIndented("<Color color=\"", 1)
for face in mesh.active_vertex_color.data:
for face in mesh.vertex_colors.active.data:
c = face.color1
if self.verbose > 2:
print("Debug: face.col r=%d g=%d b=%d" % (c[0], c[1], c[2]))
@ -717,21 +672,20 @@ class x3d_class:
def writeImageTexture(self, image):
name = image.name
filename = image.filepath.split('/')[-1].split('\\')[-1]
filepath = os.path.basename(image.filepath)
if name in self.texNames:
self.writeIndented("<ImageTexture USE=\"%s\" />\n" % self.cleanStr(name))
self.texNames[name] += 1
return
else:
self.writeIndented("<ImageTexture DEF=\"%s\" " % self.cleanStr(name), 1)
self.file.write("url=\"%s\" />" % name)
self.file.write("url=\"%s\" />" % filepath)
self.writeIndented("\n",-1)
self.texNames[name] = 1
def writeBackground(self, world, alltextures):
if world: worldname = world.name
else: return
blending = (world.blend_sky, world.paper_sky, world.use_sky_real)
blending = (world.use_sky_blend, world.use_sky_paper, world.use_sky_real)
# blending = world.getSkytype()
grd = world.horizon_color
# grd = world.getHor()
@ -827,7 +781,7 @@ class x3d_class:
EXPORT_TRI= False,\
):
print("Info: starting X3D export to " + self.filename + "...")
print("Info: starting X3D export to %r..." % self.filepath)
self.writeHeader()
# self.writeScript()
self.writeNavigationInfo(scene)
@ -925,7 +879,7 @@ class x3d_class:
self.texNames={}
self.matNames={}
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_'):
"""cleanStr(name,prefix) - try to create a valid VRML DEF name from object name"""
@ -961,9 +915,9 @@ class x3d_class:
faceMap={}
nFaceIndx=0
if mesh.active_uv_texture:
if mesh.uv_textures.active:
# if mesh.faceUV:
for face in mesh.active_uv_texture.data:
for face in mesh.uv_textures.active.data:
# for face in mesh.faces
sidename = "two" if face.use_twoside else "one"
@ -1135,91 +1089,35 @@ class x3d_class:
# Callbacks, needed before Main
##########################################################
def write(filename,
context,
EXPORT_APPLY_MODIFIERS=False,
EXPORT_TRI=False,
EXPORT_GZIP=False):
def save(operator, context, filepath="",
use_apply_modifiers=False,
use_triangulate=False,
use_compress=False):
if EXPORT_GZIP:
if not filename.lower().endswith('.x3dz'):
filename = '.'.join(filename.split('.')[:-1]) + '.x3dz'
if use_compress:
if not filepath.lower().endswith('.x3dz'):
filepath = '.'.join(filepath.split('.')[:-1]) + '.x3dz'
else:
if not filename.lower().endswith('.x3d'):
filename = '.'.join(filename.split('.')[:-1]) + '.x3d'
if not filepath.lower().endswith('.x3d'):
filepath = '.'.join(filepath.split('.')[:-1]) + '.x3d'
scene = context.scene
world = scene.world
if scene.objects.active:
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
# XXX these are global textures while .Get() returned only scene's?
alltextures = bpy.data.textures
# alltextures = Blender.Texture.Get()
wrlexport=x3d_class(filename)
wrlexport.export(\
scene,\
world,\
alltextures,\
\
EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS,\
EXPORT_TRI = EXPORT_TRI,\
)
wrlexport = x3d_class(filepath)
wrlexport.export(scene,
world,
alltextures,
EXPORT_APPLY_MODIFIERS=use_apply_modifiers,
EXPORT_TRI=use_triangulate,
)
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()

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

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

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

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

@ -59,7 +59,7 @@ class SelectPattern(bpy.types.Operator):
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm = context.window_manager
# return wm.invoke_props_popup(self, event)
wm.invoke_props_popup(self, event)
return {'RUNNING_MODAL'}
@ -427,13 +427,13 @@ class JoinUVs(bpy.types.Operator):
if is_editmode:
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
if not mesh.active_uv_texture:
if not mesh.uv_textures:
self.report({'WARNING'}, "Object: %s, Mesh: '%s' has no UVs\n" % (obj.name, mesh.name))
else:
len_faces = len(mesh.faces)
uv_array = array.array('f', [0.0] * 8) * len_faces # seems to be the fastest way to create an array
mesh.active_uv_texture.data.foreach_get("uv_raw", uv_array)
mesh.uv_textures.active.data.foreach_get("uv_raw", uv_array)
objects = context.selected_editable_objects[:]
@ -451,10 +451,9 @@ class JoinUVs(bpy.types.Operator):
if len(mesh_other.faces) != len_faces:
self.report({'WARNING'}, "Object: %s, Mesh: '%s' has %d faces, expected %d\n" % (obj_other.name, mesh_other.name, len(mesh_other.faces), len_faces))
else:
uv_other = mesh_other.active_uv_texture
uv_other = mesh_other.uv_textures.active
if not uv_other:
mesh_other.add_uv_texture() # should return the texture it adds
uv_other = mesh_other.active_uv_texture
uv_other = mesh_other.uv_textures.new() # should return the texture it adds
# finally do the copy
uv_other.data.foreach_set("uv_raw", uv_array)
@ -500,11 +499,13 @@ class MakeDupliFace(bpy.types.Operator):
for data, objects in linked.items():
face_verts = [axis for obj in objects for v in matrix_to_quat(obj.matrix_world) for axis in v]
faces = list(range(int(len(face_verts) / 3)))
faces = list(range(len(face_verts) // 3))
mesh = bpy.data.meshes.new(data.name + "_dupli")
mesh.add_geometry(int(len(face_verts) / 3), 0, int(len(face_verts) / (4 * 3)))
mesh.vertices.add(len(face_verts) // 3)
mesh.faces.add(len(face_verts) // 12)
mesh.vertices.foreach_set("co", face_verts)
mesh.faces.foreach_set("vertices_raw", faces)
mesh.update() # generates edge data
@ -572,4 +573,4 @@ def unregister():
pass
if __name__ == "__main__":
register()
register()

@ -50,7 +50,7 @@ class AddPresetBase():
if getattr(self, "save_keyconfig", False):
bpy.ops.wm.keyconfig_export(filepath=filepath, kc_name=self.properties.name)
file_preset = open(filepath, 'a')
file_preset.write("wm.active_keyconfig = kc\n\n")
file_preset.write("wm.keyconfigs.active = kc\n\n")
else:
file_preset = open(filepath, 'w')
file_preset.write("import bpy\n")
@ -64,7 +64,7 @@ class AddPresetBase():
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm = context.window_manager
#crashes, TODO - fix
#return wm.invoke_props_popup(self, event)

@ -69,7 +69,7 @@ class ExportUVLayout(bpy.types.Operator):
def _face_uv_iter(self, context):
obj = context.active_object
mesh = obj.data
uv_layer = mesh.active_uv_texture.data
uv_layer = mesh.uv_textures.active.data
uv_layer_len = len(uv_layer)
if not self.properties.export_all:
@ -207,7 +207,7 @@ class ExportUVLayout(bpy.types.Operator):
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm = context.window_manager
wm.add_fileselect(self)
return {'RUNNING_MODAL'}

@ -28,8 +28,8 @@ def extend(obj, operator, EXTEND_MODE):
me = obj.data
me_verts = me.vertices
# script will fail without UVs
if not me.active_uv_texture:
me.add_uv_texture()
if not me.uv_textures:
me.uv_textures.new()
# Toggle Edit mode
@ -57,10 +57,10 @@ def extend(obj, operator, EXTEND_MODE):
vidx_source = face_source.vertices
vidx_target = face_target.vertices
faceUVsource = me.active_uv_texture.data[face_source.index]
faceUVsource = me.uv_textures.active.data[face_source.index]
uvs_source = [faceUVsource.uv1, faceUVsource.uv2, faceUVsource.uv3, faceUVsource.uv4]
faceUVtarget = me.active_uv_texture.data[face_target.index]
faceUVtarget = me.uv_textures.active.data[face_target.index]
uvs_target = [faceUVtarget.uv1, faceUVtarget.uv2, faceUVtarget.uv3, faceUVtarget.uv4]
# vertex index is the key, uv is the value
@ -138,8 +138,8 @@ def extend(obj, operator, EXTEND_MODE):
uvs_vhash_target[edgepair_outer_target[iA]][:] = uvs_vhash_source[edgepair_inner_source[1]] + (uvs_vhash_source[edgepair_inner_source[1]] - uvs_vhash_source[edgepair_outer_source[0]])
if me.active_uv_texture == None:
me.add_uv_texture
if not me.uv_textures:
me.uv_textures.new()
face_act = me.faces.active
if face_act == -1:

@ -892,10 +892,10 @@ def main(context, island_margin, projection_limit):
# Tag as used
me.tag = True
if len(me.uv_textures)==0: # Mesh has no UV Coords, dont bother.
me.add_uv_texture()
if not me.uv_textures: # Mesh has no UV Coords, dont bother.
me.uv_textures.new()
uv_layer = me.active_uv_texture.data
uv_layer = me.uv_textures.active.data
me_verts = list(me.vertices)
if USER_ONLY_SELECTED_FACES:

@ -449,7 +449,7 @@ class WM_OT_context_modal_mouse(bpy.types.Operator):
else:
self.properties.initial_x = event.mouse_x
context.manager.add_modal_handler(self)
context.window_manager.add_modal_handler(self)
return {'RUNNING_MODAL'}
@ -505,7 +505,7 @@ class WM_OT_doc_view(bpy.types.Operator):
bl_label = "View Documentation"
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):
ls = []
@ -608,7 +608,7 @@ class WM_OT_doc_edit(bpy.types.Operator):
layout.prop(props, "doc_new", text="")
def invoke(self, context, event):
wm = context.manager
wm = context.window_manager
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.description = prop_ui.get("description", "")
wm = context.manager
wm = context.window_manager
# This crashes, TODO - fix
#return wm.invoke_props_popup(self, event)

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

@ -1,381 +1,381 @@
# Configuration Maya
import bpy
wm = bpy.context.manager
kc = wm.add_keyconfig('Maya')
wm = bpy.context.window_manager
kc = wm.keyconfigs.new('Maya')
# 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.show_manipulator', 'LEFTMOUSE', 'PRESS', any=True)
kmi = km.items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', any=True)
kmi.properties.release_confirm = True
kmi = km.items.add('view3d.cursor3d', 'ACTIONMOUSE', 'PRESS')
kmi = km.items.add('view3d.rotate', 'LEFTMOUSE', 'PRESS', alt=True)
kmi = km.items.add('view3d.move', 'MIDDLEMOUSE', 'PRESS', alt=True)
kmi = km.items.add('view3d.zoom', 'RIGHTMOUSE', 'PRESS', alt=True)
kmi = km.items.add('view3d.view_selected', 'NUMPAD_PERIOD', 'PRESS')
kmi = km.items.add('view3d.view_center_cursor', 'NUMPAD_PERIOD', 'PRESS', ctrl=True)
kmi = km.items.add('view3d.fly', 'F', 'PRESS', shift=True)
kmi = km.items.add('view3d.smoothview', 'TIMER1', 'ANY', any=True)
kmi = km.items.add('view3d.rotate', 'TRACKPADPAN', 'ANY', alt=True)
kmi = km.items.add('view3d.rotate', 'MOUSEROTATE', 'ANY')
kmi = km.items.add('view3d.move', 'TRACKPADPAN', 'ANY')
kmi = km.items.add('view3d.zoom', 'TRACKPADZOOM', 'ANY')
kmi = km.items.add('view3d.zoom', 'NUMPAD_PLUS', 'PRESS')
kmi = km.items.new('view3d.cursor3d', 'ACTIONMOUSE', 'PRESS')
kmi = km.items.new('view3d.rotate', 'LEFTMOUSE', 'PRESS', alt=True)
kmi = km.items.new('view3d.move', 'MIDDLEMOUSE', 'PRESS', alt=True)
kmi = km.items.new('view3d.zoom', 'RIGHTMOUSE', 'PRESS', alt=True)
kmi = km.items.new('view3d.view_selected', 'NUMPAD_PERIOD', 'PRESS')
kmi = km.items.new('view3d.view_center_cursor', 'NUMPAD_PERIOD', 'PRESS', ctrl=True)
kmi = km.items.new('view3d.fly', 'F', 'PRESS', shift=True)
kmi = km.items.new('view3d.smoothview', 'TIMER1', 'ANY', any=True)
kmi = km.items.new('view3d.rotate', 'TRACKPADPAN', 'ANY', alt=True)
kmi = km.items.new('view3d.rotate', 'MOUSEROTATE', 'ANY')
kmi = km.items.new('view3d.move', 'TRACKPADPAN', 'ANY')
kmi = km.items.new('view3d.zoom', 'TRACKPADZOOM', 'ANY')
kmi = km.items.new('view3d.zoom', 'NUMPAD_PLUS', 'PRESS')
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 = km.items.add('view3d.zoom', 'EQUAL', 'PRESS', ctrl=True)
kmi = km.items.new('view3d.zoom', 'EQUAL', 'PRESS', ctrl=True)
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 = km.items.add('view3d.zoom', 'WHEELINMOUSE', 'PRESS')
kmi = km.items.new('view3d.zoom', 'WHEELINMOUSE', 'PRESS')
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 = km.items.add('view3d.view_all', 'HOME', 'PRESS')
kmi = km.items.new('view3d.view_all', 'HOME', 'PRESS')
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 = km.items.add('view3d.viewnumpad', 'NUMPAD_0', 'PRESS')
kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_0', 'PRESS')
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 = km.items.add('view3d.view_orbit', 'NUMPAD_2', 'PRESS')
kmi = km.items.new('view3d.view_orbit', 'NUMPAD_2', 'PRESS')
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 = km.items.add('view3d.view_orbit', 'NUMPAD_4', 'PRESS')
kmi = km.items.new('view3d.view_orbit', 'NUMPAD_4', 'PRESS')
kmi.properties.type = 'ORBITLEFT'
kmi = km.items.add('view3d.view_persportho', 'NUMPAD_5', 'PRESS')
kmi = km.items.add('view3d.view_orbit', 'NUMPAD_6', 'PRESS')
kmi = km.items.new('view3d.view_persportho', 'NUMPAD_5', 'PRESS')
kmi = km.items.new('view3d.view_orbit', 'NUMPAD_6', 'PRESS')
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 = km.items.add('view3d.view_orbit', 'NUMPAD_8', 'PRESS')
kmi = km.items.new('view3d.view_orbit', 'NUMPAD_8', 'PRESS')
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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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.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.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.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.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.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.type = 'BOTTOM'
kmi = km.items.add('view3d.localview', 'NUMPAD_SLASH', 'PRESS')
kmi = km.items.add('view3d.layers', 'ACCENT_GRAVE', 'PRESS')
kmi = km.items.new('view3d.localview', 'NUMPAD_SLASH', 'PRESS')
kmi = km.items.new('view3d.layers', 'ACCENT_GRAVE', 'PRESS')
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 = km.items.add('view3d.layers', 'TWO', 'PRESS', any=True)
kmi = km.items.new('view3d.layers', 'TWO', 'PRESS', any=True)
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 = km.items.add('view3d.layers', 'FOUR', 'PRESS', any=True)
kmi = km.items.new('view3d.layers', 'FOUR', 'PRESS', any=True)
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 = km.items.add('view3d.layers', 'SIX', 'PRESS', any=True)
kmi = km.items.new('view3d.layers', 'SIX', 'PRESS', any=True)
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 = km.items.add('view3d.layers', 'EIGHT', 'PRESS', any=True)
kmi = km.items.new('view3d.layers', 'EIGHT', 'PRESS', any=True)
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 = km.items.add('view3d.layers', 'ZERO', 'PRESS', any=True)
kmi = km.items.new('view3d.layers', 'ZERO', 'PRESS', any=True)
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.value_1 = 'SOLID'
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.value_1 = 'TEXTURED'
kmi.properties.value_2 = 'SOLID'
kmi = km.items.add('view3d.select', 'SELECTMOUSE', 'PRESS')
kmi = km.items.add('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True)
kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS')
kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=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 = km.items.add('view3d.select', 'SELECTMOUSE', 'PRESS', alt=True)
kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', alt=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.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.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.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.enumerate = 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 = km.items.add('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', ctrl=True)
kmi = km.items.new('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', shift=True, ctrl=True)
kmi.properties.deselect = True
kmi = km.items.add('view3d.select_circle', 'C', 'PRESS')
kmi = km.items.add('view3d.clip_border', 'B', 'PRESS', alt=True)
kmi = km.items.add('view3d.zoom_border', 'B', 'PRESS', shift=True)
kmi = km.items.add('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.add('view3d.object_as_camera', 'NUMPAD_0', 'PRESS', ctrl=True)
kmi = km.items.add('wm.call_menu', 'S', 'PRESS', shift=True)
kmi = km.items.new('view3d.select_circle', 'C', 'PRESS')
kmi = km.items.new('view3d.clip_border', 'B', 'PRESS', alt=True)
kmi = km.items.new('view3d.zoom_border', 'B', 'PRESS', shift=True)
kmi = km.items.new('view3d.render_border', 'B', 'PRESS', shift=True)
kmi = km.items.new('view3d.camera_to_view', 'NUMPAD_0', 'PRESS', ctrl=True, alt=True)
kmi = km.items.new('view3d.object_as_camera', 'NUMPAD_0', 'PRESS', ctrl=True)
kmi = km.items.new('wm.call_menu', 'S', 'PRESS', shift=True)
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.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.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 = 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 = 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.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.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.value = 'ACTIVE_ELEMENT'
kmi = km.items.add('transform.translate', 'G', 'PRESS', shift=True)
kmi = km.items.add('transform.translate', 'EVT_TWEAK_S', 'ANY')
kmi = km.items.add('transform.rotate', 'R', 'PRESS', shift=True)
kmi = km.items.add('transform.resize', 'S', 'PRESS', shift=True)
kmi = km.items.add('transform.warp', 'W', 'PRESS', shift=True)
kmi = km.items.add('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.add('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.translate', 'G', 'PRESS', shift=True)
kmi = km.items.new('transform.translate', 'EVT_TWEAK_S', 'ANY')
kmi = km.items.new('transform.rotate', 'R', 'PRESS', shift=True)
kmi = km.items.new('transform.resize', 'S', 'PRESS', shift=True)
kmi = km.items.new('transform.warp', 'W', 'PRESS', shift=True)
kmi = km.items.new('transform.tosphere', 'S', 'PRESS', shift=True, alt=True)
kmi = km.items.new('transform.shear', 'S', 'PRESS', shift=True, ctrl=True, alt=True)
kmi = km.items.new('transform.select_orientation', 'SPACE', 'PRESS', alt=True)
kmi = km.items.new('transform.create_orientation', 'SPACE', 'PRESS', ctrl=True, alt=True)
kmi.properties.use = True
kmi = km.items.add('transform.mirror', 'M', 'PRESS', ctrl=True)
kmi = km.items.add('wm.context_toggle', 'TAB', 'PRESS', shift=True)
kmi.properties.data_path = 'tool_settings.snap'
kmi = km.items.add('transform.snap_type', 'TAB', 'PRESS', shift=True, ctrl=True)
kmi = km.items.add('view3d.enable_manipulator', 'W', 'PRESS')
kmi = km.items.new('transform.mirror', 'M', 'PRESS', ctrl=True)
kmi = km.items.new('wm.context_toggle', 'TAB', 'PRESS', shift=True)
kmi.properties.data_path = 'tool_settings.use_snap'
kmi = km.items.new('transform.snap_type', 'TAB', 'PRESS', shift=True, ctrl=True)
kmi = km.items.new('view3d.enable_manipulator', 'W', 'PRESS')
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 = km.items.add('view3d.enable_manipulator', 'R', 'PRESS')
kmi = km.items.new('view3d.enable_manipulator', 'R', 'PRESS')
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
# 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 = 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.value_1 = 'DISABLED'
kmi.properties.value_2 = 'ENABLED'
kmi = km.items.add('view3d.game_start', 'P', 'PRESS')
kmi = km.items.add('object.select_all', 'A', 'PRESS')
kmi = km.items.add('object.select_inverse', 'I', 'PRESS', ctrl=True)
kmi = km.items.add('object.select_linked', 'L', 'PRESS', shift=True)
kmi = km.items.add('object.select_grouped', 'G', 'PRESS', shift=True)
kmi = km.items.add('object.select_mirror', 'M', 'PRESS', shift=True, ctrl=True)
kmi = km.items.add('object.select_hierarchy', 'LEFT_BRACKET', 'PRESS')
kmi = km.items.new('view3d.game_start', 'P', 'PRESS')
kmi = km.items.new('object.select_all', 'A', 'PRESS')
kmi = km.items.new('object.select_inverse', 'I', 'PRESS', ctrl=True)
kmi = km.items.new('object.select_linked', 'L', 'PRESS', shift=True)
kmi = km.items.new('object.select_grouped', 'G', 'PRESS', shift=True)
kmi = km.items.new('object.select_mirror', 'M', 'PRESS', shift=True, ctrl=True)
kmi = km.items.new('object.select_hierarchy', 'LEFT_BRACKET', 'PRESS')
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.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 = 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.extend = True
kmi = km.items.add('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.add('object.parent_clear', 'P', 'PRESS', alt=True)
kmi = km.items.add('object.track_set', 'T', 'PRESS', ctrl=True)
kmi = km.items.add('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.add('object.constraints_clear', 'C', 'PRESS', ctrl=True, alt=True)
kmi = km.items.add('object.location_clear', 'G', 'PRESS', alt=True)
kmi = km.items.add('object.rotation_clear', 'R', 'PRESS', alt=True)
kmi = km.items.add('object.scale_clear', 'S', 'PRESS', alt=True)
kmi = km.items.add('object.origin_clear', 'O', 'PRESS', alt=True)
kmi = km.items.add('object.hide_view_clear', 'H', 'PRESS', alt=True)
kmi = km.items.add('object.hide_view_set', 'H', 'PRESS')
kmi = km.items.add('object.hide_view_set', 'H', 'PRESS', shift=True)
kmi = km.items.new('object.parent_set', 'P', 'PRESS', ctrl=True)
kmi = km.items.new('object.parent_no_inverse_set', 'P', 'PRESS', shift=True, ctrl=True)
kmi = km.items.new('object.parent_clear', 'P', 'PRESS', alt=True)
kmi = km.items.new('object.track_set', 'T', 'PRESS', ctrl=True)
kmi = km.items.new('object.track_clear', 'T', 'PRESS', alt=True)
kmi = km.items.new('object.constraint_add_with_targets', 'C', 'PRESS', shift=True, ctrl=True)
kmi = km.items.new('object.constraints_clear', 'C', 'PRESS', ctrl=True, alt=True)
kmi = km.items.new('object.location_clear', 'G', 'PRESS', alt=True)
kmi = km.items.new('object.rotation_clear', 'R', 'PRESS', alt=True)
kmi = km.items.new('object.scale_clear', 'S', 'PRESS', alt=True)
kmi = km.items.new('object.origin_clear', 'O', 'PRESS', alt=True)
kmi = km.items.new('object.hide_view_clear', 'H', 'PRESS', alt=True)
kmi = km.items.new('object.hide_view_set', 'H', 'PRESS')
kmi = km.items.new('object.hide_view_set', 'H', 'PRESS', shift=True)
kmi.properties.unselected = True
kmi = km.items.add('object.move_to_layer', 'M', 'PRESS')
kmi = km.items.add('object.delete', 'X', 'PRESS')
kmi = km.items.add('object.delete', 'DEL', 'PRESS')
kmi = km.items.add('wm.call_menu', 'A', 'PRESS', shift=True)
kmi = km.items.new('object.move_to_layer', 'M', 'PRESS')
kmi = km.items.new('object.delete', 'X', 'PRESS')
kmi = km.items.new('object.delete', 'DEL', 'PRESS')
kmi = km.items.new('wm.call_menu', 'A', 'PRESS', shift=True)
kmi.properties.name = 'INFO_MT_add'
kmi = km.items.add('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('object.duplicates_make_real', 'A', 'PRESS', shift=True, ctrl=True)
kmi = km.items.new('wm.call_menu', 'A', 'PRESS', ctrl=True)
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 = 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 = km.items.add('object.duplicate_move', 'D', 'PRESS', shift=True)
kmi = km.items.add('object.duplicate_move_linked', 'D', 'PRESS', alt=True)
kmi = km.items.add('object.join', 'J', 'PRESS', ctrl=True)
kmi = km.items.add('object.convert', 'C', 'PRESS', alt=True)
kmi = km.items.add('object.proxy_make', 'P', 'PRESS', ctrl=True, alt=True)
kmi = km.items.add('object.make_local', 'L', 'PRESS')
kmi = km.items.add('anim.keyframe_insert_menu', 'I', 'PRESS')
kmi = km.items.add('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.add('group.create', 'G', 'PRESS', ctrl=True)
kmi = km.items.add('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.add('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('object.duplicate_move', 'D', 'PRESS', shift=True)
kmi = km.items.new('object.duplicate_move_linked', 'D', 'PRESS', alt=True)
kmi = km.items.new('object.join', 'J', 'PRESS', ctrl=True)
kmi = km.items.new('object.convert', 'C', 'PRESS', alt=True)
kmi = km.items.new('object.proxy_make', 'P', 'PRESS', ctrl=True, alt=True)
kmi = km.items.new('object.make_local', 'L', 'PRESS')
kmi = km.items.new('anim.keyframe_insert_menu', 'I', 'PRESS')
kmi = km.items.new('anim.keyframe_delete_v3d', 'I', 'PRESS', alt=True)
kmi = km.items.new('anim.keying_set_active_set', 'I', 'PRESS', shift=True, ctrl=True, alt=True)
kmi = km.items.new('group.create', 'G', 'PRESS', ctrl=True)
kmi = km.items.new('group.objects_remove', 'G', 'PRESS', ctrl=True, alt=True)
kmi = km.items.new('group.objects_add_active', 'G', 'PRESS', shift=True, ctrl=True)
kmi = km.items.new('group.objects_remove_active', 'G', 'PRESS', shift=True, alt=True)
kmi = km.items.new('wm.call_menu', 'W', 'PRESS', ctrl=True)
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 = 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 = 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 = 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 = 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 = 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 = km.items.add('object.select_all', 'SELECTMOUSE', 'CLICK')
kmi = km.items.new('object.select_all', 'SELECTMOUSE', 'CLICK')
kmi.properties.action = 'DESELECT'
# 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.add('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.loopcut_slide', 'R', 'PRESS', ctrl=True)
kmi = km.items.new('mesh.loop_select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True)
kmi = km.items.new('mesh.loop_select', 'SELECTMOUSE', 'PRESS', shift=True, alt=True)
kmi.properties.extend = True
kmi = km.items.add('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', ctrl=True, alt=True)
kmi = km.items.new('mesh.edgering_select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True)
kmi.properties.extend = True
kmi = km.items.add('mesh.select_shortest_path', 'SELECTMOUSE', 'PRESS', ctrl=True)
kmi = km.items.add('mesh.select_all', 'A', 'PRESS')
kmi = km.items.add('mesh.select_more', 'NUMPAD_PLUS', 'PRESS', ctrl=True)
kmi = km.items.add('mesh.select_less', 'NUMPAD_MINUS', 'PRESS', ctrl=True)
kmi = km.items.add('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.add('mesh.select_linked', 'L', 'PRESS', ctrl=True)
kmi = km.items.add('mesh.select_linked_pick', 'L', 'PRESS')
kmi = km.items.add('mesh.select_linked_pick', 'L', 'PRESS', shift=True)
kmi = km.items.new('mesh.select_shortest_path', 'SELECTMOUSE', 'PRESS', ctrl=True)
kmi = km.items.new('mesh.select_all', 'A', 'PRESS')
kmi = km.items.new('mesh.select_more', 'NUMPAD_PLUS', 'PRESS', ctrl=True)
kmi = km.items.new('mesh.select_less', 'NUMPAD_MINUS', 'PRESS', ctrl=True)
kmi = km.items.new('mesh.select_inverse', 'I', 'PRESS', ctrl=True)
kmi = km.items.new('mesh.select_non_manifold', 'M', 'PRESS', shift=True, ctrl=True, alt=True)
kmi = km.items.new('mesh.select_linked', 'L', 'PRESS', ctrl=True)
kmi = km.items.new('mesh.select_linked_pick', 'L', 'PRESS')
kmi = km.items.new('mesh.select_linked_pick', 'L', 'PRESS', shift=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 = km.items.add('mesh.select_similar', 'G', 'PRESS', shift=True)
kmi = km.items.add('wm.call_menu', 'TAB', 'PRESS', ctrl=True)
kmi = km.items.new('mesh.select_similar', 'G', 'PRESS', shift=True)
kmi = km.items.new('wm.call_menu', 'TAB', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_selection_mode'
kmi = km.items.add('mesh.hide', 'H', 'PRESS')
kmi = km.items.add('mesh.hide', 'H', 'PRESS', shift=True)
kmi = km.items.new('mesh.hide', 'H', 'PRESS')
kmi = km.items.new('mesh.hide', 'H', 'PRESS', shift=True)
kmi.properties.unselected = True
kmi = km.items.add('mesh.reveal', 'H', 'PRESS', alt=True)
kmi = km.items.add('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.reveal', 'H', 'PRESS', alt=True)
kmi = km.items.new('mesh.normals_make_consistent', 'N', 'PRESS', ctrl=True)
kmi = km.items.new('mesh.normals_make_consistent', 'N', 'PRESS', shift=True, ctrl=True)
kmi.properties.inside = True
kmi = km.items.add('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.add('wm.call_menu', 'E', 'PRESS', alt=True)
kmi = km.items.new('view3d.edit_mesh_extrude_move_normal', 'E', 'PRESS', ctrl=True)
kmi = km.items.new('view3d.edit_mesh_extrude_individual_move', 'E', 'PRESS', shift=True)
kmi = km.items.new('wm.call_menu', 'E', 'PRESS', alt=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_extrude'
kmi = km.items.add('mesh.spin', 'R', 'PRESS', alt=True)
kmi = km.items.add('mesh.fill', 'F', 'PRESS', alt=True)
kmi = km.items.add('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.add('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.add('mesh.rip_move', 'V', 'PRESS')
kmi = km.items.add('mesh.merge', 'M', 'PRESS', alt=True)
kmi = km.items.add('transform.shrink_fatten', 'S', 'PRESS', ctrl=True, alt=True)
kmi = km.items.add('mesh.edge_face_add', 'F', 'PRESS')
kmi = km.items.add('mesh.duplicate_move', 'D', 'PRESS', shift=True)
kmi = km.items.add('wm.call_menu', 'A', 'PRESS', shift=True)
kmi = km.items.new('mesh.spin', 'R', 'PRESS', alt=True)
kmi = km.items.new('mesh.fill', 'F', 'PRESS', alt=True)
kmi = km.items.new('mesh.beautify_fill', 'F', 'PRESS', shift=True, alt=True)
kmi = km.items.new('mesh.quads_convert_to_tris', 'T', 'PRESS', ctrl=True)
kmi = km.items.new('mesh.tris_convert_to_quads', 'J', 'PRESS', alt=True)
kmi = km.items.new('mesh.edge_flip', 'F', 'PRESS', shift=True, ctrl=True)
kmi = km.items.new('mesh.rip_move', 'V', 'PRESS')
kmi = km.items.new('mesh.merge', 'M', 'PRESS', alt=True)
kmi = km.items.new('transform.shrink_fatten', 'S', 'PRESS', ctrl=True, alt=True)
kmi = km.items.new('mesh.edge_face_add', 'F', 'PRESS')
kmi = km.items.new('mesh.duplicate_move', 'D', 'PRESS', shift=True)
kmi = km.items.new('wm.call_menu', 'A', 'PRESS', shift=True)
kmi.properties.name = 'INFO_MT_mesh_add'
kmi = km.items.add('mesh.separate', 'P', 'PRESS')
kmi = km.items.add('mesh.split', 'Y', 'PRESS')
kmi = km.items.add('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', ctrl=True)
kmi = km.items.add('mesh.delete', 'X', 'PRESS')
kmi = km.items.add('mesh.delete', 'DEL', 'PRESS')
kmi = km.items.add('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.separate', 'P', 'PRESS')
kmi = km.items.new('mesh.split', 'Y', 'PRESS')
kmi = km.items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', ctrl=True)
kmi = km.items.new('mesh.delete', 'X', 'PRESS')
kmi = km.items.new('mesh.delete', 'DEL', 'PRESS')
kmi = km.items.new('mesh.knife_cut', 'LEFTMOUSE', 'PRESS', key_modifier='K')
kmi = km.items.new('mesh.knife_cut', 'LEFTMOUSE', 'PRESS', shift=True, key_modifier='K')
kmi.properties.type = 'MIDPOINTS'
kmi = km.items.add('object.vertex_parent_set', 'P', 'PRESS', ctrl=True)
kmi = km.items.add('wm.call_menu', 'W', 'PRESS', ctrl=True)
kmi = km.items.new('object.vertex_parent_set', 'P', 'PRESS', ctrl=True)
kmi = km.items.new('wm.call_menu', 'W', 'PRESS', ctrl=True)
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 = 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 = 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 = 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 = 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 = 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 = 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 = 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.value_1 = 'DISABLED'
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.value_1 = 'DISABLED'
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'
wm.active_keyconfig = kc
wm.keyconfigs.active = kc
bpy.context.user_preferences.edit.use_drag_immediately = True
bpy.context.user_preferences.edit.use_insertkey_xyz_to_rgb = False

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

@ -25,7 +25,7 @@ class ModalOperator(bpy.types.Operator):
def invoke(self, context, event):
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_value = context.object.location.x
return {'RUNNING_MODAL'}

@ -52,7 +52,7 @@ class ModalDrawOperator(bpy.types.Operator):
def invoke(self, context, event):
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
# draw in view space with 'POST_VIEW' and 'PRE_VIEW'

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

@ -9,11 +9,11 @@ def main(context):
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
if not mesh.active_uv_texture:
bpy.ops.mesh.uv_texture_add()
if not mesh.uv_textures:
uvtex = bpy.ops.mesh.uv_texture_add()
# adjust UVs
for i, uv in enumerate(mesh.active_uv_texture.data):
for i, uv in enumerate(uvtex.data):
uvs = uv.uv1, uv.uv2, uv.uv3, uv.uv4
for j, v_idx in enumerate(mesh.faces[i].vertices):
if uv.select_uv[j]:

@ -27,7 +27,7 @@ class MotionPathButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_label = "Motion Paths"
bl_default_closed = True
bl_options = {'DEFAULT_CLOSED'}
def draw_settings(self, context, avs, bones=False):
layout = self.layout
@ -65,7 +65,7 @@ class OnionSkinButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_label = "Onion Skinning"
bl_default_closed = True
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout

@ -33,7 +33,7 @@ class ArmatureButtonsPanel():
class DATA_PT_context_arm(ArmatureButtonsPanel, bpy.types.Panel):
bl_label = ""
bl_show_header = False
bl_options = {'HIDE_HEADER'}
def draw(self, context):
layout = self.layout
@ -119,14 +119,14 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, bpy.types.Panel):
pose = ob.pose
row = layout.row()
row.template_list(pose, "bone_groups", pose, "active_bone_group_index", rows=2)
row.template_list(pose, "bone_groups", pose.bone_groups, "active_index", rows=2)
col = row.column(align=True)
col.active = (ob.proxy is None)
col.operator("pose.group_add", icon='ZOOMIN', text="")
col.operator("pose.group_remove", icon='ZOOMOUT', text="")
group = pose.active_bone_group
group = pose.bone_groups.active
if group:
col = layout.column()
col.active = (ob.proxy is None)
@ -139,7 +139,10 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, bpy.types.Panel):
col.prop(group, "color_set")
if group.color_set:
col = split.column()
col.template_triColorSet(group, "colors")
subrow = col.row(align=True)
subrow.prop(group.colors, "normal", text="")
subrow.prop(group.colors, "select", text="")
subrow.prop(group.colors, "active", text="")
row = layout.row()
row.active = (ob.proxy is None)
@ -184,7 +187,7 @@ class DATA_PT_ghost(ArmatureButtonsPanel, bpy.types.Panel):
class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, bpy.types.Panel):
bl_label = "iTaSC parameters"
bl_default_closed = True
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):

@ -38,7 +38,7 @@ class DATA_PT_template(bpy.types.Panel):
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
bl_default_closed = True
bl_options = {'DEFAULT_CLOSED'}
templates = []
@ -250,7 +250,7 @@ class AsScript(bpy.types.Operator):
import os
obj = context.object
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)
return {'RUNNING_MODAL'}

@ -33,7 +33,7 @@ class BoneButtonsPanel():
class BONE_PT_context_bone(BoneButtonsPanel, bpy.types.Panel):
bl_label = ""
bl_show_header = False
bl_options = {'HIDE_HEADER'}
def draw(self, context):
layout = self.layout
@ -95,7 +95,7 @@ class BONE_PT_transform(BoneButtonsPanel, bpy.types.Panel):
class BONE_PT_transform_locks(BoneButtonsPanel, bpy.types.Panel):
bl_label = "Transform Locks"
bl_default_closed = True
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
@ -151,14 +151,14 @@ class BONE_PT_relations(BoneButtonsPanel, bpy.types.Panel):
if ob and pchan:
col.label(text="Bone Group:")
col.prop_object(pchan, "bone_group", ob.pose, "bone_groups", text="")
col.prop_search(pchan, "bone_group", ob.pose, "bone_groups", text="")
col = split.column()
col.label(text="Parent:")
if context.bone:
col.prop(bone, "parent", text="")
else:
col.prop_object(bone, "parent", arm, "edit_bones", text="")
col.prop_search(bone, "parent", arm, "edit_bones", text="")
sub = col.column()
sub.active = (bone.parent is not None)
@ -202,12 +202,12 @@ class BONE_PT_display(BoneButtonsPanel, bpy.types.Panel):
col.label(text="Custom Shape:")
col.prop(pchan, "custom_shape", text="")
if pchan.custom_shape:
col.prop_object(pchan, "custom_shape_transform", ob.pose, "bones", text="At")
col.prop_search(pchan, "custom_shape_transform", ob.pose, "bones", text="At")
class BONE_PT_inverse_kinematics(BoneButtonsPanel, bpy.types.Panel):
bl_label = "Inverse Kinematics"
bl_default_closed = True
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
@ -224,7 +224,7 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, bpy.types.Panel):
row.prop(ob.pose, "ik_solver")
split = layout.split(percentage=0.25)
split.prop(pchan, "lock_ik_x", text="Lock X")
split.prop(pchan, "lock_ik_x", icon='LOCKED' if pchan.lock_ik_x else 'UNLOCKED', text="X")
split.active = pchan.is_in_ik_chain
row = split.row()
row.prop(pchan, "ik_stiffness_x", text="Stiffness", slider=True)
@ -241,8 +241,8 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, bpy.types.Panel):
sub.active = pchan.lock_ik_x == False and pchan.use_ik_limit_x and pchan.is_in_ik_chain
split = layout.split(percentage=0.25)
split.prop(pchan, "lock_ik_y", text="Y")
split.active = pchan.is_in_ik_chain and pchan.is_in_ik_chain
split.prop(pchan, "lock_ik_y", icon='LOCKED' if pchan.lock_ik_y else 'UNLOCKED', text="Y")
split.active = pchan.is_in_ik_chain
row = split.row()
row.prop(pchan, "ik_stiffness_y", text="Stiffness", slider=True)
row.active = pchan.lock_ik_y == False and pchan.is_in_ik_chain
@ -259,8 +259,8 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, bpy.types.Panel):
sub.active = pchan.lock_ik_y == False and pchan.use_ik_limit_y and pchan.is_in_ik_chain
split = layout.split(percentage=0.25)
split.prop(pchan, "lock_ik_z", text="Z")
split.active = pchan.is_in_ik_chain and pchan.is_in_ik_chain
split.prop(pchan, "lock_ik_z", icon='LOCKED' if pchan.lock_ik_z else 'UNLOCKED', text="Z")
split.active = pchan.is_in_ik_chain
sub = split.row()
sub.prop(pchan, "ik_stiffness_z", text="Stiffness", slider=True)
sub.active = pchan.lock_ik_z == False and pchan.is_in_ik_chain
@ -274,10 +274,12 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, bpy.types.Panel):
sub.prop(pchan, "ik_min_z", text="")
sub.prop(pchan, "ik_max_z", text="")
sub.active = pchan.lock_ik_z == False and pchan.use_ik_limit_z and pchan.is_in_ik_chain
split = layout.split()
split.prop(pchan, "ik_stretch", text="Stretch", slider=True)
split.label()
split.active = pchan.is_in_ik_chain
split = layout.split(percentage=0.25)
split.label(text="Stretch:")
sub = split.row()
sub.prop(pchan, "ik_stretch", text="", slider=True)
sub.active = pchan.is_in_ik_chain
if ob.pose.ik_solver == 'ITASC':
split = layout.split()
@ -295,7 +297,7 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, bpy.types.Panel):
class BONE_PT_deform(BoneButtonsPanel, bpy.types.Panel):
bl_label = "Deform"
bl_default_closed = True
bl_options = {'DEFAULT_CLOSED'}
def draw_header(self, context):
bone = context.bone

@ -34,7 +34,7 @@ class CameraButtonsPanel():
class DATA_PT_context_camera(CameraButtonsPanel, bpy.types.Panel):
bl_label = ""
bl_show_header = False
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
def draw(self, context):

@ -50,7 +50,7 @@ class CurveButtonsPanelActive(CurveButtonsPanel):
class DATA_PT_context_curve(CurveButtonsPanel, bpy.types.Panel):
bl_label = ""
bl_show_header = False
bl_options = {'HIDE_HEADER'}
def draw(self, context):
layout = self.layout

@ -42,7 +42,7 @@ class DataButtonsPanel():
class DATA_PT_context_lamp(DataButtonsPanel, bpy.types.Panel):
bl_label = ""
bl_show_header = False
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
def draw(self, context):
@ -54,13 +54,15 @@ class DATA_PT_context_lamp(DataButtonsPanel, bpy.types.Panel):
split = layout.split(percentage=0.65)
texture_count = len(lamp.texture_slots.keys())
if ob:
split.template_ID(ob, "data")
split.separator()
elif lamp:
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):
bl_label = "Preview"
@ -367,7 +369,7 @@ class DATA_PT_spot(DataButtonsPanel, bpy.types.Panel):
class DATA_PT_falloff_curve(DataButtonsPanel, bpy.types.Panel):
bl_label = "Falloff Curve"
bl_default_closed = True
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@classmethod

@ -33,7 +33,7 @@ class DataButtonsPanel():
class DATA_PT_context_lattice(DataButtonsPanel, bpy.types.Panel):
bl_label = ""
bl_show_header = False
bl_options = {'HIDE_HEADER'}
def draw(self, context):
layout = self.layout
@ -79,7 +79,7 @@ class DATA_PT_lattice(DataButtonsPanel, bpy.types.Panel):
row = layout.row()
row.prop(lat, "use_outside")
row.prop_object(lat, "vertex_group", context.object, "vertex_groups", text="")
row.prop_search(lat, "vertex_group", context.object, "vertex_groups", text="")
class DATA_PT_custom_props_lattice(DataButtonsPanel, PropertyPanel, bpy.types.Panel):

@ -60,7 +60,7 @@ class MeshButtonsPanel():
class DATA_PT_context_mesh(MeshButtonsPanel, bpy.types.Panel):
bl_label = ""
bl_show_header = False
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
def draw(self, context):
@ -127,14 +127,14 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, bpy.types.Panel):
layout = self.layout
ob = context.object
group = ob.active_vertex_group
group = ob.vertex_groups.active
rows = 2
if group:
rows = 5
row = layout.row()
row.template_list(ob, "vertex_groups", ob, "active_vertex_group_index", rows=rows)
row.template_list(ob, "vertex_groups", ob.vertex_groups, "active_index", rows=rows)
col = row.column(align=True)
col.operator("object.vertex_group_add", icon='ZOOMIN', text="")
@ -245,8 +245,8 @@ class DATA_PT_shape_keys(MeshButtonsPanel, bpy.types.Panel):
col = split.column(align=True)
col.active = enable_edit_value
col.label(text="Blend:")
col.prop_object(kb, "vertex_group", ob, "vertex_groups", text="")
col.prop_object(kb, "relative_key", key, "keys", text="")
col.prop_search(kb, "vertex_group", ob, "vertex_groups", text="")
col.prop_search(kb, "relative_key", key, "keys", text="")
else:
row = layout.row()
@ -266,13 +266,13 @@ class DATA_PT_uv_texture(MeshButtonsPanel, bpy.types.Panel):
row = layout.row()
col = row.column()
col.template_list(me, "uv_textures", me, "active_uv_texture_index", rows=2)
col.template_list(me, "uv_textures", me.uv_textures, "active_index", rows=2)
col = row.column(align=True)
col.operator("mesh.uv_texture_add", icon='ZOOMIN', text="")
col.operator("mesh.uv_texture_remove", icon='ZOOMOUT', text="")
lay = me.active_uv_texture
lay = me.uv_textures.active
if lay:
layout.prop(lay, "name")
@ -300,7 +300,7 @@ class DATA_PT_texface(MeshButtonsPanel, bpy.types.Panel):
split = layout.split()
col = split.column()
col.prop(tf, "use_bitmap_text")
col.prop(tf, "use_image")
col.prop(tf, "use_light")
col.prop(tf, "hide")
col.prop(tf, "use_collision")
@ -335,13 +335,13 @@ class DATA_PT_vertex_colors(MeshButtonsPanel, bpy.types.Panel):
row = layout.row()
col = row.column()
col.template_list(me, "vertex_colors", me, "active_vertex_color_index", rows=2)
col.template_list(me, "vertex_colors", me.vertex_colors, "active_index", rows=2)
col = row.column(align=True)
col.operator("mesh.vertex_color_add", icon='ZOOMIN', text="")
col.operator("mesh.vertex_color_remove", icon='ZOOMOUT', text="")
lay = me.active_vertex_color
lay = me.vertex_colors.active
if lay:
layout.prop(lay, "name")

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